From 40c606b25d5c9e51bc972cd1bea5099ec70b8b46 Mon Sep 17 00:00:00 2001 From: Jonathan Sanchez Date: Tue, 15 Oct 2013 13:08:14 -0500 Subject: [PATCH 01/26] Issue #2463 Create square polygon for single frame. Change-Id: Iaf2defc5627434ed1856e8ca3448c3ab28e283a2 Former-commit-id: 3353571634d92a8834bcd87552e86e07164bc651 [formerly 37ce552351074c59a680604f026aee7de051630a] [formerly c4803feaede3a6e9da84d5ae695710a63266d79e] [formerly a92f3056e75069005e9ee624d12c73169e872548 [formerly c4803feaede3a6e9da84d5ae695710a63266d79e [formerly 7505aa9ede362fcac1d9dec9dd221d79389552e0]]] Former-commit-id: a92f3056e75069005e9ee624d12c73169e872548 Former-commit-id: 938721b86e82ad231c8895b978a3fa5b00c9af44 [formerly 8756c06ae8087b982cf5564ff470aca91d679442] Former-commit-id: fe531839b15fed954eb970464d16a75601949ddb --- .../src/com/raytheon/viz/warngen/gui/WarngenLayer.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java index 7bef3b3064..ebb4a1a69b 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java @@ -189,6 +189,7 @@ import com.vividsolutions.jts.io.WKTReader; * 07/26/2013 DR 16450 D. Friedman Fix logic errors when frame count is one. * 08/19/2013 2177 jsanchez Set a GeneralGridGeometry object in the GeospatialDataList. * 09/17/2013 DR 16496 D. Friedman Make editable state more consistent. + * 10/15/2013 2463 jsanchez Create a square polygon for frame count equal to 1. * * * @author mschenke @@ -1995,6 +1996,12 @@ public class WarngenLayer extends AbstractStormTrackResource { } } + // Create a square polygon if time matcher basis is 1 frame. + if (descriptor.getFramesInfo().getFrameCount() == 1) { + createSquare(); + return; + } + DestinationGeodeticCalculator gc = new DestinationGeodeticCalculator(); GeometryFactory gf = new GeometryFactory(); From 85324e84f7d9b7687fd125e3d7f85f130220c6c4 Mon Sep 17 00:00:00 2001 From: Roger Ferrel Date: Wed, 16 Oct 2013 13:41:56 -0500 Subject: [PATCH 02/26] Issue #2439 Changes to warning mapping to support simulated time. Change-Id: I64ff51987e20f0ee9d1e1d6e107e5d5208641013 Former-commit-id: 4422090384a72de4189672785d25716e188cf137 [formerly cdf2b1ca54c0aca0399fc5bef68b0b7cbca81bbe] [formerly 3017da5c44cf46f57b8783a3026d0be65d33d786] [formerly aa19ef919beed1ab87ed5c9f66cc0baba42024e2 [formerly 3017da5c44cf46f57b8783a3026d0be65d33d786 [formerly 7e1290ed2e7eaf9f438e605addb96d423e182bb2]]] Former-commit-id: aa19ef919beed1ab87ed5c9f66cc0baba42024e2 Former-commit-id: f50ff95ac5615600e65c3de1dd505c3d06fe6afe [formerly e2c6605e21c4aac0dd3d409df735eb8ddd400dbd] Former-commit-id: 17b141237e7b769430caf410295a9ead180c444c --- .../viz/warngen/util/CurrentWarnings.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java index 611154a8c5..264f20eb60 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java @@ -44,6 +44,7 @@ import com.raytheon.uf.common.site.SiteMap; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.ISimulatedTimeChangeListener; import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.TimeRange; import com.raytheon.uf.common.time.util.TimeUtil; @@ -76,6 +77,7 @@ import com.vividsolutions.jts.geom.Geometry; * Jul 22, 2013 2176 jsanchez Set the raw message for an EXT. * Aug 14, 2013 DR 16483 Qinglu Lin Fixed no option issue in WarnGen dropdown menu after * issuance of an CANCON and restart of CAVE. + * Oct 16, 2013 2439 rferrel Restrict retrieval of warnings to prevent getting future warnings. * * * @author mschenke @@ -130,9 +132,9 @@ public class CurrentWarnings { } - private static Map instanceMap = new HashMap(); + private static final Map instanceMap = new HashMap(); - private static Set listeners = Collections + private static final Set listeners = Collections .synchronizedSet(new HashSet()); static { @@ -208,9 +210,25 @@ public class CurrentWarnings { } }; + /** + * Singleton constructor. + * + * @param officeId + */ private CurrentWarnings(String officeId) { this.officeId = officeId; initializeData(); + + // This assumes the instances stays around for the life of the JVM. + ISimulatedTimeChangeListener changeListener = new ISimulatedTimeChangeListener() { + + @Override + public void timechanged() { + initializeData(); + } + }; + SimulatedTime.getSystemTime().addSimulatedTimeChangeListener( + changeListener); } /** @@ -219,6 +237,10 @@ public class CurrentWarnings { private void initializeData() { Map constraints = new HashMap(); constraints.put("officeid", new RequestConstraint(officeId)); + Calendar time = TimeUtil.newCalendar(); + constraints.put("issueTime", + new RequestConstraint(TimeUtil.formatDate(time), + ConstraintType.LESS_THAN_EQUALS)); long t0 = System.currentTimeMillis(); List warnings = requestRecords(constraints); From 40f5bc92fc9e87a990fc5dd23ae68119e3f272d8 Mon Sep 17 00:00:00 2001 From: Jonathan Sanchez Date: Thu, 17 Oct 2013 08:00:35 -0500 Subject: [PATCH 03/26] Issue #2463 Fixed polygon on follow up Change-Id: I3002a333ac75b7799d162fa7084a08c59fce94ab Former-commit-id: f7539e354c4a1cd07a2dd657187419fe7b6f1ca3 [formerly e4fae68952cfbaadc1dbbf208552eb6562533c2e] [formerly 462057932e778b3390d6534f32fd180d85da36e6] [formerly d92ef062c1aaf7af6f13a093cb02dddf2ad7a9e9 [formerly 462057932e778b3390d6534f32fd180d85da36e6 [formerly 44665cd00858a98f6d25181a305facd440b6b0e0]]] Former-commit-id: d92ef062c1aaf7af6f13a093cb02dddf2ad7a9e9 Former-commit-id: f80beb9a46e7e91c751d8636da7cc7e0c013c4f0 [formerly c651489ae363b37c06579ccbc7659ede2a619e9b] Former-commit-id: d9b66a15ee48325d48b09c263df2e61a6647b77a --- .../viz/warngen/gui/WarngenLayer.java | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java index ebb4a1a69b..39a339091b 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java @@ -189,7 +189,7 @@ import com.vividsolutions.jts.io.WKTReader; * 07/26/2013 DR 16450 D. Friedman Fix logic errors when frame count is one. * 08/19/2013 2177 jsanchez Set a GeneralGridGeometry object in the GeospatialDataList. * 09/17/2013 DR 16496 D. Friedman Make editable state more consistent. - * 10/15/2013 2463 jsanchez Create a square polygon for frame count equal to 1. + * 10/15/2013 2463 jsanchez Create a square polygon when time matched with a resource with no data. * * * @author mschenke @@ -836,12 +836,8 @@ public class WarngenLayer extends AbstractStormTrackResource { int frameCount = trackUtil.getFrameCount(paintProps.getFramesInfo()); // TODO: Issues with frameCount == 1? Could happen if we update on all - // tilts where we had multiple frames then they went away - if ((displayState.mode == Mode.TRACK && lastMode == Mode.DRAG_ME) - || (frameCount == 1 && displayState.geomChanged)) { - if (frameCount == 1 && displayState.geomChanged) { - displayState.geomChanged = false; - } + // tilts where we had multiple frames then they went away. + if (displayState.mode == Mode.TRACK && lastMode == Mode.DRAG_ME) { if (warningAction == null || warningAction == WarningAction.NEW) { // Initialize box redrawBoxFromTrack(); @@ -1993,15 +1989,12 @@ public class WarngenLayer extends AbstractStormTrackResource { && this.displayState.displayType != DisplayType.POLY) { createSquare(); return; + } else if (descriptor.getFramesInfo().getFrameCount() == 1) { + createSquare(); + return; } } - // Create a square polygon if time matcher basis is 1 frame. - if (descriptor.getFramesInfo().getFrameCount() == 1) { - createSquare(); - return; - } - DestinationGeodeticCalculator gc = new DestinationGeodeticCalculator(); GeometryFactory gf = new GeometryFactory(); From b57cadd40a42f2602ffc56105ad0d786dac848ce Mon Sep 17 00:00:00 2001 From: Dave Hladky Date: Thu, 10 Oct 2013 10:47:00 -0500 Subject: [PATCH 04/26] Issue #2466 Returned to original harvesterThreadPool Change-Id: Ia894f9e0330b1ae6f89a3bd3496e25085ad90b5d Former-commit-id: 0c8360db4546c949258d7229ce08413cf4437a94 [formerly 73aa2c69ac819ffed21fbb9efad2fd6d07ee46ca] [formerly 1c37f0f7659635b9d7bbe44ae29cdf11ae38dd05] [formerly beb0e573c1834b4b52123bde226b773a7786a181 [formerly 1c37f0f7659635b9d7bbe44ae29cdf11ae38dd05 [formerly 534a6e392dab175f4e683af522c5e800cbb1391d]]] Former-commit-id: beb0e573c1834b4b52123bde226b773a7786a181 Former-commit-id: 71bbc39b27da704277849a3577ea2b6de0371e48 [formerly 06ad289dc952fe297f65d5328894a88880c89357] Former-commit-id: ef46aa15755abeaa788eeb1d5e9150f52413665b --- edexOsgi/build.edex/esb/conf/modes.xml | 2 -- .../res/spring/harvester-datadelivery.xml | 7 ++++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/edexOsgi/build.edex/esb/conf/modes.xml b/edexOsgi/build.edex/esb/conf/modes.xml index 9cec116d65..86d13b4bcd 100644 --- a/edexOsgi/build.edex/esb/conf/modes.xml +++ b/edexOsgi/build.edex/esb/conf/modes.xml @@ -277,7 +277,6 @@ time-common.xml auth-common.xml nwsauth-request.xml - grid-staticdata-process.xml grid-common.xml gridcoverage-.*.xml parameter-common.xml @@ -403,7 +402,6 @@ obs-ogc.xml--> - - - java.lang.Throwable - - - - - - - - - \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/src/gov/noaa/nws/ncep/edex/plugin/ntrans/decoder/NtransDecoder.java b/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/src/gov/noaa/nws/ncep/edex/plugin/ntrans/decoder/NtransDecoder.java index 1bf593041c..b5f327c224 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/src/gov/noaa/nws/ncep/edex/plugin/ntrans/decoder/NtransDecoder.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/src/gov/noaa/nws/ncep/edex/plugin/ntrans/decoder/NtransDecoder.java @@ -10,6 +10,7 @@ * ------------ ---------- ----------- -------------------------- * 03/2013 B. Hebbard Initial creation * 04/2013 B. Hebbard IOC version (for OB13.4.1) + * 10/2013 B. Hebbard Modify model name inference from metafile name * * This code has been developed by the SIB for use in the AWIPS2 system. */ @@ -365,6 +366,61 @@ public class NtransDecoder extends AbstractDecoder { */ } + private enum Model { + //TODO - Remove this, to make decoder agnostic w.r.t. list of available models. + // We do this temporarily because we don't yet know the possible formats + // of filename strings we're going to be fed, so for now we just look for + // known model names appearing anywhere in the file name. + // NOTE: Sequence is important only insofar as any model name must appear + // after all model names of which it is a proper substring. + // Also, OPC_ENC comes first, since its metafiles may contain other + // model substrings + OPC_ENS, + CMCE_AVGSPR, + CMCE, + CMCVER, + CMC, + CPC, + DGEX, + ECENS_AVGSPR, + ECENS, + ECMWFVER, + ECMWF_HR, + ECMWF, + ENSVER, + FNMOCWAVE, + GDAS, + GEFS_AVGSPR, + GEFS, + GFSP, + GFSVERP, + GFSVER, + GFS, + GHM, + HPCQPF, + HPCVER, + HWRF, + ICEACCR, + JMAP, + JMA, + MEDRT, + NAEFS, + NAM20, + NAM44, + NAMVER, + NAM, + NAVGEM, + NOGAPS, + NWW3P, + NWW3, + RAPP, + RAP, + SREFX, + SST, + UKMETVER, + UKMET, + VAFTAD }; + private String inferModel(String fileName) { // Infer the model name from the file name @@ -387,14 +443,31 @@ public class NtransDecoder extends AbstractDecoder { fileName.contains("_GFS")) { modelName = "vaftad"; } + + /* else if (fileName.contains("_2")) { modelName = fileName.substring(0, fileName.indexOf("_2")); if (modelName.equals("jma")) { modelName = "jmap"; } } - - return modelName; + + return modelName; + */ + + else { + for (Model model : Model.values()) { + if (fileName.toLowerCase().contains(model.name().toLowerCase())) { + modelName = model.name().toLowerCase(); + break; + } + } + if (modelName.equals("jma")) { + modelName = "jmap"; + } + return modelName; + } + return "other"; // unrecognized } private ByteOrder determineEndianess(ByteBuffer byteBuffer) { diff --git a/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/AbstractGriddedDisplay.java b/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/AbstractGriddedDisplay.java index 12d892f896..6b35c3c184 100644 --- a/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/AbstractGriddedDisplay.java +++ b/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/AbstractGriddedDisplay.java @@ -41,12 +41,13 @@ import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.viz.core.IExtent; import com.raytheon.uf.viz.core.IGraphicsTarget; -//import com.raytheon.uf.viz.core.drawables.IRenderable; import com.raytheon.uf.viz.core.drawables.PaintProperties; import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.map.IMapDescriptor; import com.vividsolutions.jts.geom.Coordinate; +//import com.raytheon.uf.viz.core.drawables.IRenderable; + /** * An abstract resource for displays where each grid cell is an individual * IImage. Handles progressive disclosure algorithm. @@ -68,10 +69,11 @@ import com.vividsolutions.jts.geom.Coordinate; * @version 1.0 */ -public abstract class AbstractGriddedDisplay { //implements IRenderable +public abstract class AbstractGriddedDisplay { // implements IRenderable + + private static final IUFStatusHandler statusHandler = UFStatus + .getHandler(AbstractGriddedDisplay.class); - private static final IUFStatusHandler statusHandler = UFStatus.getHandler(AbstractGriddedDisplay.class); - private final Queue calculationQueue; private CalculationJob calculationJob; @@ -89,13 +91,15 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable protected RGB color; protected int skipx; + protected int skipy; + protected double filter; protected double magnification = 1.0; private boolean async = true; - + protected boolean[] isPlotted; /** @@ -105,22 +109,19 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable * @param size */ public AbstractGriddedDisplay(IMapDescriptor descriptor, - GeneralGridGeometry gridGeometryOfGrid,int nx, int ny) { + GeneralGridGeometry gridGeometryOfGrid, int nx, int ny) { this.calculationQueue = new ConcurrentLinkedQueue(); this.descriptor = descriptor; this.gridGeometryOfGrid = gridGeometryOfGrid; - -// this.size = size; - this.gridDims = new int[] { - nx, - ny }; - + // this.size = size; + + this.gridDims = new int[] { nx, ny }; + isPlotted = new boolean[gridDims[0] * gridDims[1]]; - - + } public void setASync(boolean async) { @@ -134,106 +135,104 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable * com.raytheon.viz.core.drawables.IRenderable#paint(com.raytheon.viz.core * .IGraphicsTarget, com.raytheon.viz.core.drawables.PaintProperties) */ - // @Override - public void paint(NcgridResourceData gridRscData, IGraphicsTarget target, PaintProperties paintProps) - throws VizException { - - boolean globalModel = isGlobalModel(); - - /** - * Get filter attribute + // @Override + public void paint(NcgridResourceData gridRscData, IGraphicsTarget target, + PaintProperties paintProps) throws VizException { + + boolean globalModel = isGlobalModel(); + + /** + * Get filter attribute */ - String den = gridRscData.getFilter(); - String noFilter = ""; - if (den != null ){ - try { - if (den.equalsIgnoreCase("YES") || den.equalsIgnoreCase("Y")) { - filter = 1.0; - } - else if (den.equalsIgnoreCase("NO") || den.equalsIgnoreCase("N") || den.equalsIgnoreCase("")) { - filter = 0.0; - noFilter = "NO"; - } - else { - filter = Double.parseDouble(den); - } - - if (filter == 0) - noFilter = "NO"; - if (filter <0.1) - filter = 0.1; - } - catch (NumberFormatException e) { - System.out.println("The filter is not a double number"); - filter = 1.0; - } - } - else { - filter = 1.0; - } - -// /** -// * Get skip attribute -// */ -// -// String[] skip = null; -// int skipx = 0; -// int skipy = 0; -// -// String skipString = gridRscData.getSkip(); //now for positive skip -// if (skipString != null && noFilter.equalsIgnoreCase("NO")) { -// int ind = skipString.indexOf("/"); -// if (ind != -1) { -// skipString = skipString.substring(ind +1); -// -// if (skipString.trim().startsWith("-")) //temp fix for negative value -// skipString = skipString.substring(1); -// -// skip = skipString.split(";"); -// -// if (skip != null && skip.length !=0){ -// try { -// skipx = Integer.parseInt(skip[0]); -// } -// catch (NumberFormatException e) { -// System.out.println("The skip is not an interger"); -// skipx = 0; -// } -// -// if (skip.length ==1 ) { -// skipy = skipx; -// } -// if (skip.length >1 && skip[0] != skip[1]) { -// try { -// skipy = Integer.parseInt(skip[1]); -// } -// catch (NumberFormatException e) { -// System.out.println("The skip is not an interger"); -// skipy = skipx; -// } -// } -// } -// else { -// skipx = 0; -// skipy = 0; -// } -// } -// else { -// skipx = 0; -// skipy = 0; -// } -// } -// else { -// skipx = 0; -// skipy = 0; -// } -// - - for (int i = 0; i < (gridDims[0] * gridDims[1]); i++) - isPlotted[i] = false; - + String den = gridRscData.getFilter(); + String noFilter = ""; + if (den != null) { + try { + if (den.equalsIgnoreCase("YES") || den.equalsIgnoreCase("Y")) { + filter = 1.0; + } else if (den.equalsIgnoreCase("NO") + || den.equalsIgnoreCase("N") + || den.equalsIgnoreCase("")) { + filter = 0.0; + noFilter = "NO"; + } else { + filter = Double.parseDouble(den); + } + + if (filter == 0) + noFilter = "NO"; + if (filter < 0.1) + filter = 0.1; + } catch (NumberFormatException e) { + System.out.println("The filter is not a double number"); + filter = 1.0; + } + } else { + filter = 1.0; + } + + // /** + // * Get skip attribute + // */ + // + // String[] skip = null; + // int skipx = 0; + // int skipy = 0; + // + // String skipString = gridRscData.getSkip(); //now for positive skip + // if (skipString != null && noFilter.equalsIgnoreCase("NO")) { + // int ind = skipString.indexOf("/"); + // if (ind != -1) { + // skipString = skipString.substring(ind +1); + // + // if (skipString.trim().startsWith("-")) //temp fix for negative value + // skipString = skipString.substring(1); + // + // skip = skipString.split(";"); + // + // if (skip != null && skip.length !=0){ + // try { + // skipx = Integer.parseInt(skip[0]); + // } + // catch (NumberFormatException e) { + // System.out.println("The skip is not an interger"); + // skipx = 0; + // } + // + // if (skip.length ==1 ) { + // skipy = skipx; + // } + // if (skip.length >1 && skip[0] != skip[1]) { + // try { + // skipy = Integer.parseInt(skip[1]); + // } + // catch (NumberFormatException e) { + // System.out.println("The skip is not an interger"); + // skipy = skipx; + // } + // } + // } + // else { + // skipx = 0; + // skipy = 0; + // } + // } + // else { + // skipx = 0; + // skipy = 0; + // } + // } + // else { + // skipx = 0; + // skipy = 0; + // } + // + + for (int i = 0; i < (gridDims[0] * gridDims[1]); i++) + isPlotted[i] = false; + // Controls whether to draw images or debugging output on the map -// boolean debug = false; + // boolean debug = false; this.target = target; PaintProperties pp = new PaintProperties(paintProps); @@ -242,8 +241,8 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable IExtent viewPixelExtent = paintProps.getView().getExtent(); double ratio = viewPixelExtent.getWidth() / paintProps.getCanvasBounds().width; - - //double interval = size * .75 * ratio / Math.min(2.0, filter); + + // double interval = size * .75 * ratio / Math.min(2.0, filter); double interval = size * .75 * ratio * filter; double adjSize = size * ratio * magnification; @@ -284,18 +283,15 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable } jcount++; /* - if (debug == true) { - // Draw a red labeled square over the area where - // we will look for grid points - target.drawString(null, icount + "," + jcount, i, j, - 0.0, TextStyle.NORMAL, new RGB(255, 0, 0), - HorizontalAlignment.CENTER, - VerticalAlignment.MIDDLE, 0.0); - target.drawRect(new PixelExtent(i - halfInterval, i - + halfInterval, j - halfInterval, j - + halfInterval), new RGB(255, 0, 0), 1, 1); - } - */ + * if (debug == true) { // Draw a red labeled square over + * the area where // we will look for grid points + * target.drawString(null, icount + "," + jcount, i, j, 0.0, + * TextStyle.NORMAL, new RGB(255, 0, 0), + * HorizontalAlignment.CENTER, VerticalAlignment.MIDDLE, + * 0.0); target.drawRect(new PixelExtent(i - halfInterval, i + * + halfInterval, j - halfInterval, j + halfInterval), new + * RGB(255, 0, 0), 1, 1); } + */ // Get a grid coordinate near i, j ReferencedCoordinate coordToTry = new ReferencedCoordinate( this.descriptor.getGridGeometry(), new Coordinate( @@ -304,23 +300,27 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable gridGeometryOfGrid, PixelInCell.CELL_CORNER); gridCell.y = Math.round(gridCell.y); gridCell.x = Math.round(gridCell.x); - - + + // System.out.println("Look--" + i + " , " + j); + // System.out.println("grid--" + gridCell.x + " , " + // + gridCell.y); /* * Convert negative longitude */ Coordinate coord = coordToTry.asLatLon(); double x = coord.x; if (globalModel && x < 0) { - x = x + 360; + x = x + 360; } - + Coordinate newCoord = new Coordinate(x, coord.y); - ReferencedCoordinate newrco = new ReferencedCoordinate(newCoord); + // System.out.println("latlon: " + newCoord); + ReferencedCoordinate newrco = new ReferencedCoordinate( + newCoord); Coordinate newGridCell = newrco.asGridCell( gridGeometryOfGrid, PixelInCell.CELL_CORNER); newGridCell.x = Math.round(newGridCell.x); - + /* * Check for bounds */ @@ -328,33 +328,33 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable || (gridCell.y < 0 || gridCell.y >= gridDims[1])) { thisRow.put(j, i); continue; - + } - + ReferencedCoordinate rco = new ReferencedCoordinate( - new Coordinate((int)gridCell.x, (int)gridCell.y), - this.gridGeometryOfGrid, Type.GRID_CORNER); - Coordinate plotLoc = rco.asPixel(this.descriptor.getGridGeometry()); - Coordinate gridCell2 = rco.asGridCell( - gridGeometryOfGrid, PixelInCell.CELL_CORNER); - -// Coordinate plotLoc = coordToTry.asPixel(this.descriptor -// .getGridGeometry()); - - + new Coordinate((int) gridCell.x, (int) gridCell.y), + this.gridGeometryOfGrid, Type.GRID_CORNER); + Coordinate plotLoc = rco.asPixel(this.descriptor + .getGridGeometry()); + Coordinate gridCell2 = rco.asGridCell(gridGeometryOfGrid, + PixelInCell.CELL_CORNER); + + // System.out.println("gridcell: " + gridCell); + // System.out.println("gridcell2: " + gridCell2); + // Coordinate plotLoc = coordToTry.asPixel(this.descriptor + // .getGridGeometry()); + /* - if (debug == true) { - // draw a blue dot where the gridpoints are found. - target.drawString(null, ".", plotLoc.x, plotLoc.y, 0.0, - TextStyle.NORMAL, new RGB(0, 0, 255), - HorizontalAlignment.CENTER, - VerticalAlignment.BOTTOM, 0.0); - } - */ + * if (debug == true) { // draw a blue dot where the + * gridpoints are found. target.drawString(null, ".", + * plotLoc.x, plotLoc.y, 0.0, TextStyle.NORMAL, new RGB(0, + * 0, 255), HorizontalAlignment.CENTER, + * VerticalAlignment.BOTTOM, 0.0); } + */ // If the real loc of this grid coordinate is close to the // loc we wanted go with it - if (Math.abs(plotLoc.y - j) < (interval/2) - && Math.abs(plotLoc.x - i) < (interval/2)) { + if (Math.abs(plotLoc.y - j) < (interval / 2) + && Math.abs(plotLoc.x - i) < (interval / 2)) { j = plotLoc.y; thisRow.put(j, plotLoc.x); } else { @@ -362,21 +362,24 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable continue; } /* - if (debug == true) { - // Draw a green label where the image will actually be - // drawn - target.drawString(null, icount + "," + jcount, - plotLoc.x, plotLoc.y, 0.0, TextStyle.NORMAL, - new RGB(0, 255, 0), HorizontalAlignment.CENTER, - VerticalAlignment.MIDDLE, 0.0); - } - */ - + * if (debug == true) { // Draw a green label where the + * image will actually be // drawn target.drawString(null, + * icount + "," + jcount, plotLoc.x, plotLoc.y, 0.0, + * TextStyle.NORMAL, new RGB(0, 255, 0), + * HorizontalAlignment.CENTER, VerticalAlignment.MIDDLE, + * 0.0); } + */ + T oldImage = getImage(gridCell2); if (oldImage != null) { -// if (debug == false) { - paintImage((int)gridCell.x, (int)gridCell.y, pp, adjSize); -// } + // if (debug == false) { + if (globalModel) + paintGlobalImage((int) gridCell.x, + (int) gridCell.y, pp, adjSize); + else + paintImage((int) gridCell.x, (int) gridCell.y, pp, + adjSize); + // } } else { if (async) { if (!this.calculationQueue.contains(gridCell2)) { @@ -384,17 +387,22 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable } } else { T image = createImage(gridCell2); - if (image != null /*&& debug == false*/) { - paintImage((int)gridCell.x, (int)gridCell.y, pp, adjSize); + if (image != null /* && debug == false */) { + if (globalModel) + paintGlobalImage((int) gridCell.x, + (int) gridCell.y, pp, adjSize); + else + paintImage((int) gridCell.x, + (int) gridCell.y, pp, adjSize); } } - } + } } - } //while + } // while } catch (Exception e) { throw new VizException("Error occured during paint", e); } - + if (calculationQueue.size() > 0) { if (this.calculationJob == null) { this.calculationJob = new CalculationJob(); @@ -429,8 +437,13 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable */ protected abstract void disposeImages(); - protected abstract void paintImage(int x, int y, PaintProperties paintProps, - double adjustedSize) throws VizException; + protected abstract void paintImage(int x, int y, + PaintProperties paintProps, double adjustedSize) + throws VizException; + + protected abstract void paintGlobalImage(int x, int y, + PaintProperties paintProps, double adjustedSize) + throws VizException; public void dispose() { disposeImages(); @@ -451,7 +464,7 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable /** * @param filter - * the filter to set. Changed from density. + * the filter to set. Changed from density. */ public boolean setFilter(double filter) { if (this.filter != filter) { @@ -461,16 +474,15 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable return false; } - public float getSize() { - return size; - } + return size; + } - public void setSize(float size) { - this.size = size; - } + public void setSize(float size) { + this.size = size; + } - /** + /** * @param magnification * the magnification to set */ @@ -482,38 +494,36 @@ public abstract class AbstractGriddedDisplay { //implements IRenderable return false; } - private boolean isGlobalModel() throws VizException { - - ReferencedCoordinate newrco0 = new ReferencedCoordinate( - new Coordinate(0, 0), - this.gridGeometryOfGrid, Type.GRID_CORNER); - ReferencedCoordinate newrco1 = new ReferencedCoordinate( - new Coordinate(gridDims[0] - 1, 0), - this.gridGeometryOfGrid, Type.GRID_CORNER); - ReferencedCoordinate newrco2 = new ReferencedCoordinate( - new Coordinate(1, 0), - this.gridGeometryOfGrid, Type.GRID_CORNER); - try { - Coordinate latLon0 = newrco0.asLatLon(); - Coordinate latLon1 = newrco1.asLatLon(); - Coordinate latLon2 = newrco2.asLatLon(); - - double dx1 = latLon2.x - latLon0.x; - double dx2 = (360 - latLon1.x) + latLon0.x; - - int dx = (int) Math.round(dx2/dx1); - int dlat = (int) Math.round(latLon1.y - latLon0.y); + ReferencedCoordinate newrco0 = new ReferencedCoordinate(new Coordinate( + 0, 0), this.gridGeometryOfGrid, Type.GRID_CORNER); + ReferencedCoordinate newrco1 = new ReferencedCoordinate(new Coordinate( + gridDims[0] - 1, 0), this.gridGeometryOfGrid, Type.GRID_CORNER); + ReferencedCoordinate newrco2 = new ReferencedCoordinate(new Coordinate( + 1, 0), this.gridGeometryOfGrid, Type.GRID_CORNER); - if (dx <= 2 && dlat == 0) return true; - - } catch (Exception e) { - throw new VizException(e); - } - - return false; + try { + Coordinate latLon0 = newrco0.asLatLon(); + Coordinate latLon1 = newrco1.asLatLon(); + Coordinate latLon2 = newrco2.asLatLon(); + + double dx1 = latLon2.x - latLon0.x; + double dx2 = (360 - latLon1.x) + latLon0.x; + + int dx = (int) Math.round(dx2 / dx1); + int dlat = (int) Math.round(latLon1.y - latLon0.y); + + if (dx <= 2 && dlat == 0) + return true; + + } catch (Exception e) { + throw new VizException(e); + } + + return false; } + /** * Off UI Thread job for calculating the wind images * diff --git a/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/ContourSupport.java b/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/ContourSupport.java index 71c2ff429b..0cd036de4c 100644 --- a/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/ContourSupport.java +++ b/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/ContourSupport.java @@ -49,13 +49,13 @@ import java.util.TreeMap; import org.eclipse.swt.graphics.RGB; import org.geotools.coverage.grid.GeneralGridGeometry; import org.geotools.geometry.GeneralEnvelope; +import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; +import org.geotools.referencing.operation.DefaultMathTransformFactory; import org.geotools.referencing.operation.projection.MapProjection; import org.geotools.referencing.operation.projection.MapProjection.AbstractProvider; -import org.opengis.parameter.ParameterValueGroup; -import org.geotools.geometry.jts.ReferencedEnvelope; -import org.geotools.referencing.operation.DefaultMathTransformFactory; import org.opengis.coverage.grid.GridGeometry; +import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.datum.PixelInCell; import org.opengis.referencing.operation.MathTransform; @@ -114,7 +114,7 @@ import com.vividsolutions.jts.linearref.LocationIndexedLine; * May 23, 2012 X. Guo Loaded ncgrib logger * Apr 26, 2013 B. Yin Fixed the world wrap problem for centeral line 0/180. * Jun 06, 2013 B. Yin fixed the half-degree grid porblem. - * Jul 19, 2013 B. Hebbard Merge in RTS change of Util-->ArraysUtil + * Jul 19, 2013 B. Hebbard Merge in RTS change of Util-->ArraysUtil * Aug 19, 2013 #743 S. Gurung Added clrbar and corresponding getter/setter method (from Archana's branch) and * fix for editing clrbar related attribute changess not being applied from right click legend. * @@ -124,58 +124,80 @@ import com.vividsolutions.jts.linearref.LocationIndexedLine; */ public class ContourSupport { - private static NcepLogger logger = NcepLoggerManager.getNcepLogger(ContourSupport.class); + private static NcepLogger logger = NcepLoggerManager + .getNcepLogger(ContourSupport.class); + + // provided values + private IDataRecord records; + + private int level; + + private IExtent extent; + + private double currentDensity; + + private IMapDescriptor descriptor; + + private ContourAttributes attr; + + private String cint; + + private String fint; + + private String type; + + private String fline; + + private String name; + + private float zoom; + + // calculated values + private ContourGroup contourGroup = null; + + private MathTransform rastPosToWorldGrid = null; - //provided values - private IDataRecord records; - private int level; - private IExtent extent; - private double currentDensity; - private IMapDescriptor descriptor; - private ContourAttributes attr; - private String cint; - private String fint; - private String type; - private String fline; - private String name; - private float zoom; - - //calculated values - private ContourGroup contourGroup = null; - private MathTransform rastPosToWorldGrid = null; private MathTransform rastPosToLatLon = null; + private MathTransform rastPosLatLonToWorldGrid = null; + private int zoomLevelIndex; + private ContourGridData cntrData = null; + private List cvalues; + private List fvalues; + private Set svalues; + private boolean globalData = false; - - //world map with central meridian at 180 degree + + // world map with central meridian at 180 degree private boolean isWorld180; - - //return value from raytheon's worlWrapChecker + + // return value from raytheon's worlWrapChecker private boolean worldWrapChecker; - //flag that indicates world wrap is needed + // flag that indicates world wrap is needed private boolean worldWrap; - - //central meridian + + // central meridian private double centralMeridian = 0; - - //screen width of the map + + // screen width of the map private double mapScreenWidth; - - //screen x of the zero longitude + + // screen x of the zero longitude private double zeroLonOnScreen; - - //maximum number of grid along x direction + + // maximum number of grid along x direction private int maxGridX; - + private boolean isCntrsCreated; + private static NcgribLogger ncgribLogger = NcgribLogger.getInstance(); - + /** * Constructor * @@ -193,23 +215,18 @@ public class ContourSupport { * @param zoom * @param contourGp * */ - public ContourSupport(IDataRecord records, int level, - IExtent extent, double currentDensity, - MathTransform worldGridToCRSTransform, + public ContourSupport(IDataRecord records, int level, IExtent extent, + double currentDensity, MathTransform worldGridToCRSTransform, GeneralGridGeometry imageGridGeometry, GeneralGridGeometry mapGridGeometry, IGraphicsTarget target, - IMapDescriptor descriptor, ContourAttributes attr, String name, float zoom, - ContourGroup contourGp) { - - initContourSupport ( records, level, - extent, currentDensity, - worldGridToCRSTransform, - imageGridGeometry, - mapGridGeometry, target, - descriptor, attr, name, zoom, - contourGp); + IMapDescriptor descriptor, ContourAttributes attr, String name, + float zoom, ContourGroup contourGp) { + + initContourSupport(records, level, extent, currentDensity, + worldGridToCRSTransform, imageGridGeometry, mapGridGeometry, + target, descriptor, attr, name, zoom, contourGp); } - + /** * Data structure for contouring */ @@ -219,7 +236,7 @@ public class ContourSupport { public IWireframeShape posValueShape; public IWireframeShape negValueShape; - + public IShadedShape fillShapes; public ContourGroup parent; @@ -229,187 +246,200 @@ public class ContourSupport { public double lastDensity; public GridGeometry gridGeometry; - + public List cvalues; - + public List fvalues; - - public HashMap< String, Geometry> data; - + + public HashMap data; + public LinearRing grid; public CLRBAR clrbar; - + public ColorBar colorBarForGriddedFill; - + } public class ContourGridData { - private float minValue; - private float maxValue; - private float[] data; - private int szX; - private int szY; - - public ContourGridData ( IDataRecord record ) { - maxValue = Float.MIN_VALUE; + private float minValue; + + private float maxValue; + + private float[] data; + + private int szX; + + private int szY; + + public ContourGridData(IDataRecord record) { + maxValue = Float.MIN_VALUE; minValue = Float.MAX_VALUE; float[] data1D = null; long[] sz = record.getSizes(); - + data1D = ((NcFloatDataRecord) record).getXdata(); - - szX = (int)sz[0]; - szY = (int)sz[1]; - data = new float[szX*szY]; + + szX = (int) sz[0]; + szY = (int) sz[1]; + data = new float[szX * szY]; for (int j = 0; j < szY; j++) { for (int i = 0; i < szX; i++) { - data[szX * j + i] = data1D[(szX * j)+ i]; - if ( data[szX * j + i] != -999999.f ) { - maxValue = Math.max( maxValue, data[szX * j + i]); - minValue = Math.min( minValue, data[szX * j + i]); - } + data[szX * j + i] = data1D[(szX * j) + i]; + if (data[szX * j + i] != -999999.f) { + maxValue = Math.max(maxValue, data[szX * j + i]); + minValue = Math.min(minValue, data[szX * j + i]); + } } } - } - - public float getMinValue () { - return minValue; - } - - public float getMaxValue () { - return maxValue; - } - - public float[] getData () { - return data; - } - public int getX () { - return szX; - } - - public int getY () { - return szY; - } + } + + public float getMinValue() { + return minValue; + } + + public float getMaxValue() { + return maxValue; + } + + public float[] getData() { + return data; + } + + public int getX() { + return szX; + } + + public int getY() { + return szY; + } } - + public void initContourSupport(IDataRecord records, int level, IExtent extent, double currentDensity, MathTransform worldGridToCRSTransform, GeneralGridGeometry imageGridGeometry, GeneralGridGeometry mapGridGeometry, IGraphicsTarget target, - IMapDescriptor descriptor, ContourAttributes attr, String name, float zoom, - ContourGroup contourGp) { - isCntrsCreated = true; - if ( records == null || attr == null ) { - isCntrsCreated = false; - return; - } - if ( ! initMathTransform (imageGridGeometry,mapGridGeometry) ) { - isCntrsCreated = false; - return; - } - this.records = records; - this.level = level; - this.extent = extent; - this.currentDensity = currentDensity; - this.descriptor = descriptor; - this.attr = attr; - this.cint = attr.getCint(); - this.type = attr.getType(); - this.fint = attr.getFint(); - this.fline = attr.getFline(); - this.name = name; - this.zoom = zoom; - this.cntrData = new ContourGridData(records); - this.centralMeridian = getCentralMeridian(descriptor); - if ( centralMeridian == -180 ) centralMeridian = 180; - this.isWorld180 = (centralMeridian == 180.0); - this.worldWrapChecker = new WorldWrapChecker(descriptor.getGridGeometry().getEnvelope()).needsChecking(); - this.worldWrap = needWrap(imageGridGeometry, rastPosToLatLon); - mapScreenWidth = this.getMapWidth(); + IMapDescriptor descriptor, ContourAttributes attr, String name, + float zoom, ContourGroup contourGp) { + isCntrsCreated = true; + if (records == null || attr == null) { + isCntrsCreated = false; + return; + } + if (!initMathTransform(imageGridGeometry, mapGridGeometry)) { + isCntrsCreated = false; + return; + } + this.records = records; + this.level = level; + this.extent = extent; + this.currentDensity = currentDensity; + this.descriptor = descriptor; + this.attr = attr; + this.cint = attr.getCint(); + this.type = attr.getType(); + this.fint = attr.getFint(); + this.fline = attr.getFline(); + this.name = name; + this.zoom = zoom; + this.cntrData = new ContourGridData(records); + this.centralMeridian = getCentralMeridian(descriptor); + if (centralMeridian == -180) + centralMeridian = 180; + this.isWorld180 = (centralMeridian == 180.0); + this.worldWrapChecker = new WorldWrapChecker(descriptor + .getGridGeometry().getEnvelope()).needsChecking(); + this.worldWrap = needWrap(imageGridGeometry, rastPosToLatLon); + mapScreenWidth = this.getMapWidth(); maxGridX = this.getMaxGridX(imageGridGeometry); - initContourGroup ( target,contourGp ); + initContourGroup(target, contourGp); } + /** * Create contours from provided parameters * */ - public void createContours( ) { - - long t0 = System.currentTimeMillis(); - + public void createContours() { + + long t0 = System.currentTimeMillis(); + // Copy the pixel extent (deep copy required!) // expand by 50% to cover the subgrid expansion -/* PixelExtent workingExtent = (PixelExtent) extent.clone(); - workingExtent.getEnvelope().expandBy(workingExtent.getWidth() * .5, - workingExtent.getHeight() * .5);*/ + /* + * PixelExtent workingExtent = (PixelExtent) extent.clone(); + * workingExtent.getEnvelope().expandBy(workingExtent.getWidth() * .5, + * workingExtent.getHeight() * .5); + */ /* * Contours and/or color fills */ - if (records instanceof NcFloatDataRecord && - !((NcFloatDataRecord)records).isVector()) { + if (records instanceof NcFloatDataRecord + && !((NcFloatDataRecord) records).isVector()) { long t1 = System.currentTimeMillis(); - logger.debug("Preparing " + name + " grid data took: " + (t1-t0)); - + logger.debug("Preparing " + name + " grid data took: " + (t1 - t0)); + /* - * ZoomLevel. + * ZoomLevel. */ - initZoomIndex (); - + initZoomIndex(); + long t1a = System.currentTimeMillis(); - logger.debug("new ContourGenerator took: " + (t1a-t1)); - + logger.debug("new ContourGenerator took: " + (t1a - t1)); + /* - * Get contour values from CINT - */ - cvalues = calcCintValue (); + * Get contour values from CINT + */ + cvalues = calcCintValue(); /* - * Get color fill values from FINT and FLINE - */ - fvalues = calcFintValue (); + * Get color fill values from FINT and FLINE + */ + fvalues = calcFintValue(); /* * Combine contour and fill values */ - combineCintAndFillValues (); - + combineCintAndFillValues(); + long t2 = System.currentTimeMillis(); - if ( svalues != null && svalues.size() > 0 ) { - genContour (); - if ( ! isCntrsCreated ) return; - } - else { - logger.debug("Re-load contour line values took: " + (t2-t1)); + if (svalues != null && svalues.size() > 0) { + genContour(); + if (!isCntrsCreated) + return; + } else { + logger.debug("Re-load contour line values took: " + (t2 - t1)); } /* * Create contour lines and labels wireframes */ - createContourLines (); + createContourLines(); /* * Create color fills */ createColorFills(); - + long t10 = System.currentTimeMillis(); -// System.out.println("Contouring/Filling took: " + (t10-t0)); - logger.debug("===Total time for ("+name+") "+ " took: " + (t10-t0) + "\n"); -// logger.info("===Total time for "+ cf_string + " " + attr.getGdpfun().trim().toUpperCase() -// + " took: " + (t10-t0) + "\n"); - -// System.out.println("Total time for " + cf_string + " " + name + " took: " + (t10-t0) + "\n"); - /* - * Streamlines - */ + // System.out.println("Contouring/Filling took: " + (t10-t0)); + logger.debug("===Total time for (" + name + ") " + " took: " + + (t10 - t0) + "\n"); + // logger.info("===Total time for "+ cf_string + " " + + // attr.getGdpfun().trim().toUpperCase() + // + " took: " + (t10-t0) + "\n"); + + // System.out.println("Total time for " + cf_string + " " + name + + // " took: " + (t10-t0) + "\n"); + /* + * Streamlines + */ } else { - createStreamLines(); + createStreamLines(); } } public static GeneralEnvelope calculateSubGrid(IExtent workingExtent, GeneralGridGeometry mapGridGeometry, - GeneralGridGeometry imageGridGeometry) { + GeneralGridGeometry imageGridGeometry) { GeneralEnvelope env = null; try { // transform screen extent to map crs @@ -420,16 +450,17 @@ public class ContourSupport { mapGridGeometry.getGridToCRS(PixelInCell.CELL_CORNER).transform( screen, 0, map, 0, 2); Envelope mapEnv = new Envelope(map[0], map[2], map[1], map[3]); - + // transform map envelope to image crs ReferencedEnvelope ref = new ReferencedEnvelope(mapEnv, mapGridGeometry.getCoordinateReferenceSystem()); - - Envelope imageEnv = ref.transform(imageGridGeometry - .getCoordinateReferenceSystem(), true); - if (imageEnv == null) return null; - + Envelope imageEnv = ref.transform( + imageGridGeometry.getCoordinateReferenceSystem(), true); + + if (imageEnv == null) + return null; + // transform image envelope to image grid cells double[] image = new double[] { imageEnv.getMinX(), imageEnv.getMinY(), imageEnv.getMaxX(), imageEnv.getMaxY() }; @@ -438,460 +469,477 @@ public class ContourSupport { .transform(image, 0, grid, 0, 2); env = new GeneralEnvelope(2); - env.setRange(0, Math.min(grid[0], grid[2]), Math.max(grid[0], - grid[2])); - env.setRange(1, Math.min(grid[1], grid[3]), Math.max(grid[1], - grid[3])); + env.setRange(0, Math.min(grid[0], grid[2]), + Math.max(grid[0], grid[2])); + env.setRange(1, Math.min(grid[1], grid[3]), + Math.max(grid[1], grid[3])); } catch (Exception e) { -// throw new VizException("Error transforming extent", e); + // throw new VizException("Error transforming extent", e); logger.error("Error transforming extent:" + e); return null; } -// System.out.println("*** Subgrid: " + env); + // System.out.println("*** Subgrid: " + env); return env; } - private static void createContourLabel(IExtent extent, ContourGroup contourGroup, - float contourValue, double[][] valsArr) { - - double minx = extent.getMinX(); - double miny = extent.getMinY(); - double maxx = extent.getMaxX(); - double maxy = extent.getMaxY(); - - double[][] visiblePts = new double[valsArr.length][valsArr[0].length]; - int actualLength = 0; - - for ( double[] dl : valsArr ) { - if ( dl[0] > minx && dl[0] < maxx && - dl[1] > miny && dl[1] < maxy ) { - visiblePts[actualLength][0] = dl[0]; - visiblePts[actualLength][1] = dl[1]; - actualLength++; - } - } - - DecimalFormat df = new DecimalFormat("0.#"); - double[] loc = {0.0, 0.0}; - - if (actualLength > 0) { - loc[ 0 ] = visiblePts[ actualLength/2 ][0]; - loc[ 1 ] = visiblePts[ actualLength/2 ][1]; - - contourGroup.negValueShape.addLabel(df - .format(contourValue), loc); - } - - } - private double[][] toScreen(Coordinate[] coords, MathTransform xform, int minX, int minY) { - - int size = coords.length; - - //remove points on longitude 360 degree. to avoid long cross lines - if ( isWorld180 ) { - for ( Coordinate pt : coords ){ - if ( pt.x == maxGridX) size--; - } - } - - double[][] out = new double[size][3]; - long nx = records.getSizes()[0] - 1; - - for ( int i=0, jj = 0; i< coords.length; i++, jj++ ) { - if ( isWorld180 && coords[i].x == maxGridX ){ jj--; continue;} - - double[] tmp = new double[2]; - tmp[0]=coords[i].x + minX; - tmp[1]=coords[i].y + minY; -// if (tmp[0] > 180) tmp[0] -= 360; - - try { - xform.transform(tmp, 0, out[jj], 0, 1); - } catch (TransformException e) { - // TODO Auto-generated catch block - // e.printStackTrace(); - return null; - } - - if ( worldWrapChecker ) { - if ( tmp[0] > (nx-1) && out[jj][0] < 0){ - out[jj][0] = mapScreenWidth; - } - else if (tmp[0] < 1 && out[jj][0] > mapScreenWidth*0.9 ){ - out[jj][0] = 0; - } - } + private static void createContourLabel(IExtent extent, + ContourGroup contourGroup, float contourValue, double[][] valsArr) { + double minx = extent.getMinX(); + double miny = extent.getMinY(); + double maxx = extent.getMaxX(); + double maxy = extent.getMaxY(); + + double[][] visiblePts = new double[valsArr.length][valsArr[0].length]; + int actualLength = 0; + + for (double[] dl : valsArr) { + if (dl[0] > minx && dl[0] < maxx && dl[1] > miny && dl[1] < maxy) { + visiblePts[actualLength][0] = dl[0]; + visiblePts[actualLength][1] = dl[1]; + actualLength++; + } } - - if ( out.length > 0 ) { - return out; - } - else { - return null; + + DecimalFormat df = new DecimalFormat("0.#"); + double[] loc = { 0.0, 0.0 }; + + if (actualLength > 0) { + loc[0] = visiblePts[actualLength / 2][0]; + loc[1] = visiblePts[actualLength / 2][1]; + + contourGroup.negValueShape.addLabel(df.format(contourValue), loc); } + } - private double[][] toScreenRightOfZero(Coordinate[] coords, MathTransform xform, int minX, int minY) { - // Coordinate[] out = new Coordinate[coords.length]; - double[][] out = new double[coords.length][3]; - - for ( int i=0; i< coords.length; i++ ) { - double[] tmp = new double[2]; - tmp[0]=coords[i].x + minX; - tmp[1]=coords[i].y + minY; - - try { - xform.transform(tmp, 0, out[i], 0, 1); - } catch (TransformException e) { - // e.printStackTrace(); - return null; - } - - // System.out.println("WWWWWWW " + tmp[0]+" " + " " + out[i][0]); - - if ( out[i][0] < zeroLonOnScreen || (tmp[0] == maxGridX && out[i][0] == zeroLonOnScreen)){ - out[i][0] += mapScreenWidth; - // System.out.println("Shift " + tmp[0]+" " + out[i][0]); - } - // else if ( delta < 0 && !(out[i][0] < middle ) && (delta < 0 || Math.abs(out[i][0]) < Math.abs(delta)) ){ - - // System.out.println("SSSSSSSSSSSShift" + tmp[0]+" " + tmpout[0] + " " + out[i][0]); - // out[i][0] += delta; - // } - - } - - if ( out.length > 0 ) { - return out; - } - else { - return null; - } - } - - private LineString toScreenLSRightOfZero(Coordinate[] coords, MathTransform xform, int minX, int minY) { - GeometryFactory gf = new GeometryFactory(); - Coordinate[] out = new Coordinate[coords.length]; - double[] tmpout = new double[3]; - - for ( int i=0; i< coords.length; i++ ) { - double[] tmp = new double[2]; - tmp[0]=coords[i].x + minX; - tmp[1]=coords[i].y + minY; - - try { - xform.transform(tmp, 0, tmpout, 0, 1); - } catch (TransformException e) { - // e.printStackTrace(); - return null; - } - - if ( tmpout[0] < zeroLonOnScreen || (tmp[0] == maxGridX && tmpout[0] == zeroLonOnScreen)){ - tmpout[0] += mapScreenWidth; - } - - out[i] = new Coordinate( tmpout[0], tmpout[1] ); - - } - - if ( out.length >= 2 ) { - return gf.createLineString(out); - } - else { - return null; - } - } - - private double[][] toScreenLeftOfZero(Coordinate[] coords, MathTransform xform, int minX, int minY) { - // Coordinate[] out = new Coordinate[coords.length]; - double[][] out = new double[coords.length][3]; - - for ( int i=0; i< coords.length; i++ ) { - double[] tmp = new double[2]; - tmp[0]=coords[i].x + minX; - tmp[1]=coords[i].y + minY; - - try { - xform.transform(tmp, 0, out[i], 0, 1); - } catch (TransformException e) { - // e.printStackTrace(); - return null; - } - - // System.out.println("WWWWWWW " + tmp[0]+" " + tmpout[0] + " " + out[i][0]); - - if ( out[i][0] > zeroLonOnScreen || ( tmp[0] == 0 && out[i][0] == zeroLonOnScreen )){ - // System.out.println("Shift " + tmp[0]+" " + out[i][0]); - out[i][0] -= mapScreenWidth; - } - - } - - if ( out.length > 0 ) { - return out; - } - else { - return null; - } - } - - - private LineString toScreenLSLeftOfZero(Coordinate[] coords, MathTransform xform, int minX, int minY) { - GeometryFactory gf = new GeometryFactory(); - Coordinate[] out = new Coordinate[coords.length]; - double[] tmpout = new double[3]; - - for ( int i=0; i< coords.length; i++ ) { - double[] tmp = new double[2]; - tmp[0]=coords[i].x + minX; - tmp[1]=coords[i].y + minY; - - try { - xform.transform(tmp, 0, tmpout, 0, 1); - } catch (TransformException e) { - // e.printStackTrace(); - return null; - } - - if ( tmpout[0] > zeroLonOnScreen || (tmp[0] == 0 && tmpout[0] == zeroLonOnScreen)){ - tmpout[0] -= mapScreenWidth; - } - - out[i] = new Coordinate( tmpout[0], tmpout[1] ); - - } - - if ( out.length >= 2 ) { - return gf.createLineString(out); - } - else { - return null; - } - } - private LineString toScreenLS(Coordinate[] coords, MathTransform xform, int minX, int minY) { - - GeometryFactory gf = new GeometryFactory(); - long nx = records.getSizes()[0] - 1; + private double[][] toScreen(Coordinate[] coords, MathTransform xform, + int minX, int minY) { int size = coords.length; - //remove points on 360. to avoid long cross lines - if ( isWorld180 ) { - for ( Coordinate pt : coords ){ - if ( pt.x == maxGridX) size--; - } - } - + + // remove points on longitude 360 degree. to avoid long cross lines + if (isWorld180) { + for (Coordinate pt : coords) { + if (pt.x == maxGridX) + size--; + } + } + + double[][] out = new double[size][3]; + long nx = records.getSizes()[0] - 1; + + for (int i = 0, jj = 0; i < coords.length; i++, jj++) { + if (isWorld180 && coords[i].x == maxGridX) { + jj--; + continue; + } + + double[] tmp = new double[2]; + tmp[0] = coords[i].x + minX; + tmp[1] = coords[i].y + minY; + // if (tmp[0] > 180) tmp[0] -= 360; + + try { + xform.transform(tmp, 0, out[jj], 0, 1); + } catch (TransformException e) { + // TODO Auto-generated catch block + // e.printStackTrace(); + return null; + } + + if (worldWrap) { + if (tmp[0] > (nx - 1) && out[jj][0] < 0) { + out[jj][0] = mapScreenWidth; + } else if (tmp[0] < 1 && out[jj][0] > mapScreenWidth * 0.9) { + out[jj][0] = 0; + } + } + + } + + if (out.length > 0) { + return out; + } else { + return null; + } + } + + private double[][] toScreenRightOfZero(Coordinate[] coords, + MathTransform xform, int minX, int minY) { + // Coordinate[] out = new Coordinate[coords.length]; + double[][] out = new double[coords.length][3]; + + for (int i = 0; i < coords.length; i++) { + double[] tmp = new double[2]; + tmp[0] = coords[i].x + minX; + tmp[1] = coords[i].y + minY; + + try { + xform.transform(tmp, 0, out[i], 0, 1); + } catch (TransformException e) { + // e.printStackTrace(); + return null; + } + + if (out[i][0] < zeroLonOnScreen + || (tmp[0] == maxGridX && out[i][0] == zeroLonOnScreen)) { + out[i][0] += mapScreenWidth; + + } + } + + if (out.length > 0) { + return out; + } else { + return null; + } + } + + private LineString toScreenLSRightOfZero(Coordinate[] coords, + MathTransform xform, int minX, int minY) { + GeometryFactory gf = new GeometryFactory(); + Coordinate[] out = new Coordinate[coords.length]; + double[] tmpout = new double[3]; + + for (int i = 0; i < coords.length; i++) { + double[] tmp = new double[2]; + tmp[0] = coords[i].x + minX; + tmp[1] = coords[i].y + minY; + + try { + xform.transform(tmp, 0, tmpout, 0, 1); + } catch (TransformException e) { + // e.printStackTrace(); + return null; + } + + if (tmpout[0] < zeroLonOnScreen + || (tmp[0] == maxGridX && tmpout[0] == zeroLonOnScreen)) { + tmpout[0] += mapScreenWidth; + } + + out[i] = new Coordinate(tmpout[0], tmpout[1]); + + } + + if (out.length >= 2) { + return gf.createLineString(out); + } else { + return null; + } + } + + private double[][] toScreenLeftOfZero(Coordinate[] coords, + MathTransform xform, int minX, int minY) { + // Coordinate[] out = new Coordinate[coords.length]; + double[][] out = new double[coords.length][3]; + + for (int i = 0; i < coords.length; i++) { + double[] tmp = new double[2]; + tmp[0] = coords[i].x + minX; + tmp[1] = coords[i].y + minY; + + try { + xform.transform(tmp, 0, out[i], 0, 1); + } catch (TransformException e) { + // e.printStackTrace(); + return null; + } + + // System.out.println("WWWWWWW " + tmp[0]+" " + tmpout[0] + + // " " + out[i][0]); + + if (out[i][0] > zeroLonOnScreen + || (tmp[0] == 0 && out[i][0] == zeroLonOnScreen)) { + // System.out.println("Shift " + tmp[0]+" " + out[i][0]); + out[i][0] -= mapScreenWidth; + } + + } + + if (out.length > 0) { + return out; + } else { + return null; + } + } + + private LineString toScreenLSLeftOfZero(Coordinate[] coords, + MathTransform xform, int minX, int minY) { + GeometryFactory gf = new GeometryFactory(); + Coordinate[] out = new Coordinate[coords.length]; + double[] tmpout = new double[3]; + + for (int i = 0; i < coords.length; i++) { + double[] tmp = new double[2]; + tmp[0] = coords[i].x + minX; + tmp[1] = coords[i].y + minY; + + try { + xform.transform(tmp, 0, tmpout, 0, 1); + } catch (TransformException e) { + // e.printStackTrace(); + return null; + } + + if (tmpout[0] > zeroLonOnScreen + || (tmp[0] == 0 && tmpout[0] == zeroLonOnScreen)) { + tmpout[0] -= mapScreenWidth; + } + + out[i] = new Coordinate(tmpout[0], tmpout[1]); + + } + + if (out.length >= 2) { + return gf.createLineString(out); + } else { + return null; + } + } + + private LineString toScreenLS(Coordinate[] coords, MathTransform xform, + int minX, int minY) { + + GeometryFactory gf = new GeometryFactory(); + long nx = records.getSizes()[0] - 1; + + int size = coords.length; + // remove points on 360. to avoid long cross lines + if (isWorld180) { + for (Coordinate pt : coords) { + if (pt.x == maxGridX) + size--; + } + } + Coordinate[] out = new Coordinate[size]; double[] tmpout = new double[3]; - for ( int i=0, jj = 0; i< coords.length; i++, jj++ ) { - if ( isWorld180 && coords[i].x == maxGridX ){ jj--; continue;} - - double[] tmp = new double[2]; - tmp[0]=coords[i].x + minX; - tmp[1]=coords[i].y + minY; - // if (tmp[0] > 180) tmp[0] -= 360; - - try { - xform.transform(tmp, 0, tmpout, 0, 1); - } catch (TransformException e) { - // TODO Auto-generated catch block - // e.printStackTrace(); - return null; - } - if ( worldWrapChecker ) { - if ( tmp[0] > (nx-1) && tmpout[0] < 0){ - tmpout[0] = extent.getMaxX(); - } - else if (tmp[0] < 1 && tmpout[0] > extent.getMaxX()*0.9 ){ - tmpout[0] = 0; - } + for (int i = 0, jj = 0; i < coords.length; i++, jj++) { + if (isWorld180 && coords[i].x == maxGridX) { + jj--; + continue; } - - out[jj] = new Coordinate( tmpout[0], tmpout[1] ); + double[] tmp = new double[2]; + tmp[0] = coords[i].x + minX; + tmp[1] = coords[i].y + minY; + // if (tmp[0] > 180) tmp[0] -= 360; + + try { + xform.transform(tmp, 0, tmpout, 0, 1); + } catch (TransformException e) { + // TODO Auto-generated catch block + // e.printStackTrace(); + return null; + } + if (worldWrap) { + if (tmp[0] > (nx - 1) && tmpout[0] < 0) { + tmpout[0] = extent.getMaxX(); + } else if (tmp[0] < 1 && tmpout[0] > extent.getMaxX() * 0.9) { + tmpout[0] = 0; + } + } + + out[jj] = new Coordinate(tmpout[0], tmpout[1]); } - if ( out.length >= 2 ) { - return gf.createLineString(out); - } - else { - return null; + if (out.length >= 2) { + return gf.createLineString(out); + } else { + return null; } } private static Geometry polyToLine(Polygon poly) { - GeometryFactory gf = new GeometryFactory(); + GeometryFactory gf = new GeometryFactory(); - if ( poly.getNumInteriorRing() == 0 ) return poly; + if (poly.getNumInteriorRing() == 0) + return poly; - poly.normalize(); - LineString outerPoly = poly.getExteriorRing(); + poly.normalize(); + LineString outerPoly = poly.getExteriorRing(); - /* - * sort interior rings - */ - TreeMap orderedHoles = new TreeMap(); - for ( int i=0; i < poly.getNumInteriorRing(); i++ ) { - LineString hole = poly.getInteriorRingN(i); - //if ( hole.getArea() == 8.0 ) System.out.println("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFound"); - Coordinate min = CoordinateArrays.minCoordinate( hole.getCoordinates() ); - orderedHoles.put( min, hole); - } + /* + * sort interior rings + */ + TreeMap orderedHoles = new TreeMap(); + for (int i = 0; i < poly.getNumInteriorRing(); i++) { + LineString hole = poly.getInteriorRingN(i); + // if ( hole.getArea() == 8.0 ) + // System.out.println("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFound"); + Coordinate min = CoordinateArrays.minCoordinate(hole + .getCoordinates()); + orderedHoles.put(min, hole); + } - for ( Coordinate leftmost : orderedHoles.keySet() ) { - CoordinateList clist = new CoordinateList(); - LineString hole = orderedHoles.get(leftmost); - //Coordinate[] connector = DistanceOp.closestPoints( outerPoly, hole); + for (Coordinate leftmost : orderedHoles.keySet()) { + CoordinateList clist = new CoordinateList(); + LineString hole = orderedHoles.get(leftmost); + // Coordinate[] connector = DistanceOp.closestPoints( outerPoly, + // hole); - Coordinate testCoord = new Coordinate( 0, leftmost.y); - // LineString testSegment = gf.createLineString( new Coordinate[] { leftmost, testCoord } ); - LineSegment testSegment = new LineSegment( leftmost, testCoord); + Coordinate testCoord = new Coordinate(0, leftmost.y); + // LineString testSegment = gf.createLineString( new Coordinate[] { + // leftmost, testCoord } ); + LineSegment testSegment = new LineSegment(leftmost, testCoord); - Coordinate max = findSegments(outerPoly, leftmost.y, testSegment); - // System.out.println("MAX INTX = "+max); - Coordinate[] connector = new Coordinate[] { max, leftmost }; + Coordinate max = findSegments(outerPoly, leftmost.y, testSegment); + // System.out.println("MAX INTX = "+max); + Coordinate[] connector = new Coordinate[] { max, leftmost }; - LocationIndexedLine outerLil = new LocationIndexedLine(outerPoly); - LinearLocation outerLoc= outerLil.indexOf( connector[0] ); - LocationIndexedLine innerLil = new LocationIndexedLine(hole); - LinearLocation innerLoc= innerLil.indexOf( connector[1] ); + LocationIndexedLine outerLil = new LocationIndexedLine(outerPoly); + LinearLocation outerLoc = outerLil.indexOf(connector[0]); + LocationIndexedLine innerLil = new LocationIndexedLine(hole); + LinearLocation innerLoc = innerLil.indexOf(connector[1]); - clist.add( outerLil.extractLine( outerLil.getStartIndex(), outerLoc).getCoordinates(), true ); + clist.add(outerLil.extractLine(outerLil.getStartIndex(), outerLoc) + .getCoordinates(), true); - clist.add( innerLil.extractLine(innerLoc, innerLil.getEndIndex()).getCoordinates(), true); - clist.add( innerLil.extractLine( innerLil.getStartIndex(), innerLoc).getCoordinates(), true); + clist.add(innerLil.extractLine(innerLoc, innerLil.getEndIndex()) + .getCoordinates(), true); + clist.add(innerLil.extractLine(innerLil.getStartIndex(), innerLoc) + .getCoordinates(), true); - clist.add( outerLil.extractLine( outerLoc, outerLil.getEndIndex() ).getCoordinates(), true ); + clist.add(outerLil.extractLine(outerLoc, outerLil.getEndIndex()) + .getCoordinates(), true); - outerPoly = gf.createLineString(clist.toCoordinateArray()); + outerPoly = gf.createLineString(clist.toCoordinateArray()); - } + } - return outerPoly; - //return ls.getSequencedLineStrings(); + return outerPoly; + // return ls.getSequencedLineStrings(); } - private static Coordinate findSegments(LineString outerPoly, double y, LineSegment seg) { + private static Coordinate findSegments(LineString outerPoly, double y, + LineSegment seg) { - //GeometryFactory gf = new GeometryFactory(); - //List geoms = new ArrayList(); - Coordinate max = new Coordinate(0,0); - //Geometry testGeom; + // GeometryFactory gf = new GeometryFactory(); + // List geoms = new ArrayList(); + Coordinate max = new Coordinate(0, 0); + // Geometry testGeom; Coordinate[] coords = outerPoly.getCoordinates(); - for ( int i=0; i= coords[i+1].y)) || ((y >= coords[i].y) && (y <= coords[i+1].y)) ) { - //Geometry temp = gf.createLineString(new Coordinate[] {coords[1], coords[i+1]} ); - LineSegment temp = new LineSegment( coords[i], coords[i+1]); - intx = seg.intersection(temp); - } - //else if ( y == coords[i].y ) { - // intx = coords[i]; - //} + for (int i = 0; i < coords.length - 1; i++) { + Coordinate intx = null; + if (((y <= coords[i].y) && (y >= coords[i + 1].y)) + || ((y >= coords[i].y) && (y <= coords[i + 1].y))) { + // Geometry temp = gf.createLineString(new Coordinate[] + // {coords[1], coords[i+1]} ); + LineSegment temp = new LineSegment(coords[i], coords[i + 1]); + intx = seg.intersection(temp); + } + // else if ( y == coords[i].y ) { + // intx = coords[i]; + // } - if ( intx != null ) { - if ( max.compareTo( intx ) == -1 ) max = intx; - } + if (intx != null) { + if (max.compareTo(intx) == -1) + max = intx; + } - // testGeom = seg.intersection(temp); - // for ( int j=0; j < testGeom.getNumGeometries(); j++ ) { - // Geometry g = testGeom.getGeometryN(j); - // if ( max.compareTo( g.getCoordinate() ) == -1 ) max = g.getCoordinate(); - // } - //} + // testGeom = seg.intersection(temp); + // for ( int j=0; j < testGeom.getNumGeometries(); j++ ) { + // Geometry g = testGeom.getGeometryN(j); + // if ( max.compareTo( g.getCoordinate() ) == -1 ) max = + // g.getCoordinate(); + // } + // } } return max; } - - public static double getCentralMeridian (IMapDescriptor descriptor) { - MapProjection worldProjection = CRS.getMapProjection(descriptor + + public static double getCentralMeridian(IMapDescriptor descriptor) { + MapProjection worldProjection = CRS.getMapProjection(descriptor .getCRS()); if (worldProjection != null) { ParameterValueGroup group = worldProjection.getParameterValues(); double centralMeridian = group.parameter( AbstractProvider.CENTRAL_MERIDIAN.getName().getCode()) .doubleValue(); - if ( centralMeridian > 180 ) centralMeridian -= 360; + if (centralMeridian > 180) + centralMeridian -= 360; return centralMeridian; - } - return -999; + } + return -999; } - - private static List contourReduce ( List contour1, List contour2){ - List tmp = new ArrayList(); - if ( contour2 != null ) { - for ( Double d2 : contour2 ) { - boolean found = false; - for ( Double d1 : contour1 ) { - if ( Double.compare(d1, d2) == 0 ) { - found = true; - break; - } - } - if ( ! found ) { - tmp.add(d2); - } - } - } - return tmp; + + private static List contourReduce(List contour1, + List contour2) { + List tmp = new ArrayList(); + if (contour2 != null) { + for (Double d2 : contour2) { + boolean found = false; + for (Double d1 : contour1) { + if (Double.compare(d1, d2) == 0) { + found = true; + break; + } + } + if (!found) { + tmp.add(d2); + } + } + } + return tmp; } - - private void initContourGroup (IGraphicsTarget target, - ContourGroup contourGp) { - contourGroup = new ContourGroup(); + + private void initContourGroup(IGraphicsTarget target, ContourGroup contourGp) { + contourGroup = new ContourGroup(); contourGroup.lastDensity = currentDensity; contourGroup.posValueShape = target.createWireframeShape(false, descriptor); contourGroup.negValueShape = target.createWireframeShape(false, descriptor); - contourGroup.fillShapes = target.createShadedShape(false, descriptor, true); + contourGroup.fillShapes = target.createShadedShape(false, descriptor, + true); contourGroup.zoomLevel = 1.0 / Math.pow(2.0, level); - + contourGroup.cvalues = new ArrayList(); - + contourGroup.fvalues = new ArrayList(); - - contourGroup.data = new HashMap< String, Geometry>(); - + + contourGroup.data = new HashMap(); + contourGroup.grid = null; - - if ( contourGp != null ) { - if ( contourGp.cvalues != null && contourGp.cvalues.size() > 0 ) { - contourGroup.cvalues.addAll(contourGp.cvalues); - } - if ( contourGp.fvalues != null && contourGp.fvalues.size() > 0 ) { - contourGroup.fvalues.addAll(contourGp.fvalues); - } - if ( contourGp.data != null && contourGp.data.size() > 0 ) { - contourGroup.data.putAll(contourGp.data); - } - if ( contourGp.grid != null ) - contourGroup.grid = contourGp.grid; + + if (contourGp != null) { + if (contourGp.cvalues != null && contourGp.cvalues.size() > 0) { + contourGroup.cvalues.addAll(contourGp.cvalues); + } + if (contourGp.fvalues != null && contourGp.fvalues.size() > 0) { + contourGroup.fvalues.addAll(contourGp.fvalues); + } + if (contourGp.data != null && contourGp.data.size() > 0) { + contourGroup.data.putAll(contourGp.data); + } + if (contourGp.grid != null) + contourGroup.grid = contourGp.grid; } - + contourGroup.lastUsedPixelExtent = (PixelExtent) extent.clone(); contourGroup.lastUsedPixelExtent.getEnvelope().expandBy( contourGroup.lastUsedPixelExtent.getWidth() * .25, contourGroup.lastUsedPixelExtent.getHeight() * .25); } - - private boolean initMathTransform ( GeneralGridGeometry imageGridGeometry, + + private boolean initMathTransform(GeneralGridGeometry imageGridGeometry, GeneralGridGeometry mapGridGeometry) { try { - DefaultMathTransformFactory factory = new DefaultMathTransformFactory(); + DefaultMathTransformFactory factory = new DefaultMathTransformFactory(); CoordinateReferenceSystem rastCrs = imageGridGeometry .getCoordinateReferenceSystem(); CoordinateReferenceSystem mapCrs = mapGridGeometry .getCoordinateReferenceSystem(); - + MathTransform rastGridToCrs = imageGridGeometry .getGridToCRS(PixelInCell.CELL_CENTER); MathTransform mapCrsToGrid = mapGridGeometry.getGridToCRS( @@ -901,375 +949,417 @@ public class ContourSupport { .getTransformToLatLon(rastCrs); MathTransform rastCrsToWorldGrid = MapUtil - .getTransformFromLatLon(mapCrs); + .getTransformFromLatLon(mapCrs); MathTransform crs2crs = CRSCache.getInstance().findMathTransform( rastCrs, mapCrs); - rastPosToWorldGrid = factory - .createConcatenatedTransform( - factory.createConcatenatedTransform(rastGridToCrs, - crs2crs), mapCrsToGrid); - + rastPosToWorldGrid = factory + .createConcatenatedTransform( + factory.createConcatenatedTransform(rastGridToCrs, + crs2crs), mapCrsToGrid); + rastPosToLatLon = factory.createConcatenatedTransform( rastGridToCrs, rastCrsToLatLon); rastPosLatLonToWorldGrid = factory.createConcatenatedTransform( - rastCrsToWorldGrid,mapCrsToGrid); + rastCrsToWorldGrid, mapCrsToGrid); } catch (Exception e) { -// throw new VizException("Error building Transforms", e); + // throw new VizException("Error building Transforms", e); logger.error("Error building Transforms:" + e); return false; } return true; } - - private void initZoomIndex () { - zoomLevelIndex = level+1;//(int)(zoom / 2) + 1; // To be adjusted - if (zoomLevelIndex < 1) zoomLevelIndex = 1; - int maxZoomLevel = 5; - String cint = attr.getCint(); - if (cint != null) maxZoomLevel = cint.trim().split(">").length; - if (zoomLevelIndex > maxZoomLevel ) zoomLevelIndex = maxZoomLevel; + + private void initZoomIndex() { + zoomLevelIndex = level + 1;// (int)(zoom / 2) + 1; // To be adjusted + if (zoomLevelIndex < 1) + zoomLevelIndex = 1; + int maxZoomLevel = 5; + String cint = attr.getCint(); + if (cint != null) + maxZoomLevel = cint.trim().split(">").length; + if (zoomLevelIndex > maxZoomLevel) + zoomLevelIndex = maxZoomLevel; } - - private List calcCintValue () { - List cvalues = null; - if (type.trim().toUpperCase().contains("C")) { - cvalues =CINT.parseCINT(cint, zoomLevelIndex, cntrData.getMinValue(), cntrData.getMaxValue()); - } -// if ( cvalues != null ) { -// System.out.println ("******after CINT.parseCINT("+cint+").cvalues:"+ cvalues.toString()); -// System.out.println ("******cgen.getMinValue():" + cgen.getMinValue() + " cgen.getMaxValue():"+cgen.getMaxValue()); -// } - if ( contourGroup.cvalues.size() == 0 && cvalues != null ) { - contourGroup.cvalues.addAll(cvalues); - } - else if (contourGroup.cvalues.size() > 0 ) { - if ( cvalues != null ) { - List tmp = new ArrayList(cvalues); - cvalues = contourReduce (contourGroup.cvalues, cvalues); - contourGroup.cvalues.clear(); - contourGroup.cvalues.addAll(tmp); - } - else { - contourGroup.cvalues.clear(); - } - } - return cvalues; + + private List calcCintValue() { + List cvalues = null; + if (type.trim().toUpperCase().contains("C")) { + cvalues = CINT.parseCINT(cint, zoomLevelIndex, + cntrData.getMinValue(), cntrData.getMaxValue()); + } + // if ( cvalues != null ) { + // System.out.println ("******after CINT.parseCINT("+cint+").cvalues:"+ + // cvalues.toString()); + // System.out.println ("******cgen.getMinValue():" + cgen.getMinValue() + // + " cgen.getMaxValue():"+cgen.getMaxValue()); + // } + if (contourGroup.cvalues.size() == 0 && cvalues != null) { + contourGroup.cvalues.addAll(cvalues); + } else if (contourGroup.cvalues.size() > 0) { + if (cvalues != null) { + List tmp = new ArrayList(cvalues); + cvalues = contourReduce(contourGroup.cvalues, cvalues); + contourGroup.cvalues.clear(); + contourGroup.cvalues.addAll(tmp); + } else { + contourGroup.cvalues.clear(); + } + } + return cvalues; } - - private List calcFintValue () { - List fvalues = null; - if (type.trim().toUpperCase().contains("F")) { - if ( !(fint.equalsIgnoreCase(cint)) ) { - fvalues = FINT.parseFINT(fint, zoomLevelIndex, cntrData.minValue, cntrData.getMaxValue()); - } - else if ( contourGroup.cvalues != null ){ - fvalues = contourGroup.cvalues; - } - } - if ( contourGroup.fvalues.size() == 0 && fvalues != null){ - contourGroup.fvalues.addAll(fvalues); - } - else if ( contourGroup.fvalues.size() > 0 ) { - if ( fvalues != null ){ - List tmp = new ArrayList(fvalues); - fvalues = contourReduce (contourGroup.fvalues, fvalues); - contourGroup.fvalues.clear(); - contourGroup.fvalues.addAll(tmp); - } - else { - contourGroup.fvalues.clear(); - } - } - return fvalues; + + private List calcFintValue() { + List fvalues = null; + if (type.trim().toUpperCase().contains("F")) { + if (!(fint.equalsIgnoreCase(cint))) { + fvalues = FINT.parseFINT(fint, zoomLevelIndex, + cntrData.minValue, cntrData.getMaxValue()); + } else if (contourGroup.cvalues != null) { + fvalues = contourGroup.cvalues; + } + } + if (contourGroup.fvalues.size() == 0 && fvalues != null) { + contourGroup.fvalues.addAll(fvalues); + } else if (contourGroup.fvalues.size() > 0) { + if (fvalues != null) { + List tmp = new ArrayList(fvalues); + fvalues = contourReduce(contourGroup.fvalues, fvalues); + contourGroup.fvalues.clear(); + contourGroup.fvalues.addAll(tmp); + } else { + contourGroup.fvalues.clear(); + } + } + return fvalues; } - - private void combineCintAndFillValues () { - if (cvalues != null && cvalues.size() > 0) svalues = new HashSet(cvalues); + + private void combineCintAndFillValues() { + if (cvalues != null && cvalues.size() > 0) + svalues = new HashSet(cvalues); if (fvalues != null && fvalues.size() > 0) { - if (svalues == null) - svalues = new HashSet(fvalues); - else - svalues.addAll(fvalues); - } + if (svalues == null) + svalues = new HashSet(fvalues); + else + svalues.addAll(fvalues); + } } - - private void createContourLines () { - - long total_labeling_time = 0; - long t2 = System.currentTimeMillis(); - if (type.trim().toUpperCase().contains("C") && contourGroup.cvalues.size() > 0) { - int labelFreq = 1; - String[] tempLineStrs = attr.getLine().split("/"); - List labelValues = null; - if (tempLineStrs.length >= 4) { - if (tempLineStrs[3].trim().contains(";")) { - LineDataStringParser lineAttr = new LineDataStringParser(attr.getLine()); - labelValues = lineAttr.getInstanceOfLineBuilder().getLineLabelPresentList(); - } - else { - labelFreq = Math.abs(Integer.parseInt(tempLineStrs[3].trim())); - } - } - - - int n = 0,minX=0,minY=0; - - double[][] screen = null; - double[][] screenx = null; - - for ( Double cval : contourGroup.cvalues ) { - float fval = (float) (cval * 1.0f); - boolean toLabel = false; - - // Label frequency - if (labelValues != null) { - for(Integer value : labelValues) { - if (value == Math.rint(fval)) { - toLabel = true; - break; - } - } - } - else { - if (labelFreq == 0) - toLabel = false; - else - toLabel = (n % labelFreq == 0) ? true : false; - } - - - Geometry g = contourGroup.data.get(cval.toString()); - if ( g == null ) continue; - - for ( int i=0; i < g.getNumGeometries(); i++ ) { - Geometry gn = g.getGeometryN(i); - if ( worldWrap ) { - // screen = toScreenRightPart( gn.getCoordinates(), 0, rastPosToLatLon,rastPosLatLonToWorldGrid, minX, minY ); - // if ( screen != null ) contourGroup.negValueShape.addLineSegment(screen); - - screen = toScreenRightOfZero( gn.getCoordinates(), rastPosToWorldGrid, minX, minY ); - if ( screen != null ) contourGroup.negValueShape.addLineSegment(screen); - screenx = toScreenLeftOfZero( gn.getCoordinates(), rastPosToWorldGrid, minX, minY ); - if ( screenx != null ) contourGroup.negValueShape.addLineSegment(screenx); - } - else { - screen = toScreen( gn.getCoordinates(), rastPosToWorldGrid, minX, minY ); - if ( screen != null ) contourGroup.negValueShape.addLineSegment(screen); - } - - /* if ( isWorld0 ) { - screen1 = toScreenSubtract360( gn.getCoordinates(), rastPosToLatLon,rastPosLatLonToWorldGrid, minX, minY ); - if ( screen1 != null ) - contourGroup.negValueShape.addLineSegment(screen1); - } - - */ - if (toLabel) { - long tl0 = System.currentTimeMillis(); -// prepareLabel(contourGroup, zoom, fval, -// labelPoints, screen); - if ( screen != null ) - createContourLabel(extent, contourGroup, fval, screen); - if ( screenx != null) { - createContourLabel(extent, contourGroup, fval, screenx); - } - long tl1 = System.currentTimeMillis(); - total_labeling_time += (tl1-tl0); - } - } - - n++; - } - } - long t3 = System.currentTimeMillis(); - logger.debug("===Creating label wireframes for ("+name+") took: " + total_labeling_time); - if ( ncgribLogger.enableCntrLogs() ) - logger.info("===Creating contour line wireframes for ("+name+")took: " + (t3 - t2 )); -// System.out.println("Creating contour line wireframes took: " + (t3 - t2 - total_labeling_time)); + private void createContourLines() { + + long total_labeling_time = 0; + long t2 = System.currentTimeMillis(); + if (type.trim().toUpperCase().contains("C") + && contourGroup.cvalues.size() > 0) { + int labelFreq = 1; + String[] tempLineStrs = attr.getLine().split("/"); + List labelValues = null; + if (tempLineStrs.length >= 4) { + if (tempLineStrs[3].trim().contains(";")) { + LineDataStringParser lineAttr = new LineDataStringParser( + attr.getLine()); + labelValues = lineAttr.getInstanceOfLineBuilder() + .getLineLabelPresentList(); + } else { + labelFreq = Math.abs(Integer.parseInt(tempLineStrs[3] + .trim())); + } + } + + int n = 0, minX = 0, minY = 0; + + double[][] screen = null; + double[][] screenx = null; + + for (Double cval : contourGroup.cvalues) { + float fval = (float) (cval * 1.0f); + boolean toLabel = false; + + // Label frequency + if (labelValues != null) { + for (Integer value : labelValues) { + if (value == Math.rint(fval)) { + toLabel = true; + break; + } + } + } else { + if (labelFreq == 0) + toLabel = false; + else + toLabel = (n % labelFreq == 0) ? true : false; + } + + Geometry g = contourGroup.data.get(cval.toString()); + if (g == null) + continue; + + for (int i = 0; i < g.getNumGeometries(); i++) { + Geometry gn = g.getGeometryN(i); + if (worldWrap) { + // screen = toScreenRightPart( gn.getCoordinates(), 0, + // rastPosToLatLon,rastPosLatLonToWorldGrid, minX, minY + // ); + // if ( screen != null ) + // contourGroup.negValueShape.addLineSegment(screen); + + screen = toScreenRightOfZero(gn.getCoordinates(), + rastPosToWorldGrid, minX, minY); + if (screen != null) + contourGroup.negValueShape.addLineSegment(screen); + + screenx = toScreenLeftOfZero(gn.getCoordinates(), + rastPosToWorldGrid, minX, minY); + if (screenx != null) + contourGroup.negValueShape.addLineSegment(screenx); + } else { + screen = toScreen(gn.getCoordinates(), + rastPosToWorldGrid, minX, minY); + if (screen != null) + contourGroup.negValueShape.addLineSegment(screen); + } + + /* + * if ( isWorld0 ) { screen1 = toScreenSubtract360( + * gn.getCoordinates(), + * rastPosToLatLon,rastPosLatLonToWorldGrid, minX, minY ); + * if ( screen1 != null ) + * contourGroup.negValueShape.addLineSegment(screen1); } + */ + if (toLabel) { + long tl0 = System.currentTimeMillis(); + // prepareLabel(contourGroup, zoom, fval, + // labelPoints, screen); + if (screen != null) + createContourLabel(extent, contourGroup, fval, + screen); + if (screenx != null) { + createContourLabel(extent, contourGroup, fval, + screenx); + } + long tl1 = System.currentTimeMillis(); + total_labeling_time += (tl1 - tl0); + } + } + + n++; + } + } + long t3 = System.currentTimeMillis(); + logger.debug("===Creating label wireframes for (" + name + ") took: " + + total_labeling_time); + if (ncgribLogger.enableCntrLogs()) + logger.info("===Creating contour line wireframes for (" + name + + ")took: " + (t3 - t2)); + // System.out.println("Creating contour line wireframes took: " + (t3 - + // t2 - total_labeling_time)); } - - private void createColorFills () { - - long t3 = System.currentTimeMillis(); - - //Prepare the colorbar - if (type.trim().toUpperCase().contains("F") && (attr.getClrbar() != null || !"0".equals(attr.getClrbar()))){ - ColorBar tempColorBar = generateColorBarInfo(); - if( tempColorBar != null ){ - contourGroup.colorBarForGriddedFill = new ColorBar(tempColorBar); - } - } else { - contourGroup.colorBarForGriddedFill = null; - } - - if (type.trim().toUpperCase().contains("F") && contourGroup.fvalues.size() > 0) { - - try { - - // Prepare colors for color fills - List fillColorsIndex = new ArrayList(); - if (fline == null || fline.trim().length() < 1) { - for(int i = 0; i < contourGroup.fvalues.size()+2; i++) { - if (i <= 30) - fillColorsIndex.add(i + 1); - else - fillColorsIndex.add(30); - } - } else { - FLine flineInfo = new FLine(fline.trim()); - fillColorsIndex = flineInfo.getFillColorList(); - - /* - * Apply last color if not enough input color. - */ - if (contourGroup.fvalues != null && fillColorsIndex.size() < (contourGroup.fvalues.size()+1)) { - for (int i = fillColorsIndex.size(); i < contourGroup.fvalues.size()+2; i++) { - fillColorsIndex.add(i); - } - } - } - int minX=0,minY=0; - long t11 = System.currentTimeMillis(); - FillGenerator fgen = new FillGenerator(contourGroup.grid); - long t12 = System.currentTimeMillis(); - logger.debug(" create FillGenerator took:" + (t12-t11)); - for ( Double cval : contourGroup.fvalues ) { - float fval = (float) (cval * 1.0f); - Geometry g = contourGroup.data.get(cval.toString()); - if ( g == null ) continue; - fgen.addContours(fval, g); - } - t11 = System.currentTimeMillis(); - logger.debug(" add Contour took:" + (t11-t12)); - // Add color fill to contourGroup - for (int n=0; n <= contourGroup.fvalues.size(); n++ ) { - if (fillColorsIndex.get(n) <= 0 || fillColorsIndex.get(n) >= 32) continue; - - RGB color = GempakColor.convertToRGB(fillColorsIndex.get(n)); - Geometry fillPolys = null; - - int index = (n < contourGroup.fvalues.size()) ? n : (n-1); - float fval = (float)(contourGroup.fvalues.get(index) * 1.0f); - - try { - if (n == 0) { - fillPolys = fgen.fillLessThan(fval); - } else if (n == contourGroup.fvalues.size()) { - fillPolys = fgen.fillGreaterThan(fval); - } else { - float fval1 = (float)(contourGroup.fvalues.get(n-1) * 1.0f); - float fval2 = (float)(contourGroup.fvalues.get(n) * 1.0f); - fillPolys = fgen.fillBetween( fval1, fval2 ); - } - for (int j=0; j 0) { + + try { + + // Prepare colors for color fills + List fillColorsIndex = new ArrayList(); + if (fline == null || fline.trim().length() < 1) { + for (int i = 0; i < contourGroup.fvalues.size() + 2; i++) { + if (i <= 30) + fillColorsIndex.add(i + 1); + else + fillColorsIndex.add(30); + } + } else { + FLine flineInfo = new FLine(fline.trim()); + fillColorsIndex = flineInfo.getFillColorList(); + + /* + * Apply last color if not enough input color. + */ + if (contourGroup.fvalues != null + && fillColorsIndex.size() < (contourGroup.fvalues + .size() + 1)) { + for (int i = fillColorsIndex.size(); i < contourGroup.fvalues + .size() + 2; i++) { + fillColorsIndex.add(i); + } + } + } + + int minX = 0, minY = 0; + long t11 = System.currentTimeMillis(); + FillGenerator fgen = new FillGenerator(contourGroup.grid); + long t12 = System.currentTimeMillis(); + logger.debug(" create FillGenerator took:" + (t12 - t11)); + for (Double cval : contourGroup.fvalues) { + float fval = (float) (cval * 1.0f); + Geometry g = contourGroup.data.get(cval.toString()); + if (g == null) + continue; + fgen.addContours(fval, g); + } + t11 = System.currentTimeMillis(); + logger.debug(" add Contour took:" + (t11 - t12)); + // Add color fill to contourGroup + for (int n = 0; n <= contourGroup.fvalues.size(); n++) { + if (fillColorsIndex.get(n) <= 0 + || fillColorsIndex.get(n) >= 32) + continue; + + RGB color = GempakColor + .convertToRGB(fillColorsIndex.get(n)); + Geometry fillPolys = null; + + int index = (n < contourGroup.fvalues.size()) ? n : (n - 1); + float fval = (float) (contourGroup.fvalues.get(index) * 1.0f); + + try { + if (n == 0) { + fillPolys = fgen.fillLessThan(fval); + } else if (n == contourGroup.fvalues.size()) { + fillPolys = fgen.fillGreaterThan(fval); + } else { + float fval1 = (float) (contourGroup.fvalues + .get(n - 1) * 1.0f); + float fval2 = (float) (contourGroup.fvalues.get(n) * 1.0f); + fillPolys = fgen.fillBetween(fval1, fval2); + } + for (int j = 0; j < fillPolys.getNumGeometries(); j++) { + Geometry g = fillPolys.getGeometryN(j); + if (g instanceof Polygon) + g = polyToLine((Polygon) g); + + if (worldWrap) { + LineString ls = toScreenLSRightOfZero( + g.getCoordinates(), rastPosToWorldGrid, + minX, minY); + if (ls != null) + contourGroup.fillShapes + .addPolygonPixelSpace( + new LineString[] { ls }, + color); + ls = toScreenLSLeftOfZero(g.getCoordinates(), + rastPosToWorldGrid, minX, minY); + if (ls != null) + contourGroup.fillShapes + .addPolygonPixelSpace( + new LineString[] { ls }, + color); + } else { + LineString ls = toScreenLS(g.getCoordinates(), + rastPosToWorldGrid, minX, minY); + if (ls != null) + contourGroup.fillShapes + .addPolygonPixelSpace( + new LineString[] { ls }, + color); + } + + // if ( isWorld0 ) { + // ls = toScreenLSSubtract360( g.getCoordinates(), + // rastPosToLatLon,rastPosLatLonToWorldGrid, minX, + // minY); + // if ( ls != null ) + // contourGroup.fillShapes.addPolygonPixelSpace(new + // LineString[]{ls}, color); + // } + } + } catch (FillException e) { + // e.printStackTrace(); + } + } + t12 = System.currentTimeMillis(); + logger.debug(" loop fvalues took:" + (t12 - t11)); + // System.out.println("Creating color fills took : " + (t4-t3)); + + } catch (Exception e) { + logger.debug("Could not create FILL Polygons."); + // e.printStackTrace(); + return; + } + } + long t4 = System.currentTimeMillis(); + if (ncgribLogger.enableCntrLogs()) + logger.info("===Creating color fills for (" + name + ") took : " + + (t4 - t3)); } - - private void createStreamLines () { - // Step 1: Get the actual data + + private void createStreamLines() { + // Step 1: Get the actual data float[] uW = null; float[] vW = null; long[] sz = records.getSizes(); - -// Step 2: Determine the subgrid, if any - int minX=0,minY=0; - int maxX = (int)sz[0] - 1; - int maxY = (int)sz[1] - 1; + + // Step 2: Determine the subgrid, if any + int minX = 0, minY = 0; + int maxX = (int) sz[0] - 1; + int maxY = (int) sz[1] - 1; int szX = (maxX - minX) + 1; int szY = (maxY - minY) + 1; int x = (int) sz[0]; - + uW = ((NcFloatDataRecord) records).getXdata(); vW = ((NcFloatDataRecord) records).getYdata(); - - if ( globalData ){ // remove column 360 - x--; - szX--; - maxX--; + + if (globalData) { // remove column 360 + x--; + szX--; + maxX--; } - + int totalSz = szX * szY; if (totalSz <= 0) { - isCntrsCreated = false; - return ; + isCntrsCreated = false; + return; } - + float[] adjustedUw = new float[totalSz]; float[] adjustedVw = new float[totalSz]; int n = 0; - if ( globalData ){ - for (int j = 0; j < szY; j++) { - for (int i = 0; i < szX+1; i++) { - if (( i+minX )== 360 ) { - continue; - } - adjustedUw[n] = uW[((x+1) * (j + minY)) + (i + minX)]; - adjustedVw[n] = vW[((x+1) * (j + minY)) + (i + minX)]; + if (globalData) { + for (int j = 0; j < szY; j++) { + for (int i = 0; i < szX + 1; i++) { + if ((i + minX) == 360) { + continue; + } + adjustedUw[n] = uW[((x + 1) * (j + minY)) + (i + minX)]; + adjustedVw[n] = vW[((x + 1) * (j + minY)) + (i + minX)]; - n++; - } - } - } - else { - for (int j = 0; j < szY; j++) { - for (int i = 0; i < szX; i++) { - adjustedUw[n] = uW[(x * (j + minY)) + (i + minX)]; - adjustedVw[n] = vW[(x * (j + minY)) + (i + minX)]; + n++; + } + } + } else { + for (int j = 0; j < szY; j++) { + for (int i = 0; i < szX; i++) { + adjustedUw[n] = uW[(x * (j + minY)) + (i + minX)]; + adjustedVw[n] = vW[(x * (j + minY)) + (i + minX)]; - n++; - } - } + n++; + } + } } - // for ( int kk = 0; kk < 365; kk++ ){ - // System.out.println( kk + " " + adjustedUw[kk]+ " " + uW[kk]); - // } + // for ( int kk = 0; kk < 365; kk++ ){ + // System.out.println( kk + " " + adjustedUw[kk]+ " " + uW[kk]); + // } ArraysUtil.flipVert(adjustedUw, szY, szX); ArraysUtil.flipVert(adjustedVw, szY, szX); @@ -1277,18 +1367,17 @@ public class ContourSupport { int arrSz = Math.max(10 * adjustedUw.length, uW.length); uW = null; vW = null; - - + int[] work = new int[arrSz]; float[] xPoints = new float[arrSz]; float[] yPoints = new float[arrSz]; int[] numPoints = new int[1]; // Use ported legacy code to determine contour interval -// contourGroup.lastDensity = currentDensity; - + // contourGroup.lastDensity = currentDensity; + double spadiv = 1 * contourGroup.lastDensity * 500 / 25; - + double minSpacing = 1.0 / spadiv; double maxSpacing = 3.0 / spadiv; @@ -1307,293 +1396,336 @@ public class ContourSupport { if (maxspc < 0.25) { maxspc = 0.25f; } - + /* * Fix arrow size by M. Li */ float arrowSize = (float) (0.4f / Math.sqrt(zoom)); - if (arrowSize > 0.4) arrowSize = 0.4f; - + if (arrowSize > 0.4) + arrowSize = 0.4f; + Controller.strmpak(adjustedUw, adjustedVw, work, szX, szX, szY, arrowSize, xPoints, yPoints, numPoints, minspc, maxspc, -1000000f, -999998f); - -// long t1 = System.currentTimeMillis(); -// System.out.println("Streamline Contouring took: " + (t1 - t0)); + + // long t1 = System.currentTimeMillis(); + // System.out.println("Streamline Contouring took: " + (t1 - t0)); List vals = new ArrayList(); List pts = new ArrayList(); - double[][] screen, screenx;; + double[][] screen, screenx; long tAccum = 0; try { for (int i = 0; i < numPoints[0] && i < xPoints.length; i++) { if (xPoints[i] == -99999.0) { - if (pts.size() > 0 ) { - - if ( worldWrap ) { - screen = toScreenRightOfZero( pts.toArray(new Coordinate[pts.size()]), rastPosToWorldGrid, minX, minY ); - if ( screen != null ) contourGroup.posValueShape.addLineSegment(screen); + if (pts.size() > 0) { - screenx = toScreenLeftOfZero( pts.toArray(new Coordinate[pts.size()]),rastPosToWorldGrid, minX, minY ); - if ( screenx != null ) contourGroup.posValueShape.addLineSegment(screenx); - } - else { - double[][] valsArr = vals.toArray(new double[vals.size()][2]); - contourGroup.posValueShape.addLineSegment(valsArr); - } + if (worldWrap) { + screen = toScreenRightOfZero( + pts.toArray(new Coordinate[pts.size()]), + rastPosToWorldGrid, minX, minY); + if (screen != null) + contourGroup.posValueShape + .addLineSegment(screen); + + screenx = toScreenLeftOfZero( + pts.toArray(new Coordinate[pts.size()]), + rastPosToWorldGrid, minX, minY); + if (screenx != null) + contourGroup.posValueShape + .addLineSegment(screenx); + } else { + double[][] valsArr = vals.toArray(new double[vals + .size()][2]); + contourGroup.posValueShape.addLineSegment(valsArr); + } + + vals.clear(); + pts.clear(); - vals.clear(); - pts.clear(); - } } else { double[] out = new double[2]; try { long tZ0 = System.currentTimeMillis(); - + float f; - - if ( xPoints[i] >= 360 ){ - f = 0; + + if (xPoints[i] >= 360) { + f = 0; } - + else { - f= maxX + 1 - xPoints[i]; + f = maxX + 1 - xPoints[i]; } - - if (f > 180) f = f - 360; - - rastPosToWorldGrid.transform(new double[] { - f, yPoints[i] + minY }, 0, - out, 0, 1); - - pts.add( new Coordinate(f, yPoints[i] + minY)); - + + if (f > 180) + f = f - 360; + + rastPosToWorldGrid.transform(new double[] { f, + yPoints[i] + minY }, 0, out, 0, 1); + + pts.add(new Coordinate(f, yPoints[i] + minY)); + long tZ1 = System.currentTimeMillis(); tAccum += (tZ1 - tZ0); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } - + vals.add(out); } } -// System.out.println("streamline transformation time: " + tAccum); + // System.out.println("streamline transformation time: " + tAccum); if (vals.size() > 0) { - double[][] valsArr = vals - .toArray(new double[vals.size()][2]); + double[][] valsArr = vals.toArray(new double[vals.size()][2]); contourGroup.posValueShape.addLineSegment(valsArr); - - if ( worldWrap ) { - screen = toScreenRightOfZero( pts.toArray(new Coordinate[pts.size()]), rastPosToWorldGrid, minX, minY ); - if ( screen != null ) contourGroup.posValueShape.addLineSegment(screen); - screenx = toScreenLeftOfZero( pts.toArray(new Coordinate[pts.size()]),rastPosToWorldGrid, minX, minY ); - if ( screenx != null ) contourGroup.posValueShape.addLineSegment(screenx); - } + if (worldWrap) { + screen = toScreenRightOfZero( + pts.toArray(new Coordinate[pts.size()]), + rastPosToWorldGrid, minX, minY); + if (screen != null) + contourGroup.posValueShape.addLineSegment(screen); + + screenx = toScreenLeftOfZero( + pts.toArray(new Coordinate[pts.size()]), + rastPosToWorldGrid, minX, minY); + if (screenx != null) + contourGroup.posValueShape.addLineSegment(screenx); + } vals.clear(); } } catch (Throwable e) { -// throw new VizException("Error postprocessing contours", e); + // throw new VizException("Error postprocessing contours", e); logger.error("Error postprocessing contours:" + e); isCntrsCreated = false; return; - } + } } - - - private ColorBar generateColorBarInfo(){ - - if( attr.getClrbar() != null && !attr.getClrbar().isEmpty()){ - contourGroup.clrbar = new CLRBAR(attr.getClrbar()); - ColorBarAttributesBuilder cBarAttrBuilder = contourGroup.clrbar.getcBarAttributesBuilder(); - ColorBar colorBar = new ColorBar(); - if ( cBarAttrBuilder.isDrawColorBar() ){ - colorBar.setAttributesFromColorBarAttributesBuilder(cBarAttrBuilder); - colorBar.setAttributesFromColorBarAttributesBuilder(cBarAttrBuilder); - colorBar.setColorDevice( NcDisplayMngr.getActiveNatlCntrsEditor().getActiveDisplayPane().getDisplay() ); - FINT theFillIntervals = new FINT(fint.trim()); - FLine fillColorString = new FLine(fline.trim()); - if( !theFillIntervals.isFINTStringParsed() || !fillColorString.isFLineStringParsed() ) - return null; - List fillIntvls = theFillIntervals.getUniqueSortedFillValuesFromAllZoomLevels(); - List fillColors = fillColorString.getFillColorList(); - - fillIntvls.add(0, Double.NEGATIVE_INFINITY); - int numFillIntervals = fillIntvls.size(); - fillIntvls.add(numFillIntervals, Double.POSITIVE_INFINITY); - int numDecimals = 0; - for (int index = 0 ; index <= numFillIntervals -1 ; index++){ - colorBar.addColorBarInterval(fillIntvls.get(index).floatValue(), fillIntvls.get(index + 1).floatValue(), GempakColor.convertToRGB(fillColors.get(index))); - String tmp[] = fillIntvls.get(index).toString().split("\\."); - if (tmp.length > 1 && tmp[1].length() > numDecimals && !"0".equals(tmp[1])) { - numDecimals = tmp[1].length(); - } - } - colorBar.setNumDecimals(numDecimals); - return colorBar; - } - } - return null; - } - - public void genContour () { - - ContourCalculationReentrantLock.getReentrantLock(); -// synchronized (ContourSupport.class) { - List allvalues = new ArrayList(svalues); - Collections.sort(allvalues); - long t1a = System.currentTimeMillis(); - ContourGenerator cgen = new ContourGenerator( cntrData.getData(), cntrData.getX(), cntrData.getY()); - long t1b = System.currentTimeMillis(); - logger.debug("Creating contour values took: " + (t1b-t1a)); - cgen.setContourValues( allvalues ); + private ColorBar generateColorBarInfo() { - long t1c = System.currentTimeMillis(); - logger.debug("ContourGenerator.setContourValues(allvalues) took: " + (t1c-t1b)); -// System.out.println("ContourGenerator init took:" + (t1c-t0)); - - try { - cgen.generateContours(); - } catch (ContourException e1) { - // TODO Auto-generated catch block -// e1.printStackTrace(); - cgen.dispose(); - isCntrsCreated = false; - ContourCalculationReentrantLock.releaseReentrantLock(); - return; - } - - - - long t2 = System.currentTimeMillis(); - if ( ncgribLogger.enableCntrLogs() ) - logger.info("===ContourGenerator.generateContours() for ("+name+") took: " + (t2-t1a)); - -// System.out.println("Contour Computation took: " + (t2-t1c)); - - logger.debug("Total generating contour line values took: " + (t2-t1a)); - if ( cvalues != null ) { - for ( Double cval : cvalues ) { - float fval = (float) (cval * 1.0f); - contourGroup.data.put(cval.toString(), cgen.getContours(fval)); - } - } - if ( fvalues != null ) { - for ( Double cval : fvalues ) { - float fval = (float) (cval * 1.0f); - contourGroup.data.put(cval.toString(), cgen.getContours(fval)); - } - } - - if ( contourGroup.grid == null ) { - contourGroup.grid = cgen.getEdges(); - } - cgen.dispose(); - ContourCalculationReentrantLock.releaseReentrantLock(); -// } + if (attr.getClrbar() != null && !attr.getClrbar().isEmpty()) { + contourGroup.clrbar = new CLRBAR(attr.getClrbar()); + ColorBarAttributesBuilder cBarAttrBuilder = contourGroup.clrbar + .getcBarAttributesBuilder(); + ColorBar colorBar = new ColorBar(); + if (cBarAttrBuilder.isDrawColorBar()) { + colorBar.setAttributesFromColorBarAttributesBuilder(cBarAttrBuilder); + colorBar.setAttributesFromColorBarAttributesBuilder(cBarAttrBuilder); + colorBar.setColorDevice(NcDisplayMngr + .getActiveNatlCntrsEditor().getActiveDisplayPane() + .getDisplay()); + FINT theFillIntervals = new FINT(fint.trim()); + FLine fillColorString = new FLine(fline.trim()); + if (!theFillIntervals.isFINTStringParsed() + || !fillColorString.isFLineStringParsed()) + return null; + List fillIntvls = theFillIntervals + .getUniqueSortedFillValuesFromAllZoomLevels(); + List fillColors = fillColorString.getFillColorList(); + + fillIntvls.add(0, Double.NEGATIVE_INFINITY); + int numFillIntervals = fillIntvls.size(); + fillIntvls.add(numFillIntervals, Double.POSITIVE_INFINITY); + int numDecimals = 0; + for (int index = 0; index <= numFillIntervals - 1; index++) { + colorBar.addColorBarInterval(fillIntvls.get(index) + .floatValue(), fillIntvls.get(index + 1) + .floatValue(), GempakColor.convertToRGB(fillColors + .get(index))); + String tmp[] = fillIntvls.get(index).toString() + .split("\\."); + if (tmp.length > 1 && tmp[1].length() > numDecimals + && !"0".equals(tmp[1])) { + numDecimals = tmp[1].length(); + } + } + colorBar.setNumDecimals(numDecimals); + return colorBar; + } + } + return null; } - + + public void genContour() { + + ContourCalculationReentrantLock.getReentrantLock(); + // synchronized (ContourSupport.class) { + List allvalues = new ArrayList(svalues); + Collections.sort(allvalues); + + long t1a = System.currentTimeMillis(); + ContourGenerator cgen = new ContourGenerator(cntrData.getData(), + cntrData.getX(), cntrData.getY()); + long t1b = System.currentTimeMillis(); + logger.debug("Creating contour values took: " + (t1b - t1a)); + cgen.setContourValues(allvalues); + + long t1c = System.currentTimeMillis(); + logger.debug("ContourGenerator.setContourValues(allvalues) took: " + + (t1c - t1b)); + // System.out.println("ContourGenerator init took:" + (t1c-t0)); + + try { + cgen.generateContours(); + } catch (ContourException e1) { + // TODO Auto-generated catch block + // e1.printStackTrace(); + cgen.dispose(); + isCntrsCreated = false; + ContourCalculationReentrantLock.releaseReentrantLock(); + return; + } + + long t2 = System.currentTimeMillis(); + if (ncgribLogger.enableCntrLogs()) + logger.info("===ContourGenerator.generateContours() for (" + name + + ") took: " + (t2 - t1a)); + + // System.out.println("Contour Computation took: " + (t2-t1c)); + + logger.debug("Total generating contour line values took: " + (t2 - t1a)); + if (cvalues != null) { + for (Double cval : cvalues) { + float fval = (float) (cval * 1.0f); + contourGroup.data.put(cval.toString(), cgen.getContours(fval)); + } + } + if (fvalues != null) { + for (Double cval : fvalues) { + float fval = (float) (cval * 1.0f); + contourGroup.data.put(cval.toString(), cgen.getContours(fval)); + } + } + + if (contourGroup.grid == null) { + contourGroup.grid = cgen.getEdges(); + } + cgen.dispose(); + ContourCalculationReentrantLock.releaseReentrantLock(); + // } + } + public ContourGroup getContours() { - if ( ! isCntrsCreated ) return null; - return contourGroup; + if (!isCntrsCreated) + return null; + return contourGroup; } - + /** - * If the worldWrapChecker is true and the gird is split by the map border. + * If the worldWrapChecker is true and the grid is split by the map border. + * * @param imageGridGeometry * @param rastPosToLatLon * @return */ - private boolean needWrap(GeneralGridGeometry imageGridGeometry, MathTransform rastPosToLatLon){ - boolean ret = worldWrapChecker; - - if ( ret ){ - //minimum, maximum X grid - int minx = imageGridGeometry.getGridRange().getLow(0); - int maxx = imageGridGeometry.getGridRange().getHigh(0); + private boolean needWrap(GeneralGridGeometry imageGridGeometry, + MathTransform rastPosToLatLon) { + boolean ret = worldWrapChecker; - double [] out0 = new double[3]; - double [] out1 = new double[3]; + if (ret) { + // minimum, maximum X grid + int minx = imageGridGeometry.getGridRange().getLow(0); + int maxx = imageGridGeometry.getGridRange().getHigh(0); - //minimum, maximum longitudes - try { - rastPosToLatLon.transform( new double[]{minx, 0}, 0, out0, 0, 1 ); - rastPosToLatLon.transform( new double[]{maxx, 0}, 0, out1, 0, 1 ); - } catch (TransformException e) { - // TODO Auto-generated catch block - //printStackTrace(); - ret = false; - } - - - double minLon = ( out0[0] >= 0 ) ? out0[0] : out0[0] +360; - double maxLon = ( out1[0] >= 0 ) ? out1[0] : out1[0] +360; - - if ( minLon == 0 && maxLon == 360 ) globalData = true; - - if ( maxLon >= 360 ) maxLon = 359; + double[] out0 = new double[3]; + double[] out1 = new double[3]; - double right = centralMeridian + 180; + // minimum, maximum longitudes + try { + rastPosToLatLon.transform(new double[] { minx, 0 }, 0, out0, 0, + 1); + rastPosToLatLon.transform(new double[] { maxx, 0 }, 0, out1, 0, + 1); + } catch (TransformException e) { + // TODO Auto-generated catch block + // printStackTrace(); + ret = false; + } - if ( maxLon > minLon ){ - ret = (right > minLon) && (right < maxLon ); - } - else { - ret = !(right > minLon) && (right < maxLon ); - } - } - - return ret; + double minLon = (out0[0] >= 0) ? out0[0] : out0[0] + 360; + double maxLon = (out1[0] >= 0) ? out1[0] : out1[0] + 360; + + if (minLon == 0 && maxLon == 360) + globalData = true; + + if (maxLon >= 360) + maxLon = 359; + double right = centralMeridian + 180; + + if (maxLon > minLon) { + ret = (right > minLon) && (right < maxLon); + + } else { + ret = !(right > minLon) && (right < maxLon); + + } + + } + // ret = false; + + MapProjection worldProjection = CRS.getMapProjection(descriptor + .getCRS()); + try { + if (worldProjection.getClass().getCanonicalName() + .contains("Lambert")) { + ret = false; + } + } catch (Exception e) { + System.out.println(" Can't get projection"); + } + return ret; } - + /** * Gets the maximum grid number in x direction + * * @param imageGridGeometry * @return int - maximum grid number in x direction */ - private int getMaxGridX(GeneralGridGeometry imageGridGeometry){ + private int getMaxGridX(GeneralGridGeometry imageGridGeometry) { return imageGridGeometry.getGridRange().getHigh(0); } - + /** * Gets the map width in screen coordinate. + * * @return */ private double getMapWidth() { - if ( worldWrapChecker ){ - // double right[] = new double[]{centralMeridian + 180, 0}; - // double left[] = new double[]{centralMeridian - 180, 0}; - double right[] = new double[]{-180, 0}; - double left[] = new double[]{0, 0}; - - double screenLeft[] = new double[2]; - double screenRight[] = new double[2]; + if (worldWrapChecker) { + // double right[] = new double[]{centralMeridian + 180, 0}; + // double left[] = new double[]{centralMeridian - 180, 0}; + double right[] = new double[] { -180, 0 }; + double left[] = new double[] { 0, 0 }; - try { - double center[] = new double[]{0, 0}; - double out[] = new double[2]; - rastPosLatLonToWorldGrid.transform(center, 0, out, 0, 1); - zeroLonOnScreen = out[0]; - - rastPosLatLonToWorldGrid.transform(left, 0, screenLeft, 0, 1); - rastPosLatLonToWorldGrid.transform(right, 0, screenRight, 0, 1); - - return Math.abs(screenRight[0] - screenLeft[0])*2; - } catch (TransformException e) { - // TODO Auto-generated catch block - return 0; - } - - } - else { - return 0; - } + double screenLeft[] = new double[2]; + double screenRight[] = new double[2]; + + try { + double center[] = new double[] { 0, 0 }; + double out[] = new double[2]; + rastPosLatLonToWorldGrid.transform(center, 0, out, 0, 1); + zeroLonOnScreen = out[0]; + + rastPosLatLonToWorldGrid.transform(left, 0, screenLeft, 0, 1); + rastPosLatLonToWorldGrid.transform(right, 0, screenRight, 0, 1); + + return Math.abs(screenRight[0] - screenLeft[0]) * 2; + } catch (TransformException e) { + // TODO Auto-generated catch block + return 0; + } + + } else { + return 0; + } } -} +} diff --git a/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/GriddedVectorDisplay.java b/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/GriddedVectorDisplay.java index fb059e86c5..c6f6f772a4 100644 --- a/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/GriddedVectorDisplay.java +++ b/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/contours/GriddedVectorDisplay.java @@ -212,7 +212,8 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { int idx = x + y * this.gridDims[0]; // System.out.println("paintImage idx==="+idx+" x=="+ijcoord.x+" y====="+ijcoord.y); - + // System.out.println("INDEX " + idx + " : " + x + "," + y + " : " + // + gridDims[0] + "," + gridDims[1]); if (idx < 0 || idx >= (gridDims[0] * gridDims[1])) { return; } @@ -623,4 +624,93 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { } return match; } + + @Override + /* + * HACK hack hack ... this version of paintImage is being used for global + * grids. I don't think the grid <-> latlon transforms are working, so the + * index calculation has been modified. This is not a good solution, but was + * implemented due to time crunch for 13.5.2 + */ + protected void paintGlobalImage(int x, int y, PaintProperties paintProps, + double adjSize) throws VizException { + int adjx = x - 1; + // if (x > 0) + // adjx = 180 + x; + int adjy = y + 1; + if (x > 0) { + adjx++; + adjy = y; + } + int idx = adjx + adjy * this.gridDims[0]; + + // System.out.println("paintImage idx==="+idx+" x=="+ijcoord.x+" y====="+ijcoord.y); + // System.out.println("INDEX " + idx + " : " + x + "," + y + " : " + + // adjx + // + "," + adjy + " : " + gridDims[0] + "," + gridDims[1]); + if (idx < 0 || idx >= (gridDims[0] * gridDims[1])) { + return; + } + float spd = this.magnitude.get(idx); + float dir = this.direction.get(idx); + + if (Float.isNaN(spd) || Float.isNaN(dir)) { + return; + } + + if (this.isPlotted[idx]) { + return; + } + + ReferencedCoordinate newrco = new ReferencedCoordinate(new Coordinate( + x, y), this.gridGeometryOfGrid, Type.GRID_CENTER); + Coordinate plotLoc = null; + + try { + plotLoc = newrco.asPixel(this.descriptor.getGridGeometry()); + latLon = newrco.asLatLon(); + // System.out.println("plotloc = " + latLon); + + if (latLon.x > 180 || latLon.x < -180 || latLon.y < -90 + || latLon.y > 90) { + return; + } + + double[] stationLocation = { latLon.x, latLon.y }; + double[] stationPixelLocation = this.descriptor + .worldToPixel(stationLocation); + + if (stationPixelLocation != null) { + stationPixelLocation[1]--; + double[] newWorldLocation = this.descriptor + .pixelToWorld(stationPixelLocation); + this.gc.setStartingGeographicPoint(stationLocation[0], + stationLocation[1]); + this.gc.setDestinationGeographicPoint(newWorldLocation[0], + newWorldLocation[1]); + } + + dir = dir + (float) MapUtil.rotation(latLon, gridLocation); + dir -= this.gc.getAzimuth(); + } catch (Exception e) { + throw new VizException(e); + } + + dir = (float) Math.toRadians(dir); + switch (displayType) { + case ARROW: + paintArrow(plotLoc, adjSize, spd, dir); + break; + case BARB: + paintBarb(plotLoc, adjSize, spd, dir); + break; + case DUALARROW: + paintDualArrow(plotLoc, adjSize, spd, dir); + break; + default: + throw new VizException("Unsupported disply type: " + displayType); + } + + this.isPlotted[idx] = true; + } } diff --git a/rpms/awips2.core/Installer.httpd-pypies/SOURCES/httpd-pypies.logrotate b/rpms/awips2.core/Installer.httpd-pypies/SOURCES/httpd-pypies.logrotate deleted file mode 100644 index ab3f28b269..0000000000 --- a/rpms/awips2.core/Installer.httpd-pypies/SOURCES/httpd-pypies.logrotate +++ /dev/null @@ -1,8 +0,0 @@ -/awips2/httpd_pypies/var/log/httpd/*log { - missingok - notifempty - sharedscripts - postrotate - /sbin/service httpd-pypies reload > /dev/null 2>/dev/null || true - endscript -} diff --git a/rpms/awips2.core/Installer.httpd-pypies/component.spec b/rpms/awips2.core/Installer.httpd-pypies/component.spec index 5f646e979f..4ea8e60b22 100644 --- a/rpms/awips2.core/Installer.httpd-pypies/component.spec +++ b/rpms/awips2.core/Installer.httpd-pypies/component.spec @@ -8,12 +8,11 @@ Summary: Pypies Apache HTTP Server Name: awips2-httpd-pypies Version: 2.2.3 # This Is Officially Release: 22%{?dist} -Release: 30%{?dist} +Release: 31%{?dist} URL: http://httpd.apache.org/ Prefix: /awips2/httpd_pypies Source0: http://www.apache.org/dist/httpd/httpd-%{version}.tar.gz Source1: centos_index.html -Source3: httpd-pypies.logrotate Source4: httpd-pypies.init Source5: httpd.sysconf Source8: centos_powered_by_rh.png @@ -362,11 +361,11 @@ ln -s ../..%{_libdir}/httpd/modules $RPM_BUILD_ROOT/awips2/httpd_pypies/etc/http mkdir -p ${RPM_BUILD_ROOT}/etc/init.d install -m755 %{_baseline_workspace}/rpms/awips2.core/Installer.httpd-pypies/configuration/etc/init.d/httpd-pypies \ ${RPM_BUILD_ROOT}/etc/init.d - -# install log rotation stuff -mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d -install -m644 $RPM_SOURCE_DIR/httpd-pypies.logrotate \ - $RPM_BUILD_ROOT/etc/logrotate.d/httpd-pypies + +# install cron job +mkdir -p ${RPM_BUILD_ROOT}/etc/cron.daily +install -m755 %{_baseline_workspace}/rpms/awips2.core/Installer.httpd-pypies/configuration/etc/cron.daily/pypiesLogCleanup.sh \ + ${RPM_BUILD_ROOT}/etc/cron.daily # fix man page paths sed -e "s|/usr/local/apache2/conf/httpd.conf|/etc/httpd/conf/httpd.conf|" \ @@ -571,7 +570,7 @@ rm -rf $RPM_BUILD_ROOT %config(noreplace) /awips2/httpd_pypies%{_sysconfdir}/httpd/conf.d/proxy_ajp.conf %config(noreplace) /awips2/httpd_pypies%{_sysconfdir}/httpd/conf/magic -%config(noreplace) %{_sysconfdir}/logrotate.d/httpd-pypies +%{_sysconfdir}/cron.daily/pypiesLogCleanup.sh %config(noreplace) %{_sysconfdir}/init.d/httpd-pypies %dir /awips2/httpd_pypies%{_sysconfdir}/httpd/conf.d diff --git a/rpms/awips2.core/Installer.httpd-pypies/configuration/conf/httpd.conf b/rpms/awips2.core/Installer.httpd-pypies/configuration/conf/httpd.conf index c1d1363356..10b8710ddd 100644 --- a/rpms/awips2.core/Installer.httpd-pypies/configuration/conf/httpd.conf +++ b/rpms/awips2.core/Installer.httpd-pypies/configuration/conf/httpd.conf @@ -469,7 +469,7 @@ HostnameLookups Off # logged here. If you *do* define an error logfile for a # container, that host's errors will be logged there and not here. # -ErrorLog logs/error_log +ErrorLog "|/awips2/httpd_pypies/usr/sbin/rotatelogs /awips2/httpd_pypies/var/log/httpd/error_log.%Y.%m.%d 86400" # # LogLevel: Control the number of messages logged to the error_log. @@ -511,7 +511,7 @@ LogFormat "%{User-agent}i" agent # For a single logfile with access, agent, and referer information # (Combined Logfile Format), use the following directive: # -CustomLog logs/access_log combined +CustomLog "|/awips2/httpd_pypies/usr/sbin/rotatelogs /awips2/httpd_pypies/var/log/httpd/access_log.%Y.%m.%d 86400" combined # # Optionally add a line containing the server version and virtual host diff --git a/rpms/awips2.core/Installer.httpd-pypies/configuration/etc/cron.daily/pypiesLogCleanup.sh b/rpms/awips2.core/Installer.httpd-pypies/configuration/etc/cron.daily/pypiesLogCleanup.sh new file mode 100644 index 0000000000..4008cb8d85 --- /dev/null +++ b/rpms/awips2.core/Installer.httpd-pypies/configuration/etc/cron.daily/pypiesLogCleanup.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Remove any logs from a week ago, if they exist. + +_PYPIES_LOG_DIRECTORY="/awips2/httpd_pypies/var/log/httpd" + +_LOG_NAME_PREFIXES=( 'access_log' 'error_log' ) +_COUNT_DAYS=( 7 8 9 10 11 12 13 14 ) + +for day in ${_COUNT_DAYS[*]}; do + _log_date=`date -d "-${day} day" +%Y.%m.%d` + + for logPrefix in ${_LOG_NAME_PREFIXES[*]}; do + _log_file="${logPrefix}.${_log_date}" + + echo "${_PYPIES_LOG_DIRECTORY}/${_log_file}" + rm -f ${_PYPIES_LOG_DIRECTORY}/${_log_file} + done +done diff --git a/rpms/awips2.core/Installer.httpd-pypies/configuration/etc/init.d/httpd-pypies b/rpms/awips2.core/Installer.httpd-pypies/configuration/etc/init.d/httpd-pypies index cdbe6c81ce..24a54b3fce 100644 --- a/rpms/awips2.core/Installer.httpd-pypies/configuration/etc/init.d/httpd-pypies +++ b/rpms/awips2.core/Installer.httpd-pypies/configuration/etc/init.d/httpd-pypies @@ -98,10 +98,30 @@ start() { return $RETVAL } +stop() { + echo -n $"Stopping $prog: " + /awips2/httpd_pypies/usr/sbin/apachectl -k graceful-stop + RETVAL=$? + echo + [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile} + echo -n $"Stopping logging service:" + # Stop the logging process + for pid in `ps aux | grep [l]ogProcess.py | awk '{print $2}'`; + do + kill -9 ${pid} + RC=$? + if [ ${RC} -ne 0 ]; then + failure + return + fi + done + success + echo +} # When stopping httpd a delay of >10 second is required before SIGKILLing the # httpd parent; this gives enough time for the httpd parent to SIGKILL any # errant children. -stop() { +forcestop() { echo -n $"Stopping $prog: " killproc -d 10 $httpd RETVAL=$? @@ -128,7 +148,7 @@ reload() { echo $"not reloading due to configuration syntax error" failure $"not reloading $httpd due to configuration syntax error" else - killproc $httpd -HUP + /awips2/httpd_pypies/usr/sbin/apachectl -k graceful RETVAL=$? fi echo @@ -142,6 +162,9 @@ case "$1" in stop) stop ;; + forcestop) + forcestop + ;; status) status $httpd RETVAL=$? @@ -164,7 +187,7 @@ case "$1" in RETVAL=$? ;; *) - echo $"Usage: $prog {start|stop|restart|condrestart|reload|status|fullstatus|graceful|help|configtest}" + echo $"Usage: $prog {start|stop|forcestop|restart|condrestart|reload|status|fullstatus|graceful|help|configtest}" exit 1 esac diff --git a/rpms/build/i386/build.sh b/rpms/build/i386/build.sh index 31dd6470c1..924ea5d820 100644 --- a/rpms/build/i386/build.sh +++ b/rpms/build/i386/build.sh @@ -408,7 +408,13 @@ fi # Use the custom flag for selecting specific rpms to build if [ "${1}" = "-custom" ]; then - #buildRPM "awips2-ldm" + unpackHttpdPypies + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-httpd-pypies" + buildRPM "awips2-adapt-native" + buildRPM "awips2-hydroapps-shared" exit 0 fi diff --git a/rpms/build/x86_64/build.sh b/rpms/build/x86_64/build.sh index eb3cddb126..c1ac1b921a 100644 --- a/rpms/build/x86_64/build.sh +++ b/rpms/build/x86_64/build.sh @@ -116,7 +116,6 @@ if [ "${1}" = "-64bit" ]; then buildRPM "awips2-python-pygtk" buildRPM "awips2-python-pycairo" buildJava - buildRPM "awips2" buildRPM "awips2-python-shapely" buildRPM "awips2-notification" @@ -155,7 +154,6 @@ if [ "${1}" = "-delta" ]; then buildRPM "awips2-localapps-environment" buildRPM "awips2-data.hdf5-topo" buildRPM "awips2-data.gfe" - buildRPM "awips2" buildLocalizationRPMs if [ $? -ne 0 ]; then exit 1 @@ -205,7 +203,6 @@ if [ "${1}" = "-full" ]; then buildRPM "awips2-localapps-environment" buildRPM "awips2-data.hdf5-topo" buildRPM "awips2-data.gfe" - buildRPM "awips2" unpackHttpdPypies if [ $? -ne 0 ]; then exit 1 @@ -273,6 +270,27 @@ if [ "${1}" = "-ldm" ]; then exit 0 fi + +if [ "${1}" = "-awips2" ]; then + buildRPM "awips2" + + exit 0 +fi + +# Use the custom flag for selecting specific rpms to build +if [ "${1}" = "-custom" ]; then + unpackHttpdPypies + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-httpd-pypies" + buildRPM "awips2-adapt-native" + buildRPM "awips2-hydroapps-shared" + + exit 0 +fi + + if [ "${1}" = "-package" ]; then repository_directory="awips2-repository-${AWIPSII_VERSION}-${AWIPSII_RELEASE}" if [ -d ${WORKSPACE}/${repository_directory} ]; then From 2e6e0311986c411a4e06575eb733791f9e5d6975 Mon Sep 17 00:00:00 2001 From: Steve Harris Date: Fri, 25 Oct 2013 09:59:15 -0400 Subject: [PATCH 07/26] 13.5.2-12 baseline Former-commit-id: 845d49e3701e737bbbbb9fbfcb2063eef9c6c759 [formerly e2b9baf2ed41ce03c77b511b7f9b6088d84f597a] [formerly a53289647336e64f89d16b5c56b51e94c1cb4c52] [formerly bcb531e671e975781651824a6540d0ba3d203161 [formerly a53289647336e64f89d16b5c56b51e94c1cb4c52 [formerly 7918a1bb18c212f8a3b84edec932880126d351be]]] Former-commit-id: bcb531e671e975781651824a6540d0ba3d203161 Former-commit-id: 7b3329db475d8a4c9b900f448656bc46192af5e3 [formerly b70ec5732dab85eb6c3765dc4ac22b44e2146142] Former-commit-id: 15d98481704a0d9482c971eeb36d71eab2621cf2 --- .../com.raytheon.rcm.feature/feature.xml | 6 + .../feature.xml | 6 - .../feature.xml | 6 + .../formatterlauncher/ZoneCombinerComp.java | 23 +- .../plugin/gfe/config/GFESiteActivation.java | 14 +- .../raytheon/edex/plugin/gfe/isc/GfeIRT.java | 285 +++++++++------ .../edex_static/base/gfe/isc/IrtServer.py | 50 +-- .../feature.xml | 6 + .../META-INF/MANIFEST.MF | 3 +- .../com/raytheon/uf/common/util/FileUtil.java | 207 +++++------ .../feature.xml | 6 - rpms/build/i386/build.sh | 30 +- rpms/build/x86_64/build.sh | 4 + rpms/build/x86_64/build.sh-10172013 | 333 ++++++++++++++++++ 14 files changed, 653 insertions(+), 326 deletions(-) create mode 100644 rpms/build/x86_64/build.sh-10172013 diff --git a/RadarServer/com.raytheon.rcm.feature/feature.xml b/RadarServer/com.raytheon.rcm.feature/feature.xml index f43dcbbe23..338a05cdc8 100644 --- a/RadarServer/com.raytheon.rcm.feature/feature.xml +++ b/RadarServer/com.raytheon.rcm.feature/feature.xml @@ -161,4 +161,10 @@ install-size="0" version="0.0.0"/> + + diff --git a/cave/com.raytheon.uf.viz.archive.feature/feature.xml b/cave/com.raytheon.uf.viz.archive.feature/feature.xml index 17e8e6923a..9705fea76d 100644 --- a/cave/com.raytheon.uf.viz.archive.feature/feature.xml +++ b/cave/com.raytheon.uf.viz.archive.feature/feature.xml @@ -36,12 +36,6 @@ version="0.0.0" unpack="false"/> - - + + diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/ZoneCombinerComp.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/ZoneCombinerComp.java index 9adb3635b9..1cb430d434 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/ZoneCombinerComp.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/ZoneCombinerComp.java @@ -95,6 +95,9 @@ import com.raytheon.viz.gfe.ui.zoneselector.ZoneSelector; * Changes for non-blocking ZoneColorEditorDlg. * Mar 14, 2013 1794 djohnson Consolidate common FilenameFilter implementations. * Sep 05, 2013 2329 randerso Removed obsolete methods, added ApplyZoneCombo method + * Oct 17, 2013 2481 randerso Fixed regression which cause configured level combinations + * files to not be found. Removed message when combinations file + * not found to match A1. * * * @@ -781,7 +784,7 @@ public class ZoneCombinerComp extends Composite implements colorMap = getColorsFromFile(); String comboName = theFile; - if (comboName == null || comboName.isEmpty()) { + if ((comboName == null) || comboName.isEmpty()) { comboName = getCombinationsFileName(); } Map comboDict = loadCombinationsFile(comboName); @@ -911,18 +914,16 @@ public class ZoneCombinerComp extends Composite implements public Map loadCombinationsFile(String comboName) { Map dict = new HashMap(); try { - IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationContext ctx = pm.getContext( - LocalizationType.CAVE_STATIC, LocalizationLevel.SITE); - File localFile = pm.getFile(ctx, FileUtil.join( - CombinationsFileUtil.COMBO_DIR_PATH, comboName + ".py")); + File localFile = PathManagerFactory.getPathManager().getStaticFile( + FileUtil.join(CombinationsFileUtil.COMBO_DIR_PATH, + comboName + ".py")); List> combolist = new ArrayList>(); - if (localFile != null && localFile.exists()) { + if ((localFile != null) && localFile.exists()) { combolist = CombinationsFileUtil.init(comboName); } else { - statusHandler.error("Combinations file does not found: " - + comboName); + // statusHandler + // .error("Combinations file not found: " + comboName); } // reformat combinations into combo dictionary @@ -1004,7 +1005,7 @@ public class ZoneCombinerComp extends Composite implements @Override public void applyButtonState(final boolean enabled) { - if (this.applyZoneComboBtn != null + if ((this.applyZoneComboBtn != null) && !this.applyZoneComboBtn.isDisposed()) { VizApp.runAsync(new Runnable() { @Override @@ -1017,7 +1018,7 @@ public class ZoneCombinerComp extends Composite implements private boolean buttonState() { final boolean[] state = { false }; - if (this.applyZoneComboBtn != null + if ((this.applyZoneComboBtn != null) && !this.applyZoneComboBtn.isDisposed()) { VizApp.runSync(new Runnable() { @Override diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java index 106c4fd65f..66573cb0e5 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java @@ -89,6 +89,7 @@ import com.raytheon.uf.edex.site.notify.SendSiteActivationNotifications; * Mar 20, 2013 #1774 randerso Changed to use GFED2DDao * May 02, 2013 #1969 randerso Moved updateDbs method into IFPGridDatabase * Sep 13, 2013 2368 rjpeter Used durable jms settings. + * Oct 16, 2013 #2475 dgilling Better error handling for IRT activation. * * * @author njensen @@ -370,6 +371,7 @@ public class GFESiteActivation implements ISiteActivationListener { // Doesn't need to be cluster locked statusHandler.handle(Priority.EVENTA, "Checking ISC configuration..."); + boolean isIscActivated = false; if (config.requestISC()) { String host = InetAddress.getLocalHost().getCanonicalHostName(); String gfeHost = config.getServerHost(); @@ -382,7 +384,15 @@ public class GFESiteActivation implements ISiteActivationListener { if (host.contains(hostNameToCompare) && System.getProperty("edex.run.mode").equals("request")) { statusHandler.handle(Priority.EVENTA, "Enabling ISC..."); - IRTManager.getInstance().enableISC(siteID, config.getMhsid()); + try { + IRTManager.getInstance().enableISC(siteID, + config.getMhsid()); + isIscActivated = true; + } catch (Exception e) { + statusHandler + .error("Error starting GFE ISC. ISC functionality will be unavailable!!", + e); + } } else { statusHandler.handle(Priority.EVENTA, "ISC Enabled but will use another EDEX instance"); @@ -491,7 +501,7 @@ public class GFESiteActivation implements ISiteActivationListener { }; postActivationTaskExecutor.submit(smartInit); - if (config.tableFetchTime() > 0) { + if (config.tableFetchTime() > 0 && isIscActivated) { Runnable activateFetchAT = new Runnable() { @Override diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/GfeIRT.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/GfeIRT.java index c723397310..4d505708e5 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/GfeIRT.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/isc/GfeIRT.java @@ -33,10 +33,10 @@ import jep.JepException; import com.raytheon.edex.plugin.gfe.config.GridDbConfig; import com.raytheon.edex.plugin.gfe.config.IFPServerConfig; import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager; +import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException; import com.raytheon.edex.plugin.gfe.server.GridParmManager; import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation; -import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException; import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil; import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext; @@ -47,6 +47,7 @@ import com.raytheon.uf.common.python.PyUtil; import com.raytheon.uf.common.python.PythonScript; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.util.FileUtil; /** @@ -60,6 +61,8 @@ import com.raytheon.uf.common.util.FileUtil; * ------------ ---------- ----------- -------------------------- * 07/14/09 1995 bphillip Initial creation * Mar 14, 2013 1794 djohnson FileUtil.listFiles now returns List. + * Oct 16, 2013 2475 dgilling Move logic previously in IrtServer.py + * into this class to avoid Jep memory leak. * * * @@ -72,14 +75,29 @@ public class GfeIRT extends Thread { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(GfeIRT.class); + private static final String PYTHON_INSTANCE = "irt"; + /** The site ID associated with this IRT thread */ private final String siteID; /** The MHS ID associated with this IRT thread */ private final String mhsID; - /** The script file name */ - private final String scriptFile; + private final String serverHost; + + private final long serverPort; + + private final long serverProtocol; + + private List parmsWanted; + + private final List gridDims; + + private final String gridProj; + + private final List gridBoundBox; + + private List iscWfosWanted; /** The Python script object */ private PythonScript script; @@ -94,20 +112,83 @@ public class GfeIRT extends Thread { * * @param siteID * The site ID to create the GfeIRT object for - * @throws GfeException + * @throws GfeConfigurationException + * If the GFE configuration for the specified site could not be + * loaded. */ - public GfeIRT(String mhsid, String siteid) throws GfeException { + public GfeIRT(String mhsid, String siteid) throws GfeConfigurationException { this.setDaemon(true); this.siteID = siteid; this.mhsID = mhsid; - IPathManager pathMgr = PathManagerFactory.getPathManager(); - LocalizationContext cx = pathMgr.getContext( - LocalizationType.EDEX_STATIC, LocalizationLevel.BASE); - scriptFile = pathMgr - .getLocalizationFile(cx, - "gfe/isc" + File.separator + "IrtServer.py").getFile() - .getPath(); + IFPServerConfig config = IFPServerConfigManager.getServerConfig(siteID); + + this.serverHost = config.getServerHost(); + this.serverPort = config.getRpcPort(); + this.serverProtocol = config.getProtocolVersion(); + + GridLocation domain = config.dbDomain(); + + this.gridProj = domain.getProjection().getProjectionID().toString(); + + this.gridDims = new ArrayList(2); + this.gridDims.add(domain.getNy()); + this.gridDims.add(domain.getNx()); + + this.gridBoundBox = new ArrayList(4); + this.gridBoundBox.add(domain.getOrigin().x); + this.gridBoundBox.add(domain.getOrigin().y); + this.gridBoundBox.add(domain.getExtent().x); + this.gridBoundBox.add(domain.getExtent().y); + + this.parmsWanted = config.requestedISCparms(); + if (this.parmsWanted.isEmpty()) { + List dbs = GridParmManager.getDbInventory(this.siteID) + .getPayload(); + for (DatabaseID dbId : dbs) { + if ((dbId.getModelName().equals("ISC")) + && (dbId.getDbType().equals("")) + && (dbId.getSiteId().equals(this.siteID))) { + GridDbConfig gdc = config.gridDbConfig(dbId); + this.parmsWanted = gdc.parmAndLevelList(); + } + } + config.setRequestedISCparms(this.parmsWanted); + } + statusHandler.info("ParmsWanted: " + this.parmsWanted); + + this.iscWfosWanted = config.requestedISCsites(); + if (this.iscWfosWanted.isEmpty()) { + List knownSites = config.allSites(); + + IPathManager pathMgr = PathManagerFactory.getPathManager(); + LocalizationContext commonStaticConfig = pathMgr.getContext( + LocalizationType.COMMON_STATIC, + LocalizationLevel.CONFIGURED); + commonStaticConfig.setContextName(this.siteID); + File editAreaDir = pathMgr.getFile(commonStaticConfig, + "gfe/editAreas"); + + FilenameFilter filter = new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.trim().matches("ISC_\\p{Alnum}{3}\\.xml"); + } + }; + List editAreas = FileUtil.listFiles(editAreaDir, filter, + false); + + this.iscWfosWanted = new ArrayList(); + for (File f : editAreas) { + String name = f.getName().replace("ISC_", "") + .replace(".xml", ""); + if (knownSites.contains(name)) { + iscWfosWanted.add(name); + } + } + config.setRequestedISCsites(this.iscWfosWanted); + } + Thread hook = new Thread() { @Override public void run() { @@ -123,111 +204,97 @@ public class GfeIRT extends Thread { @Override public void run() { - try { + IPathManager pathMgr = PathManagerFactory.getPathManager(); + LocalizationContext cx = pathMgr.getContext( + LocalizationType.EDEX_STATIC, LocalizationLevel.BASE); + String scriptPath = pathMgr + .getLocalizationFile(cx, "gfe/isc/IrtAccess.py").getFile() + .getPath(); String includePath = PyUtil.buildJepIncludePath( GfePyIncludeUtil.getCommonPythonIncludePath(), GfePyIncludeUtil.getIscScriptsIncludePath(), - GfePyIncludeUtil.getGfeConfigIncludePath(siteID)); - script = new PythonScript(scriptFile, includePath); - Map args = new HashMap(); + GfePyIncludeUtil.getGfeConfigIncludePath(this.siteID)); + this.script = new PythonScript(scriptPath, includePath, getClass() + .getClassLoader()); IFPServerConfig config = IFPServerConfigManager .getServerConfig(siteID); - GridLocation domain = config.dbDomain(); - - String site = config.getSiteID().get(0); - List gridDims = new ArrayList(); - gridDims.add(domain.getNy()); - gridDims.add(domain.getNx()); - - List gridBoundBox = new ArrayList(); - gridBoundBox.add(domain.getOrigin().x); - gridBoundBox.add(domain.getOrigin().y); - gridBoundBox.add(domain.getExtent().x); - gridBoundBox.add(domain.getExtent().y); - - // determine which parms are wanted - List parmsWanted = config.requestedISCparms(); - if (parmsWanted.isEmpty()) { - List dbs = GridParmManager.getDbInventory(site) - .getPayload(); - - for (int i = 0; i < dbs.size(); i++) { - if (dbs.get(i).getModelName().equals("ISC") - && dbs.get(i).getDbType().equals("") - && dbs.get(i).getSiteId().equals(site)) { - GridDbConfig gdc = config.gridDbConfig(dbs.get(i)); - parmsWanted = gdc.parmAndLevelList(); - } - } - } - statusHandler.info("ParmsWanted: " + parmsWanted); - - // reset them to actual values - config.setRequestedISCparms(parmsWanted); - - // determine isc areas that are wanted - List iscWfosWanted = config.requestedISCsites(); - - if (iscWfosWanted.isEmpty()) { - List knownSites = config.allSites(); - - IPathManager pathMgr = PathManagerFactory.getPathManager(); - LocalizationContext commonStaticConfig = pathMgr.getContext( - LocalizationType.COMMON_STATIC, - LocalizationLevel.CONFIGURED); - commonStaticConfig.setContextName(site); - File editAreaDir = pathMgr.getFile(commonStaticConfig, - "gfe/editAreas"); - - FilenameFilter filter = new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.trim().matches("ISC_\\p{Alnum}{3}\\.xml"); - } - }; - List editAreas = FileUtil.listFiles(editAreaDir, - filter, false); - - String name = ""; - for (File f : editAreas) { - name = f.getName().replace("ISC_", "").replace(".xml", ""); - if (knownSites.contains(name)) { - iscWfosWanted.add(name); - } - } - config.setRequestedISCsites(iscWfosWanted); - } - - args.put("ancfURL", config.iscRoutingTableAddress().get("ANCF")); - args.put("bncfURL", config.iscRoutingTableAddress().get("BNCF")); - args.put("mhsid", config.getMhsid()); - args.put("serverHost", config.getServerHost()); - args.put("serverPort", config.getRpcPort()); - args.put("serverProtocol", config.getProtocolVersion()); - args.put("site", site); - args.put("parmsWanted", config.requestedISCparms()); - args.put("gridDims", gridDims); - args.put("gridProj", domain.getProjection().getProjectionID() - .toString()); - args.put("gridBoundBox", gridBoundBox); - args.put("iscWfosWanted", iscWfosWanted); - - boolean regSuccess = (Boolean) script.execute("irtReg", args); - if (!regSuccess) { - statusHandler - .error("Error registering site with IRT server. ISC functionality will be unavailable. Check config and IRT connectivity."); - removeShutdownHook(this.mhsID, this.siteID); - } + Map initArgs = new HashMap(2, 1f); + initArgs.put("ancfURL", config.iscRoutingTableAddress().get("ANCF")); + initArgs.put("bncfURL", config.iscRoutingTableAddress().get("BNCF")); + this.script.instantiatePythonClass(PYTHON_INSTANCE, "IrtAccess", + initArgs); + } catch (GfeConfigurationException e) { + throw new RuntimeException("Could not load GFE configuration", e); } catch (JepException e) { - statusHandler - .fatal("Error starting GFE ISC. ISC functionality will be unavailable!!", - e); - } catch (GfeException e) { - statusHandler - .fatal("Unable to get Mhs ID. ISC functionality will be unavailable!!", - e); + throw new RuntimeException( + "Could not instantiate IRT python script instance", e); + } + + try { + // upon any overall failure, start thread over + while (IRTManager.getInstance().isRegistered(mhsID, siteID)) { + try { + // do initial registration, keep trying until successful + while (IRTManager.getInstance().isRegistered(mhsID, siteID)) { + statusHandler + .info("performing initial IRT registration."); + + Map args = new HashMap( + 10, 1f); + args.put("mhsid", mhsID); + args.put("serverHost", serverHost); + args.put("serverPort", serverPort); + args.put("serverProtocol", serverProtocol); + args.put("site", siteID); + args.put("parmsWanted", parmsWanted); + args.put("gridDims", gridDims); + args.put("gridProj", gridProj); + args.put("gridBoundBox", gridBoundBox); + args.put("iscWfosWanted", iscWfosWanted); + Boolean okay = (Boolean) script.execute("register", + PYTHON_INSTANCE, args); + + if (okay) { + break; + } else if (!IRTManager.getInstance().isRegistered( + mhsID, siteID)) { + break; // exit processing loop + } else { + sleep(3 * TimeUtil.MILLIS_PER_SECOND); + } + } + + // if we are here, we had a successful registration, check + // for re-register every few seconds, check the StopIRT flag + // every few seconds + statusHandler.info("initial IRT registration complete."); + while (IRTManager.getInstance().isRegistered(mhsID, siteID)) { + sleep(3 * TimeUtil.MILLIS_PER_SECOND); // wait 3 seconds + + Boolean status1 = (Boolean) script.execute( + "checkForReregister", PYTHON_INSTANCE, null); + if (!status1) { + statusHandler.error("FAIL on checkForRegister()."); + break; // break out of rereg loop, to cause another + // reg + } + } + } catch (Throwable t) { + statusHandler.error("Exception in IRT register thread.", t); + } + } + + // if we get here, we have been told to stop IRT, so we unregister. + // We try only once. + statusHandler.info("FINAL IRT unregister."); + try { + script.execute("unregister", PYTHON_INSTANCE, null); + } catch (JepException e) { + statusHandler.error("Exception unregister IRT.", e); + } + statusHandler.info("FINAL -- exiting IRT registration thread."); } finally { if (script != null) { script.dispose(); diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py index 72512699e9..da97fae738 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py @@ -44,12 +44,11 @@ from com.raytheon.edex.plugin.gfe.isc import IRTManager # to interact better with IscScript. # 05/22/13 1759 dgilling Add missing import to # makeISCrequest(). +# 10/16/13 2475 dgilling Remove unneeded code to handle +# registration with IRT. # # # -# starts the IRT thread and registers. -StopIRT = 0 #flag to shut down the 2nd thread -IRTthread = None #flag to hold the IRTthread object def logEvent(*msg): iscUtil.getLogger("irtServer").info(iscUtil.tupleToString(*msg)) @@ -188,51 +187,6 @@ def putVTECActiveTable(strTable, xmlPacket): except: logProblem("Error executing ingestAT: ", traceback.format_exc()) logEvent("ingesAT command output: ", output) - -def initIRT(ancfURL, bncfURL, mhsid, serverHost, serverPort, serverProtocol, - site, parmsWanted, gridDims, gridProj, gridBoundBox, iscWfosWanted): - global IRTthread - import threading - IRTthread = threading.Thread(target=irtReg, args=[ancfURL, bncfURL, mhsid, - serverHost, serverPort, serverProtocol, site, parmsWanted, gridDims, - gridProj, gridBoundBox, iscWfosWanted]) - IRTthread.setDaemon(True) - IRTthread.start() - -# IRT registration thread -def irtReg(ancfURL, bncfURL, mhsid, serverHost, serverPort, serverProtocol, - site, parmsWanted, gridDims, gridProj, gridBoundBox, iscWfosWanted): - import IrtAccess, threading - irt = IrtAccess.IrtAccess(ancfURL, bncfURL) - - # do initial registration, keep trying until successful - while True: - okay = irt.register(mhsid, serverHost, serverPort, serverProtocol, - site, parmsWanted, gridDims, gridProj, gridBoundBox, iscWfosWanted) - if okay: - break - elif StopIRT: - return False#stop this thread - else: - return False - - # if we are here, we had a successful registration, check for re-register - # every few seconds, check the StopIRT flag every few seconds - while IRTManager.getInstance().isRegistered(mhsid,site) == True: - time.sleep(3.0) #wait 3 seconds - irt.checkForReregister() - - # if we get here, we have been told to stop IRT, so we unregister. We - # try only once. - irt.unregister() - return True - -# call from C++ to Python to tell IRT thread to shut itself down -def irtStop(): - global StopIRT - StopIRT = True #tells irt thread to exit - if IRTthread: - IRTthread.join() #wait till thread returns then return to caller # get servers direct call for IRT def irtGetServers(ancfURL, bncfURL, iscWfosWanted): diff --git a/edexOsgi/com.raytheon.uf.common.base.feature/feature.xml b/edexOsgi/com.raytheon.uf.common.base.feature/feature.xml index 784aa537bb..d50b6099f2 100644 --- a/edexOsgi/com.raytheon.uf.common.base.feature/feature.xml +++ b/edexOsgi/com.raytheon.uf.common.base.feature/feature.xml @@ -399,4 +399,10 @@ install-size="0" version="0.0.0"/> + + diff --git a/edexOsgi/com.raytheon.uf.common.util/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.util/META-INF/MANIFEST.MF index 7ee7146d7c..1562ee23b4 100644 --- a/edexOsgi/com.raytheon.uf.common.util/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.util/META-INF/MANIFEST.MF @@ -8,7 +8,8 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Require-Bundle: org.junit;bundle-version="1.0.0", org.apache.commons.beanutils;bundle-version="1.8.3", com.raytheon.uf.common.status;bundle-version="1.12.1174", - org.apache.commons.lang;bundle-version="2.3.0" + org.apache.commons.lang;bundle-version="2.3.0", + org.apache.commons.io;bundle-version="2.4.0" Export-Package: com.raytheon.uf.common.util, com.raytheon.uf.common.util.algorithm, com.raytheon.uf.common.util.cache, diff --git a/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/FileUtil.java b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/FileUtil.java index f8def3954c..04a99d099c 100644 --- a/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/FileUtil.java +++ b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/FileUtil.java @@ -30,13 +30,14 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; +import org.apache.commons.io.IOUtils; + /** * Contains common file utilities. Methods are generally static to use without a * class instance. Methods in class should not log directly; rather they should @@ -54,11 +55,13 @@ import java.util.zip.GZIPOutputStream; * Jun 28, 2012 0819 djohnson Add write method. * Jul 06, 2012 798 jkorman Added more robust {@link #copyFile}. Added methods * to create temporary directories and files. - * 02/15/2013 #1597 randerso Fixed error when copying empty files + * Feb 15, 2013 1597 randerso Fixed error when copying empty files * Feb 15, 2013 1638 mschenke Moved EOL field from edex.common Util * Mar 11, 2013 1645 djohnson Added file modification watcher. * Mar 14, 2013 1794 djohnson FileUtil.listFiles now returns List. * May 16, 2013 1966 rferrel Add sizeOfDirectory and listDirFiles method. + * Oct 9, 2013 2467 randerso Change coypFile to use apache instead of FileChannel + * to improve memory utilization * * * @@ -74,6 +77,9 @@ public class FileUtil { private static final Pattern VALID_FILENAME = Pattern .compile("^[A-Za-z0-9._\\- ]+$"); + /** + * regex to match both Linux and Windows file separators + */ public final static String fileSeparatorRegex = "[/\\\\]"; /** @@ -134,7 +140,7 @@ public class FileUtil { File entry = entries[i]; // If there is no filter or the filter accepts the // file / directory, add it to the list - if (filter == null || filter.accept(directory, entry.getName())) { + if ((filter == null) || filter.accept(directory, entry.getName())) { files.add(entry); } @@ -152,9 +158,12 @@ public class FileUtil { * List files/directories that match a FileFilter. * * @param directory + * source directory * @param filter + * file filter * @param recurse - * @return + * true to recursively walk the directory tree + * @return list of files in directory matching filter */ public static List listDirFiles(File directory, FileFilter filter, boolean recurse) { @@ -171,7 +180,7 @@ public class FileUtil { // Go over entries for (File entry : entries) { files.add(entry); - if (recurse && filter != null && entry.isDirectory()) { + if (recurse && (filter != null) && entry.isDirectory()) { files.addAll(listDirFiles(entry, filter, recurse)); } } @@ -241,19 +250,7 @@ public class FileUtil { file)); } } else { - - InputStream in = new FileInputStream(source); - OutputStream out = new FileOutputStream(destination); - - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - - in.close(); - out.close(); - + copyFile(source, destination); } } @@ -361,24 +358,13 @@ public class FileUtil { } /** - * Copy a file to a another file. + * Read the contents of a file into a string * - * @param fileToCopy - * The source file. This file reference must exist. - * @param outputFile - * The destination file. This file may exist, if so it will be - * overwritten. + * @param file + * file to be read + * @return string containing the file contents * @throws IOException - * An error occurred while copying the data. - * @throws NullPointerException - * Either the source or target file references are null. */ - public static void copyFile(File fileToCopy, File outputFile) - throws IOException { - // Copy the entire file. - copyFile(fileToCopy, outputFile, 0); - } - public static String file2String(File file) throws IOException { return new String(file2bytes(file)); } @@ -415,8 +401,9 @@ public class FileUtil { // Read in the bytes int offset = 0; int numRead = 0; - while (offset < bytes.length - && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) { + while ((offset < bytes.length) + && ((numRead = is + .read(bytes, offset, bytes.length - offset)) >= 0)) { offset += numRead; } @@ -500,9 +487,9 @@ public class FileUtil { // Read in the bytes int offset = 0; int numRead = 0; - while (offset < bytes.length - && (numRead = is.read(bytes, offset, bytes.length - - offset)) >= 0) { + while ((offset < bytes.length) + && ((numRead = is.read(bytes, offset, bytes.length + - offset)) >= 0)) { offset += numRead; } @@ -546,6 +533,8 @@ public class FileUtil { * The data to store * @param outFile * The file to write this data + * @param compress + * if true file will be compressed using gzip * @throws IOException */ public static void bytes2File(byte[] outBytes, File outFile, @@ -564,7 +553,7 @@ public class FileUtil { // only write out buffer at a time for (int counter = 0; counter < outBytes.length; counter += buffer) { - if ((outBytes.length - counter) - buffer >= 0) { + if (((outBytes.length - counter) - buffer) >= 0) { out.write(outBytes, counter, buffer); } else { out.write(outBytes, counter, (outBytes.length - counter)); @@ -627,7 +616,7 @@ public class FileUtil { String replacement = (File.separatorChar == '\\') ? "\\\\" : File.separator; - if (aPath != null && aPath.length() > 0) { + if ((aPath != null) && (aPath.length() > 0)) { return aPath.replaceAll(fileSeparatorRegex, replacement); } else { return aPath; @@ -643,9 +632,9 @@ public class FileUtil { */ public static String edexPath(String aPath) { - if (aPath != null && aPath.length() > 0) { + if ((aPath != null) && (aPath.length() > 0)) { // Remove drive letter - if (aPath.length() > 1 && aPath.charAt(1) == ':') { + if ((aPath.length() > 1) && (aPath.charAt(1) == ':')) { aPath = aPath.substring(2); } return aPath.replace("\\", "/"); @@ -683,92 +672,68 @@ public class FileUtil { } /** - * Copy a file from one location to another. The file copy may begin at some - * specified position within the source file. + * Copy a file to another file. * * @param source * The source file. This file reference must exist. - * @param target + * @param destination * The destination file. This file may exist, if so it will be * overwritten. - * @param position - * The start position within the source file where the copy - * operation will begin. The position must be greater than or - * equal to zero, and less than the file length of the source. - * @return Was the required data copied to the target file. * @throws IOException * An error occurred while copying the data. * @throws IllegalArgumentException - * The position is less than zero or greater than the length of - * the source file or either of the source, target files are - * null. + * Either the source or target file references are null. */ - public static boolean copyFile(File source, File target, int position) + public static void copyFile(File source, File destination) throws IOException { - boolean status = false; - if (source != null) { - if (target != null) { - if ((position >= 0) && (position <= source.length())) { - FileInputStream fis = null; - FileOutputStream fos = null; - try { - fis = new FileInputStream(source); - FileChannel fci = fis.getChannel(); - - fos = new FileOutputStream(target); - FileChannel fco = fos.getChannel(); - - long count = source.length() - position; - - long transfered = fci.transferTo(position, count, fco); - // ensure we copied all of the data. - status = (transfered == count); - } finally { - String cause = null; - try { - close(fis); - } catch (IOException e) { - cause = String.format( - "copyFile.source.close[%s][%s]", e - .getClass().getName(), e - .getMessage()); - } - try { - close(fos); - } catch (IOException e) { - if (cause == null) { - cause = String.format( - "copyFile.target.close[%s][%s]", e - .getClass().getName(), e - .getMessage()); - } else { - cause = String.format( - "%s copyFile.target.close[%s][%s]", - cause, e.getClass().getName(), - e.getMessage()); - } - } - // One or more closes failed. Construct and throw an - // exception. - if (cause != null) { - throw new IOException(cause); - } - } - } else { - String msg = String.format( - "position [%d] is out of range. Max is [%d]", - position, source.length()); - throw new IllegalArgumentException(msg); - } - } else { - throw new IllegalArgumentException( - "target file reference is null"); - } - } else { + if (source == null) { throw new IllegalArgumentException("source file reference is null"); } - return status; + + if (destination == null) { + throw new IllegalArgumentException("target file reference is null"); + } + + FileInputStream fis = null; + FileOutputStream fos = null; + IOException exception = null; + try { + fis = new FileInputStream(source); + fos = new FileOutputStream(destination); + + IOUtils.copyLarge(fis, fos); + + } catch (IOException e) { + // close the output stream ignoring any exceptions + close(fos); + fos = null; + + // remove the invalid destination file + destination.delete(); + + exception = new IOException(String.format("Error copying %s to %s", + source.getCanonicalPath(), destination.getCanonicalPath()), + e); + } finally { + // close destination and source files reporting first exception + + IOException e = close(fos); + if ((exception == null) && (e != null)) { + exception = new IOException(String.format("Error closing %s", + destination.getCanonicalPath()), e); + } + + e = close(fis); + if ((exception == null) && (e != null)) { + exception = new IOException(String.format("Error closing %s", + source.getCanonicalPath()), e); + } + + if (exception != null) { + throw exception; + } + } } /** @@ -887,13 +852,17 @@ public class FileUtil { * * @param c * An object that needs to be closed. - * @throws IOException - * An error occurred attempting to close the object. + * @return IOException if one occurs or null */ - public static void close(Closeable c) throws IOException { + private static IOException close(Closeable c) { if (c != null) { - c.close(); + try { + c.close(); + } catch (IOException e) { + return e; + } } + return null; } /** diff --git a/edexOsgi/com.raytheon.uf.edex.archive.feature/feature.xml b/edexOsgi/com.raytheon.uf.edex.archive.feature/feature.xml index 183ef5d428..053c312b77 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive.feature/feature.xml +++ b/edexOsgi/com.raytheon.uf.edex.archive.feature/feature.xml @@ -31,10 +31,4 @@ version="0.0.0" unpack="false"/> - - diff --git a/rpms/build/i386/build.sh b/rpms/build/i386/build.sh index 924ea5d820..9ee32c3e1c 100644 --- a/rpms/build/i386/build.sh +++ b/rpms/build/i386/build.sh @@ -85,7 +85,6 @@ if [ "${2}" = "-nobinlightning" ]; then fi if [ "${1}" = "-python-qpid" ]; then - buildRPM "awips2" buildRPM "awips2-python-qpid" buildRPM "awips2-python" buildRPM "awips2-python-cherrypy" @@ -116,15 +115,6 @@ if [ "${1}" = "-python-qpid" ]; then exit 1 fi - #buildRPM "awips2-ant" - #unpackHttpdPypies - if [ $? -ne 0 ]; then - exit 1 - fi - #buildRPM "awips2-httpd-pypies" - #buildRPM "awips2-java" - #buildRPM "awips2-ldm" - #buildRPM "awips2-tools" buildRPM "awips2-python-shapely" exit 0 @@ -157,7 +147,6 @@ if [ "${1}" = "-delta" ]; then exit 1 fi - buildRPM "awips2" buildRPM "awips2-ncep-database" buildRPM "awips2-gfesuite-client" buildRPM "awips2-gfesuite-server" @@ -173,7 +162,6 @@ if [ "${1}" = "-delta" ]; then buildRPM "awips2-database-server-configuration" buildRPM "awips2-database-standalone-configuration" buildRPM "awips2-data.hdf5-gfe.climo" - buildRPM "awips2-hydroapps-shared" buildRPM "awips2-localapps-environment" buildRPM "awips2-maps-database" buildRPM "awips2-notification" @@ -181,7 +169,6 @@ if [ "${1}" = "-delta" ]; then buildRPM "awips2-data.hdf5-topo" buildRPM "awips2-data.gfe" buildRPM "awips2-rcm" - buildRPM "awips2-edex-environment" buildLocalizationRPMs if [ $? -ne 0 ]; then exit 1 @@ -222,8 +209,8 @@ if [ "${1}" = "-full" ]; then buildRPM "awips2-python-werkzeug" buildRPM "awips2-python-pygtk" buildRPM "awips2-python-pycairo" + buildRPM "awips2-python-shapely" - buildRPM "awips2" buildRPM "awips2-adapt-native" buildRPM "awips2-aviation-shared" buildRPM "awips2-cli" @@ -260,14 +247,11 @@ if [ "${1}" = "-full" ]; then buildRPM "awips2-httpd-pypies" buildJava buildRPM "awips2-groovy" - #buildRPM "awips2-ldm" buildRPM "awips2-postgres" buildRPM "awips2-pgadmin3" buildRPM "awips2-tools" - buildRPM "awips2-edex-environment" buildRPM "awips2-openfire" buildRPM "awips2-httpd-collaboration" - buildRPM "awips2-python-shapely" exit 0 fi @@ -347,9 +331,6 @@ if [ "${1}" = "-ade" ]; then fi if [ "${1}" = "-viz" ]; then - buildRPM "awips2-common-base" - buildRPM "awips2-rcm" - buildRPM "awips2-hydroapps-shared" buildCAVE if [ $? -ne 0 ]; then exit 1 @@ -360,13 +341,9 @@ if [ "${1}" = "-viz" ]; then fi if [ "${1}" = "-edex" ]; then - buildRPM "awips2-common-base" - buildRPM "awips2-adapt-native" buildRPM "awips2-gfesuite-client" buildRPM "awips2-gfesuite-server" buildRPM "awips2-edex-environment" - # buildRPM "awips2-ncep-database" - # buildRPM "awips2-python-dynamicserialize" buildEDEX if [ $? -ne 0 ]; then exit 1 @@ -415,6 +392,11 @@ if [ "${1}" = "-custom" ]; then buildRPM "awips2-httpd-pypies" buildRPM "awips2-adapt-native" buildRPM "awips2-hydroapps-shared" + buildRPM "awips2-common-base" + buildRPM "awips2-rcm" + #buildRPM "awips2-ant" + #buildRPM "awips2-java" + #buildRPM "awips2-tools" exit 0 fi diff --git a/rpms/build/x86_64/build.sh b/rpms/build/x86_64/build.sh index c1ac1b921a..82b3bb8fc1 100644 --- a/rpms/build/x86_64/build.sh +++ b/rpms/build/x86_64/build.sh @@ -247,6 +247,7 @@ fi if [ "${1}" = "-edex" ]; then buildRPM "awips2-common-base" + buildRPM "awips2-edex-environment" buildEDEX if [ $? -ne 0 ]; then exit 1 @@ -286,6 +287,9 @@ if [ "${1}" = "-custom" ]; then buildRPM "awips2-httpd-pypies" buildRPM "awips2-adapt-native" buildRPM "awips2-hydroapps-shared" + #buildRPM "awips2-ant" + #buildRPM "awips2-java" + #buildRPM "awips2-tools" exit 0 fi diff --git a/rpms/build/x86_64/build.sh-10172013 b/rpms/build/x86_64/build.sh-10172013 new file mode 100644 index 0000000000..c1ac1b921a --- /dev/null +++ b/rpms/build/x86_64/build.sh-10172013 @@ -0,0 +1,333 @@ +#!/bin/bash + +function buildRPM() +{ + # Arguments: + # ${1} == the name of the rpm. + lookupRPM "${1}" + if [ $? -ne 0 ]; then + echo "ERROR: '${1}' is not a recognized AWIPS II RPM." + exit 1 + fi + + /usr/bin/rpmbuild -ba \ + --define '_topdir %(echo ${AWIPSII_TOP_DIR})' \ + --define '_baseline_workspace %(echo ${WORKSPACE})' \ + --define '_uframe_eclipse %(echo ${UFRAME_ECLIPSE})' \ + --define '_awipscm_share %(echo ${AWIPSCM_SHARE})' \ + --define '_build_root %(echo ${AWIPSII_BUILD_ROOT})' \ + --define '_component_version %(echo ${AWIPSII_VERSION})' \ + --define '_component_release %(echo ${AWIPSII_RELEASE})' \ + --define '_component_build_date %(echo ${COMPONENT_BUILD_DATE})' \ + --define '_component_build_time %(echo ${COMPONENT_BUILD_TIME})' \ + --define '_component_build_system %(echo ${COMPONENT_BUILD_SYSTEM})' \ + --buildroot ${AWIPSII_BUILD_ROOT} \ + ${RPM_SPECIFICATION}/component.spec + if [ $? -ne 0 ]; then + echo "ERROR: Failed to build RPM ${1}." + exit 1 + fi + + return 0 +} + +# This script will build all of the 64-bit rpms. +# Ensure that we are on a machine with the correct architecture. + +architecture=`uname -i` +if [ ! "${architecture}" = "x86_64" ]; then + echo "ERROR: This build can only be performed on a 64-bit Operating System." + exit 1 +fi + +# Determine which directory we are running from. +path_to_script=`readlink -f $0` +dir=$(dirname $path_to_script) + +common_dir=`cd ${dir}/../common; pwd;` +if [ $? -ne 0 ]; then + echo "ERROR: Unable to find the common functions directory." + exit 1 +fi +# source the common functions. +source ${common_dir}/lookupRPM.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to source the common functions." + exit 1 +fi +source ${common_dir}/usage.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to source the common functions." + exit 1 +fi +source ${common_dir}/rpms.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to source the common functions." + exit 1 +fi +source ${common_dir}/systemInfo.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to retrieve the system information." + exit 1 +fi + +# prepare the build environment. +source ${dir}/buildEnvironment.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to prepare the build environment." + exit 1 +fi + +export LIGHTNING=true +# Determine if the optional '-nobinlightning' argument has been specified. +if [ "${2}" = "-nobinlightning" ]; then + LIGHTNING=false +fi + +if [ "${1}" = "-64bit" ]; then + buildRPM "awips2-common-base" + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-python" + buildRPM "awips2-python-cherrypy" + buildRPM "awips2-python-dynamicserialize" + buildRPM "awips2-python-h5py" + buildRPM "awips2-python-jimporter" + buildRPM "awips2-python-matplotlib" + buildRPM "awips2-python-nose" + buildRPM "awips2-python-numpy" + buildRPM "awips2-python-pil" + buildRPM "awips2-python-pmw" + buildRPM "awips2-python-pupynere" + buildRPM "awips2-python-qpid" + buildRPM "awips2-python-scientific" + buildRPM "awips2-python-scipy" + buildRPM "awips2-python-tables" + buildRPM "awips2-python-thrift" + buildRPM "awips2-python-tpg" + buildRPM "awips2-python-ufpy" + buildRPM "awips2-python-werkzeug" + buildRPM "awips2-python-pygtk" + buildRPM "awips2-python-pycairo" + buildJava + buildRPM "awips2-python-shapely" + buildRPM "awips2-notification" + + exit 0 +fi + +if [ "${1}" = "-postgres" ]; then + buildRPM "awips2-postgres" + buildRPM "awips2-database-server-configuration" + buildRPM "awips2-database-standalone-configuration" + buildRPM "awips2-database" + buildRPM "awips2-maps-database" + buildRPM "awips2-ncep-database" + buildRPM "awips2-pgadmin3" + + exit 0 +fi + +if [ "${1}" = "-delta" ]; then + buildRPM "awips2-common-base" + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + buildEDEX + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-python-dynamicserialize" + buildRPM "awips2-python-ufpy" + buildRPM "awips2-cli" + buildRPM "awips2-data.hdf5-gfe.climo" + buildRPM "awips2-gfesuite-client" + buildRPM "awips2-gfesuite-server" + buildRPM "awips2-localapps-environment" + buildRPM "awips2-data.hdf5-topo" + buildRPM "awips2-data.gfe" + buildLocalizationRPMs + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-edex-environment" + buildRPM "awips2-notification" + + exit 0 +fi + +if [ "${1}" = "-full" ]; then + buildRPM "awips2-common-base" + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + buildEDEX + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-python" + buildRPM "awips2-python-cherrypy" + buildRPM "awips2-python-dynamicserialize" + buildRPM "awips2-python-h5py" + buildRPM "awips2-python-jimporter" + buildRPM "awips2-python-matplotlib" + buildRPM "awips2-python-nose" + buildRPM "awips2-python-numpy" + buildRPM "awips2-python-pil" + buildRPM "awips2-python-pmw" + buildRPM "awips2-python-pupynere" + buildRPM "awips2-python-qpid" + buildRPM "awips2-python-scientific" + buildRPM "awips2-python-scipy" + buildRPM "awips2-python-tables" + buildRPM "awips2-python-thrift" + buildRPM "awips2-python-tpg" + buildRPM "awips2-python-ufpy" + buildRPM "awips2-python-werkzeug" + buildRPM "awips2-python-pygtk" + buildRPM "awips2-python-pycairo" + buildRPM "awips2-cli" + buildRPM "awips2-data.hdf5-gfe.climo" + buildRPM "awips2-gfesuite-client" + buildRPM "awips2-gfesuite-server" + buildRPM "awips2-localapps-environment" + buildRPM "awips2-data.hdf5-topo" + buildRPM "awips2-data.gfe" + unpackHttpdPypies + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-httpd-pypies" + buildJava + buildRPM "awips2-groovy" + buildLocalizationRPMs + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-edex-environment" + buildRPM "awips2-notification" + buildRPM "awips2-python-shapely" + buildRPM "awips2-postgres" + buildRPM "awips2-database" + buildRPM "awips2-maps-database" + buildRPM "awips2-ncep-database" + buildRPM "awips2-pgadmin3" + buildRPM "awips2-ldm" + exit 0 +fi + +if [ "${1}" = "-ade" ]; then + echo "INFO: AWIPS II currently does not support a 64-bit version of the ADE." + exit 0 + buildRPM "awips2-eclipse" + + exit 0 +fi + +if [ "${1}" = "-viz" ]; then + buildRPM "awips2-common-base" + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + + exit 0 +fi + +if [ "${1}" = "-edex" ]; then + buildRPM "awips2-common-base" + buildEDEX + if [ $? -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + +if [ "${1}" = "-qpid" ]; then + buildQPID + if [ $? -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + +if [ "${1}" = "-ldm" ]; then + buildRPM "awips2-ldm" + + exit 0 +fi + + +if [ "${1}" = "-awips2" ]; then + buildRPM "awips2" + + exit 0 +fi + +# Use the custom flag for selecting specific rpms to build +if [ "${1}" = "-custom" ]; then + unpackHttpdPypies + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-httpd-pypies" + buildRPM "awips2-adapt-native" + buildRPM "awips2-hydroapps-shared" + + exit 0 +fi + + +if [ "${1}" = "-package" ]; then + repository_directory="awips2-repository-${AWIPSII_VERSION}-${AWIPSII_RELEASE}" + if [ -d ${WORKSPACE}/${repository_directory} ]; then + rm -rf ${WORKSPACE}/${repository_directory} + if [ $? -ne 0 ]; then + exit 1 + fi + fi + mkdir -p ${WORKSPACE}/${repository_directory}/${AWIPSII_VERSION}-${AWIPSII_RELEASE} + if [ $? -ne 0 ]; then + exit 1 + fi + + cp -r ${AWIPSII_TOP_DIR}/RPMS/* \ + ${WORKSPACE}/${repository_directory}/${AWIPSII_VERSION}-${AWIPSII_RELEASE} + if [ $? -ne 0 ]; then + exit 1 + fi + + rpms_directory="${WORKSPACE}/rpms" + comps_xml="${rpms_directory}/common/yum/arch.x86_64/comps.xml" + cp -v ${comps_xml} ${WORKSPACE}/${repository_directory} + if [ $? -ne 0 ]; then + exit 1 + fi + + pushd . > /dev/null + cd ${WORKSPACE} + tar -cvf ${repository_directory}.tar ${repository_directory} + RC=$? + popd > /dev/null + if [ ${RC} -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + +usage +exit 0 From a2442a8e391d91c2216a710437fbf68f27cdbcea Mon Sep 17 00:00:00 2001 From: Steve Harris Date: Fri, 25 Oct 2013 10:06:56 -0400 Subject: [PATCH 08/26] 13.5.2-13 baseline Former-commit-id: e755dbb114c6524ee141fd98017e82b154c7bc2c [formerly ba50a26e70c799b4e408f3ba1892504115a38088] [formerly 2100a150137253b063b09785d3936e058ce64743] [formerly e7b17020325256532d7a84516033934dfc734765 [formerly 2100a150137253b063b09785d3936e058ce64743 [formerly f931b3b75bd2581c8942b43d73dff02de4362ecf]]] Former-commit-id: e7b17020325256532d7a84516033934dfc734765 Former-commit-id: 96aa43a7d3c8df257077a396b7cc0804a594105a [formerly bc3eff506b41bfb016bb3398e3e205b37d03cbc8] Former-commit-id: 96c50ba3946393169b213c3ea180321bd3e2387f --- .../uf/common/monitor/config/MonitorConfigurationManager.java | 4 ++-- .../lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id | 2 +- .../lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id | 2 +- rpms/build/i386/build.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java b/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java index 35096de150..aec3938960 100644 --- a/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java +++ b/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java @@ -212,14 +212,14 @@ public abstract class MonitorConfigurationManager { if (!adjacentAreaFileExists) { AdjacentWfoMgr adjMgr = new AdjacentWfoMgr(currentSite); List zones = adjMgr.getAdjZones(); - if (zones.isEmpty()) { + if (!zones.isEmpty()) { for (String zone : zones) { AreaIdXML zoneXml = new AreaIdXML(); zoneXml.setAreaId(zone); zoneXml.setType(ZoneType.REGULAR); List stations = MonitorAreaUtils .getZoneReportingStationXMLs(zone); - if (stations.isEmpty()) { + if (!stations.isEmpty()) { for (StationIdXML station : stations) { zoneXml.addStationIdXml(station); } diff --git a/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id b/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id index 2291591ae6..7b5e854ce1 100644 --- a/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id +++ b/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id @@ -1 +1 @@ -2d8d4c03270ef631f167570cf0c03461ff832fea \ No newline at end of file +759799451b20c427bdaa8cb8185b9602cc66c6c6 \ No newline at end of file diff --git a/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id b/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id index 2291591ae6..7b5e854ce1 100644 --- a/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id +++ b/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id @@ -1 +1 @@ -2d8d4c03270ef631f167570cf0c03461ff832fea \ No newline at end of file +759799451b20c427bdaa8cb8185b9602cc66c6c6 \ No newline at end of file diff --git a/rpms/build/i386/build.sh b/rpms/build/i386/build.sh index 9ee32c3e1c..3cbff01ce3 100644 --- a/rpms/build/i386/build.sh +++ b/rpms/build/i386/build.sh @@ -393,7 +393,7 @@ if [ "${1}" = "-custom" ]; then buildRPM "awips2-adapt-native" buildRPM "awips2-hydroapps-shared" buildRPM "awips2-common-base" - buildRPM "awips2-rcm" + #buildRPM "awips2-rcm" #buildRPM "awips2-ant" #buildRPM "awips2-java" #buildRPM "awips2-tools" From a8366bfc312325386647f6d58b93de7c2b63f607 Mon Sep 17 00:00:00 2001 From: Roger Ferrel Date: Fri, 25 Oct 2013 11:16:22 -0500 Subject: [PATCH 09/26] Issue #2249 availableTime now always return non-empty list. Change-Id: Id0afee6e7673ff0eb062dc2deebacd89fece78ec Former-commit-id: dea388b7746018ee167a3775d43c4d5c7a441c95 [formerly b12987b714ae15775e250222bb8610f9c71f1fb0] [formerly dc846b2f2c236bf1c13467576620c5aad94bdfd1] [formerly 4528b03c702d899e321419d221e0675f9f6db253 [formerly dc846b2f2c236bf1c13467576620c5aad94bdfd1 [formerly d29c0635c08e75cb956cf415ffcdfacd53c53fd8]]] Former-commit-id: 4528b03c702d899e321419d221e0675f9f6db253 Former-commit-id: 74b3ee81ce861235a91c4cc2dce5d557570f65b1 [formerly 4c61794a6fc217c11e85f16d7537f3ed477dc1b2] Former-commit-id: 550138a28a36ada4bdf2a2cb5d346d595b6c0451 --- .../viz/warnings/rsc/WWAResourceData.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java index 36d956dc14..76c3d33e99 100644 --- a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java +++ b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java @@ -20,8 +20,8 @@ import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.dataquery.responses.DbQueryResponse; import com.raytheon.uf.common.time.BinOffset; import com.raytheon.uf.common.time.DataTime; -import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.requests.ThriftClient; import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData; @@ -40,6 +40,7 @@ import com.raytheon.viz.core.mode.CAVEMode; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * May 3, 2011 jsanchez Initial creation + * Oct 25, 2013 2249 rferrel getAvailableTimes always returns a non-empty list. * * * @@ -143,11 +144,19 @@ public class WWAResourceData extends AbstractRequestableResourceData { && phenSig.getConstraintValue().contains(".A") ? getWatchStartTimes(warnings) : getWarningStartTimes(warnings); - if (SimulatedTime.getSystemTime().isRealTime()) { - // Add the current time to the end of the array. - startTimes - .add(new DataTime(SimulatedTime.getSystemTime().getTime())); - } + // DR2249 + // When not in real time the commented code allows availableTimes to be + // empty. This causes Null pointer exceptions when getting frames. If + // always placing non-realtime causes other problems may want to add + // only when startTimes is empty: + // if (SimulatedTime.getSystemTime().isRealTime()) { + // // Add the current time to the end of the array. + // startTimes.add(new + // DataTime(SimulatedTime.getSystemTime().getTime())); + // } + + // Add current configured system time. + startTimes.add(new DataTime(TimeUtil.newDate())); DataTime[] availableTimes = startTimes.toArray(new DataTime[startTimes .size()]); From 2fbc08d837e776d4d5736855c212ac6bf3fb6f47 Mon Sep 17 00:00:00 2001 From: Steve Harris Date: Mon, 28 Oct 2013 10:30:57 -0400 Subject: [PATCH 10/26] 13.5.3-1 baseline Former-commit-id: 9577afee9e309f882168faba2d7ced01a6fab477 [formerly 059083170dc8e7a0fd26704f7a7c38c8626e1856] [formerly 1d8a2026f65df0e617bf98c726778d03aee4590a] [formerly 30f65c28584dd4787f67abd137bc01bfe951e31b [formerly 1d8a2026f65df0e617bf98c726778d03aee4590a [formerly 04f39d579bad5ebfee1e6ff9e75f49a9ed679f8e]]] Former-commit-id: 30f65c28584dd4787f67abd137bc01bfe951e31b Former-commit-id: 2948c5d853c374ea9e8651c7b440ddb4ecbec60c [formerly 9df3027bf0045ffb1603eea9027b9ebbcac311cd] Former-commit-id: 06f5dcf80153d357896b2bfcda1b89bcd3a056e1 --- .../linux/cave/awips2VisualizeUtility.sh | 153 ++++++- .../styleRules/d2dContourStyleRules.xml | 4 +- .../viz/monitor/ffmp/ui/rsc/FFMPResource.java | 8 +- .../aviation/editor/TafViewerEditorDlg.java | 111 ++++- .../stationprofile/StationProfileDlg.java | 22 +- .../postProcessModels/postProcessedModels.xml | 2 +- .../config/MonitorConfigurationManager.java | 4 +- .../library.ohd.pproc.so.REMOVED.git-id | 2 +- .../library.ohd.pproc.so.REMOVED.git-id | 2 +- rpms/build/i386/build.sh | 2 +- ...h-keep-10032013 => build.sh-keep-10212013} | 38 +- rpms/build/i386/build.sh_old | 423 ------------------ 12 files changed, 280 insertions(+), 491 deletions(-) mode change 100755 => 100644 cave/build/static/linux/cave/awips2VisualizeUtility.sh rename rpms/build/i386/{build.sh-keep-10032013 => build.sh-keep-10212013} (96%) delete mode 100644 rpms/build/i386/build.sh_old diff --git a/cave/build/static/linux/cave/awips2VisualizeUtility.sh b/cave/build/static/linux/cave/awips2VisualizeUtility.sh old mode 100755 new mode 100644 index a10f6bed20..5f6ab56892 --- a/cave/build/static/linux/cave/awips2VisualizeUtility.sh +++ b/cave/build/static/linux/cave/awips2VisualizeUtility.sh @@ -1,37 +1,150 @@ #!/bin/bash +# +# +# 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. +# -# This script will kill any running AlertViz and/or -# CAVE processes whenever the user logs off. +# SOFTWARE HISTORY +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# July 10 2013 DR 16111 dhuffman Initial creation +# +# +# @author dhuffman +# @version 1.0 + + + +# This script will kill any running AlertViz and/or Cave +# processes when a user logs off. if [ ! -f ${HOME}/vizUtility.log ]; then - touch ${HOME}/vizUtility.log + touch ${HOME}/vizUtility.log else - echo "" >> ${HOME}/vizUtility.log + echo "" >> ${HOME}/vizUtility.log fi -# Find all CAVE processes. +date >> ${HOME}/vizUtility.log + +function findAlertvizProcesses { +# Find all the alertviz processes. +echo "Searching for alertviz processes." >> ${HOME}/vizUtility.log +zpid=` ps u -u $USER | grep '[a]lertviz' | awk '{print $2}' ` +npid=` echo $zpid | wc -w ` +if [ $npid -le 0 ] +then + echo "There are no alertviz processes found." >> ${HOME}/vizUtility.log + date >> ${HOME}/vizUtility.log +fi +} + +function findAlertvizShProcesses { +# Find all the alertviz.sh processes. +echo "Searching for alertviz.sh processes." >> ${HOME}/vizUtility.log +zpid=` ps u -u $USER | grep '[a]lertviz.sh' | awk '{print $2}' ` +npid=` echo $zpid | wc -w ` +if [ $npid -le 0 ] +then + echo "There are no alertviz.sh processes found." >> ${HOME}/vizUtility.log + date >> ${HOME}/vizUtility.log +fi +} + +function findCaveProcesses { +# Find all the Cave processes. echo "Searching for cave processes." >> ${HOME}/vizUtility.log -for pid in `ps aux | grep [c]ave | awk '{print $2}'`; +zpid=` ps u -u $USER | grep '[c]ave' | awk '{print $2}' ` +npid=` echo $zpid | wc -w ` +if [ $npid -le 0 ] +then + echo "There are no cave processes found." >> ${HOME}/vizUtility.log + date >> ${HOME}/vizUtility.log +fi +} + + +# First let's attempt to kill the processes quickly which will work if the computer is not burdened. +findAlertvizShProcesses +for pid in $zpid do - kill -9 ${pid} - echo "Killing 'cave' process with pid ${pid}." >> ${HOME}/vizUtility.log + echo "Attempting to kill 'alertviz.sh' process with pid ${pid}." >> ${HOME}/vizUtility.log + kill ${pid} 2>> ${HOME}/vizUtility.log done -# Find the alertviz.sh script. -echo "Searching for the alertviz.sh script." >> ${HOME}/vizUtility.log -for pid in `ps aux | grep [a]lertviz.sh | awk '{print $2}'`; +findAlertvizProcesses +for pid in $zpid do - kill -9 ${pid} - echo "Killing 'alertviz.sh' process with pid ${pid}." >> ${HOME}/vizUtility.log + echo "Attempting to kill 'alertviz' process with pid ${pid}." >> ${HOME}/vizUtility.log + kill ${pid} 2>> ${HOME}/vizUtility.log done -# Find the AlertViz process. -echo "Searching for the alertviz process." >> ${HOME}/vizUtility.log -for pid in `ps aux | grep [a]lertviz | awk '{print $2}'`; +findCaveProcesses +for pid in $zpid do - kill -9 ${pid} - echo "Killing 'alertviz' process with pid ${pid}." >> ${HOME}/vizUtility.log + echo "Attempting to kill 'cave' process with pid ${pid}." >> ${HOME}/vizUtility.log + kill ${pid} 2>> ${HOME}/vizUtility.log done -echo "FINISHED" >> ${HOME}/vizUtility.log -exit 0 + +# Second let's be resolute in our assurances that these processes are killed. +# Please review the paperwork included in DR 16111 for an unabridged explanation. +findAlertvizShProcesses +# Lets loop until we are sure all the alertviz.sh processes are killed or we +# have looped too many times. +ntoomany=2002 +while [[ $npid -ne 0 && $ntoomany -ne 0 ]] +do + for pid in $zpid + do + echo "Attempting to kill 'alertviz.sh' process with pid ${pid}." >> ${HOME}/vizUtility.log + kill -9 ${pid} 2>> ${HOME}/vizUtility.log + done + npid=0 + ((ntoomany-=1)) + if [ $ntoomany -le 1 ] + then + echo "The kill alertviz portion of this script $0 has been unable preform its duties. 02" >> ${HOME}/vizUtility.log + break + fi + sleep 1 + findAlertvizShProcesses +done + +# Let's give the SIGTERM a chance if it has not had enough time yet. +sleep 1 +findAlertvizProcesses +for pid in $zpid +do + echo "Attempting to kill 'alertviz' process with pid ${pid}." >> ${HOME}/vizUtility.log + kill -9 ${pid} 2>> ${HOME}/vizUtility.log +done + + +findCaveProcesses +for pid in $zpid +do + echo "Attempting to kill 'cave' process with pid ${pid}." >> ${HOME}/vizUtility.log + kill -9 ${pid} 2>> ${HOME}/vizUtility.log +done + + +date >> ${HOME}/vizUtility.log +echo >> ${HOME}/vizUtility.log + + diff --git a/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dContourStyleRules.xml b/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dContourStyleRules.xml index 235dace2f5..8b18e14e74 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dContourStyleRules.xml +++ b/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dContourStyleRules.xml @@ -1027,8 +1027,8 @@ in|.0394|.0| 4 | |f5.2|@.|8000F0FF| |13|\ --> - TP24hr - TP36hr + TP24hr + TP36hr in diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java index ecde5a4e10..527cf9e83f 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java @@ -172,9 +172,9 @@ import com.vividsolutions.jts.geom.Point; * Jun 27, 2013 2152 njensen More thorough disposeInternal() * Jul 15, 2013 2184 dhladky Remove all HUC's for storage except ALL * Jul 17, 2013 2197 njensen Improved speed of getName() + * Oct 18, 2013 DR 16151 gzhang Used getAverageValue() for QPF Graph. * * - * * @author dhladky * @version 1.0 */ @@ -3157,9 +3157,9 @@ public class FFMPResource extends getDataKey(), null, oldestRefTime, FFMPRecord.ALL, basinPfaf); - Float qpfFloat = qpfBasin.getValue(monitor.getQpfWindow() - .getBeforeTime(), monitor.getQpfWindow().getAfterTime()); - + //Float qpfFloat = qpfBasin.getValue(monitor.getQpfWindow() + //.getBeforeTime(), monitor.getQpfWindow().getAfterTime()); + Float qpfFloat = qpfBasin.getAverageValue(monitor.getQpfWindow().getAfterTime(),monitor.getQpfWindow().getBeforeTime() ); // DR 16151 fgd.setQpfValue(qpfFloat); ArrayList qpfTimes = new ArrayList(); diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java index de9d6c8804..419d1c11df 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java @@ -224,6 +224,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback; * 10/15/2012 1229 rferrel Changes for non-blocking HelpUsageDlg. * 11/05/2012 15477 zhao Trim blank lines in text in Editor when check Syntax * 01/09/2013 15528 zhao Modified saveFile() and restoreFile() + * 10/24/2013 16478 zhao add syntax check for extra '=' sign * * * @@ -1959,7 +1960,7 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable, configMgr.setDefaultFontAndColors(applyBtn); applyBtn.addSelectionListener(new SelectionAdapter() { @Override - public void widgetSelected(SelectionEvent event) { + public void widgetSelected(SelectionEvent event) { if (editorTafTabComp.getTextEditorControl().getText() != null && !editorTafTabComp.getTextEditorControl().getText() .isEmpty()) { @@ -1972,6 +1973,13 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable, String toolName = toolsCbo.getItem(toolsCbo .getSelectionIndex()); String bbb = editorTafTabComp.getBBB(); + + // DR166478 + if ( toolName.equals("UseMetarForPrevailing") ) { + if ( checkBasicSyntaxError(true) ) { + return; + } + } // Setup for python request AvnSmartToolRequest req = new AvnSmartToolRequest(); @@ -2037,7 +2045,106 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable, return editorComp; } - private void syntaxCheck() { + /** + * + * @param doLogMessage + * @return true if error found, otherwise false + */ + private boolean checkBasicSyntaxError(boolean doLogMessage) { + + String in = editorTafTabComp.getTextEditorControl().getText(); + + clearSyntaxErrorLevel(); + + st = editorTafTabComp.getTextEditorControl(); + + final Map syntaxMap = new HashMap(); + + st.addMouseTrackListener(new MouseTrackAdapter() { + @Override + public void mouseHover(MouseEvent e) { + st = editorTafTabComp.getTextEditorControl(); + Point p = new Point(e.x, e.y); + try { + int offset = st.getOffsetAtLocation(p); + StyleRange[] srs = st.getStyleRanges(); + StyleRange sr = null; + for (StyleRange range : srs) { + if (offset >= range.start + && offset <= (range.start + range.length)) { + sr = range; + break; + } + } + if (sr != null) { + if (syntaxMap != null) { + st.setToolTipText(syntaxMap.get(sr)); + } + } else { + st.setToolTipText(null); + } + } catch (Exception ex) { + st.setToolTipText(null); + } + } + }); + + int tafIndex = in.indexOf("TAF"); + int equalSignIndex = in.indexOf("="); + int lastEqualSignIndex = equalSignIndex; + + if ( tafIndex < 0 && equalSignIndex < 0 ) { // empty TAF + return false; + } + + while (tafIndex > -1 || equalSignIndex > -1) { + + if ( tafIndex == -1 || tafIndex > equalSignIndex ) { + + int lineIndexOfFirstEqualSign = st.getLineAtOffset(lastEqualSignIndex); + int lineIndexOfSecondEqualSign = st.getLineAtOffset(equalSignIndex); + if ( lineIndexOfFirstEqualSign == lineIndexOfSecondEqualSign ) { + StyleRange sr = new StyleRange(lastEqualSignIndex,1,null,qcColors[3]); + String msg = "Syntax error: there is an extra '=' sign in this line"; + syntaxMap.put(sr, msg); + st.setStyleRange(null); + st.setStyleRange(sr); + if (doLogMessage) { + msgStatComp.setMessageText(msg, qcColors[3].getRGB()); + } + return true; + } + + int startIndex = lastEqualSignIndex; + + while ( !in.substring(startIndex,startIndex+1).matches("[A-Z]") && !in.substring(startIndex,startIndex+1).matches("[0-9]") ) { + startIndex++; + } + int length = 6; + if ( (equalSignIndex-startIndex) < 6 ) { + length = equalSignIndex-startIndex; + } + StyleRange sr = new StyleRange(startIndex,length,null,qcColors[3]); + String msg = "Syntax error: There is an extra '=' sign before this point, or 'TAF' is missing at beginning of TAF"; + syntaxMap.put(sr, msg); + st.setStyleRange(null); + st.setStyleRange(sr); + if (doLogMessage) { + msgStatComp.setMessageText(msg, qcColors[3].getRGB()); + } + + return true; + } + + tafIndex = in.indexOf("TAF", tafIndex+1); + lastEqualSignIndex = equalSignIndex; + equalSignIndex = in.indexOf("=", equalSignIndex+1); + } + + return false; + } + + private void syntaxCheck() { // Assume editorTafTabComp is for the active tab. st = editorTafTabComp.getTextEditorControl(); st.setText(st.getText().toUpperCase()); diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/stationprofile/StationProfileDlg.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/stationprofile/StationProfileDlg.java index 62b10edca9..a1f6763239 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/stationprofile/StationProfileDlg.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/stationprofile/StationProfileDlg.java @@ -19,6 +19,7 @@ **/ package com.raytheon.viz.hydro.stationprofile; +import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; @@ -65,6 +66,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * 15 Jun 2010 4304 mpduff Added some null checks. * 30 Nov 2011 11253 lbousaidi used List instead of TreeMap * 29 Mar 2013 1790 rferrel Make dialog non-blocking. + * 23 Oct 2013 15183 wkwock Fix scales and value format * * * @@ -327,7 +329,7 @@ public class StationProfileDlg extends CaveSWTDialog { */ private void calculateValues() { double totalElevInc = Math.abs(stationProfData.getElevationFtMax()) - + Math.abs(stationProfData.getElevationFtMin()); + - Math.abs(stationProfData.getElevationFtMin()); // Calculate the offset between the elevation points double offsetDbl = totalElevInc / 5; @@ -608,6 +610,7 @@ public class StationProfileDlg extends CaveSWTDialog { e.gc.setFont(font); int fontHeight = (e.gc.getFontMetrics().getHeight()); int fontAveWidth = (e.gc.getFontMetrics().getAverageCharWidth()); + DecimalFormat df = new DecimalFormat("#.##"); // List of label position objects ArrayList labelList = new ArrayList(); @@ -633,16 +636,17 @@ public class StationProfileDlg extends CaveSWTDialog { // ---------------------------------------- // Draw 0 miles hash and label - e.gc.drawLine(PROFILE_CANVAS_WIDTH / 2, BOTTOM_Y_COORD, +/* e.gc.drawLine(PROFILE_CANVAS_WIDTH / 2, BOTTOM_Y_COORD, PROFILE_CANVAS_WIDTH / 2, BOTTOM_Y_COORD + RIVER_MILES_HASH); e.gc.drawString("0", PROFILE_CANVAS_WIDTH / 2 - fontAveWidth / 2, BOTTOM_Y_COORD + RIVER_MILES_HASH + 3, true); - +*/ // Draw 50 miles hash and label - int currMile = 50; + double maxMile = getMaxMile(stationList); + int currMile = (int) Math.ceil(getMinMile(stationList) / 50) * 50; int x; int y; - while (Double.compare(mileRange, currMile) > 0) { + while (maxMile > currMile) { x = calcRiverMileXCoord(currMile); e.gc.drawLine(x, BOTTOM_Y_COORD, x, BOTTOM_Y_COORD @@ -680,7 +684,6 @@ public class StationProfileDlg extends CaveSWTDialog { if (stationList != null) { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm MM/dd"); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); - int i = 0; for (Statprof station : stationList) { // Skip gage if the river mile is not valid @@ -691,7 +694,6 @@ public class StationProfileDlg extends CaveSWTDialog { e.gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK)); x = calcRiverMileXCoord(station.getId().getMile()); y = calcElevationYCoord(station.getId().getZd()); - i++; // hash mark at each site e.gc.drawLine(x, y, x, y + POINT_HASH); @@ -743,7 +745,7 @@ public class StationProfileDlg extends CaveSWTDialog { HydroDataReport rpt = allReports.get(station.getId().getLid()); if (rpt.getValue() != HydroConstants.MISSING_VALUE) { - label.append(rpt.getValue() + " - "); + label.append(df.format(rpt.getValue()) + " - "); label.append(sdf.format(rpt.getValidTime()) + ")"); } else { label.append("MSG/MSG)"); @@ -946,8 +948,10 @@ public class StationProfileDlg extends CaveSWTDialog { mileRange = 10; } + double maxMile = getMaxMile(stationList); + int xCoord = (int) Math.round((ZERO_MILE_XCOORD + 2) - * (mileRange - riverMile) / mileRange); + * (maxMile - riverMile) / mileRange); return xCoord; } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.xml index 9f76ee1f23..2ce19d43ce 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.xml @@ -4,7 +4,7 @@ - UKMET[0-9]{2}|ECMF[0-9]{2}|ENSEMBLE[0-9]{2}|AVN[0-9]{2} + UKMET[0-9]{2}|ECMF[0-9]|ENSEMBLE[0-9]{2}|AVN[0-9]{2} EnsembleGridAssembler diff --git a/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java b/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java index aec3938960..35096de150 100644 --- a/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java +++ b/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java @@ -212,14 +212,14 @@ public abstract class MonitorConfigurationManager { if (!adjacentAreaFileExists) { AdjacentWfoMgr adjMgr = new AdjacentWfoMgr(currentSite); List zones = adjMgr.getAdjZones(); - if (!zones.isEmpty()) { + if (zones.isEmpty()) { for (String zone : zones) { AreaIdXML zoneXml = new AreaIdXML(); zoneXml.setAreaId(zone); zoneXml.setType(ZoneType.REGULAR); List stations = MonitorAreaUtils .getZoneReportingStationXMLs(zone); - if (!stations.isEmpty()) { + if (stations.isEmpty()) { for (StationIdXML station : stations) { zoneXml.addStationIdXml(station); } diff --git a/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id b/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id index 7b5e854ce1..2291591ae6 100644 --- a/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id +++ b/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id @@ -1 +1 @@ -759799451b20c427bdaa8cb8185b9602cc66c6c6 \ No newline at end of file +2d8d4c03270ef631f167570cf0c03461ff832fea \ No newline at end of file diff --git a/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id b/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id index 7b5e854ce1..2291591ae6 100644 --- a/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id +++ b/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id @@ -1 +1 @@ -759799451b20c427bdaa8cb8185b9602cc66c6c6 \ No newline at end of file +2d8d4c03270ef631f167570cf0c03461ff832fea \ No newline at end of file diff --git a/rpms/build/i386/build.sh b/rpms/build/i386/build.sh index 3cbff01ce3..9ee32c3e1c 100644 --- a/rpms/build/i386/build.sh +++ b/rpms/build/i386/build.sh @@ -393,7 +393,7 @@ if [ "${1}" = "-custom" ]; then buildRPM "awips2-adapt-native" buildRPM "awips2-hydroapps-shared" buildRPM "awips2-common-base" - #buildRPM "awips2-rcm" + buildRPM "awips2-rcm" #buildRPM "awips2-ant" #buildRPM "awips2-java" #buildRPM "awips2-tools" diff --git a/rpms/build/i386/build.sh-keep-10032013 b/rpms/build/i386/build.sh-keep-10212013 similarity index 96% rename from rpms/build/i386/build.sh-keep-10032013 rename to rpms/build/i386/build.sh-keep-10212013 index 31dd6470c1..9ee32c3e1c 100644 --- a/rpms/build/i386/build.sh-keep-10032013 +++ b/rpms/build/i386/build.sh-keep-10212013 @@ -85,7 +85,6 @@ if [ "${2}" = "-nobinlightning" ]; then fi if [ "${1}" = "-python-qpid" ]; then - buildRPM "awips2" buildRPM "awips2-python-qpid" buildRPM "awips2-python" buildRPM "awips2-python-cherrypy" @@ -116,15 +115,6 @@ if [ "${1}" = "-python-qpid" ]; then exit 1 fi - #buildRPM "awips2-ant" - #unpackHttpdPypies - if [ $? -ne 0 ]; then - exit 1 - fi - #buildRPM "awips2-httpd-pypies" - #buildRPM "awips2-java" - #buildRPM "awips2-ldm" - #buildRPM "awips2-tools" buildRPM "awips2-python-shapely" exit 0 @@ -157,7 +147,6 @@ if [ "${1}" = "-delta" ]; then exit 1 fi - buildRPM "awips2" buildRPM "awips2-ncep-database" buildRPM "awips2-gfesuite-client" buildRPM "awips2-gfesuite-server" @@ -173,7 +162,6 @@ if [ "${1}" = "-delta" ]; then buildRPM "awips2-database-server-configuration" buildRPM "awips2-database-standalone-configuration" buildRPM "awips2-data.hdf5-gfe.climo" - buildRPM "awips2-hydroapps-shared" buildRPM "awips2-localapps-environment" buildRPM "awips2-maps-database" buildRPM "awips2-notification" @@ -181,7 +169,6 @@ if [ "${1}" = "-delta" ]; then buildRPM "awips2-data.hdf5-topo" buildRPM "awips2-data.gfe" buildRPM "awips2-rcm" - buildRPM "awips2-edex-environment" buildLocalizationRPMs if [ $? -ne 0 ]; then exit 1 @@ -222,8 +209,8 @@ if [ "${1}" = "-full" ]; then buildRPM "awips2-python-werkzeug" buildRPM "awips2-python-pygtk" buildRPM "awips2-python-pycairo" + buildRPM "awips2-python-shapely" - buildRPM "awips2" buildRPM "awips2-adapt-native" buildRPM "awips2-aviation-shared" buildRPM "awips2-cli" @@ -260,14 +247,11 @@ if [ "${1}" = "-full" ]; then buildRPM "awips2-httpd-pypies" buildJava buildRPM "awips2-groovy" - #buildRPM "awips2-ldm" buildRPM "awips2-postgres" buildRPM "awips2-pgadmin3" buildRPM "awips2-tools" - buildRPM "awips2-edex-environment" buildRPM "awips2-openfire" buildRPM "awips2-httpd-collaboration" - buildRPM "awips2-python-shapely" exit 0 fi @@ -347,9 +331,6 @@ if [ "${1}" = "-ade" ]; then fi if [ "${1}" = "-viz" ]; then - buildRPM "awips2-common-base" - buildRPM "awips2-rcm" - buildRPM "awips2-hydroapps-shared" buildCAVE if [ $? -ne 0 ]; then exit 1 @@ -360,13 +341,9 @@ if [ "${1}" = "-viz" ]; then fi if [ "${1}" = "-edex" ]; then - buildRPM "awips2-common-base" - buildRPM "awips2-adapt-native" buildRPM "awips2-gfesuite-client" buildRPM "awips2-gfesuite-server" buildRPM "awips2-edex-environment" - # buildRPM "awips2-ncep-database" - # buildRPM "awips2-python-dynamicserialize" buildEDEX if [ $? -ne 0 ]; then exit 1 @@ -408,7 +385,18 @@ fi # Use the custom flag for selecting specific rpms to build if [ "${1}" = "-custom" ]; then - #buildRPM "awips2-ldm" + unpackHttpdPypies + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-httpd-pypies" + buildRPM "awips2-adapt-native" + buildRPM "awips2-hydroapps-shared" + buildRPM "awips2-common-base" + buildRPM "awips2-rcm" + #buildRPM "awips2-ant" + #buildRPM "awips2-java" + #buildRPM "awips2-tools" exit 0 fi diff --git a/rpms/build/i386/build.sh_old b/rpms/build/i386/build.sh_old deleted file mode 100644 index 37dbb8eaa6..0000000000 --- a/rpms/build/i386/build.sh_old +++ /dev/null @@ -1,423 +0,0 @@ -#!/bin/bash - -function buildRPM() -{ - # Arguments: - # ${1} == the name of the rpm. - lookupRPM "${1}" - if [ $? -ne 0 ]; then - echo "ERROR: '${1}' is not a recognized AWIPS II RPM." - exit 1 - fi - - /usr/bin/rpmbuild -ba \ - --define '_topdir %(echo ${AWIPSII_TOP_DIR})' \ - --define '_baseline_workspace %(echo ${WORKSPACE})' \ - --define '_uframe_eclipse %(echo ${UFRAME_ECLIPSE})' \ - --define '_awipscm_share %(echo ${AWIPSCM_SHARE})' \ - --define '_build_root %(echo ${AWIPSII_BUILD_ROOT})' \ - --define '_component_version %(echo ${AWIPSII_VERSION})' \ - --define '_component_release %(echo ${AWIPSII_RELEASE})' \ - --define '_component_build_date %(echo ${COMPONENT_BUILD_DATE})' \ - --define '_component_build_time %(echo ${COMPONENT_BUILD_TIME})' \ - --define '_component_build_system %(echo ${COMPONENT_BUILD_SYSTEM})' \ - --buildroot ${AWIPSII_BUILD_ROOT} \ - ${RPM_SPECIFICATION}/component.spec - if [ $? -ne 0 ]; then - echo "ERROR: Failed to build RPM ${1}." - exit 1 - fi - - return 0 -} - -# This script will build all of the 32-bit rpms. -# Ensure that we are on a machine with the correct architecture. - -architecture=`uname -i` -if [ ! "${architecture}" = "i386" ]; then - echo "ERROR: This build can only be performed on a 32-bit Operating System." - exit 1 -fi - -# Determine which directory we are running from. -path_to_script=`readlink -f $0` -dir=$(dirname $path_to_script) - -common_dir=`cd ${dir}/../common; pwd;` -if [ $? -ne 0 ]; then - echo "ERROR: Unable to find the common functions directory." - exit 1 -fi -# source the common functions. -source ${common_dir}/lookupRPM.sh -if [ $? -ne 0 ]; then - echo "ERROR: Unable to source the common functions." - exit 1 -fi -source ${common_dir}/usage.sh -if [ $? -ne 0 ]; then - echo "ERROR: Unable to source the common functions." - exit 1 -fi -source ${common_dir}/rpms.sh -if [ $? -ne 0 ]; then - echo "ERROR: Unable to source the common functions." - exit 1 -fi -source ${common_dir}/systemInfo.sh -if [ $? -ne 0 ]; then - echo "ERROR: Unable to retrieve the system information." - exit 1 -fi - -# prepare the build environment. -source ${dir}/buildEnvironment.sh -if [ $? -ne 0 ]; then - echo "ERROR: Unable to prepare the build environment." - exit 1 -fi - -export LIGHTNING=true -# Determine if the optional '-nobinlightning' argument has been specified. -if [ "${2}" = "-nobinlightning" ]; then - LIGHTNING=false -fi - -if [ "${1}" = "-python-qpid" ]; then - buildRPM "awips2" - buildRPM "awips2-python-qpid" - buildRPM "awips2-python" - buildRPM "awips2-python-cherrypy" - buildRPM "awips2-python-dynamicserialize" - buildRPM "awips2-python-nose" - buildRPM "awips2-python-numpy" - buildRPM "awips2-python-h5py" - buildRPM "awips2-python-jimporter" - buildRPM "awips2-python-matplotlib" - buildRPM "awips2-python-pil" - buildRPM "awips2-python-pmw" - buildRPM "awips2-python-pupynere" - buildRPM "awips2-python-scientific" - buildRPM "awips2-python-scipy" - buildRPM "awips2-python-tables" - buildRPM "awips2-python-thrift" - buildRPM "awips2-python-tpg" - buildRPM "awips2-python-ufpy" - buildRPM "awips2-python-werkzeug" - buildRPM "awips2-python-pygtk" - buildRPM "awips2-python-pycairo" - if [ $? -ne 0 ]; then - exit 1 - fi - - buildQPID - if [ $? -ne 0 ]; then - exit 1 - fi - - #buildRPM "awips2-ant" - #unpackHttpdPypies - if [ $? -ne 0 ]; then - exit 1 - fi - #buildRPM "awips2-httpd-pypies" - #buildRPM "awips2-java" - #buildRPM "awips2-ldm" - #buildRPM "awips2-tools" - buildRPM "awips2-python-shapely" - - exit 0 -fi - -if [ "${1}" = "-postgres" ]; then - buildRPM "awips2-postgres" - buildRPM "awips2-database-server-configuration" - buildRPM "awips2-database-standalone-configuration" - buildRPM "awips2-database" - buildRPM "awips2-maps-database" - buildRPM "awips2-pgadmin3" - - exit 0 -fi - -if [ "${1}" = "-delta" ]; then - buildCAVE - if [ $? -ne 0 ]; then - exit 1 - fi - buildRPM "awips2-alertviz" - buildEDEX - if [ $? -ne 0 ]; then - exit 1 - fi - - buildRPM "awips2" - buildRPM "Installer.ncep-database" - buildRPM "awips2-gfesuite-client" - buildRPM "awips2-gfesuite-server" - buildRPM "awips2-python" - buildRPM "awips2-python-dynamicserialize" - buildRPM "awips2-python-ufpy" - buildRPM "awips2-python-qpid" - - buildRPM "awips2-adapt-native" - buildRPM "awips2-aviation-shared" - buildRPM "awips2-cli" - buildRPM "awips2-database" - buildRPM "awips2-database-server-configuration" - buildRPM "awips2-database-standalone-configuration" - buildRPM "awips2-data.hdf5-gfe.climo" - buildRPM "awips2-hydroapps-shared" - buildRPM "awips2-localapps-environment" - buildRPM "awips2-maps-database" - buildRPM "awips2-notification" - buildRPM "awips2-pypies" - buildRPM "awips2-data.hdf5-topo" - buildRPM "awips2-data.gfe" - buildRPM "awips2-rcm" - buildRPM "awips2-edex-environment" - buildLocalizationRPMs - if [ $? -ne 0 ]; then - exit 1 - fi - - exit 0 -fi - -if [ "${1}" = "-full" ]; then - buildCAVE - if [ $? -ne 0 ]; then - exit 1 - fi - buildRPM "Installer.ncep-database" - buildRPM "awips2-alertviz" - buildEDEX - if [ $? -ne 0 ]; then - exit 1 - fi - buildRPM "awips2-python" - buildRPM "awips2-python-cherrypy" - buildRPM "awips2-python-dynamicserialize" - buildRPM "awips2-python-h5py" - buildRPM "awips2-python-jimporter" - buildRPM "awips2-python-matplotlib" - buildRPM "awips2-python-nose" - buildRPM "awips2-python-numpy" - buildRPM "awips2-python-pil" - buildRPM "awips2-python-pmw" - buildRPM "awips2-python-pupynere" - buildRPM "awips2-python-qpid" - buildRPM "awips2-python-scientific" - buildRPM "awips2-python-scipy" - buildRPM "awips2-python-tables" - buildRPM "awips2-python-thrift" - buildRPM "awips2-python-tpg" - buildRPM "awips2-python-ufpy" - buildRPM "awips2-python-werkzeug" - buildRPM "awips2-python-pygtk" - buildRPM "awips2-python-pycairo" - - buildRPM "awips2" - buildRPM "awips2-adapt-native" - buildRPM "awips2-aviation-shared" - buildRPM "awips2-cli" - buildRPM "awips2-database" - buildRPM "awips2-database-server-configuration" - buildRPM "awips2-database-standalone-configuration" - buildRPM "awips2-data.hdf5-gfe.climo" - buildRPM "awips2-data.gfe" - buildRPM "awips2-gfesuite-client" - buildRPM "awips2-gfesuite-server" - buildRPM "awips2-hydroapps-shared" - buildRPM "awips2-localapps-environment" - buildRPM "awips2-maps-database" - buildRPM "awips2-notification" - buildRPM "awips2-pypies" - buildRPM "awips2-data.hdf5-topo" - buildRPM "awips2-rcm" - buildLocalizationRPMs - if [ $? -ne 0 ]; then - exit 1 - fi - - buildQPID - if [ $? -ne 0 ]; then - exit 1 - fi - - buildRPM "awips2-ant" - unpackHttpdPypies - if [ $? -ne 0 ]; then - exit 1 - fi - buildRPM "awips2-httpd-pypies" - buildRPM "awips2-java" - #buildRPM "awips2-ldm" - buildRPM "awips2-postgres" - buildRPM "awips2-pgadmin3" - buildRPM "awips2-tools" - buildRPM "awips2-edex-environment" - buildRPM "awips2-openfire" - buildRPM "awips2-httpd-collaboration" - buildRPM "awips2-python-shapely" - - exit 0 -fi - -if [ "${1}" = "-ade" ]; then - buildRPM "awips2-eclipse" - buildRPM "awips2-java" - buildRPM "awips2-ant" - buildRPM "awips2-python" - buildRPM "awips2-python-cherrypy" - buildRPM "awips2-python-dynamicserialize" - buildRPM "awips2-python-h5py" - buildRPM "awips2-python-jimporter" - buildRPM "awips2-python-matplotlib" - buildRPM "awips2-python-nose" - buildRPM "awips2-python-numpy" - buildRPM "awips2-python-pil" - buildRPM "awips2-python-pmw" - buildRPM "awips2-python-pupynere" - buildRPM "awips2-python-qpid" - buildRPM "awips2-python-scientific" - buildRPM "awips2-python-scipy" - buildRPM "awips2-python-tables" - buildRPM "awips2-python-thrift" - buildRPM "awips2-python-tpg" - buildRPM "awips2-python-ufpy" - buildRPM "awips2-python-werkzeug" - buildRPM "awips2-python-pygtk" - buildRPM "awips2-python-pycairo" - buildRPM "awips2-python-shapely" - buildQPID -ade - if [ $? -ne 0 ]; then - exit 1 - fi - - # Package the ade. - # Create the containing directory. - ade_directory="awips2-ade-${AWIPSII_VERSION}-${AWIPSII_RELEASE}" - if [ -d ${WORKSPACE}/${ade_directory} ]; then - rm -rf ${WORKSPACE}/${ade_directory} - if [ $? -ne 0 ]; then - exit 1 - fi - fi - mkdir -p ${WORKSPACE}/${ade_directory} - if [ $? -ne 0 ]; then - exit 1 - fi - - # Copy the rpms to the directory. - cp -v ${AWIPSII_TOP_DIR}/RPMS/i386/* \ - ${AWIPSII_TOP_DIR}/RPMS/noarch/* \ - ${WORKSPACE}/${ade_directory} - if [ $? -ne 0 ]; then - exit 1 - fi - - awips2_ade_directory="${WORKSPACE}/rpms/awips2.ade" - # Copy the install and uninstall script to the directory. - cp -v ${awips2_ade_directory}/tar.ade/scripts/*.sh \ - ${WORKSPACE}/${ade_directory} - if [ $? -ne 0 ]; then - exit 1 - fi - - # Tar the directory. - pushd . > /dev/null 2>&1 - cd ${WORKSPACE} - tar -cvf ${ade_directory}.tar ${ade_directory} - popd > /dev/null 2>&1 - RC=$? - if [ ${RC} -ne 0 ]; then - exit 1 - fi - - exit 0 -fi - -if [ "${1}" = "-viz" ]; then - buildRPM "awips2" - buildRPM "awips2-rcm" - buildCAVE - if [ $? -ne 0 ]; then - exit 1 - fi - buildRPM "awips2-alertviz" - - exit 0 -fi - -if [ "${1}" = "-edex" ]; then - buildRPM "awips2" - buildRPM "awips2-cli" - buildRPM "awips2-gfesuite-client" - buildRPM "awips2-gfesuite-server" - buildRPM "Installer.ncep-database" - buildEDEX - if [ $? -ne 0 ]; then - exit 1 - fi - - exit 0 -fi - -if [ "${1}" = "-qpid" ]; then - buildQPID - if [ $? -ne 0 ]; then - exit 1 - fi - - exit 0 -fi - -if [ "${1}" = "-ldm" ]; then - buildRPM "awips2-ldm" - - exit 0 -fi - -if [ "${1}" = "-package" ]; then - repository_directory="awips2-repository-${AWIPSII_VERSION}-${AWIPSII_RELEASE}" - if [ -d ${WORKSPACE}/${repository_directory} ]; then - rm -rf ${WORKSPACE}/${repository_directory} - if [ $? -ne 0 ]; then - exit 1 - fi - fi - mkdir -p ${WORKSPACE}/${repository_directory}/${AWIPSII_VERSION}-${AWIPSII_RELEASE} - if [ $? -ne 0 ]; then - exit 1 - fi - - cp -r ${AWIPSII_TOP_DIR}/RPMS/* \ - ${WORKSPACE}/${repository_directory}/${AWIPSII_VERSION}-${AWIPSII_RELEASE} - if [ $? -ne 0 ]; then - exit 1 - fi - - rpms_directory="${WORKSPACE}/rpms" - comps_xml="${rpms_directory}/common/yum/arch.x86/comps.xml" - cp -v ${comps_xml} ${WORKSPACE}/${repository_directory} - if [ $? -ne 0 ]; then - exit 1 - fi - - pushd . > /dev/null - cd ${WORKSPACE} - tar -cvf ${repository_directory}.tar ${repository_directory} - RC=$? - popd > /dev/null - if [ ${RC} -ne 0 ]; then - exit 1 - fi - - exit 0 -fi - - -usage -exit 0 From 48267f510bab2a02423b27ba9adc3c72c7459130 Mon Sep 17 00:00:00 2001 From: Richard Peter Date: Mon, 28 Oct 2013 12:13:04 -0500 Subject: [PATCH 11/26] Issue #2362: Fix merge issue Former-commit-id: 89e5781b133e0e73bc212ee4f3dfc5100ade5fd6 [formerly 6dba9925c3eea07b26e4f798528a7de986f1c0ce] [formerly 814b1878b2807956fb2bac4649d31656a7b90d1b] [formerly 51bf66d456f377727391158471418f9d66e6c19f [formerly 814b1878b2807956fb2bac4649d31656a7b90d1b [formerly 03fa4950011aaee4f4d7cfeda68fe8ad3359a138]]] Former-commit-id: 51bf66d456f377727391158471418f9d66e6c19f Former-commit-id: f75934ef7aeecb24bea0928dbfb67cd395fc700d [formerly 50bd787f24cc0dce8a3531b801827beaef9b60cf] Former-commit-id: 4e5cd1b28b03c6639a088f55d113ffe3af619bf8 --- .../nws/ncep/edex/plugin/ntrans/decoder/NtransDecoder.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/src/gov/noaa/nws/ncep/edex/plugin/ntrans/decoder/NtransDecoder.java b/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/src/gov/noaa/nws/ncep/edex/plugin/ntrans/decoder/NtransDecoder.java index e05154aa00..0a56a0693c 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/src/gov/noaa/nws/ncep/edex/plugin/ntrans/decoder/NtransDecoder.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.ntrans/src/gov/noaa/nws/ncep/edex/plugin/ntrans/decoder/NtransDecoder.java @@ -1,4 +1,3 @@ - * 10/2013 B. Hebbard Modify model name inference from metafile name package gov.noaa.nws.ncep.edex.plugin.ntrans.decoder; import gov.noaa.nws.ncep.common.dataplugin.ntrans.NtransRecord; @@ -31,6 +30,7 @@ import com.raytheon.uf.common.time.DataTime; * ------------ -------- ----------- ------------------------------------- * 03/2013 B. Hebbard Initial creation * 04/2013 B. Hebbard IOC version (for OB13.4.1) + * 10/2013 B. Hebbard Modify model name inference from metafile name * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * @@ -439,9 +439,8 @@ public class NtransDecoder extends AbstractDecoder { } else if (/* fileName.matches("^[A-Z]") */ fileName.contains("_GFS")) { modelName = "vaftad"; + /* } else if (fileName.contains("_2")) { - - /* modelName = fileName.substring(0, fileName.indexOf("_2")); if (modelName.equals("jma")) { modelName = "jmap"; @@ -451,7 +450,7 @@ public class NtransDecoder extends AbstractDecoder { return modelName; */ - else { + } else { for (Model model : Model.values()) { if (fileName.toLowerCase().contains(model.name().toLowerCase())) { modelName = model.name().toLowerCase(); From fef629ce2691b9aaf5415ee7b176f07452db6271 Mon Sep 17 00:00:00 2001 From: Steve Harris Date: Wed, 30 Oct 2013 12:53:25 -0400 Subject: [PATCH 12/26] 13.5.3-2 baseline Former-commit-id: 235d1f8583a24d90a814dc0e1e95400c26d8b132 [formerly c6d951b39069eaf448776bbed54ac071d335dc63] [formerly 055783655b22872e356f8a0253c127cf6cd220cc] [formerly 6d85d944a6ead47e938c63ea7646c4e828badcf8 [formerly 055783655b22872e356f8a0253c127cf6cd220cc [formerly 53d73b86bbee5d75bc7cb3a69e12ae78ea22f18f]]] Former-commit-id: 6d85d944a6ead47e938c63ea7646c4e828badcf8 Former-commit-id: 08cfc6740d0a1f987b0743cf3f07ab435cbb6ddc [formerly aef0e828d2c5c6a02f83bf1bfef6769eaff845e4] Former-commit-id: 0c177771643593dc7e031438ff10a34ab0f1efbb --- .../raytheon/viz/warngen/gis/PolygonUtil.java | 25 +- .../viz/warngen/gui/WarngenDialog.java | 7 + .../viz/warngen/gui/WarngenLayer.java | 232 +- .../config/AreaSourceConfiguration.java | 12 + .../dataplugin/warning/util/GeometryUtil.java | 13 +- .../config/MonitorConfigurationManager.java | 4 +- .../common_static/base/hydro/Apps_defaults | 3747 ++++++++--------- .../plugin/lsr/decoder/InternalReport.java | 3 +- .../library.ohd.pproc.so.REMOVED.git-id | 2 +- .../awipsShare/hydroapps/whfs/bin/nrldb.ksh | 38 - .../awipsShare/hydroapps/whfs/bin/nrldb.pl | 1415 ------- .../hydroapps/whfs/bin/run_update_nrldb.ksh | 21 - .../hydroapps/whfs/bin/send_nrldb_update.sh | 167 - .../hydroapps/whfs/bin/update_nrldb.pl | 248 -- .../whfs/local/data/app/nrldb/nrldb.conf | 6 - .../local/data/app/nrldb/nrldb_control_wfo | 174 - .../whfs/local/data/app/nrldb/sed_script.txt | 1 - .../library.ohd.pproc.so.REMOVED.git-id | 2 +- .../ncgrid/rsc/EnsembleSelectComposite.java | 20 +- .../viz/rsc/plotdata/rsc/NcPlotResource2.java | 3 +- rpms/build/i386/build.sh | 14 +- 21 files changed, 2107 insertions(+), 4047 deletions(-) delete mode 100644 nativeLib/files.native/awipsShare/hydroapps/whfs/bin/nrldb.ksh delete mode 100644 nativeLib/files.native/awipsShare/hydroapps/whfs/bin/nrldb.pl delete mode 100644 nativeLib/files.native/awipsShare/hydroapps/whfs/bin/run_update_nrldb.ksh delete mode 100644 nativeLib/files.native/awipsShare/hydroapps/whfs/bin/send_nrldb_update.sh delete mode 100644 nativeLib/files.native/awipsShare/hydroapps/whfs/bin/update_nrldb.pl delete mode 100644 nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/nrldb.conf delete mode 100644 nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/nrldb_control_wfo delete mode 100644 nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/sed_script.txt diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java index 5672cb355e..13c686c89a 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java @@ -74,6 +74,8 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; * removeDuplicateCoordinate(), computeCoordinate(), adjustPolygon() prolog, and * removeOverlaidLinesegments(); added alterVertexes() and calcShortestDistance(). * 10/01/2013 DR 16632 Qinglu Lin Fixed the bug in for loop range. + * 10/17/2013 DR 16632 Qinglu Lin Updated removeOverlaidLinesegments(). + * 10/18/2013 DR 16632 Qinglu Lin Catch exception thrown when coords length is less than 4 and doing createLinearRing(coords). * * * @author mschenke @@ -1094,16 +1096,23 @@ public class PolygonUtil { if (polygon == null) { return null; } + if (polygon.getNumPoints() <= 4) + return polygon; Coordinate[] coords = removeDuplicateCoordinate(polygon.getCoordinates()); - GeometryFactory gf = new GeometryFactory(); - return gf.createPolygon(gf.createLinearRing(coords), null); + GeometryFactory gf = new GeometryFactory(); + try { + polygon = gf.createPolygon(gf.createLinearRing(coords), null); + } catch (Exception e) { + ; + } + return polygon; } public static Coordinate[] removeDuplicateCoordinate(Coordinate[] verts) { if (verts == null) { return null; } - if (verts.length <= 3) + if (verts.length <= 4) return verts; Set coords = new LinkedHashSet(); @@ -1119,7 +1128,10 @@ public class PolygonUtil { i += 1; } vertices[i] = new Coordinate(vertices[0]); - return vertices; + if (vertices.length <=3) + return verts; + else + return vertices; } /** @@ -1271,9 +1283,14 @@ public class PolygonUtil { } public static Coordinate[] removeOverlaidLinesegments(Coordinate[] coords) { + if (coords.length <= 4) + return coords; Coordinate[] expandedCoords = null; boolean flag = true; while (flag) { + if (coords.length <= 4) { + return coords; + } expandedCoords = new Coordinate[coords.length+1]; flag = false; for (int i = 0; i < coords.length; i++) { diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenDialog.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenDialog.java index 4dbe973985..04fd01d75a 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenDialog.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenDialog.java @@ -150,6 +150,7 @@ import com.vividsolutions.jts.geom.Polygon; * Aug 15, 2013 DR 16418 D. Friedman Make dialog visibility match editable state. * Sep 17, 2013 DR 16496 D. Friedman Make editable state more consistent. * Oct 01, 2013 DR16612 m.gamazaychikov Fixed inconsistencies with track locking and updateListSelected method + * Oct 29, 2013 DR 16734 D. Friedman If redraw-from-hatched-area fails, don't allow the pollygon the be used. * * * @author chammack @@ -1073,6 +1074,12 @@ public class WarngenDialog extends CaveSWTDialog implements redrawFromWarned(); } + // Need to check again because redraw may have failed. + if (warngenLayer.getWarningArea() == null) { + setInstructions(); + return; + } + ProgressMonitorDialog pmd = new ProgressMonitorDialog(Display .getCurrent().getActiveShell()); pmd.setCancelable(false); diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java index 7bef3b3064..22fcb375ee 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java @@ -189,6 +189,10 @@ import com.vividsolutions.jts.io.WKTReader; * 07/26/2013 DR 16450 D. Friedman Fix logic errors when frame count is one. * 08/19/2013 2177 jsanchez Set a GeneralGridGeometry object in the GeospatialDataList. * 09/17/2013 DR 16496 D. Friedman Make editable state more consistent. + * 10/01/2013 DR 16632 Qinglu Lin Catch exceptions thrown while doing areaPercent computation and union(). + * 10/21/2013 DR 16632 D. Friedman Modify areaPercent exception handling. Fix an NPE. + * Use A1 hatching behavior when no county passes the inclusion filter. + * 10/29/2013 DR 16734 D. Friedman If redraw-from-hatched-area fails, don't allow the pollygon the be used. * * * @author mschenke @@ -1605,6 +1609,36 @@ public class WarngenLayer extends AbstractStormTrackResource { Geometry oldWarningPolygon = latLonToLocal(state.getOldWarningPolygon()); Geometry oldWarningArea = latLonToLocal(state.getOldWarningArea()); Geometry newHatchedArea = null; + Geometry newUnfilteredArea = null; + boolean useFilteredArea = false; + boolean useFallback = getConfiguration().getHatchedAreaSource().isInclusionFallback(); + + /* + * The resultant warning area is constructed in one of two ways: + * + * 1. When preservedSelection is null: + * + * If at least one county in hatchedArea passes the inclusion filter, + * the result contains only the counties in hatchedArea that pass the + * inclusion filter. Otherwise, all counties in hatchedArea are + * included. + * + * This behavior reflects A1 baseline template logic. The fallback can + * be disabled by setting AreaSourceConfiguration.isInclusionFallback to + * false. + * + * 2. When preservedSelection is not null: + * + * A county is included in the result if and only if it is contained in + * preservedSelection. If the portion of the county in hatchedArea is + * non-empty, it used. Otherwise, the hatched portion from + * preservedSelection is used. + * + * + * In both cases, when there is an old warning area in effect (i.e., for + * followups), the intersection of hatchedArea and the old warning area + * is used instead of hatchedArea. + */ Set selectedFips = null; List selectedGeoms = null; @@ -1666,19 +1700,19 @@ public class WarngenLayer extends AbstractStormTrackResource { try { boolean include; - if (selectedFips != null) + if (selectedFips != null) { include = selectedFips.contains(getFips(f)); - else - include = filterArea(f, intersection, true) + useFilteredArea = true; + } else { + boolean passed = filterArea(f, intersection, true); + useFilteredArea = useFilteredArea || passed; + include = (passed || filterAreaSecondChance(f, intersection, true)) && (oldWarningPolygon == null || prepGeom.intersects(oldWarningPolygon) || isOldAreaOutsidePolygon(f)); + newUnfilteredArea = union(newUnfilteredArea, intersection); + } if (include) { - if (newHatchedArea == null) { - newHatchedArea = intersection; - } else { - newHatchedArea = GeometryUtil.union(newHatchedArea, - intersection); - } + newHatchedArea = union(newHatchedArea, intersection); } } catch (TopologyException e) { @@ -1690,10 +1724,19 @@ public class WarngenLayer extends AbstractStormTrackResource { } } + newHatchedArea = useFilteredArea && newHatchedArea != null ? newHatchedArea : + useFallback ? newUnfilteredArea : null; return newHatchedArea != null ? newHatchedArea : new GeometryFactory() .createGeometryCollection(new Geometry[0]); } + private static Geometry union(Geometry a, Geometry b) { + if (a != null && b != null) + return GeometryUtil.union(a, b); + else + return a != null ? a : b; + } + private void updateWarnedAreaState(Geometry newHatchedArea, boolean snapToHatchedArea) throws VizException { try { @@ -1720,10 +1763,17 @@ public class WarngenLayer extends AbstractStormTrackResource { } if (oldWarningArea != null) { - int areaPercent = Double.valueOf( - ((oldWarningPolygon.intersection(warningPolygon) - .getArea() / oldWarningArea.getArea()) * 100)) - .intValue(); + int areaPercent = -1; + try { + areaPercent = Double.valueOf( + ((oldWarningPolygon.intersection(warningPolygon) + .getArea() / oldWarningArea.getArea()) * 100)) + .intValue(); + } catch (Exception e) { + statusHandler.handle(Priority.VERBOSE, + "Error determining amount of overlap with original polygon", e); + areaPercent = 100; + } if (oldWarningPolygon.intersects(warningPolygon) == false && !state.isMarked()) { // Snap back to polygon @@ -1867,9 +1917,6 @@ public class WarngenLayer extends AbstractStormTrackResource { * the portion of the feature that is hatched * @param localCoordinates * if true, use local CRS; otherwise, use lat/lon - * @param anyAmountOfArea - * if true, ignore the configured criteria and include the - * feature if event a small amount is hatched. * @return true if the feature should be included */ private boolean filterArea(GeospatialData feature, @@ -1878,9 +1925,16 @@ public class WarngenLayer extends AbstractStormTrackResource { .get(GeospatialDataList.LOCAL_GEOM) : feature.geometry; double areaOfGeom = (Double) feature.attributes.get(AREA); - if (filterCheck(featureAreaToConsider, geom, areaOfGeom)) - return true; - else if (state.getOldWarningArea() != null) { + return filterCheck(featureAreaToConsider, geom, areaOfGeom); + } + + private boolean filterAreaSecondChance(GeospatialData feature, + Geometry featureAreaToConsider, boolean localCRS) { + Geometry geom = localCRS ? (Geometry) feature.attributes + .get(GeospatialDataList.LOCAL_GEOM) : feature.geometry; + double areaOfGeom = (Double) feature.attributes.get(AREA); + + if (state.getOldWarningArea() != null) { /* * Second chance: If the county slipped by the filter in the initial * warning, allow it now as long as the hatched area is (nearly) the @@ -2225,6 +2279,29 @@ public class WarngenLayer extends AbstractStormTrackResource { issueRefresh(); // End of DR 15559 state.snappedToArea = true; + } else { + /* + * If redraw failed, do not allow this polygon to be used to + * generate a warning. + * + * Note that this duplicates code from updateWarnedAreaState. + */ + state.strings.clear(); + state.setWarningArea(null); + state.geometryChanged = true; + if (dialog != null) { + dialog.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + dialog.setInstructions(); + } + }); + } + state.resetMarked(); + state.geometryChanged = true; + issueRefresh(); + statusHandler.handle(Priority.PROBLEM, + "Could not redraw box from warned area"); } System.out.println("Time to createWarningPolygon: " + (System.currentTimeMillis() - t0) + "ms"); @@ -2719,17 +2796,23 @@ public class WarngenLayer extends AbstractStormTrackResource { Polygon oldWarningPolygon = state.getOldWarningPolygon(); Polygon warningPolygon = state.getWarningPolygon(); + // TODO: Should this even be null when there is no hatching? + Geometry warningArea = state.getWarningArea(); + if (warningArea == null) { + warningArea = new GeometryFactory() + .createGeometryCollection(new Geometry[0]); + } + GeometryFactory gf = new GeometryFactory(); Point point = gf.createPoint(coord); // potentially adding or removing a county, figure out county for (GeospatialData f : geoData.features) { Geometry geom = f.geometry; if (f.prepGeom.contains(point)) { - String[] gids = GeometryUtil.getGID(geom); - if (GeometryUtil.contains(state.getWarningArea(), point)) { + Geometry newWarningArea; + if (GeometryUtil.contains(warningArea, point)) { // remove county - Geometry tmp = removeCounty(state.getWarningArea(), - getFips(f)); + Geometry tmp = removeCounty(warningArea, getFips(f)); if (tmp.isEmpty()) { String fip = getFips(f); if (fip != null && uniqueFip != null @@ -2739,58 +2822,46 @@ public class WarngenLayer extends AbstractStormTrackResource { break; } - state.setWarningArea(tmp); + newWarningArea = tmp; } else { + // add county String featureFips = getFips(f); Collection dataWithFips = getDataWithFips(featureFips); if (oldWarningArea != null) { // for a CON, prevents extra areas to be added Set fipsIds = getAllFipsInArea(oldWarningArea); - if (fipsIds.contains(featureFips) == false) { + if (fipsIds.contains(featureFips) == false || + ! (oldWarningPolygon.contains(point) == true + || isOldAreaOutsidePolygon(f))) { break; - } else if (oldWarningPolygon.contains(point) == true - || isOldAreaOutsidePolygon(f)) { - // Get intersecting parts for each geom with - // matching fips - List fipsParts = new ArrayList( - dataWithFips.size()); - for (GeospatialData g : dataWithFips) { - fipsParts.add(GeometryUtil.intersection( - oldWarningArea, g.geometry)); - } - // Create a collection of each part - geom = GeometryUtil.union(fipsParts - .toArray(new Geometry[0])); - if (warningPolygon.contains(point)) { - // If inside warning polygon, intersect - geom = GeometryUtil.intersection( - warningPolygon, geom); - } - if (filterArea(f, geom, false)) { - state.setWarningArea(GeometryUtil.union( - state.getWarningArea(), geom)); - } } - } else { - // add county - if (warningPolygon.contains(point)) { - // add part of county - List parts = new ArrayList( - dataWithFips.size() + 1); - for (GeospatialData data : dataWithFips) { - parts.add(GeometryUtil.intersection( - warningPolygon, data.geometry)); - } - geom = geom.getFactory() - .createGeometryCollection( - parts.toArray(new Geometry[0])); - if (!filterArea(f, geom, false)) - continue; - } - state.setWarningArea(GeometryUtil.union( - state.getWarningArea(), geom)); } + + // Get intersecting parts for each geom with + // matching fips + List fipsParts = new ArrayList( + dataWithFips.size()); + for (GeospatialData gd : dataWithFips) { + Geometry g = gd.geometry; + if (oldWarningArea != null) { + g = GeometryUtil.intersection(oldWarningArea, g); + } + fipsParts.add(g); + } + // Create a collection of each part + geom = GeometryUtil.union(fipsParts + .toArray(new Geometry[fipsParts.size()])); + if (warningPolygon.contains(point)) { + // If inside warning polygon, intersect + geom = GeometryUtil.intersection( + warningPolygon, geom); + } + newWarningArea = GeometryUtil.union( + removeCounty(warningArea, featureFips), + geom); } + state.setWarningArea(filterWarningArea(newWarningArea)); + setUniqueFip(); warningAreaChanged(); populateStrings(); issueRefresh(); @@ -2803,6 +2874,36 @@ public class WarngenLayer extends AbstractStormTrackResource { } } + private Geometry filterWarningArea(Geometry warningArea) { + // TODO: Duplicates logic in createWarnedArea + if (warningArea == null) + return null; + /* + * Note: Currently does not determine if warningArea is valid (i.e., in + * contained in CWA, old warning area, etc.) or has overlapping geometries. + */ + Geometry newHatchedArea = null; + Geometry newUnfilteredArea = null; + boolean useFilteredArea = false; + boolean useFallback = getConfiguration().getHatchedAreaSource().isInclusionFallback(); + + for (GeospatialData f : geoData.features) { + String gid = GeometryUtil.getPrefix(f.geometry.getUserData()); + Geometry warningAreaForFeature = getWarningAreaForGids(Arrays.asList(gid), warningArea); + boolean passed = filterArea(f, warningAreaForFeature, false); + useFilteredArea = useFilteredArea || passed; + if (passed || filterAreaSecondChance(f, warningAreaForFeature, false)) + newHatchedArea = union(newHatchedArea, warningAreaForFeature); + newUnfilteredArea = union(newUnfilteredArea, warningAreaForFeature); + } + + newHatchedArea = useFilteredArea && newHatchedArea != null ? newHatchedArea : + useFallback ? newUnfilteredArea : null; + + return newHatchedArea != null ? newHatchedArea : new GeometryFactory() + .createGeometryCollection(new Geometry[0]); + } + private String getFips(GeospatialData data) { return geoAccessor.getFips(data); } @@ -3124,6 +3225,7 @@ public class WarngenLayer extends AbstractStormTrackResource { public void setUniqueFip() { Geometry g = state.getWarningArea(); + uniqueFip = null; if (g != null) { if (getAllFipsInArea(g).size() == 1) { Set fips = getAllFipsInArea(g); diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/AreaSourceConfiguration.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/AreaSourceConfiguration.java index 07e25bf5df..752e275f3f 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/AreaSourceConfiguration.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/AreaSourceConfiguration.java @@ -23,6 +23,7 @@ import com.raytheon.uf.common.dataquery.requests.RequestableMetadataMarshaller; * ------------ ---------- ----------- -------------------------- * Mar 29, 2012 #14691 Qinglu Lin Added feAreaField and its getter and setter, etc. * Apr 24, 2014 1943 jsanchez Removed unused areaType. + * Oct 23, 2013 DR 16632 D. Friedman Added inclusionFallback field. * * * @@ -89,6 +90,9 @@ public class AreaSourceConfiguration { @XmlElement private double includedWatchAreaBuffer; + @XmlElement + private boolean inclusionFallback = true; + public AreaSourceConfiguration() { } @@ -271,4 +275,12 @@ public class AreaSourceConfiguration { this.type = type; } + public boolean isInclusionFallback() { + return inclusionFallback; + } + + public void setInclusionFallback(boolean inclusionFallback) { + this.inclusionFallback = inclusionFallback; + } + } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/util/GeometryUtil.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/util/GeometryUtil.java index b26beb59b4..78cb2f787c 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/util/GeometryUtil.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/util/GeometryUtil.java @@ -26,7 +26,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometry; * ------------ ---------- ----------- -------------------------- * Nov 15, 2010 mschenke Initial creation * Apr 28, 2013 1955 jsanchez Added an ignoreUserData flag to intersection method. - * Oct 01, 2013 DR 16632 Qinglu Lin Catch exceptions thrown by intersection(). + * Oct 21, 2013 DR 16632 D. Friedman Handle zero-length input in union. * * * @@ -121,13 +121,8 @@ public class GeometryUtil { if (g1Name == null || g2Name == null || g2Name.equals(g1Name) || ignoreUserData) { - Geometry section = null; - try { - section = g1.intersection(g2); - } catch (Exception e) { - ; //continue; - } - if (section != null && section.isEmpty() == false) { + Geometry section = g1.intersection(g2); + if (section.isEmpty() == false) { if (g2.getUserData() != null) { if (section instanceof GeometryCollection) { for (int n = 0; n < section.getNumGeometries(); ++n) { @@ -210,7 +205,7 @@ public class GeometryUtil { */ public static Geometry union(Geometry... geoms) { List geometries = new ArrayList( - geoms[0].getNumGeometries() + 1); + geoms.length > 0 ? geoms[0].getNumGeometries() + 1 : 0); for (Geometry g : geoms) { buildGeometryList(geometries, g); } diff --git a/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java b/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java index 35096de150..aec3938960 100644 --- a/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java +++ b/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/config/MonitorConfigurationManager.java @@ -212,14 +212,14 @@ public abstract class MonitorConfigurationManager { if (!adjacentAreaFileExists) { AdjacentWfoMgr adjMgr = new AdjacentWfoMgr(currentSite); List zones = adjMgr.getAdjZones(); - if (zones.isEmpty()) { + if (!zones.isEmpty()) { for (String zone : zones) { AreaIdXML zoneXml = new AreaIdXML(); zoneXml.setAreaId(zone); zoneXml.setType(ZoneType.REGULAR); List stations = MonitorAreaUtils .getZoneReportingStationXMLs(zone); - if (stations.isEmpty()) { + if (!stations.isEmpty()) { for (StationIdXML station : stations) { zoneXml.addStationIdXml(station); } diff --git a/edexOsgi/com.raytheon.uf.common.ohd/utility/common_static/base/hydro/Apps_defaults b/edexOsgi/com.raytheon.uf.common.ohd/utility/common_static/base/hydro/Apps_defaults index 9904db1bca..d3908a8b55 100644 --- a/edexOsgi/com.raytheon.uf.common.ohd/utility/common_static/base/hydro/Apps_defaults +++ b/edexOsgi/com.raytheon.uf.common.ohd/utility/common_static/base/hydro/Apps_defaults @@ -1,1876 +1,1871 @@ -# -# Official National .Apps_defaults file for AWIPS Release OB8.3 -# Also see .Apps_defaults_site for override settings -# Revision History: -# 11/06/2001 - adjusted many directory locations of precip_proc tokens. -# notable changes: st3_mkimage, rfcwide_input_dir -# added pproc_local, pproc_local_data, pproc_log -# grouped tokens together for 3 subsystems - shefdecode, whfs, -# precip_proc. -# placed precip_proc section after ofs since there are some -# dependencies -# changed value of whfs_editor -# added hydro_publicbin token -# added pproc_util_log_dir -# 07/01/2002 - added ens_input, ens_output, ens_files -# 07/22/2002 - add global gaff execution token -# 11/04/2002 - added disagg tokens -# 08/29/2003 - added sqlcmd_bin_dir -# 08/20/2003 - added ligtning_input_dir, lightning_log_dir -# 10/03/2003 - added tokens gage_qc, sccqc_threshold, mpe_scc_boxes_failed, -# mpe_msc_precip_limit -# 10/10/2003 - changed token names to mpe_gage_qc, mpe_sccqc_threshold -# - changed mpe_gage_qc token value to ON -# 02/04/2004 - Added new tokens for ens_pre netCDF enhancement --kwz -# 2/4/2004 - added mpe_locbias_1hr_rerun token -# 02/11/2004 - Added hv_map_projection. -# 02/19/2004 - Removed stage2 and stage3 related tokens. -# 03/10/2004 - Added mpe_mlmosaic_calc and rfcwide_mlmosaic_dir tokens. -# 03/16/2004 - Added rfcwide_lsatpre_dir, rfcwide_satstate_var_dir, -# mpe_lsatpre_calc. -# 03/19/2004 - Added mpe_del_gage_zeros. -# 03/22/2004 - added sshp tokens -# 03/24/2004 - Added rpf_min_dur_filled -# 03/31/2004 - Added SSHP tokens -# 04/26/2004 - added sshp_invoke_map_preprocess and -# sshp_java_process_host tokens for the -# mpe_fieldgen scripts -# 05/06/2004 - Added more RFC archive database (adb) tokens -# 06/28/2004 - Added preadj_outts_dir -# 07/31/2004 - Added gage_pp_userid, gage_pp_host, gage_pp_data, gage_pp_log -# and gage_pp_sleep. -# 08/10/2004 - ssh- Added gage_pp_userid, gage_pp_host, gage_pp_data, -# gage_pp_log, gage_pp_sleep, gage_pp_enable, shef_post_precip -# 08/12/2004 - Added timeseries_begintime, timeseries_endtime, timeseries_mode -# timeseries_showcat, timeseries_linewidth, dam_icon_color -# 10/14/2004 - Added the mpe_generate_list token. BAL -# 10/14/2004 - Removed the tokens: mpe_mlmosaic_calc, mpe_lsatpre_calc -# 11/05/2004 - Corrected spelling of timeseries_endime. RAE -# 11/23/2004 - Added the mpe_show_missing_gage token. -# 01/07/2005 - Added the sum_pc_reports token. This controls how PC-based -# precipitation totals are derived. -# 01/10/2005 - Added the sum_pc_reports token. -# 01/28/2005 - Added AWIPS MODIFICATION BLOCK. When gmake is run in the -# development tree location of .Apps_defaults, a copy of it -# will be placed in /awips/hydroapps with the lines modified -# in the AWIPS modification block to work in the /awips/hydroapps -# tree. -# 01/28/2005 - Modified the definitions of adb_shef_pro_err_dir and -# adb_shef_pro_logs_dir. -# Added the pghost, and pguser, pgport tokens for PostGres. -# 04/21/2005 - Changed shefdecode_host and gage_pp_host to dx. -# 04/28/2005 - Added hv_min_dur_filled token. Added ppp_ppd_local_7am_window -# token. -# 5/5/2005 - Added SSHP tokens sshp_initial_forecast_length, sshp_max_forecast_length, -# sshp_sac_update_expiration_hours, sshp_sac_update_hours_forward. -# Moved sshp_fcst_ts to be next to the rest of the SSHP tokens. -# 5/11/2005 - Changed pguser token value to pguser. -# 6/9/2005 - Changed value of grib_rls (location of gribit executable) -# - Added new tokens mpe_d2d_display_grib, d2d_input_dir, mpe_send_grib -# 6/15/2005 - Changed value for d2d_input_dir token -# 9/13/2005 - Replaced the edit_poly token with the rfcwide_drawpre_dir -# token. This directory will contain the precip edit polygons -# drawn in Hydroview/MPE and applied in MPE Fieldgen. -# 9/22/2005 - Added the rfcwide_gageloc_dir and rfcwide_beamheight_dir tokens. -# 9/27/2005 - Added the hdb_db_name token. Contains the name of the database -# used by the historical data browser. -#10/6/2005 - Modified the value of the rfcwide_utiltriangles_dir token to -# be under local/data/app/mpe instead of local/data/mpe. -#10/6/2005 - Added the mpe_base_radar_mosaic token. -#02/7/2006 - Added the mpe_split_screen token. -#02/8/2006 - Added tokens for the PDC Preprocessor -#02/9/2006 - Added mpe_polygon_action_order and mpe_polygon_field_order -# tokens. -#03/2/2006 - Added new tokens for DailyQC. Added renamed MPE tokens. -#04/19/2006 - Added new tokens for controling the orientation/appearance -# of the historical data browser and the locations of the help -# and configuration directory. -#05/30/2006 - Modified the token values for datview_plot_font and anav_data. -# Added the following tokens for archive database programs: -# adb_shef_pro_tmp_dir, adb_shef_raw_tmp_dir, -# adb_shef_raw_add_adjust, rax_pghost, adb_name -#05/30/2006 - Added the mpe_send_qpe_to_sbn token. -#06/06/2006 - Added the grib_set_subcenter_0 token. -#07/07/2006 - Added the ifp_griddb_dir token. -#09/05/2006 - Added the dhm_d2d_data_dir and dhm_d2d_notify_dir tokens. -#10/02/2006 - Added the sshp_map_qpe_to_use token. -#11/02/2006 - Added the mpe_qpe_grib_sbn_dir token. -#11/17/2006 - Added the mpe_qpe_sbn_dir token. -#05/08/2007 - Added tokens for the rfc bias transfer project. -#05/09/2007 - Added 3 tokens for SRG field directories -#05/14/2007 - Added token for rdhm input directory -#O5/23/2007 - Added sshp_show_simulated_timeseries, changed sshp_background_fcst_length to -# sshp_background_forecast_length -#05/23/2007 - Add tokens for RiverPro: rpf_endtime_shifthrs, -# show_vtecqc_window, event_expire_withinhr -#06/18/2007 - Added the send_local_bias_when_rfc_bias_missing token. -# Biasmesgen reads this token to determine whether or not -# to send the locally generated MPE bias to the RPG if -# the RFC bias is not available. -#06/28/2007 - Added DailyQC preprocessor token dqc_preprocessor_basetime -#07/17/2007 - Added rgb_file_path token. Used by new Color Manager in Hydroview -# and MPE Editor. -#10/24/2007 - Added dhm_rain_plus_melt_data_dir token -#11/08/2007 - Added tokens for IHFS->RAX Synchronization: adb_sync_logs_dir, -# adb_sync_mode, adb_sync_tablenames, adb_sync_ihfs_ingest, adb_sync_rivercrit -#1/16/2008 - added new tokens for disagg processing -# mpe_disagg_execute, mpe_disagg_method, mpe_disagg_6hreq_0,mpe_disagg_6hrgt_0 -#3/22/2008 - Added variable substitution for database port. -# -#3/5/2008 - Modified the value of the mpe_mmosaic_dir token. There was a typo in the -# product name. It was mrmosaic. It is now mmosaic. -#05/19/2008 - Added sshp_hpn_minutes_before and sshp_hpn_minutes_after tokens. -# These tokens define the time window for the SSHP HPN Prerocessor. -#07/07/08 - Added sshp_show_unadjusted_states // for sshp -# -#10/01/09 - Added 5 tokens for arcnav application. //only for arcnav for raxum application -#10/03/12 - Added token section for script execution - - -# ============================================================================== -# To see syntax rules for this file, see the bottom of this file -# -# Also see .Apps_defaults_site for overriding settings -# - -#$============================================================================= -#$ This section contains the tokens whose values are different between the -#$ development and the delivery tree. The value give is the development -#$ value. The commented value is the delivery value. The uncommented value -#$ is in the development tree. All of these tokens must be enclosed -#$ by the AWIPS_MODIFICATION_BLOCK_BEGIN and AWIPS_MODIFICATION_BLOCK_END -#$ tags. Token names and commented lines should at column 1. - -#AWIPS_MODIFICATION_BLOCK_BEGIN - -apps_dir : $(SHARE_DIR)/hydroapps # Hydrologic applications directory - -data_archive_root : /data_store # root directory of the data archive - -mcp3_icp_iface : $(HOME)/mcp3_ntrfc -#mcp3_icp_iface : /tmp/$(LOGNAME)/mcp3_ntrfc - -verify_dir : $(apps_dir)/rfc/verify #base verify directory -#verify_dir : /rfc_arc/verify #base verify directory - -vsys_dir : $(apps_dir)/rfc/verify #base verify directory -#vsys_dir : $(verify_dir) #base verify directory - -#AWIPS_MODIFICATION_BLOCK_END - -#===================== Apps/Script Execution Tokens ================================= -WhfsSrv : ON -WhfsSrv.purge_files : ON -WhfsSrv.run_db_purge : ON -WhfsSrv.run_floodseq : ON -PprocSrv : ON -PprocSrv.purge_mpe_files : ON -PprocSrv.purge_hpe_file : ON -MpeFieldGenSrv.run_mpe_fieldgen : ON -WhfsSrv.run_pdc_pp : ON -WhfsSrv.run_alarm_whfs : ON -WhfsSrv.run_alarm_whfs.run_roc_checker : ON -WhfsSrv.run_alarm_whfs.run_report_alarm : ON -WhfsSrv.run_alarm_whfs.run_report_alarm.textdb : ON -ArealQpeGenSrv : ON -DqcPreProcSrv : ON -DqcPreProcSrv.run_dqc_preprocessor : ON -MpeRUCFreezingLevel : ON -MpeLightningSrv : ON -#==================================================================================== - -# ============================================================================== - -# Executable directory tokens. -sys_java_dir : /awips2/java # Location of Java COTS software -hydro_publicbin : $(apps_dir)/public/bin -sqlcmd_bin_dir : /usr/local/sqlcmd/bin # location of sqlcmd executable on both HP and - # Linux beginning in OB3 - -################################################################################# -# Default Display Maps - comma separated list of maps with no spaces -# Map names can be found in the localization perspective under -# CAVE->Bundles->Maps. Use the filename without the extension. -# statesCounties.xml -> statesCounties -# -# display_maps - default display maps for Hydro Perspective -# mpe_display_maps - default display maps for MPE Perspective -display_maps : statesCounties -mpe_display_maps : statesCounties -################################################################################# - -# database selection tokens -server_name : ONLINE # Informix database server name -db_name : hd_ob92lwx # IHFS database name -damcat_db_name : dc_ob5xxx # Dam Catalog database name -hdb_db_name : ob81_histdata # Historical database. -pghost : localhost # The machine PostGres is running on -pguser : awips # The user allowed to access PostGres -pgport : 5432 # The PostGres Server port -adb_name : adb_ob7xxx # RFC archive database name -rax_pghost : ax # The machine PostGres is running on for the adb - -# vacuum log dir token. -vacuum_log_dir : $(whfs_log_dir)/vacuum - -# WHFS specific tokens -whfs_tz : EST5EDT # WHFS time zone for local time -whfs_primary_radar : TLX # WHFS primary radar id, for Stage II - -# damcat tokens -damcat_hostoffice_type : wfo # source of run-from office -damcat_office_datasource : ohd # which data source is used -max_storage_value : 0.00 # max storage volume filter -damcat_data : /tmp/damcatData - -# Damcrest tokens -damcrest.db_enabled : true # set to true when the user has damcat database -damcrest.hasListAllDams : true # when set to true, all dams will be displayed initially - -# Path to the editor used by Damcrest -damcrest.editor : /usr/bin/gvim - -# Path to the damcrest data directory where input and output files -# of the model are stored -damcrest_data_dir : $(whfs_local_data_dir)/damcrest - -# Path to the directory where .vimrc resource file resides. -# This resource file is needed when editor in Damcrest application -# is set to gvim. -damcrest_res_dir : $(whfs_config_dir)/damcrest - -#===================== SHEFDECODE Application Tokens ================================ - -shefdecode_userid : oper # controlling UNIX user -shefdecode_host : dx1f # controlling UNIX system. -shefdecode_dir : $(apps_dir)/shefdecode # main directory location -shefdecode_bin : $(shefdecode_dir)/bin # executable programs location -shefdecode_input : $(shefdecode_dir)/input # SHEF parameter file location -shef_data_dir : /data/fxa/ispan/hydro # input products location - -shefdecode_log : $(shefdecode_dir)/logs/decoder # daily log files location -shef_error_dir : $(shefdecode_dir)/logs/product # product log files location -shef_keeperror : ALWAYS # keep product log files (=ALWAYS) or - # only when errors occur (=IF_ERROR) -shef_perflog : ON # ON/OFF - create a separate performance log file to - # save internal decoder timing messages for - # monitoring performance -shef_data_log : ON # ON/OFF - include messages in the log file detailing - the SHEF records -dupmess : ON # ON/OFF - include messages in the log file about - # duplicate data -elgmess : ON # ON/OFF - include messages in the log file about - # data types not found in IngestFilter or - # data types turned off in IngestFilter -locmess : ON # ON/OFF - include messages in the log file about - # stations and areas not found in Location - # or GeoArea - -shef_sleep : 10 # sleep duration in seconds in between queries -shef_winpast : 10 # number of days in past to post data -shef_winfuture : 30 # number of minutes in future to post obs data -shef_duplicate : IF_DIFFERENT # flag for handling duplicate date - # ALWAYS_OVERWRITE-always overwrite when value repeats - # USE_REVCODE-if revcode set overwrite duplicate value - # IF_DIFFERENT-overwrite if new value is different - # IF_DIFFERENT_OR_REVCODE-overwrite if new value is - # different or revcode is set -shef_load_ingest : ON # ON/OFF - automatically load the IngestFilter table or not - # with (station id-PEDTSE) combinations as they - # arrive in the input data flow -shef_storetext : OFF # ON/OFF - post/don't post raw encoded SHEF text messages - # to the TextProduct table -shef_post_unk : NONE # NONE - do not post to the UnkStn nor UnkStnValue tables - # IDS_ONLY - post only location identifiers for unknown - # stations to the UnkStn table - # IDS_AND_DATA - post all data from unknown stations to - # the UnkStnValue table -shef_post_baddata : REJECT # PE/REJECT - post data that have failed the gross range - # check to the physical element data tables (=PE) OR - # to the RejectedData table (=REJECT) -shef_procobs : OFF # ON/OFF - post Processed data values (i.e., TS=P*) to - # the observation data tables (=ON) or to - # the ProcValue table (=OFF) -shef_post_latest : ON # ON/OFF - post/don't post data to the LatestObsValue table - # VALID_ONLY - post data to the LatestObsValue table - # ONLY if the gross range check is passed -shef_post_link : ON # ON/OFF - post/don't post data to the ProductLink table -shef_load_maxfcst : ON # ON/OFF - after each product that resulted in forecast - # height or discharge data being posted, load - # the maximum forecast data into the RiverStatus table -shef_alertalarm : ON # ON/OFF - causes shefdecoder to screen data against - # alert and alarm thresholds -# -- Intermediate output from ShefParser prior to post -shef_out : OFF - - -#===================== WHFS Applications Tokens ================================ - -whfs_base_dir : $(apps_dir)/whfs # top of the WHFS tree -whfs_local_dir : $(whfs_base_dir)/local # top of WHFS local tree -whfs_local_data_dir : $(whfs_local_dir)/data # top of WHFS local data tree -whfs_local_grid_dir : $(whfs_local_data_dir)/grid # top of WHFS grids tree -whfs_log_dir : $(whfs_local_data_dir)/log # top of WHFS logs tree - -whfs_local_bin_dir : $(whfs_local_dir)/bin # local WHFS executables - -whfs_geodata_dir : $(whfs_local_data_dir)/geo # WHFS map backgrounds -whfs_image_dir : $(whfs_local_data_dir)/image # user-saved image files -whfs_import_dir : $(whfs_local_data_dir)/import # files to import into WHFS -whfs_product_dir : $(whfs_local_data_dir)/product # WHFS generated external products -whfs_report_dir : $(whfs_local_data_dir)/report # user-saved text reports -whfs_lines_per_page : 60 - -whfs_config_dir : $(whfs_local_data_dir)/app # WHFS app configuration files -rpf_template_dir : $(RPF_TEMPLATE_DIR) # RiverPro templates -metar_config_dir : $(whfs_config_dir)/metar2shef # METAR translator config -metar2shef_options : " -a -b -p1 -y2k -salias -p6 -p24 -round -w -strip " -ts_config_dir : $(whfs_config_dir)/timeseries # Time Series config -hv_config_dir : $(whfs_config_dir)/hydroview # Hydroview pixmaps etc. -hv_help_dir : $(hv_config_dir)/help/ # Hydroview Help direc. -rivermon_config_dir : $(whfs_config_dir)/rivermon/ # RiverMonitor Conf dir. - -whfs_misc_grid_dir : $(whfs_local_grid_dir)/misc # misc WHFS grids - -rgb_file_path : /usr/share/X11/rgb.txt # Location of X/Motif color file. - -rpf_log_dir : $(RPF_LOG_DIR) # RiverPro logs -rivermon_log_dir : $(whfs_log_dir)/rivermon # RiverMonitor logs -obsfcstmonitor_log_dir : $(whfs_log_dir)/obsfcst_monitor # ObsFcstMonitor logs -whfs_util_log_dir : $(whfs_log_dir)/misc # WHFS misc logs -precip_accum_log_dir : $(whfs_log_dir)/precip_accum # precip_accum logs -floodseq_log_dir : $(whfs_log_dir)/floodseq # flood sequencer logs -metar_log_dir : $(whfs_log_dir)/metar2shef # METAR translator logs -hb_gagrad_log_dir : $(whfs_log_dir)/create_gagradloc # gage-radar locator logs -qcalarm_log_dir : $(whfs_log_dir)/qcalarm # batch QC logs - -db_purge_log_dir : $(whfs_log_dir)/db_purge # db_purge token -db_purge_backup_retention_use : ON # db_purge token for using backup retention value - -purge_files_log_dir : $(whfs_log_dir)/misc # purge_files token - -whfs_bin_dir : $(whfs_base_dir)/bin # WHFS executables -sws_parent_dir : $(whfs_bin_dir) # SWS parent dir -sws_home_dir : $(whfs_bin_dir)/pa # SWS dir - -# ----------------------------------------------------------------- -# The Gage Precip Processor tokens -# ----------------------------------------------------------------- - -gage_pp_userid : oper # controlling UNIX user -gage_pp_host : dx # controlling UNIX system -gage_pp_data : $(pproc_local_data)/gpp_input # input data files location -gage_pp_log : $(pproc_log)/gage_pp # daily log files location -gage_pp_sleep : 10 # sleep duration in seconds in between queries -gage_pp_enable : ON # gpp enabled; shef uses to determine post -shef_post_precip : OFF # post to Precip/CurPrecip tables -build_hourly_enable : ON # Enable the build_hourly application - -# ---------------------------------------------------------------- -# The following tokens are most likely to be customized by the user -# (the first 4 MUST be customized at each site in the .Apps_defaults_site file) -# ---------------------------------------------------------------- -hv_center_lat : 35.0 # HydroView center latitude -hv_center_lon : -97.8 # HydroView center longitude -hv_height_in_pixels : 900 # Hydroview map height in pixels -hv_width_in_pixels : 1200 # Hydroview map width in pixels -hv_map_width : 320 # HydroView map width (nautical miles) -hv_pointdata_display : ON # Hydroview point data display flag (ON, OFF) -hv_hours_in_window : 4 # Change window hours -hv_zoom_out_limit : 20 # Limits how far the map can be zoomed out -hv_disclosure_limit : 60 # Prog disclosure limit -hv_zoom_threshold : 150 # nautical miles; Hydroview - # detail level for cities/towns -hv_map_projection : FLAT # Sets default map projection used in - # hydroview/MPE. Options are FLAT, POLAR - # or HRAP. -hv_refresh_minutes : 15 # HydroView auto refresh time (minutes) -hv_riverbasis : maxobsfcst # initial river basis for river characteristics -hv_min_dur_filled : 0.0 # Minimum percentage of accum interval covered - # by precip data. -ppp_ppd_local_7am_window : 3 # Number of +/- hours around 7 AM local to - # to use PPP and PPD reports for 24 hour - # precip summaries. - # values either obs, fcst, maxobsfcst -shefencode_prodid : CCCCNNNXXX # product identifier for outgoing SHEF - # encoded messages from Hydro Time Series -whfs_editor : whfs_editor # WHFS text editor -rpf_linewidth : 80 # width of line in RiverPro generated products -rpf_min_dur_filled : 0.25 # min percent time of requested precip dur in RiverPro -office_prefix : K # fourth char prepended to 3-char office id -vtec_record_stageoffset : 2.0 # ft offset from record value for H-VTEC field -vtec_record_flowoffset : 5000.0 # cfs offset from record value for H-VTEC field -pproc_s2_gridgen_hrs : 5 # WHFS Stage II lookback (hours) -whfs_min_dur_filled : 0.83 # WHFS min fractional time duration needed for radar accumulations -whfs_min_area_covered : 0.80 # WHFS min fractional area needed to compute MAPs -whfs_printcommand_HP : lp # command used to print WHFS apps reports on HP -whfs_printcommand_LX : lp # command used to print WHFS apps reports - # on LX -whfs_e19_print_command : "lp -o cpi=19 -o lpi=7" # command used to print e19 text reports - -dam_icon_color : BROWN # Color used for dam icon in Hydroview -timeseries_begintime : 5 # number of days back relative to current time -timeseries_endtime : 3 # number of days ahead relative to current time -timeseries_showcat : 2 # scale by data and show categories -timeseries_linewidth : 1 # width of line drawn on graph -timeseries_mode : STATION # set to GROUP or STATION mode -timeseries_dist_shef : OFF # ON/OFF token for the shef send script distribute check box - # Defaults to off if not set -rpf_stage_window : 0.5 # set stage window for determining the trend - # variables in RiverPro -show_vtecqc_window : IF_ERROR #or ALWAYS, used in RiverPro -rpf_endtime_shifthrs : 6 # in RiverPro -event_expire_withinhr : 3 # in RiverPro - -#=====Tokens To Generate Areal FFG from Mosaicked FFG Grids for Use By SSHP===== -# (NOTE: gaff_rfc_list MUST be customized at EVERY Field Office) - -gaff_execution : ON # ON/OFF token for the gen_areal_ffg process - # the gen_areal_ffg process is run from the - # process_dpa_files script at WFOs -gaff_rfc_list : ABRFC,LMRFC # list of RFCs to be mosaicked - # list is comma separated, no embedded - # spaces are allowed -gaff_input_dir : $(EDEX_HOME)/data/processing - # directory containing gridded FFG - # generated by RFCs -gaff_look_back_limit : 60 # number of hours to look back for valid gridded - # FFG data for input -gaff_mosaic_dir : $(whfs_misc_grid_dir) # directory containing output - # mosaicked gridded FFG in - # netCDF format -gaff_durations : 1,3,6 # FFG durations in hours - # list is comma separated, no embedded - # spaces are allowed - - -# ================= "ds_" system tokens (see more in site file) =============== - -ofs_dir : $(apps_dir)/rfc/nwsrfs/ofs -util_dir : $(apps_dir)/rfc/nwsrfs/util -calb_dir : $(apps_dir)/rfc/nwsrfs/calb -ifp_dir : $(apps_dir)/rfc/nwsrfs/ifp -icp_dir : $(apps_dir)/rfc/nwsrfs/icp -ens_dir : $(apps_dir)/rfc/nwsrfs/ens -fld_dir : $(apps_dir)/rfc/fld - - -hdb_dir : $(apps_dir)/rfc/hdb - -# = = = = = = = = = = = = = = = = = = = = = = end "ds_" system requirements = = - -ofs_rls : $(ofs_dir)/bin/RELEASE -util_rls : $(util_dir)/bin/RELEASE -calb_rls : $(calb_dir)/bin/RELEASE -ffg_rls : $(ffg_dir)/bin/RELEASE -ifp_rls : $(ifp_dir)/bin/RELEASE -icp_rls : $(icp_dir)/bin/RELEASE -ens_rls : $(ens_dir)/bin/RELEASE -hdb_rls : $(hdb_dir)/bin/RELEASE -fld_rls : $(fld_dir)/bin/RELEASE -xsets_rls : $(xsets_dir)/bin/RELEASE -xnav_rls : $(xnav_dir)/bin/RELEASE -xdat_rls : $(xdat_dir)/bin/RELEASE - -ofs_arc : $(ofs_dir)/bin/ARCHIVE -util_arc : $(util_dir)/bin/ARCHIVE -calb_arc : $(calb_dir)/bin/ARCHIVE -ffg_arc : $(ffg_dir)/bin/ARCHIVE -ifp_arc : $(ifp_dir)/bin/ARCHIVE -icp_arc : $(icp_dir)/bin/ARCHIVE -ens_arc : $(ens_dir)/bin/ARCHIVE -hdb_arc : $(hdb_dir)/bin/ARCHIVE -fld_arc : $(fld_dir)/bin/ARCHIVE -xsets_arc : $(xsets_dir)/bin/ARCHIVE -xnav_arc : $(xnav_dir)/bin/ARCHIVE -xdat_arc : $(xdat_dir)/bin/ARCHIVE -# = = = = = = = = = = = = = = = = = = = = = = end of other "ds_" tokens = = = = - -# LDAD shefencode tokens -ldad_data_dir : /awips/ldad/data # the LDAD internal data dir -shefenc_pe_table : $(ldad_data_dir)/ShefEncoder_PE.tbl -shefenc_units_table : $(ldad_data_dir)/ShefEncoder_Units.tbl - -# NWSRFS tokens - -rfs_dir : $(apps_dir)/rfc/nwsrfs # Top-level rfs mt. -rfs_sys_dir : $(rfs_dir)/sys_files # RFS system files -rfs_doc : $(rfs_dir)/doc # NWSRFS documentation - -# OFS tokens -locks_dir : $(rfs_dir)/locks -ofs_lock_max_wait : 60 # no. of mins to wait to get an ofs lock -ofs_lock_wait_interval : 5 # no. of secs 'tween retries to get an ofs lock -ofs_locks_max_pass : 4 # no. of attempts to make to get a set of locks. - -ofs_level : oper -ofs_reor_lvl : oper_new -ofs_inpt_grp : oper - -home_files_workstation : ds - -ofs_log_output : off # whether to output file r/w info -ofs_error_output : on # whether to output file error info -fortran_stderr : 7 # FORTRAN standard error unit - -ofs_bin : $(ofs_dir)/bin # OFS executables dir -ofs_files : $(ofs_dir)/files # OFS file group -ofs_fs5files : $(ofs_files)/$(ofs_level)/fs5files # OFS files dir -ofs_reorder_dir : $(ofs_files)/$(ofs_reor_lvl)/fs5files # OFS reordered files -ofs_output : $(ofs_dir)/output # OFS output dir -ofs_input : $(ofs_dir)/input/$(ofs_inpt_grp) # OFS input dir -ofs_input_dflt : $(ofs_dir)/input/$(ofs_inpt_grp) # OFS input dir -ofs_shefdata_dir: $(ofs_files)/$(ofs_level)/shefdata # OFS SHEF data dir -ofs_shefout_dir : $(ofs_files)/$(ofs_level)/shefdata # OFS shefout file dir -ofs_mods_dir : $(ofs_files)/$(ofs_level)/mods # OFS MODS files dir -ofs_griddb_dir : $(ofs_files)/$(ofs_level)/griddb # OFS gridded fields -ofs_scripts : $(ofs_dir)/scripts # OFS scripts dir -ofs_server : apwk01g2 # OFS "slave" server -my_output : $(ofs_output)/$(LOGNAME) # users ofs output files - -ndfd2rfs_input : $(ofs_files)/$(ofs_level)/ndfd -ndfd2rfs_output : $(my_output) -ndfd2rfs_log_level : 0 - -fldview_dir : $(apps_dir)/rfc/fldview/floodmapdata - -# calb tokens -calb_bin : $(calb_dir)/bin -calb_lib : $(calb_dir)/lib - -calb_data_grp : oper -calb_inpt_grp : oper -calb_input : $(calb_dir)/input/$(calb_inpt_grp) -calb_output : $(calb_dir)/output -calb_sta_ts_dir : $(calb_dir)/data/sta_ts/$(calb_data_grp) -calb_area_ts_dir : $(calb_dir)/data/area_ts/$(calb_data_grp) -peakflow_data_dir : $(calb_dir)/data/area_ts/$(calb_data_grp) - -calb_gzio_read : off # whether or not to read gzipped DATACARD files -calb_gzio_write : off # whether or not to write gzipped DATACARD files - -nwsrfs_calbfile_default : CARD # default calibration file type -nwsrfs_platform : AIX # operating system - -# ICP tokens -icp_bin : $(icp_dir)/bin -icp_pw : hILLEL -icp_scripts : $(icp_dir)/scripts - -mcp_decks : $(calb_input)/mcp3 -mcp_dir : $(calb_rls) - -# IFP tokens -ifp_help_dir : $(ifp_dir)/help_files # IFP help files -ifp_bin_dir : $(ifp_dir)/bin/RELEASE # IFP bin files - ref in code -ifp_nwsrfs_bin_dir : $(ifp_dir)/bin/RELEASE # ifp_nwsrfs bin - ref in code -ifp_sys_dir : $(ifp_dir)/system # IFP system files -ifp_scripts_dir : $(ifp_dir)/scripts # IFP script files -ifp_options_dir : $(ifp_dir)/options # IFP options files -ifp_colors_dir : $(ifp_options_dir)/colors # IFP color files -ifp_fs5files : $(HOME)/ofs_ifp/fs5files # user copy of fs5files -ifp_rfc : host # name of RFC to run -ifp_num_columns : 3 # number of columns to display -ifp_gif_files : $(ofs_files)/$(ofs_level)/gif_files # gif files directory -ifp_sacco_dir : $(ofs_files)/$(ofs_level)/sacsnow_clim -ifp_dhm_data_dir : /data/dhm/$(LOGNAME) -ifp_griddb_dir : $(ifp_dhm_data_dir)/precip - -# Ensemble (ens) tokens - -espts_dir : $(ens_dir)/files/$(ofs_level)/espts #espts files esp -espadp_dir : $(ens_dir) -preadj_dir : $(ens_dir)/files/$(ofs_level)/cpc_fcsts -ens_input : $(ens_dir)/input/$(ofs_level) -ens_output : $(ens_dir)/output -ens_files : $(ens_dir)/files/$(ofs_level) -ens_scripts : $(ens_dir)/scripts - -# ens_pre tokens -##FXA_HOME : /px1data #taken out by kwz.2/11/04 -enspre_griddb : $(FXA_DATA)/Grid/SBN/netCDF/CONUS211/CPCoutlook -ens_log_dir : $(ens_output)/$(ofs_level) -ens_msglog_level : 5 -preadj_outts_dir : $(calb_area_ts_dir)/pre - -# FLDGRF tokens (added 6 April 2000) - -fldgrf_iface : $(HOME)/fldgrf - -# ofsde tokens - -ofsde_log_dir : $(ofs_output)/ofsde_logs # ofsde log dir - # (formerly ofsde_output_dir) -ofsde_ndate : 7 # number of days to search for forecast temps -ofsde_rrstime_check : OFF # flag to check obs times of RRS data - # against window around 12Z (OFF/ON) - -# intervals for max/min temperatures (used by ofsde) -# these represent number of hours around 12z - -intlrmn : 8 -inturmn : 2 -intlrzn : 2 -inturzn : 2 -intlrzx : 8 -inturzx : 2 -siipp_calc_624_PP : OFF # flag for calculating 6hr and 24hr - # PP data from PC data - # if running RFCWide, should be set to OFF - -# defaults for geographic data - -geo_data : $(apps_dir)/geo_data -geo_util : $(geo_data)/util - -geo_ifp_bin : $(geo_data)/$(ifp_rfc)/binary -geo_ifp_ascii : $(geo_data)/$(ifp_rfc)/ascii - -#===================== PRECIP_PROC Application Tokens ======================== - -# precip_proc directory - -pproc_dir : $(apps_dir)/precip_proc # precip proc top - # level dir -pproc_bin : $(pproc_dir)/bin # dir with precip proc exes -pproc_local : $(pproc_dir)/local # dir with local items, esp. data -pproc_local_data : $(pproc_local)/data # dir with local data -pproc_local_bin : $(pproc_local)/bin # dir with local bin -pproc_log : $(pproc_local_data)/log # dir with local logs - -pproc_util_log_dir : $(pproc_log)/misc # miscellaneous logs - -# DecodeDPA tokens (formerly DecodeHDP tokens that looked like hdp_*) - -dpa_log_dir : $(pproc_log)/decodedpa # DPA Decoder logs -dpa_prod_dir : /data/fxa/ispan/hdp # DPA input directory -dpa_gather : $(pproc_local_data)/dpa_gather # DPA gather directory -dpa_error_dir : $(pproc_local_data)/stage1_error # DPA error files -dpa_arch_dir : $(pproc_local_data)/stage1_archive # DPA archives -dpa_wind : 10 - - -dpa_filter_decode : ON # flag for non-top-of-hour - # filtering of decoded products - # ON - filter products for decode - # OFF - do not filter (ie decode all products) - -dpa_decode_window : 10 # number of minutes around top - # of hour for filtering products for - # decoding - -dpa_archive : OFF # ON/OFF flag for archiving products - # OFF - do not archive products - # ON - archive products and filter based - # on value of dpa_archive_window - -dpa_archive_window : 10 # number of minutes around top - # of hour for filtering products for archiving - -dpa_dirname1 : $(data_archive_root)/radar # first part of directory name - # containing DPA products for - # associated or dial in radars -dpa_dirname2 : DPA/layer0/res4/level256 # second part of directory name - # containing DPA products for - # associated or dial in radars -dpa_grid_dir : $(pproc_local_data)/stage1_decoded # decoded DPA radar grids - -# siipp tokens - -intpc : 10 # interval (minutes) around top of hour for using PC data -intlppp : 2 -intuppp : 2 -intppq : 2 -siipp_log_dir : $(pproc_log)/siipp # Stage II preprocessor logs - # (formerly siipp_output_dir) - -# tokens for stageiii -st3_help : $(pproc_local_data)/app/stage3/help # online help text - -st3_rfc : host -awips_rfc_id : TUA # 3 char AWIPS RFC identifier - # must be all upper case - -# tokens for stageiii output -st3_mapx_id : xmrg # identifier for Stage 3 output -st3_date_form : mdY # date format - # current allowable = Ymd or mdY - # similar to formatting codes for - # strftime function - -st3_output : $(ofs_griddb_dir) # dir for xmrg files for MAPX - # ofs_griddb_dir defined outside of pproc -st3_out_dir : $(pproc_local_data)/stage3 -post_output : $(st3_out_dir)/post_analysis - -# defaults for netCDF output - -st3_netcdf_loc : arkansas_red_basin_river_forecast_center_tulsa_ok - # underscores needed between words -st3_netcdf_swlat : 33.603 -st3_netcdf_swlon : 106.456 -st3_netcdf_selat : 32.433 -st3_netcdf_selon : 92.322 -st3_netcdf_nelat : 38.027 -st3_netcdf_nelon : 90.678 -st3_netcdf_nwlat : 39.420 -st3_netcdf_nwlon : 106.652 - -#defaults for auto stageiii -st3_auto_graphic_scale : 2.4 # used by gif file generation - -#===================== disagg Tokens (old disagg process)======================== - -disagg_msglog_level : 30 # message level - # possible values are 1,10,20,30,...80 - # lower values signify less info in log - -disagg_dur : 24 # maximum duration of precip gage data to - # be disaggregated - # possible values = 2,3,...,24 - -disagg_look_back : 0 # time (hours) to look back from current hour - # for precip gage data to be disaggregated - -disagg_radius : 3 # number of HRAP bins within which the QPE - # will be averaged for disagg - # for example, if disagg_radius = 3, then - # the 9 nearest neighbor QPE bin values - # will be averaged -disagg_set_date : 0 # identifier for current date (yyyymmdd). - # Default value is 0 - set to - # today date - -disagg_set_hour : 0 # identifier for current hour (hh). - # Default value is 0 - # Possible values = 0,1,2,3,...,23 - -disagg_log_dir : $(pproc_log)/disagg # directory containing disagg logs - -# =============== Multi-Sensor Precipitation Estimator (MPE) ================ - -rfcw_rfcname : host -rfcwide_logs_dir : $(pproc_log)/mpe_fieldgen -hmap_mpe_timelapse : 1000 # time between images, in milliseconds, for the MPE - # time lapse display - -### tokens for input ### - -rfcwide_input_dir : $(pproc_local_data)/app/mpe - -rfcwide_satpre_dir : $(mpe_fieldgen_product_dir)/satpre - -# the help_dir token needs a trailing slash because it is required byt -# the RFC software the processes the help info... - -rfcwide_help_dir : $(rfcwide_input_dir)/help/ -rfcwide_misbin_dir : $(rfcwide_input_dir)/misbin -rfcwide_prism_dir : $(rfcwide_input_dir)/prism -rfcwide_gageloc_dir : $(rfcwide_input_dir)/gage_locations -rfcwide_beamheight_dir : $(rfcwide_input_dir)/beam_height -rfcwide_utiltriangles_dir : $(rfcwide_input_dir)/utiltriangles - -### tokens for output ### -### NOTE: xmrg files are stored in dir defined by rfcwide_xmrg_dir token below - -rfcwide_output_dir : $(pproc_local_data)/mpe # fka ofs_griddb_dir defined outside of pproc - -rfcwide_gagetriangles_dir : $(rfcwide_output_dir)/gagetriangles -rfcwide_drawpre_dir : $(rfcwide_output_dir)/draw_precip - -rfcwide_avg_rmosaic_dir : $(rfcwide_output_dir)/avgrmosaic -rfcwide_max_rmosaic_dir : $(rfcwide_output_dir)/maxrmosaic -rfcwide_rmosaic_dir : $(rfcwide_output_dir)/rmosaic -rfcwide_bmosaic_dir : $(rfcwide_output_dir)/bmosaic -rfcwide_mmosaic_dir : $(rfcwide_output_dir)/mmosaic -rfcwide_mlmosaic_dir : $(rfcwide_output_dir)/mlmosaic -rfcwide_lmosaic_dir : $(rfcwide_output_dir)/lmosaic -rfcwide_lsatpre_dir : $(rfcwide_output_dir)/lsatpre -rfcwide_gageonly_dir : $(rfcwide_output_dir)/gageonly - -rfcwide_height_dir : $(rfcwide_output_dir)/height -rfcwide_index_dir : $(rfcwide_output_dir)/index -rfcwide_locbias_dir : $(rfcwide_output_dir)/locbias -rfcwide_locspan_dir : $(rfcwide_output_dir)/locspan -rfcwide_p3lmosaic_dir : $(rfcwide_output_dir)/p3lmosaic - -rfcwide_xmrg_dir : $(rfcwide_output_dir)/qpe -rfcwide_statevar_dir : $(rfcwide_output_dir)/state_var -rfcwide_sat_statevar_dir : $(rfcwide_output_dir)/sat_state_var -mpe_q2_statevar_dir : $(rfcwide_output_dir)/q2_state_var - -# ==================== MPE Tokens =============================== - -#daily qc options token defaults to 'off' where daily qc options are grayed out; values are 'on' and 'off' -mpe_dqc_options : off -mpe_map_background_color : GRAY20 # The default color of the MPE map background -mpe_temperature_window : 60 # The window in minutes the dqc preprocessor - # searches around a synoptic time - # (00z,06z,12z,18z) for temperature data. -mpe_maxminT_hour_window : 2 -mpe_dqc_max_precip_neighbors : 30 -mpe_dqc_max_temp_neighbors : 20 -mpe_dqc_precip_deviation : 3.0 -mpe_dqc_temperature_deviation : 10.0 -mpe_dqc_min_good_stations : 5 -mpe_copy_level2_dqc_to_ihfs_shef : OFF -mpe_copy_level2_dqc_to_archive_shef : OFF -mpe_dqc_num_days : 10 -mpe_dqc_warningpopup : on -mpe_dqc_6hr_24hr_set_bad : OFF # Define logic if user sets a 6hr value to Bad in the - # Edit Precip Stations window. - # OFF – if user sets 6hr value to Bad; 24hr value unaffected - # ON - if user sets 6hr value to Bad; 24hr value set to Bad - # Added at request of MBRFC to help with QC of SNOTEL. - -mpe_dqc_grid_max_dist : 70 # Max distance (units of grid bins) between a grid bin and a - # station to use the station to estimate the value at the grid bin. - -mpe_dqc_output_qc_file : OFF # ON/OFF default = OFF - -mpe_dqc_execute_internal_script : OFF # ON/OFF - -mpe_dqc_24hr_precip_grid_meth : USE_24HR # We use the token values of ACCUM_6HR and USE_24HR -mpe_td_new_algorithm : OFF # flag set for new algorithm in calculating Time Distributed estimate, the default - # is false -mpe_dqc_gridtype : SCALAR -mpe_dqc_projectiontype : POLAR_STEREOGRAPHIC -mpe_dqc_lonorigin : -105. - -#daily qc preprocessor tokens -dqc_preprocessor_basetime : 12Z #The value can be 12Z, 18Z, 00Z, or 06Z - -### MPE base directory tokens. -mpe_dir : $(pproc_local_data)/mpe -mpe_gageqc_dir : $(mpe_dir)/dailyQC -mpe_scratch_dir : $(mpe_gageqc_dir)/scratch -mpe_app_dir : $(pproc_local_data)/app/mpe -mpe_fieldgen_product_dir : $(mpe_dir) - -### MPE station list tokens -mpe_station_list_dir : $(mpe_app_dir)/station_lists -mpe_site_id : ounx -mpe_area_names : $(mpe_site_id) - -### MPE static data files -mpe_prism_dir : $(mpe_app_dir)/prism -mpe_misbin_dir : $(mpe_app_dir)/misbin -mpe_utiltriangles_dir : $(mpe_app_dir)/utiltriangles -mpe_beamheight_dir : $(mpe_app_dir)/beam_height -mpe_climo_dir : $(mpe_app_dir)/climo -mpe_help_dir : $(mpe_app_dir)/help -mpe_gridmask_dir : $(mpe_app_dir)/grid_masks -mpe_basin_file : $(whfs_geodata_dir)/basins.dat - -### MPE precipitation gage qc directories -mpe_precip_data_dir : $(mpe_gageqc_dir)/precip -mpe_bad_precip_dir : $(mpe_precip_data_dir)/bad -mpe_dev_precip_dir : $(mpe_precip_data_dir)/dev -mpe_map_dir : $(mpe_precip_data_dir)/MAP -mpe_grid_precip_dir : $(mpe_precip_data_dir)/grid -mpe_point_precip_dir : $(mpe_precip_data_dir)/point - -### MPE temperature gage qc directories -mpe_temperature_data_dir : $(mpe_gageqc_dir)/temperature -mpe_bad_temperature_dir : $(mpe_temperature_data_dir)/bad -mpe_dev_temperature_dir : $(mpe_temperature_data_dir)/dev -mpe_mat_dir : $(mpe_temperature_data_dir)/MAT -mpe_grid_temperature_dir : $(mpe_temperature_data_dir)/grid -mpe_point_temperature_dir : $(mpe_temperature_data_dir)/point - -### MPE freezing level gage qc directories -mpe_freezing_data_dir : $(mpe_gageqc_dir)/freezing_level -mpe_maz_dir : $(mpe_freezing_data_dir)/MAZ -mpe_grid_freezing_dir : $(mpe_freezing_data_dir)/grid -mpe_point_freezing_dir : $(mpe_freezing_data_dir)/point -ruc_model_data_dir : /data/fxa/Grid/SBN/netCDF/CONUS211/RUC - -### MPE 1 hour mosaics and fields and supporting reference fields. -mpe_avgrmosaic_dir : $(mpe_fieldgen_product_dir)/avgrmosaic -mpe_maxrmosaic_dir : $(mpe_fieldgen_product_dir)/maxrmosaic -mpe_bmosaic_dir : $(mpe_fieldgen_product_dir)/bmosaic -mpe_d2d_files_dir : $(mpe_fieldgen_product_dir)/d2d_files -mpe_polygon_dir : $(mpe_fieldgen_product_dir)/edit_polygon -mpe_gageonly_dir : $(mpe_fieldgen_product_dir)/gageonly -mpe_gagetriangles_dir : $(mpe_fieldgen_product_dir)/gagetriangles -mpe_height_dir : $(mpe_fieldgen_product_dir)/height -mpe_index_dir : $(mpe_fieldgen_product_dir)/index -mpe_lmosaic_dir : $(mpe_fieldgen_product_dir)/lmosaic -mpe_locbias_dir : $(mpe_fieldgen_product_dir)/locbias -mpe_locspan_dir : $(mpe_fieldgen_product_dir)/locspan -mpe_lsatpre_dir : $(mpe_fieldgen_product_dir)/lsatpre -mpe_mlmosaic_dir : $(mpe_fieldgen_product_dir)/mlmosaic -mpe_mmosaic_dir : $(mpe_fieldgen_product_dir)/mmosaic -mpe_qmosaic_dir : $(mpe_fieldgen_product_dir)/qmosaic -mpe_lqmosaic_dir : $(mpe_fieldgen_product_dir)/lqmosaic -mpe_mlqmosaic_dir : $(mpe_fieldgen_product_dir)/mlqmosaic -mpe_p3lmosaic_dir : $(mpe_fieldgen_product_dir)/p3lmosaic -mpe_qpe_dir : $(mpe_fieldgen_product_dir)/qpe -mpe_qpe_sbn_dir : $(mpe_fieldgen_product_dir)/qpe_sbn -mpe_qpe_gif_dir : $(mpe_fieldgen_product_dir)/qpe_gif -mpe_qpe_grib_dir : $(mpe_fieldgen_product_dir)/qpe_grib -mpe_qpe_grib_sbn_dir : $(mpe_fieldgen_product_dir)/qpe_grib_sbn -mpe_qpe_jpeg_dir : $(mpe_fieldgen_product_dir)/qpe_jpeg -mpe_qpe_netcdf_dir : $(mpe_fieldgen_product_dir)/qpe_netcdf -mpe_rmosaic_dir : $(mpe_fieldgen_product_dir)/rmosaic -mpe_sat_state_var : $(mpe_fieldgen_product_dir)/sat_state_var -mpe_state_var : $(mpe_fieldgen_product_dir)/state_var -mpe_srmosaic_dir : $(mpe_fieldgen_product_dir)/srmosaic -mpe_sgmosaic_dir : $(mpe_fieldgen_product_dir)/sgmosaic -mpe_srgmosaic_dir : $(mpe_fieldgen_product_dir)/srgmosaic -mpe_satpre_dir : $(mpe_fieldgen_product_dir)/satpre -mpe_rfcmmosaic_dir : $(mpe_fieldgen_product_dir)/rfcmmosaic -mpe_rfcbmosaic_dir : $(mpe_fieldgen_product_dir)/rfcbmosaic -mpe_localfield1_dir : $(mpe_fieldgen_product_dir)/localfield1 -mpe_localfield2_dir : $(mpe_fieldgen_product_dir)/localfield2 -mpe_localfield3_dir : $(mpe_fieldgen_product_dir)/localfield3 - -### Tokens related to the MPE Editor map display. -mpe_config_dir : $(whfs_config_dir) -mpe_center_lat : 39.8 -mpe_center_lon : -98.55 -mpe_height_in_pixels : 900 -mpe_width_in_pixels : 1200 -mpe_map_width : 1320 -mpe_zoom_out_limit : 20 -mpe_disclosure_limit : 60 -mpe_map_projection : FLAT - -### Misc tokens -mpe_load_hourlypc : ON -mpe_gageqc_gif_dir : $(whfs_image_dir) -mpe_gif_location : 34.0,-97.0,34.0,-94.0,33.0,-94.0 -mpe_overlay_dir : $(whfs_geodata_dir) -mpe_editor_logs_dir : $(pproc_log)/mpe_editor -mpe_type_source : RG:GOES,RR:ALERT,RM:SNOTEL,RP:LARC,RZ:COOP - -### New tokens for DQC/CHPS -mpe_level2_type_value : 2 # Allow user to customize the type value. The default is “2” -mpe_td_details_set : OFF # Allow generating a time distribution details file. -mpe_process_PC : ON # Skip call to the load_PC_hourly routine if "OFF" -mpe_map_one_zone : OFF # Allow MAP generation for one zone only -fewsgrib_dir : $(mpe_gageqc_dir)/fewsgrib # default nc2grib grib file output dir -nc2g_app_dir : $(mpe_app_dir)/nc2grib # directory for gfe2grib.txt file -netcdf_dir : $(mpe_gageqc_dir)/netcdf_files #default output directory for netcdf files -mpe_dqc_save_netcdf : OFF # Save Daily QC as netCDF -mpe_dqc_save_grib : OFF # Save Daily QC as grib - -### Tokens which control the products generated by MPE Fieldgen. -mpe_locbias_1hr_rerun : OFF # ON/OF .Apps_defaultsF flag to - # determine if local bias should be - # recalculated as part of the mpe_fieldgen - # rerun from hmap_mpe - # ON -- recalc loc bias on rerun - # OFF -- do not recalc loc bias on rerun -mpe_del_gage_zeros : OFF # ON/OFF flog to determine if a zero gage - # value should be removed from consideration - # if the radar shows > 0.0 - # ON -- check for and remove zero gage values - # OFF -- do not check for or remove zero - # gage values - -mpe_selected_grid_gagediff : MMOSAIC - -mpe_qpe_fieldtype : MMOSAIC # field type to be saved as qpe -mpe_generate_list : BMOSAIC,GAGEONLY,LMOSAIC,LSATPRE,MLMOSAIC,MMOSAIC,RMOSAIC,SATPRE,P3LMOSAIC,SRMOSAIC,SGMOSAIC,QMOSAIC,LQMOSAIC,MLQMOSAIC,RFCBMOSAIC,RFCMMOSAIC,RFCMOSAIC,SAVELEVEL2 -mpe_base_radar_mosaic : RMOSAIC # The base radar mosaic used for the fields - # that mpe_fieldgen generates -mpe_show_missing_gage : None # MPE missing gage display. - # (None,All,Reported) -mpe_bad_gages_dir : $(rfcwide_output_dir)/bad_gages - -### directory locations of various format MPE output grid files -mpe_gif_dir : $(rfcwide_output_dir)/qpe_gif -mpe_jpeg_dir : $(rfcwide_output_dir)/qpe_jpeg -mpe_netcdf_dir : $(rfcwide_output_dir)/qpe_netcdf -mpe_grib_dir : $(rfcwide_output_dir)/qpe_grib - -### which format MPE output grid files to save -mpe_save_gif : nosave -mpe_save_jpeg : nosave -mpe_save_netcdf : nosave -mpe_save_grib : save - -### prefixes for various format MPE output grid files, blank by default -mpe_gif_id : -mpe_jpeg_id : -mpe_netcdf_id : -mpe_grib_id : - -### mpe gage QC tokens -mpe_gage_qc : ON -mpe_sccqc_threshold : 2.0 -mpe_scc_boxes_failed : 4 -mpe_msc_precip_limit : 1.0 -mpe_split_screen : OFF - -### mpe polygon tokens -mpe_polygon_action_order : None -mpe_polygon_field_order : None - -### tokens which control the transmission of RFC bias data. -mpe_transmit_bias : OFF -transmit_bias_on_save : NO -transmit_bias_on_rerun : NO -rfc_bias_input_dir : $(mpe_dir)/bias_message_input -rfc_bias_output_dir : $(mpe_dir)/bias_message_output -process_bias_log_dir : $(pproc_log)/process_bias_message -send_local_bias_when_rfc_bias_missing : NO - -### rfc qpe to wfo tokens -mpe_send_qpe_to_sbn : OFF -mpe_generate_areal_qpe : OFF -# List of RFCs to process for Gen Areal Qpe -gaq_rfc_list : MBRFC,NCRFC -gaq_dur_list : 1,6,24 -gaq_app_dir : $(pproc_local_data)/app/gen_areal_qpe -gaq_input_dir : /data/fxa/Grid/SBN/netCDF/HRAP/QPE -gaq_log_dir : $(pproc_log)/gen_areal_qpe -gaq_rfc_mask_dir : $(gaq_app_dir) -gaq_temp_xmrg_dir : $(rfcwide_output_dir)/rfcqpe_temp -gaq_xmrg_1hr_dir : $(rfcwide_output_dir)/rfcqpe01 -gaq_xmrg_6hr_dir : $(rfcwide_output_dir)/rfcqpe06 -gaq_xmrg_24hr_dir : $(rfcwide_output_dir)/rfcqpe24 -gaq_grib_dir : $(rfcwide_output_dir)/rfcqpe_grib - -### token which controls how PC precipitation totals are derived. -sum_pc_reports : NO - -geo_st3_bin : $(geo_data)/$(st3_rfc)/binary #geo_data defined outside of pproc -geo_st3_ascii : $(geo_data)/$(st3_rfc)/ascii -adjust_PC_startingtime : 4 #allow PC starting time tolerance - -### tokens for sending MPE mean field bias data to the ORPG - -bias_message_dir : $(apps_dir)/data/fxa/radar/envData - -### tokens for Lightning Data processing - -lightning_input_dir : /data/fxa/point/binLightning/netcdf - -lightning_log_dir : $(pproc_log)/lightning_proc - -### tokens for D2D display - -mpe_d2d_display_grib : ON # ON/OFF token to determine if further - # processing of grib file for D2D display - # is required - -d2d_input_dir : $(EDEX_HOME)/data/manual/mpe # dir containing grib files - # to be processed for D2D display - -mpe_send_grib : OFF # ON/OFF token to determine if grib file is - # to be sent to other sites such as NPVU - -# disagg processing tokens - -mpe_disagg_execute : OFF -mpe_disagg_method : POINT -mpe_disagg_6hreq_0 : 1 -mpe_disagg_6hrgt_0 : 1 - -#====== High-resolution Precipitation Estimator (HPE) tokens==================== - -# DecodeDHR tokens (formerly DecodeHDP tokens that looked like hdp_*) - -dhr_log_dir : $(pproc_log)/decodedhr # DHR Decoder logs - -dhr_prod_dir : $(pproc_local_data)/dhr_gather # DHR input directory - -dhr_dirname1 : $(data_archive_root)/radar # first part of directory name -# # containing DHR products for -# # associated or dial in radars - -dhr_dirname2 : DHR/layer0/res1/level256 # second part of directory name - # containing DHR products for - # associated or dial in radar -dhr_grid_dir : $(pproc_local_data)/dhr_decoded # decoded DHR radar grids - -dhr_error_dir : $(pproc_local_data)/dhr_error # DHR error files -dhr_arch_dir : $(pproc_local_data)/dhr_archive # DHR archives - -# DecodeDSP tokens (formerly DecodeHDP tokens that looked like hdp_*) - -dsp_log_dir : $(pproc_log)/decodedsp # DSP Decoder logs - -dsp_prod_dir : $(pproc_local_data)/dsp_gather # DSP input directory - -dsp_dirname1 : $(data_archive_root)/radar # first part of directory name -# # containing DSP products for -# # associated or dial in radars - -dsp_dirname2 : STP/layer0/res2/level256 # second part of directory name - # containing DSP products for - # associated or dial in radars - # NOTE that DSP is level256 vs level16 for - # STP and this is where it is stored - # in AWIPS -dsp_grid_dir : $(pproc_local_data)/dsp_decoded # decoded DSP radar grids -dsp_error_dir : $(pproc_local_data)/dsp_error # DSP error files -dsp_arch_dir : $(pproc_local_data)/dsp_archive # DSP archives - - -hpe_generate_list : DHRMOSAIC,BDHRMOSAIC,ERMOSAIC,LSATPRE,EBMOSAIC -hpe_qpe_fieldtype : ERMOSAIC # field type to be saved as qpe - -hpe_satpre_dir : $(mpe_fieldgen_product_dir)/satpre -hpe_input_dir : $(pproc_local_data)/app/hpe -hpe_output_dir : $(pproc_local_data)/hpe -hpe_sat_statevar_dir : $(rfcwide_output_dir)/state_var - -hpe_log_dir : $(pproc_local_data)/log/hpe - -hpe_hrap_grid_factor : 4 # 1 for HRAP grid - # 4 for quarter HRAP grid - -hpe_dhrmosaic_dir : $(hpe_output_dir)/dhrmosaic -hpe_bdhrmosaic_dir : $(hpe_output_dir)/bdhrmosaic -hpe_ermosaic_dir : $(hpe_output_dir)/ermosaic -hpe_ebmosaic_dir : $(hpe_output_dir)/ebmosaic -hpe_avg_ermosaic_dir : $(hpe_output_dir)/avgrmosaic -hpe_max_ermosaic_dir : $(hpe_output_dir)/maxrmosaic -hpe_lsatpre_dir : $(hpe_output_dir)/lsatpre - -hpe_dspheight_dir : $(hpe_output_dir)/height -hpe_dspindex_dir : $(hpe_output_dir)/index -hpe_height_dir : $(hpe_output_dir)/height -hpe_index_dir : $(hpe_output_dir)/index - -hpe_dhrmosaic_grib_dir : $(hpe_dhrmosaic_dir)/grib -dhrmosaic_netcdf_dir : $(hpe_dhrmosaic_dir)/netcdf -dhrmosaic_gif_dir : $(hpe_dhrmosaic_dir)/gif -hpe_bdhrmosaic_grib_dir : $(hpe_bdhrmosaic_dir)/grib -bdhrmosaic_netcdf_dir : $(hpe_bdhrmosaic_dir)/netcdf -bdhrmosaic_gif_dir : $(hpe_bdhrmosaic_dir)/gif -hpe_ermosaic_grib_dir : $(hpe_ermosaic_dir)/grib -ermosaic_netcdf_dir : $(hpe_ermosaic_dir)/netcdf -ermosaic_gif_dir : $(hpe_ermosaic_dir)/gif -hpe_ebmosaic_grib_dir : $(hpe_ebmosaic_dir)/grib -ebmosaic_netcdf_dir : $(hpe_ebmosaic_dir)/netcdf -ebmosaic_gif_dir : $(hpe_ebmosaic_dir)/gif - -dhrmosaic_save_grib : save -dhrmosaic_save_gif : nosave -dhrmosaic_save_netcdf : nosave -bdhrmosaic_save_grib : save -bdhrmosaic_save_gif : nosave -bdhrmosaic_save_netcdf : nosave -ermosaic_save_grib : save -ermosaic_save_gif : nosave -ermosaic_save_netcdf : nosave -ebmosaic_save_grib : save -ebmosaic_save_gif : nosave -ebmosaic_save_netcdf : nosave - -hpe_gif_dir : $(hpe_output_dir)/hpe_gif -hpe_jpeg_dir : $(hpe_output_dir)/hpe_jpeg -hpe_netcdf_dir : $(hpe_output_dir)/hpe_netcdf -hpe_grib_dir : $(hpe_output_dir)/hpe_grib -hpe_xmrg_dir : $(hpe_output_dir)/hpe_xmrg -hpe_save_gif : nosave -hpe_save_jpeg : nosave -hpe_save_netcdf : nosave -hpe_save_grib : nosave - -dhr_window : 15 -dsp_window : 15 -dsp_duration : 60 - -hpe_base_radar_mosaic : ERMOSAIC -hpe_qpe_fieldtype : ERMOSAIC -hpe_load_misbin : OFF -hpe_debug_log : ON -hpe_use_locbias : OFF -hpe_runfreq : 5 -hpe_timelag : 5 -hpe_bias_source : RFC -hpe_rfc_bias_lag : 2 -hpe_purge_logage : 720 -hpe_purge_fileage : 180 -hpe_purge_xmrgage : 75 - -dhrmosaic_d2d_display_grib : ON -ermosaic_d2d_display_grib : ON -ebmosaic_d2d_display_grib : ON -bdhrmosaic_d2d_display_grib : ON -hpe_run_nowcast : ON -hpe_nowcast_generate_list : PRTM, BPTRM -hpe_nowcast_dir : $(hpe_output_dir)/nowcast -hpe_rate_save_grib : save -hpe_brate_save_grib : save -hpe_tp1h_save_grib : save -hpe_btp1h_save_grib : save -hpe_4km_tp1h_save_grib : nosave -hpe_4km_btp1h_save_grib : nosave -nowcast_d2d_display_grib : ON -hpe_smooth_method : 1 # 0=no smoothing 1=FFP method (default) 2=BZ94 method -hpn_use_meanvelocity : OFF -hpn_meanvelocity_direction : 45 # direction precip is moving towards -hpn_meanvelocity_speed : 20 # miles per hour - - -hpe_send_grib : OFF # ON/OFF token to determine if grib file is - # to be sent to other sites such as NPVU - -#========END HPE tokens====================================================== - -# ================= Flash Flood Guidance System ============================= - -ffg_level : oper - -ffg_dir : $(apps_dir)/rfc/nwsrfs/ffg # Top-level ffg -ffg_bin : $(ffg_dir)/bin # FFG execute dir -ffg_files : $(ffg_dir)/files # FFG file group -ffg_gsfiles : $(ffg_files)/$(ffg_level) # FFG files dir -ffg_out_dir : $(ffg_dir)/output # FFG output dir -ffg_grib_out : $(ffg_out_dir)/grib # GRIB output -ffg_scripts : $(ffg_dir)/scripts # FFG scripts -ffg_gff_level : grff # regular grid ffg dir -ffg_gro_level : grro # regular grid ro dir - .Apps_defaults -ffg_usr_dir : $(ffg_gsfiles)/user # FFG user dir -ffg_area_dir : $(ffg_gsfiles)/affg # FFG area dir -ffg_cary_dir : $(ffg_gsfiles)/cary # FFG carryover dir -ffg_define_dir : $(ffg_gsfiles)/define # FFG definition dir -ffg_gridff_dir : $(ffg_gsfiles)/$(ffg_gff_level) # FFG grid ff dir -ffg_gridro_dir : $(ffg_gsfiles)/$(ffg_gro_level) # FFG grid ro dir -ffg_hwatr_dir : $(ffg_gsfiles)/hffg # FFG headwater dir - -ffg_gridpm_dir : $(ffg_gsfiles)/gdpm # grid runoff adjust parameters -ffg_group_dir : $(ffg_gsfiles)/grpp # FFG groups of products -ffg_prod_dir : $(ffg_gsfiles)/prod # FFG products dir -ffg_text_dir : $(ffg_gsfiles)/text # FFG text dir -ffg_wsup_dir : $(ffg_gsfiles)/wsup # Water supply dir - -# ffg program control -ffg_error_output : on # whether to output error messages -ffg_log_output : off # whether to output log messages - -# ===================== GRIB packer/encoder ================================= - -grib_dir : $(apps_dir)/rfc/grib # Top level grib -grib_rls : $(pproc_bin) # location of gribit executable -grib_arc : $(grib_dir)/bin/ARCHIVE # grib archive -grib_in_dir : $(rfcwide_xmrg_dir) # depends on data to be encoded -grib_out_dir : $(grib_dir)/output # GRIB encoded files -grib_error_output : on # turn on/off GRIB error output -grib_set_subcenter_0 : off # set subcenter to 0 - # on - set subcenter to 0 - # off - do not set subcenter to 0 - -# end of ffg apps - -#================== XSETS Apps_defaults Tokens - 08/03/2001 =================== - -# [] = default value -#................................. -# Date Control -#................................. -xsets_date_used : SYSTEM # computer system clock - # OFSFILES = forecast time series - # mm/dd/ccyy = explicit date, 12Z - -#................................. -# Directories and files to use -#................................. -xsets_dir : $(apps_dir)/rfc/xsets -xsets_level : oper -xsets_files : $(xsets_dir)/files -xsets_xsfiles : $(xsets_files)/$(xsets_level) -xsets_param_dir : $(xsets_xsfiles)/param -xsets_config_file : xsetsconfig -xsets_output_dir : $(xsets_xsfiles)/output - -#................................. -# Commands -#................................. -xsets_editor : "nedit" -xsets_hydrographs_cmd : "$(xsets_dir)/bin/RELEASE/new_hydroplot" -xsets_print_cmd : "lp" -xsets_xmit_cmd : "cat " - -#................................. -# Parameters for creation of hydrographs -#................................. -xsets_hydro_button : NO # Create Make Hydro button, [NO] - (currently unused) -xsets_make_hydro : NO # Create .gif hydrographs, [NO] - -#................................. -# NEW_HYDROPLOTS parameters -#................................. -xsets_html_daily_dir : /pub/FcstGraphs # Location of gif images on - web server -xsets_html_flood_dir : /pub/FloodGraphs # Location of gif images on - web server -xsets_hydrographs_html : 1 # 1 = create basic html - 0 = no html created -xsets_hydrographs_output: "$(xsets_output_dir)/gifs" -xsets_hydrographs_param : $(xsets_xsfiles)/hydrographs/param - -#................................. -# File Print Options and Settings -#................................. -xsets_add_remarks : NO # Add remark after each site, [NO] -xsets_brackets : NO # Put brackets around latest stage, - # forecasts and dates, [NO] -xsets_cmt_line : NO # YES = separate line, - # NO = append to description, river -xsets_expanded_dates : YES # Insert MMDD before values, [NO] -xsets_fgroup_preamble : "FORECAST GROUP IS" #Preamble for the fgroup (string) -xsets_H_precision : 1 # 0, [1], or 2 decimal precision of stages -xsets_output_style : E # E = Expanded, each day has line, - # C = Compact -xsets_print_crests : YES # Print crest comment, [NO] -xsets_print_disclaimer : YES # Print disclaimer, [NO] -xsets_print_fs : YES # YES = encode flood stage in SHEF, - # [NO] = display as comment -xsets_print_fs_cross : COMMENT # Time level passes flood stage - # [NO] = don't include, - # SHEF = encode in SHEF, - # COMMENT = display as comment -xsets_print_ls : COMMENT # Latest stage - # [NO] = don't include, - # SHEF = encode in SHEF, - # COMMENT = display as comment -xsets_print_MAP : NO # Print MAP values, [NO] -xsets_print_qpf : COMMENT # Print QPF values - # [NO] = don't include, - # SHEF = encode in SHEF, - # COMMENT = display as comment -xsets_print_ws : YES # Display warning/caution stage, [NO] -xsets_product_hdr : PIT # Indentifier in Product Header, non-AWIPS -xsets_Q_precision : 1 # 0, [1], 2 decimal precision of flows -xsets_signature : $(LOGNAME) #User signature (string) -xsets_wmo_id : TTAA00 KTUR DDHHMM # the wmo id -xsets_ws_label : "WARNING" # Label for WARNING/[CAUTION] stage (string) -xsets_zczc : YES # Include ZCZC & NNNN, [NO], non-AWIPS - -#................................. -# Run Options -#................................. -xsets_age_check : 6 # Number of hours old of forecast before - # error generated, [6] -xsets_edit_lock : NO # Lock main display when editing SETS file, [NO]??? -xsets_gen_summary : NO # Include summary of flood locations, [NO], Currently Unused -xsets_msg_obs_warn : YES # Print warning when observed values are - # missing, [NO] -xsets_numhrs_curob : 12 # number of hours back from current time to use - # informix obs as "current obs" -xsets_num_MAP_values : 4 # Number [4] of MAP values to include in product -xsets_num_qpf_values : 4 # Number [4] of qpf values to include in product -xsets_numdays_hydro : 3 # Run Parameters for FCSTPROG -xsets_ofs_select : OFS # OFS or IFP for time series files -xsets_stdout : NO # Send wprint messages to stdout, [NO] -xsets_time : Z # Time Zone code used in product - # ([Z], E, C, M, P, A, H OR N) -# ================== end of xsets tokens ======================================= - -#================== XNAV Apps_defaults Tokens - 03/29/2000 ==================== -# defaults for program XNAV - -xnav_user : oper - -#................................. -# Date/time related tokens -#................................. -db_days : 10 -xnav_daily_days : 30 -xnav_ffg_periods : 3 -xnav_sixhr_periods : 40 -xnav_hyd_days_fut : 5 -xnav_hyd_days_prev : 5 -xnav_precip_hours : 240 -xnav_settoday : - -#................................. -# Directories and files to use -#................................. -xnav_dir : $(apps_dir)/rfc/xnav -xnav_data : $(xnav_dir)/data -xnav_params : $(xnav_dir)/parameters -xnav_P1xmrg_dir : $(rfs_dir)/ofs/files/$(xnav_user)/griddb -xnav_S1xmrg_dir : $(rfs_dir)/ofs/files/$(xnav_user)/griddb -xnav_bin_dir : $(xnav_dir)/bin -xnav_data_dir : $(xnav_data) -xnav_ffg_dir : $(ffg_dir)/output/$(xnav_user) -xnav_geo_data : $(geo_data)/$(ifp_rfc)/binary -xnav_gif_dir : $(HOME)/gifs/xnav -xnav_grid_ffg_dir : $(ffg_dir)/files/$(xnav_user)/grff -xnav_localdata_dir : $(xnav_data)/localdata -xnav_misc_dir : $(xnav_data)/misc_data -xnav_qpfbin_dir : $(xnav_data)/wfoqpf -xnav_rfcfmap_dir : $(xnav_data)/rfcqpf -xnav_rules_dir : $(xnav_params)/rules -xnav_shefdata_dir : $(xnav_data)/shefdata -xnav_wfoqpf_dir : $(apps_dir)/rfc/data/products -xnav_xmrg_dir : $(rfs_dir)/ofs/files/$(xnav_user)/griddb -nmap_xmrg_dir : $(xnav_rfcfmap_dir)/nmap - -#................................. -# Fonts and colors -#................................. -xnav_action_color : yellow -xnav_flood_color : red -xnav_ok_color : green -xnav_ts1_color : yellow -xnav_ts2_color : magenta -xnav_label_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" -xnav_legend_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" -xnav_list_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" -xnav_menu_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" -xnav_pb_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" -xnav_text_font : -*-charter-bold-*-*-*-17-*-*-*-*-*-*-* -xnav_toggle_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" -xnav_town_font : "-*-new century schoolbook-bold-*-*-*-14-*-*-*-*-*-*-*" - -idma_label_font : "-*-new century schoolbook-bold-*-*-*-12-*-*-*-*-*-*-*" -idma_data_font : "-*-new century schoolbook-bold-*-*-*-18-*-*-*-*-*-*-*" - -#................................. -# Window size controls -#................................. -xnav_hrap_x : 59 -xnav_hrap_xor : 311 -xnav_hrap_y : 83 -xnav_hrap_yor : 410 -xnav_hydro_height : 400 -xnav_hydro_width : 750 -xnav_scale : 8.0 -xnav_scale_colors : 3.0 -xnav_x_offset : 100 -xnav_y_offset : 100 - -#................................. -# Display options -#................................. -xnav_basins : yes -xnav_counties : no -xnav_cwas : no -xnav_fgroups : no -xnav_flights : no -xnav_grid : no -xnav_hydro_segments : no -xnav_radars : no -xnav_rfc : yes -xnav_rivers : yes -xnav_states : yes -xnav_towns : yes - -#................................. -# Other control options -#................................. -load_db_on_boot : no -load_ofs_on_boot : no -check_flood_on_boot : no -use_new_xmrg : yes -xnav_afosid : ? #PITRR1RHA -xnav_editor : nedit -xnav_exception_file : exception_file -xnav_grid_ffg_pattern : xhr -xnav_locrangecheck : no -xnav_office_hdr : ? #KRHA -xnav_only_use_ofs_data : no -xnav_pe : "HG HP HT PP PT QR QT SD SF SW TA TD TS XC" -xnav_precip_filter : .01 -xnav_route_code : ? #ES -xnav_seg_type : 2 -xnav_send_shef : no -xnav_show_p1_files : yes -xnav_suppress_msg : yes -xnav_xmit_cmd : "cat " - -# ====== MAKE24HRXMRG Tokens ====== - -make24hrxmrg_settoday : # Run date in mm/dd/yyyy. Empty means uses number - # of days back argument to program. -make24hrxmrg_debug_level : 0 # Set debug output level. 1 or 2 yields more output. -make24hrxmrg_endtime : # Hour to end the 24 hour total. Default: 12Z if not - # given. -make24hrxmrg_tz : Z # Time zone; E, C, M, P, Y, H, L, or Z (defautlt). - -# ================== end of xnav tokens ======================================== - -#================== XDAT Apps_defaults Tokens - 03/29/2000 ==================== -# defaults for program XDAT - -xdat_user : oper - -#................................ -# Date/time related tokens -#................................ -xdat_flood_hours : 6 -xdat_settoday : - -#.................................. -# Directories and files to use -#.................................. -xdat_dir : $(apps_dir)/rfc/xdat -xdat_data : $(xdat_dir)/data -xdat_params : $(xdat_dir)/parameters -xdat_groups_dir : $(xdat_params)/groups -xdat_localdata_dir : $(xdat_data)/localdata -xdat_shefdata_dir : $(xdat_data)/shefdata - -#.................................. -# Fonts and colors to use -#.................................. -xdat_label_font : ncenb14 -xdat_list_font : helvb14 -xdat_text_font : user14x19 -xdat_pb_font : ncenb14 - -#................................. -# Window size controls -#................................. -xdat_scale : 1.0 - -#.................................. -# Display Options -#.................................. -xdat_clear_id : yes - -#.................................. -# Other Control Options -#.................................. -xdat_afosid : ?ofstest? -xdat_office_hdr : ??? -xdat_post_unk : $(shef_post_unk) -xdat_route_code : ??? -xdat_send_shef : no -xdat_xmit_cmd : "cat " -# ================== end of xdat tokens ======================================== - -#====================== Shape Data File Directory ============================== -shape_data_dir : $(apps_dir)/ffmpShapeData # Directory holding shape - # files acting as data files - - -#================== send_rfc Apps_defaults Tokens - 3/08/2001 ================= -send_rfc_dir : $(apps_dir)/rfc/send_rfc -send_rfc_input_dir : $(send_rfc_dir)/data/send -send_rfc_id : WWW -send_hardcopy_nnn : PRI-WRK-EDI-SNO-ADM-RVF -send_rfc_hardcopy : $(send_rfc_dir)/data/sbnprods -send_rfc_hpc : 0 -send_rfc_host : ds-www -send_rfc_alternate : 0 -# ================== end of send_rfc tokens ==================================== - -#================== verify Apps_defaults Tokens - 08/03/2001 ================== -# defaults for program verify -vsys_output : $(vsys_dir)/output #location of output files -vsys_input : $(vsys_dir)/input #location of input files -vsys_files : $(vsys_dir)/files #location of verify files -vsys_scripts : $(vsys_dir)/scripts #location of verify scripts -vsys_output_log : test.log #name of log file -vsys_ihfsdb : $(db_name) #ihfs_db name -vsys_vdb : vdb1_1rfc #verification db name for RFC="rfc" -verify_rls : $(vsys_dir)/bin/RELEASE #The release directory. -vsys_rls : $(verify_rls) #Not really needed, but consistent. - -# ================== end of verify tokens ====================================== - -# ================== RFC Archive Database tokens =============================== - -archive_shefdata_dir : /data/fxa/ispan/hydro_adbs # directory for archive data -archive_enable : OFF # ON/OFF - Enable or Disable - # archive data feed (OFF by default) -metar_output_dir : $(whfs_local_data_dir)/metar_output # metar2shef temp output directory - # used if archive_enable is ON - -#================== Directory tokens for RFC Archive Database ================== -adb_dir : /rfc_arc # Base RFC Archive Directory -adb_raw_que : /rfc_arc_data/q/raw/ # pathname for raw q input directory -adb_pro_que : /rfc_arc_data/q/processed/ # pathname for processed q input directory -adb_bin_dir : $(adb_dir)/bin # pathname for the bin directory -adb_cfg_dir : $(adb_dir)/cfg # pathname for the config directory -adb_lib_dir : $(adb_dir)/lib # pathname for the lib directory -adb_logs_dir : $(adb_dir)/logs # pathname for the logs directory -adb_scripts_dir: $(adb_dir)/scripts # pathname for the scripts directory - -#================== Shefdecode tokens for RFC Archive Database ================= - -adb_shef_winpast : 9999 # number of days in past to post data for RAW -adb_shef_winfuture : 9999 # number of mins in future to post obs data - # for RAW. -adb_shef_winpast_pro : 9999 # number of days in past to post data -adb_shef_winfuture_pro : 9999 # number of minutes in future to post obs data -shefdecode_rax_userid : oper # controlling UNIX user -adb_shefdecode_input : $(adb_cfg_dir)/decoders # adb SHEF parameter file - # location -adb_shef_raw_perflog : OFF # ON/OFF - create a separate performance - # log file to save internal decoder timing - # messages for monitoring performance -adb_shef_raw_logs_dir : $(adb_logs_dir)/decoder/raw/logs # pathname for the - # daily logs directory -adb_shef_raw_err_dir : $(adb_logs_dir)/decoder/raw/err # pathname for the - #product logs directory -adb_shef_raw_keeperror : ALWAYS # keep files (=ALWAYS) or only - # when errors occur (=IF_ERROR) -adb_shef_raw_post_unk : IDS_AND_DATA # NONE - do not post to the UnkStnValue tables - # values IDS_ONLY or IDS_AND_DATA - # will post everything - # to the UnkStnValue table -adb_shef_pro_post_unk : NONE # NONE - do not post to the UnkStnValue tables - # values IDS_ONLY or IDS_AND_DATA - # will post everything - # to the UnkStnValue table -adb_shef_pro_perflog : OFF # ON/OFF - create a separate performance - # log file to save internal decoder timing - # messages for monitoring performance -adb_shef_pro_logs_dir : $(adb_logs_dir)/decoder/processed/logs # pathname for the - # daily logs directory -adb_shef_pro_err_dir : $(adb_logs_dir)/decoder/processed/err # pathname for the - # product logs directory -adb_shef_pro_keeperror : ALWAYS # keep files (=ALWAYS) or only - # when errors occur (=IF_ERROR) -adb_shef_raw_checktab : ON # ON checks location and ingestfilter tables -adb_shef_pro_checktab : OFF # ON checks location and ingestfilter tables -adb_shef_duplicate_raw : USE_REVCODE # Token for allowing duplicate records to be - # posted for raw decoder. -adb_shef_duplicate_pro : USE_REVCODE # Same thing but for processed decoder. -adb_shef_raw_dupmess : ON # duplication messages from adb raw decoder. -adb_shef_raw_locmess : ON # invalid location messages from adb raw decoder. -adb_shef_raw_elgmess : ON # invalid ingestfilter messages from adb raw - # decoder. -adb_shef_raw_storall : OFF # OFF - default- will only write to pecrsep table - # ON will write to both pecrsep and peirsep tables -adb_shef_pro_dupmess : ON # duplication messages from adb processed decoder. -adb_shef_pro_locmess : OFF # invalid location messages from adb pro decoder. -adb_shef_pro_elgmess : OFF # invalid ingestfilter messages from adb pro - # decoder. -adb_shef_pro_tmp_dir : $(adb_pro_que) -adb_shef_raw_tmp_dir : $(adb_raw_que) -adb_shef_raw_add_adjust : OFF - -#========== IHFS->RAX synchronization tokens for RFC Archive Database ========== -adb_sync_logs_dir : $(adb_logs_dir)/dbsync # directory for synchronization log files -adb_sync_mode : ANALYSIS # ANALYSIS or UPDATE -adb_sync_tablenames : ALL # List of table names to synchronize -adb_sync_ihfs_ingest: USE # USE or IGNORE -adb_sync_rivercrit : ACTION # ACTION, FIS or BOTH - - -#================== DatView program tokens for RFC Archive Database ============ -datview_db_name : $(adb_name) -datview_startdate : '1975-01-01 00:00:00' -datview_label_font : -schumacher-clean-bold-r-normal-*-14-*-75-75-c-80-*-* -datview_list_font : -schumacher-clean-bold-r-normal-*-14-*-75-75-c-80-*-* -datview_text_font : -schumacher-clean-bold-r-normal-*-14-*-75-75-c-80-*-* -datview_text2_font :-adobe-courier-bold-r-normal-*-*-140-*-*-m-*-iso8859-1 -datview_bg_color : black -datview_fg_color : white -datview_ob_color1 : green -datview_ob_color2 : blue -datview_ob_color3 : yellow -datview_ob_color4 : red -datview_ob_color5 : DarkOrange -datview_ob_color6 : SlateGray1 -datview_plot_font : -adobe-courier-bold-r-normal-*-*-80-*-*-m-*-iso8859-1 -datview_plot_width : 750 -datview_plot_height : 420 -datview_data_dir : /home/oper -datview_raw_shef_dir : $(adb_raw_que) -datview_pro_shef_dir : $(adb_pro_que) -datview_office_header : KTUA # to be set by each RFC -datview_pil : OKCRR1TUR # to be set by each RFC - - -#=============== ARCH_NAV Apps_defaults Tokens - 05/5/2005 ================== -# defaults for program ARCNAV - -anav_user : oper - -#................................. -# Date/time related tokens -#................................. -anav_daily_days : 30 -anav_sixhr_periods : 40 -anav_precip_hours : 24 - - -#................................. -# Directories and files to use -#................................. - -anav_dir : /awips/hydroapps/lx/rfc/xnav -anav_data : /data -anav_flatfiles : $(anav_data)/flatfiles -anav_params : $(anav_dir)/parameters -anav_data_dir : $(anav_data) -anav_geo_data : /awips/hydroapps/lx/geo_data/$(ifp_rfc)/binary -anav_gif_dir : /rfc_arc/data/arcnav/gifs -anav_localdata_dir : $(anav_data)/localdata -anav_xmrg_dir : $(anav_flatfiles) - -#................................. -# Fonts and colors -#................................. -anav_label_font : courb14gr -anav_legend_font : courb14gr -anav_list_font : courb14gr -anav_menu_font : 9x15 -anav_pb_font : courb12gr -anav_text_font : helvb18gr -anav_toggle_font : courb14gr -anav_town_font : courb12gr - -#................................. -# Window size controls -#................................. -anav_hrap_x : 200 -anav_hrap_xor : 850 -anav_hrap_y : 200 -anav_hrap_yor : 470 -anav_hydro_height : 400 -anav_hydro_width : 750 -anav_scale : 3.5 -anav_scale_colors : 3.0 -anav_x_offset : 300 -anav_y_offset : 300 - -#................................. -# Display options -#................................. -anav_basins : yes -anav_counties : no -anav_cwas : no -anav_fgroups : no -anav_flights : no -anav_grid : no -anav_hydro_segments : no -anav_radars : no -anav_rfc : no -anav_rivers : no -anav_states : yes -anav_towns : yes - -#................................. -# Other control options -#................................. -anav_editor : nedit -anav_suppress_msg : yes - -#...................................... -# tokens added for arcnav application -# for future use -#...................................... -anav_ok_color : green -anav_action_color : yellow -anav_flood_color : red -anav_ts1_color : yellow -anav_ts2_color : magenta - -# ================= end of arcnav tokens ====================================== - -# ================== end of RFC Archive Database tokens ======================== - -# ================== SSHP Directory Structure and application tokens =============================== - -local_data_sshp_dir : $(whfs_local_data_dir)/sshp_transfer -sshp_control_dir : $(whfs_local_data_dir)/app/sshp -sshp_ofs_extract_text_dir : $(local_data_sshp_dir)/ofs_extract_text -sshp_ofs_extract_xml_dir : $(local_data_sshp_dir)/ofs_extract_xml -sshp_ingest_xml_dir : $(local_data_sshp_dir)/ingest_xml -sshp_incoming_dir : $(local_data_sshp_dir)/incoming -sshp_outgoing_dir : $(local_data_sshp_dir)/outgoing -sshp_log_dir : $(whfs_log_dir)/sshp -sshp_java_process_host : px1f -sshp_invoke_map_preprocess: ON -sshp_map_qpe_to_use : MIXED # choices are: MIXED, LOCAL_BEST_ONLY, RFC_ONLY -sshp_fcst_ts : FZ # SSHP type-source code for generated forecasts -sshp_initial_forecast_length: 24 # length of forecast in hours -sshp_max_forecast_length: 120 # max length of forecast in hours that user can make generated in GUI -sshp_sac_update_expiration_hours: 25 # number of hours after which to update locally the SAC states -sshp_sac_update_hours_forward: -2 # number of hours forward of last top of hour to save sac states - - # negative -2 means 2 hours BEFORE last top of hour -sshp_adjustment_pairing_minutes : 70 -sshp_adjustment_interpolation_hours : 3 -sshp_show_simulated_timeseries : true - -sshp_data_dir : $(whfs_local_data_dir)/sshp # base sshp dynamic data dir -sshp_precip_dir : $(sshp_data_dir)/precip # default location for saved precip files -sshp_background_forecast_output_dir : $(sshp_data_dir)/forecast -sshp_background_forecast_length : 48 # length of a background forecast - -sshp_hpn_minutes_before : 5 # don't use grid files prior to X minutes before Hour -sshp_hpn_minutes_after : 5 # don't use grid files after X minutes past the Hour - -sshp_show_unadjusted_states: false # initial setting of option in GUI for displaying the unadjusted SAC-SMA states -# ==================== Radar Climatology Tokens ============================== -radclim_data_dir : $(pproc_local_data)/app/radclim - -# ==================== PDC Preprocessor Tokens =============================== -pdc_clean_cache_minutes : 60 -pdc_temperature_hours : 168 -pdc_height_hours : 168 -pdc_snow_hours : 168 -pdc_wind_hours : 168 -pdc_weather_hours : 168 -pdc_precip_hours : 168 -pdc_lower_window : 5 -pdc_upper_window : 5 - -pdc_pp_dir : $(whfs_local_data_dir)/pdc_pp -pdc_pp_log_dir : $(whfs_log_dir)/pdc_pp - -# ====================== Historical Data Browser Tokens ======================= - -hdb_help_dir : $(hdb_dir)/help_files # Historical data browser help - # files -hdb_script_directory : $(hdb_dir)/scripts # Historical data browser - # scripts dir -hdb_config_dir : $(hdb_dir)/app-defaults # Historical data browser - # configuration file directory - -hdb_height_in_pixels : 900 # Historical data browser map height in - # pixels -hdb_width_in_pixels : 1200 # Historical data browser map width in - # pixels -hdb_center_lat : 35 # The initial center latitude of the HDB -hdb_center_lon : -88.9 # The initial center longitude of the HDB -hdb_map_width : 2999.862 # The width in nautical miles of the area - # displayed in the HDB -hdb_disclosure_limit : 60 # The disclosure limit for displaying finer - # detail in the city overlay. -hdb_map_projection : FLAT # The initial map projection used by HDB. - # Possible values: FLAT, POLAR, HRAP -# ====================== DHM Token ======================= -dhm_data_dir : $(ofs_files)/$(ofs_level)/dhmdata # DHM data dir -dhm_d2d_data_dir : /data/fxa/Grid/LOCAL/netCDF/DHM # d2d data dir -dhm_d2d_notify_bin_dir : /awips/fxa/bin # d2d notify bin dir -rdhm_input_dir : $(geo_data) -dhm_rain_plus_melt_data_dir: $(geo_data) -# ================== end of SSHP Directory Structure tokens ======================== - -# ========================== NRLDB Tokens=================== -nrldb_log : $(whfs_log_dir)/nrldb -nrldb_data : $(whfs_local_data_dir)/nrldb -nrldb_config : $(whfs_config_dir)/nrldb -nrldb_tmp : /awips/hydroapps/whfs/local/data/output - -# The syntax needed in the file is: -# -# token : resource -# -# where: token is defined as a string delimited by white space or -# the delimiter, -# the delimiter between token and resource is the :, -# no white space needs to surround the delimiter, -# comments are indicated by a #, -# neither token nor resource can begin with a # or :, -# a # or a : can be embedded within resource, -# resource can contain white space if it is bounded by -# the ' or " characters, -# blank lines are allowed. -# referbacks are indicated by $(...). The '...' is resolved -# the same way any other token is, and is substituted for -# the $(...) string to compose the final resource value. -# Multiple referbacks are allowed in a resource, but -# embedded referbacks are not allowed (i.e. no -# $($(...)) allowed). -# Note that this file is read only if the token can not be resolved -# as an environment variable. -# -# ============================================================================== +# +# Official National .Apps_defaults file for AWIPS Release OB8.3 +# Also see .Apps_defaults_site for override settings +# Revision History: +# 11/06/2001 - adjusted many directory locations of precip_proc tokens. +# notable changes: st3_mkimage, rfcwide_input_dir +# added pproc_local, pproc_local_data, pproc_log +# grouped tokens together for 3 subsystems - shefdecode, whfs, +# precip_proc. +# placed precip_proc section after ofs since there are some +# dependencies +# changed value of whfs_editor +# added hydro_publicbin token +# added pproc_util_log_dir +# 07/01/2002 - added ens_input, ens_output, ens_files +# 07/22/2002 - add global gaff execution token +# 11/04/2002 - added disagg tokens +# 08/29/2003 - added sqlcmd_bin_dir +# 08/20/2003 - added ligtning_input_dir, lightning_log_dir +# 10/03/2003 - added tokens gage_qc, sccqc_threshold, mpe_scc_boxes_failed, +# mpe_msc_precip_limit +# 10/10/2003 - changed token names to mpe_gage_qc, mpe_sccqc_threshold +# - changed mpe_gage_qc token value to ON +# 02/04/2004 - Added new tokens for ens_pre netCDF enhancement --kwz +# 2/4/2004 - added mpe_locbias_1hr_rerun token +# 02/11/2004 - Added hv_map_projection. +# 02/19/2004 - Removed stage2 and stage3 related tokens. +# 03/10/2004 - Added mpe_mlmosaic_calc and rfcwide_mlmosaic_dir tokens. +# 03/16/2004 - Added rfcwide_lsatpre_dir, rfcwide_satstate_var_dir, +# mpe_lsatpre_calc. +# 03/19/2004 - Added mpe_del_gage_zeros. +# 03/22/2004 - added sshp tokens +# 03/24/2004 - Added rpf_min_dur_filled +# 03/31/2004 - Added SSHP tokens +# 04/26/2004 - added sshp_invoke_map_preprocess and +# sshp_java_process_host tokens for the +# mpe_fieldgen scripts +# 05/06/2004 - Added more RFC archive database (adb) tokens +# 06/28/2004 - Added preadj_outts_dir +# 07/31/2004 - Added gage_pp_userid, gage_pp_host, gage_pp_data, gage_pp_log +# and gage_pp_sleep. +# 08/10/2004 - ssh- Added gage_pp_userid, gage_pp_host, gage_pp_data, +# gage_pp_log, gage_pp_sleep, gage_pp_enable, shef_post_precip +# 08/12/2004 - Added timeseries_begintime, timeseries_endtime, timeseries_mode +# timeseries_showcat, timeseries_linewidth, dam_icon_color +# 10/14/2004 - Added the mpe_generate_list token. BAL +# 10/14/2004 - Removed the tokens: mpe_mlmosaic_calc, mpe_lsatpre_calc +# 11/05/2004 - Corrected spelling of timeseries_endime. RAE +# 11/23/2004 - Added the mpe_show_missing_gage token. +# 01/07/2005 - Added the sum_pc_reports token. This controls how PC-based +# precipitation totals are derived. +# 01/10/2005 - Added the sum_pc_reports token. +# 01/28/2005 - Added AWIPS MODIFICATION BLOCK. When gmake is run in the +# development tree location of .Apps_defaults, a copy of it +# will be placed in /awips/hydroapps with the lines modified +# in the AWIPS modification block to work in the /awips/hydroapps +# tree. +# 01/28/2005 - Modified the definitions of adb_shef_pro_err_dir and +# adb_shef_pro_logs_dir. +# Added the pghost, and pguser, pgport tokens for PostGres. +# 04/21/2005 - Changed shefdecode_host and gage_pp_host to dx. +# 04/28/2005 - Added hv_min_dur_filled token. Added ppp_ppd_local_7am_window +# token. +# 5/5/2005 - Added SSHP tokens sshp_initial_forecast_length, sshp_max_forecast_length, +# sshp_sac_update_expiration_hours, sshp_sac_update_hours_forward. +# Moved sshp_fcst_ts to be next to the rest of the SSHP tokens. +# 5/11/2005 - Changed pguser token value to pguser. +# 6/9/2005 - Changed value of grib_rls (location of gribit executable) +# - Added new tokens mpe_d2d_display_grib, d2d_input_dir, mpe_send_grib +# 6/15/2005 - Changed value for d2d_input_dir token +# 9/13/2005 - Replaced the edit_poly token with the rfcwide_drawpre_dir +# token. This directory will contain the precip edit polygons +# drawn in Hydroview/MPE and applied in MPE Fieldgen. +# 9/22/2005 - Added the rfcwide_gageloc_dir and rfcwide_beamheight_dir tokens. +# 9/27/2005 - Added the hdb_db_name token. Contains the name of the database +# used by the historical data browser. +#10/6/2005 - Modified the value of the rfcwide_utiltriangles_dir token to +# be under local/data/app/mpe instead of local/data/mpe. +#10/6/2005 - Added the mpe_base_radar_mosaic token. +#02/7/2006 - Added the mpe_split_screen token. +#02/8/2006 - Added tokens for the PDC Preprocessor +#02/9/2006 - Added mpe_polygon_action_order and mpe_polygon_field_order +# tokens. +#03/2/2006 - Added new tokens for DailyQC. Added renamed MPE tokens. +#04/19/2006 - Added new tokens for controling the orientation/appearance +# of the historical data browser and the locations of the help +# and configuration directory. +#05/30/2006 - Modified the token values for datview_plot_font and anav_data. +# Added the following tokens for archive database programs: +# adb_shef_pro_tmp_dir, adb_shef_raw_tmp_dir, +# adb_shef_raw_add_adjust, rax_pghost, adb_name +#05/30/2006 - Added the mpe_send_qpe_to_sbn token. +#06/06/2006 - Added the grib_set_subcenter_0 token. +#07/07/2006 - Added the ifp_griddb_dir token. +#09/05/2006 - Added the dhm_d2d_data_dir and dhm_d2d_notify_dir tokens. +#10/02/2006 - Added the sshp_map_qpe_to_use token. +#11/02/2006 - Added the mpe_qpe_grib_sbn_dir token. +#11/17/2006 - Added the mpe_qpe_sbn_dir token. +#05/08/2007 - Added tokens for the rfc bias transfer project. +#05/09/2007 - Added 3 tokens for SRG field directories +#05/14/2007 - Added token for rdhm input directory +#O5/23/2007 - Added sshp_show_simulated_timeseries, changed sshp_background_fcst_length to +# sshp_background_forecast_length +#05/23/2007 - Add tokens for RiverPro: rpf_endtime_shifthrs, +# show_vtecqc_window, event_expire_withinhr +#06/18/2007 - Added the send_local_bias_when_rfc_bias_missing token. +# Biasmesgen reads this token to determine whether or not +# to send the locally generated MPE bias to the RPG if +# the RFC bias is not available. +#06/28/2007 - Added DailyQC preprocessor token dqc_preprocessor_basetime +#07/17/2007 - Added rgb_file_path token. Used by new Color Manager in Hydroview +# and MPE Editor. +#10/24/2007 - Added dhm_rain_plus_melt_data_dir token +#11/08/2007 - Added tokens for IHFS->RAX Synchronization: adb_sync_logs_dir, +# adb_sync_mode, adb_sync_tablenames, adb_sync_ihfs_ingest, adb_sync_rivercrit +#1/16/2008 - added new tokens for disagg processing +# mpe_disagg_execute, mpe_disagg_method, mpe_disagg_6hreq_0,mpe_disagg_6hrgt_0 +#3/22/2008 - Added variable substitution for database port. +# +#3/5/2008 - Modified the value of the mpe_mmosaic_dir token. There was a typo in the +# product name. It was mrmosaic. It is now mmosaic. +#05/19/2008 - Added sshp_hpn_minutes_before and sshp_hpn_minutes_after tokens. +# These tokens define the time window for the SSHP HPN Prerocessor. +#07/07/08 - Added sshp_show_unadjusted_states // for sshp +# +#10/01/09 - Added 5 tokens for arcnav application. //only for arcnav for raxum application +#10/03/12 - Added token section for script execution + + +# ============================================================================== +# To see syntax rules for this file, see the bottom of this file +# +# Also see .Apps_defaults_site for overriding settings +# + +#$============================================================================= +#$ This section contains the tokens whose values are different between the +#$ development and the delivery tree. The value give is the development +#$ value. The commented value is the delivery value. The uncommented value +#$ is in the development tree. All of these tokens must be enclosed +#$ by the AWIPS_MODIFICATION_BLOCK_BEGIN and AWIPS_MODIFICATION_BLOCK_END +#$ tags. Token names and commented lines should at column 1. + +#AWIPS_MODIFICATION_BLOCK_BEGIN + +apps_dir : $(SHARE_DIR)/hydroapps # Hydrologic applications directory + +data_archive_root : /data_store # root directory of the data archive + +mcp3_icp_iface : $(HOME)/mcp3_ntrfc +#mcp3_icp_iface : /tmp/$(LOGNAME)/mcp3_ntrfc + +verify_dir : $(apps_dir)/rfc/verify #base verify directory +#verify_dir : /rfc_arc/verify #base verify directory + +vsys_dir : $(apps_dir)/rfc/verify #base verify directory +#vsys_dir : $(verify_dir) #base verify directory + +#AWIPS_MODIFICATION_BLOCK_END + +#===================== Apps/Script Execution Tokens ================================= +WhfsSrv : ON +WhfsSrv.purge_files : ON +WhfsSrv.run_db_purge : ON +WhfsSrv.run_floodseq : ON +PprocSrv : ON +PprocSrv.purge_mpe_files : ON +PprocSrv.purge_hpe_file : ON +MpeFieldGenSrv.run_mpe_fieldgen : ON +WhfsSrv.run_pdc_pp : ON +WhfsSrv.run_alarm_whfs : ON +WhfsSrv.run_alarm_whfs.run_roc_checker : ON +WhfsSrv.run_alarm_whfs.run_report_alarm : ON +WhfsSrv.run_alarm_whfs.run_report_alarm.textdb : ON +ArealQpeGenSrv : ON +DqcPreProcSrv : ON +DqcPreProcSrv.run_dqc_preprocessor : ON +MpeRUCFreezingLevel : ON +MpeLightningSrv : ON +#==================================================================================== + +# ============================================================================== + +# Executable directory tokens. +sys_java_dir : /awips2/java # Location of Java COTS software +hydro_publicbin : $(apps_dir)/public/bin +sqlcmd_bin_dir : /usr/local/sqlcmd/bin # location of sqlcmd executable on both HP and + # Linux beginning in OB3 + +################################################################################# +# Default Display Maps - comma separated list of maps with no spaces +# Map names can be found in the localization perspective under +# CAVE->Bundles->Maps. Use the filename without the extension. +# statesCounties.xml -> statesCounties +# +# display_maps - default display maps for Hydro Perspective +# mpe_display_maps - default display maps for MPE Perspective +display_maps : statesCounties +mpe_display_maps : statesCounties +################################################################################# + +# database selection tokens +server_name : ONLINE # Informix database server name +db_name : hd_ob92lwx # IHFS database name +damcat_db_name : dc_ob5xxx # Dam Catalog database name +hdb_db_name : ob81_histdata # Historical database. +pghost : localhost # The machine PostGres is running on +pguser : awips # The user allowed to access PostGres +pgport : 5432 # The PostGres Server port +adb_name : adb_ob7xxx # RFC archive database name +rax_pghost : ax # The machine PostGres is running on for the adb + +# vacuum log dir token. +vacuum_log_dir : $(whfs_log_dir)/vacuum + +# WHFS specific tokens +whfs_tz : EST5EDT # WHFS time zone for local time +whfs_primary_radar : TLX # WHFS primary radar id, for Stage II + +# damcat tokens +damcat_hostoffice_type : wfo # source of run-from office +damcat_office_datasource : ohd # which data source is used +max_storage_value : 0.00 # max storage volume filter +damcat_data : /tmp/damcatData + +# Damcrest tokens +damcrest.db_enabled : true # set to true when the user has damcat database +damcrest.hasListAllDams : true # when set to true, all dams will be displayed initially + +# Path to the editor used by Damcrest +damcrest.editor : /usr/bin/gvim + +# Path to the damcrest data directory where input and output files +# of the model are stored +damcrest_data_dir : $(whfs_local_data_dir)/damcrest + +# Path to the directory where .vimrc resource file resides. +# This resource file is needed when editor in Damcrest application +# is set to gvim. +damcrest_res_dir : $(whfs_config_dir)/damcrest + +#===================== SHEFDECODE Application Tokens ================================ + +shefdecode_userid : oper # controlling UNIX user +shefdecode_host : dx1f # controlling UNIX system. +shefdecode_dir : $(apps_dir)/shefdecode # main directory location +shefdecode_bin : $(shefdecode_dir)/bin # executable programs location +shefdecode_input : $(shefdecode_dir)/input # SHEF parameter file location +shef_data_dir : /data/fxa/ispan/hydro # input products location + +shefdecode_log : $(shefdecode_dir)/logs/decoder # daily log files location +shef_error_dir : $(shefdecode_dir)/logs/product # product log files location +shef_keeperror : ALWAYS # keep product log files (=ALWAYS) or + # only when errors occur (=IF_ERROR) +shef_perflog : ON # ON/OFF - create a separate performance log file to + # save internal decoder timing messages for + # monitoring performance +shef_data_log : ON # ON/OFF - include messages in the log file detailing + the SHEF records +dupmess : ON # ON/OFF - include messages in the log file about + # duplicate data +elgmess : ON # ON/OFF - include messages in the log file about + # data types not found in IngestFilter or + # data types turned off in IngestFilter +locmess : ON # ON/OFF - include messages in the log file about + # stations and areas not found in Location + # or GeoArea + +shef_sleep : 10 # sleep duration in seconds in between queries +shef_winpast : 10 # number of days in past to post data +shef_winfuture : 30 # number of minutes in future to post obs data +shef_duplicate : IF_DIFFERENT # flag for handling duplicate date + # ALWAYS_OVERWRITE-always overwrite when value repeats + # USE_REVCODE-if revcode set overwrite duplicate value + # IF_DIFFERENT-overwrite if new value is different + # IF_DIFFERENT_OR_REVCODE-overwrite if new value is + # different or revcode is set +shef_load_ingest : ON # ON/OFF - automatically load the IngestFilter table or not + # with (station id-PEDTSE) combinations as they + # arrive in the input data flow +shef_storetext : OFF # ON/OFF - post/don't post raw encoded SHEF text messages + # to the TextProduct table +shef_post_unk : NONE # NONE - do not post to the UnkStn nor UnkStnValue tables + # IDS_ONLY - post only location identifiers for unknown + # stations to the UnkStn table + # IDS_AND_DATA - post all data from unknown stations to + # the UnkStnValue table +shef_post_baddata : REJECT # PE/REJECT - post data that have failed the gross range + # check to the physical element data tables (=PE) OR + # to the RejectedData table (=REJECT) +shef_procobs : OFF # ON/OFF - post Processed data values (i.e., TS=P*) to + # the observation data tables (=ON) or to + # the ProcValue table (=OFF) +shef_post_latest : ON # ON/OFF - post/don't post data to the LatestObsValue table + # VALID_ONLY - post data to the LatestObsValue table + # ONLY if the gross range check is passed +shef_post_link : ON # ON/OFF - post/don't post data to the ProductLink table +shef_load_maxfcst : ON # ON/OFF - after each product that resulted in forecast + # height or discharge data being posted, load + # the maximum forecast data into the RiverStatus table +shef_alertalarm : ON # ON/OFF - causes shefdecoder to screen data against + # alert and alarm thresholds +# -- Intermediate output from ShefParser prior to post +shef_out : OFF + + +#===================== WHFS Applications Tokens ================================ + +whfs_base_dir : $(apps_dir)/whfs # top of the WHFS tree +whfs_local_dir : $(whfs_base_dir)/local # top of WHFS local tree +whfs_local_data_dir : $(whfs_local_dir)/data # top of WHFS local data tree +whfs_local_grid_dir : $(whfs_local_data_dir)/grid # top of WHFS grids tree +whfs_log_dir : $(whfs_local_data_dir)/log # top of WHFS logs tree + +whfs_local_bin_dir : $(whfs_local_dir)/bin # local WHFS executables + +whfs_geodata_dir : $(whfs_local_data_dir)/geo # WHFS map backgrounds +whfs_image_dir : $(whfs_local_data_dir)/image # user-saved image files +whfs_import_dir : $(whfs_local_data_dir)/import # files to import into WHFS +whfs_product_dir : $(whfs_local_data_dir)/product # WHFS generated external products +whfs_report_dir : $(whfs_local_data_dir)/report # user-saved text reports +whfs_lines_per_page : 60 + +whfs_config_dir : $(whfs_local_data_dir)/app # WHFS app configuration files +rpf_template_dir : $(RPF_TEMPLATE_DIR) # RiverPro templates +metar_config_dir : $(whfs_config_dir)/metar2shef # METAR translator config +metar2shef_options : " -a -b -p1 -y2k -salias -p6 -p24 -round -w -strip " +ts_config_dir : $(whfs_config_dir)/timeseries # Time Series config +hv_config_dir : $(whfs_config_dir)/hydroview # Hydroview pixmaps etc. +hv_help_dir : $(hv_config_dir)/help/ # Hydroview Help direc. +rivermon_config_dir : $(whfs_config_dir)/rivermon/ # RiverMonitor Conf dir. + +whfs_misc_grid_dir : $(whfs_local_grid_dir)/misc # misc WHFS grids + +rgb_file_path : /usr/share/X11/rgb.txt # Location of X/Motif color file. + +rpf_log_dir : $(RPF_LOG_DIR) # RiverPro logs +rivermon_log_dir : $(whfs_log_dir)/rivermon # RiverMonitor logs +obsfcstmonitor_log_dir : $(whfs_log_dir)/obsfcst_monitor # ObsFcstMonitor logs +whfs_util_log_dir : $(whfs_log_dir)/misc # WHFS misc logs +precip_accum_log_dir : $(whfs_log_dir)/precip_accum # precip_accum logs +floodseq_log_dir : $(whfs_log_dir)/floodseq # flood sequencer logs +metar_log_dir : $(whfs_log_dir)/metar2shef # METAR translator logs +hb_gagrad_log_dir : $(whfs_log_dir)/create_gagradloc # gage-radar locator logs +qcalarm_log_dir : $(whfs_log_dir)/qcalarm # batch QC logs + +db_purge_log_dir : $(whfs_log_dir)/db_purge # db_purge token +db_purge_backup_retention_use : ON # db_purge token for using backup retention value + +purge_files_log_dir : $(whfs_log_dir)/misc # purge_files token + +whfs_bin_dir : $(whfs_base_dir)/bin # WHFS executables +sws_parent_dir : $(whfs_bin_dir) # SWS parent dir +sws_home_dir : $(whfs_bin_dir)/pa # SWS dir + +# ----------------------------------------------------------------- +# The Gage Precip Processor tokens +# ----------------------------------------------------------------- + +gage_pp_userid : oper # controlling UNIX user +gage_pp_host : dx # controlling UNIX system +gage_pp_data : $(pproc_local_data)/gpp_input # input data files location +gage_pp_log : $(pproc_log)/gage_pp # daily log files location +gage_pp_sleep : 10 # sleep duration in seconds in between queries +gage_pp_enable : ON # gpp enabled; shef uses to determine post +shef_post_precip : OFF # post to Precip/CurPrecip tables +build_hourly_enable : ON # Enable the build_hourly application + +# ---------------------------------------------------------------- +# The following tokens are most likely to be customized by the user +# (the first 4 MUST be customized at each site in the .Apps_defaults_site file) +# ---------------------------------------------------------------- +hv_center_lat : 35.0 # HydroView center latitude +hv_center_lon : -97.8 # HydroView center longitude +hv_height_in_pixels : 900 # Hydroview map height in pixels +hv_width_in_pixels : 1200 # Hydroview map width in pixels +hv_map_width : 320 # HydroView map width (nautical miles) +hv_pointdata_display : ON # Hydroview point data display flag (ON, OFF) +hv_hours_in_window : 4 # Change window hours +hv_zoom_out_limit : 20 # Limits how far the map can be zoomed out +hv_disclosure_limit : 60 # Prog disclosure limit +hv_zoom_threshold : 150 # nautical miles; Hydroview + # detail level for cities/towns +hv_map_projection : FLAT # Sets default map projection used in + # hydroview/MPE. Options are FLAT, POLAR + # or HRAP. +hv_refresh_minutes : 15 # HydroView auto refresh time (minutes) +hv_riverbasis : maxobsfcst # initial river basis for river characteristics +hv_min_dur_filled : 0.0 # Minimum percentage of accum interval covered + # by precip data. +ppp_ppd_local_7am_window : 3 # Number of +/- hours around 7 AM local to + # to use PPP and PPD reports for 24 hour + # precip summaries. + # values either obs, fcst, maxobsfcst +shefencode_prodid : CCCCNNNXXX # product identifier for outgoing SHEF + # encoded messages from Hydro Time Series +whfs_editor : whfs_editor # WHFS text editor +rpf_linewidth : 80 # width of line in RiverPro generated products +rpf_min_dur_filled : 0.25 # min percent time of requested precip dur in RiverPro +office_prefix : K # fourth char prepended to 3-char office id +vtec_record_stageoffset : 2.0 # ft offset from record value for H-VTEC field +vtec_record_flowoffset : 5000.0 # cfs offset from record value for H-VTEC field +pproc_s2_gridgen_hrs : 5 # WHFS Stage II lookback (hours) +whfs_min_dur_filled : 0.83 # WHFS min fractional time duration needed for radar accumulations +whfs_min_area_covered : 0.80 # WHFS min fractional area needed to compute MAPs +whfs_printcommand_HP : lp # command used to print WHFS apps reports on HP +whfs_printcommand_LX : lp # command used to print WHFS apps reports + # on LX +whfs_e19_print_command : "lp -o cpi=19 -o lpi=7" # command used to print e19 text reports + +dam_icon_color : BROWN # Color used for dam icon in Hydroview +timeseries_begintime : 5 # number of days back relative to current time +timeseries_endtime : 3 # number of days ahead relative to current time +timeseries_showcat : 2 # scale by data and show categories +timeseries_linewidth : 1 # width of line drawn on graph +timeseries_mode : STATION # set to GROUP or STATION mode +timeseries_dist_shef : OFF # ON/OFF token for the shef send script distribute check box + # Defaults to off if not set +rpf_stage_window : 0.5 # set stage window for determining the trend + # variables in RiverPro +show_vtecqc_window : IF_ERROR #or ALWAYS, used in RiverPro +rpf_endtime_shifthrs : 6 # in RiverPro +event_expire_withinhr : 3 # in RiverPro + +#=====Tokens To Generate Areal FFG from Mosaicked FFG Grids for Use By SSHP===== +# (NOTE: gaff_rfc_list MUST be customized at EVERY Field Office) + +gaff_execution : ON # ON/OFF token for the gen_areal_ffg process + # the gen_areal_ffg process is run from the + # process_dpa_files script at WFOs +gaff_rfc_list : ABRFC,LMRFC # list of RFCs to be mosaicked + # list is comma separated, no embedded + # spaces are allowed +gaff_input_dir : $(EDEX_HOME)/data/processing + # directory containing gridded FFG + # generated by RFCs +gaff_look_back_limit : 60 # number of hours to look back for valid gridded + # FFG data for input +gaff_mosaic_dir : $(whfs_misc_grid_dir) # directory containing output + # mosaicked gridded FFG in + # netCDF format +gaff_durations : 1,3,6 # FFG durations in hours + # list is comma separated, no embedded + # spaces are allowed + + +# ================= "ds_" system tokens (see more in site file) =============== + +ofs_dir : $(apps_dir)/rfc/nwsrfs/ofs +util_dir : $(apps_dir)/rfc/nwsrfs/util +calb_dir : $(apps_dir)/rfc/nwsrfs/calb +ifp_dir : $(apps_dir)/rfc/nwsrfs/ifp +icp_dir : $(apps_dir)/rfc/nwsrfs/icp +ens_dir : $(apps_dir)/rfc/nwsrfs/ens +fld_dir : $(apps_dir)/rfc/fld + + +hdb_dir : $(apps_dir)/rfc/hdb + +# = = = = = = = = = = = = = = = = = = = = = = end "ds_" system requirements = = + +ofs_rls : $(ofs_dir)/bin/RELEASE +util_rls : $(util_dir)/bin/RELEASE +calb_rls : $(calb_dir)/bin/RELEASE +ffg_rls : $(ffg_dir)/bin/RELEASE +ifp_rls : $(ifp_dir)/bin/RELEASE +icp_rls : $(icp_dir)/bin/RELEASE +ens_rls : $(ens_dir)/bin/RELEASE +hdb_rls : $(hdb_dir)/bin/RELEASE +fld_rls : $(fld_dir)/bin/RELEASE +xsets_rls : $(xsets_dir)/bin/RELEASE +xnav_rls : $(xnav_dir)/bin/RELEASE +xdat_rls : $(xdat_dir)/bin/RELEASE + +ofs_arc : $(ofs_dir)/bin/ARCHIVE +util_arc : $(util_dir)/bin/ARCHIVE +calb_arc : $(calb_dir)/bin/ARCHIVE +ffg_arc : $(ffg_dir)/bin/ARCHIVE +ifp_arc : $(ifp_dir)/bin/ARCHIVE +icp_arc : $(icp_dir)/bin/ARCHIVE +ens_arc : $(ens_dir)/bin/ARCHIVE +hdb_arc : $(hdb_dir)/bin/ARCHIVE +fld_arc : $(fld_dir)/bin/ARCHIVE +xsets_arc : $(xsets_dir)/bin/ARCHIVE +xnav_arc : $(xnav_dir)/bin/ARCHIVE +xdat_arc : $(xdat_dir)/bin/ARCHIVE +# = = = = = = = = = = = = = = = = = = = = = = end of other "ds_" tokens = = = = + +# LDAD shefencode tokens +ldad_data_dir : /awips/ldad/data # the LDAD internal data dir +shefenc_pe_table : $(ldad_data_dir)/ShefEncoder_PE.tbl +shefenc_units_table : $(ldad_data_dir)/ShefEncoder_Units.tbl + +# NWSRFS tokens + +rfs_dir : $(apps_dir)/rfc/nwsrfs # Top-level rfs mt. +rfs_sys_dir : $(rfs_dir)/sys_files # RFS system files +rfs_doc : $(rfs_dir)/doc # NWSRFS documentation + +# OFS tokens +locks_dir : $(rfs_dir)/locks +ofs_lock_max_wait : 60 # no. of mins to wait to get an ofs lock +ofs_lock_wait_interval : 5 # no. of secs 'tween retries to get an ofs lock +ofs_locks_max_pass : 4 # no. of attempts to make to get a set of locks. + +ofs_level : oper +ofs_reor_lvl : oper_new +ofs_inpt_grp : oper + +home_files_workstation : ds + +ofs_log_output : off # whether to output file r/w info +ofs_error_output : on # whether to output file error info +fortran_stderr : 7 # FORTRAN standard error unit + +ofs_bin : $(ofs_dir)/bin # OFS executables dir +ofs_files : $(ofs_dir)/files # OFS file group +ofs_fs5files : $(ofs_files)/$(ofs_level)/fs5files # OFS files dir +ofs_reorder_dir : $(ofs_files)/$(ofs_reor_lvl)/fs5files # OFS reordered files +ofs_output : $(ofs_dir)/output # OFS output dir +ofs_input : $(ofs_dir)/input/$(ofs_inpt_grp) # OFS input dir +ofs_input_dflt : $(ofs_dir)/input/$(ofs_inpt_grp) # OFS input dir +ofs_shefdata_dir: $(ofs_files)/$(ofs_level)/shefdata # OFS SHEF data dir +ofs_shefout_dir : $(ofs_files)/$(ofs_level)/shefdata # OFS shefout file dir +ofs_mods_dir : $(ofs_files)/$(ofs_level)/mods # OFS MODS files dir +ofs_griddb_dir : $(ofs_files)/$(ofs_level)/griddb # OFS gridded fields +ofs_scripts : $(ofs_dir)/scripts # OFS scripts dir +ofs_server : apwk01g2 # OFS "slave" server +my_output : $(ofs_output)/$(LOGNAME) # users ofs output files + +ndfd2rfs_input : $(ofs_files)/$(ofs_level)/ndfd +ndfd2rfs_output : $(my_output) +ndfd2rfs_log_level : 0 + +fldview_dir : $(apps_dir)/rfc/fldview/floodmapdata + +# calb tokens +calb_bin : $(calb_dir)/bin +calb_lib : $(calb_dir)/lib + +calb_data_grp : oper +calb_inpt_grp : oper +calb_input : $(calb_dir)/input/$(calb_inpt_grp) +calb_output : $(calb_dir)/output +calb_sta_ts_dir : $(calb_dir)/data/sta_ts/$(calb_data_grp) +calb_area_ts_dir : $(calb_dir)/data/area_ts/$(calb_data_grp) +peakflow_data_dir : $(calb_dir)/data/area_ts/$(calb_data_grp) + +calb_gzio_read : off # whether or not to read gzipped DATACARD files +calb_gzio_write : off # whether or not to write gzipped DATACARD files + +nwsrfs_calbfile_default : CARD # default calibration file type +nwsrfs_platform : AIX # operating system + +# ICP tokens +icp_bin : $(icp_dir)/bin +icp_pw : hILLEL +icp_scripts : $(icp_dir)/scripts + +mcp_decks : $(calb_input)/mcp3 +mcp_dir : $(calb_rls) + +# IFP tokens +ifp_help_dir : $(ifp_dir)/help_files # IFP help files +ifp_bin_dir : $(ifp_dir)/bin/RELEASE # IFP bin files - ref in code +ifp_nwsrfs_bin_dir : $(ifp_dir)/bin/RELEASE # ifp_nwsrfs bin - ref in code +ifp_sys_dir : $(ifp_dir)/system # IFP system files +ifp_scripts_dir : $(ifp_dir)/scripts # IFP script files +ifp_options_dir : $(ifp_dir)/options # IFP options files +ifp_colors_dir : $(ifp_options_dir)/colors # IFP color files +ifp_fs5files : $(HOME)/ofs_ifp/fs5files # user copy of fs5files +ifp_rfc : host # name of RFC to run +ifp_num_columns : 3 # number of columns to display +ifp_gif_files : $(ofs_files)/$(ofs_level)/gif_files # gif files directory +ifp_sacco_dir : $(ofs_files)/$(ofs_level)/sacsnow_clim +ifp_dhm_data_dir : /data/dhm/$(LOGNAME) +ifp_griddb_dir : $(ifp_dhm_data_dir)/precip + +# Ensemble (ens) tokens + +espts_dir : $(ens_dir)/files/$(ofs_level)/espts #espts files esp +espadp_dir : $(ens_dir) +preadj_dir : $(ens_dir)/files/$(ofs_level)/cpc_fcsts +ens_input : $(ens_dir)/input/$(ofs_level) +ens_output : $(ens_dir)/output +ens_files : $(ens_dir)/files/$(ofs_level) +ens_scripts : $(ens_dir)/scripts + +# ens_pre tokens +##FXA_HOME : /px1data #taken out by kwz.2/11/04 +enspre_griddb : $(FXA_DATA)/Grid/SBN/netCDF/CONUS211/CPCoutlook +ens_log_dir : $(ens_output)/$(ofs_level) +ens_msglog_level : 5 +preadj_outts_dir : $(calb_area_ts_dir)/pre + +# FLDGRF tokens (added 6 April 2000) + +fldgrf_iface : $(HOME)/fldgrf + +# ofsde tokens + +ofsde_log_dir : $(ofs_output)/ofsde_logs # ofsde log dir + # (formerly ofsde_output_dir) +ofsde_ndate : 7 # number of days to search for forecast temps +ofsde_rrstime_check : OFF # flag to check obs times of RRS data + # against window around 12Z (OFF/ON) + +# intervals for max/min temperatures (used by ofsde) +# these represent number of hours around 12z + +intlrmn : 8 +inturmn : 2 +intlrzn : 2 +inturzn : 2 +intlrzx : 8 +inturzx : 2 +siipp_calc_624_PP : OFF # flag for calculating 6hr and 24hr + # PP data from PC data + # if running RFCWide, should be set to OFF + +# defaults for geographic data + +geo_data : $(apps_dir)/geo_data +geo_util : $(geo_data)/util + +geo_ifp_bin : $(geo_data)/$(ifp_rfc)/binary +geo_ifp_ascii : $(geo_data)/$(ifp_rfc)/ascii + +#===================== PRECIP_PROC Application Tokens ======================== + +# precip_proc directory + +pproc_dir : $(apps_dir)/precip_proc # precip proc top + # level dir +pproc_bin : $(pproc_dir)/bin # dir with precip proc exes +pproc_local : $(pproc_dir)/local # dir with local items, esp. data +pproc_local_data : $(pproc_local)/data # dir with local data +pproc_local_bin : $(pproc_local)/bin # dir with local bin +pproc_log : $(pproc_local_data)/log # dir with local logs + +pproc_util_log_dir : $(pproc_log)/misc # miscellaneous logs + +# DecodeDPA tokens (formerly DecodeHDP tokens that looked like hdp_*) + +dpa_log_dir : $(pproc_log)/decodedpa # DPA Decoder logs +dpa_prod_dir : /data/fxa/ispan/hdp # DPA input directory +dpa_gather : $(pproc_local_data)/dpa_gather # DPA gather directory +dpa_error_dir : $(pproc_local_data)/stage1_error # DPA error files +dpa_arch_dir : $(pproc_local_data)/stage1_archive # DPA archives +dpa_wind : 10 + + +dpa_filter_decode : ON # flag for non-top-of-hour + # filtering of decoded products + # ON - filter products for decode + # OFF - do not filter (ie decode all products) + +dpa_decode_window : 10 # number of minutes around top + # of hour for filtering products for + # decoding + +dpa_archive : OFF # ON/OFF flag for archiving products + # OFF - do not archive products + # ON - archive products and filter based + # on value of dpa_archive_window + +dpa_archive_window : 10 # number of minutes around top + # of hour for filtering products for archiving + +dpa_dirname1 : $(data_archive_root)/radar # first part of directory name + # containing DPA products for + # associated or dial in radars +dpa_dirname2 : DPA/layer0/res4/level256 # second part of directory name + # containing DPA products for + # associated or dial in radars +dpa_grid_dir : $(pproc_local_data)/stage1_decoded # decoded DPA radar grids + +# siipp tokens + +intpc : 10 # interval (minutes) around top of hour for using PC data +intlppp : 2 +intuppp : 2 +intppq : 2 +siipp_log_dir : $(pproc_log)/siipp # Stage II preprocessor logs + # (formerly siipp_output_dir) + +# tokens for stageiii +st3_help : $(pproc_local_data)/app/stage3/help # online help text + +st3_rfc : host +awips_rfc_id : TUA # 3 char AWIPS RFC identifier + # must be all upper case + +# tokens for stageiii output +st3_mapx_id : xmrg # identifier for Stage 3 output +st3_date_form : mdY # date format + # current allowable = Ymd or mdY + # similar to formatting codes for + # strftime function + +st3_output : $(ofs_griddb_dir) # dir for xmrg files for MAPX + # ofs_griddb_dir defined outside of pproc +st3_out_dir : $(pproc_local_data)/stage3 +post_output : $(st3_out_dir)/post_analysis + +# defaults for netCDF output + +st3_netcdf_loc : arkansas_red_basin_river_forecast_center_tulsa_ok + # underscores needed between words +st3_netcdf_swlat : 33.603 +st3_netcdf_swlon : 106.456 +st3_netcdf_selat : 32.433 +st3_netcdf_selon : 92.322 +st3_netcdf_nelat : 38.027 +st3_netcdf_nelon : 90.678 +st3_netcdf_nwlat : 39.420 +st3_netcdf_nwlon : 106.652 + +#defaults for auto stageiii +st3_auto_graphic_scale : 2.4 # used by gif file generation + +#===================== disagg Tokens (old disagg process)======================== + +disagg_msglog_level : 30 # message level + # possible values are 1,10,20,30,...80 + # lower values signify less info in log + +disagg_dur : 24 # maximum duration of precip gage data to + # be disaggregated + # possible values = 2,3,...,24 + +disagg_look_back : 0 # time (hours) to look back from current hour + # for precip gage data to be disaggregated + +disagg_radius : 3 # number of HRAP bins within which the QPE + # will be averaged for disagg + # for example, if disagg_radius = 3, then + # the 9 nearest neighbor QPE bin values + # will be averaged +disagg_set_date : 0 # identifier for current date (yyyymmdd). + # Default value is 0 - set to + # today date + +disagg_set_hour : 0 # identifier for current hour (hh). + # Default value is 0 + # Possible values = 0,1,2,3,...,23 + +disagg_log_dir : $(pproc_log)/disagg # directory containing disagg logs + +# =============== Multi-Sensor Precipitation Estimator (MPE) ================ + +rfcw_rfcname : host +rfcwide_logs_dir : $(pproc_log)/mpe_fieldgen +hmap_mpe_timelapse : 1000 # time between images, in milliseconds, for the MPE + # time lapse display + +### tokens for input ### + +rfcwide_input_dir : $(pproc_local_data)/app/mpe + +rfcwide_satpre_dir : $(mpe_fieldgen_product_dir)/satpre + +# the help_dir token needs a trailing slash because it is required byt +# the RFC software the processes the help info... + +rfcwide_help_dir : $(rfcwide_input_dir)/help/ +rfcwide_misbin_dir : $(rfcwide_input_dir)/misbin +rfcwide_prism_dir : $(rfcwide_input_dir)/prism +rfcwide_gageloc_dir : $(rfcwide_input_dir)/gage_locations +rfcwide_beamheight_dir : $(rfcwide_input_dir)/beam_height +rfcwide_utiltriangles_dir : $(rfcwide_input_dir)/utiltriangles + +### tokens for output ### +### NOTE: xmrg files are stored in dir defined by rfcwide_xmrg_dir token below + +rfcwide_output_dir : $(pproc_local_data)/mpe # fka ofs_griddb_dir defined outside of pproc + +rfcwide_gagetriangles_dir : $(rfcwide_output_dir)/gagetriangles +rfcwide_drawpre_dir : $(rfcwide_output_dir)/draw_precip + +rfcwide_avg_rmosaic_dir : $(rfcwide_output_dir)/avgrmosaic +rfcwide_max_rmosaic_dir : $(rfcwide_output_dir)/maxrmosaic +rfcwide_rmosaic_dir : $(rfcwide_output_dir)/rmosaic +rfcwide_bmosaic_dir : $(rfcwide_output_dir)/bmosaic +rfcwide_mmosaic_dir : $(rfcwide_output_dir)/mmosaic +rfcwide_mlmosaic_dir : $(rfcwide_output_dir)/mlmosaic +rfcwide_lmosaic_dir : $(rfcwide_output_dir)/lmosaic +rfcwide_lsatpre_dir : $(rfcwide_output_dir)/lsatpre +rfcwide_gageonly_dir : $(rfcwide_output_dir)/gageonly + +rfcwide_height_dir : $(rfcwide_output_dir)/height +rfcwide_index_dir : $(rfcwide_output_dir)/index +rfcwide_locbias_dir : $(rfcwide_output_dir)/locbias +rfcwide_locspan_dir : $(rfcwide_output_dir)/locspan +rfcwide_p3lmosaic_dir : $(rfcwide_output_dir)/p3lmosaic + +rfcwide_xmrg_dir : $(rfcwide_output_dir)/qpe +rfcwide_statevar_dir : $(rfcwide_output_dir)/state_var +rfcwide_sat_statevar_dir : $(rfcwide_output_dir)/sat_state_var +mpe_q2_statevar_dir : $(rfcwide_output_dir)/q2_state_var + +# ==================== MPE Tokens =============================== + +#daily qc options token defaults to 'off' where daily qc options are grayed out; values are 'on' and 'off' +mpe_dqc_options : off +mpe_map_background_color : GRAY20 # The default color of the MPE map background +mpe_temperature_window : 60 # The window in minutes the dqc preprocessor + # searches around a synoptic time + # (00z,06z,12z,18z) for temperature data. +mpe_maxminT_hour_window : 2 +mpe_dqc_max_precip_neighbors : 30 +mpe_dqc_max_temp_neighbors : 20 +mpe_dqc_precip_deviation : 3.0 +mpe_dqc_temperature_deviation : 10.0 +mpe_dqc_min_good_stations : 5 +mpe_copy_level2_dqc_to_ihfs_shef : OFF +mpe_copy_level2_dqc_to_archive_shef : OFF +mpe_dqc_num_days : 10 +mpe_dqc_warningpopup : on +mpe_dqc_6hr_24hr_set_bad : OFF # Define logic if user sets a 6hr value to Bad in the + # Edit Precip Stations window. + # OFF – if user sets 6hr value to Bad; 24hr value unaffected + # ON - if user sets 6hr value to Bad; 24hr value set to Bad + # Added at request of MBRFC to help with QC of SNOTEL. + +mpe_dqc_grid_max_dist : 70 # Max distance (units of grid bins) between a grid bin and a + # station to use the station to estimate the value at the grid bin. + +mpe_dqc_output_qc_file : OFF # ON/OFF default = OFF + +mpe_dqc_execute_internal_script : OFF # ON/OFF + +mpe_dqc_24hr_precip_grid_meth : USE_24HR # We use the token values of ACCUM_6HR and USE_24HR +mpe_td_new_algorithm : OFF # flag set for new algorithm in calculating Time Distributed estimate, the default + # is false +mpe_dqc_gridtype : SCALAR +mpe_dqc_projectiontype : POLAR_STEREOGRAPHIC +mpe_dqc_lonorigin : -105. + +#daily qc preprocessor tokens +dqc_preprocessor_basetime : 12Z #The value can be 12Z, 18Z, 00Z, or 06Z + +### MPE base directory tokens. +mpe_dir : $(pproc_local_data)/mpe +mpe_gageqc_dir : $(mpe_dir)/dailyQC +mpe_scratch_dir : $(mpe_gageqc_dir)/scratch +mpe_app_dir : $(pproc_local_data)/app/mpe +mpe_fieldgen_product_dir : $(mpe_dir) + +### MPE station list tokens +mpe_station_list_dir : $(mpe_app_dir)/station_lists +mpe_site_id : ounx +mpe_area_names : $(mpe_site_id) + +### MPE static data files +mpe_prism_dir : $(mpe_app_dir)/prism +mpe_misbin_dir : $(mpe_app_dir)/misbin +mpe_utiltriangles_dir : $(mpe_app_dir)/utiltriangles +mpe_beamheight_dir : $(mpe_app_dir)/beam_height +mpe_climo_dir : $(mpe_app_dir)/climo +mpe_help_dir : $(mpe_app_dir)/help +mpe_gridmask_dir : $(mpe_app_dir)/grid_masks +mpe_basin_file : $(whfs_geodata_dir)/basins.dat + +### MPE precipitation gage qc directories +mpe_precip_data_dir : $(mpe_gageqc_dir)/precip +mpe_bad_precip_dir : $(mpe_precip_data_dir)/bad +mpe_dev_precip_dir : $(mpe_precip_data_dir)/dev +mpe_map_dir : $(mpe_precip_data_dir)/MAP +mpe_grid_precip_dir : $(mpe_precip_data_dir)/grid +mpe_point_precip_dir : $(mpe_precip_data_dir)/point + +### MPE temperature gage qc directories +mpe_temperature_data_dir : $(mpe_gageqc_dir)/temperature +mpe_bad_temperature_dir : $(mpe_temperature_data_dir)/bad +mpe_dev_temperature_dir : $(mpe_temperature_data_dir)/dev +mpe_mat_dir : $(mpe_temperature_data_dir)/MAT +mpe_grid_temperature_dir : $(mpe_temperature_data_dir)/grid +mpe_point_temperature_dir : $(mpe_temperature_data_dir)/point + +### MPE freezing level gage qc directories +mpe_freezing_data_dir : $(mpe_gageqc_dir)/freezing_level +mpe_maz_dir : $(mpe_freezing_data_dir)/MAZ +mpe_grid_freezing_dir : $(mpe_freezing_data_dir)/grid +mpe_point_freezing_dir : $(mpe_freezing_data_dir)/point +ruc_model_data_dir : /data/fxa/Grid/SBN/netCDF/CONUS211/RUC + +### MPE 1 hour mosaics and fields and supporting reference fields. +mpe_avgrmosaic_dir : $(mpe_fieldgen_product_dir)/avgrmosaic +mpe_maxrmosaic_dir : $(mpe_fieldgen_product_dir)/maxrmosaic +mpe_bmosaic_dir : $(mpe_fieldgen_product_dir)/bmosaic +mpe_d2d_files_dir : $(mpe_fieldgen_product_dir)/d2d_files +mpe_polygon_dir : $(mpe_fieldgen_product_dir)/edit_polygon +mpe_gageonly_dir : $(mpe_fieldgen_product_dir)/gageonly +mpe_gagetriangles_dir : $(mpe_fieldgen_product_dir)/gagetriangles +mpe_height_dir : $(mpe_fieldgen_product_dir)/height +mpe_index_dir : $(mpe_fieldgen_product_dir)/index +mpe_lmosaic_dir : $(mpe_fieldgen_product_dir)/lmosaic +mpe_locbias_dir : $(mpe_fieldgen_product_dir)/locbias +mpe_locspan_dir : $(mpe_fieldgen_product_dir)/locspan +mpe_lsatpre_dir : $(mpe_fieldgen_product_dir)/lsatpre +mpe_mlmosaic_dir : $(mpe_fieldgen_product_dir)/mlmosaic +mpe_mmosaic_dir : $(mpe_fieldgen_product_dir)/mmosaic +mpe_qmosaic_dir : $(mpe_fieldgen_product_dir)/qmosaic +mpe_lqmosaic_dir : $(mpe_fieldgen_product_dir)/lqmosaic +mpe_mlqmosaic_dir : $(mpe_fieldgen_product_dir)/mlqmosaic +mpe_p3lmosaic_dir : $(mpe_fieldgen_product_dir)/p3lmosaic +mpe_qpe_dir : $(mpe_fieldgen_product_dir)/qpe +mpe_qpe_sbn_dir : $(mpe_fieldgen_product_dir)/qpe_sbn +mpe_qpe_gif_dir : $(mpe_fieldgen_product_dir)/qpe_gif +mpe_qpe_grib_dir : $(mpe_fieldgen_product_dir)/qpe_grib +mpe_qpe_grib_sbn_dir : $(mpe_fieldgen_product_dir)/qpe_grib_sbn +mpe_qpe_jpeg_dir : $(mpe_fieldgen_product_dir)/qpe_jpeg +mpe_qpe_netcdf_dir : $(mpe_fieldgen_product_dir)/qpe_netcdf +mpe_rmosaic_dir : $(mpe_fieldgen_product_dir)/rmosaic +mpe_sat_state_var : $(mpe_fieldgen_product_dir)/sat_state_var +mpe_state_var : $(mpe_fieldgen_product_dir)/state_var +mpe_srmosaic_dir : $(mpe_fieldgen_product_dir)/srmosaic +mpe_sgmosaic_dir : $(mpe_fieldgen_product_dir)/sgmosaic +mpe_srgmosaic_dir : $(mpe_fieldgen_product_dir)/srgmosaic +mpe_satpre_dir : $(mpe_fieldgen_product_dir)/satpre +mpe_rfcmmosaic_dir : $(mpe_fieldgen_product_dir)/rfcmmosaic +mpe_rfcbmosaic_dir : $(mpe_fieldgen_product_dir)/rfcbmosaic +mpe_localfield1_dir : $(mpe_fieldgen_product_dir)/localfield1 +mpe_localfield2_dir : $(mpe_fieldgen_product_dir)/localfield2 +mpe_localfield3_dir : $(mpe_fieldgen_product_dir)/localfield3 + +### Tokens related to the MPE Editor map display. +mpe_config_dir : $(whfs_config_dir) +mpe_center_lat : 39.8 +mpe_center_lon : -98.55 +mpe_height_in_pixels : 900 +mpe_width_in_pixels : 1200 +mpe_map_width : 1320 +mpe_zoom_out_limit : 20 +mpe_disclosure_limit : 60 +mpe_map_projection : FLAT + +### Misc tokens +mpe_load_hourlypc : ON +mpe_gageqc_gif_dir : $(whfs_image_dir) +mpe_gif_location : 34.0,-97.0,34.0,-94.0,33.0,-94.0 +mpe_overlay_dir : $(whfs_geodata_dir) +mpe_editor_logs_dir : $(pproc_log)/mpe_editor +mpe_type_source : RG:GOES,RR:ALERT,RM:SNOTEL,RP:LARC,RZ:COOP + +### New tokens for DQC/CHPS +mpe_level2_type_value : 2 # Allow user to customize the type value. The default is “2” +mpe_td_details_set : OFF # Allow generating a time distribution details file. +mpe_process_PC : ON # Skip call to the load_PC_hourly routine if "OFF" +mpe_map_one_zone : OFF # Allow MAP generation for one zone only +fewsgrib_dir : $(mpe_gageqc_dir)/fewsgrib # default nc2grib grib file output dir +nc2g_app_dir : $(mpe_app_dir)/nc2grib # directory for gfe2grib.txt file +netcdf_dir : $(mpe_gageqc_dir)/netcdf_files #default output directory for netcdf files +mpe_dqc_save_netcdf : OFF # Save Daily QC as netCDF +mpe_dqc_save_grib : OFF # Save Daily QC as grib + +### Tokens which control the products generated by MPE Fieldgen. +mpe_locbias_1hr_rerun : OFF # ON/OF .Apps_defaultsF flag to + # determine if local bias should be + # recalculated as part of the mpe_fieldgen + # rerun from hmap_mpe + # ON -- recalc loc bias on rerun + # OFF -- do not recalc loc bias on rerun +mpe_del_gage_zeros : OFF # ON/OFF flog to determine if a zero gage + # value should be removed from consideration + # if the radar shows > 0.0 + # ON -- check for and remove zero gage values + # OFF -- do not check for or remove zero + # gage values + +mpe_selected_grid_gagediff : MMOSAIC + +mpe_qpe_fieldtype : MMOSAIC # field type to be saved as qpe +mpe_generate_list : BMOSAIC,GAGEONLY,LMOSAIC,LSATPRE,MLMOSAIC,MMOSAIC,RMOSAIC,SATPRE,P3LMOSAIC,SRMOSAIC,SGMOSAIC,QMOSAIC,LQMOSAIC,MLQMOSAIC,RFCBMOSAIC,RFCMMOSAIC,RFCMOSAIC,SAVELEVEL2 +mpe_base_radar_mosaic : RMOSAIC # The base radar mosaic used for the fields + # that mpe_fieldgen generates +mpe_show_missing_gage : None # MPE missing gage display. + # (None,All,Reported) +mpe_bad_gages_dir : $(rfcwide_output_dir)/bad_gages + +### directory locations of various format MPE output grid files +mpe_gif_dir : $(rfcwide_output_dir)/qpe_gif +mpe_jpeg_dir : $(rfcwide_output_dir)/qpe_jpeg +mpe_netcdf_dir : $(rfcwide_output_dir)/qpe_netcdf +mpe_grib_dir : $(rfcwide_output_dir)/qpe_grib + +### which format MPE output grid files to save +mpe_save_gif : nosave +mpe_save_jpeg : nosave +mpe_save_netcdf : nosave +mpe_save_grib : save + +### prefixes for various format MPE output grid files, blank by default +mpe_gif_id : +mpe_jpeg_id : +mpe_netcdf_id : +mpe_grib_id : + +### mpe gage QC tokens +mpe_gage_qc : ON +mpe_sccqc_threshold : 2.0 +mpe_scc_boxes_failed : 4 +mpe_msc_precip_limit : 1.0 +mpe_split_screen : OFF + +### mpe polygon tokens +mpe_polygon_action_order : None +mpe_polygon_field_order : None + +### tokens which control the transmission of RFC bias data. +mpe_transmit_bias : OFF +transmit_bias_on_save : NO +transmit_bias_on_rerun : NO +rfc_bias_input_dir : $(mpe_dir)/bias_message_input +rfc_bias_output_dir : $(mpe_dir)/bias_message_output +process_bias_log_dir : $(pproc_log)/process_bias_message +send_local_bias_when_rfc_bias_missing : NO + +### rfc qpe to wfo tokens +mpe_send_qpe_to_sbn : OFF +mpe_generate_areal_qpe : OFF +# List of RFCs to process for Gen Areal Qpe +gaq_rfc_list : MBRFC,NCRFC +gaq_dur_list : 1,6,24 +gaq_app_dir : $(pproc_local_data)/app/gen_areal_qpe +gaq_input_dir : /data/fxa/Grid/SBN/netCDF/HRAP/QPE +gaq_log_dir : $(pproc_log)/gen_areal_qpe +gaq_rfc_mask_dir : $(gaq_app_dir) +gaq_temp_xmrg_dir : $(rfcwide_output_dir)/rfcqpe_temp +gaq_xmrg_1hr_dir : $(rfcwide_output_dir)/rfcqpe01 +gaq_xmrg_6hr_dir : $(rfcwide_output_dir)/rfcqpe06 +gaq_xmrg_24hr_dir : $(rfcwide_output_dir)/rfcqpe24 +gaq_grib_dir : $(rfcwide_output_dir)/rfcqpe_grib + +### token which controls how PC precipitation totals are derived. +sum_pc_reports : NO + +geo_st3_bin : $(geo_data)/$(st3_rfc)/binary #geo_data defined outside of pproc +geo_st3_ascii : $(geo_data)/$(st3_rfc)/ascii +adjust_PC_startingtime : 4 #allow PC starting time tolerance + +### tokens for sending MPE mean field bias data to the ORPG + +bias_message_dir : $(apps_dir)/data/fxa/radar/envData + +### tokens for Lightning Data processing + +lightning_input_dir : /data/fxa/point/binLightning/netcdf + +lightning_log_dir : $(pproc_log)/lightning_proc + +### tokens for D2D display + +mpe_d2d_display_grib : ON # ON/OFF token to determine if further + # processing of grib file for D2D display + # is required + +d2d_input_dir : $(EDEX_HOME)/data/manual/mpe # dir containing grib files + # to be processed for D2D display + +mpe_send_grib : OFF # ON/OFF token to determine if grib file is + # to be sent to other sites such as NPVU + +# disagg processing tokens + +mpe_disagg_execute : OFF +mpe_disagg_method : POINT +mpe_disagg_6hreq_0 : 1 +mpe_disagg_6hrgt_0 : 1 + +#====== High-resolution Precipitation Estimator (HPE) tokens==================== + +# DecodeDHR tokens (formerly DecodeHDP tokens that looked like hdp_*) + +dhr_log_dir : $(pproc_log)/decodedhr # DHR Decoder logs + +dhr_prod_dir : $(pproc_local_data)/dhr_gather # DHR input directory + +dhr_dirname1 : $(data_archive_root)/radar # first part of directory name +# # containing DHR products for +# # associated or dial in radars + +dhr_dirname2 : DHR/layer0/res1/level256 # second part of directory name + # containing DHR products for + # associated or dial in radar +dhr_grid_dir : $(pproc_local_data)/dhr_decoded # decoded DHR radar grids + +dhr_error_dir : $(pproc_local_data)/dhr_error # DHR error files +dhr_arch_dir : $(pproc_local_data)/dhr_archive # DHR archives + +# DecodeDSP tokens (formerly DecodeHDP tokens that looked like hdp_*) + +dsp_log_dir : $(pproc_log)/decodedsp # DSP Decoder logs + +dsp_prod_dir : $(pproc_local_data)/dsp_gather # DSP input directory + +dsp_dirname1 : $(data_archive_root)/radar # first part of directory name +# # containing DSP products for +# # associated or dial in radars + +dsp_dirname2 : STP/layer0/res2/level256 # second part of directory name + # containing DSP products for + # associated or dial in radars + # NOTE that DSP is level256 vs level16 for + # STP and this is where it is stored + # in AWIPS +dsp_grid_dir : $(pproc_local_data)/dsp_decoded # decoded DSP radar grids +dsp_error_dir : $(pproc_local_data)/dsp_error # DSP error files +dsp_arch_dir : $(pproc_local_data)/dsp_archive # DSP archives + + +hpe_generate_list : DHRMOSAIC,BDHRMOSAIC,ERMOSAIC,LSATPRE,EBMOSAIC +hpe_qpe_fieldtype : ERMOSAIC # field type to be saved as qpe + +hpe_satpre_dir : $(mpe_fieldgen_product_dir)/satpre +hpe_input_dir : $(pproc_local_data)/app/hpe +hpe_output_dir : $(pproc_local_data)/hpe +hpe_sat_statevar_dir : $(rfcwide_output_dir)/state_var + +hpe_log_dir : $(pproc_local_data)/log/hpe + +hpe_hrap_grid_factor : 4 # 1 for HRAP grid + # 4 for quarter HRAP grid + +hpe_dhrmosaic_dir : $(hpe_output_dir)/dhrmosaic +hpe_bdhrmosaic_dir : $(hpe_output_dir)/bdhrmosaic +hpe_ermosaic_dir : $(hpe_output_dir)/ermosaic +hpe_ebmosaic_dir : $(hpe_output_dir)/ebmosaic +hpe_avg_ermosaic_dir : $(hpe_output_dir)/avgrmosaic +hpe_max_ermosaic_dir : $(hpe_output_dir)/maxrmosaic +hpe_lsatpre_dir : $(hpe_output_dir)/lsatpre + +hpe_dspheight_dir : $(hpe_output_dir)/height +hpe_dspindex_dir : $(hpe_output_dir)/index +hpe_height_dir : $(hpe_output_dir)/height +hpe_index_dir : $(hpe_output_dir)/index + +hpe_dhrmosaic_grib_dir : $(hpe_dhrmosaic_dir)/grib +dhrmosaic_netcdf_dir : $(hpe_dhrmosaic_dir)/netcdf +dhrmosaic_gif_dir : $(hpe_dhrmosaic_dir)/gif +hpe_bdhrmosaic_grib_dir : $(hpe_bdhrmosaic_dir)/grib +bdhrmosaic_netcdf_dir : $(hpe_bdhrmosaic_dir)/netcdf +bdhrmosaic_gif_dir : $(hpe_bdhrmosaic_dir)/gif +hpe_ermosaic_grib_dir : $(hpe_ermosaic_dir)/grib +ermosaic_netcdf_dir : $(hpe_ermosaic_dir)/netcdf +ermosaic_gif_dir : $(hpe_ermosaic_dir)/gif +hpe_ebmosaic_grib_dir : $(hpe_ebmosaic_dir)/grib +ebmosaic_netcdf_dir : $(hpe_ebmosaic_dir)/netcdf +ebmosaic_gif_dir : $(hpe_ebmosaic_dir)/gif + +dhrmosaic_save_grib : save +dhrmosaic_save_gif : nosave +dhrmosaic_save_netcdf : nosave +bdhrmosaic_save_grib : save +bdhrmosaic_save_gif : nosave +bdhrmosaic_save_netcdf : nosave +ermosaic_save_grib : save +ermosaic_save_gif : nosave +ermosaic_save_netcdf : nosave +ebmosaic_save_grib : save +ebmosaic_save_gif : nosave +ebmosaic_save_netcdf : nosave + +hpe_gif_dir : $(hpe_output_dir)/hpe_gif +hpe_jpeg_dir : $(hpe_output_dir)/hpe_jpeg +hpe_netcdf_dir : $(hpe_output_dir)/hpe_netcdf +hpe_grib_dir : $(hpe_output_dir)/hpe_grib +hpe_xmrg_dir : $(hpe_output_dir)/hpe_xmrg +hpe_save_gif : nosave +hpe_save_jpeg : nosave +hpe_save_netcdf : nosave +hpe_save_grib : nosave + +dhr_window : 15 +dsp_window : 15 +dsp_duration : 60 + +hpe_base_radar_mosaic : ERMOSAIC +hpe_qpe_fieldtype : ERMOSAIC +hpe_load_misbin : OFF +hpe_debug_log : ON +hpe_use_locbias : OFF +hpe_runfreq : 5 +hpe_timelag : 5 +hpe_bias_source : RFC +hpe_rfc_bias_lag : 2 +hpe_purge_logage : 720 +hpe_purge_fileage : 180 +hpe_purge_xmrgage : 75 + +dhrmosaic_d2d_display_grib : ON +ermosaic_d2d_display_grib : ON +ebmosaic_d2d_display_grib : ON +bdhrmosaic_d2d_display_grib : ON +hpe_run_nowcast : ON +hpe_nowcast_generate_list : PRTM, BPTRM +hpe_nowcast_dir : $(hpe_output_dir)/nowcast +hpe_rate_save_grib : save +hpe_brate_save_grib : save +hpe_tp1h_save_grib : save +hpe_btp1h_save_grib : save +hpe_4km_tp1h_save_grib : nosave +hpe_4km_btp1h_save_grib : nosave +nowcast_d2d_display_grib : ON +hpe_smooth_method : 1 # 0=no smoothing 1=FFP method (default) 2=BZ94 method +hpn_use_meanvelocity : OFF +hpn_meanvelocity_direction : 45 # direction precip is moving towards +hpn_meanvelocity_speed : 20 # miles per hour + + +hpe_send_grib : OFF # ON/OFF token to determine if grib file is + # to be sent to other sites such as NPVU + +#========END HPE tokens====================================================== + +# ================= Flash Flood Guidance System ============================= + +ffg_level : oper + +ffg_dir : $(apps_dir)/rfc/nwsrfs/ffg # Top-level ffg +ffg_bin : $(ffg_dir)/bin # FFG execute dir +ffg_files : $(ffg_dir)/files # FFG file group +ffg_gsfiles : $(ffg_files)/$(ffg_level) # FFG files dir +ffg_out_dir : $(ffg_dir)/output # FFG output dir +ffg_grib_out : $(ffg_out_dir)/grib # GRIB output +ffg_scripts : $(ffg_dir)/scripts # FFG scripts +ffg_gff_level : grff # regular grid ffg dir +ffg_gro_level : grro # regular grid ro dir + .Apps_defaults +ffg_usr_dir : $(ffg_gsfiles)/user # FFG user dir +ffg_area_dir : $(ffg_gsfiles)/affg # FFG area dir +ffg_cary_dir : $(ffg_gsfiles)/cary # FFG carryover dir +ffg_define_dir : $(ffg_gsfiles)/define # FFG definition dir +ffg_gridff_dir : $(ffg_gsfiles)/$(ffg_gff_level) # FFG grid ff dir +ffg_gridro_dir : $(ffg_gsfiles)/$(ffg_gro_level) # FFG grid ro dir +ffg_hwatr_dir : $(ffg_gsfiles)/hffg # FFG headwater dir + +ffg_gridpm_dir : $(ffg_gsfiles)/gdpm # grid runoff adjust parameters +ffg_group_dir : $(ffg_gsfiles)/grpp # FFG groups of products +ffg_prod_dir : $(ffg_gsfiles)/prod # FFG products dir +ffg_text_dir : $(ffg_gsfiles)/text # FFG text dir +ffg_wsup_dir : $(ffg_gsfiles)/wsup # Water supply dir + +# ffg program control +ffg_error_output : on # whether to output error messages +ffg_log_output : off # whether to output log messages + +# ===================== GRIB packer/encoder ================================= + +grib_dir : $(apps_dir)/rfc/grib # Top level grib +grib_rls : $(pproc_bin) # location of gribit executable +grib_arc : $(grib_dir)/bin/ARCHIVE # grib archive +grib_in_dir : $(rfcwide_xmrg_dir) # depends on data to be encoded +grib_out_dir : $(grib_dir)/output # GRIB encoded files +grib_error_output : on # turn on/off GRIB error output +grib_set_subcenter_0 : off # set subcenter to 0 + # on - set subcenter to 0 + # off - do not set subcenter to 0 + +# end of ffg apps + +#================== XSETS Apps_defaults Tokens - 08/03/2001 =================== + +# [] = default value +#................................. +# Date Control +#................................. +xsets_date_used : SYSTEM # computer system clock + # OFSFILES = forecast time series + # mm/dd/ccyy = explicit date, 12Z + +#................................. +# Directories and files to use +#................................. +xsets_dir : $(apps_dir)/rfc/xsets +xsets_level : oper +xsets_files : $(xsets_dir)/files +xsets_xsfiles : $(xsets_files)/$(xsets_level) +xsets_param_dir : $(xsets_xsfiles)/param +xsets_config_file : xsetsconfig +xsets_output_dir : $(xsets_xsfiles)/output + +#................................. +# Commands +#................................. +xsets_editor : "nedit" +xsets_hydrographs_cmd : "$(xsets_dir)/bin/RELEASE/new_hydroplot" +xsets_print_cmd : "lp" +xsets_xmit_cmd : "cat " + +#................................. +# Parameters for creation of hydrographs +#................................. +xsets_hydro_button : NO # Create Make Hydro button, [NO] + (currently unused) +xsets_make_hydro : NO # Create .gif hydrographs, [NO] + +#................................. +# NEW_HYDROPLOTS parameters +#................................. +xsets_html_daily_dir : /pub/FcstGraphs # Location of gif images on + web server +xsets_html_flood_dir : /pub/FloodGraphs # Location of gif images on + web server +xsets_hydrographs_html : 1 # 1 = create basic html + 0 = no html created +xsets_hydrographs_output: "$(xsets_output_dir)/gifs" +xsets_hydrographs_param : $(xsets_xsfiles)/hydrographs/param + +#................................. +# File Print Options and Settings +#................................. +xsets_add_remarks : NO # Add remark after each site, [NO] +xsets_brackets : NO # Put brackets around latest stage, + # forecasts and dates, [NO] +xsets_cmt_line : NO # YES = separate line, + # NO = append to description, river +xsets_expanded_dates : YES # Insert MMDD before values, [NO] +xsets_fgroup_preamble : "FORECAST GROUP IS" #Preamble for the fgroup (string) +xsets_H_precision : 1 # 0, [1], or 2 decimal precision of stages +xsets_output_style : E # E = Expanded, each day has line, + # C = Compact +xsets_print_crests : YES # Print crest comment, [NO] +xsets_print_disclaimer : YES # Print disclaimer, [NO] +xsets_print_fs : YES # YES = encode flood stage in SHEF, + # [NO] = display as comment +xsets_print_fs_cross : COMMENT # Time level passes flood stage + # [NO] = don't include, + # SHEF = encode in SHEF, + # COMMENT = display as comment +xsets_print_ls : COMMENT # Latest stage + # [NO] = don't include, + # SHEF = encode in SHEF, + # COMMENT = display as comment +xsets_print_MAP : NO # Print MAP values, [NO] +xsets_print_qpf : COMMENT # Print QPF values + # [NO] = don't include, + # SHEF = encode in SHEF, + # COMMENT = display as comment +xsets_print_ws : YES # Display warning/caution stage, [NO] +xsets_product_hdr : PIT # Indentifier in Product Header, non-AWIPS +xsets_Q_precision : 1 # 0, [1], 2 decimal precision of flows +xsets_signature : $(LOGNAME) #User signature (string) +xsets_wmo_id : TTAA00 KTUR DDHHMM # the wmo id +xsets_ws_label : "WARNING" # Label for WARNING/[CAUTION] stage (string) +xsets_zczc : YES # Include ZCZC & NNNN, [NO], non-AWIPS + +#................................. +# Run Options +#................................. +xsets_age_check : 6 # Number of hours old of forecast before + # error generated, [6] +xsets_edit_lock : NO # Lock main display when editing SETS file, [NO]??? +xsets_gen_summary : NO # Include summary of flood locations, [NO], Currently Unused +xsets_msg_obs_warn : YES # Print warning when observed values are + # missing, [NO] +xsets_numhrs_curob : 12 # number of hours back from current time to use + # informix obs as "current obs" +xsets_num_MAP_values : 4 # Number [4] of MAP values to include in product +xsets_num_qpf_values : 4 # Number [4] of qpf values to include in product +xsets_numdays_hydro : 3 # Run Parameters for FCSTPROG +xsets_ofs_select : OFS # OFS or IFP for time series files +xsets_stdout : NO # Send wprint messages to stdout, [NO] +xsets_time : Z # Time Zone code used in product + # ([Z], E, C, M, P, A, H OR N) +# ================== end of xsets tokens ======================================= + +#================== XNAV Apps_defaults Tokens - 03/29/2000 ==================== +# defaults for program XNAV + +xnav_user : oper + +#................................. +# Date/time related tokens +#................................. +db_days : 10 +xnav_daily_days : 30 +xnav_ffg_periods : 3 +xnav_sixhr_periods : 40 +xnav_hyd_days_fut : 5 +xnav_hyd_days_prev : 5 +xnav_precip_hours : 240 +xnav_settoday : + +#................................. +# Directories and files to use +#................................. +xnav_dir : $(apps_dir)/rfc/xnav +xnav_data : $(xnav_dir)/data +xnav_params : $(xnav_dir)/parameters +xnav_P1xmrg_dir : $(rfs_dir)/ofs/files/$(xnav_user)/griddb +xnav_S1xmrg_dir : $(rfs_dir)/ofs/files/$(xnav_user)/griddb +xnav_bin_dir : $(xnav_dir)/bin +xnav_data_dir : $(xnav_data) +xnav_ffg_dir : $(ffg_dir)/output/$(xnav_user) +xnav_geo_data : $(geo_data)/$(ifp_rfc)/binary +xnav_gif_dir : $(HOME)/gifs/xnav +xnav_grid_ffg_dir : $(ffg_dir)/files/$(xnav_user)/grff +xnav_localdata_dir : $(xnav_data)/localdata +xnav_misc_dir : $(xnav_data)/misc_data +xnav_qpfbin_dir : $(xnav_data)/wfoqpf +xnav_rfcfmap_dir : $(xnav_data)/rfcqpf +xnav_rules_dir : $(xnav_params)/rules +xnav_shefdata_dir : $(xnav_data)/shefdata +xnav_wfoqpf_dir : $(apps_dir)/rfc/data/products +xnav_xmrg_dir : $(rfs_dir)/ofs/files/$(xnav_user)/griddb +nmap_xmrg_dir : $(xnav_rfcfmap_dir)/nmap + +#................................. +# Fonts and colors +#................................. +xnav_action_color : yellow +xnav_flood_color : red +xnav_ok_color : green +xnav_ts1_color : yellow +xnav_ts2_color : magenta +xnav_label_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" +xnav_legend_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" +xnav_list_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" +xnav_menu_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" +xnav_pb_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" +xnav_text_font : -*-charter-bold-*-*-*-17-*-*-*-*-*-*-* +xnav_toggle_font : "-*-new century schoolbook-*-*-*-*-14-*-*-*-*-*-*-*" +xnav_town_font : "-*-new century schoolbook-bold-*-*-*-14-*-*-*-*-*-*-*" + +idma_label_font : "-*-new century schoolbook-bold-*-*-*-12-*-*-*-*-*-*-*" +idma_data_font : "-*-new century schoolbook-bold-*-*-*-18-*-*-*-*-*-*-*" + +#................................. +# Window size controls +#................................. +xnav_hrap_x : 59 +xnav_hrap_xor : 311 +xnav_hrap_y : 83 +xnav_hrap_yor : 410 +xnav_hydro_height : 400 +xnav_hydro_width : 750 +xnav_scale : 8.0 +xnav_scale_colors : 3.0 +xnav_x_offset : 100 +xnav_y_offset : 100 + +#................................. +# Display options +#................................. +xnav_basins : yes +xnav_counties : no +xnav_cwas : no +xnav_fgroups : no +xnav_flights : no +xnav_grid : no +xnav_hydro_segments : no +xnav_radars : no +xnav_rfc : yes +xnav_rivers : yes +xnav_states : yes +xnav_towns : yes + +#................................. +# Other control options +#................................. +load_db_on_boot : no +load_ofs_on_boot : no +check_flood_on_boot : no +use_new_xmrg : yes +xnav_afosid : ? #PITRR1RHA +xnav_editor : nedit +xnav_exception_file : exception_file +xnav_grid_ffg_pattern : xhr +xnav_locrangecheck : no +xnav_office_hdr : ? #KRHA +xnav_only_use_ofs_data : no +xnav_pe : "HG HP HT PP PT QR QT SD SF SW TA TD TS XC" +xnav_precip_filter : .01 +xnav_route_code : ? #ES +xnav_seg_type : 2 +xnav_send_shef : no +xnav_show_p1_files : yes +xnav_suppress_msg : yes +xnav_xmit_cmd : "cat " + +# ====== MAKE24HRXMRG Tokens ====== + +make24hrxmrg_settoday : # Run date in mm/dd/yyyy. Empty means uses number + # of days back argument to program. +make24hrxmrg_debug_level : 0 # Set debug output level. 1 or 2 yields more output. +make24hrxmrg_endtime : # Hour to end the 24 hour total. Default: 12Z if not + # given. +make24hrxmrg_tz : Z # Time zone; E, C, M, P, Y, H, L, or Z (defautlt). + +# ================== end of xnav tokens ======================================== + +#================== XDAT Apps_defaults Tokens - 03/29/2000 ==================== +# defaults for program XDAT + +xdat_user : oper + +#................................ +# Date/time related tokens +#................................ +xdat_flood_hours : 6 +xdat_settoday : + +#.................................. +# Directories and files to use +#.................................. +xdat_dir : $(apps_dir)/rfc/xdat +xdat_data : $(xdat_dir)/data +xdat_params : $(xdat_dir)/parameters +xdat_groups_dir : $(xdat_params)/groups +xdat_localdata_dir : $(xdat_data)/localdata +xdat_shefdata_dir : $(xdat_data)/shefdata + +#.................................. +# Fonts and colors to use +#.................................. +xdat_label_font : ncenb14 +xdat_list_font : helvb14 +xdat_text_font : user14x19 +xdat_pb_font : ncenb14 + +#................................. +# Window size controls +#................................. +xdat_scale : 1.0 + +#.................................. +# Display Options +#.................................. +xdat_clear_id : yes + +#.................................. +# Other Control Options +#.................................. +xdat_afosid : ?ofstest? +xdat_office_hdr : ??? +xdat_post_unk : $(shef_post_unk) +xdat_route_code : ??? +xdat_send_shef : no +xdat_xmit_cmd : "cat " +# ================== end of xdat tokens ======================================== + +#====================== Shape Data File Directory ============================== +shape_data_dir : $(apps_dir)/ffmpShapeData # Directory holding shape + # files acting as data files + + +#================== send_rfc Apps_defaults Tokens - 3/08/2001 ================= +send_rfc_dir : $(apps_dir)/rfc/send_rfc +send_rfc_input_dir : $(send_rfc_dir)/data/send +send_rfc_id : WWW +send_hardcopy_nnn : PRI-WRK-EDI-SNO-ADM-RVF +send_rfc_hardcopy : $(send_rfc_dir)/data/sbnprods +send_rfc_hpc : 0 +send_rfc_host : ds-www +send_rfc_alternate : 0 +# ================== end of send_rfc tokens ==================================== + +#================== verify Apps_defaults Tokens - 08/03/2001 ================== +# defaults for program verify +vsys_output : $(vsys_dir)/output #location of output files +vsys_input : $(vsys_dir)/input #location of input files +vsys_files : $(vsys_dir)/files #location of verify files +vsys_scripts : $(vsys_dir)/scripts #location of verify scripts +vsys_output_log : test.log #name of log file +vsys_ihfsdb : $(db_name) #ihfs_db name +vsys_vdb : vdb1_1rfc #verification db name for RFC="rfc" +verify_rls : $(vsys_dir)/bin/RELEASE #The release directory. +vsys_rls : $(verify_rls) #Not really needed, but consistent. + +# ================== end of verify tokens ====================================== + +# ================== RFC Archive Database tokens =============================== + +archive_shefdata_dir : /data/fxa/ispan/hydro_adbs # directory for archive data +archive_enable : OFF # ON/OFF - Enable or Disable + # archive data feed (OFF by default) +metar_output_dir : $(whfs_local_data_dir)/metar_output # metar2shef temp output directory + # used if archive_enable is ON + +#================== Directory tokens for RFC Archive Database ================== +adb_dir : /rfc_arc # Base RFC Archive Directory +adb_raw_que : /rfc_arc_data/q/raw/ # pathname for raw q input directory +adb_pro_que : /rfc_arc_data/q/processed/ # pathname for processed q input directory +adb_bin_dir : $(adb_dir)/bin # pathname for the bin directory +adb_cfg_dir : $(adb_dir)/cfg # pathname for the config directory +adb_lib_dir : $(adb_dir)/lib # pathname for the lib directory +adb_logs_dir : $(adb_dir)/logs # pathname for the logs directory +adb_scripts_dir: $(adb_dir)/scripts # pathname for the scripts directory + +#================== Shefdecode tokens for RFC Archive Database ================= + +adb_shef_winpast : 9999 # number of days in past to post data for RAW +adb_shef_winfuture : 9999 # number of mins in future to post obs data + # for RAW. +adb_shef_winpast_pro : 9999 # number of days in past to post data +adb_shef_winfuture_pro : 9999 # number of minutes in future to post obs data +shefdecode_rax_userid : oper # controlling UNIX user +adb_shefdecode_input : $(adb_cfg_dir)/decoders # adb SHEF parameter file + # location +adb_shef_raw_perflog : OFF # ON/OFF - create a separate performance + # log file to save internal decoder timing + # messages for monitoring performance +adb_shef_raw_logs_dir : $(adb_logs_dir)/decoder/raw/logs # pathname for the + # daily logs directory +adb_shef_raw_err_dir : $(adb_logs_dir)/decoder/raw/err # pathname for the + #product logs directory +adb_shef_raw_keeperror : ALWAYS # keep files (=ALWAYS) or only + # when errors occur (=IF_ERROR) +adb_shef_raw_post_unk : IDS_AND_DATA # NONE - do not post to the UnkStnValue tables + # values IDS_ONLY or IDS_AND_DATA + # will post everything + # to the UnkStnValue table +adb_shef_pro_post_unk : NONE # NONE - do not post to the UnkStnValue tables + # values IDS_ONLY or IDS_AND_DATA + # will post everything + # to the UnkStnValue table +adb_shef_pro_perflog : OFF # ON/OFF - create a separate performance + # log file to save internal decoder timing + # messages for monitoring performance +adb_shef_pro_logs_dir : $(adb_logs_dir)/decoder/processed/logs # pathname for the + # daily logs directory +adb_shef_pro_err_dir : $(adb_logs_dir)/decoder/processed/err # pathname for the + # product logs directory +adb_shef_pro_keeperror : ALWAYS # keep files (=ALWAYS) or only + # when errors occur (=IF_ERROR) +adb_shef_raw_checktab : ON # ON checks location and ingestfilter tables +adb_shef_pro_checktab : OFF # ON checks location and ingestfilter tables +adb_shef_duplicate_raw : USE_REVCODE # Token for allowing duplicate records to be + # posted for raw decoder. +adb_shef_duplicate_pro : USE_REVCODE # Same thing but for processed decoder. +adb_shef_raw_dupmess : ON # duplication messages from adb raw decoder. +adb_shef_raw_locmess : ON # invalid location messages from adb raw decoder. +adb_shef_raw_elgmess : ON # invalid ingestfilter messages from adb raw + # decoder. +adb_shef_raw_storall : OFF # OFF - default- will only write to pecrsep table + # ON will write to both pecrsep and peirsep tables +adb_shef_pro_dupmess : ON # duplication messages from adb processed decoder. +adb_shef_pro_locmess : OFF # invalid location messages from adb pro decoder. +adb_shef_pro_elgmess : OFF # invalid ingestfilter messages from adb pro + # decoder. +adb_shef_pro_tmp_dir : $(adb_pro_que) +adb_shef_raw_tmp_dir : $(adb_raw_que) +adb_shef_raw_add_adjust : OFF + +#========== IHFS->RAX synchronization tokens for RFC Archive Database ========== +adb_sync_logs_dir : $(adb_logs_dir)/dbsync # directory for synchronization log files +adb_sync_mode : ANALYSIS # ANALYSIS or UPDATE +adb_sync_tablenames : ALL # List of table names to synchronize +adb_sync_ihfs_ingest: USE # USE or IGNORE +adb_sync_rivercrit : ACTION # ACTION, FIS or BOTH + + +#================== DatView program tokens for RFC Archive Database ============ +datview_db_name : $(adb_name) +datview_startdate : '1975-01-01 00:00:00' +datview_label_font : -schumacher-clean-bold-r-normal-*-14-*-75-75-c-80-*-* +datview_list_font : -schumacher-clean-bold-r-normal-*-14-*-75-75-c-80-*-* +datview_text_font : -schumacher-clean-bold-r-normal-*-14-*-75-75-c-80-*-* +datview_text2_font :-adobe-courier-bold-r-normal-*-*-140-*-*-m-*-iso8859-1 +datview_bg_color : black +datview_fg_color : white +datview_ob_color1 : green +datview_ob_color2 : blue +datview_ob_color3 : yellow +datview_ob_color4 : red +datview_ob_color5 : DarkOrange +datview_ob_color6 : SlateGray1 +datview_plot_font : -adobe-courier-bold-r-normal-*-*-80-*-*-m-*-iso8859-1 +datview_plot_width : 750 +datview_plot_height : 420 +datview_data_dir : /home/oper +datview_raw_shef_dir : $(adb_raw_que) +datview_pro_shef_dir : $(adb_pro_que) +datview_office_header : KTUA # to be set by each RFC +datview_pil : OKCRR1TUR # to be set by each RFC + + +#=============== ARCH_NAV Apps_defaults Tokens - 05/5/2005 ================== +# defaults for program ARCNAV + +anav_user : oper + +#................................. +# Date/time related tokens +#................................. +anav_daily_days : 30 +anav_sixhr_periods : 40 +anav_precip_hours : 24 + + +#................................. +# Directories and files to use +#................................. + +anav_dir : /awips/hydroapps/lx/rfc/xnav +anav_data : /data +anav_flatfiles : $(anav_data)/flatfiles +anav_params : $(anav_dir)/parameters +anav_data_dir : $(anav_data) +anav_geo_data : /awips/hydroapps/lx/geo_data/$(ifp_rfc)/binary +anav_gif_dir : /rfc_arc/data/arcnav/gifs +anav_localdata_dir : $(anav_data)/localdata +anav_xmrg_dir : $(anav_flatfiles) + +#................................. +# Fonts and colors +#................................. +anav_label_font : courb14gr +anav_legend_font : courb14gr +anav_list_font : courb14gr +anav_menu_font : 9x15 +anav_pb_font : courb12gr +anav_text_font : helvb18gr +anav_toggle_font : courb14gr +anav_town_font : courb12gr + +#................................. +# Window size controls +#................................. +anav_hrap_x : 200 +anav_hrap_xor : 850 +anav_hrap_y : 200 +anav_hrap_yor : 470 +anav_hydro_height : 400 +anav_hydro_width : 750 +anav_scale : 3.5 +anav_scale_colors : 3.0 +anav_x_offset : 300 +anav_y_offset : 300 + +#................................. +# Display options +#................................. +anav_basins : yes +anav_counties : no +anav_cwas : no +anav_fgroups : no +anav_flights : no +anav_grid : no +anav_hydro_segments : no +anav_radars : no +anav_rfc : no +anav_rivers : no +anav_states : yes +anav_towns : yes + +#................................. +# Other control options +#................................. +anav_editor : nedit +anav_suppress_msg : yes + +#...................................... +# tokens added for arcnav application +# for future use +#...................................... +anav_ok_color : green +anav_action_color : yellow +anav_flood_color : red +anav_ts1_color : yellow +anav_ts2_color : magenta + +# ================= end of arcnav tokens ====================================== + +# ================== end of RFC Archive Database tokens ======================== + +# ================== SSHP Directory Structure and application tokens =============================== + +local_data_sshp_dir : $(whfs_local_data_dir)/sshp_transfer +sshp_control_dir : $(whfs_local_data_dir)/app/sshp +sshp_ofs_extract_text_dir : $(local_data_sshp_dir)/ofs_extract_text +sshp_ofs_extract_xml_dir : $(local_data_sshp_dir)/ofs_extract_xml +sshp_ingest_xml_dir : $(local_data_sshp_dir)/ingest_xml +sshp_incoming_dir : $(local_data_sshp_dir)/incoming +sshp_outgoing_dir : $(local_data_sshp_dir)/outgoing +sshp_log_dir : $(whfs_log_dir)/sshp +sshp_java_process_host : px1f +sshp_invoke_map_preprocess: ON +sshp_map_qpe_to_use : MIXED # choices are: MIXED, LOCAL_BEST_ONLY, RFC_ONLY +sshp_fcst_ts : FZ # SSHP type-source code for generated forecasts +sshp_initial_forecast_length: 24 # length of forecast in hours +sshp_max_forecast_length: 120 # max length of forecast in hours that user can make generated in GUI +sshp_sac_update_expiration_hours: 25 # number of hours after which to update locally the SAC states +sshp_sac_update_hours_forward: -2 # number of hours forward of last top of hour to save sac states - + # negative -2 means 2 hours BEFORE last top of hour +sshp_adjustment_pairing_minutes : 70 +sshp_adjustment_interpolation_hours : 3 +sshp_show_simulated_timeseries : true + +sshp_data_dir : $(whfs_local_data_dir)/sshp # base sshp dynamic data dir +sshp_precip_dir : $(sshp_data_dir)/precip # default location for saved precip files +sshp_background_forecast_output_dir : $(sshp_data_dir)/forecast +sshp_background_forecast_length : 48 # length of a background forecast + +sshp_hpn_minutes_before : 5 # don't use grid files prior to X minutes before Hour +sshp_hpn_minutes_after : 5 # don't use grid files after X minutes past the Hour + +sshp_show_unadjusted_states: false # initial setting of option in GUI for displaying the unadjusted SAC-SMA states +# ==================== Radar Climatology Tokens ============================== +radclim_data_dir : $(pproc_local_data)/app/radclim + +# ==================== PDC Preprocessor Tokens =============================== +pdc_clean_cache_minutes : 60 +pdc_temperature_hours : 168 +pdc_height_hours : 168 +pdc_snow_hours : 168 +pdc_wind_hours : 168 +pdc_weather_hours : 168 +pdc_precip_hours : 168 +pdc_lower_window : 5 +pdc_upper_window : 5 + +pdc_pp_dir : $(whfs_local_data_dir)/pdc_pp +pdc_pp_log_dir : $(whfs_log_dir)/pdc_pp + +# ====================== Historical Data Browser Tokens ======================= + +hdb_help_dir : $(hdb_dir)/help_files # Historical data browser help + # files +hdb_script_directory : $(hdb_dir)/scripts # Historical data browser + # scripts dir +hdb_config_dir : $(hdb_dir)/app-defaults # Historical data browser + # configuration file directory + +hdb_height_in_pixels : 900 # Historical data browser map height in + # pixels +hdb_width_in_pixels : 1200 # Historical data browser map width in + # pixels +hdb_center_lat : 35 # The initial center latitude of the HDB +hdb_center_lon : -88.9 # The initial center longitude of the HDB +hdb_map_width : 2999.862 # The width in nautical miles of the area + # displayed in the HDB +hdb_disclosure_limit : 60 # The disclosure limit for displaying finer + # detail in the city overlay. +hdb_map_projection : FLAT # The initial map projection used by HDB. + # Possible values: FLAT, POLAR, HRAP +# ====================== DHM Token ======================= +dhm_data_dir : $(ofs_files)/$(ofs_level)/dhmdata # DHM data dir +dhm_d2d_data_dir : /data/fxa/Grid/LOCAL/netCDF/DHM # d2d data dir +dhm_d2d_notify_bin_dir : /awips/fxa/bin # d2d notify bin dir +rdhm_input_dir : $(geo_data) +dhm_rain_plus_melt_data_dir: $(geo_data) +# ================== end of SSHP Directory Structure tokens ======================== + + +# The syntax needed in the file is: +# +# token : resource +# +# where: token is defined as a string delimited by white space or +# the delimiter, +# the delimiter between token and resource is the :, +# no white space needs to surround the delimiter, +# comments are indicated by a #, +# neither token nor resource can begin with a # or :, +# a # or a : can be embedded within resource, +# resource can contain white space if it is bounded by +# the ' or " characters, +# blank lines are allowed. +# referbacks are indicated by $(...). The '...' is resolved +# the same way any other token is, and is substituted for +# the $(...) string to compose the final resource value. +# Multiple referbacks are allowed in a resource, but +# embedded referbacks are not allowed (i.e. no +# $($(...)) allowed). +# Note that this file is read only if the token can not be resolved +# as an environment variable. +# +# ============================================================================== diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/InternalReport.java b/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/InternalReport.java index e2d3642815..6a9582572c 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/InternalReport.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/InternalReport.java @@ -41,6 +41,7 @@ import org.apache.commons.logging.LogFactory; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 26, 2009 jkorman Initial creation + * Oct 23, 2013 DR 16674 D. Friedman Prevent infinite loop * * * @@ -238,8 +239,8 @@ public class InternalReport { case DATE : { if(currRpt != null) { currRpt.subLines.add(r); - reports.remove(r); } + reports.remove(r); break; } case REMARK : { diff --git a/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id b/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id index 2291591ae6..7b5e854ce1 100644 --- a/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id +++ b/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id @@ -1 +1 @@ -2d8d4c03270ef631f167570cf0c03461ff832fea \ No newline at end of file +759799451b20c427bdaa8cb8185b9602cc66c6c6 \ No newline at end of file diff --git a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/nrldb.ksh b/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/nrldb.ksh deleted file mode 100644 index 9b0f0198fe..0000000000 --- a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/nrldb.ksh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/ksh -############################################################################### -# AWIPS2 wrapper script for the daily scheduled NRLDB process. This uses the # -# nrldb.pl script to extract the static data from the IHFSDB, packages it in # -# an XML file and uploads it to the NRLDB server on the NHOR. # -# # -# Mark Armstrong (HSD) - 10/17/2013 # -############################################################################### -RUN_FROM_DIR=`dirname $0` -#echo "RFD: $RUN_FROM_DIR" -# set up SOME environment variables for WHFS applications -export PGSQL_DRIVER_DIR=/awips2/cave/plugins/org.postgres_9.2.0 -export EDEX_HOME=/awips2/edex -export apps_dir=/awips2/edex/data/share/hydroapps -. $RUN_FROM_DIR/../../set_hydro_env -. $RUN_FROM_DIR/../../check_app_context - - -export NRLDB_DATA=$(get_apps_defaults nrldb_data) -#echo "NRLDB data: $NRLDB_DATA" - -export NRLDB_LOG=$(get_apps_defaults nrldb_log) -#echo "NRLDB log: $NRLDB_LOG" - -export NRLDB_CONFIG=$(get_apps_defaults nrldb_config) -#echo "NRLDB config: $NRLDB_CONFIG" - -export WHFS_BIN=$(get_apps_defaults whfs_bin_dir) -#echo "WHFS_BIN: $WHFS_BIN" - -export NRLDBLOGFILE=${NRLDB_LOG}/nrldb.log -export NRLDBTMPFILE=${NRLDB_LOG}/nrldb.tmp -tail -5000 $NRLDBLOGFILE > $NRLDBTMPFILE -mv $NRLDBTMPFILE $NRLDBLOGFILE - -${WHFS_BIN}/nrldb.pl -t wfo -u - -# diff --git a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/nrldb.pl b/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/nrldb.pl deleted file mode 100644 index 409152e903..0000000000 --- a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/nrldb.pl +++ /dev/null @@ -1,1415 +0,0 @@ -#!/usr/bin/perl - -use strict; -use DBI; -use AppConfig qw(:expand :argcount); - - -#Set/define command line args -my %cfg = ( DEBUG => 0); # debug mode on or off -my $config = AppConfig->new(\%cfg); # create config object -$config->define('type',{ARGCOUNT => ARGCOUNT_ONE, VALIDATE => '(WFO|RFC|HQ|wfo|rfc|hq)', ALIAS => 'T'}); -$config->define('local-control-file',{ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'L',DEFAULT => 0}); -$config->define('upload',{ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'U', DEFAULT => 0}); -$config->define('wfo-id',{ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'W', DEFAULT => 0}); -$config->define('rfc-id',{ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'R', DEFAULT => 0}); -$config->define('out-xmlfile',{ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'O', DEFAULT => 0}); -$config->define('input-xmlfile',{ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'I', DEFAULT => 0}); -$config->define('check',{ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'C', DEFAULT => 0}); -$config->define('verbose',{ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'V', DEFAULT => 0}); -$config->define('dbname',{ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'D', DEFAULT => 0}); -$config->define('extract',{ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'E', DEFAULT => 0}); -$config->define('delete',{ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'A', DEFAULT => 0}); -$config->getopt(\@ARGV); - -our $type = uc($config->get('type')); -our $localControlFile = $config->get('local-control-file'); -our $Upload = $config->get('upload'); -our $wfoID = uc($config->get('wfo-id')); -our $rfcID = uc($config->get('rfc-id')); -our $outFile = $config->get('out-xmlfile'); -our $inFile = $config->get('input-xmlfile'); -our $check = $config->get('check'); -our $verbose = $config->get('verbose'); -our $dbname_flag = $config->get('dbname'); -our $extract = $config->get('extract'); -our $delete = $config->get('delete'); -our $office; -our $update_count = 0; -our $insert_count = 0; -our $error_count = 0; -our $total_count = 0; -our $file_name; -our $conf_dir; -my ($dbname, $host, $user, $pass, $nrldb_host, $backup_host); -my @delete_list; -my $delete_listRef; -print "db name flag: $dbname_flag\n"; -if($check) { - warn "-----Starting NRLDB installation check-----\nInstallation Complete.\n"; - print "Installation Complete.\n"; - exit 0; -} - - -#Get config file info -($dbname, $host, $user, $pass, $nrldb_host, $office, $backup_host) = read_config_file(); - -if(!$dbname_flag) -{ - if( -e "/awips/hydroapps/public/bin/get_apps_defaults") - { - $dbname = `/awips/hydroapps/public/bin/get_apps_defaults.LX db_name`; - } -} -else{ - $dbname = $dbname_flag; -} -# Do parameter checks -if($type eq "") -{ - print "No office type specified.\nusage: --type WFO|RFC|HQ\n\n"; - exit 1; -} -if($type eq "HQ") -{ - if($inFile eq 0) - { - print "No xml input file specified.\nusage: --type HQ --input-xmlfile 'file'\n\n"; - exit 1; - } - if($rfcID eq 0 && $wfoID eq 0) - { - print "You must specify a WFO/RFC office identifier with the HQ type.\n"; - exit 1; - } - - unless($rfcID eq 0) { - $office = $rfcID; - } - unless($wfoID eq 0) { - $office = $wfoID; - } - -} - -if($type eq "RFC") -{ - if($rfcID eq 0) - { - print "You must specify an RFC office identifier with the rfc option.\nusage: --type RFC --rfc-id IDRFC\n\n"; - exit 1; - } -} - - -#Connect to database -our $db = db_connect($dbname, $host, $user, $pass); - -my $date = getdate(); -print "---Starting NRLDB process at $office\, running as $type\---\n---$date\n\n" if($verbose); -warn "---Starting NRLDB process at $office\, running as $type\---\n---$date\n\n"; -print "Connected to database: $dbname\n" if($verbose); -warn "Connected to database: $dbname\n"; -#Determine what type of office is running nrldb software -if(($type eq "WFO") | ($type eq "RFC")) -{ - if($localControlFile eq 0) - { - download_control_file($type); - } - create_xml(); - if($Upload) - { - upload_xml($nrldb_host); - upload_xml($backup_host); - } -} -elsif($type eq "HQ") -{ - if($delete) - { - $delete_listRef = get_delete_list(); - @delete_list = @$delete_listRef; - foreach my $delete_table (@delete_list) - { - deleteValues($delete_table); - } - } - xml_parse(); -} - -print "\n-----------------------------\n\n" if($verbose); -warn "\n-----------------------------\n\n"; -exit 0; - - -# sub 'create_xml' is responsible for querying the database and putting the info into xml format. -sub create_xml -{ - -my $table_name; -my ($select_string, $field_string); -my $xml_string; -my $record_count; -my ($st, $at); -my $table_query; -my $query_error_flag; -my $numrows; -my $lid_flag; -my $pkey; -my ($pk_name, $field_name); -my $row; -my $extract_detail; -my %infohash; -my @tables; -my @fields; -my @fields_all; -my @select_array; -my @PK; -my @keys; -my (@pk_output, @fields_output); - -#read control file and put specified fields into array -my ($tables_ref, $fields_all_ref) = read_control_file(); -@tables = @$tables_ref; -@fields_all = @$fields_all_ref; - - $extract_detail = ''; -# print "EXTRACT: $extract\n"; - unless($extract eq 0) - { - $extract_detail = extract_detail(); - } - -# Start creating xml -$xml_string = "\n\n"; -foreach $table_name (@tables) -{ - - print "TABLE: $table_name\n" if($verbose); - warn "TABLE: $table_name\n"; - $select_string = ""; - $lid_flag = 1; - # Get primary key list for specified tables - @keys = $db->primary_key(undef, undef, $table_name); - - foreach $pkey (@keys) - { - # The following 6 lines were by mark Armstrong (HSD) on 2/26/09 - # to remove the quotes from primary keys. - # When primary keys occurred with quotes, the update queries - # were not successful. - if ($pkey =~ /"/){ - my $length_pkey = length $pkey; - $length_pkey -= 2; - my $new_pkey = substr($pkey,1,$length_pkey); - $pkey=$new_pkey; - } - push(@PK, "$table_name.$pkey"); - } - - @pk_output = grep(/$table_name\.\w*/, @PK); - print "\tPK: @pk_output\n" if($verbose); - warn "\tPK: @pk_output\n"; - @fields_output = grep(/$table_name\.\w*/, @fields_all); - print "\tFIELDS: @fields_output\n" if($verbose); - warn "\tFIELDS: @fields_output\n"; - - my $pk_count = @pk_output; - if($pk_count == 0) - { - print "No Primary Keys found for Table: $table_name\nContinuing\n\n" if($verbose); - warn "No Primary Keys found for Table: $table_name\nContinuing\n\n"; - next; - } - - #loop through arrays and put together a select string for specified table - foreach my $pk (@pk_output) - { - if($pk =~ /$table_name\.\w*/) - { - if($select_string eq "") - { - $select_string = "$pk"; - } - else - { - $select_string .= ",$pk"; - } - } - } - - - foreach my $fields (@fields_output) - { - if($select_string =~ /.*$fields.*/) - { - if($field_string eq "") - { - $field_string = "$fields"; - } - else - { - $field_string .= ",$fields"; - } - next; - } - elsif($fields =~ /.*ALL.*/) - { - $select_string = "*"; - last; - } - else - { - if($field_string eq "") - { - $field_string = "$fields"; - } - else - { - $field_string .= ",$fields"; - } - $select_string .= ",$fields"; - } - } - - - #print select string to be used - print "\n" if($verbose); - warn "\n"; - $query_error_flag = 0; - #if select string equal 'ALL' get a list of all fields in specified table by querying database info tables. - if($select_string eq "*") - { - - my $query_column1 = "SELECT c.oid - FROM pg_catalog.pg_class c - LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE pg_catalog.pg_table_is_visible(c.oid) - AND c.relname ~ '^$table_name\$'"; - - my $attribute_query = "SELECT a.attname - FROM pg_catalog.pg_attribute a - WHERE a.attnum > 0 AND NOT a.attisdropped - AND a.attrelid = ($query_column1) - ORDER BY a.attnum;"; - - eval - { - $at = $db->prepare($attribute_query); - $at->execute() or die "Cannot execute: ".$at->errstr(); - }; - if($@) - {print "$@\n" if($verbose); warn "$@\n";} - - my $att_count = 0; - while ( defined ( my $attribues = $at->fetchrow_arrayref() ) ) - { - if($att_count > 0) - { - $select_string .= ",$table_name.@$attribues[0]"; - } - else - { - $select_string = "$table_name.@$attribues[0]"; - } - $att_count++; - } - $field_string = $select_string; - } - - #Check for lid in table - if($select_string !~ /$table_name\.lid/) - { - $lid_flag = lid_check($table_name); - } - - # Determine query depending on office type and other parameters - ## Revised query to properly select only counties from primary HSA or identified WFO - Ernie Wells February 09 ## - if($type eq "WFO") - { - if($wfoID eq 0) { - if($table_name =~ /location/) - { - $table_query = "SELECT $select_string FROM location, admin WHERE location.hsa = admin.hsa $extract_detail ORDER BY lid;"; - } elsif($table_name =~ /counties/) { - $table_query = "SELECT $select_string FROM counties, admin WHERE counties.wfo = admin.hsa;"; - } elsif($table_name =~ /rpffcstgroup/) { - $table_query = "SELECT distinct $select_string from rpffcstgroup join rpffcstpoint rp on rp.group_id = rpffcstgroup.group_id join location l on l.lid = rp.lid join admin on l.hsa = admin.hsa;"; - } elsif($table_name =~ /vtecevent/) { - $table_query = "SELECT $select_string FROM vtecevent WHERE vtecevent.geoid in (select location.lid from location, admin where location.hsa = admin.hsa) $extract_detail;"; - } elsif($table_name eq "height" || $table_name =~ /temperature/ || $table_name =~ /curpp/ || $table_name =~ /curpc/ || $table_name eq "discharge"){ - my $cutoff_dtime = getcutoffdate(); - $table_query = "SELECT $select_string FROM $table_name WHERE exists (SELECT lid FROM location, admin WHERE location.lid = $table_name.lid AND location.hsa = admin.hsa) and obstime > '$cutoff_dtime' $extract_detail ORDER BY lid;"; - } elsif($table_name =~ /fcstheight/ || $table_name =~ /fcstdischarge/) { - my $cutoff_dtime = getcutoffdate(); - $table_query = "SELECT $select_string FROM $table_name WHERE exists (SELECT lid FROM location, admin WHERE location.lid = $table_name.lid AND location.hsa = admin.hsa) and basistime > '$cutoff_dtime' $extract_detail ORDER BY lid;"; - } elsif($lid_flag == 1){ - $table_query = "SELECT $select_string FROM $table_name WHERE exists (SELECT lid FROM location, admin WHERE location.lid = $table_name.lid AND location.hsa = admin.hsa) $extract_detail ORDER BY lid;"; - } - else { - $table_query = "SELECT $select_string FROM $table_name\;"; - } - } - else { - if($table_name =~ /location/) - { - if($extract eq 0) { - $table_query = "SELECT $select_string FROM location WHERE location.hsa = '$wfoID' $extract_detail ORDER BY lid;"; - } else { - $table_query = "SELECT $select_string FROM location WHERE location.hsa like '%' $extract_detail ORDER BY lid;"; - } - } elsif($table_name =~ /counties/) { - if($extract eq 0) { - $table_query = "SELECT $select_string FROM counties WHERE counties.wfo = '$wfoID';"; - } else { - $table_query = "SELECT $select_string FROM counties WHERE counties.wfo in (select hsa from location where hsa is not null $extract_detail) ;"; - } - } elsif($table_name =~ /rpffcstgroup/) { - if($extract eq 0) { - $table_query = "SELECT distinct $select_string from rpffcstgroup join rpffcstpoint rp on rp.group_id = rpffcstgroup.group_id join location l on l.lid = rp.lid where l.hsa = '$wfoID';"; - } else { - my $rpgroup_extract_detail = $extract_detail; - $rpgroup_extract_detail =~ s/lid/l.lid/g; - $table_query = "SELECT distinct $select_string from rpffcstgroup join rpffcstpoint rp on rp.group_id = rpffcstgroup.group_id join location l on l.lid = rp.lid where l.hsa is not null $rpgroup_extract_detail;"; - } - } elsif($table_name =~ /vtecevent/) { - if($extract eq 0) { - $table_query = "SELECT $select_string FROM vtecevent WHERE vtecevent.geoid in (select location.lid from location where location.hsa = '$wfoID') ;"; - } else { - my $vtec_extract_detail = $extract_detail; - $vtec_extract_detail =~ s/lid/geoid/g; - print "vtec_extract_detail: $vtec_extract_detail\n"; - $table_query = "SELECT $select_string FROM vtecevent WHERE vtecevent.geoid in (select location.lid from location where location.hsa is not null) $vtec_extract_detail;"; - } - } elsif($table_name eq "height" || $table_name =~ /temperature/ || $table_name =~ /curpp/ || $table_name =~ /curpc/ || $table_name eq "discharge"){ - my $cutoff_dtime = getcutoffdate(); - if($extract eq 0) { - $table_query = "SELECT $select_string FROM $table_name WHERE exists (SELECT lid FROM location WHERE location.lid = $table_name.lid AND location.hsa = '$wfoID') and obstime > '$cutoff_dtime' ORDER BY lid;"; - } else { - $table_query = "SELECT $select_string FROM $table_name WHERE exists (SELECT lid FROM location WHERE location.lid = $table_name.lid ) and obstime > '$cutoff_dtime' $extract_detail ORDER BY lid;"; - } - } elsif($table_name =~ /fcstheight/ || $table_name =~ /fcstdischarge/) { - my $cutoff_dtime = getcutoffdate(); - if($extract eq 0) { - $table_query = "SELECT $select_string FROM $table_name WHERE exists (SELECT lid FROM location WHERE location.lid = $table_name.lid AND location.hsa = '$wfoID') and basistime > '$cutoff_dtime' ORDER BY lid;"; - } else { - $table_query = "SELECT $select_string FROM $table_name WHERE exists (SELECT lid FROM location WHERE location.lid = $table_name.lid) and basistime > '$cutoff_dtime' $extract_detail ORDER BY lid;"; - } - } elsif($lid_flag == 1) { - if($extract eq 0) { - $table_query = "SELECT $select_string FROM $table_name WHERE exists (SELECT lid FROM location WHERE location.lid = $table_name.lid AND location.hsa = '$wfoID') $extract_detail ORDER BY lid;"; - } else { - $table_query = "SELECT $select_string FROM $table_name WHERE exists (SELECT lid FROM location WHERE location.lid = $table_name.lid) $extract_detail ORDER BY lid;"; - } - } else { - $table_query = "SELECT $select_string FROM $table_name\;"; - } - } - } elsif($type eq "RFC") { - if($table_name =~ /location/) { - $table_query = "SELECT $select_string FROM location WHERE location.rfc='$rfcID' $extract_detail ORDER BY lid;"; - } elsif($lid_flag == 1) { - $table_query = "SELECT $select_string from $table_name where exists (select lid from location where -location.lid = $table_name.lid and location.rfc='$rfcID') $extract_detail ORDER BY lid;"; - # $table_query = "SELECT $select_string from $table_name where exists (select lid from location where -#location.lid=rating.lid and location.rfc='$rfcID') $extract_detail ORDER BY lid;"; - } else { - $table_query = "SELECT $select_string FROM $table_name\;"; - } - } - - # print the query for log purpose and execute the query - print "$table_query\n\n" if($verbose); - warn "$table_query\n\n"; - $record_count = 0; - eval - { - $st = $db->prepare($table_query); - $row = $db->selectall_arrayref($st,{Slice => {}}); - #$st->execute() or die "Cannot execute: ".$st->errstr(); - }; - if ($@) - { - print "$@\n" if($verbose); - warn "$@\n"; - $xml_string .= " \n"; - $query_error_flag = 1; - } - - # if no db error continue adding info to xml file for the table. - if($query_error_flag == 0) - { - $numrows = $st->rows; - print "Number of records obtained: $numrows\n" if($verbose); - warn "Number of records obtained: $numrows\n"; - if ($numrows == 0) - { - $xml_string .= "
\n"; - } - else - { - $xml_string .= "
\n"; - } - - foreach my $sref (@$row) - { - %infohash=%{$sref}; - #print record number to xml file - $xml_string .= " \n \n"; - - #print primary key to xml file - my $pk_count = 0; - foreach my $pk (@pk_output) - { - if($pk =~ /$table_name\.(.*)/) - { - $pk_name=$1; - #$infohash{$pk_name}=~ s/\r|\n//g; - $xml_string .= " <$pk>$infohash{$pk_name}\n"; - $pk_count++; - } - } - $xml_string .= " \n \n"; - @select_array = split(/,/, $field_string); - #start printing fields to xml file - my $field_count = 0; - foreach my $select (@select_array) - { - if($select =~ /.*$table_name\.(.*)/) - { - $field_name = $1; - if($infohash{$field_name} !~/^\s*$/) - { - #$infohash{$field_name} =~ s/\r|\n//g; - $xml_string .= " <$select>$infohash{$field_name}\n"; - } - else - { - $xml_string .= " <$select/>\n"; - } - $field_count++; - } - } - $xml_string .=" \n"; - $xml_string .=" \n"; - $record_count++; - } - - } - if($numrows != 0 && $query_error_flag == 0) - { - $xml_string .="
\n"; - } - @select_array = (); - $field_string = ""; - - print "\n---------------\n" if($verbose); - warn "\n---------------\n"; - -} -$xml_string .="
\n"; - -if ($type eq "WFO" && $wfoID eq 0) -{ - my $hsa_admin_query = "SELECT admin.hsa FROM admin;"; - my $st_admin; - eval - { - $st_admin = $db->prepare($hsa_admin_query); - $st_admin->execute() or die "Cannot execute: ".$st_admin->errstr(); - }; - if ($@) - { - print "$@\n" if($verbose); - warn "$@\n"; - } - while ( defined ( my $row = $st_admin->fetchrow_arrayref() ) ) - { - $wfoID = @$row[0]; - } - -} - -if($type eq "WFO") -{ - $file_name = "$wfoID\_from-$office\_nrldb.xml"; -} -elsif($type eq "RFC") -{ - $file_name = "$rfcID\_from-$office\_nrldb.xml"; -} - - -#determine output file -if($outFile eq 0) -{ - $outFile = $file_name; -} - -my $outDir; - -if( -e "/awips/hydroapps/public/bin/get_apps_defaults"){ - $outDir = `/awips/hydroapps/public/bin/get_apps_defaults.LX nrldb_data`; - - chomp($outDir); -} else { - print "Could not access /awips/hydroapps/public/bin/get_apps_defaults.LX. Exiting"; - exit -1; -} - -$outFile = $outDir . "/" . $outFile; -open(XMLFILE, ">$outFile") || die "Could not open $outFile for writing.\n$!\nExiting\n"; -printf XMLFILE "$xml_string"; -close(XMLFILE); - -my $end = $db->disconnect; -zip_xml($outFile); -} - -sub zip_xml -{ -my $filename = shift; -my $zip_string; - - $zip_string = "zip $filename.zip $filename"; - print "$zip_string\n" if($verbose); - warn "$zip_string\n"; - my $zip_exe = `$zip_string`; - print "$zip_exe\n" if($verbose); - warn "$zip_exe\n"; - print "Failed: \"$zip_string\"\n" if ($? && $verbose); - warn "Failed: \"$zip_string\"\n" if $?; -} - - -sub read_control_file -{ -my @fields_all; -my @tables; -my @fields; -my $table_name; -my $control_file; - -if($localControlFile eq 0) -{ - if($type eq "WFO") - { - $control_file = "${conf_dir}/nrldb_control_wfo"; - } - elsif($type eq "RFC") - { - $control_file = "${conf_dir}/nrldb_control_rfc"; - } -} -else -{ - $control_file = $localControlFile; -} -open(FILE, "$control_file") || die "Could not open control file: $control_file\n$!\nExiting\n"; -my @infile = ; -close(FILE); - -foreach my $line (@infile) -{ -chomp($line); - if($line =~ /^#.*$/) - { - next; - } - elsif($line =~ /\[(.*)\]/) - { - $table_name = $1; - push (@tables, $table_name); - } - elsif($line =~ /^(fields)/) - { - $line =~ /fields = (.*)/; - @fields = split(/,/, $1); - - foreach my $tmp_field (@fields) - { - $tmp_field =~ s/\s*//; - push(@fields_all, "$table_name.$tmp_field"); - } - } -} - - -return (\@tables, \@fields_all); -} - -sub extract_detail() -{ - -my $wfo = $office; -my $wfo_fh_pointer = 0; -my $info_found = 0; -my ($ex_type, $ex_list); -my @extract_lid; -my $uclid; -my $compare_symbol; -my $extract_query = ''; - -open(FILE, "nrldb_extract") || die "Could not open detail extract file nrldb_extract:\n$!\nExiting\n"; -my @infile = ; -close(FILE); - - foreach my $line (@infile) - { - chomp($line); - if($line =~ m/type:\s*(\w*)/) - {$ex_type= $1;} - if($line =~ m/list:\s*(.*)/) - { - $ex_list= $1; - if(defined($ex_type) && defined($ex_list)) - {$info_found = 1;} - } - - if($info_found eq 1) - {last;} - } - if($info_found eq 1) - { - print "EXTRACT: $ex_type, [$ex_list]\n" if($verbose); - warn "EXTRACT: $ex_type, [$ex_list]\n"; - @extract_lid = split(/,/,$ex_list); - - if(lc($ex_type) eq 'only') - {$compare_symbol = '=';} - elsif(lc($ex_type) eq 'except') - {$compare_symbol = '!=';} - else - { - print "Undefined extraction type '$ex_type', should be only|except\n" if($verbose); - warn "Undefined extraction type '$ex_type', should be only|except\n"; - return($extract_query); - } - # The following has been modified by Mark Armstrong HSD - # Originally, the query for multiple lids using the "only" extract - # was incorrect. It used the AND condition for each lid which - # would never be true. I added another if condition and a new - # for loop to handle this case. - if(lc($ex_type) eq 'only'){ - my $count = 0; - $extract_query=" AND ("; - foreach my $lid (@extract_lid) - { - if($lid eq '') - {next;} - - $uclid=uc($lid); - $uclid =~ s/\s*//g; - if ( $count eq 0) - { - $extract_query .= " lid $compare_symbol '$uclid'"; - } - else - { - $extract_query .= " OR lid $compare_symbol '$uclid'"; - } - $count = $count + 1; - } - $extract_query .= ") "; - } - else{ - foreach my $lid (@extract_lid) - { - if($lid eq '') - {next;} - - $uclid=uc($lid); - $uclid =~ s/\s*//g; - $extract_query .= " AND lid $compare_symbol '$uclid'"; - - } - } - } - return($extract_query); -} - -sub read_config_file() -{ - -my $dbname; -my $host; -my $pass; -my $user; -my $nrldb_host; -my $site_conf; -my $backup_host; -my $conf_file; - -if( -e "/awips/hydroapps/public/bin/get_apps_defaults") -{ - $conf_dir = `/awips/hydroapps/public/bin/get_apps_defaults.LX nrldb_config`; - chomp($conf_dir); - $conf_file = "${conf_dir}/nrldb.conf"; -} -else -{ - print "nrldb_conf token not specified. Exiting"; - exit -1; -} -open(FILE, "${conf_file}") || die "Could not open configuration ${conf_file}:\n$!\nExiting\n"; -my @infile = ; -close(FILE); - - foreach my $line (@infile) - { - chomp($line); - if($line =~ /(^\s*dbname\s*=\s*"(.*)")/) - { - $dbname = "$2"; - } - elsif($line =~ /(^\s*dbhost\s*=\s*"(.*)")/) - { - $host = "$2"; - } - elsif($line =~ /(^\s*dbpass\s*=\s*"(.*)")/) - { - $pass = "$2"; - } - elsif($line =~ /(^\s*dbuser\s*=\s*"(.*)")/) - { - $user = "$2"; - } - elsif($line =~ /(^\s*nrldb_host\s*=\s*"(.*)")/) - { - $nrldb_host = "$2"; - } - elsif($line =~ /(^\s*site\s*=\s*"(.*)")/) - { - $site_conf = "$2"; - } - elsif($line =~ /(^\s*backup_host\s*=\s*"(.*)")/) - { - $backup_host = "$2"; - } - - } - return($dbname, $host, $user, $pass, $nrldb_host, $site_conf, $backup_host); -} - - -sub xml_parse -{ -my $xmlfile = $inFile; # the file to parse -my $lineCount = 0; -my @rawLine; -my $last_f; -my $record_num; -my $table; -my ($i, $j, $k); -my ($PK_name, $PK_value, $Field_name, $Field_value); -sub insertValues($table, $record_num, $PK_name, $PK_value, $Field_name, $Field_value); - -print "Parsing and Inserting Values from $xmlfile into database\n\n" if($verbose); -warn "Parsing and Inserting Values from $xmlfile into database\n\n"; - -open(XML_FH, "$xmlfile") or die("Cant open file $xmlfile for reading: $!\nExiting\n"); -while () -{ - # $_ is the line that has set. - $rawLine[$lineCount] = "$_"; - $lineCount++; -} - - - -close(XML_FH); - -$i=0; - - while (!$last_f) - { - if ($rawLine[$i] =~ m//) - { - print "Current Table: $1\n" if($verbose); - warn "Current Table: $1\n"; - $table = $1; - while($rawLine[$i] !~ m/<\/Table>/) - { - if($rawLine[$i] =~ //) - { - $record_num = $1; - while ($rawLine[$i] !~ m/<\/Record>/) - { - if($rawLine[$i] =~ //) - { $i++; - $j = 0; - while($rawLine[$i] !~ m/<\/PK>/) - { - if($rawLine[$i] =~ m/<$table\.(.*?)>(.*)<\/$table\..*>/) - { - $$PK_name[$j] = $1; - $$PK_value[$j] = $2; - $j++; - } - elsif($rawLine[$i] =~ m/<$table\.(.*)\/>/) - { - $$PK_name[$j] = $1; - $$PK_value[$j] = "NULL"; - $j++; - } - elsif($rawLine[$i] =~ m/<$table\.(.*?)>.*/) - { - - {$$PK_name[$k] = $1;} - $$PK_value[$j] = ''; - do - { - $$PK_value[$j] .= $rawLine[$i]; - $i++; - } until ($rawLine[$i] =~ m/<\/$table\..*>$/); - $$PK_value[$j] .= $rawLine[$i]; - $$PK_value[$j] =~ s/^\s*<$table\.(.*)>//g; - $$PK_value[$j] =~ s/<\/$table\..*>$//g; #/ - $j++; - } - $i++; - } - } - if($rawLine[$i] =~ //) - { $i++; - $k = 0; - while($rawLine[$i] !~ m/<\/Fields>/) - { - if($rawLine[$i] =~ m/<$table\.(.*?)>(.*)<\/$table\..*>/) - { - $$Field_name[$k] = $1; - $$Field_value[$k] = $2; - $k++; - } - elsif($rawLine[$i] =~ m/<$table\.(.*)\/>/) - { - $$Field_name[$k] = $1; - $$Field_value[$k] = "NULL"; - $k++; - } - elsif($rawLine[$i] =~ m/<$table\.(.*?)>.*/) - { - - {$$Field_name[$k] = $1;} - $$Field_value[$k] = ''; - do - { - $$Field_value[$k] .= $rawLine[$i]; - $i++; - } until ($rawLine[$i] =~ m/<\/$table\..*>$/); - $$Field_value[$k] .= $rawLine[$i]; - $$Field_value[$k] =~ s/^\s*<$table\.(.*)>//g; - $$Field_value[$k] =~ s/<\/$table\..*>$//g; #/ - $k++; - } - $i++; - } - } - $i++; - } - &insertValues($table, $record_num, $PK_name, $PK_value, $Field_name, $Field_value); - $#$PK_name = -1; $#$PK_value = -1; $#$Field_name = -1; $#$Field_value = -1; - $total_count++; - } - $i++; - } - print "\tTotal Inserts: $insert_count\n" if($verbose); - warn "\tTotal Inserts: $insert_count\n"; - print "\tTotal Updates: $update_count\n" if($verbose); - warn "\tTotal Updates: $update_count\n"; - print "\tTotal Errors: $error_count\n" if($verbose); - warn "\tTotal Errors: $error_count\n"; - print "\tTOTAL: $total_count\n\n" if($verbose); - warn "\tTOTAL: $total_count\n\n"; - $insert_count = 0; - $update_count = 0; - $error_count = 0; - $total_count = 0; - } - elsif ($rawLine[$i] =~ /<\/NRLDB>/) - {$last_f = 1;} - else - {$i++;} - } - -} - -sub get_delete_list -{ - my @list; - my $table; - - open(FILE, "${conf_dir}/nrldb_control_delete") || die "Could not open detail extract file ${conf_dir}/nrldb_control_delete:\n$!\nExiting\n"; - my @infile = ; - close(FILE); - - foreach my $line (@infile) - { - chomp($line); - if($line =~ m/^\s*#/) - {next;} - - if($line =~ m/^\s*\w+\s*$/) - { - $line =~ s/\s*//g; - $table=lc($line); - push(@list, $table); - } - } - - return(\@list); -} - -sub deleteValues -{ - my $deleteTable = shift; - my $deleteWFO = $office; - my $lid_flag = lid_check($deleteTable); - my ($delete_query, $st); - - my ($delete_detail, $total); - - if($lid_flag == 1) - { - ($delete_detail, $total)=getDeleteLid($deleteTable); - if($total !=0) - { - $delete_query = "DELETE FROM $deleteTable $delete_detail\;"; - print "DELETE: $delete_query\n"; - } - } - else - { - $delete_query = "DELETE FROM $deleteTable\;"; - } - - eval - { - $st = $db->prepare($delete_query); - $st->execute() or die "Cannot execute: ".$st->errstr(); - }; - if($@) - {print "$@\n" if($verbose); warn "$@\n";} - -} - - -sub getDeleteLid -{ - -my $xmlfile = $inFile; # the file to parse -my $lineCount = 0; -my @rawLine; -my $last_f; -my $record_num; -my $table; -my ($i, $j, $k); -my $lid_name; - -my $deleteTable = shift; -my $total_count = 0; - -open(XML_FH, "$xmlfile") or die("Cant open file $xmlfile for reading: $!\nExiting\n"); -while () -{ - # $_ is the line that has set. - $rawLine[$lineCount] = "$_"; - $lineCount++; -} - -close(XML_FH); - -$i=0; -my $delete_str = ""; -my $last_lid = -1; - while (!$last_f) - { - if ($rawLine[$i] =~ m/
/) - { - print "Delete Table: $1\n" if($verbose); - warn "Delete Table: $1\n"; - $table = $1; - while($rawLine[$i] !~ m/<\/Table>/) - { - if($rawLine[$i] =~ //) - { - $record_num = $1; - while ($rawLine[$i] !~ m/<\/Record>/) - { - if($rawLine[$i] =~ //) - { $i++; - while($rawLine[$i] !~ m/<\/PK>/) - { - if($rawLine[$i] =~ m/<$table\.lid>(.*)<\/$table\.lid>/) - { - if(($last_lid != -1) && ($last_lid eq $1)) - {$i++; next;} - #print "$1\n"; - if ($total_count == 0) - { - $delete_str .= "WHERE $table.lid = '$1'"; - } - else - { - $delete_str .= " OR $table.lid = '$1'"; - } - - $last_lid = $1; - - } - $i++; - } - } - $i++; - } - $total_count++; - } - $i++; - } - print "\tTotal Delete LIDs: $total_count\n" if($verbose); - warn "\tTotal Delete LIDs: $total_count\n"; - $last_f = 1; - } - elsif ($rawLine[$i] =~ /<\/NRLDB>/) - {$last_f = 1;} - else - {$i++;} - } - #print "$delete_str, $total_count\n"; - return ($delete_str, $total_count); - -} - - -sub insertValues($table, $record_num, $PK_name, $PK_value, $Field_name, $Field_value) -{ - my $num; - my ($fields, $values); - my ($update_set, $update_where); - my $Field_value_quoted; - my $table = shift; - my $record_num = shift; - my $PK_name = shift; - my $PK_value = shift; - my $Field_name = shift; - my $Field_value = shift; - my $update_flag = 0; - my $st_handle; - my $insertrows; - - for($num = 0; $num <= $#$Field_value; $num++) - { - if($num == 0) - { - $fields = "($$Field_name[$num]"; - if($$Field_value[$num] ne "NULL") - { - $$Field_value[$num] = $db->quote($$Field_value[$num]); - $values = "($$Field_value[$num]"; - $update_set = "$$Field_name[$num]=$$Field_value[$num]"; - } - else - { - $values = "($$Field_value[$num]"; - $update_set = "$$Field_name[$num]=$$Field_value[$num]"; - } - } - else - { - $fields .= ", $$Field_name[$num]"; - if($$Field_value[$num] ne "NULL") - { - $$Field_value[$num] =~ s/\n//g; - $$Field_value[$num] =~ s/\r//g; - $$Field_value[$num] = $db->quote($$Field_value[$num]); - $values .= ", $$Field_value[$num]"; - $update_set .= ", $$Field_name[$num]=$$Field_value[$num]"; - } - else - { - $values .= ", $$Field_value[$num]"; - $update_set .= ", $$Field_name[$num]=$$Field_value[$num]"; - } - } - } - for($num = 0; $num <= $#$PK_name; $num++) - { - if($num == 0) - { - $$PK_value[$num] = $db->quote($$PK_value[$num]); - $update_where = "$$PK_name[$num]=$$PK_value[$num] "; - } - else - { - $$PK_value[$num] = $db->quote($$PK_value[$num]); - $update_where .= "AND $$PK_name[$num]=$$PK_value[$num]"; - } - } - - $fields .= ")"; - $values .= ")"; - my $insert_cmd = "INSERT INTO $table $fields VALUES $values\;"; - my $update_cmd = "UPDATE $table SET $update_set WHERE $update_where\;"; - - eval { - $insert_count++; - $st_handle = $db->prepare($insert_cmd); - $st_handle->execute() or die "Cannot execute: ".$st_handle->errstr(); - $insertrows = $st_handle->rows(); - if($insertrows == 0) - { - $insert_count--; - $error_count++; - print "ZERO ROWS FOR QUERY: $insert_cmd\n\n" if($verbose); - warn "ZERO ROWS FOR QUERY: $insert_cmd\n\n"; - } - }; - - if ($@) { - if($@ =~ /duplicate key/) - { - $update_flag = 1; - $insert_count--; - } - else - { - print "$@\n" if($verbose); - warn "$@\n"; - $insert_count--; - $error_count++; - print "INSERT ERROR ON QUERY: $insert_cmd\n\n" if($verbose); - warn "INSERT ERROR ON QUERY: $insert_cmd\n\n"; - - } - } - - if($update_flag == 1) - { - eval { - $update_count++; - $st_handle = $db->prepare($update_cmd); - $st_handle->execute() or die "Cannot execute: ".$st_handle->errstr(); - $insertrows = $st_handle->rows(); - if($insertrows == 0) - { - $update_count--; - $error_count++; - print "ZERO ROWS FOR QUERY: $update_cmd\n\n" if($verbose); - warn "ZERO ROWS FOR QUERY: $update_cmd\n\n"; - } - }; - - if ($@) { - print "$@\n" if($verbose); - warn "$@\n"; - $update_count--; - $error_count++; - print "UPDATE ERROR ON QUERY: $update_cmd\n\n" if($verbose); - warn "UPDATE ERROR ON QUERY: $update_cmd\n\n"; - } - } - -} - - -sub db_connect -{ -my $dbname = shift; -my $host = shift; -my $user = shift; -my $pass = shift; - -my %db_attr = ( - PrintError => 0, - RaiseError => 0, -); - -my $dsn = "DBI:Pg:dbname=$dbname;host=$host"; -my $db = DBI->connect($dsn, $user, $pass, \%db_attr) or die "Can't connect() to database $dbname: $DBI::errstr"; -return ($db); -} - -sub upload_xml -{ - print "---UPLOAD XML FILE----\n" if($verbose); - warn "---UPLOAD XML FILE----\n"; - my $upload_string = "rsync -av --chmod=ugo+rw $outFile.zip $nrldb_host\::nrldb_xml/"; - print "$upload_string\n" if($verbose); - warn "$upload_string\n"; - my $upload_exe = `$upload_string`; - print "$upload_exe\n" if($verbose); - warn "$upload_exe\n"; - print "Failed: \"$upload_string\"\n" if ($? && $verbose); - warn "Failed: \"$upload_string\"\n" if $?; - return; -} -sub download_control_file -{ - my $office_type = shift; - my $download_string; - print "---DOWNLOAD $office_type CONTROL FILE----\n" if($verbose); - warn "---DOWNLOAD $office_type CONTROL FILE----\n"; - - if ($office_type eq "WFO") - { - $download_string = "rsync -av $nrldb_host\::nrldb_control/nrldb_control_wfo ${conf_dir}/"; - } - elsif ($office_type eq "RFC") - { - $download_string = "rsync -av $nrldb_host\::nrldb_control/nrldb_control_rfc ${conf_dir}/"; - } - print "$download_string\n" if($verbose); - warn "$download_string\n"; - my $download_exe = `$download_string`; - print "$download_exe\n" if($verbose); - warn "$download_exe\n"; - print "Failed: \"$download_string\"\n" if ($? && $verbose); - warn "Failed: \"$download_string\"\n" if $?; - return; -} - -sub getdate() -{ -my ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time) ; -my $RealMonth = $Month + 1 ; # Months of the year are not zero-based -my $FixedYear; - -if ($Hour < 10) -{ - $Hour = "0" . $Hour -} - -if ($Minute < 10) -{ - $Minute = "0" . $Minute -} - -if ($Second < 10) -{ - $Second = "0" . $Second -} - -if ($RealMonth < 10) -{ - $RealMonth = "0" . $RealMonth; -} - -if ($Day < 10) -{ - $Day = "0" . $Day; -} - -if ($Year >= 100) -{ - $FixedYear = $Year - 100; -} -else -{ - $FixedYear = $Year; -} - -if ($FixedYear < 10) -{ - $FixedYear = "0" . $FixedYear; -} - -my $clean_date = "$Hour:$Minute:$Second $RealMonth/$Day/$FixedYear"; - -return($clean_date); -} - -sub lid_check { - my $table_name = shift; - my $at; - my $lid_flag = 0; - - my $query_column1 = "SELECT c.oid - FROM pg_catalog.pg_class c - LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE pg_catalog.pg_table_is_visible(c.oid) - AND c.relname ~ '^$table_name\$'"; - - my $attribute_query = "SELECT a.attname - FROM pg_catalog.pg_attribute a - WHERE a.attnum > 0 AND NOT a.attisdropped - AND a.attrelid = ($query_column1) - ORDER BY a.attnum;"; - - eval { - $at = $db->prepare($attribute_query); - $at->execute() or die "Cannot execute: ".$at->errstr(); - }; - if($@) { - print "$@\n"; - } - - while ( defined ( my $attribues = $at->fetchrow_arrayref() ) ) { - if(@$attribues[0] =~ /^lid$/) { - $lid_flag = 1; - } - } - -return ($lid_flag); -} - -BEGIN { - use CGI::Carp qw(carpout); - my $logDir; - if( -e "/awips/hydroapps/public/bin/get_apps_defaults"){ - $logDir = `/awips/hydroapps/public/bin/get_apps_defaults.LX nrldb_log`; - chomp($logDir); - } else { - print "Could not access /awips/hydroapps/public/bin/get_apps_defaults.LX. Exiting\n"; - exit -1; - } - print "log dirlogDir\n"; - my $log = "${logDir}/nrldb.log"; - open(LOG, ">>$log") or die "Unable to open $log. $! "; - carpout(*LOG); -} - -END { - my $date = `date`; - print LOG "End $0 at $date\tElapsed time: " . (time - $^T) . " seconds\n\n"; - close LOG; -} - -sub getcutoffdate() -{ -my ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = gmtime(time-172800) ; -my $RealMonth = $Month + 1 ; # Months of the year are not zero-based -my $FixedYear; - -if ($Hour < 10) -{ - $Hour = "0" . $Hour -} - -if ($Minute < 10) -{ - $Minute = "0" . $Minute -} - -if ($Second < 10) -{ - $Second = "0" . $Second -} - -if ($RealMonth < 10) -{ - $RealMonth = "0" . $RealMonth; -} - -if ($Day < 10) -{ - $Day = "0" . $Day; -} - - $FixedYear = $Year + 1900; - -my $clean_date = "$FixedYear-$RealMonth-$Day $Hour:$Minute"; - -return($clean_date); -} diff --git a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/run_update_nrldb.ksh b/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/run_update_nrldb.ksh deleted file mode 100644 index b9e03f1e1b..0000000000 --- a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/run_update_nrldb.ksh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/ksh - -RUN_FROM_DIR=`dirname $0` -# set up SOME environment variables for WHFS applications -export PGSQL_DRIVER_DIR=/awips2/cave/plugins/org.postgres_9.2.0 -. $RUN_FROM_DIR/../../set_hydro_env -. $RUN_FROM_DIR/../../check_app_context -export APPS_DEFAULTS=~/caveData/common/base/hydro/Apps_defaults -export APPS_DEFAULTS_SITE=~/caveData/common/site/${AW_SITE_IDENTIFIER}/hydro/Apps_defaults -export PGUSER="awips" -export BIN_DIR=`get_apps_defaults whfs_bin_dir"` -export NRLDB_LOG=`get_apps_defaults nrldb_log` -export NRLDB_CONFIG=`get_apps_defaults nrldb_config` -export NRLDB_DATA=`get_apps_defaults nrldb_data` -export NRLDB_TMP=`get_apps_defaults nrldb_tmp` -export db_name=`get_apps_defaults db_name` -export PGHOST=`get_apps_defaults pghost` - -$RUN_FROM_DIR/update_nrldb.pl - -exit 0 diff --git a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/send_nrldb_update.sh b/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/send_nrldb_update.sh deleted file mode 100644 index 946a1464ea..0000000000 --- a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/send_nrldb_update.sh +++ /dev/null @@ -1,167 +0,0 @@ -#!/bin/sh -############################################################################### -# This script is run at the field office to send ad-hoc updates to the NRLDB -# server, then on to the AHPS CMS. It can be run at any time. It is designed -# to send small, time-sensitive updates to the CMS. It takes two argument -# lists:-table table names (comma-separated) and -lid lid names -# (comma-separated). It parses the arguments, selects the updated data from -# the database and builds an SQL formatted text file for use on the nrldb and -# CMS databases. The SQL file contains a delete staement that deletes the -# pre-existing data for the lid/table combinations, before running the inserts -# -# Usage: send_nrldb_update.sh -table ,,... -lid ,,... -# Example: send_nrldb_update.sh -table rating,floodstmt -lid BRKM2,CBEM2 -# -if [ $# -ne 4 ] -then - echo "Incorrect number of arguments entered: $#" - echo "Correct Arguments are:" - echo "send_nrldb_update.sh -table table1,table2 -lid lid1,lid2" - echo "Any number of tables and lids may be specified, but they need to be in a comma separated list with no spaces between commas and table/lid names" - exit 0 -fi -# set up SOME environment variables for NRLDB applications - -# get the nrldb host and wfo from the nrldb.conf file/database -nrldb_host=`grep nrldb_host $NRLDB_CONFIG/nrldb.conf | cut -d= -f2 | sed 's/"//g' | sed 's/ //g'` -echo "DB NAME: $db_name" -wfo=`psql -h $PGHOST -d $db_name -c "select hsa from admin;" | tail -3 | head -1 | sed -e 's/ //g'` -echo `date` -echo "WFO $wfo" - -# create the final SQL file that will be sent to the NRLDB host -timestamp=`date +%Y%m%d%H%N` -sql_file="${wfo}_update_${timestamp}.sql" -if [ -f $sql_file ] -then - rm $sql_file -fi - -# build the list of tables/lids to send -lid_list="XXXXX" -table_list="XXXXX" -while [ $# -gt 0 ] -do - case "$1" in - -lid) lid_list="$2,";shift;; - -table) table_list="$2,";shift;; - *) break;; - esac - shift -done - -# set the last update information for update_nrldb.pl to use -echo `date` > ${NRLDB_LOG}/last_nrldb_update.txt -up_lid_list=`echo $lid_list | sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` -echo "lid list: $up_lid_list" >> ${NRLDB_LOG}/last_nrldb_update.txt -echo "table_list: $table_list" >> ${NRLDB_LOG}/last_nrldb_update.txt - -#loop through the tables/lids -if [ $table_list != "XXXXX" ] -then - pos=1 - table="XXXXX" - ltable=`echo $table | wc -m` - while [ $ltable -gt 4 ] - do - table=`echo $table_list | cut -d"," -f$pos` - pos=`expr $pos + 1` - ltable=`echo $table | wc -m` - if [ $ltable -gt 4 ] - then - lid="XXXXX" - lpos=1 - llid=`echo $lid | wc -m` - while [ $llid -gt 3 ] - do - lid=`echo $up_lid_list | cut -d"," -f$lpos` - lpos=`expr $lpos + 1` - llid=`echo $lid | wc -m` - if [ $llid -gt 3 ] - then - # fetch the values from the DB and edit them - export PGUSER=awips - touch $NRLDB_TMP/update.txt - chmod ugo+rw $NRLDB_TMP/update.txt - ls -l $NRLDB_TMP/update.txt - psql -h $PGHOST -d $db_name -c "copy (select * from $table where lid = '$lid') to '$NRLDB_TMP/update.txt' with delimiter '|';" - cp $NRLDB_TMP/update.txt ${NRLDB_DATA}/update.txt - sed -f ${NRLDB_CONFIG}/sed_script.txt ${NRLDB_TMP}/update.txt > ${NRLDB_DATA}/update11.txt - sed -e "s/|/'|'/g" ${NRLDB_DATA}/update11.txt > ${NRLDB_DATA}/update1.txt - sed -e "s/^/insert into $table values('/g" ${NRLDB_DATA}/update1.txt > ${NRLDB_DATA}/update2.txt - sed -e "s/$/');/g" ${NRLDB_DATA}/update2.txt > ${NRLDB_DATA}/update3.txt - sed -e "s/|/,/g" ${NRLDB_DATA}/update3.txt > ${NRLDB_DATA}/update4.txt - if [ -f "${NRLDB_DATA}/update.txt" ] - then - update_lines=`wc -l "${NRLDB_DATA}/update.txt" | cut -d" " -f1` - else - echo "No update file found". - update_lines=0 - fi - if [ $update_lines -gt 0 ] - then - if [ $table != "location" -a $table != "riverstat" ] - then - echo "delete from $table where lid = '$lid';" >> ${NRLDB_DATA}/$sql_file - fi - cat ${NRLDB_DATA}/update4.txt >> ${NRLDB_DATA}/$sql_file - fi - # location and riverstat require a special forecast since they have dependent tables via foreign keys - if [ $table = "location" ] - then - sql_stmt="update location set lid = '$lid'" - for col in county coe cpm detail elev hdatum hsa hu lat lon lremark lrevise name network rb rfc sbd sn state waro wfo wsfo type des det post stntype tzone - do - psql -h $PGHOST -d $db_name -c "select $col from location where lid = '$lid' and $col is not null;" > ${NRLDB_DATA}/update.txt - ct_zero=`grep -c "0 row" ${NRLDB_DATA}/update.txt` - if [ $ct_zero -eq 0 ] - then - export val=`cat ${NRLDB_DATA}/update.txt | head -3 | tail -1 | cut -c2-80` - new_val=`echo "$val" | sed -f ${NRLDB_CONFIG}/sed_script.txt` - sql_stmt="$sql_stmt, $col = '$new_val'" - fi - done - sql_stmt="$sql_stmt where lid = '$lid';" - echo $sql_stmt >> ${NRLDB_DATA}/$sql_file - - elif [ $table = "riverstat" ] - then - sql_stmt="update riverstat set lid = '$lid'" - for col in primary_pe bf cb da response_time threshold_runoff fq fs gsno level mile pool por rated lat lon remark rrevise rsource stream tide backwater vdatum action_flow wstg zd ratedat usgs_ratenum uhgdur use_latest_fcst - do - psql -h $PGHOST -d $db_name -c "select $col from riverstat where lid = '$lid' and $col is not null;" > ${NRLDB_DATA}/update.txt - ct_zero=`grep -c "0 row" ${NRLDB_DATA}/update.txt` - if [ $ct_zero -eq 0 ] - then - export val=`cat ${NRLDB_DATA}/update.txt | head -3 | tail -1 | cut -c2-80` - new_val=`echo "$val" | sed -f ${NRLDB_CONFIG}/sed_script.txt` - sql_stmt="$sql_stmt, $col = '$new_val'" - fi - done - sql_stmt="$sql_stmt where lid = '$lid';" - echo $sql_stmt >> ${NRLDB_DATA}/$sql_file - fi - fi - done - fi - - done - - # send the SQL file to the NRLDB server - if [ -f ${NRLDB_DATA}/$sql_file ] - then - rsync -av ${NRLDB_DATA}/$sql_file ${nrldb_host}\::nrldb_update/ - echo "SQL file: $sql_file created for lids: $up_lid_list and tables: $table_list" - else - echo "No SQL file created. Database contained no entries for lids: $up_lid_list and tables: $table_list" - fi -fi - -# remove the temp files to keep the directory clean -for temp_file in ${NRLDB_DATA}/update.txt ${NRLDB_DATA}/update11.txt ${NRLDB_DATA}/update1.txt ${NRLDB_DATA}/update2.txt ${NRLDB_DATA}/update3.txt ${NRLDB_DATA}/update4.txt -do - if [ -f $temp_file ] - then - rm $temp_file - fi -done diff --git a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/update_nrldb.pl b/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/update_nrldb.pl deleted file mode 100644 index 97669495f3..0000000000 --- a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/update_nrldb.pl +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/perl -################################################################################ -# update_nrldb.pl is the GUI for the Ad-Hoc update process. ## This process was put in place so that WFOs could update information # -# between daily runs of the NRLDB update process. The information is # -# collected at the WFO, sent to the NRLDB central server and then forwarded to # -# CMS servers outside of the AWIPS firewall. # -# # -# Developer: Mark Armstrong (OCWWS/HSD) # -# Developed 2011 - Modified for AWIPS2 2013 # -################################################################################ - -use Tk; -use strict; -use warnings; -use AppConfig qw(:expand :argcount); -use DBI; - -our $BIN_DIR = `echo \$BIN_DIR`; -chomp($BIN_DIR); -our $NRLDB_LOG = `echo \$NRLDB_LOG`; -chomp($NRLDB_LOG); - -my $lids; -my $tables; - -# Set up some inial configuration. Most of this comes from the hydroGen input file: hg.cfg -$ENV{HYDROGENHOME} = "/awips/hydroapps/HydroGen" if ! defined $ENV{HYDROGENHOME}; -my %cfg = ( DEBUG => 0, # debug mode on or off - PEDANTIC => 0, # be patient with warnings/errors - CREATE => 1, # create variables, defining not required... - GLOBAL => { # for all config options unless overridden... - EXPAND => EXPAND_ALL, # expand ~, $ENV{*}, and $(var) - ARGCOUNT => ARGCOUNT_ONE, # each config expects an arg unless overriden... - ARGS => '=s' # each arg is a string unless overriden - } - ); - -my $config = AppConfig->new(\%cfg); # create config object - -$config->define('version',{ ALIAS => 'V',ARGCOUNT => ARGCOUNT_NONE, ARGS => '!',DEFAULT => 0}); -$config->define('help',{ ALIAS => 'h',ARGCOUNT => ARGCOUNT_NONE, ARGS => '!',DEFAULT => 0}); -$config->define('man',{ ALIAS => 'm',ARGCOUNT => ARGCOUNT_NONE, ARGS => '!',DEFAULT => 0}); -$config->define('DBengine',{ VALIDATE => '[\w]+',DEFAULT => "Pg"}); -$config->define('DBname',{ VALIDATE => '[\w]+',DEFAULT => "hd_ob8xxx"}); -$config->define('DBhost',{ VALIDATE => '[-\w]+',DEFAULT => "dx1f"}); -$config->define('DBport',{ ARGS => '=i',DEFAULT => 5432}); -$config->define('master',{ VALIDATE => '[.\w]+',DEFAULT => "HGstation"}); -$config->define('basedir',{ VALIDATE => '[- /.\w]+',DEFAULT => $ENV{HYDROGENHOME} . "/bin"}); - -$config->file($ENV{HYDROGENHOME} . "/input/hg.cfg"); # look in user's $HYDROGENHOME to find configured settings -$config->args(\@ARGV); # get config settings from the command-line, overwriting any settings from the file... - -my $master = $config->get('master'); # name of DB table or view which holds master list of IDs for which MXD files are to be generated... -my $DBengine = $config->get('DBengine'); -my $DBname = $config->get('DBname'); -my $DBhost = $config->get('DBhost'); -my $DBport = $config->get('DBport'); -my $baseDir = `pwd`; -chomp $baseDir; -my $DBstr; -my $wildcard; - -#Open a database connection and get the list of LIDs from the IHFS DB -if($DBengine eq "Pg") { - $DBstr = "dbi:$DBengine:dbname=$DBname;host=$DBhost;port=$DBport"; - $wildcard = '%'; -} else { - $DBstr = "dbi:$DBengine:$DBname"; - $wildcard = '*'; -} - -my $dbh = DBI->connect("$DBstr",undef,undef,{ChopBlanks => 1}) or warn $DBI::errstr; -# creates the list of WFOs based on the HydroGen .xxx_backup files -# and builds the query to create the list of LIDs -my $wfo=`ls -a /awips/hydroapps/HydroGen/ | grep _backup | cut -c2-4`; -my $list_len=length $wfo; -my $num_wfos=$list_len/4; -my $index=1; -my $off=0; -my $wfoid=substr($wfo,$off,3); -my $wfoID=uc $wfoid; -my $wfo_query = "(location.hsa = \'$wfoID\'"; -while ($index < $num_wfos){ - $off+=4; - $wfoid=substr($wfo,$off,3); - $wfoID=uc $wfoid; - $wfo_query .= " or location.hsa = \'$wfoID\'"; - $index++; -} -$wfo_query .= ")"; - -#my $list_type="river"; -our $mw = MainWindow->new; -$mw->title('Ad-Hoc NRLDB Update'); - -my $lst_lab= $mw->Label(-text => 'Add any Unlisted Locations (comma-separated): '); -my $sql = "select distinct hgstation.lid,location.name,location.hsa from hgstation,location where hgstation.lid = location.lid and $wfo_query order by 3,1;"; - -# get the list of LIDs -my $qhw = $dbh->prepare("$sql") or warn $DBI::errstr; - -our @lid_list; # = ($wildcard); - -#get the data from the DB -get_results($qhw,\@lid_list); - -#set up a static array with the tables that are allowed for ad-hoc updates -#table_list is the actual name of the DB tables, while tabledesc is a friendlier description that is displayed to the user -our @table_list = ('location','riverstat','crest','floodstmt','hgstation','floodcat','lowwater'); -my @tabledesc = ('Location','Riverstat','Crest History','Impacts','HGstation','Flood Categories','Low Water'); - -$dbh->disconnect(); - -#manipulate the results of the lid/hsa/name query for better display -my @liddeschsa; -our @lidsend; -$index=0; -my $num_lids=scalar(@lid_list); -while ($index < $num_lids){ - my $line = $lid_list[$index]; - my @results = split('\|',$line); - #my $lid = $lid_list[$index]; - my $lid_lid = $results[0]; - my $lid_name = $results[1]; - my $lid_hsa = $results[2]; - push(@liddeschsa,"$lid_hsa | $lid_lid | $lid_name"); - push(@lidsend,$lid_lid); - $index++; -} - -# Create the GUI object -# Labels for the LID and table scroll boxes -my $misc_ent = $mw->Entry(); -my $label1 = $mw->Label(-text => 'HSA|LID|Location Name'); -my $label2 = $mw->Label(-text => 'Tables'); - -# Create the scroll boxes for the LIDs and tables -my $lb1 = $mw->Scrolled('Listbox', - -scrollbars => 'osoe',-width=>50, - -selectmode => 'multiple', -exportselection=>0); -my $lb2 = $mw->Scrolled('Listbox', - -scrollbars => 'osow',-width=>20, - -selectmode => 'multiple',-exportselection=>0); - -# Add the arrays that we want to display in the list boxes -$lb1->insert('end', @liddeschsa); -$lb2->insert('end', @tabledesc); - -# Create the buttons -my $exit = $mw->Button(-text => 'Exit', - -command => [$mw => 'destroy']); -my $send = $mw->Button(-text => 'Send', - -command => \&send_button); -my $show_log = $mw->Button(-text => 'Show Log', - -command => \&show_log); -my $update_list = $mw->Button(-text => 'Update List', -command => \&upd_list); -# create the label and text box for the last pdate window -my $status_box = $mw->Text(-width=>20, -height=>3); -my $lb_status = $mw->Label(-width=>20, -height=>3,-text=>"Last Ad-Hoc Update:"); -my $last_update = `cat $NRLDB_LOG/last_nrldb_update.txt`; - -$status_box->insert('end',"$last_update"); - -# Crate the GUI using grid to specify the physical locations of the objects -$label1->grid(-row=>1, -column=>1, -columnspan=>3) ; -$label2->grid(-row=>1, -column=>4) ; -$lb1->grid(-row=>2, -column=>1, -columnspan=>3, -sticky=>"ew") ;#pack; -$lb2->grid(-row=>2, -column=>4, -columnspan=>1, -sticky=>"w") ;#pack; -$lst_lab->grid(-row=>3, -column=>1, -columnspan=>1); -$misc_ent->grid(-row=>3, -column=>2); -$lb_status->grid(-row=>4, -column=>1); -$status_box->grid(-row=>4, -column=>2, -columnspan=>3, -sticky=>"ew"); -$send->grid(-row=>5, -column=>1) ;#pack; -$show_log->grid(-row=>5,-column=>2); -$exit->grid(-row=>5, -column=>4) ;#pack; - -MainLoop; - -# End of main -# - -# The Send button functionality function -sub send_button { - # Get the indices of the selected array items - my @LIDindex = $lb1->curselection; - my @Tableindex = $lb2->curselection; - my $index=1; - my $misc_lid = $misc_ent-> get(); - # build the lists of LIDs and tables - $tables = $table_list[$Tableindex[0]]; - my $numLIDs=@LIDindex; - print "numLIDs: $numLIDs\n"; - my $numTables=@Tableindex; - if ($numLIDs > 0){ - $lids = $lidsend[$LIDindex[0]]; - while ($index < $numLIDs){ - $lids .= "," . $lidsend[$LIDindex[$index]]; - $index++; - } - $lids .= "," . $misc_lid; - } else { - $lids=$misc_lid; - } - $index=1; - while ($index < $numTables){ - $tables .= "," . $table_list[$Tableindex[$index]]; - $index++; - } - - # Create the call to the script and execute it using system() - my $cmd = "${BIN_DIR}/send_nrldb_update.sh -table $tables -lid $lids > ${NRLDB_LOG}/send_nrldb_update.log\n"; - system($cmd); - - # Create a dialog box to inform the user that their data has been sent - my $dsend=$mw->Dialog(-title=>'Sent NRLDB Update',-buttons=>['OK']); - my $text_field="NRLDB Update Sent for LIDs: $lids \n and tables: $tables\n"; - my $box=$dsend->add('Label',-text=>"$text_field")->pack(-side => 'left',-fill => 'both',-expand => 1); - my $button = $dsend->Show; -} -# This subroutine, copied from Mark Fenbers bless program, takes a db query and returns an array of results -sub get_results -{ - my $qh = shift; - my $array = shift; - my $record; - - if(defined $qh) { - if($qh->execute(@_)) { - while($record = $qh->fetchrow_arrayref) { - foreach (@$record) { $_ = "" if ! defined $_; } - push @$array,(join '|',@$record); - } - } else { - warn $DBI::errstr; - } - } else { warn "unable to prepare query \"$sql\"\n"; } -} - -#This subroutine displays the log from the send script in the form of a dialog box -sub show_log -{ - use Tk::Dialog; - my $text_field=`cat ${NRLDB_LOG}/send_nrldb_update.log`; - my $d = $mw->Dialog(-title=>'Show Log',-buttons => ['OK']); - my $box=$d->add('Label',-text=>"$text_field")->pack(-side => 'left',-fill => 'both',-expand => 1); - my $button = $d->Show; -} - diff --git a/nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/nrldb.conf b/nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/nrldb.conf deleted file mode 100644 index 4a3ce4eb68..0000000000 --- a/nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/nrldb.conf +++ /dev/null @@ -1,6 +0,0 @@ -dbhost = "dx1f" -dbuser = "awips" -dbpass = "" -nrldb_host = "165.92.28.1" -site = "CCC" -dbname = "hd_ob92ccc" diff --git a/nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/nrldb_control_wfo b/nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/nrldb_control_wfo deleted file mode 100644 index f76ac5221e..0000000000 --- a/nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/nrldb_control_wfo +++ /dev/null @@ -1,174 +0,0 @@ -#NRLDB national configuration file -# -# -[hsa] -fields = ALL - -[wfo] -fields = ALL - -[state] -fields = ALL - -[counties] -fields = ALL - -[network] -fields = ALL - -[rfc] -fields = ALL - -[timezone] -fields = ALL - -#[admin] -#fields = ALL - -[coopcomms] -fields = ALL - -[cooprecip] -fields = ALL - -[coopspons] -fields = ALL - -[dcpowner] -fields = ALL - -#[eligzon] -#fields = ALL - -[gagemaint] -fields = ALL - -[gageowner] -fields = ALL - -[gagetype] -fields = ALL - -[proximity] -fields = ALL - -[telmtype] -fields = ALL - -[telmowner] -fields = ALL - -[telmpayor] -fields = ALL - -[resowner] -fields = ALL - -[damtypes] -fields = ALL - -[location] -fields = ALL - -[riverstat] -fields = ALL - -[benchmark] -fields = lid, bnum, elev, remark - -[observer] -fields = ALL - -#[zonenum] -#fields = lid, state, zonenum - -[reservoir] -fields = ALL - -[crest] -fields = ALL - -[datum] -fields = ALL - -#[dcp] -#fields = ALL -[dcp] -fields = lid, criteria, owner, goes, rptfreq, rptime, notify, obsvfreq, randrept - -[descrip] -fields = ALL - -[flood] -fields = ALL - -[floodcat] -fields = ALL - -[floodstmt] -fields = ALL - -[gage] -fields = ALL - -[lowwater] -fields = ALL - -[pub] -fields = ALL - -[refer] -fields = ALL - -#[telem] -#fields = ALL -[telem] -fields = lid, type, payor, cost, criteria, owner, phone, sensorid, rptfreq, notify, obsvfreq - -[rating] -fields = ALL - -[ratingshift] -fields = ALL - -[contacts] -fields = ALL - -[countynum] -fields = ALL - -[unitgraph] -fields = ALL - -[hgstation] -fields = ALL - -#[floodts] -#fields = ALL - -[lwstmt] -fields = ALL - -[rpffcstgroup] -fields = ALL - -[rpffcstpoint] -fields = ALL - -[locdatalimits] -fields = lid,pe,dur,monthdaystart,monthdayend,gross_range_min,gross_range_max,reason_range_min,reason_range_max,roc_max - -[sshpconfig] -fields = ALL - -[shefpe] -fields = ALL - -[shefdur] -fields = ALL - -#[ingestfilter] -#fields = ALL - -[locarea] -fields = ALL diff --git a/nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/sed_script.txt b/nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/sed_script.txt deleted file mode 100644 index 99f27bad14..0000000000 --- a/nativeLib/files.native/awipsShare/hydroapps/whfs/local/data/app/nrldb/sed_script.txt +++ /dev/null @@ -1 +0,0 @@ -s/'/\\'/g diff --git a/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id b/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id index 2291591ae6..7b5e854ce1 100644 --- a/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id +++ b/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id @@ -1 +1 @@ -2d8d4c03270ef631f167570cf0c03461ff832fea \ No newline at end of file +759799451b20c427bdaa8cb8185b9602cc66c6c6 \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/rsc/EnsembleSelectComposite.java b/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/rsc/EnsembleSelectComposite.java index a446d01690..c7097f3682 100644 --- a/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/rsc/EnsembleSelectComposite.java +++ b/ncep/gov.noaa.nws.ncep.viz.rsc.ncgrid/src/gov/noaa/nws/ncep/viz/rsc/ncgrid/rsc/EnsembleSelectComposite.java @@ -114,7 +114,7 @@ public class EnsembleSelectComposite extends Composite { Button isPrimaryButton; Text[] weightText = new Text[MaxNumOfEnsembleCycles]; - Button[] cycleButtons = new Button[MaxNumOfEnsembleCycles]; + Button[] cycleButtons = new Button[MaxNumOfEnsembleCycles]; } public EnsembleSelectComposite( Composite parent ) { @@ -294,7 +294,7 @@ public class EnsembleSelectComposite extends Composite { // Use the NcGridInventory with constraints on the model/ensembleId @SuppressWarnings("null") public Date[] getAvailCycleTimes( Date seldCycleTime, String modelName, String pertNum ) { - + HashMap reqConstraints = new HashMap(); reqConstraints.put( "pluginName", new RequestConstraint( GridDBConstants.GRID_TBL_NAME ) ); @@ -312,20 +312,20 @@ public class EnsembleSelectComposite extends Composite { reqMsg.setReqConstraintsMap( (HashMap)reqConstraints ); reqMsg.setUniqueValues( true ); - + Object rslts; - try { + try { rslts = ThriftClient.sendRequest( reqMsg ); } catch (VizException e) { System.out.println("Error querying inventory "+inventoryName+" for ensemble "+ " component cycle times:"+e.getMessage() ); return new Date[0]; - } + } if( !(rslts instanceof String[]) ) { out.println("Inventory Request Failed: "+rslts.toString() ); return new Date[0]; - } + } String[] rsltsList = (String[]) rslts; DataTime[] dataTimeArr = new DataTime[ rsltsList.length ]; @@ -333,7 +333,7 @@ public class EnsembleSelectComposite extends Composite { for( int i=0 ; i refTimes = new ArrayList(); @@ -347,14 +347,14 @@ public class EnsembleSelectComposite extends Composite { if( !refTimes.contains( refTime ) && refTime.getTime() <= seldCycleTime.getTime() ) { refTimes.add( refTime ); - } + } } - + Date[] sortedRefTimesArr = refTimes.toArray( new Date[0] ); Arrays.sort( sortedRefTimesArr ); Date[] availCycleTimesArray = - Arrays.copyOf( sortedRefTimesArr, MaxNumOfEnsembleCycles ); + Arrays.copyOf( sortedRefTimesArr, sortedRefTimesArr.length ); return availCycleTimesArray; } diff --git a/ncep/gov.noaa.nws.ncep.viz.rsc.plotdata/src/gov/noaa/nws/ncep/viz/rsc/plotdata/rsc/NcPlotResource2.java b/ncep/gov.noaa.nws.ncep.viz.rsc.plotdata/src/gov/noaa/nws/ncep/viz/rsc/plotdata/rsc/NcPlotResource2.java index 4b7d504e49..3992874700 100644 --- a/ncep/gov.noaa.nws.ncep.viz.rsc.plotdata/src/gov/noaa/nws/ncep/viz/rsc/plotdata/rsc/NcPlotResource2.java +++ b/ncep/gov.noaa.nws.ncep.viz.rsc.plotdata/src/gov/noaa/nws/ncep/viz/rsc/plotdata/rsc/NcPlotResource2.java @@ -125,6 +125,8 @@ import static java.lang.System.out; * 10/18/2012 896 sgurung Refactored PlotResource2 to use new generator class: NcPlotDataThreadPool. Added FrameLoaderJob to populate all frames. * Added code to plot stations within 25% of the area outside of the current display area. * 05/20/2013 988 Archana.S Refactored this class for performance improvement + * 10/24/2013 sgurung Added fix for "no data for every other frame" issue + * * * * @author brockwoo @@ -1470,7 +1472,6 @@ public class NcPlotResource2 extends AbstractNatlCntrsResource= 0 ; --index){ frameLoaderTask = new FrameLoaderTask( listOfFrameTimes.get( index ) ); frameRetrievalPool.schedule( frameLoaderTask ); - --index; } } else{ diff --git a/rpms/build/i386/build.sh b/rpms/build/i386/build.sh index 9ee32c3e1c..02bb5cc53a 100644 --- a/rpms/build/i386/build.sh +++ b/rpms/build/i386/build.sh @@ -385,15 +385,15 @@ fi # Use the custom flag for selecting specific rpms to build if [ "${1}" = "-custom" ]; then - unpackHttpdPypies - if [ $? -ne 0 ]; then - exit 1 - fi - buildRPM "awips2-httpd-pypies" + #unpackHttpdPypies + #if [ $? -ne 0 ]; then + # exit 1 + #fi + #buildRPM "awips2-httpd-pypies" buildRPM "awips2-adapt-native" buildRPM "awips2-hydroapps-shared" - buildRPM "awips2-common-base" - buildRPM "awips2-rcm" + #buildRPM "awips2-common-base" + #buildRPM "awips2-rcm" #buildRPM "awips2-ant" #buildRPM "awips2-java" #buildRPM "awips2-tools" From 8479f5a2a34b0e001f3a23f0703e4ea35a1b0428 Mon Sep 17 00:00:00 2001 From: Bryan Kowal Date: Wed, 30 Oct 2013 15:24:01 -0500 Subject: [PATCH 13/26] Re-enable the build of the awips2 rpm. Former-commit-id: bf245a7f89265a3067b80b67d665b10f0a4560d1 [formerly 16e83e34556943859286393d560387ee4ed624d6] [formerly 40e8a942358742cd87e806e813840fb5ec361a01] [formerly 326144970cd74f0d9cbd08a9ce0200b4bac5fa90 [formerly 40e8a942358742cd87e806e813840fb5ec361a01 [formerly 65ab48743eecfebde890b51a1c74f9a0d68506bf]]] Former-commit-id: 326144970cd74f0d9cbd08a9ce0200b4bac5fa90 Former-commit-id: 1c783532062ff1679c7f78199095439201056d75 [formerly 1c0a4699750fd692cc858a53a66c9e45e5b3c25a] Former-commit-id: 897b7fbd2759255bfa88a6651bac5a2f195fc043 --- rpms/build/i386/build.sh | 1 + rpms/build/x86_64/build.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/rpms/build/i386/build.sh b/rpms/build/i386/build.sh index 473546d58e..c44abc3c10 100644 --- a/rpms/build/i386/build.sh +++ b/rpms/build/i386/build.sh @@ -185,6 +185,7 @@ if [ "${1}" = "-delta" ]; then fi if [ "${1}" = "-full" ]; then + buildRPM "awips2" buildRPM "awips2-common-base" buildCAVE if [ $? -ne 0 ]; then diff --git a/rpms/build/x86_64/build.sh b/rpms/build/x86_64/build.sh index 82b3bb8fc1..59477263bc 100644 --- a/rpms/build/x86_64/build.sh +++ b/rpms/build/x86_64/build.sh @@ -165,6 +165,7 @@ if [ "${1}" = "-delta" ]; then fi if [ "${1}" = "-full" ]; then + buildRPM "awips2" buildRPM "awips2-common-base" buildCAVE if [ $? -ne 0 ]; then From 3a5911368f9ea8b16b684457208f0ad6a98fd732 Mon Sep 17 00:00:00 2001 From: Steve Harris Date: Thu, 31 Oct 2013 12:52:07 -0400 Subject: [PATCH 14/26] 13.5.3-3 baseline Former-commit-id: 8df88e1b77629598dfeb759743b719583404bd6a [formerly 883ad324437508e52f88920bc9a3c02746462614] [formerly 7262d8048f574b9f53c07b9d52160b617af83270 [formerly baa036cd62d0479bfb9bf275a8b0b5bbf66ed8db]] [formerly 1503847a4b12f899de4003fd53ecc5e3fc73014f [formerly baa036cd62d0479bfb9bf275a8b0b5bbf66ed8db [formerly c261e0753eb106a2912314056a1b4903695750c5]]] Former-commit-id: 1503847a4b12f899de4003fd53ecc5e3fc73014f Former-commit-id: e27f6359a046d1d0047ec0fc1c24c9d171c5bf82 [formerly 6b879b246590f351b44ac861708bc7b10b7237b7] Former-commit-id: a58b825ddeb16d38a5557136ac422db59d5c7efb --- .../feature.xml | 7 +- .../META-INF/MANIFEST.MF | 6 +- .../ArchiveCaseCreationDialogAction.java | 76 +- .../archive/ArchiveRetentionDialogAction.java | 77 +- .../uf/viz/archive/data/ArchiveInfo.java | 4 +- .../uf/viz/archive/data/CategoryInfo.java | 39 +- .../uf/viz/archive/data/IRetentionHour.java | 47 + .../uf/viz/archive/data/IUpdateListener.java | 5 +- .../raytheon/uf/viz/archive/data/SizeJob.java | 831 ++- .../uf/viz/archive/ui/AbstractArchiveDlg.java | 407 +- .../viz/archive/ui/ArchiveRetentionDlg.java | 159 +- .../uf/viz/archive/ui/ArchiveTableComp.java | 101 +- .../viz/archive/ui/CaseCreateException.java | 69 + .../uf/viz/archive/ui/CaseCreationDlg.java | 705 ++- .../viz/archive/ui/CaseLoadSaveDeleteDlg.java | 261 + .../uf/viz/archive/ui/CaseNameDialog.java | 5 +- .../uf/viz/archive/ui/GenerateCaseDlg.java | 774 ++- .../SizeJobRequest.java => ui/ICaseCopy.java} | 60 +- .../uf/viz/archive/ui/IRetentionHour.java | 28 +- .../src/com/raytheon/uf/viz/core/VizApp.java | 18 +- .../uf/viz/core/comm/JMSConnection.java | 51 +- .../localization/LocalizationInitializer.java | 4 +- .../localization/LocalizationManager.java | 42 +- .../d2d/nsharp/rsc/D2DNSharpDataObject.java | 15 +- .../scan/resource/ScanResourceData.java | 14 +- .../viz/radarapps/fsi/FSILauncherLayer.java | 42 +- .../ThinClientNotificationManagerJob.java | 11 +- .../ThinClientLocalizationInitializer.java | 9 +- .../viz/grid/data/RadarRequestableData.java | 9 +- .../raytheon/viz/grid/inv/GridUpdater.java | 41 +- .../raytheon/viz/grid/inv/RadarUpdater.java | 48 +- .../grid/record/RequestableDataRecord.java | 22 +- .../texteditor/dialogs/TextEditorDialog.java | 392 +- .../viz/warngen/gui/FollowupData.java | 13 +- .../viz/warngen/gui/WarngenLayer.java | 12 +- .../viz/warngen/util/CurrentWarnings.java | 26 +- .../viz/warnings/rsc/WWAResourceData.java | 21 +- cots/edu.uci.ics.crawler4j/.classpath | 1 - .../META-INF/MANIFEST.MF | 17 +- cots/edu.uci.ics.crawler4j/build.properties | 1 - .../commons-compress-1.3.jar | Bin 224548 -> 0 bytes cots/org.apache.commons.compress/.classpath | 7 + cots/org.apache.commons.compress/.project | 28 + .../.settings/org.eclipse.jdt.core.prefs | 7 + .../META-INF/MANIFEST.MF | 21 + .../build.properties | 2 + .../commons-compress-1.5-javadoc.jar | Bin 0 -> 696321 bytes .../commons-compress-1.5-sources.jar | Bin 0 -> 283704 bytes .../commons-compress-1.5.jar | Bin 0 -> 256241 bytes edexOsgi/build.edex/esb/bin/setup.env | 1 + edexOsgi/build.edex/esb/conf/modes.xml | 54 +- .../esb/conf/spring/cron.properties | 4 - edexOsgi/build.edex/esb/conf/spring/edex.xml | 2 +- edexOsgi/build.edex/esb/etc/ingestHydro.sh | 29 + edexOsgi/build.edex/esb/etc/requestHydro.sh | 36 + .../edex/plugin/airep/AirepDecoder.java | 29 +- .../binlightning/BinLightningDecoder.java | 125 +- .../plugin/bufrmos/common/BufrMosData.java | 204 +- .../bufrua/decoder/AbstractBUFRUAAdapter.java | 2 +- .../edex/plugin/ccfp/CcfpDecoder.java | 80 +- .../raytheon/edex/plugin/ccfp/CcfpRecord.java | 24 +- .../edex/plugin/gfe/db/dao/GFED2DDao.java | 20 +- .../edex/plugin/gfe/db/dao/GFEDao.java | 3 + .../plugin/gfe/db/dao/GFEPathProvider.java | 97 + .../goessounding/GOESSoundingDecoder.java | 6 +- .../GribDecoder.py | 5 +- .../edex/plugin/grib/Grib1Decoder.java | 47 +- .../edex/plugin/grib/GridToGribConverter.java | 20 +- .../CPCoutlookGribPostProcessor.java | 5 +- .../EnsembleGridAssembler.java | 6 +- .../decoderpostprocessors/GFSProcessor.java | 11 +- .../Nam80PostProcessor.java | 14 +- .../SixHrPrecipGridProcessor.java | 6 +- .../ThreeHrPrecipGridProcessor.java | 8 +- .../res/spring/ldadhydro-common.xml | 9 +- .../res/spring/ldadhydro-ingest.xml | 4 +- .../plugin/ldadhydro/dao/HydroDecoder.java | 17 +- .../res/spring/ldadmanual-common.xml | 6 - .../res/spring/ldadmanual-ingest.xml | 4 +- .../plugin/ldadmanual/dao/ManualDecoder.java | 42 +- .../ldadmanual/dao/ManualLdadRecord.java | 3657 ++++++------ .../ldadprofiler/common/ProfilerLdadObs.java | 501 +- .../modelsounding/ModelSoundingDecoder.java | 34 +- .../modelsounding/common/SoundingSite.java | 14 +- .../META-INF/MANIFEST.MF | 1 - ...f.common.serialization.ISerializableObject | 1 - .../res/spring/obs-ingest.xml | 4 +- .../raytheon/edex/plugin/obs/ObsDecoder.java | 68 +- .../plugin/obs/mesowest/MesowestDecoder.java | 150 - .../plugin/obs/mesowest/MesowestRecord.java | 361 -- .../edex/plugin/obs/metar/MetarDecoder.java | 41 +- .../obs/metar/MetarPointDataTransform.java | 20 +- .../edex/plugin/pirep/PirepDecoder.java | 15 +- .../poessounding/POESSoundingDecoder.java | 6 +- .../edex/plugin/profiler/ProfilerDecoder.java | 10 +- .../edex/plugin/radar/RadarDecoder.java | 26 +- .../edex/plugin/radar/dao/RadarDao.java | 15 +- .../edex/plugin/recco/RECCODecoder.java | 6 +- .../edex/plugin/recco/common/RECCORecord.java | 17 +- .../edex/plugin/redbook/RedbookDecoder.java | 22 +- .../plugin/redbook/common/RedbookRecord.java | 121 +- .../plugin/satellite/SatelliteDecoder.java | 58 +- .../edex/plugin/sfcobs/SfcObsDecoder.java | 18 +- .../edex/plugin/shef/data/ShefRecord.java | 97 +- .../edex/plugin/shef/database/PostShef.java | 15 + .../shef/TestMetarToShefTransformer.java | 52 +- .../raytheon/edex/plugin/taf/TafDecoder.java | 25 +- .../edex/plugin/taf/common/TafRecord.java | 44 +- .../res/spring/text-ingest.xml | 5 + .../edex/plugin/text/TextDecoder.java | 45 +- .../raytheon/edex/plugin/text/TextRecord.java | 7 +- .../textlightning/TextLightningDecoder.java | 29 +- .../WarningDecoder.py | 42 +- .../edex/uengine/tasks/query/TermQuery.java | 31 +- .../edex/services/GetServersHandler.java | 27 +- .../META-INF/MANIFEST.MF | 9 +- .../archive/config/ArchiveConfigManager.java | 524 +- .../archive/config/ArchiveConstants.java | 112 + .../common/archive/config/CategoryConfig.java | 165 +- .../archive/config/CategoryDataSet.java | 294 + .../config/CategoryFileDateHelper.java | 126 +- .../uf/common/archive/config/DisplayData.java | 93 +- .../common/archive/config/FileDateFilter.java | 22 +- .../archive/config/IFileDateHelper.java | 10 +- .../common/archive/config/SelectConfig.java | 192 + .../archive/config/select/ArchiveSelect.java | 104 + .../archive/config/select/CategorySelect.java | 98 + .../request/ArchiveAdminAuthRequest.java | 107 + .../common/dataplugin/acars/ACARSRecord.java | 77 +- .../acarssounding/ACARSSoundingRecord.java | 44 +- .../common/dataplugin/airep/AirepRecord.java | 44 +- .../binlightning/BinLightningRecord.java | 91 +- .../common/dataplugin/bufrascat/AScatObs.java | 465 +- .../common/dataplugin/bufrhdw/BufrHDWObs.java | 1081 ++-- .../dataplugin/bufrmthdw/BufrMTHDWObs.java | 1081 ++-- .../uf/common/dataplugin/ncwf/BUFRncwf.java | 338 +- .../dataplugin/bufrquikscat/QUIKScatObs.java | 534 +- .../dataplugin/bufrsigwx/SigWxData.java | 399 +- .../dataplugin/bufrssmi/SSMIScanData.java | 501 +- .../uf/common/dataplugin/bufrua/UAObs.java | 1355 ++--- .../uf/common/dataplugin/cwa/CWARecord.java | 202 +- .../uf/common/dataplugin/cwat/CWATRecord.java | 21 +- .../uf/common/dataplugin/ffmp/FFMPRecord.java | 44 +- .../uf/common/dataplugin/fog/FogRecord.java | 59 +- .../dataplugin/fssobs/FSSObsRecord.java | 2354 ++++---- .../dataplugin/gfe/db/objects/GFERecord.java | 24 +- .../dataplugin/goessounding/GOESSounding.java | 589 +- .../uf/common/dataplugin/grib/GribRecord.java | 116 +- .../uf/common/dataplugin/grid/GridRecord.java | 39 +- .../dataplugin/ldadhydro/HydroLdadRecord.java | 1956 +++---- .../LdadmesonetPointDataTransform.java | 614 +- .../ldadmesonet/MesonetLdadRecord.java | 3071 +++++----- .../dataplugin/lsr/LocalStormReport.java | 932 +-- .../dataplugin/npp/crimss/CrimssRecord.java | 7 +- .../dataplugin/npp/nucaps/NucapsRecord.java | 7 +- .../dataplugin/npp/viirs/VIIRSDataRecord.java | 26 +- .../dataplugin/obs/metar/MetarRecord.java | 3156 +++++----- .../common/dataplugin/pirep/PirepRecord.java | 66 +- .../dataplugin/poessounding/POESSounding.java | 297 +- .../preciprate/PrecipRateRecord.java | 29 +- .../dataplugin/profiler/ProfilerObs.java | 45 +- .../uf/common/dataplugin/qc/QCRecord.java | 3003 +++++----- .../uf/common/dataplugin/qpf/QPFRecord.java | 35 +- .../common/dataplugin/radar/RadarRecord.java | 85 +- .../dataplugin/satellite/SatelliteRecord.java | 28 +- .../uf/common/dataplugin/scan/ScanRecord.java | 15 +- .../common/dataplugin/sfcobs/ObsCommon.java | 3160 ++++++----- .../common/dataplugin/svrwx/SvrWxRecord.java | 372 +- .../tcg/TropicalCycloneGuidance.java | 374 +- .../tcs/TropicalCycloneSummary.java | 440 +- .../uf/common/dataplugin/vaa/VAARecord.java | 164 +- .../uf/common/dataplugin/vil/VILRecord.java | 31 +- .../warning/AbstractWarningRecord.java | 5 +- .../warning/PracticeWarningRecord.java | 11 +- .../dataplugin/warning/WarningRecord.java | 11 +- .../common/dataplugin/PluginDataObject.java | 37 +- .../dataplugin/annotations/DataURIUtil.java | 31 +- .../localization/msgs/GetServersResponse.java | 11 +- .../common/util/header/WMOHeaderFinder.java | 28 +- .../com.raytheon.uf.edex.archive/.classpath | 10 +- .../META-INF/MANIFEST.MF | 10 +- .../res/spring/archiveadmim-request.xml | 13 + ...m.raytheon.uf.edex.archive.cron.properties | 6 + .../uf/edex/archive/purge/ArchivePurger.java | 40 +- .../ArchiveAdminPrivilegedRequestHandler.java | 98 + .../base/archiver/purger/PROCESSED_DATA.xml | 188 +- .../base/archiver/purger/RAW_DATA.xml | 174 +- .../base/roles/archiveAdminRoles.xml | 16 + .../feature.xml | 6 + .../database/cluster/ClusterLockUtils.java | 12 + .../database/handlers/DbQueryHandler.java | 9 +- .../uf/edex/database/plugin/PluginDao.java | 15 +- .../feature.xml | 7 + .../res/spring/harvester-datadelivery.xml | 7 +- .../util/ResponseProcessingUtilities.java | 17 +- .../filterimpl/PluginDataObjectFilter.java | 151 +- .../filterimpl/WMOHeaderFilterElement.java | 121 +- .../uf/edex/decodertools/time/TimeTools.java | 52 +- .../META-INF/MANIFEST.MF | 1 + .../res/spring/distribution-spring.xml | 5 +- .../distribution/DistributionPatterns.java | 215 + .../uf/edex/distribution/DistributionSrv.java | 212 +- .../uf/edex/distribution/RequestPatterns.java | 51 +- .../quartz/ClusteredQuartzEndpoint.java | 3 +- .../context/ClusteredContextManager.java | 4 +- .../archive/DataStoreArchiver.java | 9 +- .../res/spring/DPADecoder-spring.xml | 5 + .../res/spring/hpeDHRDecoder-spring.xml | 9 +- .../uf/edex/plugin/acars/dao/ACARSDao.java | 4 +- .../acars/decoder/ACARSDataAdapter.java | 17 +- .../acarssounding/tools/SoundingBuilder.java | 34 +- .../bufrascat/decoder/AScatDataAdapter.java | 2 +- .../bufrhdw/decoder/HDWDataAdapter.java | 2 +- .../bufrmthdw/decoder/MTHDWDataAdapter.java | 2 +- .../bufrncwf/decoder/BUFRncwfDataAdapter.java | 507 +- .../decoder/QUIKScatDataAdapter.java | 147 +- .../edex/plugin/bufrsigwx/SigWxDecoder.java | 29 +- .../bufrsigwx/decoder/SigWxDataAdapter.java | 97 +- .../bufrssmi/decoder/SSMIDataAdapter.java | 4 +- .../uf/edex/plugin/cwa/decoder/CWAParser.java | 33 +- .../uf/edex/plugin/cwat/CWATGenerator.java | 13 +- .../uf/edex/plugin/ffmp/FFMPGenerator.java | 62 +- .../uf/edex/plugin/fog/FogGenerator.java | 1 - .../plugin/fssobs/common/FSSObsConfig.java | 8 +- .../plugin/ldadmesonet/MesonetDecoder.java | 43 +- .../uf/edex/plugin/lsr/decoder/LSRParser.java | 14 +- .../META-INF/MANIFEST.MF | 5 +- .../plugin/manualIngest/MessageGenerator.java | 163 +- .../edex/plugin/mesowest/MESOWestDecoder.java | 55 +- .../mesowest/common/MESOWestRecord.java | 151 +- .../npp/sounding/NPPSoundingDecoder.java | 16 +- .../common_static/base/roles/userRoles.xml | 4 + .../preciprate/PrecipRateGenerator.java | 24 +- .../raytheon/uf/edex/plugin/qc/QCScanner.java | 69 +- .../uf/edex/plugin/qpf/QPFGenerator.java | 10 +- .../mcidas/McidasSatelliteDecoder.java | 41 +- .../uf/edex/plugin/scan/ScanGenerator.java | 9 +- .../plugin/svrwx/decoder/SvrWxParser.java | 22 +- .../uf/edex/plugin/tcg/decoder/HURData.java | 167 +- .../uf/edex/plugin/tcg/decoder/QLMData.java | 15 +- .../uf/edex/plugin/tcg/decoder/TCEData.java | 127 +- .../uf/edex/plugin/tcs/decoder/TCMData.java | 26 +- .../uf/edex/plugin/vaa/decoder/VAAParser.java | 12 +- .../uf/edex/plugin/vil/VILGenerator.java | 12 +- .../uf/edex/python/decoder/PythonDecoder.java | 20 +- .../dataplugin/airmet/AirmetRecord.java | 468 +- .../common/dataplugin/atcf/AtcfRecord.java | 1272 ++--- .../ncep/common/dataplugin/aww/AwwRecord.java | 481 +- .../convsigmet/ConvSigmetRecord.java | 405 +- .../ncep/common/dataplugin/ffg/FfgRecord.java | 208 +- .../dataplugin/geomag/GeoMagRecord.java | 14 +- .../gpd/GenericPointDataRecord.java | 431 +- .../common/dataplugin/idft/IdftRecord.java | 52 +- .../intlsigmet/IntlSigmetRecord.java | 910 +-- .../dataplugin/mcidas/McidasRecord.java | 30 +- .../ncairep/NcAirepPointDataTransform.java | 116 +- .../dataplugin/ncairep/NcAirepRecord.java | 1547 ++--- .../dataplugin/ncccfp/NcccfpRecord.java | 57 +- .../dataplugin/ncgrib/NcgribRecord.java | 396 +- .../dataplugin/ncpafm/NcPafmRecord.java | 578 +- .../dataplugin/ncpirep/NcPirepRecord.java | 1354 ++--- .../dataplugin/ncscat/NcscatRecord.java | 13 +- .../common/dataplugin/ncscd/NcScdRecord.java | 1000 ++-- .../ncscd/dao/NcScdPointDataTransform.java | 76 +- .../common/dataplugin/nctaf/NcTafRecord.java | 3188 ++++++----- .../dataplugin/ncuair/NcUairRecord.java | 993 ++-- .../nonconvsigmet/NonConvSigmetRecord.java | 906 ++- .../dataplugin/ntrans/NtransRecord.java | 228 +- .../common/dataplugin/pgen/PgenRecord.java | 12 +- .../common/dataplugin/sgwh/SgwhRecord.java | 3322 ++++++----- .../common/dataplugin/sgwhv/SgwhvRecord.java | 889 +-- .../solarimage/SolarImageRecord.java | 64 +- .../common/dataplugin/ssha/SshaRecord.java | 5056 +++++++++-------- .../stormtrack/StormTrackRecord.java | 1266 ++--- .../ncep/common/dataplugin/tcm/TcmRecord.java | 519 +- .../ncep/common/dataplugin/wcp/WcpRecord.java | 195 +- .../plugin/airmet/decoder/AirmetDecoder.java | 1 - .../edex/plugin/atcf/decoder/AtcfDecoder.java | 23 +- .../res/spring/aww-ingest.xml | 4 +- .../edex/plugin/aww/decoder/AwwDecoder.java | 281 +- .../convsigmet/decoder/ConvSigmetDecoder.java | 46 +- .../res/spring/ffg-ingest.xml | 4 +- .../edex/plugin/ffg/decoder/FfgDecoder.java | 32 +- .../res/spring/geomag-ingest.xml | 8 +- .../edex/plugin/geomag/GeoMagDecoder.java | 1181 ++-- .../edex/plugin/idft/decoder/IdftDecoder.java | 58 +- .../intlsigmet/decoder/IntlSigmetDecoder.java | 6 +- .../plugin/mcidas/decoder/McidasDecoder.java | 142 +- .../plugin/mosaic/common/MosaicRecord.java | 13 +- .../plugin/mosaic/common/dao/MosaicDao.java | 83 +- .../plugin/mosaic/decoder/MosaicDecoder.java | 48 +- .../edex/plugin/ncairep/NcAirepDecoder.java | 62 +- .../plugin/ncccfp/decoder/NcccfpDecoder.java | 540 +- .../NcgribDecoder.py | 4 +- .../edex/plugin/ncgrib/Ncgrib1Decoder.java | 418 +- .../edex/plugin/ncgrib/NcgridAssembler.java | 8 +- .../plugin/ncpafm/decoder/NcPafmDecoder.java | 115 +- .../edex/plugin/ncpirep/NcPirepDecoder.java | 229 +- .../plugin/ncscat/decoder/NcscatDecoder.java | 356 +- .../plugin/ncscd/decoder/NcScdDecoder.java | 57 +- .../plugin/nctaf/decoder/NcTafDecoder.java | 101 +- .../res/spring/nctext-ingest.xml | 5 + .../plugin/nctext/common/NctextRecord.java | 300 +- .../res/spring/ncuair-ingest.xml | 4 +- .../plugin/ncuair/decoder/NcUairDecoder.java | 1047 ++-- .../decoder/NonConvSigmetDecoder.java | 75 +- .../res/spring/ntrans-ingest.xml | 4 +- .../plugin/ntrans/decoder/NtransDecoder.java | 752 ++- .../pgen/handler/StoreActivityHandler.java | 7 +- .../edex/plugin/sgwh/decoder/SgwhDecoder.java | 40 +- .../plugin/sgwhv/decoder/SgwhvDecoder.java | 11 +- .../plugin/solarimage/SolarImageDecoder.java | 167 +- .../edex/plugin/ssha/decoder/SshaDecoder.java | 38 +- .../META-INF/MANIFEST.MF | 1 + .../res/spring/stormtrack-ingest.xml | 6 +- .../stormtrack/decoder/StormTrackDecoder.java | 82 +- .../edex/plugin/tcm/decoder/TcmDecoder.java | 44 +- .../edex/plugin/wcp/decoder/WcpDecoder.java | 35 +- .../tasks/profile/ObservedSoundingQuery.java | 3589 ++++++------ .../nws/ncep/ui/pgen/store/StorageUtils.java | 16 +- .../decoder/RegionalSatDecoder.java | 30 +- .../dataplugin/gfe/db/objects/GFERecord.py | 5 +- rpms/build/i386/build.sh | 9 +- rpms/build/i386/build.sh-keep-10312013 | 445 ++ .../archive/ArchiveConfigManagerTest.java | 212 +- 325 files changed, 42823 insertions(+), 37801 deletions(-) create mode 100644 cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IRetentionHour.java create mode 100644 cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreateException.java create mode 100644 cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseLoadSaveDeleteDlg.java rename cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/{data/SizeJobRequest.java => ui/ICaseCopy.java} (52%) rename edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/util/package-info.java => cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/IRetentionHour.java (54%) delete mode 100644 cots/edu.uci.ics.crawler4j/commons-compress-1.3.jar create mode 100644 cots/org.apache.commons.compress/.classpath create mode 100644 cots/org.apache.commons.compress/.project create mode 100644 cots/org.apache.commons.compress/.settings/org.eclipse.jdt.core.prefs create mode 100644 cots/org.apache.commons.compress/META-INF/MANIFEST.MF create mode 100644 cots/org.apache.commons.compress/build.properties create mode 100644 cots/org.apache.commons.compress/commons-compress-1.5-javadoc.jar create mode 100644 cots/org.apache.commons.compress/commons-compress-1.5-sources.jar create mode 100644 cots/org.apache.commons.compress/commons-compress-1.5.jar create mode 100644 edexOsgi/build.edex/esb/etc/ingestHydro.sh create mode 100644 edexOsgi/build.edex/esb/etc/requestHydro.sh create mode 100644 edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEPathProvider.java delete mode 100644 edexOsgi/com.raytheon.edex.plugin.obs/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject delete mode 100644 edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/MesowestDecoder.java delete mode 100644 edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/MesowestRecord.java create mode 100644 edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConstants.java create mode 100644 edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryDataSet.java create mode 100644 edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/SelectConfig.java create mode 100644 edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/ArchiveSelect.java create mode 100644 edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/CategorySelect.java create mode 100644 edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/request/ArchiveAdminAuthRequest.java create mode 100644 edexOsgi/com.raytheon.uf.edex.archive/res/spring/archiveadmim-request.xml create mode 100644 edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties create mode 100644 edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/useradmin/ArchiveAdminPrivilegedRequestHandler.java create mode 100644 edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/roles/archiveAdminRoles.xml create mode 100644 edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionPatterns.java mode change 100755 => 100644 ncep/gov.noaa.nws.ncep.edex.plugin.airmet/src/gov/noaa/nws/ncep/edex/plugin/airmet/decoder/AirmetDecoder.java create mode 100644 rpms/build/i386/build.sh-keep-10312013 diff --git a/cave/com.raytheon.uf.viz.archive.feature/feature.xml b/cave/com.raytheon.uf.viz.archive.feature/feature.xml index 9705fea76d..37b1cd68f2 100644 --- a/cave/com.raytheon.uf.viz.archive.feature/feature.xml +++ b/cave/com.raytheon.uf.viz.archive.feature/feature.xml @@ -37,14 +37,13 @@ unpack="false"/> + version="0.0.0"/> * @@ -25,8 +53,14 @@ import com.raytheon.uf.viz.archive.ui.CaseCreationDlg; * @version 1.0 */ public class ArchiveCaseCreationDialogAction extends AbstractHandler { + private final IUFStatusHandler statusHandler = UFStatus + .getHandler(ArchiveCaseCreationDialogAction.class); + private CaseCreationDlg dialog; + /** Case Administration permission */ + private final String PERMISSION = "archive.casecreation"; + /* * (non-Javadoc) * @@ -36,16 +70,44 @@ public class ArchiveCaseCreationDialogAction extends AbstractHandler { */ @Override public Object execute(ExecutionEvent event) throws ExecutionException { - if (dialog == null || dialog.isDisposed()) { - Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() - .getShell(); - dialog = new CaseCreationDlg(shell); - dialog.open(); - } else { - dialog.bringToTop(); + if (isAuthorized()) { + if (dialog == null || dialog.isDisposed()) { + Shell shell = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow().getShell(); + dialog = new CaseCreationDlg(shell); + dialog.open(); + } else { + dialog.bringToTop(); + } } return null; } + /** + * Is user authorized? + * + * @return true if authorized + */ + private boolean isAuthorized() { + IUser user = UserController.getUserObject(); + String msg = user.uniqueId() + + " does not have permission to access archive case creation dialog."; + ArchiveAdminAuthRequest request = new ArchiveAdminAuthRequest(); + request.setRoleId(PERMISSION); + request.setNotAuthorizedMessage(msg); + request.setUser(user); + + try { + Object o = ThriftClient.sendPrivilegedRequest(request); + if (o instanceof ArchiveAdminAuthRequest) { + ArchiveAdminAuthRequest r = (ArchiveAdminAuthRequest) o; + return r.isAuthorized(); + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + + return false; + } } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ArchiveRetentionDialogAction.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ArchiveRetentionDialogAction.java index d9a6fa1d60..67d3da0d53 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ArchiveRetentionDialogAction.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ArchiveRetentionDialogAction.java @@ -1,3 +1,22 @@ +/** + * 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.viz.archive; import org.eclipse.core.commands.AbstractHandler; @@ -6,7 +25,15 @@ import org.eclipse.core.commands.ExecutionException; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; +import com.raytheon.uf.common.archive.request.ArchiveAdminAuthRequest; +import com.raytheon.uf.common.auth.user.IUser; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.viz.archive.ui.ArchiveRetentionDlg; +import com.raytheon.uf.viz.core.auth.UserController; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.requests.ThriftClient; /** * Action to display the Archive Retention dialog. @@ -18,6 +45,7 @@ import com.raytheon.uf.viz.archive.ui.ArchiveRetentionDlg; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * May 16, 2013 1966 rferrel Initial creation + * Oct 02, 2013 2326 rferrel Check for administration authorization. * * * @@ -25,8 +53,14 @@ import com.raytheon.uf.viz.archive.ui.ArchiveRetentionDlg; * @version 1.0 */ public class ArchiveRetentionDialogAction extends AbstractHandler { + private final IUFStatusHandler statusHandler = UFStatus + .getHandler(ArchiveRetentionDialogAction.class); + private ArchiveRetentionDlg dialog; + /** Retention Administration permission */ + private final String PERMISSION = "archive.retention"; + /* * (non-Javadoc) * @@ -36,15 +70,44 @@ public class ArchiveRetentionDialogAction extends AbstractHandler { */ @Override public Object execute(ExecutionEvent event) throws ExecutionException { - if (dialog == null || dialog.isDisposed()) { - Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() - .getShell(); - dialog = new ArchiveRetentionDlg(shell); - dialog.open(); - } else { - dialog.bringToTop(); + if (isAuthorized()) { + if (dialog == null || dialog.isDisposed()) { + Shell shell = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow().getShell(); + dialog = new ArchiveRetentionDlg(shell); + dialog.open(); + } else { + dialog.bringToTop(); + } } return null; } + + /** + * Is user authorized? + * + * @return true if authorized + */ + private boolean isAuthorized() { + IUser user = UserController.getUserObject(); + String msg = user.uniqueId() + + " does not have permission to access archive retention dialog."; + ArchiveAdminAuthRequest request = new ArchiveAdminAuthRequest(); + request.setRoleId(PERMISSION); + request.setNotAuthorizedMessage(msg); + request.setUser(user); + + try { + Object o = ThriftClient.sendPrivilegedRequest(request); + if (o instanceof ArchiveAdminAuthRequest) { + ArchiveAdminAuthRequest r = (ArchiveAdminAuthRequest) o; + return r.isAuthorized(); + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + + return false; + } } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/ArchiveInfo.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/ArchiveInfo.java index 6391f7a2d9..78eae24d98 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/ArchiveInfo.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/ArchiveInfo.java @@ -19,9 +19,9 @@ **/ package com.raytheon.uf.viz.archive.data; -import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * This class maintains the state of the archive selection so it can be restored @@ -42,7 +42,7 @@ import java.util.Set; */ public class ArchiveInfo { - private final Map categoryInfoMap = new HashMap(); + private final Map categoryInfoMap = new ConcurrentHashMap(); public void add(CategoryInfo categoryInfo) { categoryInfoMap.put(categoryInfo.getCategoryName(), categoryInfo); diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/CategoryInfo.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/CategoryInfo.java index cc9b64735b..2a9ffc05ec 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/CategoryInfo.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/CategoryInfo.java @@ -19,6 +19,8 @@ **/ package com.raytheon.uf.viz.archive.data; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import com.raytheon.uf.common.archive.config.DisplayData; @@ -34,6 +36,7 @@ import com.raytheon.uf.common.archive.config.DisplayData; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * May 24, 2013 1966 rferrel Initial creation + * Aug 14, 2013 2220 rferrel Make sure displayDataList is never null. * * * @@ -49,31 +52,57 @@ public class CategoryInfo { private final String categoryName; /** List of display items for the category. */ - private final List displayDataList; + private List displayDataList; /** - * Contructor. + * Constructor. * * @param archiveName * @param categoryName * @param displayInfoList */ public CategoryInfo(String archiveName, String categoryName, - List displayInfoList) { + List displayDataList) { this.archiveName = archiveName; this.categoryName = categoryName; - this.displayDataList = displayInfoList; + if (displayDataList == null) { + this.displayDataList = new ArrayList(0); + } else { + setDisplayDataList(displayDataList); + } } + /** + * Change the display data list. + * + * @param displayDataList + */ + public void setDisplayDataList(List displayDataList) { + this.displayDataList = new ArrayList( + displayDataList.size()); + this.displayDataList.addAll(displayDataList); + } + + /** + * @return archiveName + */ public String getArchiveName() { return archiveName; } + /** + * @return categoryName + */ public String getCategoryName() { return categoryName; } + /** + * Get unmodifiable display data list. + * + * @return displayDataList + */ public List getDisplayDataList() { - return displayDataList; + return Collections.unmodifiableList(displayDataList); } } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IRetentionHour.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IRetentionHour.java new file mode 100644 index 0000000000..a393f5a335 --- /dev/null +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IRetentionHour.java @@ -0,0 +1,47 @@ +/** + * 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.viz.archive.data; + +/** + * Interface to adjusting values based on the retention hour value found in a + * selection configuration. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 13, 2013 2220       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public interface IRetentionHour { + /** + * Adjust start/end based on the value found in selection configuration. + * + * @param startRetentionHours + */ + public void setRetentionTimes(long startRetentionHours); +} diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IUpdateListener.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IUpdateListener.java index 1916b3c928..29e0cdaa0b 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IUpdateListener.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IUpdateListener.java @@ -21,6 +21,8 @@ package com.raytheon.uf.viz.archive.data; import java.util.List; +import com.raytheon.uf.common.archive.config.DisplayData; + /** * A listener to update file/directory information. * @@ -31,6 +33,7 @@ import java.util.List; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * May 16, 2013 1966 rferrel Initial creation + * Jul 29, 2012 #2220 rferrel Change to get all data sizes only one time. * * * @@ -43,5 +46,5 @@ public interface IUpdateListener { * * @param dirInfos */ - public void update(List request); + public void update(List request); } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJob.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJob.java index 3e4b249ead..c4c6bfdb87 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJob.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJob.java @@ -3,8 +3,18 @@ package com.raytheon.uf.viz.archive.data; import java.io.File; import java.util.ArrayList; import java.util.Calendar; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; -import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.core.runtime.IProgressMonitor; @@ -13,8 +23,16 @@ import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import com.raytheon.uf.common.archive.config.ArchiveConfigManager; +import com.raytheon.uf.common.archive.config.ArchiveConstants; +import com.raytheon.uf.common.archive.config.ArchiveConstants.Type; import com.raytheon.uf.common.archive.config.DisplayData; -import com.raytheon.uf.common.util.FileUtil; +import com.raytheon.uf.common.archive.config.SelectConfig; +import com.raytheon.uf.common.archive.config.select.ArchiveSelect; +import com.raytheon.uf.common.archive.config.select.CategorySelect; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.util.TimeUtil; /** * Job to determine the size for a directory and its contents on a non-UI @@ -27,6 +45,9 @@ import com.raytheon.uf.common.util.FileUtil; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 13, 2013 rferrel Initial creation + * Jul 24, 2013 #2220 rferrel Change to get all data sizes only one time. + * Aug 02, 2013 #2224 rferrel Changes for new configuration files. + * Aug 06, 2013 #2222 rferrel Changes to display all selected data. * * * @@ -34,26 +55,139 @@ import com.raytheon.uf.common.util.FileUtil; * @version 1.0 */ public class SizeJob extends Job { - - /** The queue for requested sizes. */ - private final ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); + private final IUFStatusHandler statusHandler = UFStatus + .getHandler(SizeJob.class); /** - * Pending selected entries that still need to have the sizes determined. + * The private variable from PriorityQueue. */ - private final ConcurrentLinkedQueue selectedQueue = new ConcurrentLinkedQueue(); + private final int DEFAULT_INITIAL_CAPACITY = 11; /** - * Indicates the job should stop computing the size of the current - * non-selected entry. + * Mapping of display data by archive and category names. */ - private final AtomicBoolean stopComputeSize = new AtomicBoolean(false); + private final Map archiveInfoMap = new ConcurrentHashMap(); /** - * The listeners to inform when job is done with an entry. + * Current archive name needing sizes. + */ + private String displayArchive; + + /** + * Current category name needing sizes. + */ + private String displayCategory; + + /** + * Set to true when all sizes are computed for the current display + * archive/category list. + */ + private final AtomicBoolean displaySizesComputed = new AtomicBoolean(false); + + /** + * Queue of display data needing sizes. + */ + private final PriorityBlockingQueue sizeQueue = new PriorityBlockingQueue( + DEFAULT_INITIAL_CAPACITY, DisplayData.PRIORITY_ORDER); + + /** + * Data to send to listeners. + */ + private final LinkedBlockingQueue displayQueue = new LinkedBlockingQueue(); + + /** + * Current list of visible data. + */ + private List visibleList = new ArrayList(0); + + /** + * Set to true when running job should stop and never be rescheduled. + */ + private final AtomicBoolean shutdown = new AtomicBoolean(false); + + /** + * The listeners to inform when job is done with a request. */ private final List listeners = new ArrayList(); + /** + * The display data whose size is being computed. + */ + private DisplayData currentDisplayData; + + /** + * Method to call when loading a new selection for retention/case creation + * to update times. + */ + private IRetentionHour iRetentionHour; + + /** + * Current start time. + */ + private Calendar startCal; + + /** + * Current end time. + */ + private Calendar endCal; + + /** + * Timer to periodically update the GUI display computed sizes. + */ + private Timer displayTimer; + + /** + * Flag to shutdown the display timer. + */ + private final AtomicBoolean shutdownDisplayTimer = new AtomicBoolean(false); + + /** + * Frequency for performing peek while computing sizes. + */ + private final int peekFrequency = 50; + + /** + * Counter to reduce the number of times a peek is performed while computing + * sizes. + */ + private int peekCnt; + + /** + * Flag to stop computing sizes; only accessed by a single thread. + */ + private boolean stopComputeSize; + + /** + * Priority queue for getting display data for an archive/category. + */ + // Do not use a PriorityBlockingQueue since the load select and change + // display methods need to be notified when the display data is available. + private final PriorityQueue missingDataQueue = new PriorityQueue( + DEFAULT_INITIAL_CAPACITY, new Comparator() { + + @Override + public int compare(MissingData o1, MissingData o2) { + if (o1.visiable != o2.visiable) { + return o1.visiable ? -1 : +1; + } + if (o1.isSelected() != o2.isSelected()) { + return o1.isSelected() ? -1 : +1; + } + + int result = o1.archive.compareToIgnoreCase(o2.archive); + + if (result == 0) { + result = o1.category.compareToIgnoreCase(o2.category); + } + return result; + } + }); + + /** + * Job for processing the missing data queue. + */ + private final MissingDataJob missingDataJob = new MissingDataJob(); + /** * Constructor. */ @@ -81,13 +215,39 @@ public class SizeJob extends Job { } /** - * Add entry to queue and if pending selected entries add them to the queue - * with same start/end times. + * Start and/or end time has changed so all sizes need to be recomputed. * - * @param fileInfo + * @param startCal + * @param endCal */ - public void queue(SizeJobRequest fileInfo) { - queue.add(fileInfo); + public void resetTime(Calendar startCal, Calendar endCal) { + this.startCal = startCal; + this.endCal = endCal; + recomputeSize(); + } + + /** + * Force getting the sizes for all data in the archive Information map. + */ + public void recomputeSize() { + clearQueue(); + for (ArchiveInfo archiveInfo : archiveInfoMap.values()) { + for (String categoryName : archiveInfo.getCategoryNames()) { + CategoryInfo categoryInfo = archiveInfo.get(categoryName); + for (DisplayData displayData : categoryInfo + .getDisplayDataList()) { + displayData.setSize(DisplayData.UNKNOWN_SIZE); + sizeQueue.add(displayData); + + if (shutdown.get()) { + return; + } + } + } + } + + // Forces update of current display. + displaySizesComputed.set(false); if (getState() == Job.NONE) { schedule(); @@ -95,43 +255,384 @@ public class SizeJob extends Job { } /** - * Clear queue but save selected entries still needing sizes. + * Add entry to the archive information map. + * + * @param archiveName + * @param archiveInfo */ - public void clearQueue() { - List pending = new ArrayList(); + public void put(String archiveName, ArchiveInfo archiveInfo) { + archiveInfoMap.put(archiveName, archiveInfo); + } - // Drain queue queue.removeAll() doesn't work. - while (!queue.isEmpty()) { - pending.add(queue.remove()); + /** + * Get an entry from the archive information map. + * + * @param archiveName + * @return + */ + public ArchiveInfo get(String archiveName) { + return archiveInfoMap.get(archiveName); + } + + /** + * @return archiveNames + */ + public Set getArchiveNames() { + return archiveInfoMap.keySet(); + } + + /** + * Check all displayData selection state so only the data in selections are + * set. + * + * @param selections + */ + public void loadSelect(String selectName, ArchiveConstants.Type type) { + ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); + String fileName = ArchiveConstants.selectFileName(type, selectName); + SelectConfig selections = manager.loadSelection(fileName); + if (selections == null) { + selections = new SelectConfig(); + selections.setName(ArchiveConstants.defaultSelectName); } + iRetentionHour.setRetentionTimes(selections.getStarRetentionHours()); - if (getState() != NONE) { - cancel(); - } - - // Save selected items that do not have sizes. - for (SizeJobRequest dirInfo : pending) { - DisplayData displayData = dirInfo.getDisplayData(); - - if (displayData.isSelected() && displayData.getSize() < 0L) { - if (!selectedQueue.contains(displayData)) { - selectedQueue.add(displayData); + for (String archiveName : getArchiveNames()) { + ArchiveInfo archiveInfo = get(archiveName); + for (String categoryName : archiveInfo.getCategoryNames()) { + List selectionsList = selections.getSelectedList( + archiveName, categoryName); + MissingData missingData = removeMissingData(archiveName, + categoryName); + if (missingData != null) { + missingData.setSelectedList(selectionsList); + addMissingData(missingData); + } else { + CategoryInfo categoryInfo = archiveInfo.get(categoryName); + for (DisplayData displayData : categoryInfo + .getDisplayDataList()) { + String displayLabel = displayData.getDisplayLabel(); + boolean selected = selectionsList + .contains(displayLabel); + if (selected != displayData.isSelected()) { + setSelect(displayData, selected); + } + } } } } } /** - * Requeue pending entries. + * Get list of all selected data. * - * @param startCal - * @param endCal + * @return selected */ - public void requeueSelected(Calendar startCal, Calendar endCal) { - if (!selectedQueue.isEmpty()) { - DisplayData displayData = selectedQueue.remove(); - queue(new SizeJobRequest(displayData, startCal, endCal)); + public List getSelectAll() { + synchronized (missingDataQueue) { + while (!missingDataQueue.isEmpty()) { + if (missingDataJob.currentMissingData == null + || missingDataJob.currentMissingData.isSelected()) { + missingDataQueueWait(); + } else { + break; + } + } } + List selected = new LinkedList(); + for (ArchiveInfo archiveInfo : archiveInfoMap.values()) { + for (String categoryName : archiveInfo.getCategoryNames()) { + CategoryInfo categoryInfo = archiveInfo.get(categoryName); + for (DisplayData displayData : categoryInfo + .getDisplayDataList()) { + if (displayData.isSelected()) { + selected.add(displayData); + } + } + } + } + return selected; + } + + /** + * Save selections to the desired file. + * + * @param selectName + * @param type + * @param startRetentionMS + * @return + */ + public String saveSelect(String selectName, ArchiveConstants.Type type, + long startRetentionMS) { + String errorMsg = null; + SelectConfig selections = new SelectConfig(); + selections.setName(selectName); + if (type == Type.Case) { + long startRetentionHours = startRetentionMS + / TimeUtil.MILLIS_PER_HOUR; + selections.setStarRetentionHours(startRetentionHours); + } + for (String archiveName : getArchiveNames()) { + ArchiveInfo archiveInfo = get(archiveName); + ArchiveSelect archiveSelect = new ArchiveSelect(); + archiveSelect.setName(archiveName); + for (String categoryName : archiveInfo.getCategoryNames()) { + CategoryInfo categoryInfo = archiveInfo.get(categoryName); + CategorySelect categorySelect = new CategorySelect(); + categorySelect.setName(categoryName); + for (DisplayData displayData : categoryInfo + .getDisplayDataList()) { + if (displayData.isSelected()) { + categorySelect.add(displayData.getDisplayLabel()); + } + } + + if (!categorySelect.isEmpty()) { + archiveSelect.add(categorySelect); + } + } + if (!archiveSelect.isEmpty()) { + selections.add(archiveSelect); + } + } + String fileName = ArchiveConstants.selectFileName(type, selectName); + + try { + ArchiveConfigManager.getInstance().saveSelections(selections, + fileName); + } catch (Exception e) { + errorMsg = "Unable to save file: " + fileName; + statusHandler.handle(Priority.ERROR, errorMsg, e); + } + return errorMsg; + } + + /** + * Change the selection state and reset priority. + * + * @param displayData + * @param state + */ + public void setSelect(DisplayData displayData, boolean state) { + if (displayData.isSelected() != state) { + if (sizeQueue.remove(displayData)) { + displayData.setSelected(state); + sizeQueue.add(displayData); + } else { + displayData.setSelected(state); + } + } + } + + /** + * Change visibility state and reset priority. + * + * @param displayData + * @param state + */ + private void setVisible(DisplayData displayData, boolean state) { + if (displayData.isVisible() != state) { + if (sizeQueue.remove(displayData)) { + displayData.setVisible(state); + sizeQueue.add(displayData); + } else { + displayData.setVisible(state); + } + } + } + + /** + * Change the archive/category display. + * + * @param archiveName + * @param categoryName + * @return displayData when display needs to change otherwise null + */ + public List changeDisplay(String archiveName, + String categoryName) { + List displayDatas = null; + if (!archiveName.equals(displayArchive) + || !categoryName.equals(displayCategory)) { + MissingData missingData = removeMissingData(archiveName, + categoryName); + if (missingData != null) { + missingData.setVisiable(true); + synchronized (missingDataQueue) { + addMissingData(missingData); + while (missingDataQueue.contains(missingData)) { + missingDataQueueWait(); + } + } + } + displayDatas = archiveInfoMap.get(archiveName).get(categoryName) + .getDisplayDataList(); + displayArchive = archiveName; + displayCategory = categoryName; + changeDisplay(displayDatas); + } + return displayDatas; + } + + /** + * Change to display all selected data.. + * + * @return displayhData when display needs to change otherwise null. + */ + public List changeDisplayAll() { + List selectedData = null; + if (displayArchive != null) { + displayArchive = null; + displayCategory = null; + selectedData = getSelectAll(); + changeDisplay(selectedData); + } + return selectedData; + } + + public String initData(ArchiveConstants.Type type, String selectName, + String displayArchive, String displayCategory, + IRetentionHour iRetentionHour) { + this.iRetentionHour = iRetentionHour; + ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); + String fileName = ArchiveConstants.selectFileName(type, selectName); + SelectConfig selections = manager.loadSelection(fileName); + if (selections == null) { + selections = new SelectConfig(); + selections.setName(ArchiveConstants.defaultSelectName); + } + iRetentionHour.setRetentionTimes(selections.getStarRetentionHours()); + + missingDataQueue.clear(); + + visibleList = manager.getDisplayData(displayArchive, displayCategory, + false); + List selectedList = selections.getSelectedList(displayArchive, + displayCategory); + for (DisplayData displayData : visibleList) { + displayData.setSelected(selectedList.contains(displayData + .getDisplayLabel())); + } + + for (String archiveName : manager.getArchiveDataNamesList()) { + ArchiveInfo archiveInfo = new ArchiveInfo(); + String[] categoryNames = manager.getCategoryNames(manager + .getArchive(archiveName)); + for (String categoryName : categoryNames) { + CategoryInfo categoryInfo = new CategoryInfo(archiveName, + categoryName, null); + archiveInfo.add(categoryInfo); + if (archiveName.equals(displayArchive) + && categoryName.equals(displayCategory)) { + categoryInfo.setDisplayDataList(visibleList); + if (!visibleList.isEmpty()) { + schedule(); + } + } else { + selectedList = selections.getSelectedList(archiveName, + categoryName); + MissingData missingData = new MissingData(archiveName, + categoryName, selectedList); + missingDataQueue.add(missingData); + } + } + put(archiveName, archiveInfo); + } + + missingDataJob.schedule(); + + return selections.getName(); + } + + /** + * Find and remove the missing data from the missing data queue. + * + * @param archiveName + * @param categoryName + * @return missingData or null if not on the missing data queue + */ + private MissingData removeMissingData(String archiveName, + String categoryName) { + MissingData missingData = null; + synchronized (missingDataQueue) { + if (missingDataJob.currentMissingData != null + && archiveName + .equals(missingDataJob.currentMissingData.archive) + && categoryName + .equals(missingDataJob.currentMissingData.category)) { + // Finish the process of getting the data. + missingDataQueueWait(); + } else if (!missingDataQueue.isEmpty()) { + Iterator iterator = missingDataQueue.iterator(); + while (iterator.hasNext()) { + MissingData md = iterator.next(); + if (md.archive.equals(archiveName) + && md.category.equals(categoryName)) { + iterator.remove(); + missingData = md; + break; + } + } + } + } + return missingData; + } + + /** + * Wait for notification that current missing data is finished processing. + * + * @return false when interrupted exception + */ + private boolean missingDataQueueWait() { + boolean state = true; + try { + missingDataQueue.wait(); + } catch (InterruptedException e) { + state = false; + statusHandler.handle(Priority.INFO, e.getLocalizedMessage(), e); + } + return state; + } + + /** + * + * @param missingData + */ + private void addMissingData(MissingData missingData) { + synchronized (missingDataQueue) { + missingDataQueue.add(missingData); + if (missingDataJob.getState() == Job.NONE) { + missingDataJob.schedule(); + } + } + } + + /** + * Change update visible to the new list. + * + * @param newDisplays + */ + private void changeDisplay(List newDisplays) { + List oldDisplays = visibleList; + visibleList = newDisplays; + List visibleList = new ArrayList(newDisplays); + + for (DisplayData displayData : oldDisplays) { + if (!visibleList.remove(displayData)) { + setVisible(displayData, false); + } + } + + for (DisplayData displayData : visibleList) { + setVisible(displayData, true); + } + } + + /** + * Clear request queues and stop current request. + */ + public void clearQueue() { + sizeQueue.clear(); + displayQueue.clear(); } /* @@ -148,51 +649,123 @@ public class SizeJob extends Job { ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); - mainLoop: while (!queue.isEmpty()) { - SizeJobRequest dirInfo = queue.remove(); + updateDisplayTimer(); - stopComputeSize.set(false); - DisplayData displayData = dirInfo.displayData; - Calendar startCal = dirInfo.startCal; - Calendar endCal = dirInfo.endCal; + mainLoop: while (!shutdown.get()) { - List files = manager.getDisplayFiles(displayData, startCal, - endCal); - - // Size no longer needed. - if (!displayData.isSelected() && stopComputeSize.get()) { - continue; + currentDisplayData = sizeQueue.peek(); + if (currentDisplayData == null) { + break mainLoop; + } + + // System.out.println("+++SizeJob: " + currentDisplayData); + + List files = manager.getDisplayFiles(currentDisplayData, + startCal, endCal); + + // Size no longer needed. + if (currentDisplayData != sizeQueue.peek()) { + // System.out.println("---SizeJob: " + currentDisplayData); + continue mainLoop; } - dirInfo.files.clear(); - dirInfo.files.addAll(files); long size = 0L; - for (File file : dirInfo.files) { - - // Skip when size no longer needed. - if (!displayData.isSelected() && stopComputeSize.get()) { - continue mainLoop; - } + peekCnt = peekFrequency; + stopComputeSize = false; + for (File file : files) { if (file.isDirectory()) { - size += FileUtil.sizeOfDirectory(file); + size += sizeOfDirectory(file); } else { size += file.length(); } + + // Skip when size no longer needed. + if (stopComputeSize) { + // System.out.println("---SizeJob: " + currentDisplayData); + continue mainLoop; + } } - displayData.setSize(size); - - List list = new ArrayList(1); - list.add(dirInfo); - for (IUpdateListener listener : listeners) { - listener.update(list); - } + sizeQueue.remove(currentDisplayData); + currentDisplayData.setSize(size); + displayQueue.add(currentDisplayData); } + // System.out.println("xxxSizeJob: OK_STATUS"); + shutdownDisplayTimer.set(true); return Status.OK_STATUS; } + /** + * Determine the total size of a directory; unless stop flag is set then + * result is unknown. + * + * @param directory + * @return size + */ + private long sizeOfDirectory(File directory) { + long size = 0; + for (File file : directory.listFiles()) { + if (stopComputeSize) { + break; + } + if (--peekCnt == 0) { + if (currentDisplayData != sizeQueue.peek()) { + // Forces break out of recursion. + stopComputeSize = true; + break; + } + peekCnt = peekFrequency; + } + + if (file.isDirectory()) { + size += sizeOfDirectory(file); + } else { + size += file.length(); + } + } + return size; + } + + /** + * Start timer to update GUI's display form data on the display Queue. + */ + private void updateDisplayTimer() { + if (displayTimer != null) { + displayTimer.cancel(); + } + + shutdownDisplayTimer.set(false); + + displayTimer = new Timer(); + + TimerTask updateDisplayTask = new TimerTask() { + @Override + public void run() { + if (!displayQueue.isEmpty()) { + List list = new ArrayList( + displayQueue.size()); + displayQueue.drainTo(list); + + // for (DisplayData displayData : list) { + // System.out.println("== " + displayData); + // } + // + for (IUpdateListener listener : listeners) { + listener.update(list); + } + } else if (shutdownDisplayTimer.get()) { + // System.out.println("xxx updateDisplayTimer canceled"); + displayTimer.cancel(); + displayTimer = null; + } + } + }; + + displayTimer.schedule(updateDisplayTask, 1000, 2000); + } + /* * (non-Javadoc) * @@ -200,7 +773,125 @@ public class SizeJob extends Job { */ @Override protected void canceling() { - queue.clear(); - stopComputeSize.set(true); + // System.err.println("canceling SizeJob"); + clearQueue(); + missingDataQueue.clear(); + missingDataJob.cancel(); + shutdown.set(true); } + + /** + * Class used by the missing data job to obtain display data for given + * archive/category off the UI thread. + */ + private static class MissingData { + protected final String archive; + + protected final String category; + + protected final List selectedList; + + protected boolean visiable = false; + + public MissingData(String archive, String category, + List selectedList) { + this.archive = archive; + this.category = category; + this.selectedList = new ArrayList(selectedList); + } + + public boolean isSelected() { + return !selectedList.isEmpty(); + } + + public void setVisiable(boolean state) { + this.visiable = state; + } + + public void setSelectedList(List selectedList) { + this.selectedList.clear(); + this.selectedList.addAll(selectedList); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("MissingData["); + sb.append("archive: ").append(archive); + sb.append(", category: ").append(category); + sb.append(", visible: ").append(visiable); + sb.append(", isSelected: ").append(isSelected()); + sb.append("]"); + return sb.toString(); + } + } + + /** + * This handles getting the display data in the missing data queue and + * queuing the results for the size job. + */ + private class MissingDataJob extends Job { + + private final AtomicBoolean shutdown = new AtomicBoolean(false); + + protected MissingData currentMissingData = null; + + public MissingDataJob() { + super("MissingData"); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + if (monitor.isCanceled()) { + return Status.OK_STATUS; + } + + ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); + + while (!shutdown.get()) { + synchronized (missingDataQueue) { + if (currentMissingData != null) { + missingDataQueue.notifyAll(); + } + currentMissingData = missingDataQueue.poll(); + } + + if (currentMissingData == null) { + break; + } + + String archiveName = currentMissingData.archive; + String categoryName = currentMissingData.category; + // System.out.println("== missingData: " + currentMissingData); + List selectedList = currentMissingData.selectedList; + List displayDatas = manager.getDisplayData( + archiveName, categoryName, false); + if (shutdown.get()) { + break; + } + + for (DisplayData displayData : displayDatas) { + displayData.setSelected(selectedList.contains(displayData + .getDisplayLabel())); + sizeQueue.add(displayData); + } + + archiveInfoMap.get(archiveName).get(categoryName) + .setDisplayDataList(displayDatas); + + if (SizeJob.this.getState() == Job.NONE) { + SizeJob.this.schedule(); + } + } + + // System.out.println("xxx missingData"); + return Status.OK_STATUS; + } + + @Override + protected void canceling() { + // System.err.println("canceling MissingDataJob"); + shutdown.set(true); + } + } + } \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java index 14fa076a9c..4f6e103485 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java @@ -21,37 +21,37 @@ package com.raytheon.uf.viz.archive.ui; import java.util.ArrayList; import java.util.Calendar; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.ShellAdapter; +import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import com.raytheon.uf.common.archive.config.ArchiveConfig; import com.raytheon.uf.common.archive.config.ArchiveConfigManager; +import com.raytheon.uf.common.archive.config.ArchiveConstants; import com.raytheon.uf.common.archive.config.CategoryConfig; import com.raytheon.uf.common.archive.config.DisplayData; +import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException; import com.raytheon.uf.common.util.SizeUtil; import com.raytheon.uf.viz.archive.data.ArchiveInfo; import com.raytheon.uf.viz.archive.data.CategoryInfo; import com.raytheon.uf.viz.archive.data.IArchiveTotals; +import com.raytheon.uf.viz.archive.data.IRetentionHour; import com.raytheon.uf.viz.archive.data.IUpdateListener; import com.raytheon.uf.viz.archive.data.SizeJob; -import com.raytheon.uf.viz.archive.data.SizeJobRequest; -import com.raytheon.uf.viz.archive.ui.ArchiveTableComp.TableType; import com.raytheon.uf.viz.core.VizApp; import com.raytheon.viz.ui.dialogs.CaveSWTDialog; @@ -68,7 +68,9 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * ------------ ---------- ----------- -------------------------- * May 30, 2013 1965 bgonzale Initial creation * Jun 10, 2013 1966 rferrel Change to allow Case Creation to extend. - * + * Jul 24, 2013 2220 rferrel Changes to queue size request for all data. + * Aug 01, 2013 2221 rferrel Changes for select configuration. + * Aug 06, 2013 2222 rferrel Changes to display all selected data. * * * @author bgonzale @@ -76,7 +78,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; */ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements - IArchiveTotals, IUpdateListener { + IArchiveTotals, IUpdateListener, IModifyListener, IRetentionHour { /** Table composite that holds the table controls. */ private ArchiveTableComp tableComp; @@ -87,8 +89,8 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements /** Category combo box. */ private Combo categoryCbo; - /** Information for populating the various table displays. */ - protected final Map archiveInfoMap = new HashMap(); + /** Data manager. */ + protected ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); /** * Boolean to indicate when DisplayData is created should its selection be @@ -99,7 +101,7 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements /** * Must be set by sub-class prior to creating table. */ - protected TableType tableType; + protected ArchiveConstants.Type type; /** * Job that computes sizes of table row entries off the UI thread. @@ -109,6 +111,21 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements /** Keeps track of when it is safe to clear the busy cursor. */ protected final AtomicInteger busyCnt = new AtomicInteger(0); + /** Performs save action button. */ + protected Button saveBtn; + + /** Optional button to toggle displaying all selected or category */ + protected Button showSelectedBtn; + + /** Flag set when user wants to close with unsaved modifications. */ + protected boolean closeFlag = false; + + /** Current select (case/retention) loaded into the dialog. */ + protected String selectName = ArchiveConstants.defaultSelectName; + + /** Which table is being displayed. */ + private boolean showingSelected = true; + /** * @param parentShell */ @@ -133,23 +150,6 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements super(parentShell, style, caveStyle); } - public List getAllSelected() { - List allSelected = new ArrayList(); - for (String archiveName : archiveInfoMap.keySet()) { - ArchiveInfo archiveInfo = archiveInfoMap.get(archiveName); - for (String categoryName : archiveInfo.getCategoryNames()) { - CategoryInfo categoryInfo = archiveInfo.get(categoryName); - for (DisplayData displayData : categoryInfo - .getDisplayDataList()) { - if (displayData.isSelected()) { - allSelected.add(displayData); - } - } - } - } - return allSelected; - } - /** * @return the name of the currently selected archive in the dialog; null if * none found @@ -203,6 +203,11 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements */ protected abstract void setTotalSizeText(String sizeStringText); + /** + * This method is called by the AbstractArchiveDlg to set total Size. + * + * @param totalSize + */ protected abstract void setTotalSelectedItems(int totalSize); /** @@ -265,6 +270,18 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements return comboComp; } + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org + * .eclipse.swt.widgets.Shell) + */ + @Override + protected void initializeComponents(Shell shell) { + ArchiveConfigManager.getInstance().reset(); + } + /* * (non-Javadoc) * @@ -274,42 +291,55 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements protected void preOpened() { super.preOpened(); setCursorBusy(true); + populateComboBoxes(); + String titleName = initDisplayData(); + setSelectName(titleName); + populateTableComp(); + setCursorBusy(false); + + addModifiedListener(this); + shell.addShellListener(new ShellAdapter() { - // Setup to display blank dialog with busy cursor while getting data. - Job job = new Job("setup") { @Override - protected IStatus run(IProgressMonitor monitor) { - if (!shell.isDisposed()) { - VizApp.runAsync(new Runnable() { - - @Override - public void run() { - populateComboBoxes(); - setCursorBusy(false); - } - }); + public void shellClosed(ShellEvent e) { + if (closeFlag || !isModified()) { + return; } - initDisplayData(); - if (!shell.isDisposed()) { - VizApp.runAsync(new Runnable() { - @Override - public void run() { - updateTableComp(); + e.doit = false; + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + if (verifyClose()) { + close(); } - }); - } - return Status.OK_STATUS; + } + }); } - }; - job.schedule(); + }); + } + + /** + * Change the select name and update the dialog's title. Assumes the + * sub-classes places a hyphen at the end of the string when setting the + * dialog's title. + * + * @param selectName + */ + protected void setSelectName(String selectName) { + this.selectName = selectName; + StringBuilder sb = new StringBuilder(getText()); + sb.setLength(sb.indexOf("-") + 1); + sb.append(" ").append(selectName); + setText(sb.toString()); } /** * Create the table control. */ protected void createTable() { - tableComp = new ArchiveTableComp(shell, tableType, this); + tableComp = new ArchiveTableComp(shell, type, this, sizeJob); sizeJob.addUpdateListener(this); } @@ -335,7 +365,6 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements * Initial population up of the combo boxes. */ private void populateComboBoxes() { - ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); boolean doSelect = false; for (String archiveName : manager.getArchiveDataNamesList()) { archCfgCbo.add(archiveName); @@ -344,7 +373,7 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements if (doSelect) { archCfgCbo.select(0); - archiveComboSelection(); + initCategoryCbo(); } } @@ -358,10 +387,13 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements /** * Populate the category combo based on the archive name and populate the * table. - * - * @param archiveName */ private void populateCategoryCbo() { + initCategoryCbo(); + categoryComboSelection(); + } + + private void initCategoryCbo() { String archiveName = getSelectedArchiveName(); ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); categoryCbo.removeAll(); @@ -369,7 +401,6 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements categoryCbo.add(categoryName); } categoryCbo.select(0); - categoryComboSelection(); } /** @@ -383,32 +414,39 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements * Set up all display data and queue getting sizes for any that are * selected. */ - private void initDisplayData() { - ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); - Calendar startCal = getStart(); - Calendar endCal = getEnd(); - String[] archiveNames = manager.getArchiveDataNamesList(); - for (String archiveName : archiveNames) { - ArchiveInfo archiveInfo = new ArchiveInfo(); - archiveInfoMap.put(archiveName, archiveInfo); - String[] categoryNames = manager.getCategoryNames(manager - .getArchive(archiveName)); - for (String categoryName : categoryNames) { - List displayDatas = manager.getDisplayData( - archiveName, categoryName, setSelect); - CategoryInfo categoryInfo = new CategoryInfo(archiveName, - categoryName, displayDatas); - archiveInfo.add(categoryInfo); - for (DisplayData displayData : displayDatas) { - if (displayData.isSelected()) { - sizeJob.queue(new SizeJobRequest(displayData, startCal, - endCal)); - } - } - } + protected String initDisplayData() { + String displayArchive = getSelectedArchiveName(); + String displayCategory = getSelectedCategoryName(); + String selectedName = sizeJob.initData(type, null, displayArchive, + displayCategory, this); + sizeJob.resetTime(getStart(), getEnd()); + return selectedName; + } + + /** + * Delete a select configuration file. + * + * @param selectName + */ + protected void deleteSelect(String selectName) { + String fileName = ArchiveConstants.selectFileName(type, selectName); + try { + manager.deleteSelection(fileName); + } catch (LocalizationOpFailedException e) { + MessageDialog.openError(shell, "Case Error", + "Unable to delete file: " + fileName); } } + /** + * Load a select configuration file. + * + * @param selectName + */ + protected void loadSelect(String selectName) { + sizeJob.loadSelect(selectName, type); + } + /** * Populate the table based on the currently selected archive, category and * adjust sizes on the display table. @@ -416,33 +454,20 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements protected void populateTableComp() { String archiveName = getSelectedArchiveName(); String categoryName = getSelectedCategoryName(); - Calendar startCal = getStart(); - Calendar endCal = getEnd(); setCursorBusy(true); try { - sizeJob.clearQueue(); + setShowingSelected(false); - ArchiveInfo archiveInfo = archiveInfoMap.get(archiveName); - - // Not yet populated by background job. - if (archiveInfo == null) { - return; + List displayDatas = sizeJob.changeDisplay(archiveName, + categoryName); + if (displayDatas != null) { + tableComp + .populateTable(archiveName, categoryName, displayDatas); + } else { + tableComp.refresh(); } - - // Not yet populated by background job. - CategoryInfo categoryInfo = archiveInfo.get(categoryName); - if (categoryInfo == null) { - return; - } - - for (DisplayData displayData : categoryInfo.getDisplayDataList()) { - sizeJob.queue(new SizeJobRequest(displayData, startCal, endCal)); - } - sizeJob.requeueSelected(startCal, endCal); - - tableComp.populateTable(categoryInfo.getDisplayDataList()); } finally { setCursorBusy(false); } @@ -474,8 +499,8 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements long totalSize = 0; int totalSelected = 0; - for (String archiveName : archiveInfoMap.keySet()) { - ArchiveInfo archiveInfo = archiveInfoMap.get(archiveName); + for (String archiveName : sizeJob.getArchiveNames()) { + ArchiveInfo archiveInfo = sizeJob.get(archiveName); for (String categoryName : archiveInfo.getCategoryNames()) { CategoryInfo categoryInfo = archiveInfo.get(categoryName); for (DisplayData displayData : categoryInfo @@ -506,6 +531,75 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements setTotalSelectedItems(totalSelected); } + /** + * Creates the showSelectedBtn for sub-classes. + * + * @param actionControlComp + */ + protected void createShowingSelectedBtn(Composite actionControlComp) { + showSelectedBtn = new Button(actionControlComp, SWT.PUSH); + setShowingSelected(false); + showSelectedBtn.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + handelShowSelectAll(); + } + }); + } + + /** + * Populate the table with the desired display. + */ + protected void handelShowSelectAll() { + if (showingSelected) { + populateTableComp(); + } else { + populateSelectAllTable(); + } + } + + /** + * Sets the state for the showing selected flag and updates the label for + * the show selected button. + * + * @param state + */ + private void setShowingSelected(boolean state) { + if (showSelectedBtn != null && !showSelectedBtn.isDisposed()) { + if (showingSelected != state) { + showingSelected = state; + if (showingSelected) { + showSelectedBtn.setText(" Category "); + showSelectedBtn + .setToolTipText("Change display to show category."); + } else { + showSelectedBtn.setText(" Selected "); + showSelectedBtn + .setToolTipText("Change display to show all case selections"); + } + } + } + } + + /** + * Up date the table to display all selected data. + */ + private void populateSelectAllTable() { + setCursorBusy(true); + + try { + setShowingSelected(true); + List selectedData = sizeJob.changeDisplayAll(); + + if (selectedData != null) { + tableComp.populateSelectAll(selectedData); + } + } finally { + setCursorBusy(false); + } + } + /* * (non-Javadoc) * @@ -513,18 +607,26 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements * com.raytheon.uf.viz.archive.data.IUpdateListener#update(java.util.List) */ @Override - public void update(List dirInfos) { - final List displayDatas = new ArrayList( - dirInfos.size()); - for (SizeJobRequest request : dirInfos) { - displayDatas.add(request.getDisplayData()); + public void update(final List displayDatas) { + final List myDisplayDatas = new ArrayList( + displayDatas.size()); + for (DisplayData data : displayDatas) { + String label = data.getDisplayLabel(); + for (DisplayData displayData : sizeJob.get(data.getArchiveName()) + .get(data.getCategoryName()).getDisplayDataList()) { + if (label.equals(displayData.getDisplayLabel())) { + displayData.setSize(data.getSize()); + myDisplayDatas.add(displayData); + break; + } + } } VizApp.runAsync(new Runnable() { @Override public void run() { - tableComp.updateSize(displayDatas); + tableComp.updateSize(myDisplayDatas); updateTotals(null); } }); @@ -546,6 +648,16 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements tableComp.addModifiedListener(iModifyListener); } + /** + * Get the data information on all selected items; not just the currently + * displayed table. + * + * @return selectedDatas + */ + protected List getSelectedData() { + return sizeJob.getSelectAll(); + } + /** * Remove modification listener. * @@ -555,15 +667,70 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements tableComp.removeModifiedListener(iModifyListener); } - /* - * (non-Javadoc) - * - * @see - * com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org - * .eclipse.swt.widgets.Shell) + /** + * Reset all data to unknown size, and queue request for sizes. */ - @Override - protected void initializeComponents(Shell shell) { - ArchiveConfigManager.getInstance().reset(); + protected void resetSizes() { + sizeJob.recomputeSize(); + populateTableComp(); + } + + /** + * Allows a sub-class to set the start and end times based on the off set. + * + * @param startTimeOffset + */ + public void setRetentionTimes(long startTimeOffset) { + // do nothing override by sub-classes + } + + /** + * Indicate unsaved user changes. + * + * @return modified + */ + protected boolean isModified() { + return (saveBtn != null) && !saveBtn.isDisposed() + && saveBtn.isEnabled(); + } + + /** + * Save current selections of the select configuration file. + * + * @param selectName + * @return true when save is successful + */ + protected boolean saveSelection(String selectName) { + Calendar start = getStart(); + Calendar end = getEnd(); + long startRetentionMS = 0L; + if (start != null && end != null) { + startRetentionMS = end.getTimeInMillis() - start.getTimeInMillis(); + } + String errorMsg = sizeJob + .saveSelect(selectName, type, startRetentionMS); + if (errorMsg != null) { + MessageDialog.openError(shell, type + " Selection Error", errorMsg); + } + + return errorMsg == null; + } + + /** + * When unsaved modifications this asks the user to verify the close. + * + * @return true when okay to close. + */ + protected boolean verifyClose() { + boolean state = true; + if (isModified()) { + MessageBox box = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK + | SWT.CANCEL); + box.setText("Close " + type); + box.setMessage("Unsave changes.\nSelect OK to discard changes."); + state = box.open() == SWT.OK; + } + closeFlag = state; + return state; } } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveRetentionDlg.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveRetentionDlg.java index da330f8028..6072a5e10c 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveRetentionDlg.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveRetentionDlg.java @@ -25,8 +25,6 @@ import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.ShellAdapter; -import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; @@ -34,15 +32,12 @@ import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Layout; -import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Spinner; -import com.raytheon.uf.common.archive.config.ArchiveConfigManager; +import com.raytheon.uf.common.archive.config.ArchiveConstants.Type; import com.raytheon.uf.common.archive.config.DisplayData; -import com.raytheon.uf.viz.archive.data.IArchiveTotals; -import com.raytheon.uf.viz.archive.ui.ArchiveTableComp.TableType; -import com.raytheon.uf.viz.core.VizApp; +import com.raytheon.uf.common.time.util.TimeUtil; /** * Archive retention dialog. @@ -56,14 +51,18 @@ import com.raytheon.uf.viz.core.VizApp; * May 23, 2013 #1964 lvenable Initial creation * May 31, 2013 #1965 bgonzale Initial work for updating retention configurations. * Jun 10, 2013 #1966 rferrel Implemented hooks to get display and save to work. + * Jul 24, 2013 #2220 rferrel Add recompute size button. + * Jul 24, 2013 #2221 rferrel Changes for select configuration. + * Aug 26, 2013 #2225 rferrel Make dialog perspective independent. + * Oct 01, 2013 #2147 rferrel Change getEnd() to pick up files with future time stamps. + * Oct 07, 2013 #2438 rferrel Properly save and load retention times. * * * * @author lvenable * @version 1.0 */ -public class ArchiveRetentionDlg extends AbstractArchiveDlg implements - IArchiveTotals, IModifyListener { +public class ArchiveRetentionDlg extends AbstractArchiveDlg { /** Current Archive/Category selection's minimum retention hours. */ private RetentionHours minRetention; @@ -77,11 +76,18 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements /** Displays the total size of selected items. */ private Label totalSizeLbl; - /** Performs save action button. */ - private Button saveBtn; + /** Flag to indicate when retention hours are modified. */ + private boolean retentionHoursAreModified = false; - /** Flag set when user wants to close with unsaved modifications. */ - boolean closeFlag = false; + /** Modification listener for the retention hours components. */ + private final IModifyListener retentionHoursModifyListener = new IModifyListener() { + + @Override + public void modified() { + saveBtn.setEnabled(true); + retentionHoursAreModified = true; + } + }; /** * Constructor. @@ -91,9 +97,9 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements */ public ArchiveRetentionDlg(Shell parentShell) { super(parentShell, SWT.DIALOG_TRIM | SWT.MIN, CAVE.DO_NOT_BLOCK - | CAVE.MODE_INDEPENDENT | CAVE.INDEPENDENT_SHELL); - this.setSelect = true; - this.tableType = TableType.Retention; + | CAVE.MODE_INDEPENDENT | CAVE.INDEPENDENT_SHELL + | CAVE.PERSPECTIVE_INDEPENDENT); + this.type = Type.Retention; } /* @@ -120,7 +126,7 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements @Override protected void initializeComponents(Shell shell) { super.initializeComponents(shell); - setText("Archive Retention"); + setText("Archive Retention -"); Composite mainComp = new Composite(shell, SWT.NONE); GridLayout gl = new GridLayout(1, false); gl.marginHeight = 0; @@ -186,7 +192,7 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements return state; } }; - minRetention.addModifyListener(this); + minRetention.addModifyListener(retentionHoursModifyListener); /* * Bottom row of controls. @@ -216,7 +222,7 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements return state; } }; - extRetention.addModifyListener(this); + extRetention.addModifyListener(retentionHoursModifyListener); } /** @@ -225,37 +231,31 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements private void createBottomActionButtons() { Composite actionControlComp = new Composite(shell, SWT.NONE); - GridLayout gl = new GridLayout(2, false); + GridLayout gl = new GridLayout(3, false); GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); actionControlComp.setLayout(gl); actionControlComp.setLayoutData(gd); - // TODO - For the future ? - // Button calcSizeBtn = new Button(actionControlComp, SWT.PUSH); - // calcSizeBtn.setText(" Calculate Sizes "); - // calcSizeBtn.addSelectionListener(new SelectionAdapter() { - // @Override - // public void widgetSelected(SelectionEvent e) { - // // TODO : add calculate size functionality - // // With Roger's automated size calculation code, this doesn't - // // seem relevant unless it is for calculating compressed size - // } - // }); - saveBtn = new Button(actionControlComp, SWT.PUSH); saveBtn.setText(" Save "); saveBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent selectionEvent) { - ArchiveConfigManager manager = ArchiveConfigManager - .getInstance(); - manager.save(); - saveBtn.setEnabled(false); - clearModified(); + saveAction(); } }); saveBtn.setEnabled(false); + Button sizeBtn = new Button(actionControlComp, SWT.PUSH); + sizeBtn.setText(" Recompute Sizes "); + sizeBtn.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + resetSizes(); + } + }); + gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false); Button closeBtn = new Button(actionControlComp, SWT.PUSH); closeBtn.setText(" Close "); @@ -273,21 +273,15 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements } /** - * When unsaved modifications this asks the user to verify the close. - * - * @return true when okay to close. + * Save button action. */ - private boolean verifyClose() { - boolean state = true; - if (isModified()) { - MessageBox box = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK - | SWT.CANCEL); - box.setText("Close Retention"); - box.setMessage("Unsave changes.\nSelect OK to continue."); - state = box.open() == SWT.OK; + private void saveAction() { + saveSelection(selectName); + saveBtn.setEnabled(false); + if (retentionHoursAreModified) { + manager.save(); } - closeFlag = state; - return state; + clearModified(); } /* @@ -337,7 +331,10 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements @Override protected Calendar getEnd() { // display all elements so no end bound - return null; + Calendar endCal = TimeUtil.newCalendar(); + // Back off an hour so latter rounding doesn't cause overflow. + endCal.setTimeInMillis(Long.MAX_VALUE - TimeUtil.MILLIS_PER_HOUR); + return endCal; } /* @@ -402,6 +399,20 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements super.clearModified(); minRetention.clearModified(); extRetention.clearModified(); + retentionHoursAreModified = false; + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.viz.archive.ui.AbstractArchiveDlg#disposed() + */ + @Override + protected void disposed() { + minRetention.removeModifyListener(retentionHoursModifyListener); + extRetention.removeModifyListener(retentionHoursModifyListener); + removeModifiedListener(this); + super.disposed(); } /* @@ -412,49 +423,7 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements @Override protected void preOpened() { super.preOpened(); - addModifiedListener(this); - shell.addShellListener(new ShellAdapter() { - - @Override - public void shellClosed(ShellEvent e) { - if (closeFlag || !isModified()) { - return; - } - - e.doit = false; - VizApp.runAsync(new Runnable() { - - @Override - public void run() { - if (verifyClose()) { - close(); - } - } - }); - } - }); - } - - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.viz.archive.ui.AbstractArchiveDlg#disposed() - */ - @Override - protected void disposed() { - minRetention.removeModifyListener(this); - extRetention.removeModifyListener(this); - removeModifiedListener(this); - super.disposed(); - } - - /** - * Indicate unsaved user changes. - * - * @return modified - */ - private boolean isModified() { - return (saveBtn != null) && !saveBtn.isDisposed() - && saveBtn.isEnabled(); + archiveComboSelection(); + categoryComboSelection(); } } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveTableComp.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveTableComp.java index 740642beae..fab9434476 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveTableComp.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveTableComp.java @@ -42,9 +42,12 @@ import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; +import com.raytheon.uf.common.archive.config.ArchiveConstants; +import com.raytheon.uf.common.archive.config.ArchiveConstants.Type; import com.raytheon.uf.common.archive.config.DisplayData; import com.raytheon.uf.common.util.SizeUtil; import com.raytheon.uf.viz.archive.data.IArchiveTotals; +import com.raytheon.uf.viz.archive.data.SizeJob; /** * Archive table composite that contains the SWT table. @@ -56,6 +59,10 @@ import com.raytheon.uf.viz.archive.data.IArchiveTotals; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * May 23, 2013 #1964 lvenable Initial creation + * Jul 24, 2013 #2221 rferrel Changes for select configuration. + * Aug 06, 2013 #2222 rferrel Changes to display all selected data. + * Aug 14, 2013 #2220 rferrel Add refresh method. + * Aug 26, 2013 #2225 rferrel Add missing updates. * * * @@ -70,6 +77,14 @@ public class ArchiveTableComp extends Composite { /** Column to display size information,. */ private final int SIZE_COL_INDEX = 1; + private boolean showSelectAll = false; + + /** Name of table's archive. */ + String archiveName; + + /** Name of table's category. */ + String categoryName; + /** Table control. */ private Table table; @@ -82,13 +97,11 @@ public class ArchiveTableComp extends Composite { /** Size label. */ private Label sizeLbl; - /** Table type enumeration. */ - public enum TableType { - Retention, Case - }; + /** Composite for holding the table */ + Composite tblComp; - /** Current table type. */ - private final TableType type; + /** The dialog's type. */ + private final ArchiveConstants.Type type; /** Allows the parent dialog log to update other total displays. */ private final IArchiveTotals iArchiveTotals; @@ -106,6 +119,11 @@ public class ArchiveTableComp extends Composite { */ private final List modifiedListeners = new CopyOnWriteArrayList(); + /** + * Use to update the selections for size job queues. + */ + private final SizeJob sizeJob; + /** * Constructor. * @@ -114,12 +132,13 @@ public class ArchiveTableComp extends Composite { * @param type * Table type. */ - public ArchiveTableComp(Composite parent, TableType type, - IArchiveTotals iTotalSelectedSize) { + public ArchiveTableComp(Composite parent, Type type, + IArchiveTotals iTotalSelectedSize, SizeJob sizeJob) { super(parent, 0); this.type = type; this.iArchiveTotals = iTotalSelectedSize; + this.sizeJob = sizeJob; init(); } @@ -137,7 +156,7 @@ public class ArchiveTableComp extends Composite { createTable(); - if (type != TableType.Retention) { + if (type != Type.Retention) { createTableLabels(); } } @@ -148,11 +167,20 @@ public class ArchiveTableComp extends Composite { private void createTable() { GridData gd = null; - table = new Table(this, SWT.CHECK | SWT.BORDER | SWT.V_SCROLL - | SWT.H_SCROLL | SWT.MULTI | SWT.VIRTUAL); + tblComp = new Composite(this, SWT.NONE); + GridLayout gl = new GridLayout(1, false); + gl.marginHeight = 0; + gl.marginWidth = 0; + gl.horizontalSpacing = 0; + tblComp.setLayout(gl); gd = new GridData(SWT.FILL, SWT.DEFAULT, true, true); gd.widthHint = 730; gd.heightHint = 270; + tblComp.setLayoutData(gd); + + table = new Table(tblComp, SWT.CHECK | SWT.BORDER | SWT.V_SCROLL + | SWT.H_SCROLL | SWT.MULTI | SWT.VIRTUAL); + gd = new GridData(SWT.FILL, SWT.FILL, true, true); table.setLayoutData(gd); table.setHeaderVisible(true); table.setLinesVisible(true); @@ -163,8 +191,15 @@ public class ArchiveTableComp extends Composite { TableItem item = (TableItem) event.item; int index = table.indexOf(item); DisplayData displayData = tableData[index]; - item.setText(new String[] { displayData.getDisplayLabel(), - displayData.getSizeLabel() }); + String label = null; + if (showSelectAll) { + label = displayData.getArchiveName() + " | " + + displayData.getCategoryName() + " | " + + displayData.getDisplayLabel(); + } else { + label = displayData.getDisplayLabel(); + } + item.setText(new String[] { label, displayData.getSizeLabel() }); item.setChecked(displayData.isSelected()); } }); @@ -173,9 +208,9 @@ public class ArchiveTableComp extends Composite { pathColumn.setText("Label"); TableColumn sizeColumn = new TableColumn(table, SWT.CENTER); - if (type == TableType.Retention) { + if (type == Type.Retention) { sizeColumn.setText("Current Size"); - } else if (type == TableType.Case) { + } else if (type == Type.Case) { sizeColumn.setText("Size"); } @@ -285,7 +320,7 @@ public class ArchiveTableComp extends Composite { TableItem item = table.getItem(index); if (item.getChecked()) { ++count; - displayData.setSelected(true); + sizeJob.setSelect(displayData, true); if (tableTotalSize >= 0) { long diSize = displayData.getSize(); if (diSize < 0) { @@ -295,7 +330,7 @@ public class ArchiveTableComp extends Composite { } } } else { - displayData.setSelected(false); + sizeJob.setSelect(displayData, false); } } List displayDatas = Arrays.asList(tableData); @@ -422,12 +457,31 @@ public class ArchiveTableComp extends Composite { } /** - * Set up table with values in the list. + * Update table display to show data for the desired category. * * @param displayDatas */ - protected void populateTable(List displayDatas) { + protected void populateTable(String archiveName, String categoryName, + List displayDatas) { + showSelectAll = false; + table.getColumn(0).setText("Label"); + populateTable(displayDatas); + } + + /** + * Flag table as showing all selected data and update display. + * + * @param displayDatas + */ + protected void populateSelectAll(List displayDatas) { + showSelectAll = true; + table.getColumn(0).setText("Archive | Category | Label"); + populateTable(displayDatas); + } + + private void populateTable(List displayDatas) { tableData = displayDatas.toArray(new DisplayData[0]); + Arrays.sort(tableData, DisplayData.LABEL_ORDER); table.removeAll(); table.setItemCount(tableData.length); @@ -440,6 +494,15 @@ public class ArchiveTableComp extends Composite { table.setSortColumn(table.getColumn(LABEL_COL_INDEX)); table.setSortDirection(SWT.UP); table.clearAll(); + updateSelectionLabels(); + } + + /** + * Update the current tables display. + */ + public void refresh() { + table.clearAll(); + updateSelectionLabels(); } /** diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreateException.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreateException.java new file mode 100644 index 0000000000..65fae23052 --- /dev/null +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreateException.java @@ -0,0 +1,69 @@ +/** + * 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.viz.archive.ui; + +/** + * Exception to use when problem creating a case. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 22, 2013 2225       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public class CaseCreateException extends Exception { + static final long serialVersionUID = 0L; + + /** + * + */ + public CaseCreateException() { + } + + /** + * @param message + */ + public CaseCreateException(String message) { + super(message); + } + + /** + * @param cause + */ + public CaseCreateException(Throwable cause) { + super(cause); + } + + /** + * @param message + * @param cause + */ + public CaseCreateException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreationDlg.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreationDlg.java index 76a6c8b316..2f7ccf2f82 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreationDlg.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreationDlg.java @@ -21,11 +21,11 @@ package com.raytheon.uf.viz.archive.ui; import java.io.File; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; +import org.apache.commons.io.FileUtils; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.dialogs.MessageDialog; @@ -38,7 +38,6 @@ import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Display; @@ -46,17 +45,11 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Layout; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Spinner; +import com.raytheon.uf.common.archive.config.ArchiveConstants.Type; import com.raytheon.uf.common.archive.config.DisplayData; import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.util.SizeUtil; -import com.raytheon.uf.viz.archive.data.ArchiveInfo; -import com.raytheon.uf.viz.archive.data.CategoryInfo; -import com.raytheon.uf.viz.archive.data.IArchiveTotals; -import com.raytheon.uf.viz.archive.data.IUpdateListener; -import com.raytheon.uf.viz.archive.data.SizeJobRequest; -import com.raytheon.uf.viz.archive.ui.ArchiveTableComp.TableType; import com.raytheon.uf.viz.core.VizApp; import com.raytheon.viz.ui.dialogs.AwipsCalendar; import com.raytheon.viz.ui.dialogs.ICloseCallback; @@ -74,14 +67,17 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback; * May 23, 2013 #1964 lvenable Initial creation * Jun 10, 2013 #1966 rferrel Implemented back in hooks for display * and generation of cases. + * Jul 24, 2013 #2220 rferrel Add recompute size button. + * Jul 24, 2013 #2221 rferrel Changes for select configuration. + * Aug 06, 2013 #2222 rferrel Changes to display all selected data. + * Aug 26, 2013 #2225 rferrel Make perspective independent and no longer modal. * * * * @author lvenable * @version 1.0 */ -public class CaseCreationDlg extends AbstractArchiveDlg implements - IArchiveTotals, IUpdateListener { +public class CaseCreationDlg extends AbstractArchiveDlg { /** Start time label. */ private Label startTimeLbl; @@ -104,17 +100,30 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements /** Compression check box. */ private Button compressChk; - /** Break files check box. */ - private Button breakFilesChk; + // TODO restore when Multi-file implemented. + // /** Break files check box. */ + // private Button breakFilesChk; - /** File size spinner control. */ - private Spinner fileSizeSpnr; + /** Button to save new select case configuration. */ + private Button saveAsBtn; - /** File size combo box. */ - private Combo fileSizeCbo; + /** Button to load select case configuration. */ + private Button loadBtn; - /** Maximum file size label. */ - private Label maxFileSizeLbl; + /** Button to delete select case configuration. */ + private Button deleteBtn; + + // TODO restore when Multi-file implemented. + // /** File size spinner control. */ + // private Spinner fileSizeSpnr; + + // TODO restore when Multi-file implemented. + // /** File size combo box. */ + // private Combo fileSizeCbo; + + // TODO restore when Multi-file implemented. + // /** Maximum file size label. */ + // private Label maxFileSizeLbl; /** Directory location label. */ private Label locationLbl; @@ -138,6 +147,21 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements /** Number of selected items. */ private int selectedItemsSize = 0; + /** Dialog to create new select case. */ + private CaseLoadSaveDeleteDlg saveAsDlg; + + /** Dialog to load a select case. */ + private CaseLoadSaveDeleteDlg loadDlg; + + /** Dialog to delete a select case. */ + private CaseLoadSaveDeleteDlg deleteDlg; + + /** Allow only single instance of dialog. */ + private CaseNameDialog caseNameDlg; + + /** Allow only single instance of dialog. */ + private GenerateCaseDlg generateCaseDlg; + /** * Constructor. * @@ -146,9 +170,11 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements */ public CaseCreationDlg(Shell parentShell) { super(parentShell, SWT.DIALOG_TRIM | SWT.MIN, CAVE.DO_NOT_BLOCK - | CAVE.MODE_INDEPENDENT | CAVE.INDEPENDENT_SHELL); + | CAVE.PERSPECTIVE_INDEPENDENT | CAVE.MODE_INDEPENDENT + | CAVE.INDEPENDENT_SHELL); + this.type = Type.Case; this.setSelect = false; - this.tableType = TableType.Case; + this.type = Type.Case; } /* @@ -176,7 +202,7 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements @Override protected void initializeComponents(Shell shell) { super.initializeComponents(shell); - setText("Archive Case Creation"); + setText("Archive Case Creation -"); Composite mainComp = new Composite(shell, SWT.NONE); GridLayout gl = new GridLayout(1, false); gl.marginHeight = 0; @@ -238,13 +264,29 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements gd = new GridData(220, SWT.DEFAULT); endTimeLbl = new Label(timeComp, SWT.BORDER); endTimeLbl.setLayoutData(gd); + } + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.viz.archive.ui.AbstractArchiveDlg#setRetentionTimes(long) + */ + @Override + public void setRetentionTimes(long startRetentionHours) { + long startTimeOffset = startRetentionHours * TimeUtil.MILLIS_PER_HOUR; endDate = TimeUtil.newDate(); long time = endDate.getTime(); - time -= TimeUtil.MILLIS_PER_DAY; + time -= startTimeOffset; startDate = new Date(time); - startTimeLbl.setText(dateFmt.format(startDate)); - endTimeLbl.setText(dateFmt.format(endDate)); + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + startTimeLbl.setText(dateFmt.format(startDate)); + endTimeLbl.setText(dateFmt.format(endDate)); + } + }); } /** @@ -330,58 +372,60 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements */ compressChk = new Button(compressionComp, SWT.CHECK); compressChk.setText("Compress Files"); - compressChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - handleCompressSelection(); - } - }); + // TODO restore when Multi-file implemented. + // compressChk.addSelectionListener(new SelectionAdapter() { + // @Override + // public void widgetSelected(SelectionEvent e) { + // handleCompressSelection(); + // } + // }); - gd = new GridData(); - gd.horizontalIndent = 20; - breakFilesChk = new Button(compressionComp, SWT.CHECK); - breakFilesChk.setText("Break into multiple files"); - breakFilesChk.setLayoutData(gd); - breakFilesChk.setEnabled(false); - breakFilesChk.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - handleBreakFilesSelection(breakFilesChk.getSelection()); - } - }); + // TODO restore when Multi-file implemented. + // gd = new GridData(); + // gd.horizontalIndent = 20; + // breakFilesChk = new Button(compressionComp, SWT.CHECK); + // breakFilesChk.setText("Break into multiple files"); + // breakFilesChk.setLayoutData(gd); + // breakFilesChk.setEnabled(false); + // breakFilesChk.addSelectionListener(new SelectionAdapter() { + // @Override + // public void widgetSelected(SelectionEvent e) { + // handleBreakFilesSelection(breakFilesChk.getSelection()); + // } + // }); - Composite maxFileSizeComp = new Composite(compressionComp, SWT.NONE); - gl = new GridLayout(3, false); - gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); - gd.horizontalIndent = 20; - maxFileSizeComp.setLayout(gl); - maxFileSizeComp.setLayoutData(gd); - - maxFileSizeLbl = new Label(maxFileSizeComp, SWT.NONE); - maxFileSizeLbl.setText("Max File Size: "); - maxFileSizeLbl.setEnabled(false); - - gd = new GridData(60, SWT.DEFAULT); - fileSizeSpnr = new Spinner(maxFileSizeComp, SWT.BORDER); - fileSizeSpnr.setIncrement(1); - fileSizeSpnr.setPageIncrement(50); - fileSizeSpnr.setMaximum(2000); - fileSizeSpnr.setMinimum(500); - fileSizeSpnr.setLayoutData(gd); - fileSizeSpnr.setEnabled(false); - - fileSizeCbo = new Combo(maxFileSizeComp, SWT.VERTICAL | SWT.DROP_DOWN - | SWT.BORDER | SWT.READ_ONLY); - fileSizeCbo.setEnabled(false); - fileSizeCbo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - handleFileSizeChangeSelection(); - } - }); - fileSizeCbo.add("MB"); - fileSizeCbo.add("GB"); - fileSizeCbo.select(0); + // Composite maxFileSizeComp = new Composite(compressionComp, SWT.NONE); + // gl = new GridLayout(3, false); + // gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + // gd.horizontalIndent = 20; + // maxFileSizeComp.setLayout(gl); + // maxFileSizeComp.setLayoutData(gd); + // + // maxFileSizeLbl = new Label(maxFileSizeComp, SWT.NONE); + // maxFileSizeLbl.setText("Max File Size: "); + // maxFileSizeLbl.setEnabled(false); + // + // gd = new GridData(60, SWT.DEFAULT); + // fileSizeSpnr = new Spinner(maxFileSizeComp, SWT.BORDER); + // fileSizeSpnr.setIncrement(1); + // fileSizeSpnr.setPageIncrement(50); + // fileSizeSpnr.setMaximum(2000); + // fileSizeSpnr.setMinimum(500); + // fileSizeSpnr.setLayoutData(gd); + // fileSizeSpnr.setEnabled(false); + // + // fileSizeCbo = new Combo(maxFileSizeComp, SWT.VERTICAL | SWT.DROP_DOWN + // | SWT.BORDER | SWT.READ_ONLY); + // fileSizeCbo.setEnabled(false); + // fileSizeCbo.addSelectionListener(new SelectionAdapter() { + // @Override + // public void widgetSelected(SelectionEvent e) { + // handleFileSizeChangeSelection(); + // } + // }); + // fileSizeCbo.add("MB"); + // fileSizeCbo.add("GB"); + // fileSizeCbo.select(0); } /** @@ -425,7 +469,7 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements private void createBottomActionButtons() { Composite actionControlComp = new Composite(shell, SWT.NONE); - GridLayout gl = new GridLayout(3, false); + GridLayout gl = new GridLayout(8, false); GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); actionControlComp.setLayout(gl); actionControlComp.setLayoutData(gd); @@ -441,6 +485,44 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements // } // }); + saveBtn = new Button(actionControlComp, SWT.PUSH); + saveBtn.setText(" Save "); + saveBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent selectionEvent) { + saveSelection(selectName); + clearModified(); + } + }); + saveBtn.setEnabled(false); + + saveAsBtn = new Button(actionControlComp, SWT.PUSH); + saveAsBtn.setText(" Save As... "); + saveAsBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent selectionEvent) { + handleSaveAsCase(); + } + }); + + loadBtn = new Button(actionControlComp, SWT.PUSH); + loadBtn.setText(" Load... "); + loadBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent selectionEvent) { + handleLoadCase(); + } + }); + + deleteBtn = new Button(actionControlComp, SWT.PUSH); + deleteBtn.setText(" Delete... "); + deleteBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent selectionEvent) { + handleDeleteCase(); + } + }); + generateBtn = new Button(actionControlComp, SWT.PUSH); generateBtn.setText(" Generate "); generateBtn.setEnabled(false); @@ -451,6 +533,18 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements } }); + createShowingSelectedBtn(actionControlComp); + + Button sizeBtn = new Button(actionControlComp, SWT.PUSH); + sizeBtn.setText(" Recompute Sizes "); + sizeBtn.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + resetSizes(); + } + }); + gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false); Button closeBtn = new Button(actionControlComp, SWT.PUSH); closeBtn.setText(" Close "); @@ -458,13 +552,91 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements closeBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - close(); + if (verifyClose()) { + close(); + } else { + e.doit = false; + } } }); } + private void handleSaveAsCase() { + if (saveAsDlg == null || saveAsDlg.isDisposed()) { + saveAsDlg = new CaseLoadSaveDeleteDlg(shell, + CaseLoadSaveDeleteDlg.Type.SaveAs); + saveAsDlg.setCloseCallback(new ICloseCallback() { + + @Override + public void dialogClosed(Object returnValue) { + if (returnValue instanceof String) { + String name = returnValue.toString(); + if (saveSelection(name)) { + clearModified(); + loadSelect(name); + setSelectName(name); + } + } + } + }); + saveAsDlg.open(); + } else { + saveAsDlg.bringToTop(); + } + } + + private void handleLoadCase() { + if (isModified() + && !MessageDialog.openConfirm(shell, "Case Confirmation", + "Unsave changes will be lost.\nPress OK to continue.")) { + return; + + } + if (loadDlg == null || loadDlg.isDisposed()) { + loadDlg = new CaseLoadSaveDeleteDlg(shell, + CaseLoadSaveDeleteDlg.Type.Load); + loadDlg.setCloseCallback(new ICloseCallback() { + + @Override + public void dialogClosed(Object returnValue) { + if (returnValue instanceof String) { + String name = returnValue.toString(); + loadSelect(name); + populateTableComp(); + updateTotals(null); + setSelectName(name); + clearModified(); + } + } + }); + loadDlg.open(); + } else { + loadDlg.bringToTop(); + } + } + + private void handleDeleteCase() { + if (deleteDlg == null || deleteDlg.isDisposed()) { + deleteDlg = new CaseLoadSaveDeleteDlg(shell, + CaseLoadSaveDeleteDlg.Type.Delete); + deleteDlg.setCloseCallback(new ICloseCallback() { + + @Override + public void dialogClosed(Object returnValue) { + if (returnValue instanceof String) { + String selectName = returnValue.toString(); + deleteSelect(selectName); + } + } + }); + deleteDlg.open(); + } else { + deleteDlg.bringToTop(); + } + } + /** - * Display modal dialog that performs the Generation of the case. + * Display dialog that performs the Generation of the case. */ private void generateCase() { setCursorBusy(true); @@ -475,50 +647,71 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements List displayDatas = getSelectedData(); boolean doCompress = compressChk.getSelection(); - boolean doMultiFiles = breakFilesChk.getSelection(); - int compressSize = fileSizeSpnr.getSelection(); - String sizeType = fileSizeCbo.getItem(fileSizeCbo.getSelectionIndex()); - // Assume Model dialog. - GenerateCaseDlg dialog = new GenerateCaseDlg(shell, targetDir, caseDir, - startCal, endCal, displayDatas, doCompress, doMultiFiles, - compressSize, sizeType); - dialog.addJobChangeListener(new JobChangeAdapter() { + // TODO restore once Multi-file implemented. + // boolean doMultiFiles = breakFilesChk.getSelection(); + // int compressSize = fileSizeSpnr.getSelection(); + // String sizeType = + // fileSizeCbo.getItem(fileSizeCbo.getSelectionIndex()); + boolean doMultiFiles = false; + int compressSize = 500; + String sizeType = "MB"; - @Override - public void done(IJobChangeEvent event) { - VizApp.runAsync(new Runnable() { - @Override - public void run() { - updateLocationState(); - } - }); + setCursorBusy(true); + if (generateCaseDlg == null || generateCaseDlg.isDisposed()) { + long splitSize = 0L; + if (doCompress && doMultiFiles) { + if (sizeType.equals("MB")) { + splitSize = compressSize * FileUtils.ONE_MB; + } else { + splitSize = compressSize * FileUtils.ONE_GB; + } } - }); - dialog.setCloseCallback(new ICloseCallback() { + generateCaseDlg = new GenerateCaseDlg(shell, targetDir, caseDir, + startCal, endCal, displayDatas, doCompress, doMultiFiles, + splitSize); + generateCaseDlg.addJobChangeListener(new JobChangeAdapter() { - @Override - public void dialogClosed(Object returnValue) { - setCursorBusy(false); - } - }); - dialog.open(); + @Override + public void done(IJobChangeEvent event) { + VizApp.runAsync(new Runnable() { + @Override + public void run() { + updateLocationState(); + setCursorBusy(false); + generateCaseDlg = null; + } + }); + } + }); + generateCaseDlg.setCloseCallback(new ICloseCallback() { - } - - /** - * Enable/Disable controls based on the compression check box. - */ - private void handleCompressSelection() { - if (compressChk.getSelection()) { - handleBreakFilesSelection(breakFilesChk.getSelection()); + @Override + public void dialogClosed(Object returnValue) { + setCursorBusy(false); + } + }); + generateCaseDlg.open(); } else { - handleBreakFilesSelection(false); + generateCaseDlg.bringToTop(); } - breakFilesChk.setEnabled(compressChk.getSelection()); } + // TODO restore when Multi-file implemented. + // /** + // * Enable/Disable controls based on the compression check box. + // */ + // private void handleCompressSelection() { + // if (compressChk.getSelection()) { + // handleBreakFilesSelection(breakFilesChk.getSelection()); + // } else { + // handleBreakFilesSelection(false); + // } + // + // breakFilesChk.setEnabled(compressChk.getSelection()); + // } + /** * Bring up modal dialog to get the case's directory name. */ @@ -531,35 +724,43 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements } File targetDir = (File) o; - // Assume modal dialog. - CaseNameDialog dialog = new CaseNameDialog(shell, targetDir); - dialog.setCloseCallback(new ICloseCallback() { - @Override - public void dialogClosed(Object returnValue) { - if (returnValue instanceof File) { - File caseDir = (File) returnValue; - String caseName = caseDir.getAbsolutePath(); - caseNameLbl.setText(caseName); - caseNameLbl.setData(caseDir); - checkGenerateButton(); + setCursorBusy(true); + if (caseNameDlg == null || caseNameDlg.isDisposed()) { + caseNameDlg = new CaseNameDialog(shell, targetDir); + caseNameDlg.setCloseCallback(new ICloseCallback() { + + @Override + public void dialogClosed(Object returnValue) { + if (returnValue instanceof File) { + File caseDir = (File) returnValue; + String caseName = caseDir.getAbsolutePath(); + caseNameLbl.setText(caseName); + caseNameLbl.setData(caseDir); + checkGenerateButton(); + } + caseNameDlg = null; + setCursorBusy(false); } - } - }); - dialog.open(); + }); + caseNameDlg.open(); + } else { + caseNameDlg.bringToTop(); + } } - /** - * Enable/Disable file size controls. - * - * @param enabled - * Enabled flag. - */ - private void handleBreakFilesSelection(boolean enabled) { - maxFileSizeLbl.setEnabled(enabled); - fileSizeSpnr.setEnabled(enabled); - fileSizeCbo.setEnabled(enabled); - } + // TODO restore when Multi-file implemented. + // /** + // * Enable/Disable file size controls. + // * + // * @param enabled + // * Enabled flag. + // */ + // private void handleBreakFilesSelection(boolean enabled) { + // maxFileSizeLbl.setEnabled(enabled); + // fileSizeSpnr.setEnabled(enabled); + // fileSizeCbo.setEnabled(enabled); + // } /** * Enables the generate button will user has entered all needed elements. @@ -571,35 +772,36 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements } } - /** - * Action performed when the file size has changed. - */ - private void handleFileSizeChangeSelection() { - /* - * If the same item was selected just return. - */ - if (fileSizeCbo.getItem(fileSizeCbo.getSelectionIndex()).equals( - (String) fileSizeCbo.getData())) { - return; - } - - if (fileSizeCbo.getItem(fileSizeCbo.getSelectionIndex()).equals("MB")) { - fileSizeSpnr.setIncrement(1); - fileSizeSpnr.setPageIncrement(50); - fileSizeSpnr.setMaximum(2000); - fileSizeSpnr.setMinimum(500); - fileSizeSpnr.setSelection(500); - } else { - fileSizeSpnr.setIncrement(1); - fileSizeSpnr.setPageIncrement(5); - fileSizeSpnr.setMinimum(1); - fileSizeSpnr.setMaximum(10); - fileSizeSpnr.setSelection(1); - } - - fileSizeCbo - .setData(fileSizeCbo.getItem(fileSizeCbo.getSelectionIndex())); - } + // TODO restore when Multi-file implemented. + // /** + // * Action performed when the file size has changed. + // */ + // private void handleFileSizeChangeSelection() { + // /* + // * If the same item was selected just return. + // */ + // if (fileSizeCbo.getItem(fileSizeCbo.getSelectionIndex()).equals( + // (String) fileSizeCbo.getData())) { + // return; + // } + // + // if (fileSizeCbo.getItem(fileSizeCbo.getSelectionIndex()).equals("MB")) { + // fileSizeSpnr.setIncrement(1); + // fileSizeSpnr.setPageIncrement(50); + // fileSizeSpnr.setMaximum(2000); + // fileSizeSpnr.setMinimum(500); + // fileSizeSpnr.setSelection(500); + // } else { + // fileSizeSpnr.setIncrement(1); + // fileSizeSpnr.setPageIncrement(5); + // fileSizeSpnr.setMinimum(1); + // fileSizeSpnr.setMaximum(10); + // fileSizeSpnr.setSelection(1); + // } + // + // fileSizeCbo + // .setData(fileSizeCbo.getItem(fileSizeCbo.getSelectionIndex())); + // } /** * Display the directory browser dialog. @@ -624,6 +826,9 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements * Update location's state. */ private void updateLocationState() { + if (isDisposed()) { + return; + } File dir = (File) locationLbl.getData(); long totSpace = dir.getTotalSpace(); long freeSpace = dir.getUsableSpace(); @@ -665,49 +870,57 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements * True for start time, false for end time. */ private void displayDateTimeControls(boolean startTimeFlag) { + setCursorBusy(true); + try { + Date acDate = startTimeFlag ? startDate : endDate; + AwipsCalendar ac = new AwipsCalendar(shell, acDate, 1); + ac.setTimeZone(TimeUtil.newCalendar().getTimeZone()); + ac.setText((startTimeFlag ? "Start" : "End") + " Time Calendar"); - Date acDate = startTimeFlag ? startDate : endDate; - AwipsCalendar ac = new AwipsCalendar(shell, acDate, 1); - ac.setTimeZone(TimeUtil.newCalendar().getTimeZone()); - Date date = (Date) ac.open(); + Date date = (Date) ac.open(); - if (date == null) { - return; - } - - if (startTimeFlag) { - if (date.after(endDate)) { - MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION - | SWT.OK); - mb.setText("Date Error"); - mb.setMessage("The selected start date is after the end date. Resetting."); - mb.open(); + if (date == null) { return; } - if (!startDate.equals(date)) { - startDate = date; - resetSizes(); - } - } else { - if (date.before(startDate)) { - MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION - | SWT.OK); - mb.setText("Date Error"); - mb.setMessage("The selected end date is before the start date. Resetting."); - mb.open(); - return; - } - if (!endDate.equals(date)) { - endDate = date; - resetSizes(); - } - } + if (startTimeFlag) { + if (date.after(endDate)) { + MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION + | SWT.OK); + mb.setText("Date Error"); + mb.setMessage("The selected start date is after the end date. Resetting."); + mb.open(); + return; + } - if (startTimeFlag) { - startTimeLbl.setText(dateFmt.format(date)); - } else { - endTimeLbl.setText(dateFmt.format(date)); + if (!startDate.equals(date)) { + startDate = date; + sizeJob.resetTime(getStart(), getEnd()); + modified(); + } + } else { + if (date.before(startDate)) { + MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION + | SWT.OK); + mb.setText("Date Error"); + mb.setMessage("The selected end date is before the start date. Resetting."); + mb.open(); + return; + } + if (!endDate.equals(date)) { + endDate = date; + sizeJob.resetTime(getStart(), getEnd()); + modified(); + } + } + + if (startTimeFlag) { + startTimeLbl.setText(dateFmt.format(date)); + } else { + endTimeLbl.setText(dateFmt.format(date)); + } + } finally { + setCursorBusy(false); } } @@ -752,73 +965,12 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements checkGenerateButton(); } - /** - * Reset all entries to unknown size, recompute the sizes for the current - * display table and and other selected entries. - */ - private void resetSizes() { - List selectedDatas = new ArrayList(); - for (String archiveName : archiveInfoMap.keySet()) { - ArchiveInfo archiveInfo = archiveInfoMap.get(archiveName); - for (String categoryName : archiveInfo.getCategoryNames()) { - CategoryInfo categoryInfo = archiveInfo.get(categoryName); - for (DisplayData displayData : categoryInfo - .getDisplayDataList()) { - displayData.setSize(DisplayData.UNKNOWN_SIZE); - if (displayData.isSelected()) { - selectedDatas.add(displayData); - } - } - } - } - - populateTableComp(); - - if (selectedDatas.size() > 0) { - String archiveName = getSelectedArchiveName(); - String categoryName = getSelectedCategoryName(); - Calendar startCal = getStart(); - Calendar endCal = getEnd(); - - for (DisplayData displayData : selectedDatas) { - if (!displayData.isArchive(archiveName) - || !displayData.isCategory(categoryName)) { - sizeJob.queue(new SizeJobRequest(displayData, startCal, - endCal)); - } - } - } - } - - /** - * Get the data information on all selected items; not just the currently - * displayed table. - * - * @return selectedDatas - */ - private List getSelectedData() { - List selectedDatas = new ArrayList(); - for (String archiveName : archiveInfoMap.keySet()) { - ArchiveInfo archiveInfo = archiveInfoMap.get(archiveName); - for (String categoryName : archiveInfo.getCategoryNames()) { - CategoryInfo categoryInfo = archiveInfo.get(categoryName); - for (DisplayData displayData : categoryInfo - .getDisplayDataList()) { - if (displayData.isSelected()) { - selectedDatas.add(displayData); - } - } - } - } - return selectedDatas; - } - /* * (non-Javadoc) * * @see com.raytheon.uf.viz.archive.ui.AbstractArchiveDlg#getStart() */ - // @Override + @Override protected Calendar getStart() { Calendar startCal = TimeUtil.newCalendar(); startCal.setTimeInMillis(startDate.getTime()); @@ -830,10 +982,31 @@ public class CaseCreationDlg extends AbstractArchiveDlg implements * * @see com.raytheon.uf.viz.archive.ui.AbstractArchiveDlg#getEnd() */ - // @Override + @Override protected Calendar getEnd() { Calendar endCal = TimeUtil.newCalendar(); endCal.setTimeInMillis(endDate.getTime()); return endCal; } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.viz.archive.ui.IModifyListener#modified() + */ + @Override + public void modified() { + saveBtn.setEnabled(true); + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.viz.archive.ui.AbstractArchiveDlg#clearModified() + */ + @Override + public void clearModified() { + super.clearModified(); + saveBtn.setEnabled(false); + } } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseLoadSaveDeleteDlg.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseLoadSaveDeleteDlg.java new file mode 100644 index 0000000000..3dd68b9058 --- /dev/null +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseLoadSaveDeleteDlg.java @@ -0,0 +1,261 @@ +/** + * 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.viz.archive.ui; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.raytheon.uf.common.archive.config.ArchiveConfigManager; +import com.raytheon.uf.common.archive.config.ArchiveConstants; +import com.raytheon.viz.ui.dialogs.CaveSWTDialog; + +/** + * Dialog to display a list of select files for Load, Save As or Delete. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 31, 2013 2221       rferrel     Initial creation
+ * Aug 26, 2013 2225       rferrel     Make perspective independent.
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public class CaseLoadSaveDeleteDlg extends CaveSWTDialog { + public static enum Type { + SaveAs("Save As", " Save "), Load("Load", " Load "), Delete("Delete", + " Delete "); + private String title; + + private String btnLabel; + + private Type(String title, String btnLabel) { + this.title = title; + this.btnLabel = btnLabel; + } + + public String getTitle() { + return title; + } + + public String getBtnLabel() { + return btnLabel; + } + } + + private Type type; + + private List caseList; + + private Text fileNameText; + + private Button okBtn; + + private Button cancelBtn; + + protected CaseLoadSaveDeleteDlg(Shell parentShell, Type type) { + super(parentShell, SWT.DIALOG_TRIM | SWT.RESIZE, CAVE.DO_NOT_BLOCK + | CAVE.PERSPECTIVE_INDEPENDENT); + this.type = type; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org + * .eclipse.swt.widgets.Shell) + */ + @Override + protected void initializeComponents(Shell shell) { + setText(type.getTitle() + " Case"); + Composite mainComp = new Composite(shell, SWT.NONE); + GridLayout gl = new GridLayout(1, false); + gl.marginHeight = 0; + gl.marginWidth = 0; + gl.horizontalSpacing = 0; + mainComp.setLayout(gl); + init(); + } + + /** + * Set up dialog layout. + */ + private void init() { + createCaseControls(); + GuiUtil.addSeparator(shell, SWT.HORIZONTAL); + createBottomAcitonButtons(); + } + + /** + * Main body of the dialog. + */ + private void createCaseControls() { + Composite caseComp = new Composite(shell, SWT.NONE); + GridLayout gl = new GridLayout(1, false); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + caseComp.setLayout(gl); + caseComp.setLayoutData(gd); + + caseList = new List(caseComp, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + gd = new GridData(SWT.FILL, SWT.FILL, true, true); + gd.minimumHeight = 300; + caseList.setLayoutData(gd); + + caseList.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + fileNameText.setText(caseList.getSelection()[0]); + } + }); + + fileNameText = new Text(caseComp, SWT.BORDER | SWT.SINGLE); + gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + fileNameText.setLayoutData(gd); + fileNameText.setEditable(type == Type.SaveAs); + } + + /** + * Button layout at the bottom of the dialog. + */ + private void createBottomAcitonButtons() { + Composite actionControlComp = new Composite(shell, SWT.NONE); + GridLayout gl = new GridLayout(2, false); + GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + actionControlComp.setLayout(gl); + actionControlComp.setLayoutData(gd); + okBtn = new Button(actionControlComp, SWT.PUSH); + okBtn.setText(type.getBtnLabel()); + okBtn.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + String name = verifyAction(); + if (name != null) { + setReturnValue(name); + close(); + } + } + }); + + cancelBtn = new Button(actionControlComp, SWT.PUSH); + cancelBtn.setText(" Cancel "); + gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false); + cancelBtn.setLayoutData(gd); + cancelBtn.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + close(); + } + }); + } + + /** + * Verify pending action and return select case name to continue the action. + * + * @return name when ok to perform action otherwise null + */ + private String verifyAction() { + String name = fileNameText.getText().trim(); + + if (name.isEmpty()) { + MessageDialog.openError(shell, "Case Error", "Invalid case name."); + name = null; + } else { + switch (type) { + case Load: + // No need to check since text is not editable. + break; + case SaveAs: + for (String cName : caseList.getItems()) { + if (name.equals(cName)) { + boolean response = MessageDialog + .openConfirm( + shell, + "Case Confirmation", + "Case \"" + + name + + "\" exists.\nSelect OK to overwrite."); + if (!response) { + name = null; + fileNameText.selectAll(); + fileNameText.forceFocus(); + } + break; + } + } + break; + case Delete: + if (!MessageDialog.openConfirm(shell, "Case Confirmation", + "Press OK to delete \"" + name + "\".")) { + name = null; + } + break; + default: + name = null; + } + } + return name; + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.viz.ui.dialogs.CaveSWTDialog#preOpened() + */ + @Override + protected void preOpened() { + super.preOpened(); + populateList(); + } + + /** + * Populate case names in the list. + */ + private void populateList() { + caseList.add(ArchiveConstants.defaultSelectName); + String[] names = ArchiveConfigManager.getInstance().getSelectionNames( + ArchiveConstants.Type.Case); + for (String name : names) { + if (!ArchiveConstants.defaultSelectName.equals(name)) { + caseList.add(name); + } + } + caseList.select(0); + fileNameText.setText(caseList.getItem(0)); + } +} diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseNameDialog.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseNameDialog.java index 60a5e16b54..b147c1a4c7 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseNameDialog.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseNameDialog.java @@ -47,6 +47,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 5, 2013 1966 rferrel Initial creation + * Aug 26, 2013 2225 rferrel Make perspective independent. * * * @@ -65,7 +66,7 @@ public class CaseNameDialog extends CaveSWTDialog { /** Non-blocking modal constructor. */ protected CaseNameDialog(Shell parent, File locationDir) { super(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL, - CAVE.DO_NOT_BLOCK); + CAVE.DO_NOT_BLOCK | CAVE.PERSPECTIVE_INDEPENDENT); this.locationDir = locationDir; } @@ -98,7 +99,7 @@ public class CaseNameDialog extends CaveSWTDialog { } /** - * The xomposite with case name text field. + * The composite with case name text field. */ private void createFieldsComp() { Composite fieldComp = new Composite(shell, SWT.NONE); diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/GenerateCaseDlg.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/GenerateCaseDlg.java index 5ec5cfa75a..dc398ba589 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/GenerateCaseDlg.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/GenerateCaseDlg.java @@ -19,12 +19,24 @@ **/ package com.raytheon.uf.viz.archive.ui; +import java.io.Closeable; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; +import java.util.HashSet; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.zip.GZIPOutputStream; +import org.apache.commons.compress.archivers.ArchiveOutputStream; +import org.apache.commons.compress.archivers.ArchiveStreamFactory; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; +import org.apache.commons.io.FileUtils; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; @@ -45,6 +57,7 @@ import org.eclipse.swt.widgets.ProgressBar; import org.eclipse.swt.widgets.Shell; import com.raytheon.uf.common.archive.config.ArchiveConfigManager; +import com.raytheon.uf.common.archive.config.ArchiveConstants; import com.raytheon.uf.common.archive.config.DisplayData; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -54,7 +67,8 @@ import com.raytheon.uf.viz.core.VizApp; import com.raytheon.viz.ui.dialogs.CaveSWTDialog; /** - * Class to show progress of creating a case. + * This class performs the desired type of case creation and display a + * progress/status message dialog. * *
  * 
@@ -63,10 +77,14 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Jun 3, 2013  1966       rferrel     Initial creation
+ * Aug 16, 2013 2225       rferrel     Change structure of copy to include
+ *                                     archive and category directory and 
+ *                                     implementation of compression.
+ * Oct 08, 2013 2442       rferrel     Remove category directory.
  * 
  * 
* - * @author rferrelGenerateJob + * @author rferrel * @version 1.0 */ @@ -86,9 +104,6 @@ public class GenerateCaseDlg extends CaveSWTDialog { /** Active have generation is finish or has an error. */ private Button closeBtn; - /** The main destination directory. */ - private final File targetDir; - /** * The case's destination directory. Assumed to be a sub-directory of * targetDir. @@ -102,19 +117,17 @@ public class GenerateCaseDlg extends CaveSWTDialog { private final Calendar endCal; /** Data list for the case. */ - private final List sourceDataList; + private final DisplayData[] sourceDataList; /** When true compress the case directory. */ private final boolean doCompress; - /** When true break the compress file into multliple files. */ + /** When true break the compress file into multiple files. */ private final boolean doMultiFiles; - /** The compress size for muliple files. */ - private final int compressSize; - - /** Assumed to be MG or GB to indicate scaling factor for compressSize. */ - private final String sizeType; + // Needed when compress and split implemented + // /** The compress size for multiple files. */ + // private final long splitSize; /** Job to perform the case generation off of the UI thread. */ private GenerateJob generateJob; @@ -140,24 +153,24 @@ public class GenerateCaseDlg extends CaveSWTDialog { * @param sourceList * @param doCompress * @param doMultiFiles - * @param compressSize - * @param sizeType + * @param splitSize */ protected GenerateCaseDlg(Shell parentShell, File targetDir, File caseDir, Calendar startCal, Calendar endCal, List sourceList, - boolean doCompress, boolean doMultiFiles, int compressSize, - String sizeType) { - super(parentShell, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL, - CAVE.DO_NOT_BLOCK); - this.targetDir = targetDir; + boolean doCompress, boolean doMultiFiles, long splitSize) { + super(parentShell, SWT.DIALOG_TRIM, CAVE.DO_NOT_BLOCK + | CAVE.PERSPECTIVE_INDEPENDENT); this.caseDir = caseDir; this.startCal = startCal; this.endCal = endCal; - this.sourceDataList = new ArrayList(sourceList); + this.sourceDataList = sourceList.toArray(new DisplayData[sourceList + .size()]); + Arrays.sort(this.sourceDataList, DisplayData.LABEL_ORDER); this.doCompress = doCompress; this.doMultiFiles = doMultiFiles; - this.compressSize = compressSize; - this.sizeType = sizeType; + + // Needed when compress and split implemented. + // this.splitSize = splitSize; this.caseName = caseDir.getAbsolutePath().substring( targetDir.getAbsolutePath().length() + 1); setText("Generating - " + caseName); @@ -173,7 +186,7 @@ public class GenerateCaseDlg extends CaveSWTDialog { } /** - * Remve a job listener. + * Remove a job listener. * * @param listener */ @@ -357,10 +370,10 @@ public class GenerateCaseDlg extends CaveSWTDialog { * The performs the work of generating the case on a non-UI thread. */ private class GenerateJob extends Job { - boolean shutdown = false; + private final AtomicBoolean shutdown = new AtomicBoolean(false); public GenerateJob() { - super("Generate Job"); + super("Generate Case"); } @Override @@ -371,81 +384,100 @@ public class GenerateCaseDlg extends CaveSWTDialog { setStateLbl("Creating: " + caseDir.getName(), caseDir.getAbsolutePath()); + ICaseCopy caseCopy = null; + + String errorMessage = null; if (caseDir.exists()) { - setStateLbl("Case exists: " + caseName, - caseDir.getAbsolutePath()); + errorMessage = "Case exists: " + caseDir.getName(); + } else if (!caseDir.mkdirs()) { + errorMessage = "Unable to create case: " + caseDir.getName(); + } + + if (errorMessage != null) { + setStateLbl(errorMessage, caseDir.getAbsolutePath()); setProgressBar(100, SWT.ERROR); return Status.OK_STATUS; } - if (!caseDir.mkdirs()) { - setStateLbl("Unable to create case: " + caseName, - caseDir.getAbsolutePath()); - setProgressBar(100, SWT.ERROR); + if (shutdown.get()) { return Status.OK_STATUS; } - if (shutdown) { - return Status.OK_STATUS; - } + String currentArchive = null; + String currentCategory = null; + boolean updateDestDir = false; - for (DisplayData displayData : sourceDataList) { - if (shutdown) { - return Status.OK_STATUS; - } - - setStateLbl( - "Copying \"" + displayData.getDisplayLabel() + "\"", - null); - String rootDir = displayData.getRootDir(); - int beginIndex = rootDir.length(); - - List files = archiveManager.getDisplayFiles(displayData, - startCal, endCal); - for (File source : files) { - if (shutdown) { + try { + for (DisplayData displayData : sourceDataList) { + if (shutdown.get()) { return Status.OK_STATUS; } - String name = source.getAbsolutePath(); - String relativePath = name.substring(beginIndex); + if (!displayData.getArchiveName().equals(currentArchive)) { + updateDestDir = true; + currentArchive = displayData.getArchiveName(); + currentCategory = displayData.getCategoryName(); + } else if (!displayData.getCategoryName().equals( + currentCategory)) { + updateDestDir = true; + currentCategory = displayData.getCategoryName(); + } - setStateLbl("Copy: " + relativePath, name); - File destination = new File(caseDir, relativePath); - try { - if (source.isDirectory()) { - destination.mkdirs(); - FileUtil.copyDirectory(source, destination); + if (updateDestDir) { + updateDestDir = false; + if (caseCopy != null) { + caseCopy.finishCase(); } else { - File destParent = destination.getParentFile(); - destParent.mkdirs(); - FileUtil.copyFile(source, destination); + if (!doCompress) { + caseCopy = new CopyMove(); + } else if (doMultiFiles) { + caseCopy = new CompressAndSplitCopy(); + } else { + caseCopy = new CompressCopy(); + } } - } catch (IOException e) { - statusHandler.handle(Priority.PROBLEM, - e.getLocalizedMessage(), e); + caseCopy.startCase(caseDir, displayData, shutdown); + setStateLbl(currentArchive + " | " + currentCategory, + caseDir.getAbsolutePath() + "\n" + + currentArchive + "\n" + + currentCategory); + } + + List files = archiveManager.getDisplayFiles( + displayData, startCal, endCal); + for (File source : files) { + if (shutdown.get()) { + return Status.OK_STATUS; + } + + caseCopy.copy(source); } } - } + if (caseCopy != null) { + caseCopy.finishCase(); + } + caseCopy = null; - if (!doCompress) { - setProgressBar(100, SWT.NORMAL); setStateLbl("Created: " + caseName, caseDir.getAbsolutePath()); - return Status.OK_STATUS; - } - - if (shutdown) { - return Status.OK_STATUS; - } - - if (doMultiFiles) { setProgressBar(100, SWT.NORMAL); - String message = "Compress into multifiles NYI."; - setStateLbl(message, null); - } else { - setProgressBar(100, SWT.NORMAL); - String message = "Compress into one file NYI"; - setStateLbl(message, null); + + } catch (CaseCreateException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + e); + setStateLbl( + "Failed to Create: " + caseName, + caseDir.getAbsolutePath() + "\n" + + e.getLocalizedMessage()); + setProgressBar(100, SWT.ERROR); + } finally { + if (caseCopy != null) { + try { + caseCopy.finishCase(); + } catch (CaseCreateException ex) { + // Ignore + } + caseCopy = null; + } } return Status.OK_STATUS; @@ -458,8 +490,588 @@ public class GenerateCaseDlg extends CaveSWTDialog { */ @Override protected void canceling() { - shutdown = true; + shutdown.set(true); generateJob = null; } } + + /** + * This class copies selected files/directories to a case-directory/archive. + */ + private static class CopyMove implements ICaseCopy { + /** + * Flag to indicate user canceled the case generation. + */ + private AtomicBoolean shutdown; + + /** + * Top destination directory to move files/dirctories to. + */ + private File destDir; + + /** + * Index on source Files where relative path starts. + */ + private int startRelativePath; + + /** + * Copy source File to desired destination. + * + * @param source + * @param destination + * @throws IOException + */ + private void copyFile(File source, File destination) throws IOException { + if (shutdown.get()) { + return; + } + + if (source.isDirectory()) { + + if (!destination.exists()) { + destination.mkdir(); + } + + String[] files = source.list(); + + for (String file : files) { + copyFile(new File(source, file), + new File(destination, file)); + } + } else { + FileUtil.copyFile(source, destination); + destination.setLastModified(source.lastModified()); + } + } + + @Override + public void copy(File source) throws CaseCreateException { + String relativePath = source.getAbsolutePath().substring( + startRelativePath); + File destination = new File(destDir, relativePath); + try { + destination.getParentFile().mkdirs(); + copyFile(source, destination); + } catch (IOException ex) { + throw new CaseCreateException("CopyMove.copy: ", ex); + } + } + + @Override + public void startCase(File caseDir, DisplayData displayData, + AtomicBoolean shutdown) { + this.shutdown = shutdown; + String archiveDirName = ArchiveConstants + .convertToFileName(displayData.getArchiveName()); + destDir = new File(caseDir, archiveDirName); + destDir.mkdirs(); + startRelativePath = displayData.getRootDir().length(); + } + + @Override + public void finishCase() { + // Nothing to do. + } + } + + /** + * This class takes selected directories/files to + * case-directory/archive/compress-category-file. The compress-category-file + * is a tar gzip file containing the categorie's data. + */ + private static class CompressCopy implements ICaseCopy { + /** + * Flag to indicate user canceled case generation. + */ + private AtomicBoolean shutdown; + + /** + * Top Level destination directory. + */ + private File destDir; + + /** + * Stream to the file being created. + */ + private FileOutputStream fileStream; + + /** + * Stream to perform the compression. + */ + private GZIPOutputStream zipStream; + + /** + * Stream to create the tar image. + */ + private ArchiveOutputStream tarStream; + + /** + * Index to start of relative path in source File. + */ + private int startRelativePath; + + /** + * Directories already created in the tar image. + */ + private final HashSet tarDirFile = new HashSet(); + + /** + * Buffer to use for reading in a file. + */ + private final byte[] buffer = new byte[(int) (32 * FileUtils.ONE_KB)]; + + @Override + public void copy(File source) throws CaseCreateException { + try { + addParentDir(source); + addTarFiles(new File[] { source }); + } catch (IOException e) { + throw new CaseCreateException("Compress Copy failed: ", e); + } + } + + /** + * Add list of Files to the tar image. + * + * @param files + * @throws IOException + */ + private void addTarFiles(File[] files) throws IOException { + for (File file : files) { + if (shutdown.get()) { + return; + } + String name = file.getAbsolutePath().substring( + startRelativePath); + if (file.isDirectory()) { + if (!tarDirFile.contains(file)) { + TarArchiveEntry entry = new TarArchiveEntry(file, name); + tarStream.putArchiveEntry(entry); + tarStream.closeArchiveEntry(); + tarDirFile.add(file); + addTarFiles(file.listFiles()); + } + } else { + TarArchiveEntry entry = new TarArchiveEntry(file, name); + entry.setSize(file.length()); + FileInputStream fileStream = null; + tarStream.putArchiveEntry(entry); + try { + fileStream = new FileInputStream(file); + int len; + while ((len = fileStream.read(buffer)) != -1) { + tarStream.write(buffer, 0, len); + } + } finally { + if (fileStream != null) { + closeStream(fileStream); + } + } + + tarStream.closeArchiveEntry(); + } + } + } + + /** + * Convince method to close a steam and ignore any IOException. + * + * @param stream + */ + private void closeStream(Closeable stream) { + try { + stream.close(); + } catch (IOException ex) { + // Ignore + } + } + + /** + * If needed add parent directories to the tar image. + * + * @param file + * @throws IOException + */ + private void addParentDir(File file) throws IOException { + File parent = file.getParentFile(); + if (parent != null && !tarDirFile.contains(parent) + && (parent.getAbsolutePath().length() > startRelativePath)) { + addParentDir(parent); + String name = parent.getAbsolutePath().substring( + startRelativePath); + TarArchiveEntry entry = new TarArchiveEntry(parent, name); + tarStream.putArchiveEntry(entry); + tarStream.closeArchiveEntry(); + tarDirFile.add(parent); + } + } + + @Override + public void startCase(File caseDir, DisplayData displayData, + AtomicBoolean shutdown) throws CaseCreateException { + try { + this.shutdown = shutdown; + String archiveDirName = ArchiveConstants + .convertToFileName(displayData.getArchiveName()); + String categoryDirName = ArchiveConstants + .convertToFileName(displayData.getCategoryName()); + destDir = new File(caseDir, archiveDirName); + destDir.mkdirs(); + tarDirFile.clear(); + startRelativePath = displayData.getRootDir().length(); + File tarFile = new File(destDir, categoryDirName + + ArchiveConstants.TAR_EXTENSION); + fileStream = new FileOutputStream(tarFile); + zipStream = new GZIPOutputStream(fileStream); + ArchiveStreamFactory factory = new ArchiveStreamFactory(); + tarStream = factory.createArchiveOutputStream( + ArchiveStreamFactory.TAR, zipStream); + if (tarStream instanceof TarArchiveOutputStream) { + ((TarArchiveOutputStream) tarStream) + .setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); + } + } catch (Exception e) { + throw new CaseCreateException("CompressCopy.startCase: ", e); + } + } + + @Override + public void finishCase() throws CaseCreateException { + try { + if (tarStream != null) { + tarStream.finish(); + } + if (zipStream != null) { + zipStream.finish(); + } + } catch (IOException e) { + throw new CaseCreateException("CaseCopy.finish: ", e); + } finally { + if (tarStream != null) { + closeStream(tarStream); + } else if (zipStream != null) { + closeStream(zipStream); + } else if (fileStream != null) { + closeStream(fileStream); + } + tarStream = null; + zipStream = null; + fileStream = null; + } + } + } + + /* + * This class intended for making "image" files read for burning to a CD or + * DVD. Need to resolve issues on how this should be done. + */ + private static class CompressAndSplitCopy implements ICaseCopy { + + public void startCase(File caseDir, DisplayData displayData, + AtomicBoolean shutdown) throws CaseCreateException { + throw new CaseCreateException( + "Compress and split not yet implemented."); + } + + @Override + public void copy(File source) throws CaseCreateException { + // TODO Auto-generated method stub + + } + + @Override + public void finishCase() { + // TODO Auto-generated method stub + } + + // TODO Example code for future implementation of this class. + // Will need to break up into the starCase, copy and finishCase will + // need close and join. + + // private void compressAndSplitCase() { + // ArchiveOutputStream tarStream = null; + // GZIPOutputStream zipStream = null; + // try { + // Pipe pipe = Pipe.open(); + // OutputStream poStream = Channels.newOutputStream(pipe.sink()); + // zipStream = new GZIPOutputStream(poStream); + // ArchiveStreamFactory factory = new ArchiveStreamFactory(); + // + // tarStream = factory.createArchiveOutputStream( + // ArchiveStreamFactory.TAR, zipStream); + // + // if (tarStream instanceof TarArchiveOutputStream) { + // ((TarArchiveOutputStream) tarStream) + // .setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); + // } + // + // final InputStream piStream = Channels.newInputStream(pipe + // .source()); + // splitDone.set(false); + // + // Job splitJob = new Job("Split") { + // + // @Override + // protected IStatus run(IProgressMonitor monitor) { + // OutputStream splitStream = null; + // long totSize = 0; + // try { + // byte[] buffer = new byte[12 * 1024]; + // + // int bufCnt = 0; + // long splitCnt = 0L; + // while ((bufCnt = piStream.read(buffer)) != -1) { + // totSize += bufCnt; + // if (splitStream == null) { + // splitStream = openSplitFile(++numSplitFiles); + // } + // long fileSize = splitCnt + bufCnt; + // if (fileSize < splitSize) { + // splitStream.write(buffer, 0, bufCnt); + // splitCnt = fileSize; + // } else if (fileSize == splitSize) { + // splitStream.write(buffer, 0, bufCnt); + // splitStream.close(); + // splitStream = null; + // splitCnt = 0L; + // } else { + // int cnt = (int) (splitSize - splitCnt); + // splitStream.write(buffer, 0, cnt); + // splitStream.close(); + // splitStream = openSplitFile(++numSplitFiles); + // int remainder = bufCnt - cnt; + // splitStream.write(buffer, cnt, remainder); + // splitCnt = remainder; + // } + // } + // } catch (IOException e) { + // statusHandler.handle(Priority.PROBLEM, + // e.getLocalizedMessage(), e); + // } finally { + // if (splitStream != null) { + // try { + // splitStream.close(); + // } catch (IOException e) { + // // Ignore + // } + // } + // splitDone.set(true); + // System.out.println("totalSize: " + totSize + // + ", splitSize: " + splitSize + // + ", numSplitFiles: " + numSplitFiles); + // } + // + // return Status.OK_STATUS; + // } + // }; + // splitJob.schedule(); + // + // createTarFile(tarStream, caseDir.listFiles()); + // tarStream.finish(); + // zipStream.finish(); + // try { + // tarStream.close(); + // } catch (IOException ex) { + // // Ignore + // } + // tarStream = null; + // + // try { + // zipStream.close(); + // } catch (IOException ex) { + // // Ignore + // } + // zipStream = null; + // + // while (!splitDone.get()) { + // if (splitJob.getState() == Job.RUNNING) { + // try { + // System.out.println("splitJob.join()"); + // splitJob.join(); + // } catch (InterruptedException e) { + // statusHandler.handle(Priority.INFO, + // e.getLocalizedMessage(), e); + // } + // } else { + // try { + // private void compressAndSplitCase() { + // ArchiveOutputStream tarStream = null; + // GZIPOutputStream zipStream = null; + // try { + // Pipe pipe = Pipe.open(); + // OutputStream poStream = Channels.newOutputStream(pipe.sink()); + // zipStream = new GZIPOutputStream(poStream); + // ArchiveStreamFactory factory = new ArchiveStreamFactory(); + // + // tarStream = factory.createArchiveOutputStream( + // ArchiveStreamFactory.TAR, zipStream); + // + // if (tarStream instanceof TarArchiveOutputStream) { + // ((TarArchiveOutputStream) tarStream) + // .setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); + // } + // + // final InputStream piStream = Channels.newInputStream(pipe + // .source()); + // splitDone.set(false); + // + // Job splitJob = new Job("Split") { + // + // @Override + // protected IStatus run(IProgressMonitor monitor) { + // OutputStream splitStream = null; + // long totSize = 0; + // try { + // byte[] buffer = new byte[12 * 1024]; + // + // int bufCnt = 0; + // long splitCnt = 0L; + // while ((bufCnt = piStream.read(buffer)) != -1) { + // totSize += bufCnt; + // if (splitStream == null) { + // splitStream = openSplitFile(++numSplitFiles); + // } + // long fileSize = splitCnt + bufCnt; + // if (fileSize < splitSize) { + // splitStream.write(buffer, 0, bufCnt); + // splitCnt = fileSize; + // } else if (fileSize == splitSize) { + // splitStream.write(buffer, 0, bufCnt); + // splitStream.close(); + // splitStream = null; + // splitCnt = 0L; + // } else { + // int cnt = (int) (splitSize - splitCnt); + // splitStream.write(buffer, 0, cnt); + // splitStream.close(); + // splitStream = openSplitFile(++numSplitFiles); + // int remainder = bufCnt - cnt; + // splitStream.write(buffer, cnt, remainder); + // splitCnt = remainder; + // } + // } + // } catch (IOException e) { + // statusHandler.handle(Priority.PROBLEM, + // e.getLocalizedMessage(), e); + // } finally { + // if (splitStream != null) { + // try { + // splitStream.close(); + // } catch (IOException e) { + // // Ignore + // } + // } + // splitDone.set(true); + // System.out.println("totalSize: " + totSize + // + ", splitSize: " + splitSize + // + ", numSplitFiles: " + numSplitFiles); + // } + // + // return Status.OK_STATUS; + // } + // }; + // splitJob.schedule(); + // + // createTarFile(tarStream, caseDir.listFiles()); + // tarStream.finish(); + // zipStream.finish(); + // try { + // tarStream.close(); + // } catch (IOException ex) { + // // Ignore + // } + // tarStream = null; + // + // try { + // zipStream.close(); + // } catch (IOException ex) { + // // Ignore + // } + // zipStream = null; + // + // while (!splitDone.get()) { + // if (splitJob.getState() == Job.RUNNING) { + // try { + // System.out.println("splitJob.join()"); + // splitJob.join(); + // } catch (InterruptedException e) { + // statusHandler.handle(Priority.INFO, + // e.getLocalizedMessage(), e); + // } + // } else { + // try { + // Thread.sleep(200L); + // } catch (InterruptedException e) { + // statusHandler.handle(Priority.INFO, + // e.getLocalizedMessage(), e); + // } + // } + // } + // } catch (IOException e) { + // statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + // e); + // } catch (ArchiveException e1) { + // statusHandler.handle(Priority.PROBLEM, + // e1.getLocalizedMessage(), e1); + // } finally { + // if (tarStream != null) { + // try { + // tarStream.close(); + // } catch (IOException e) { + // // Ignore + // } + // } + // + // if (zipStream != null) { + // try { + // zipStream.close(); + // } catch (IOException e) { + // // Ignore + // } + // } + // } + // setProgressBar(100, SWT.NORMAL); + // deleteCaseDir(); + // String message = caseDir.getName() + "split into " + numSplitFiles + // + " file(s)."; + // setStateLbl(message, null); + // } + // Thread.sleep(200L); + // } catch (InterruptedException e) { + // statusHandler.handle(Priority.INFO, + // e.getLocalizedMessage(), e); + // } + // } + // } + // } catch (IOException e) { + // statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + // e); + // } catch (ArchiveException e1) { + // statusHandler.handle(Priority.PROBLEM, + // e1.getLocalizedMessage(), e1); + // } finally { + // if (tarStream != null) { + // try { + // tarStream.close(); + // } catch (IOException e) { + // // Ignore + // } + // } + // + // if (zipStream != null) { + // try { + // zipStream.close(); + // } catch (IOException e) { + // // Ignore + // } + // } + // } + // setProgressBar(100, SWT.NORMAL); + // deleteCaseDir(); + // String message = caseDir.getName() + "split into " + numSplitFiles + // + " file(s)."; + // setStateLbl(message, null); + // } + + } } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJobRequest.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ICaseCopy.java similarity index 52% rename from cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJobRequest.java rename to cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ICaseCopy.java index 0de53cd1e8..5c948250fd 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJobRequest.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ICaseCopy.java @@ -17,18 +17,17 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.uf.viz.archive.data; +package com.raytheon.uf.viz.archive.ui; import java.io.File; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; +import java.io.IOException; +import java.util.concurrent.atomic.AtomicBoolean; import com.raytheon.uf.common.archive.config.DisplayData; /** - * This class obtains information on a File in a Job in order to remove it from - * the UI thread. + * Interface for copying source files/directories to the desired type of + * destination. * *
  * 
@@ -36,7 +35,7 @@ import com.raytheon.uf.common.archive.config.DisplayData;
  * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * May 15, 2013 1966       rferrel     Initial creation
+ * Aug 21, 2013 2225       rferrel     Initial creation
  * 
  * 
* @@ -44,39 +43,34 @@ import com.raytheon.uf.common.archive.config.DisplayData; * @version 1.0 */ -public class SizeJobRequest { - - /** Information from archive configuration manager. */ - final DisplayData displayData; - - /** Files or directories to obtain information on. */ - final List files = new ArrayList(); - - /** Start time inclusive. */ - final Calendar startCal; - - /** End time exclusive. */ - final Calendar endCal; +public interface ICaseCopy { /** - * Create and entry and place it on the queue. + * Prepare copier for sending display data's archive and category + * selections. * + * @param caseDir + * - top level case directory file * @param displayData - * @param startCal - * @param endCal + * - data preparing to move + * @param shutdown + * - Flag to check for orderly shudown + * @throws CaseCreateException */ - public SizeJobRequest(DisplayData displayData, Calendar startCal, - Calendar endCal) { - this.displayData = displayData; - this.startCal = startCal; - this.endCal = endCal; - } + public void startCase(File caseDir, DisplayData displayData, + AtomicBoolean shutdown) throws CaseCreateException; /** + * A source to copy. * - * @return displayData + * @param source + * @throws IOException */ - public DisplayData getDisplayData() { - return displayData; - } + public void copy(File source) throws CaseCreateException; + + /** + * Finish the move process for the current archive and category. + * + */ + public void finishCase() throws CaseCreateException; } diff --git a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/util/package-info.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/IRetentionHour.java similarity index 54% rename from edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/util/package-info.java rename to cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/IRetentionHour.java index db65de0edd..444b9b4ce7 100644 --- a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/util/package-info.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/IRetentionHour.java @@ -17,7 +17,31 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ +package com.raytheon.uf.viz.archive.ui; + /** - * Contains utility classes for mesowest plugin + * Interface to adjusting values based on the retention hour value found in a + * selection configuration. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 13, 2013 2220       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 */ -package com.raytheon.edex.plugin.obs.mesowest.util; \ No newline at end of file + +public interface IRetentionHour { + /** + * Adjust start/end based on the value found in selection configuration. + * + * @param startRetentionHours + */ + public void setRetentionTimes(long startRetentionHours); +} diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/VizApp.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/VizApp.java index 642e0ea3bf..13b2ac02c9 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/VizApp.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/VizApp.java @@ -50,6 +50,8 @@ import com.raytheon.uf.viz.core.localization.LocalizationManager; * 7/1/06 chammack Initial Creation. * Sep 12, 2012 1167 djohnson Add datadelivery servers. * Jan 14, 2013 1469 bkowal Removed the hdf5 data directory. + * Aug 27, 2013 2295 bkowal Removed the jms server property; added + * jms connection string * * * @@ -70,16 +72,10 @@ public final class VizApp { private static String httpServer; - private static String jmsServer; + private static String jmsConnectionString; private static String pypiesServer; - private static String dataDeliveryServer; - - private static String dataDeliveryLcmServer; - - private static String dataDeliveryQueryServer; - static { ManagementFactory.getRuntimeMXBean().getName(); } @@ -240,12 +236,12 @@ public final class VizApp { VizApp.httpServer = System.getProperty("awips.httpServer", httpServer); } - public static String getJmsServer() { - return jmsServer; + public static String getJmsConnectionString() { + return jmsConnectionString; } - public static void setJmsServer(String jmsServer) { - VizApp.jmsServer = jmsServer; + public static void setJmsConnectionString(String jmsConnectionString) { + VizApp.jmsConnectionString = jmsConnectionString; } public static String getPypiesServer() { diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/comm/JMSConnection.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/comm/JMSConnection.java index 7d06157abf..51c771d22d 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/comm/JMSConnection.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/comm/JMSConnection.java @@ -20,14 +20,13 @@ package com.raytheon.uf.viz.core.comm; -import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.jms.ConnectionFactory; - import org.apache.qpid.client.AMQConnectionFactory; -import org.apache.qpid.url.URLSyntaxException; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.viz.core.VizApp; /** @@ -43,16 +42,23 @@ import com.raytheon.uf.viz.core.VizApp; * Nov 2, 2011 #7391 bkowal Ensure that the generated WsId is properly formatted to be * included in a url. * May 09, 2013 1814 rjpeter Updated prefetch to 10. + * Aug 27, 2013 2295 bkowal The entire connection string is now provided by EDEX; so, it + * no longer needs to be constructed. Replaced stacktrace + * printing with UFStatus. * * * @author chammack * @version 1.0 */ public class JMSConnection { + private static final IUFStatusHandler statusHandler = UFStatus + .getHandler(JMSConnection.class); + + private static final String WSID_PLACEHOLDER = "__WSID__"; private static JMSConnection instance; - private final String jndiProviderUrl; + private final String connectionUrl; private AMQConnectionFactory factory; @@ -65,38 +71,27 @@ public class JMSConnection { } public JMSConnection() { - this(VizApp.getJmsServer()); + this(VizApp.getJmsConnectionString()); } - public JMSConnection(String jndiProviderUrl) { - this.jndiProviderUrl = jndiProviderUrl; + public JMSConnection(String connectionUrl) { + this.connectionUrl = connectionUrl; try { - // do not enable retry/connectdelay connection and factory will - // silently reconnect and user will never be notified qpid is down - // and cave/text workstation will just act like they are hung - // up to each individual component that opens a connection to handle - // reconnect - this.factory = new AMQConnectionFactory( - "amqp://guest:guest@" - + URLEncoder.encode(VizApp.getWsId().toString(), - "UTF-8") - + "/edex?brokerlist='" - + this.jndiProviderUrl - + "?connecttimeout='5000'&heartbeat='0''&maxprefetch='10'&sync_publish='all'&failover='nofailover'"); - } catch (URLSyntaxException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (UnsupportedEncodingException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); + String wsid = URLEncoder.encode(VizApp.getWsId().toString(), + "UTF-8"); + this.factory = new AMQConnectionFactory(this.connectionUrl.replace( + WSID_PLACEHOLDER, wsid)); + } catch (Exception e) { + statusHandler.fatal("Failed to connect to the JMS Server!", e); } } /** - * @return the jndiProviderUrl + * + * @return the jms connection url */ - public String getJndiProviderUrl() { - return jndiProviderUrl; + public String getConnectionUrl() { + return connectionUrl; } /** diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/localization/LocalizationInitializer.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/localization/LocalizationInitializer.java index 0cd5778453..cde646daa6 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/localization/LocalizationInitializer.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/localization/LocalizationInitializer.java @@ -50,6 +50,8 @@ import com.raytheon.uf.viz.core.requests.ThriftClient; * Nov 5, 2009 mschenke Initial creation * Sep 12, 2012 1167 djohnson Add datadelivery servers. * Jan 14, 2013 1469 bkowal Removed the hdf5 data directory. + * Aug 27, 2013 2295 bkowal The entire jms connection string is now + * provided by EDEX. * * * @@ -125,7 +127,7 @@ public class LocalizationInitializer { GetServersResponse resp = (GetServersResponse) ThriftClient .sendLocalizationRequest(req); VizApp.setHttpServer(resp.getHttpServer()); - VizApp.setJmsServer(resp.getJmsServer()); + VizApp.setJmsConnectionString(resp.getJmsConnectionString()); VizApp.setPypiesServer(resp.getPypiesServer()); VizServers.getInstance().setServerLocations(resp.getServerLocations()); } diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/localization/LocalizationManager.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/localization/LocalizationManager.java index 2534b782c4..4160bf2086 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/localization/LocalizationManager.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/localization/LocalizationManager.java @@ -92,6 +92,8 @@ import com.raytheon.uf.viz.core.requests.ThriftClient; * May 19, 2007 #1127 randerso Implemented error handling * Sep 12, 2012 1167 djohnson Add datadelivery servers. * Jan 14, 2013 1469 bkowal Removed the hdf5 data directory. + * Aug 27, 2013 2295 bkowal The entire jms connection string is now + * provided by EDEX. * * * @@ -147,8 +149,8 @@ public class LocalizationManager implements IPropertyChangeListener { this.overrideServer = false; this.overrideSite = false; try { - localizationStore = new ScopedPreferenceStore(new InstanceScope(), - "localization"); + localizationStore = new ScopedPreferenceStore( + InstanceScope.INSTANCE, "localization"); localizationStore.addPropertyChangeListener(this); loadHttpServer(); loadAlertServer(); @@ -222,7 +224,7 @@ public class LocalizationManager implements IPropertyChangeListener { GetServersResponse resp = (GetServersResponse) ThriftClient .sendLocalizationRequest(req); VizApp.setHttpServer(resp.getHttpServer()); - VizApp.setJmsServer(resp.getJmsServer()); + VizApp.setJmsConnectionString(resp.getJmsConnectionString()); VizApp.setPypiesServer(resp.getPypiesServer()); VizServers.getInstance().setServerLocations( resp.getServerLocations()); @@ -910,40 +912,6 @@ public class LocalizationManager implements IPropertyChangeListener { return responses; } - /** - * Makes a request to the UtilitySrv - * - * @param request - * the request to make - * @return the responses from the request - * @throws VizException - */ - private AbstractUtilityResponse[] makeRequest( - PrivilegedUtilityRequestMessage request) - throws LocalizationOpFailedException { - - AbstractUtilityResponse[] responseList = null; - - UtilityResponseMessage localizationResponse = null; - try { - localizationResponse = (UtilityResponseMessage) ThriftClient - .sendLocalizationRequest(request); - } catch (VizException e) { - throw new LocalizationOpFailedException("Localization error", e); - } - if (localizationResponse != null) { - responseList = localizationResponse.getResponses(); - - for (AbstractUtilityResponse response : responseList) { - if (!response.successful()) { - throw new LocalizationOpFailedException( - response.getFormattedErrorMessage()); - } - } - } - return responseList; - } - public boolean isOverrideServer() { return overrideServer; } diff --git a/cave/com.raytheon.uf.viz.d2d.nsharp/src/com/raytheon/uf/viz/d2d/nsharp/rsc/D2DNSharpDataObject.java b/cave/com.raytheon.uf.viz.d2d.nsharp/src/com/raytheon/uf/viz/d2d/nsharp/rsc/D2DNSharpDataObject.java index 659bfae96b..dd7015b2f2 100644 --- a/cave/com.raytheon.uf.viz.d2d.nsharp/src/com/raytheon/uf/viz/d2d/nsharp/rsc/D2DNSharpDataObject.java +++ b/cave/com.raytheon.uf.viz.d2d.nsharp/src/com/raytheon/uf/viz/d2d/nsharp/rsc/D2DNSharpDataObject.java @@ -32,15 +32,16 @@ import com.raytheon.uf.common.dataplugin.PluginDataObject; * TODO Add Description * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * Jul 26, 2011            bsteffen     Initial creation
- *
+ * Jul 26, 2011            bsteffen    Initial creation
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
+ * 
  * 
- * + * * @author bsteffen * @version 1.0 */ @@ -79,4 +80,8 @@ public class D2DNSharpDataObject extends PluginDataObject { this.layers = layers; } + @Override + public String getPluginName() { + return "d2dnsharpdataobject"; + } } diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/ScanResourceData.java b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/ScanResourceData.java index b79ed605c4..c718004216 100644 --- a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/ScanResourceData.java +++ b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/ScanResourceData.java @@ -61,7 +61,8 @@ import com.raytheon.uf.viz.monitor.scan.ScanMonitor; * ------------ ---------- ----------- -------------------------- * Oct 13, 2009 dhladky Initial creation * Feb 28, 2013 1731 bsteffen Optimize construction of scan resource. - * Apr 18, 2013 1926 njensen Reuse URIs in construction of resource + * Apr 18, 2013 1926 njensen Reuse URIs in construction of resource + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -203,7 +204,6 @@ public class ScanResourceData extends AbstractRequestableResourceData { public void populateRecords(ScanRecord[] records) throws VizException { Map> fileMap = new HashMap>(); for (ScanRecord record : records) { - record.setPluginName("scan"); File loc = HDF5Util.findHDF5Location(record); Set recordSet = fileMap.get(loc); if (recordSet == null) { @@ -260,12 +260,12 @@ public class ScanResourceData extends AbstractRequestableResourceData { List dataList = new ArrayList(); long[] times = monitor.getDMDMaxAngleTimes(icao); - int index = times.length - 1 < 0 ? 0 : times.length - 1; + int index = (times.length - 1) < 0 ? 0 : times.length - 1; if ((times != null) && (times.length != 0)) { - for (int i = 0; i < allTimes.length; i++) { - if (allTimes[i].getRefTime() != null) { - if (allTimes[i].getRefTime().getTime() == times[index]) { - dataList.add(allTimes[i]); + for (DataTime allTime : allTimes) { + if (allTime.getRefTime() != null) { + if (allTime.getRefTime().getTime() == times[index]) { + dataList.add(allTime); index--; if (index == -1) { break; diff --git a/cave/com.raytheon.uf.viz.radarapps.fsi/src/com/raytheon/uf/viz/radarapps/fsi/FSILauncherLayer.java b/cave/com.raytheon.uf.viz.radarapps.fsi/src/com/raytheon/uf/viz/radarapps/fsi/FSILauncherLayer.java index 33c05f9ddb..fb9647b41c 100644 --- a/cave/com.raytheon.uf.viz.radarapps.fsi/src/com/raytheon/uf/viz/radarapps/fsi/FSILauncherLayer.java +++ b/cave/com.raytheon.uf.viz.radarapps.fsi/src/com/raytheon/uf/viz/radarapps/fsi/FSILauncherLayer.java @@ -84,11 +84,11 @@ public class FSILauncherLayer extends private MouseHandler mouseHandler; - private MenuManager quickMenuManager; + private final MenuManager quickMenuManager; - private MenuManager fullMenuManager; + private final MenuManager fullMenuManager; - private Shell shell; + private final Shell shell; public FSILauncherLayer(FSILauncherResourceData fsiLauncherResourceData, LoadProperties loadProperties) { @@ -201,14 +201,16 @@ public class FSILauncherLayer extends } else { try { for (Object o : (ArrayList) ((ResponseMessageGeneric) response) - .getContents()) + .getContents()) { result.add((String) o); + } } catch (RuntimeException e) { throw new VizException("Unexpected server response", e); } } - } else + } else { throw new VizException("Could not load getFsiRadars.py"); + } } catch (VizException e) { statusHandler.handle(Priority.PROBLEM, "Could not retrieve FSI radar list", e); @@ -229,15 +231,16 @@ public class FSILauncherLayer extends geoClickedPoint = getResourceContainer().translateClick(x, y); if (isEditable()) { // panelClickPoint = new Point(x, y); - if (mouseButton == MOUSE_BUTTON_TO_USE) + if (mouseButton == MOUSE_BUTTON_TO_USE) { clicked = true; + } } return false; } @Override public boolean handleMouseUp(int x, int y, int mouseButton) { - if (clicked && mouseButton == MOUSE_BUTTON_TO_USE) { + if (clicked && (mouseButton == MOUSE_BUTTON_TO_USE)) { clicked = false; /* @@ -295,8 +298,9 @@ public class FSILauncherLayer extends throw new VizException("Unexpected server response", e); } } - } else + } else { throw new VizException("Could not retrieve FSI environment"); + } } catch (VizException e) { statusHandler.handle(Priority.PROBLEM, "Could not retrieve FSI radar list", e); @@ -307,7 +311,7 @@ public class FSILauncherLayer extends public class LaunchFSIAction extends Action { - private String radarName; + private final String radarName; private class StormVector { public boolean useSTI = true; @@ -393,7 +397,8 @@ public class FSILauncherLayer extends RadarRecord radarRecord = null; try { List obs = query.performQuery(); - if (obs != null && !obs.isEmpty() && obs.get(0).length > 0) { + if ((obs != null) && !obs.isEmpty() + && (obs.get(0).length > 0)) { radarRecord = (RadarRecord) obs.get(0)[0]; } else { // default to 0.5 for non-terminal radars, test if @@ -409,7 +414,6 @@ public class FSILauncherLayer extends } catch (RuntimeException e) { throw new VizException("Unexpected response format", e); } - radarRecord.setPluginName("radar"); // TODO: huh? File loc = HDF5Util.findHDF5Location(radarRecord); IDataStore dataStore = DataStoreFactory.getDataStore(loc); try { @@ -439,8 +443,9 @@ public class FSILauncherLayer extends private String createControlMessage() { FSIEnvironment env = getFSIEnvironment(); - if (env == null) + if (env == null) { return null; + } // According to FSI_GUI, this must have the format ##.## String subTypeStr = String.format("%04.2f", @@ -540,13 +545,14 @@ public class FSILauncherLayer extends @Override public void run() { String controlMessage = createControlMessage(); - if (controlMessage == null) + if (controlMessage == null) { return; + } File f = PathManagerFactory.getPathManager().getStaticFile( "fsi" + File.separator + FSI_START_SCRIPT_NAME); - if (f == null || !f.exists()) { + if ((f == null) || !f.exists()) { statusHandler.handle(Priority.PROBLEM, "Could not find the FSI start script."); return; @@ -604,12 +610,14 @@ public class FSILauncherLayer extends int nLines = 0; while (true) { String s = br.readLine(); - if (s == null) + if (s == null) { break; + } sb.append(s); sb.append('\n'); - if (++nLines >= MAX_LINES) + if (++nLines >= MAX_LINES) { break; + } } } catch (IOException e) { e.printStackTrace(System.err); @@ -628,7 +636,7 @@ public class FSILauncherLayer extends statusHandler .handle(Priority.PROBLEM, "FSI failed to start: " - + sb.toString()); + + sb.toString()); return; } } catch (InterruptedException e) { diff --git a/cave/com.raytheon.uf.viz.thinclient/src/com/raytheon/uf/viz/thinclient/ThinClientNotificationManagerJob.java b/cave/com.raytheon.uf.viz.thinclient/src/com/raytheon/uf/viz/thinclient/ThinClientNotificationManagerJob.java index 71dc290fd2..7e058551c6 100644 --- a/cave/com.raytheon.uf.viz.thinclient/src/com/raytheon/uf/viz/thinclient/ThinClientNotificationManagerJob.java +++ b/cave/com.raytheon.uf.viz.thinclient/src/com/raytheon/uf/viz/thinclient/ThinClientNotificationManagerJob.java @@ -35,7 +35,9 @@ import com.raytheon.uf.viz.core.requests.ThriftClient; import com.raytheon.uf.viz.thinclient.preferences.ThinClientPreferenceConstants; /** - * TODO Add Description + * Listens to changes to the "Disable JMS" option in the Thin Client + * Preferences. Will automatically connect to and disconnect from the + * JMS Server as the option is updated. * *
  * 
@@ -44,6 +46,8 @@ import com.raytheon.uf.viz.thinclient.preferences.ThinClientPreferenceConstants;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Nov 29, 2011            bsteffen     Initial creation
+ * Aug 27, 2013 2295       bkowal       The entire jms connection string is now
+ *                                      provided by EDEX.
  * 
  * 
* @@ -96,13 +100,14 @@ public class ThinClientNotificationManagerJob extends NotificationManagerJob if (disableJMS) { disconnect(true); } else { - if (VizApp.getJmsServer() == null) { + if (VizApp.getJmsConnectionString() == null) { GetServersRequest req = new GetServersRequest(); GetServersResponse resp; try { resp = (GetServersResponse) ThriftClient .sendLocalizationRequest(req); - VizApp.setJmsServer(resp.getJmsServer()); + VizApp.setJmsConnectionString(resp + .getJmsConnectionString()); } catch (VizException e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); diff --git a/cave/com.raytheon.uf.viz.thinclient/src/com/raytheon/uf/viz/thinclient/localization/ThinClientLocalizationInitializer.java b/cave/com.raytheon.uf.viz.thinclient/src/com/raytheon/uf/viz/thinclient/localization/ThinClientLocalizationInitializer.java index e7c4116e77..c36a201899 100644 --- a/cave/com.raytheon.uf.viz.thinclient/src/com/raytheon/uf/viz/thinclient/localization/ThinClientLocalizationInitializer.java +++ b/cave/com.raytheon.uf.viz.thinclient/src/com/raytheon/uf/viz/thinclient/localization/ThinClientLocalizationInitializer.java @@ -48,8 +48,10 @@ import com.raytheon.uf.viz.thinclient.ui.ThinClientConnectivityDialog; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 23, 2011 bsteffen Initial creation - * Dec 06, 2012 1396 njensen Added setting VizServers + * Dec 06, 2012 1396 njensen Added setting VizServers * Jan 14, 2013 1469 bkowal Removed setting the hdf5 data directory + * Aug 27, 2013 2295 bkowal The entire jms connection string is + * now provided by EDEX. * * * @@ -92,7 +94,7 @@ public class ThinClientLocalizationInitializer extends LocalizationInitializer { GetServersResponse resp = (GetServersResponse) ThriftClient .sendLocalizationRequest(req); if (!disableJMS) { - VizApp.setJmsServer(resp.getJmsServer()); + VizApp.setJmsConnectionString(resp.getJmsConnectionString()); } } VizApp.setHttpServer(servicesProxy); @@ -103,12 +105,13 @@ public class ThinClientLocalizationInitializer extends LocalizationInitializer { HttpClient.getInstance().setCompressRequests(compressRequests); // use the proxy for all servers in VizServers + @SuppressWarnings("unchecked") Map serversMap = new DefaultedMap(servicesProxy); VizServers.getInstance().setServerLocations(serversMap); } else { processGetServers(); if (disableJMS) { - VizApp.setJmsServer(null); + VizApp.setJmsConnectionString(null); } } } diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/data/RadarRequestableData.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/data/RadarRequestableData.java index be8f1a1d20..0f0e3bc2f3 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/data/RadarRequestableData.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/data/RadarRequestableData.java @@ -27,7 +27,6 @@ import javax.measure.unit.Unit; import com.raytheon.uf.common.colormap.prefs.ColorMapParameters; import com.raytheon.uf.common.comm.CommunicationException; -import com.raytheon.uf.common.dataplugin.grid.GridConstants; import com.raytheon.uf.common.dataplugin.grid.GridRecord; import com.raytheon.uf.common.dataplugin.level.LevelFactory; import com.raytheon.uf.common.dataplugin.radar.RadarRecord; @@ -57,7 +56,8 @@ import com.raytheon.viz.grid.util.SliceUtil; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Mar 18, 2010 #4473 rjpeter Initial creation + * Mar 18, 2010 4473 rjpeter Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -69,9 +69,9 @@ public class RadarRequestableData extends GridRequestableData { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(RadarRequestableData.class); - private RadarRecord radarSource; + private final RadarRecord radarSource; - private RadarMapper tiler; + private final RadarMapper tiler; private WeakReference cache = null; @@ -107,7 +107,6 @@ public class RadarRequestableData extends GridRequestableData { Parameter parameter = new Parameter(parameterAbbrev, this.parameterName, unit); record.setParameter(parameter); - record.setPluginName(GridConstants.GRID); record.setDataTime(source.getDataTime()); record.constructDataURI(); setGridSource(record); diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/inv/GridUpdater.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/inv/GridUpdater.java index 367873f2e3..2b169677c9 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/inv/GridUpdater.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/inv/GridUpdater.java @@ -58,7 +58,8 @@ import com.raytheon.viz.grid.util.RadarAdapter; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Mar 25, 2010 bsteffen Initial creation + * Mar 25, 2010 bsteffen Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -88,9 +89,9 @@ public class GridUpdater implements IAlertObserver { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + getOuterType().hashCode(); - result = prime * result + ((node == null) ? 0 : node.hashCode()); - result = prime * result + timeOffset; + result = (prime * result) + getOuterType().hashCode(); + result = (prime * result) + ((node == null) ? 0 : node.hashCode()); + result = (prime * result) + timeOffset; return result; } @@ -101,22 +102,29 @@ public class GridUpdater implements IAlertObserver { */ @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } UpdateValue other = (UpdateValue) obj; - if (!getOuterType().equals(other.getOuterType())) + if (!getOuterType().equals(other.getOuterType())) { return false; + } if (node == null) { - if (other.node != null) + if (other.node != null) { return false; - } else if (!node.equals(other.node)) + } + } else if (!node.equals(other.node)) { return false; - if (timeOffset != other.timeOffset) + } + if (timeOffset != other.timeOffset) { return false; + } return true; } @@ -126,11 +134,11 @@ public class GridUpdater implements IAlertObserver { } - private Set myUpdates = new HashSet(); + private final Set myUpdates = new HashSet(); - private GridInventory inventory; + private final GridInventory inventory; - private Map> updateMap = new HashMap>(); + private final Map> updateMap = new HashMap>(); public GridUpdater(GridInventory inventory) { this.inventory = inventory; @@ -147,7 +155,7 @@ public class GridUpdater implements IAlertObserver { public synchronized void addNode(AbstractDerivedDataNode node) throws VizException { List dependencies = node.getDependencies(); - if (dependencies == null || dependencies.isEmpty()) { + if ((dependencies == null) || dependencies.isEmpty()) { return; } List dep = new ArrayList(dependencies); @@ -238,7 +246,7 @@ public class GridUpdater implements IAlertObserver { // Null means it is an alias model and supplement means // there exists a true GribNode buried under the or // node - if (method == null + if ((method == null) || !method.getName().equals("Supplement")) { inventory.reinitTree(); // System.out.println(((AbstractDerivedLevelNode) lNode) @@ -256,7 +264,6 @@ public class GridUpdater implements IAlertObserver { } for (UpdateValue value : set) { GridRecord fakeRec = new GridRecord(); - fakeRec.setPluginName(GridInventory.PLUGIN_NAME); Object obj = alert.decodedAlert.get("dataTime"); if (!(obj instanceof DataTime)) { throw new IllegalArgumentException( diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/inv/RadarUpdater.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/inv/RadarUpdater.java index 8dc2089ab6..f74e5ce966 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/inv/RadarUpdater.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/inv/RadarUpdater.java @@ -38,7 +38,8 @@ import com.raytheon.viz.grid.util.RadarProductCodeMapping; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Sep 20, 2012 bsteffen Initial creation + * Sep 20, 2012 bsteffen Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -77,33 +78,39 @@ public class RadarUpdater implements IAlertObserver { public int hashCode() { final int prime = 31; int result = 1; - result = prime - * result + result = (prime * result) + ((elevationAngle == null) ? 0 : elevationAngle.hashCode()); - result = prime * result + result = (prime * result) + ((productCode == null) ? 0 : productCode.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } CacheKey other = (CacheKey) obj; if (elevationAngle == null) { - if (other.elevationAngle != null) + if (other.elevationAngle != null) { return false; - } else if (!elevationAngle.equals(other.elevationAngle)) + } + } else if (!elevationAngle.equals(other.elevationAngle)) { return false; + } if (productCode == null) { - if (other.productCode != null) + if (other.productCode != null) { return false; - } else if (!productCode.equals(other.productCode)) + } + } else if (!productCode.equals(other.productCode)) { return false; + } return true; } @@ -122,7 +129,7 @@ public class RadarUpdater implements IAlertObserver { } - private Map cache = new LinkedHashMap( + private final Map cache = new LinkedHashMap( 100, .75f, true) { private static final long serialVersionUID = 2022670836957170184L; @@ -152,14 +159,14 @@ public class RadarUpdater implements IAlertObserver { for (AlertMessage alertMessage : alertMessages) { String icao = alertMessage.decodedAlert .get(RadarAdapter.ICAO_QUERY).toString(); - if (icao == null + if ((icao == null) || !icao.equalsIgnoreCase(configuredRadar.getRdaId())) { continue; } globalTimes = null; Object obj = alertMessage.decodedAlert .get(RadarAdapter.PRODUCT_CODE_QUERY); - if (obj == null || !(obj instanceof Integer)) { + if ((obj == null) || !(obj instanceof Integer)) { continue; } Integer productCode = (Integer) obj; @@ -169,12 +176,12 @@ public class RadarUpdater implements IAlertObserver { continue; } obj = alertMessage.decodedAlert.get("dataTime"); - if (obj == null || !(obj instanceof DataTime)) { + if ((obj == null) || !(obj instanceof DataTime)) { continue; } DataTime time = (DataTime) obj; obj = alertMessage.decodedAlert.get(RadarAdapter.TILT_QUERY); - if (obj == null || !(obj instanceof Double)) { + if ((obj == null) || !(obj instanceof Double)) { continue; } Double elevationAngle = (Double) obj; @@ -188,7 +195,6 @@ public class RadarUpdater implements IAlertObserver { e1.getLocalizedMessage(), e1); } GridRecord fakeRec = new GridRecord(); - fakeRec.setPluginName(GridInventory.PLUGIN_NAME); fakeRec.setDataTime(time); fakeRec.setDatasetId(RadarAdapter.RADAR_SOURCE); @@ -209,12 +215,12 @@ public class RadarUpdater implements IAlertObserver { private CacheKey getCacheKey(RadarRequestableLevelNode rNode) { Map rcMap = rNode.getRequestConstraintMap(); RequestConstraint rc = rcMap.get(RadarAdapter.PRODUCT_CODE_QUERY); - if (rc == null || rc.getConstraintType() != ConstraintType.EQUALS) { + if ((rc == null) || (rc.getConstraintType() != ConstraintType.EQUALS)) { return null; } Integer productCode = Integer.parseInt(rc.getConstraintValue()); rc = rcMap.get(RadarAdapter.TILT_QUERY); - if (rc == null || rc.getConstraintType() != ConstraintType.EQUALS) { + if ((rc == null) || (rc.getConstraintType() != ConstraintType.EQUALS)) { return null; } Double elevationAngle = Double.parseDouble(rc.getConstraintValue()); @@ -232,7 +238,7 @@ public class RadarUpdater implements IAlertObserver { if (entry == null) { return null; } - if (entry.insertTime + CACHE_TIME < System.currentTimeMillis()) { + if ((entry.insertTime + CACHE_TIME) < System.currentTimeMillis()) { cache.remove(cacheKey); return null; } @@ -248,7 +254,7 @@ public class RadarUpdater implements IAlertObserver { if (globalTimes == null) { return null; } - if (globalInsertTime + CACHE_TIME < System.currentTimeMillis()) { + if ((globalInsertTime + CACHE_TIME) < System.currentTimeMillis()) { globalTimes = null; return null; } diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/record/RequestableDataRecord.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/record/RequestableDataRecord.java index e064b79af2..aef53d86d3 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/record/RequestableDataRecord.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/record/RequestableDataRecord.java @@ -24,7 +24,6 @@ import java.util.Collection; import java.util.List; import com.raytheon.uf.common.dataplugin.PluginException; -import com.raytheon.uf.common.dataplugin.grid.GridConstants; import com.raytheon.uf.common.dataplugin.grid.GridRecord; import com.raytheon.uf.common.datastorage.Request; import com.raytheon.uf.common.datastorage.records.FloatDataRecord; @@ -40,17 +39,18 @@ import com.raytheon.viz.grid.util.TiltRequest; /** * A PDO that extends GridRecord and wraps a AbstractRequestableData to allow * derived parameters to be used anywhere GridRecords can be used. - * + * *
- *
+ * 
  * SOFTWARE HISTORY
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * Mar 18, 2010            bsteffen     Initial creation
+ * Mar 18, 2010            bsteffen    Initial creation
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
+ * 
  * 
- *
  * 
- * + * * @author bsteffen * @version 1.0 */ @@ -67,9 +67,10 @@ public class RequestableDataRecord extends GridRecord { GridCoverage coverage = null; if (requester.getSpace() instanceof GridCoverage) { coverage = (GridCoverage) requester.getSpace(); - if (requester instanceof GridRequestableData) { - setSecondaryId(((GridRequestableData) requester).getGridSource().getSecondaryId()); - } + if (requester instanceof GridRequestableData) { + setSecondaryId(((GridRequestableData) requester) + .getGridSource().getSecondaryId()); + } } setDatasetId(requester.getSource()); setLocation(coverage); @@ -78,7 +79,6 @@ public class RequestableDataRecord extends GridRecord { requester.getParameterName(), requester.getUnit()); setParameter(parameter); - setPluginName(GridConstants.GRID); setDataTime(requester.getDataTime()); try { constructDataURI(); @@ -142,7 +142,7 @@ public class RequestableDataRecord extends GridRecord { } } float[] data = new float[nx * ny]; - for (int i = 0; i < nx * ny; i++) { + for (int i = 0; i < (nx * ny); i++) { data[i] = ((Number) obj).floatValue(); } FloatDataRecord rec = new FloatDataRecord(this.getParameter() diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java index f933aa7674..f2ec58d204 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java @@ -136,7 +136,7 @@ import com.raytheon.uf.common.site.SiteMap; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; -import com.raytheon.uf.common.time.SimulatedTime; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.edex.decodertools.time.TimeTools; import com.raytheon.uf.edex.services.textdbsrv.IQueryTransport; import com.raytheon.uf.edex.wmo.message.WMOHeader; @@ -187,8 +187,6 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; import com.raytheon.viz.ui.dialogs.ICloseCallback; import com.raytheon.viz.ui.dialogs.SWTMessageBox; -// import com.raytheon.uf.viz.core.RGBColors; - /** * Main Text Editor dialog. * @@ -322,15 +320,17 @@ import com.raytheon.viz.ui.dialogs.SWTMessageBox; * 31JAN2013 1568 rferrel Spell checker now tied to this dialog instead of parent. * 26Apr2013 16123 snaples Removed setFocus to TextEditor in postExecute method. * 07Jun2013 1981 mpduff Add user id to OUPRequest as it is now protected. - * 20Jun2013 15733 XHuang Add functionalities that get Font size, Text colors from - * *.xml files in localization; - * add selection listener to catch the highlight words and - * set the highlight colors. + * 20Jun2013 15733 XHuang Add functionalities that get Font size, Text colors from + * *.xml files in localization; + * add selection listener to catch the highlight words and + * set the highlight colors. * 23Jul2013 2176 jsanchez Added a new confirmation message for emergency warnings. * 25July2013 15733 GHull Read font and color prefs from TextEditorCfg. * 23Aug2013 DR 16514 D. Friedman Fix handling of completed product requests. Do not change * command history or close browser window for "update obs". * 04Sep2013 2176 jsanchez Changed the order of the QC check dialogs. + * 12Sep2013 DR 2249 rferrel Change Time stamp in file name created by warngen to use + * simulated time. * * * @author lvenable @@ -378,8 +378,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, */ private static final int UPDATE_FG = SWT.COLOR_WHITE; - private final int HIGHLIGHT_BG = SWT.COLOR_RED; - /** * The length of BEGIN_ELEMENT_TAG. */ @@ -1087,11 +1085,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, */ private SearchReplaceDlg searchReplaceDlg; - /** - * Flag to indicate if the document being edited has been modified. - */ - private boolean dirty = false; - /** * Flag to indicate if the document being edited has been saved. */ @@ -1504,7 +1497,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, return; } - if (afosBrowser != null + if ((afosBrowser != null) && afosBrowser.isAfosBrowserActive()) { afosBrowser.hide(); displayAfosBrowser = true; @@ -1629,7 +1622,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, @Override public void widgetSelected(SelectionEvent event) { - if (faxAllMsgDlg == null || faxAllMsgDlg.isDisposed()) { + if ((faxAllMsgDlg == null) || faxAllMsgDlg.isDisposed()) { faxAllMsgDlg = new FaxMessageDlg(shell); faxAllMsgDlg.setInitialText(textEditor.getText()); faxAllMsgDlg.open(); @@ -1644,7 +1637,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, faxSelectionItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - if (faxMsgDlg == null || faxMsgDlg.isDisposed()) { + if ((faxMsgDlg == null) || faxMsgDlg.isDisposed()) { faxMsgDlg = new FaxMessageDlg(shell); faxMsgDlg.setInitialText(textEditor.getSelectionText()); faxMsgDlg.open(); @@ -1659,7 +1652,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, configAutoFaxItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - if (ldadFaxSitesDlg == null || ldadFaxSitesDlg.isDisposed()) { + if ((ldadFaxSitesDlg == null) || ldadFaxSitesDlg.isDisposed()) { ldadFaxSitesDlg = new LdadFaxSitesDlg(shell); ldadFaxSitesDlg.open(); } else { @@ -1947,7 +1940,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, searchItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - if (searchReplaceDlg == null || searchReplaceDlg.isDisposed()) { + if ((searchReplaceDlg == null) || searchReplaceDlg.isDisposed()) { searchReplaceDlg = new SearchReplaceDlg(shell, textEditor, inEditMode); searchReplaceDlg.open(); @@ -2449,7 +2442,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } } } - } /** @@ -2475,7 +2467,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } // skip any spaces at cursor - while (text.charAt(searchOffset) == ' ' && searchOffset > 0) { + while ((text.charAt(searchOffset) == ' ') && (searchOffset > 0)) { searchOffset--; } @@ -2506,8 +2498,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } // skip any spaces at cursor - while (text.charAt(searchOffset) == ' ' - && searchOffset < text.length()) { + while ((text.charAt(searchOffset) == ' ') + && (searchOffset < text.length())) { searchOffset++; } @@ -2516,7 +2508,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // set missing to end of text if (index == -1) { index = text.length() - 1; - } else if (index < text.length() - 1) { + } else if (index < (text.length() - 1)) { // skip the space index++; } @@ -2677,7 +2669,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, int line = textEditor.getLineAtOffset(caretOffset); int finish; - if (line + 1 < textEditor.getLineCount()) { + if ((line + 1) < textEditor.getLineCount()) { finish = textEditor.getOffsetAtLine(line + 1) - 1; } else { // Guard against over-indexing in getText() @@ -2833,7 +2825,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } } - if (selectionCnt == 0 && autoWrapCfg.getButtons().size() > 0) { + if ((selectionCnt == 0) && (autoWrapCfg.getButtons().size() > 0)) { WrapButtonCfg buttonCfg = autoWrapCfg.getButtons().get(0); message.append("No button selected. Selecting top item \"") .append(buttonCfg.getLabelName()).append("\"\n"); @@ -2922,7 +2914,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, private void createTextCharWrapDialog(final int rangeStart, final int rangeEnd) { // Create the text character wrap dialog. - if (textCharWrapDlg == null || textCharWrapDlg.isDisposed()) { + if ((textCharWrapDlg == null) || textCharWrapDlg.isDisposed()) { textCharWrapDlg = new TextCharWrapDlg(shell, this, otherCharWrapCol, rangeStart, rangeEnd); @@ -2954,8 +2946,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, FontSizeCfg fontSizeCfg = TextEditorCfg.getTextEditorCfg() .getFontSizeCfg(); - SizeButtonCfg seldFontBtn = TextEditorCfg.getTextEditorCfg() - .getSelectedFontButton(); + SizeButtonCfg seldFontBtn = TextEditorCfg.getSelectedFontButton(); for (SizeButtonCfg buttonCfg : fontSizeCfg.getButtons()) { MenuItem item = new MenuItem(fontSizeSubMenu, SWT.RADIO); @@ -3399,7 +3390,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, public void widgetDefaultSelected(SelectionEvent event) { awipsIdTF.setText(awipsIdTF.getText().trim().toUpperCase()); int charCount = awipsIdTF.getCharCount(); - if (charCount < 4 || charCount > 6) { + if ((charCount < 4) || (charCount > 6)) { userInformation("Must enter a 4 to 6 character AWIPS ID"); awipsIdTF.setFocus(); return; @@ -3502,7 +3493,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, */ private void clearUpdateFlag(int offset) { for (StyleRange range : textEditor.getStyleRanges()) { - if (range.start <= offset && offset < (range.start + range.length)) { + if ((range.start <= offset) + && (offset < (range.start + range.length))) { StyleRange lock = (StyleRange) range.clone(); lock.background = null; lock.foreground = null; @@ -3702,13 +3694,13 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, editorInsertCmb.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - if (editorInsertCmb.getSelectionIndex() == INSERT_TEXT - && overwriteMode == true) { + if ((editorInsertCmb.getSelectionIndex() == INSERT_TEXT) + && (overwriteMode == true)) { textEditor.invokeAction(ST.TOGGLE_OVERWRITE); overwriteMode = false; overStrikeItem.setSelection(false); - } else if (editorInsertCmb.getSelectionIndex() == OVERWRITE_TEXT - && overwriteMode == false) { + } else if ((editorInsertCmb.getSelectionIndex() == OVERWRITE_TEXT) + && (overwriteMode == false)) { textEditor.invokeAction(ST.TOGGLE_OVERWRITE); overwriteMode = true; overStrikeItem.setSelection(true); @@ -3778,7 +3770,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, textEditor.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { - if (e.keyCode == SWT.ARROW_LEFT && !textEditor.getEditable()) { + if ((e.keyCode == SWT.ARROW_LEFT) && !textEditor.getEditable()) { commandHistory.resetIndex(CommandType.AFOS); ICommand command = commandHistory .getPreviousCommand(CommandType.AFOS); @@ -3789,7 +3781,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, executeCommand(cmd); } } - } else if (e.keyCode == SWT.ARROW_RIGHT + } else if ((e.keyCode == SWT.ARROW_RIGHT) && !textEditor.getEditable()) { commandHistory.resetIndex(CommandType.AFOS); ICommand command = commandHistory @@ -3841,13 +3833,13 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (textEditor.getEditable() == false) { return; } - if (event.keyCode == SWT.DEL || event.keyCode == SWT.BS - || event.keyCode == SWT.SHIFT) { + if ((event.keyCode == SWT.DEL) || (event.keyCode == SWT.BS) + || (event.keyCode == SWT.SHIFT)) { // Do nothing... // We need to capture the Delete, Backspace and Shift // keystrokes... - } else if (event.keyCode == SWT.HOME - || event.keyCode == SWT.END) { + } else if ((event.keyCode == SWT.HOME) + || (event.keyCode == SWT.END)) { if (!textEditor.getEditable()) { int offset = 0; @@ -3859,17 +3851,17 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, textEditor.showSelection(); event.doit = false; } - } else if (event.keyCode == SWT.PAGE_UP - && event.stateMask == SWT.CTRL) { + } else if ((event.keyCode == SWT.PAGE_UP) + && (event.stateMask == SWT.CTRL)) { event.doit = false; // Ingnore Ctrl + PageUp - } else if (event.keyCode == SWT.PAGE_DOWN - && event.stateMask == SWT.CTRL) { + } else if ((event.keyCode == SWT.PAGE_DOWN) + && (event.stateMask == SWT.CTRL)) { event.doit = false; // Ignore Ctrl + PageDown - } else if (event.keyCode == SWT.PAGE_UP - && event.stateMask == (SWT.CTRL | SWT.SHIFT)) { + } else if ((event.keyCode == SWT.PAGE_UP) + && (event.stateMask == (SWT.CTRL | SWT.SHIFT))) { event.doit = false; // Ignore Ctrl+Shift+PageUp - } else if (event.keyCode == SWT.PAGE_DOWN - && event.stateMask == (SWT.CTRL | SWT.SHIFT)) { + } else if ((event.keyCode == SWT.PAGE_DOWN) + && (event.stateMask == (SWT.CTRL | SWT.SHIFT))) { event.doit = false; // Ignore Ctrl+Shift+PageDown } else if (event.keyCode == SWT.INSERT) { // Ins key on the keypad @@ -3891,20 +3883,13 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // if some event is going to happen and the key was not enter // then set userKeyPressed to true - if (event.doit && event.character != 0 - && event.character != '\r' && event.character != '\n') { + if (event.doit && (event.character != 0) + && (event.character != '\r') + && (event.character != '\n')) { userKeyPressed = true; } } }); - textEditor.addModifyListener(new ModifyListener() { - - @Override - public void modifyText(ModifyEvent e) { - // when we modify the text, we want to set the 'dirty' flag. - dirty = true; - } - }); textEditor.addMouseListener(new MouseListener() { @Override @@ -3952,38 +3937,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, }); } - // private TextColorsCfg getTextColorCfg() { - // TextColorsCfg textColorsCfg = - // TextEditorCfg.getTextEditorCfg().getTextColorsCfg(); - // - // // Perform Sanity Checks on configuration. - // StringBuilder message = new StringBuilder(); - // - // for (TextColorElement textElm : textColorsCfg.getTextColorElements()) { - // String prmtName = textElm.getParamName(); - // if (prmtName == null) { - // message.append("Item \"paramName\" problem!\n"); - // - // } - // - // if( textElm.getColor() == null ) { - // message.append("Item \"color\" data enter problem!\n"); - // } - // - // if (message.length() > 0) { - // message.insert(0, "TextColorsCfg broblem(s): "); - // IUFStatusHandler statusHandler = UFStatus - // .getHandler(TextEditorDialog.class); - // statusHandler.handle(Priority.PROBLEM, message.toString()); - // } - // - // } - // - // return textColorsCfg; - // } - private void setDefaultTextColor(TextEditorCfg txtClrCfg) { - textBackground = new Color(shell.getDisplay(), txtClrCfg.getTextBackgroundColor()); textForeground = new Color(shell.getDisplay(), @@ -4120,7 +4074,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, private void enterEditor() { StdTextProduct product = TextDisplayModel.getInstance() .getStdTextProduct(token); - if (product != null + if ((product != null) && gfeForbidden(product.getCccid(), product.getNnnid())) { // Pop up forbidden window. inEditMode = false; @@ -4130,7 +4084,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // Set the edit mode flag to true. inEditMode = true; int ranges[] = textEditor.getRanges(); - if (ranges == null || ranges.length == 0) { + if ((ranges == null) || (ranges.length == 0)) { originalText = removeSoftReturns(textEditor.getText()); } else { textEditor.setText(originalText); @@ -4221,7 +4175,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, stopAutoSave(); - if (warnGenFlag && queuedProduct != null) { + if (warnGenFlag && (queuedProduct != null)) { // Display the WarnGen in the queue, perform the popup and stop the // cancel. showWarngenProduct(queuedProduct, queuedNotify); @@ -4275,9 +4229,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, originalText = combineOriginalMessage(); } - // update editor status flags - dirty = false; - if (originalText != null) { textEditor.setText(originalText); } @@ -4317,8 +4268,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, * false otherwise. */ private void editHeader(String warning, boolean closeEditorOnCancel) { - if (headerEditSession != null) + if (headerEditSession != null) { return; + } // Create and display the AWIPS header block dialog. AWIPSHeaderBlockDlg awipsHeaderBlockDlg = new AWIPSHeaderBlockDlg( @@ -4377,16 +4329,18 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, editing = true; } else { - if (lastSession == HeaderEditSession.CLOSE_ON_EXIT) + if (lastSession == HeaderEditSession.CLOSE_ON_EXIT) { editing = !cancelEditor(false); + } } - if (lastSession == HeaderEditSession.CLOSE_ON_EXIT) + if (lastSession == HeaderEditSession.CLOSE_ON_EXIT) { if (editing) { StdTextProduct product = TextDisplayModel.getInstance() .getStdTextProduct(token); - if (product == null) + if (product == null) { return; + } if (autoSave == null) { // user can cancel the edit immediately when the header is // displayed, verify it was not cancelled before starting @@ -4398,6 +4352,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } else { stopAutoSave(); } + } } /** @@ -4436,8 +4391,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // Disabled when in editor mode // --------------------------------- resendWarningProductnItem.setEnabled(!inEditMode - && textEditor.getText() != null - && textEditor.getText().length() > 0); + && (textEditor.getText() != null) + && (textEditor.getText().length() > 0)); // --------------------------------- // File Menu menu items @@ -4658,7 +4613,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, dlg.setText("Attach File"); dlg.setFilterNames(FILTER_NAMES); dlg.setFilterExtensions(FILTER_EXTS); - if (attachedFilename != null && attachedFilename.trim().length() > 0) { + if ((attachedFilename != null) + && (attachedFilename.trim().length() > 0)) { int startIndex = statusBarLabel.getText().indexOf(":") + 1; int endIndex = statusBarLabel.getText().lastIndexOf(File.separator) + 1; String filterPath = statusBarLabel.getText().substring(startIndex, @@ -4676,9 +4632,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, byte[] bytes = new byte[(int) file.length()]; int offset = 0; int numRead = 0; - while (offset < bytes.length - && (numRead = in.read(bytes, offset, bytes.length - - offset)) >= 0) { + while ((offset < bytes.length) + && ((numRead = in.read(bytes, offset, bytes.length + - offset)) >= 0)) { offset += numRead; } in.close(); @@ -4734,7 +4690,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, s.append(removeSoftReturns(textEditor.getText())); int eolIndex = s.indexOf("\n"); int ddhhmmIndex = s.indexOf("DDHHMM"); - if (ddhhmmIndex > 0 && ddhhmmIndex < eolIndex) { + if ((ddhhmmIndex > 0) && (ddhhmmIndex < eolIndex)) { s.replace(ddhhmmIndex, ddhhmmIndex + 6, "000000"); } out.append(s); @@ -5011,10 +4967,16 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, oup.setSource("TextWS"); oup.setWmoType(fixNOR(prod.getBbbid())); oup.setUserDateTimeStamp(prod.getHdrtime()); - oup.setFilename(awipsID + ".wan" - + (System.currentTimeMillis() / 1000)); + StringBuilder fileName = new StringBuilder(); + + // The .wan extension followed by the 10 digit epoch seconds + // of simulated time is used in EDEX's WarningDecoder to + // determine the base time. + fileName.append(awipsID).append(".wan") + .append(TimeUtil.getUnixTime(TimeUtil.newDate())); + oup.setFilename(fileName.toString()); oup.setAddress(addressee); - if (attachedFile != null && attachedFilename != null) { + if ((attachedFile != null) && (attachedFilename != null)) { oup.setAttachedFile(attachedFile); oup.setAttachedFilename(attachedFilename); } @@ -5050,7 +5012,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } } - if (inEditMode == false && resend == false) { + if ((inEditMode == false) && (resend == false)) { saved = true; StdTextProductId finalProduct = this.getStdTextProduct() .getProdId(); @@ -5110,7 +5072,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, synchronized private void saveProduct() { StdTextProduct product = TextDisplayModel.getInstance() .getStdTextProduct(token); - if (product != null + if ((product != null) && gfeForbidden(product.getCccid(), product.getNnnid())) { // Pop up forbidden window. inEditMode = false; @@ -5120,7 +5082,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, boolean successful = saveEditedProduct(false, false, false); if (successful) { // reset the editor status flags - dirty = false; saved = true; replaceWorkProductId(); originalText = combineOriginalMessage(); @@ -5144,7 +5105,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, boolean resend, boolean isOperationalSend) { StdTextProduct product = TextDisplayModel.getInstance() .getStdTextProduct(token); - if (product != null + if ((product != null) && gfeForbidden(product.getCccid(), product.getNnnid())) { // Pop up forbidden window. inEditMode = false; @@ -5157,7 +5118,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, * DR14613 - string currectDate is derived from Date now ensuring the * same time in WMO heading and in the MND heading. */ - Date now = SimulatedTime.getSystemTime().getTime(); + Date now = TimeUtil.newDate(); String currentDate = getCurrentDate(now); TextDisplayModel tdmInst = TextDisplayModel.getInstance(); @@ -5186,7 +5147,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, String productText = resend ? resendMessage() : combineOriginalMessage(); - if (warnGenFlag == true && resend == false) { + if ((warnGenFlag == true) && (resend == false)) { productText = removeSoftReturns(productText); } @@ -5291,16 +5252,18 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, String[] parts = productText.split("\n", 2); if (parts.length > 0) { String[] headerParts = parts[0].split("\\s+", 0); - if (headerParts.length >= 3) + if (headerParts.length >= 3) { headerParts[2] = ddhhmm; + } // TODO: else raise error? StringBuilder sb = new StringBuilder(productText.length()); boolean first = true; for (String s : headerParts) { - if (first) + if (first) { first = false; - else + } else { sb.append(' '); + } sb.append(s); } if (parts.length > 1) { @@ -5342,8 +5305,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, textEditor.addVerifyListener(TextEditorDialog.this); for (StyleRange lock : locks) { - if (0 <= lock.start - && lock.start + lock.length <= textEditor.getCharCount()) { + if ((0 <= lock.start) + && ((lock.start + lock.length) <= textEditor.getCharCount())) { textEditor.setStyleRange(lock); } } @@ -5408,7 +5371,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, private boolean saveStoredTextProduct(StdTextProduct storedProduct) { StdTextProduct product = TextDisplayModel.getInstance() .getStdTextProduct(token); - if (product != null + if ((product != null) && gfeForbidden(product.getCccid(), product.getNnnid())) { // Pop up forbidden window. inEditMode = false; @@ -5478,13 +5441,13 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, do { startIndex = sb.indexOf(BEGIN_ELEMENT_TAG, currentIndex); endIndex = sb.indexOf(END_ELEMENT_TAG, currentIndex); - } while (startIndex > 0 - && endIndex > 0 - && (currentIndex = sb.indexOf(BEGIN_ELEMENT_TAG, - startIndex + BEGIN_ELEMENT_TAG_LEN)) > 0 - && currentIndex < endIndex); + } while ((startIndex > 0) + && (endIndex > 0) + && ((currentIndex = sb.indexOf(BEGIN_ELEMENT_TAG, + startIndex + BEGIN_ELEMENT_TAG_LEN)) > 0) + && (currentIndex < endIndex)); - if (currentIndex > 0 && currentIndex < endIndex) { + if ((currentIndex > 0) && (currentIndex < endIndex)) { startIndex = currentIndex; } @@ -5537,14 +5500,15 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, int length = event.end - event.start; try { if (length == 0) { - if (event.start != 0 - && event.start != textEditor.getCharCount()) { + if ((event.start != 0) + && (event.start != textEditor.getCharCount())) { int ranges[] = textEditor.getRanges(event.start - 1, length + 2); for (int i = 0; i < ranges.length; i += 2) { int rangeStart = ranges[i]; int rangeEnd = rangeStart + ranges[i + 1]; - if (event.start > rangeStart && event.start < rangeEnd) { + if ((event.start > rangeStart) + && (event.start < rangeEnd)) { event.doit = false; /* * DR15704 - this needs to be set so the rewrap is @@ -5557,7 +5521,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } } else { int ranges[] = textEditor.getRanges(event.start, length); - if (inEditMode && ranges != null && ranges.length != 0) { + if (inEditMode && (ranges != null) && (ranges.length != 0)) { event.doit = false; /* * DR15704 - this needs to be set so the rewrap is not @@ -5698,7 +5662,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, numberOfBlankLines++; line = textEditor.getLine(thisLine + numberOfLinesOfHeaderText + numberOfBlankLines); - } while (line.length() == 0 || line.equals("")); + } while ((line.length() == 0) || line.equals("")); // Note: 'st' is a reference to 'textEditor'... // delelete the header from the text in 'textEditor' finish = textEditor.getOffsetAtLine(thisLine @@ -5712,8 +5676,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, textEditor.setText(""); } } - // set editor status flags - dirty = false; } /** @@ -5763,7 +5725,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, */ private String updateVtecTimes(String product, VtecObject vtecObj, Date now) { - if (vtecObj == null || vtecObj.getAction().equals("COR")) { + if ((vtecObj == null) || vtecObj.getAction().equals("COR")) { return product; } // Update the vtec start time @@ -5945,7 +5907,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, boolean validExecuteCommand = command != null; if (validExecuteCommand) { - if (prodList != null && prodList.size() > 0) { + if ((prodList != null) && (prodList.size() > 0)) { if (prodList.size() > 1) { if (CommandType.WMO.equals(command.getType())) { final boolean hasAtt = hasAttachment; @@ -6433,7 +6395,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, public void manageScriptOutputWindow(boolean visible) { if (visible) { // need to set state of menu item to true - if (scriptsShowOutputItem != null + if ((scriptsShowOutputItem != null) && !scriptsShowOutputItem.isDisposed()) { scriptsShowOutputItem.setSelection(true); } @@ -6444,7 +6406,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } // create the script output window - if (scriptOutput == null || !scriptOutput.isDisposed()) { + if ((scriptOutput == null) || !scriptOutput.isDisposed()) { scriptOutput = new ScriptOutputDlg(shell, token); // open the script output window scriptOutput.setCloseCallback(new ICloseCallback() { @@ -6452,7 +6414,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, @Override public void dialogClosed(Object returnValue) { // update the menu following close - if (scriptsShowOutputItem != null + if ((scriptsShowOutputItem != null) && !scriptsShowOutputItem.isDisposed()) { scriptsShowOutputItem.setSelection(false); } @@ -6471,7 +6433,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (scriptOutput != null) { scriptOutput.close(); } else { - if (scriptsShowOutputItem != null + if ((scriptsShowOutputItem != null) && !scriptsShowOutputItem.isDisposed()) { scriptsShowOutputItem.setSelection(false); } @@ -7062,7 +7024,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, String body = textEditor.getText(); StdTextProduct stdTextProduct = TextDisplayModel.getInstance() .getStdTextProduct(token); - if (body == null || body.length() == 0) { + if ((body == null) || (body.length() == 0)) { userInformation("Resend Warning Product Error", "There is no product to send. \n Action aborted!"); resend = false; @@ -7113,7 +7075,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, String text = textEditor.getText(); int startIndex = text.indexOf("!--"); int endIndex = text.indexOf("--!", startIndex); - while (startIndex >= 0 && endIndex >= startIndex) { + while ((startIndex >= 0) && (endIndex >= startIndex)) { String part1 = text.substring(0, startIndex).trim(); String part2 = text.substring(endIndex + 3).trim(); text = part1 + "\n\n" + part2; @@ -7176,7 +7138,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // delete and write new file, rename didn't always work // rename would end up writing a new file every time and // kept the original in sync - if (file != null && file.exists()) { + if ((file != null) && file.exists()) { file.delete(); } @@ -7221,8 +7183,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, xml = new String(b); } - rval = (StdTextProduct) SerializationUtil - .unmarshalFromXml(xml); + rval = SerializationUtil.unmarshalFromXml( + StdTextProduct.class, xml); } catch (Exception e) { statusHandler.handle(Priority.PROBLEM, "Retrieval of product failed", e); @@ -7264,13 +7226,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, return success; } - public void stopTimer() { - if (timer != null) { - timer.cancel(); - timer = null; - } - } - private void setupTimer() { if (timer != null) { timer.cancel(); @@ -7508,7 +7463,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, int x = rect.width / 4; // account for dual monitor - if (rect.width > rect.height * 2) { + if (rect.width > (rect.height * 2)) { x /= 2; } @@ -7517,7 +7472,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, .intValue(); int offset = (editorIndex - 1) * 25; - getShell().setLocation(x + offset, rect.height / 4 + offset); + getShell().setLocation(x + offset, (rect.height / 4) + offset); } inEditMode = false; @@ -7656,8 +7611,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (hasLockAtOffset(offset)) { StyleRange[] ranges = textEditor.getStyleRanges(); for (StyleRange range : ranges) { - if (offset >= range.start - && offset <= range.start + range.length) { + if ((offset >= range.start) + && (offset <= (range.start + range.length))) { rval = range.start; break; } @@ -7677,8 +7632,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (hasLockAtOffset(offset)) { StyleRange[] ranges = textEditor.getStyleRanges(); for (StyleRange range : ranges) { - if (offset >= range.start - && offset <= range.start + range.length) { + if ((offset >= range.start) + && (offset <= (range.start + range.length))) { rval = range.length; break; } @@ -7700,7 +7655,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, int lineLength = textEditor.getLine(lineNumber).length(); StyleRange[] ranges = textEditor.getStyleRanges(lineStart, lineLength); - if (ranges != null && ranges.length > 0) { + if ((ranges != null) && (ranges.length > 0)) { rval = true; } return rval; @@ -7783,7 +7738,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, padding = " "; } - if (inLocations && paragraphStartLineNumber == lineNumber) { + if (inLocations && (paragraphStartLineNumber == lineNumber)) { // Keep LOCATIONS first line short & don't paste more to it. if (line.indexOf("...") == line.lastIndexOf("...")) { return; @@ -7815,7 +7770,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (lineNumber < endWrapLine) { // May have more lines to wrap. int nextLine = lineNumber + 1; - while (nextLine <= endWrapLine + while ((nextLine <= endWrapLine) && textEditor.getLine(nextLine).trim().isEmpty()) { ++nextLine; } @@ -7848,7 +7803,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // If the next line is part of the same paragraph and not empty make it // part of the current line. - if (lineNumber + 1 < textEditor.getLineCount()) { + if ((lineNumber + 1) < textEditor.getLineCount()) { // if the next line does not start a new paragraph if (!isParagraphStart(lineNumber + 1)) { // if the next line is not empty @@ -7860,8 +7815,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, String allText = textEditor.getText(); int eol = textEditor.getOffsetAtLine(lineNumber) + line.length(); - if (allText.charAt(eol) == '\r' - && allText.charAt(eol + 1) == '\n') { + if ((allText.charAt(eol) == '\r') + && (allText.charAt(eol + 1) == '\n')) { deleteLen = 2; } else if (allText.charAt(eol) == '\n') { deleteLen = 1; @@ -7876,7 +7831,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // if the line does not start with a lock int lineStart = textEditor .getOffsetAtLine(lineNumber + 1); - if (padding.length() > 0 + if ((padding.length() > 0) && textEditor.getLine(lineNumber + 1) .startsWith(padding)) { // add two to skip over padding if it exists and @@ -7889,7 +7844,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // if the lock is too long to fit on this line do // not bring up the next line int lockLength = getLengthOfLockAtOffset(lockStart); - if (line.length() + lockLength > charWrapCol) { + if ((line.length() + lockLength) > charWrapCol) { // lock is too long, do not bring up next // line return; @@ -7900,7 +7855,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, int lineStartOffset = textEditor .getOffsetAtLine(lineNumber); int newlinePosition = lineStartOffset + line.length(); - if (padding.length() > 0 + if ((padding.length() > 0) && textEditor.getLine(lineNumber + 1).startsWith( " ")) { deleteLen += padding.length(); @@ -7999,7 +7954,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, int padLen = padding.length(); if (padLen > 0) { int cnt = 0; - while (cnt < padLen + while ((cnt < padLen) && textEditor.getText(position + cnt, position + cnt) .equals(" ")) { ++cnt; @@ -8021,7 +7976,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, */ private void checkAndWrapNextLine(int line) { // if there is a next line - if (line + 1 < textEditor.getLineCount()) { + if ((line + 1) < textEditor.getLineCount()) { // if the next line does not start a new paragraph if (!isParagraphStart(line + 1)) { // if the next line is not empty ( marks the end of a paragraph @@ -8029,10 +7984,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (!textEditor.getLine(line + 1).trim().isEmpty()) { // rewrap the next line rewrapInternal(line + 1); - } else if (line + 1 < endWrapLine) { + } else if ((line + 1) < endWrapLine) { // See if another paragraph needs to be wrapped. int nextLine = line + 1; - while (nextLine <= endWrapLine + while ((nextLine <= endWrapLine) && textEditor.getLine(nextLine).trim().isEmpty()) { ++nextLine; } @@ -8040,7 +7995,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, rewrapInternal(nextLine); } } - } else if (line + 1 <= endWrapLine) { + } else if ((line + 1) <= endWrapLine) { rewrapInternal(line + 1); } } @@ -8083,7 +8038,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (isPreviousLineWrapped) { return; } - if (line - 1 > 0) { + if ((line - 1) > 0) { // if the previous line does not start a new paragraph if (!isParagraphStart(line - 1)) { // if the previous line is not empty ( marks the end of a @@ -8093,10 +8048,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // rewrap the previous line isPreviousLineWrapped = true; rewrapInternal(line - 1); - } else if (line - 1 < endWrapLine) { + } else if ((line - 1) < endWrapLine) { // See if another paragraph needs to be wrapped. int nextLine = line - 1; - while (nextLine <= endWrapLine + while ((nextLine <= endWrapLine) && textEditor.getLine(nextLine).trim().isEmpty()) { --nextLine; } @@ -8105,7 +8060,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, rewrapInternal(nextLine); } } - } else if (line - 1 <= endWrapLine) { + } else if ((line - 1) <= endWrapLine) { isPreviousLineWrapped = true; rewrapInternal(line - 1); } @@ -8122,7 +8077,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, */ private boolean checkParagraphPadding(String firstLine) { boolean rval = false; - if (firstLine.length() > 0 + if ((firstLine.length() > 0) && PADDED_PARAGRAPH_DELIMITERS.contains(firstLine.substring(0, 1))) { rval = true; @@ -8168,7 +8123,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, rval = true; } else if (PARAGRAPH_DELIMITERS.contains(lineText.substring(0, 1))) { rval = true; - } else if (isSaoMetarFlag && lineText.startsWith(" ") == false) { + } else if (isSaoMetarFlag && (lineText.startsWith(" ") == false)) { rval = true; } return rval; @@ -8276,8 +8231,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (lineOffset > 0) { boolean goBack = true; - while (goBack && lineIndex > 0) { - if (lineText.startsWith(" ") || lineText.length() == 0) { + while (goBack && (lineIndex > 0)) { + if (lineText.startsWith(" ") || (lineText.length() == 0)) { lineIndex--; } else { String tempLine = st.getLine(lineIndex); @@ -8306,10 +8261,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, boolean result = false; byte[] bytesFromFile = getBytesFromFile(file); - for (int i = 0; i < bytesFromFile.length; i++) { - byte b = bytesFromFile[i]; - if (b == 0x09 || b == 0x0A || b == 0x0C || b == 0x0D - || (b >= 0x20 && b <= 0x7E)) { + for (byte b : bytesFromFile) { + if ((b == 0x09) || (b == 0x0A) || (b == 0x0C) || (b == 0x0D) + || ((b >= 0x20) && (b <= 0x7E))) { result = true; break; } @@ -8322,38 +8276,47 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, * Get the contents of file as a byte array. * * @param file - * @return + * @return bytes * @throws IOException */ private static byte[] getBytesFromFile(File file) throws IOException { - InputStream is = new FileInputStream(file); + InputStream is = null; + byte[] bytes = null; - // Get the size of the file - long length = file.length(); + try { + is = new FileInputStream(file); - if (length > Integer.MAX_VALUE) { - // File is too large + // Get the size of the file + long length = file.length(); + + if (length > Integer.MAX_VALUE) { + // File is too large + } + + // Create the byte array to hold the data + bytes = new byte[(int) length]; + + // Read in the bytes + int offset = 0; + int numRead = 0; + while ((offset < bytes.length) + && ((numRead = is + .read(bytes, offset, bytes.length - offset)) >= 0)) { + offset += numRead; + } + + // Ensure all the bytes have been read in + if (offset < bytes.length) { + throw new IOException("Could not completely read file " + + file.getName()); + } + } finally { + + // Close the input stream and return bytes + if (is != null) { + is.close(); + } } - - // Create the byte array to hold the data - byte[] bytes = new byte[(int) length]; - - // Read in the bytes - int offset = 0; - int numRead = 0; - while (offset < bytes.length - && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) { - offset += numRead; - } - - // Ensure all the bytes have been read in - if (offset < bytes.length) { - throw new IOException("Could not completely read file " - + file.getName()); - } - - // Close the input stream and return bytes - is.close(); return bytes; } @@ -8395,7 +8358,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, */ private boolean gfeForbidden(String ccc, String nnn) { boolean retval = false; - if (ccc != null && nnn != null) { + if ((ccc != null) && (nnn != null)) { if (gfePils.contains(nnn) && !exceptionCCCs.contains(ccc)) { retval = true; } @@ -8436,9 +8399,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, * @return */ private static String fixNOR(String bbb) { - if ("NOR".equals(bbb)) + if ("NOR".equals(bbb)) { return ""; - else + } else { return bbb; + } } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/FollowupData.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/FollowupData.java index ef06609c0c..76729458ce 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/FollowupData.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/FollowupData.java @@ -53,7 +53,7 @@ public class FollowupData extends AbstractWarningRecord { /** * String displayed in the drop down update list. */ - private String displayString; + private final String displayString; /** * String used to test if this object is equivalent to one of the updated @@ -64,7 +64,7 @@ public class FollowupData extends AbstractWarningRecord { /** * Information string used when the follow up is no longer valid or allowed. */ - private String expirationString; + private final String expirationString; public FollowupData(WarningAction action, AbstractWarningRecord record) { super(record); @@ -194,4 +194,13 @@ public class FollowupData extends AbstractWarningRecord { return expirationString; } + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.dataplugin.PluginDataObject#getPluginName() + */ + @Override + public String getPluginName() { + return "followUpWarning"; + } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java index 22fcb375ee..a9f7e18629 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java @@ -190,6 +190,7 @@ import com.vividsolutions.jts.io.WKTReader; * 08/19/2013 2177 jsanchez Set a GeneralGridGeometry object in the GeospatialDataList. * 09/17/2013 DR 16496 D. Friedman Make editable state more consistent. * 10/01/2013 DR 16632 Qinglu Lin Catch exceptions thrown while doing areaPercent computation and union(). + * 10/15/2013 2463 jsanchez Create a square polygon when time matched with a resource with no data. * 10/21/2013 DR 16632 D. Friedman Modify areaPercent exception handling. Fix an NPE. * Use A1 hatching behavior when no county passes the inclusion filter. * 10/29/2013 DR 16734 D. Friedman If redraw-from-hatched-area fails, don't allow the pollygon the be used. @@ -839,12 +840,8 @@ public class WarngenLayer extends AbstractStormTrackResource { int frameCount = trackUtil.getFrameCount(paintProps.getFramesInfo()); // TODO: Issues with frameCount == 1? Could happen if we update on all - // tilts where we had multiple frames then they went away - if ((displayState.mode == Mode.TRACK && lastMode == Mode.DRAG_ME) - || (frameCount == 1 && displayState.geomChanged)) { - if (frameCount == 1 && displayState.geomChanged) { - displayState.geomChanged = false; - } + // tilts where we had multiple frames then they went away. + if (displayState.mode == Mode.TRACK && lastMode == Mode.DRAG_ME) { if (warningAction == null || warningAction == WarningAction.NEW) { // Initialize box redrawBoxFromTrack(); @@ -2046,6 +2043,9 @@ public class WarngenLayer extends AbstractStormTrackResource { && this.displayState.displayType != DisplayType.POLY) { createSquare(); return; + } else if (descriptor.getFramesInfo().getFrameCount() == 1) { + createSquare(); + return; } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java index 611154a8c5..264f20eb60 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/CurrentWarnings.java @@ -44,6 +44,7 @@ import com.raytheon.uf.common.site.SiteMap; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.ISimulatedTimeChangeListener; import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.TimeRange; import com.raytheon.uf.common.time.util.TimeUtil; @@ -76,6 +77,7 @@ import com.vividsolutions.jts.geom.Geometry; * Jul 22, 2013 2176 jsanchez Set the raw message for an EXT. * Aug 14, 2013 DR 16483 Qinglu Lin Fixed no option issue in WarnGen dropdown menu after * issuance of an CANCON and restart of CAVE. + * Oct 16, 2013 2439 rferrel Restrict retrieval of warnings to prevent getting future warnings. * * * @author mschenke @@ -130,9 +132,9 @@ public class CurrentWarnings { } - private static Map instanceMap = new HashMap(); + private static final Map instanceMap = new HashMap(); - private static Set listeners = Collections + private static final Set listeners = Collections .synchronizedSet(new HashSet()); static { @@ -208,9 +210,25 @@ public class CurrentWarnings { } }; + /** + * Singleton constructor. + * + * @param officeId + */ private CurrentWarnings(String officeId) { this.officeId = officeId; initializeData(); + + // This assumes the instances stays around for the life of the JVM. + ISimulatedTimeChangeListener changeListener = new ISimulatedTimeChangeListener() { + + @Override + public void timechanged() { + initializeData(); + } + }; + SimulatedTime.getSystemTime().addSimulatedTimeChangeListener( + changeListener); } /** @@ -219,6 +237,10 @@ public class CurrentWarnings { private void initializeData() { Map constraints = new HashMap(); constraints.put("officeid", new RequestConstraint(officeId)); + Calendar time = TimeUtil.newCalendar(); + constraints.put("issueTime", + new RequestConstraint(TimeUtil.formatDate(time), + ConstraintType.LESS_THAN_EQUALS)); long t0 = System.currentTimeMillis(); List warnings = requestRecords(constraints); diff --git a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java index 36d956dc14..76c3d33e99 100644 --- a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java +++ b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java @@ -20,8 +20,8 @@ import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.dataquery.responses.DbQueryResponse; import com.raytheon.uf.common.time.BinOffset; import com.raytheon.uf.common.time.DataTime; -import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.requests.ThriftClient; import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData; @@ -40,6 +40,7 @@ import com.raytheon.viz.core.mode.CAVEMode; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * May 3, 2011 jsanchez Initial creation + * Oct 25, 2013 2249 rferrel getAvailableTimes always returns a non-empty list. * * * @@ -143,11 +144,19 @@ public class WWAResourceData extends AbstractRequestableResourceData { && phenSig.getConstraintValue().contains(".A") ? getWatchStartTimes(warnings) : getWarningStartTimes(warnings); - if (SimulatedTime.getSystemTime().isRealTime()) { - // Add the current time to the end of the array. - startTimes - .add(new DataTime(SimulatedTime.getSystemTime().getTime())); - } + // DR2249 + // When not in real time the commented code allows availableTimes to be + // empty. This causes Null pointer exceptions when getting frames. If + // always placing non-realtime causes other problems may want to add + // only when startTimes is empty: + // if (SimulatedTime.getSystemTime().isRealTime()) { + // // Add the current time to the end of the array. + // startTimes.add(new + // DataTime(SimulatedTime.getSystemTime().getTime())); + // } + + // Add current configured system time. + startTimes.add(new DataTime(TimeUtil.newDate())); DataTime[] availableTimes = startTimes.toArray(new DataTime[startTimes .size()]); diff --git a/cots/edu.uci.ics.crawler4j/.classpath b/cots/edu.uci.ics.crawler4j/.classpath index 91d52dc1ea..ec2246d7b4 100644 --- a/cots/edu.uci.ics.crawler4j/.classpath +++ b/cots/edu.uci.ics.crawler4j/.classpath @@ -5,7 +5,6 @@ - diff --git a/cots/edu.uci.ics.crawler4j/META-INF/MANIFEST.MF b/cots/edu.uci.ics.crawler4j/META-INF/MANIFEST.MF index ac53aef703..4532dbcd7c 100644 --- a/cots/edu.uci.ics.crawler4j/META-INF/MANIFEST.MF +++ b/cots/edu.uci.ics.crawler4j/META-INF/MANIFEST.MF @@ -10,7 +10,6 @@ Bundle-ClassPath: apache-mime4j-core-0.7.jar, asm-3.1.jar, boilerpipe-1.1.0.jar, commons-codec-1.5.jar, - commons-compress-1.3.jar, commons-logging-1.1.1.jar, geronimo-stax-api_1.0_spec-1.0.1.jar, httpclient-4.1.2.jar, @@ -22,7 +21,8 @@ Bundle-ClassPath: apache-mime4j-core-0.7.jar, tika-parsers-1.0.jar, . Require-Bundle: org.eclipse.core.runtime, - org.apache.log4j + org.apache.log4j, + org.apache.commons.compress;bundle-version="1.5.0" Export-Package: com.drew.imaging, com.drew.imaging.jpeg, com.drew.imaging.tiff, @@ -100,19 +100,6 @@ Export-Package: com.drew.imaging, org.apache.commons.codec.digest, org.apache.commons.codec.language, org.apache.commons.codec.net, - org.apache.commons.compress.archivers, - org.apache.commons.compress.archivers.ar, - org.apache.commons.compress.archivers.cpio, - org.apache.commons.compress.archivers.dump, - org.apache.commons.compress.archivers.jar, - org.apache.commons.compress.archivers.tar, - org.apache.commons.compress.archivers.zip, - org.apache.commons.compress.changes, - org.apache.commons.compress.compressors, - org.apache.commons.compress.compressors.bzip2, - org.apache.commons.compress.compressors.gzip, - org.apache.commons.compress.compressors.pack200, - org.apache.commons.compress.utils, org.apache.commons.logging, org.apache.commons.logging.impl, org.apache.http, diff --git a/cots/edu.uci.ics.crawler4j/build.properties b/cots/edu.uci.ics.crawler4j/build.properties index 6ca59fa407..d727627a38 100644 --- a/cots/edu.uci.ics.crawler4j/build.properties +++ b/cots/edu.uci.ics.crawler4j/build.properties @@ -6,7 +6,6 @@ bin.includes = META-INF/,\ apache-mime4j-dom-0.7.jar,\ asm-3.1.jar,\ boilerpipe-1.1.0.jar,\ - commons-compress-1.3.jar,\ commons-logging-1.1.1.jar,\ commons-codec-1.5.jar,\ geronimo-stax-api_1.0_spec-1.0.1.jar,\ diff --git a/cots/edu.uci.ics.crawler4j/commons-compress-1.3.jar b/cots/edu.uci.ics.crawler4j/commons-compress-1.3.jar deleted file mode 100644 index 6c826c528b60bb1b25e9053b7f4c920292f6c343..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224548 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�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�OAdci#Z*d;64}a@5Ns) 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 literal 0 HcmV?d00001 diff --git a/cots/org.apache.commons.compress/commons-compress-1.5-sources.jar b/cots/org.apache.commons.compress/commons-compress-1.5-sources.jar new file mode 100644 index 0000000000000000000000000000000000000000..f9931e58cf046456fd8499cf8894dd14326c0ec1 GIT binary patch literal 283704 zcmb@ubCl#k@-N!9HEr9rZQHhO+qP|6)3$AQPh;Blo!z(hF7A8#+db#iA60cuMZ`BE zGa~bo5s@V?1q=cO@RwINhn3)8zx?eD^3SJ?h_V2Ugsdo?{NKnR0J{E=6$kIijr{pJ z9}oZlRjQHFQH-{IbYB0*7q(}eW#LnP}OS+8QBk#07> zJym=PO@-ycWqVy;Zza)_IMvT^1vV&BNuv4sD`+p1DCc84<*dV|%!MXa12ooPToW&M zbTI-Omtm2Fwv20#>Odw7cUCqx_N;(ae+GOT*O@lQ`{BOGf0IdIIctHNxZRcqAe@5p2rhxt%g@L_+k-5pgAw>RXLL)mH8#`O4 ze_*irmuF-Dzcc({w0AUd`gfe9{{yFiqmj9VtBK=3%J^5yDgR>`mIjXhV8y@6q56;I z7};Cc{To65xk8>6_Wwo>#eb~O|4()qyV(3Yeg1R1od2ytL64-#CQEv)~}4*~EO4a5w`^bWuP0HToq0C@ff{=bL1!2c8U61Mg(&PvXXCI&XN zmIkf{%j!0ASYilYGj-{T6~h$`1U4!x#3;!5Es5xmNo*ntExlTsS~G2{+dR>zx4Z9C zS3A(G#5Q~_U;g{9zcMn+bmP8?Xgr1KR0y4@lpHg+v={ObAbUqV&r=7)ITuZGp~{?P zxq@yr!fwi#i=D<7Hs%BmRSTWWmWrL-<3WXyn23%APiCINM-)9@=3kF*UMXZ$PL7pK zg0NxKDcMGGOe`v71c=NAiYfC1TpAcHS>1}$I+$H+p-#Ju z)ke%x7+3++EcY)Y)8abbDr>IiCv{60 z@9WdTXrW{vc^s4!xwXKpz3>K}Mj*G-byF3WU0M-i7h~vOY2Oy_>d~h0?AKgcFkPs9 zJ?aIn%)dDQKobjC^&qVQRq{)n@ZTMe6b6h!VhG5|PNXQ3|%MmCoh%`yPW%JLv_)^m&519{# zNRpO|68bvGteMJ|U`u4XO736VGN)LmiJpd35%QkI((pm7 z4l{0K(2uE(!!%*c>+l#oe4xrd)(+T<1YT;gLXYx5UO1B`J{_vkI+4hyC|ejGdYu7} zNUuFo4Y5YgpajM%bCj@7I987k7m5?40O1<~kt@KDSE8^bVX9mq*ht-&<+ZUvkfIlxnHe}Bu86Qx zP6;bWhqko4s!WkoHe7aDuhuBUU|nmWG?C87C3G*$4cNM0&>(aK`*G`dQKhL*>k3rh zVGp?qBpwD`PipY?dHdT-qznQ(dxA+@vG*}L94_t|y^DsjgqBcO$Gp_s&OOwGq zl4%8=Hu4!p#6dz>3%b~9pqX1#BJ1+9whC!Xb5cRunxi7>q9)EV57rGotcZzFqZ&KS z0{!3|NA!Vt2+YyjV)=SDS%w}KIpT`S)Vl|RFB8yM%bn8p$HU-roZp8B4RKz+%+8Dp?=T9e0bjmjAi z81$6e^g5364*i`35W-38E+1}o?!XgR>|D`oeh2iDM%k91;OhH*Y_h{(Cw+CoZV4=9 zUyAE8ZX3%-7DhEXwYl3qtmJSxk$AkKi!wj4EiL^3fP!vx?YMN$-3%27EKD0ezlpm~;BLoI~kqUM=~Y5%8hn{7uJeMCZ4UCua!%S^u2S zYmsS$(6v3*Y>=B?pXqfnhvfJJvt(@G;h|>Xxj*wBna1Xermj_?J(8UcRC-*PP}S+! zd{oNoo)Zg^Dp+9ikq!5J-i<49p1WIqV^y=He z&nF%7!LJogB6|9@yOg#Pmw~*eWGmnAnIh&_*LQ$0vO7Kd_7On^O_W0h*56(o5Tnff z9@lve3jlabiuz?9Yo>*_-p?8r6G9b>xu3m&!G+t}Ob5CubeJ*Vm!SEn)?<~|B}iU+ zgliP5nSfikYLbSbbTSZ~G)%$);CiG}(knvv(!`sOcIDj)c&ojYTb+-BT$~lCwQY1` zyw4UZrnGPUEo&C$AMgmz{E;AT-jvN9?XzWcp7*Y_pYIl4NkevD(;GjthVF6+06ac( z_f4oEx*ek*3)e>mf3o?jqJ7caYU+>f-wA3r{4~nntd}qVuBLZ)9(f;2%t>+1!PWf% z$ENa1Q@GPH@a-hrib93u1J+J)Jkt86L0hGkA$%mAy6Yla-~4+^BQ&@>%s^E&$*b$} z$Nxt65PwDYdh!$wFn?e@{hyN$!+*SaN?SNNn>hY;!^~0Xcidz}=((U`?M!yWo|s{X zPnTrEje|$%AfAs0fc7tC!TI)b6IduTVF|kv1RU!1vD>9(=E3NP?2Cz3 z(2(x4u;&=4Mq=n8%;^+G4-TnSAdqvOnsP>1C z>6$$p2mMXnjlw0rAzA4@OAYQJUV2_RO=K zv=_SHQbV6w5iOB3VVOW+{Dv5F;9D`5ywKQ{N=}Mf7GL7r+wfbvl zP}c`bMy~rBQ4OjCQYujb$wHrN_w&!v&A!nx2iVByEMDq7$ z6BnR~4UToiKyyC(MVEW}qA|-Z;QlWQ7nZ&S6}A;L3b#8)I3#I`nO?~QS5z62+2s0~ z<4cu3n^7Wj2qLA#+6G=&v$thQ+}`_}t#`F$Ek!w{35`QRd7G8<8%`zJXyp|brLsF=77Uv`H;43y{#N($U z16z8y)^bu2co~9yVFN%aCywpi!A;|PTzoAhy+_%DGC{ShmOr0A?x;2relsq$Kua_` zhCq!lDRwn+6C6HgUw!>H@E@gtupmqS(Z9(g{h)&>dGS*Yj>A=AK0U3NqC1R%7_;VW zcs@A^%Xg$B0;#jwn_@J{2nmcwPIf(ZJpmEgb7Zi`nGxXf1B(#Kg6?b4pNgGtiIh92 zmS!NG9=kWh#>(}}ej+-o5&+ur;v3Y%|3N9Ljz@d|ObUy0`$^xv7|rR8sq81@mY=yJ zD+_}AcmqZ!Dldm$bdImsab1+5l$%_#B0e_Pn-(%VoxL?=yGgYr6?#R3M>^IQgmzKZa^0@P=P$O^v02)*P0N($2 zY55y2mveFcXJEdqu4A`3hU)WN*FFtYldMwQ9(P+>kG-j5z{ZL|aZwtTkDfqe!HP0I z149EH@co|aWhS1Gn2o8E56==mM)=D&$Lng;{oyWHcVU)vzGIQ%HSj}nv0WLGw{&>G zE_vBmN7I$eViO5w=h8iw>V}8QYf@RN2hnrAg#Y*AV zi7Tszn+SALgtw)3d=N0!p&Gjpwhh#K2%3D!!cx6OO2YW9K229qouU9wY_w4d!@6#{|<*syk_R zqD9lDOv(qB_4ShqIJ>82eV$A`o}h6>eWToqGk_I-Y9m0quc^wAaY!s-c^Mn_Ps9?5 z-tP4c{9Jl)>Kn@-=4IyK>X*0!ws-)>l6Uup+$G}=pgPfINoW37q)m8sd^4xEANzwZ zrmP*A3zy)YZeC6t88WtZH*!U6rb{%a6q}3qDo~nw9CBoN`|r8 z706BWkOPxxDVmm=XwMrb(#eXOEe_eL;ABejMmF6D6Ah;V)5;JUL@23XF+alDRfkPkE&HHOEJ2V zw4?n%sCTK^-Du*)1A-_+XF!IWw*)2Foh%i#^RJ${86VI-qaG_guPYaNeDLw^bl;D7 z7B!!h5Z3(W2xfD|SAB*fK^K-%wkpaRl9Wy~SS@$NRM}So7|j496OA6nfE*JdWPMWW zH7Ert0Ha`S3TI<9d?$W<$$n8I@&@&}3BXY-*?V{5%BdXVoNQ3CH7IIB<*@m{e7p6f z*A)G3b#XX?pPyi30}KJ7rK{ihDXP-px(cCi%=vzqNFcMVpY}`VicZ>a1{Usgp+~<^ z1w5LaLq^&!A1lZ*aq#<}%e!|IAvo6g!e**A%0RY!rtjz_g?G_N*=&dDTyi-LT(+e! z1b8i*FWQW3A2nMgO$7=L6RRXk$@?C-*bA+vT8V8?8doIumV*o<3q=ZpcRuLbisDzJ z9HanPRHx@t#i#qNQryW^%3qBt7T|S(&bdE49S2VHmCZ{#GWqE<)uKQb)NakAU=8EG zaV7?#R}?gzW|;wf`v{aFW;>xjMC}qzW!&B0UZrQaXnTlp!vs5Dn7iIq-)|qtvVA}8 zeSBK)ZB&dIP(505?_qSp8Ob2|wGBXuibn2s?kTAHoDtijei;z9GhohpMGRhY;wR$> z)H{grCIol!v$;~mGb*PF62YqZ;{%-*UFYRC(*#PlzGybaXrX~ve7Vd zmn~mgGJi^@HHBLSzECMZ$S{_Gxy#PGbHNWO9u8pS0`td_QwD3D`+!c27J)7b&*SS0G>Rxk;S(%sjf5>t+0%0gD9b?j9@z~f22%NT;`rvNOrnxKPFCS z+6LwXuV`!_{wP6$yjbhE*>W8iEA%w;;>lM!zn1#>&7RYc=0GOpGI(QV>)S%e-p`hm zliP&ppL!n1_7IaG@=CsZq8P>k)+PC+igODKga)-qF!pM*#klF5P-!X3F&$@u(*-!3 z$3E=m^NHc4gx}}NT*h}T>iS*HfxRS}0O02R?jCJs4EVK?V9Efj1r%!KD#?`{Go=;xwJ8HUvJ`lN;aC6E*X|; zz1p3hr@9(N?IQ`No>&k+d^eA>!z8%jHy&Cyp2PN^+Uz93^xYVXw5*p_hT99aRJ#)H zZK!{VBv?=@tPz`#PQKYkY&UjwQu%=Bu__(Dx!-a9^Y#rOnkj?@1OQM83;@9RA8+4( z$u=68nb4X$+gO_@>Dgt`BlyjhwI5fcAf-RG7l>EOFgHgkhty6K1;N*Yu{Oz=_kLda zSBpNtdpqHMJZ5)(|%CZ+z zz4KuFv^Lszhcg8J2@$5z3zCO%9&5I8zxnvd*1mA5sx5#8-!llx-1}qABT=$*qgFxi zN4xz~T+ki+H2%qN(CMgo$aF^zuz@(#+q$RTcg)a1dJw}UEOf09Hm`l;kWABe8mkkk zx=w*#T~Mc6zJ3>HC3?f9Uh??tPhB5GPvuyaPr22 zgPb$?<105jGl|xN_;wOshcB6fS|4{vWgd;QdoMunqYn(@Nk)=oz(Z${zNBY|VDSfp zxZc;)T=*H0MZz3Uo?1m&Ai7ArU2xDUm4Ve~l|N7g|4bdrwRl*oN-UKNu{@)6k>>HJ zj^p<`lxo$btC-RJ`q+i7HU7El?22}Bu?muNNc)(>M>aiSa$)|k+C%K4I122&<1N0m zLKSpphZvM*WuvfE9;h_*Wgz))(N6n=sDU%&Pw2n9+FuGJ7n7u0nSb0Y90CA9_&;{F zzZ6;|4IKYJ61g=hI&pu_rQXkV>RU-Z_D6+r41u{`w*{8KSnM2-3x)8_&8Znl;wi<2 z?IK@ZVJOFoK7bVRfT7fpOk7-D+BCFe&Jx$gGZT&ivPoQwHJAy9sb@hK!3Lf4HI%_g zn)A*n+fxv6*5Xu8<~HRkYbjR8(OYeQ#&K4>ka>!Q$_%+Mnq$tcwd=uC23!Nwo4_V6 z$X~XT=t*2EhtG|CcF*5eOc$&~D#%JoIG#_qLc#J%hCR6Srd*%K zA9)%QQa|!su#q-Nc40P>#p6Fx`eJwuC|%nV_;GtVY>hG3!k(}Yt2z1ndq~g87W+t0 zeOpcTi21 z^(Ry$(OysGnkM_B8WrrvcAhx1d~y_zvufe}GPDTPa9H3>pN+~4&juVUJ?(stK@fK_ z&kn$(aQW;oWf5~%ex8~}=Jc6S=ex)^ zOM*sztEGjI&_>)h;x>?~D9GyGdv1EK8=R0Dz`N&sT0~Ml$>4@@GlSG5$YRUG)20_f zq>3cxE;yM0@kz34<;Bh^475j{n|H&SH$SWF?!~*G0^cJTuR5&XSc8MqXlVuCiYV25 z-}P9RAvDH=xb4)~$LhmM0>90`V^8}}F-OwvxYNemOb|(U#yEsU{MzjrXw@o>9y^ezCs(O9JWx zaUDMEPXY=A=D#^5{&Vb$*g89U{52cZqWb5Q$cplpQ{p79DOT(f96J3JIs%;xy;}^A zux*s>DKL%BrnHG7QAN3K!gsHbWaKfsMiAg)5bxN#$5lsKWEcF}ES2?i5 z{2o*;#SH}u54)Tfr-=}ub_i>&BgJxNbGG&Ecm8NROd`)SkRuWCkcUbt(E))?tTlGE z50p_A6%j&VEQ_Yt&5r{%f0tD4Y{CQ4{hEn&P5ehS3fLQ+D{+)?a#X3IjHn4UIur^N zJVa$M^Qy-&tIbq^ZKO*;t3ja+9YB6kK_6LCNSP$$HAJ+sKTGdle=j>TPVzmP`Xg8&RBU%jky!1ShFs9G--ig1ZHVn02S1z^GwzXUTz03=kwqK=o-ce*%ln< z6LLEI7YP+6sgx>h$y#eFHF>%rZRG}_(o<>`}8P%{K4Gs#_~ z(5N4LjudIi-y+$x{kbJhbWk#%a{S`$`}qDSl9=85!C(&|EIY{`zgI+mhvp)v_5Rva z2kogkj;gh)@y6kf$5*&o@sfu}vF&%6Vp;PiEzSP0>4^0H-d7a9R-q-TFF0)?72mBF zwbH-!S@j44na`BGcDFYst?m<>62|hTCun2wtyk?f4c_@?1pyY2spX25(?a|xM4GLU zZsIGdtm*SBT)oEPjK}@qm^$rz5&84|GLsAD z9R3RPq9&;+dfq>m0z)H0DOgvOFPePuvVh4p!fq`^bQ#vZPKR#cNWEBw2yV7X?b){T z#;rYuy)G7g_xi5n)@AF*AzA#-T2wf>ZtP#-etf5h%_gT-7{=1uH&A|f^Fr;pvTJxY zJAhygJnbR5;#)DTPXapanE-1xoM;Aq`g_4Z$aTZ z`t*HZljh4Rk`^`HBI#GW$PT#^0xo#?HHjs=|D3=JHArQ7^sskPYQp2s`it{$6tju7 zJR&oa0j z8Pvz*?KhYKf@`N*iM=A#AB?^I2V=vUhvdUHZ{Qc9XmSwA^%QlP3WF$M456ho0rH2Q z?l1b}a$E0HV+AX2+#=fG6<1-5EiVk@Ps_0*CzDH!SBU^C&Wms%F{nc-Nvh26Tv-~c zaLok?8djM$8E=v2MyvO`4eZn41wO;Lj51B0tsZ}pwJ%)! z0ofMdJ;PY$-cYb8kf6tHm{5xDV|aUEAT3r&iTU9Ki#8qHe*8wdy_wfozhEH*41 z+C3!RF_@HL>})VKf}xtRQ>x{Vix7deQ`zGIi5mRy#c8Bd)IUC%T?5OUS;$zEoe(xN zFTkS=qJTLBmeNGPA9*@y=k|VN3L8@G<4b!PF9zUwMj4ra=4o?PkgrHMOVWnMA}#_R z13nM|CS~AQA!)gd8$(S6-l=A8O`>()W=45t3S<;Eprm!+xwI{AGUADH2=!GcDE*pt zV+KL)pF}(2N0&;Kw;fJIewp9oUJ3V-Zg2rX3uv{W36=8tJ7L=ie&EG}x)5Gg{!iYP z|HnN<qCP|FQPF70ROz9#kCbQfV})?>u;-OIGbJ!U4m6QRTd*;`y~K=EAc*$UIV^ zG&Y18jc0ByULqbZ!6|G-%>>mZaxayWcRFt?JznC#7wElVmOS2vVS(B}Q!Zu8W3?Eye6 zo`6D9cGl|FvgsfU1pe!@4{*t=n*cY8X*5-rn2hjAggfbgzTWzU>8|dOiz@kGNv=Br zm8+LbGpuN_)xVArrI*a16)&;_zQ}qvO2{mG=%&vkd>}Jaai-*lm=1xcBGOC$O{1SP zVJ%MDiClL0FF+tSS?(YPS>mgY8&Pdwaw|p$dy7fbSaA50UZu55{OyS%3>2LW&}#80jJZ$435(o;-3zm`YS8&Vz3Ngv9R6Z8REm|0LGs&FLrJ z>0GVnfqSC_Va6cZBQh;8hJ5JoY2eic?krQP^92@wQ9M)xKWr`f9YV!mKN~n?RhTBk zKI+(@9^LD!t6D3>Rvo_VCuW}>CjAS2=SEQUDoC|lsv-#X$JrssfS-q62B7{4HZg#5 ztDQn;3Gw1D{{1=-TTi7p**F%U^diX&(na9LS-}1#Xya!0_QY>RGPfu8OL#6r@Sl@z zgH=+ugZsn7`+JRkj7Wpf4$Rot&vfsDfZklFVL^BfC(ob#4r1c^Kd4FgKnail(>cdv zI2fEI4*fF=jZr`sTx)T##_mfaSW*nncPHkAL?DgX-3U>vK*VMFSx#i7p-}giKsP#X zn%e-Ydj;70tf$=&eq)pF>kZUeg*;6KnCvO+y}V;#`B&kM92B`&x#0Ztf{JX&^GY9z z-Q;OC%z(9R?IZZU0GYbPJ$b@SDu)N9rCy?M9)So(DxlRM1OkoE4|#!AL776V1}6T~ zQAO+zdLMZW9C0YISPWVX&_7{i1|$eN9e(X?0Nkm>=WL#RbA;nC??x6#lhjw51jxQw zaVf|1>&ME^4i?aL_i=9+p{E<3uV+RF_|v)zY-?M-uKk62ke{Z&UQ^(2Zub6DQ=%4>eLLcI>!xnG{Z{czf*@=lqKs$Z7N=x@ zK>c*c9?%v$4ZxHwPa#cP8+?rFDTp$n|!j24I*b5x-{nC*{{S3dvmep{2TLAk_I$}itFakh81tpHo=<<;y-yApiIJj`JbMqh` z13rKa;W2)LKZ%}!KaSn@jRMxTrDlnT0AkS{qvQjBjI?qykY190W{UG0Ll@9`1MpB> znI;Zklt6As85IHpvZdm_lm7U+oS@NXCWbxL7@29tF2yX2HxX&&^H<0SiX9)(m#7Dm zp2Z*LkICYv)fdWig_k!xj&A%NLJ%O48ULmg8o|gP4y_9lph^*T2&zvEB2bcGZThT0 z{VQ`5f@s#pvsjRoAM>43B=CsVp~jxTu*{!9lcEyY%u0 zxG&W}deWdUZk&d{{POIa zR1}~dHsl6q9M?Aj{6PxS$E1p0o_6AK~^{nq70SfM8~JMrIa_rR$B@T0R28W z1^#eBuAG8EKF+`GO7mw#)D9INC+AltoE0MW0%*49HmUAYAXC()2RD?bT6K~KUcq7J zF*Pv;BMxVYz#&5z8ukF%0&CeO^;3tsZ1&?c23?^=iIyp`LVs4C5-KIdjf7Z(dO{d^ zgQXalX`)Hyr=5uh<3EoR67s9137FR0D@JH%su=nIEP2^Efnr5edVlJhZBa@eT)sjR4z{^ zyv!a+T$IG~1BFIC^~JC&-S~l{YR~yv74^IrMz(l?k5uJW^HrpU6;1gjczcA2b;G+< zU_suUN_N$MZJi=u9u+umEy6O601qRp4ES!Ke;gimaVRI}vNC#38ayK7!Z^6Y8KIy$ z6|wXzUmg-aNSzFv8Hrz3iLaj3L)Z6_xwPjdOW*TMwvutUyQ1umhZ>bZ~T-GinP3PfoQQ>N*Q~y zyWv#EW91fDrw&z)G)30~U19>(`1NB(W?|@$B3~^4AjQXw*FGU-+2ahTnFmEsJ44FX zS?a?%L;yvMydd%pM?4%H56f1ClPNOF@bNKVwg^XlnmHvlSD>`#e0+`bNTy$+I~?t+ znQzcIQQ6{QgfKkNPAZc1{1DPjI^t#-llQ_AdLbs#+#P{s+YEh4`*9vZ?x7Xt#yWJ# z&34t{&n!07s^q*x{djacdC>NHc>PntQkT=dFhL${Kqxklgy|EtWQVO_=JX#QH#Xno zWQMX0h)w8?oN&zTpC=BsPZw5{w6Q>=d<#arKM;obg08Y^(_a!Ha{!IgoOCvDw}OM+ z7U%q6_a6J==pq1#^Z|Gxh)?SZDdTzVe|q6aa>SB0UwqVIfdlQ))&B07QRn#H*}C&= zmwmq8eo^Wk?5Kaw4H zo2=%MzvM6UWz5;9g)^pu5(9-`lexW5Z%vH2NQVqek@m)l>)(G1C)UaHJtO$b!F0c@rLY_3EsRj3Sh02zO)Rx?9plduZrDNUC1FFm9JZFx{F91k4 zIOFAf_%%{>PJ4IPk9`?Gd-q$TriNt5qtKHa$gYXPB%_^#$mTC+Fq?Lc4H_sVu|5p!S7hh#NLaEieubRrD&U5NSAVgz82Ox?kn30fB!76 ztV@`yUokM~_^BbRec~m{Slm|xydXWe&u}RwMw;XLjClZy_V?jU7{rx3_xMv#KZPVJ zc4)_5vq)Xd-7Oc_5Y(v_-{9b147Xl$J}!jPAHRn=glMI?M!2?fShiinsMTnU+Tc! z{lQO<3|(%Uq|I2?>Povj&C<=VUipeaK+_Ztr5-*!(*!@~lr}7>RK&MUb2XbS46$K~ zFEa`)kx7H-^5C-_gCzGi<_Bcbs$}4!J=TNk2&;EjAwNgQu71u`bU0C(JJy(KRvu%T za}LNq)gtfbscLzfaUc1jaBm@RhB8U9Dd}RQq&d-OlC~T9WR@)3erF10w;K3*k;L*o zh>diXXLo+WLUY^#ODTbRQ-*n^+P; zwW(BV{A6e&nSmGEZ5yT{zt~Js?7k}`?&D3&h5^P%%$gAH=sT_xzMaddmS*UTuM@o0 z8kZp)V3uSI;~g5&hvFvTp`tGw9z&U6hvab(@GEp|uY-Io$919!{B2FXk#AD1d&1>$ ztv({wES7WVs_@7-LY^&w)ZL+D0+*>$S@ugBlR@9XnFuajB}O# zj{RP#vfD%SE@DVT6cbZtM%+GmvVH7wX4zeX`xgLiq+bpY%z4uxBw9pfmg|E(#jBo6JhcNB7t%?D1v1F9txQwgZL+Z+ z$}aAi^b5doChSIasPevPt_YM2Z14S#AjQ+6)hgYzI1rTZ6(KZ7vF;nPXO#pO^=nV% z#kIw|+H%GX_cO1wD+K{83?})q#&nD&iubuzg>H2T7G3a?`kCxalwQc8YqN1o`r_3@L(? zcY*`h^+wX9(r+k1qpGr2EX1n@bw)pUUH}Bz5eAMm*!z*}*BMogijRkk77Y2QvxQcp znenI9tspj8{tQ5@$UYuR0~7jQ`T?xO?}*%tlinO{pj!>!4RE$6`%dZJ*PT0tlD z)dTdv8x1sB$ooFVJ^1S*h;w$cA5>x<7-#;Tbm=6a^JDe-nA?jn`vAb9T5`s zaGV+q8Wq{6hvf(~p~2+@gLV8S6>W`@0Byz_86~j{Z=ITKDD1h!bX_E717sDRqV5-X zqi0QEON8p8gb>8UIjuGk?qRm(lEru1gxcc%2%+Y|>S`=oQUNmF`_nHV^$$Q05HHi; zM2Ag^WK`GY-q6qKfZr%t6Q8EjkS?G-h~Q90QW^FtN{pn-Bt;Dv*(YFUI)v6&w>WaD zmy*VGbhWZj{MnV`9KT07^3<^F~&XIJc{#px;3y?STwdV#y~Ssg)=Qiri@8y8Cb<1kEi=)n901R$kpN7 z_XVku*xd}iL1D7@p9^OsQHp!O3#pa>+d0jZT} zY^70i@H7V3e>6iSiZYw4Sc(o7JucIB=EeC$(#eBW%c`vZraV|ur#4n4xwV#;*e_qZ zKV%|0&zdN=o=aB$gh17cYFRR||4Jc*rT&DCn7b>q+G1)F(&F|Y85w_+3&8t?DYx9&!@@J z!M~D||80?4C2mun9bu{Ze5MO`lU25S>t)e0iXCQv`kNNOyih^I#Y7&$UUiPV_d-d@ zA_mj-3dKVR6Z=Qoh0vrZ_R|=)%@vpV61(qZZWXl7AHU>Z>0v8 ztaqoAHbhjwb)@z?@xAvz9``^l9C~QmW8)minUh4(O2+2{m~9x17|?2~$}Np;FDQ-) ziDmJMsocZDoktAHZX|LA-83GN>pJ5`j#PPZ^%ms#AAi%=bZ*OEf%S$|XT_ z6_x5hhj8`Q2==}p8^NBAJu<>9mbjpuDg21D(n2X3p@{_3utprqW6PL!p~X#H2$gZ# zP|3ugj;!bWNdx`>9%Ync^UUah;&@}rUT5WwGTczTUofnY5tj!1RuxX9#}r(J z3Om7jo=I3#Dub8`3|AEoEMUH8UcqKC7krPlRrSRY-Z&zG_&D+B-d(n`>5io#a&g^V zgqvcb`+c1#bt{MP0>&Le#)e9n!^_V42JYsi#q? z9d7x#zcS$=4iN)>o61q<>j8U~?EUaX2&XIUMyff;Vy#W)b58!D=4&v3W#AzCRPL?J z66wJlgC!IvPJlAngsNKV9dMn;#%uS1_0Oe|81B7j)Ia69l0W4Uw*M}*`p@;b>DWK@ zx!zwCr5u-%kjgx*Y0hg3w;H3Jf)~l=r_fI%jr-UqNV>2)BIl?iQ8{3p` z&D*uA05?-oC}33eNY+6JRH_SVv~{lfnET{j3JjAa{$cEVyg)b#K`0Q4LS!tQ$%;@_ zuO)5HtFhsImN9Du^`rn}h&wWqPY|yL+;AT&~~*G!I}u=3aCQ8;Mh#T`G^IlmFHNCx?G$h%wD{4RYkd z0XFp(xmDJn>H|AyfDUx>2&TBYZ%yZ2D!=$q?~=Klq&8p3fU=aAYZdwI2wp0#Fiu6vQhk(z_!YBv)FaUjdrV95V@wy? zJxZ>OohDHTZXNPT<1HCQB6Z;m!of2%PvWf^u(&-Od^g1vPMp+D!SL8CXVpA)FLfv< zW*|||Lt;gEy9u)(m2GL@GF))m;gFJrxZaVT=DPi{%lPXVwOV!aGIpdes``p+m%rGR zPIJdyq)Iq8!9~7xs(soK>2#ousDD-fXwhWQj(HA?Qn`pR#}1l zi|Ze6N&Kbv?TLQI#1iyR{|mx@b9?#!B=Lp*{Aq%-fvvOCU)x_w)NGtKL=nEO^crr{ z{@gCWI3Fp=ol!>9x0;Fq-)BGjae@G@O?|f1MU?LPw%g^E$ln?wgw2f`;QY?rHG6eg zll=^SgWE}X6mg@kI0WCZ~D3$2$A{Z$vsl(6whsep;gS)XJIXcYpMssdL(RNk5s zRd|{Z0dgn2hRC@5CA*?R{6svbHYJ@7W=v%uMK>JfRTM>Xjv{*=!(Je&q4t;&z68aE zb_CK}7$2%bfh&Yan_o2Sb#d?z+6t$Mg?OP)@t%hBW;DJGY+GdXfEkGzvc?5>I~3UG zBRgm;!k|5OU7mktV$vU@nbbdo;p{rLNwdas%2O-J@(SgaLnpZfuh~yD&MByi_&~Er z(T^@f(1*-QpTZNR5%LYA0o7!dbet5AN1Z~MDp|;l4DaDq4Seg%tg-v{y#{%Y{DAK>nDZ7%4Qi&Us<%z7(iD`hknd{#LlqUV5w;f?bqzuQ@QyaD;Gr zQ36_Y>i zNNNramTr>V@Jsh~r+v3KjBoGe0sH$r4E+uZ<992B$_wZ68kQ$k=g9NIxH*(`n4mXT zwLlw-EAZ?yoAoa{gDiZ;or=Oi?38xe&t9&NXk!dDfn)jafr%@aP#!mCT2#bK@hsDU z2`yICnH8~(p)G}MgSpm)t!mEA_ak+>Vn$G#)Wf&o&4#L`_iW->+e5Di-PsG|R7c&} zoq>BvQ9T5k#5b*oicx3RQW;{)#$|Cop{!i2E&L@qu7a^HJD~(U4rL#z<{o|I_14Jl zG(o#LOQSi_UsBmno}ri1xgMrDj$Q3fjVnP7yJs;sXe;iYA1Hi7v8cM7v&Iui9f^}m zxE72N!UGK@7G((n-zotu#Hi`2r!d$g&6tvRWC+yL$psY_eP{hjEe7(J=o}>Ho zTWj0cIY%sdQul%D)-re2-~$8PjJA2GwtOslW62UVX*=KKV-_xVjRn|p3$%AR-SX;z zqH&ylM}(M)86U>f##YV0J#%RKl*zFp(GZn3CMyTRY^q_5oyo>a1P}Bj`wcVIV;(hT zc{siqkd2}Iia`+TcVQ8n#50BHdW8KU-GH#URaNW0$}#5@(Z*jP?uPF6G1G_nBht1S z*fxw4)VFHm0S-@H39EltNlI&sOQw#sG^VUH$e1W=?+v6$LPk5Vf3^*X+Ag`M|*uFMc)gLXH$c9unRwJeZ;GQt=Xn_n4ksu>wj_f z4MCy+L6&XXwr&5mZQHi>+qP}nwr$(C-TP;D4?7#N5j%URdmSpWUgksgfb72Ex&Mp} z7Vm30Tk0UOlsZi9_;kbZC5K%uXP6lCo%57`j=QjS(dsMIM!4%1+>|S0w%6l7z(*>d zRH;RfSSYS~MKELN*zL*AQVFgVTvJXU4~MEe_eLE-AXQ+I&dJf<#=0Trg#0Zx`*%1Hja(F%+=hhBwMn2o{s-! z@tdT}u{!Mgt&C3UT|l|p?f?C+aA8>PtT*AGh*1?50D$Aa2N(W>iB z?m!g9_f#z_dI<{2R!Xnpq@Z{`PeexmHBpp0sG=XnwCN>^n>i*hh0QEuP~60ExJn)=V^Dty=xc(N zVtic7LL5aiSW=TVC4D%sEewKYA&XpFa}gAR!)>2@asBNBY=y}6huQ#&42i5h5Hs99S?WLrl6hD2lu}wNs zyOruunX1Z%apMjfjA$az7C*zBUzYsmrO4%`3%LcfoW?lhwh;I)jE5y69gx(5Is+z` z-K=dYFr)9iz|sO!lUWQ@naeUvnur}#T|L`(`Re3j*CftH&4NPh(duWENj3;OuJ9G^ zjqy};zvOp3Wc0I+t$%SCg|XBSW@A>zX~t1TEQDk9a*9G`mkcMsGTJq?>VVLO3NQ_( z(>Et37z3Q_-l+it+=e}0j!(wU^q#M~7kAdw2s@y(-M%N+J4a4*De@Ov!2S`m#}CuL zR{}ihXh8LoW=Z5P4yuw^OVy}sm?v@nhlvt?STjgmP82heL-@kqN+K}9F&je2h84mw zxG)~#5^N&w60nsn=LJjsq80@_QfCDhJ2MZt8@GdQabHv)i$^k;%Z|mfvb5}VM z+?3N;b!fnrFbdO=Xl>P8F6HUfAd4iu_@r$p7!h+TANy+^z*}42Q+8idLfRr8+7&I3 zx!NJ6E*{2^w2;o*@E(iZ!i2yWDFsJ5=9?a@-(D)4&S)MseYfzvcp1}y-ge?OG|3{x zZz_Rw_1NGTQxYCvG<6Sy9Fk*2+2dtk7QE8*4-!+K)!LOf%jx&<*S8_B`qW=_=bAI4 zT;2l#D|B_IOpEiD+z0@8nwhto72Bo>Sh|q$1!W7IHA=W(Y=7+5mZk^8>v_Q`lOU-` zVp*$yW(7lP#Vy<;jynOb8yoYO0V2|Rd__vIr{;FFB3)+=y|+G_yHLqt94)14p-J`( zJmCczo({YTHwHhq)VW&C`NJ^(qxW4WtCkrz+u7)CF>q{Za10MSf}&vM^pE^Zmdv7F z^tQN#VyVlw&vgY8x*6%o}@DfnxRM&knt z9p!}&?VE$ED-&fkZS*EVEL!x_(J3l0GqcE6ZjaQC^~d@Y)a?rQSM<9-PxxYm-A=); zpREriZ|LZ$cZcu&_ltnlfm5?8SxvETRJMPD51CF*=5BKq>mzECPihgGTPxOYnl{i; z5C|8idO(_;dtD$H^?Zme71oFavZ+ubuYSkTj|HA$j($b(u5(6Zu^r&KVApx#r3WEl>NdLc80lBo?4`LP|>; zn9v#C+*CS33g7IVSABkD+n>~muUxpqTDp?5$&!nMdtF{NBC2hdQS%)Cx~MFMp8iT# z>6OosW(p-gvj>y?7OrP1zXf;vVgLExEWQ5$R#|McLVw`_0OW-L0L1?Lb?*P_?bY)7 zCp?Go%f|#{Rv7nd#0u z->F-0#_tzQZZEa zk?w&Q$?D?vJk$)tYCDERQ^XZfY6;1ZaHcBc_6pWd&Fg1I| zu-=|S;xg#I$>?OY9iUkkb~Yz)C}U4&FOmdM<~zfa@yzY1&m9CQ`W@ov=^aQd7A+hN zpG18q?^=ID^kN9ZuUl9u81r6#!xdZ}v-H`*Ikbw;x^D5Nj?cRB^*ggQ(2f1d=k=q* z%Vm)dyP==;61GP7)$SvZ`pspgLyeE{82-C*)rO2;hassg)-Vf1{34$%*lIl?9*|a~ zRskuzp8bA=p<6%Wpuxo5|Cz4%_h zQN8DjIHZ=`v^8y#m-P6+h0i~DmBIj47#Y7XG_4avDKOHEn4fg~{B?VGP2XIOKzV%4 z8~JH4TnXjmwZ};8pYvhcQ8UN?daZV&Wq@+WaMfP@Zu>zhQ)55+MT3mfi1_icgZWGN zn%@Tq6A|PkzV<0!p%MZD2zno#j+5$x7{XM5w6Ej7D&F zk`9V$Bn=Ws660Y<5%yJ>I+T3bU4@1hsKAcFpAPxpm$KXg(WkR&o#j#>f*afxtBQi94s@cLwz@)Bs7L1VC2pvEI*kOHNWfgJ+*3sKh~|s5yc-BN2^x4C}XHr z2PX8e5V5kM!n!yh5!SwGGmGf3DO1B#041)xKze;xVNDbcqU-s5M}K6T1{A<{|Av(i zI(Q>WlTx%WY>`q_g)==1HjtdHf6n3S=63t1EuHHtOZ(uNIm|fVfEm*i4Ie2UIs?63 zNaK=qa}IS7WXCcT$N?Y*YB6ETw*zlXPG<$lKj<@Ss34o|Fbm2B^Z59Yi&|faf)zEp zZuJ-Q-pn;@hS;M@-XjUJx$_qAkit?Oi<=rm_)=433@|^5Gf*>?qtCF5NBs@S)RFs+*QE?#%0h9j6jBu!wcMji5ir73(CuRi*he0z?c{#bKoF{{&D|4B#k_{ zE5wjm`N9x$B8Oabrvbnz8GsD3F4vEbA?UFbxVXaP5e6YpCVfdiA7na{vu$6u^IAd} z-oXX0tzp|K^e$Dv_yC#_GNobgzKc0Ib4!B%?~6ADgA96u<}PO4CDC zTkJV175*#g@X>lZUnc43>#r);w-H1dV{(Zs;DaLQJ>sGyerhiJ?r*?91|BXgqsB-j zt@*qV|DfJ(+(|M@jphd)7yV6_oD;X3aSBPZY;$MclcW_ijzCl^2Bq2 zxdtgO9)S#%VmgI}z+h#i$#8>80wIN|JvMwvD94J|d^b1;dLByzTbRg?R>*_K>V-i# zkw&P#300|X$=@VPGclrMo{LJ|Si`Q=5K61TI&@rRCN`zOl5@QW1__x;nDk|8`DNrT zz#iRfuZ%*6u6@vxB8CX3)B#4uG>`?5Xzh-XHwD7qTs|c8Je-nikJmW>hhz9@x=~C% zQj+tB$C>gikt`erg#9W`@RKLAUsIqb_uA^Q%Rh62_RN(fk7mc+e_Gx~%2GQ7i@J(@ z)1u(CEDQCiZHvjyE;26gg&Uac0K*#>6)8r-i%umvZ(CPku{e{BDGl(Eu2kK9aY|vcyg?2rhuSw zqdqH9C*^Wp@d$ie&^2?UNi&ABt$d?RgesvA11h$HyKRMi6J;aDNkGE12Cd$D+iF|( z_^Tsyx57qft_kaKO(GZ56`9ej5^D0~O{QdAu zwR0^edF#z95$@4qQSV{F$=-wlhD^CiA9Ae$uG@72dj-hB#bKyqH9u;F=YbIEi<5{> zDf+t4az}6;ngMFCA9(iF?VsWGW@2BN_FNWbDp+=rH6}&lK^*lA{ejSAT7*9S3<$2q zQaNVDH;p6P*t!bi$0XdX+{;;oa3L}+C(zh$pO*{N&kGSN(8dYKeKQlza>q;W@#CrV z$4?ca>UC%8;j6$V41;qg|Ii_pO*9r9w4&N*l%t9x+M&kj9;-&7&06SgroucZFRRC& z+mG7T^B>dB8#Uz&d}+EmhF;iwNk_I@xl(wor&YXBK3o2x6g#J#RYN?<`e}&eA_#D; zvWz(bZg&Br&8#-|PMHOdYx_Sc;&cMD4O&CnCY6$+zW=U05Pz-)-S786+0Zd+kC;{Q^H^6pzhBwcMCBP(Kg)!3SRC; z4!c~*ogC*mc!O2Oe)VlyxkH+^6E_o5NjnD9hL2}Up^MsN!;u0BlWbHy(yZcca#~Oc zKy6oAVWx8M)pmaT%a^vjdXkK7wBA~cC7Mf_RG#I?PSWVA2R3o>sx1NqYn6$dL|_Z9 z2s02;?^(60N*L8r8>eEx z6r7*c@n~{i%4wovsH3VqA4k`I)Q8J^kaKR{OKD5YFbbUnJ9)2tmTGj@43sGqb^Y3BGo%7! z=L$wHuA(%tQlzjLWnzB)J8x^TgQ(d>`W>$y$gZ9dZ#1hWEKzeh+s8>={8am8o>(U` z6PgoRhwF?PW|(j5Y}Kq* zExd_m2f&Mfx^K7)F!3ANdK;EEap@Y?2YyPw(}$l8p%Sz@MTpH-D4f zvr|6TDbwx(#gwy?i6Ey^yr-*O!KE{MrOn$P?$*jc7>sEU&TH`!pEuarDf%qiqkfd& z42C7Lc22(5<3ftQfP17T$a}m4C%(w2t3eK(5k-(ZZVlCzGI`F$%6tOni$19IYUDSD zqtS%Q%}7slhb@2eO1GbkxX{9(i!ur91BtcaN%+7z0aCeJtnT1$`$6e3#9zm%>^6PV z7Z;5k`yraLUfzJ6(8khN#7F` zJ7XNgk>r=dQm32@eVrL6|5i-zmA4BR@p{c^iDy^E?P zYv5zwE9X(Xw*7mJP3{{F-8sn41Ep}D!C`>NoG_!Wi%`U`swUjY(fCbu>yjxpL%EU* zbH?4bHRo8LroA`joQv%FDHtN7nxt>^K3q4fAg*H|Crn+pY&zf^^3A4ktW#FU*1}0M z*%-)Zx!GgRG&)e!|GTsRPJbbcnLmY6A9$L!Ji$4Mq9IFDI;=t(Y>Ey}eMwJRu~4~V zwd_c{P;#|`24jwuJjGlK?mCSP(uYsG41Ms|M}Eyx2>*h6ib5g{6>zo#t!Bqp+K2s3 zF=Y}E6@AcYS^jw0Q-7}ou%ueWuEF0nRj&8zwLi64aCd_^4OZ6?3+S?!)TYVC>iX<~pDGDYhCs&#Sm;@Z*MYDXbsH!mlXyQUIj zPrF+eMzDIj?1j6xz`#mL5#gZDr~wQI8Zey7Pa9(NzC&BtYAIo4Du2pA0O{wm z=e5JD#0ySB|JIi3kcwF5)$9AFu(SF58tXG9yE6vDkkL?LETLRK8`EuXmH>y`2@ld0 zt)xGU+!muw)XaXx_)bNb1_neh6!B3g?KnsPseO>eA3bMi?2QCz09^p76%!jm;Eeur zwflw=yA!WJc1wK#5YUM|eE^5u^pT;%#E5@bj2J!j1kVZBeIJ<+0wWwUR@9ckzu4?G zo;#h4CJUS>qVxu4rBhTD%q$~KooHnesP@&MLY=Wqb-=t{4*;>DYjwu}HqDP8+tRtv zgMW^<*GwR-js=a=mFxzGQOZx7U@F&x4jv~!b<4yGAo>>CV);~T=+ z(;H5+m?Y6LFz6#h5w5f*1g;e@gGv&#bRxKQCNjTq)>Gp=X5Ef{Ag&u&w?Jg~rOxlt zU$5yMmzo-`)Ya}qz)QV)+uw&Gx9v;4fmY^~cJJ6YzE?UqO=-V2eM$%R$T-NnB@v5= zcmt^nuqKq^LU%G8w=1qbT?UDF;W~*o4Pij632EUT>_SZ=0!NUN{Z2?s<)}Q;osBzJ zFIZupNO%4<&6_-Re7`$-h1HXIW)}lYcUGstz-HDw)+nTx@V_TE?AEz2v$Eqf`qhC4 z`nA3KG-<`-1mPgBPF0l(3-P(K{q(o+IUts_JwO304&5+sw7!5Dt-YjLS3T#?ljifD z9FfOnOGMsrys(DKw}kG_Jh2j|;6fP0Tv%d(+QE z5Cqu8#mUWB#T}s6_H&`JC z!SDR3r-d1SZc2D84;DCELP4bo%#kFSSia#m==C*5p^fq>xVJ=;@of`7WX5$v!rdWP zV0gpwlbM>Q9`9MC=L12C8QepA05JokJ!`*l1*PNw)JG2ya+Rd(eJi%cPoib&kz@z3atqRTV+L6qK{)1w zn}Fk4C}nG>7YL8oMC8!Ls~PMV(Bs^uDg@(G07-zK2@>e!bL`!rCkg@Q`pt46*kFX@ z{C*Rw#PaSKUkx4f<(S6eMyQMYwGz7!x-!9HZu>QA7&36`vjZ=l&58bbbx}v@(4>U; zgHAv~9`*|xG`(N<-)DMty{k0w2XuxDkTOY2_+{32Lhisl^n*fRVh|c>8T>F5h4;1# zBa~1g(YX-rZ|d9lO(c(5I=&;>)k*{VS8jgr{QNbF;EXNtU>O&=@=yI6`jIkOtNvNf zZa>&ZZ)@ei*+=bWrQu%vx;4uhe>N*E>rNy4z`FG+^CcUS^fAOj`aZ7vzICX>kO+AZ zKITdaP_ELA19XoI!d#3?zXnM|Fc|bD-bSrvVQraVN=*L64|VN+znji|zEV!|@isjh zf4@FQi4_Ta54hK`5+;DK8fiU{;Z|-GW2uk{#>@Uu$7J8iGl^SCD)4=a2=K@fPN{lC zB`FnPqAv3_4pWg?-S43+_EJZB1hoTaF$5FtJ)n*{V7q?~U^)wOCqU(Tp>3^G#MUwJEk z-ym8P$*)MO1wn?)FRGqUbcGR+4k?&4M0-CDd(dMlswZ#2J&haetEzR|j3@#ClL#JH zkh8!Qa-@7r(WX2{Iaq2?1MQ^)ewrUdW3!2!h44&98y?xGaD1W(%M?^b87rJOi6h$7 zR+V2pP+H22X%XpOpm_#h)V`yPW}uLxmPSiuqcxTreri1ZHX%xh zX?C8IOIgo8C0P}fPsNSIN5hh3eKs0%PwO8<=>!YiAESBa^}kLIhUf6QF@i8UN(hzt zoZJZ5E_yWwP{XpIBq$JWyuHIO97s$#3Jl7c!uy6rI8gbQtEH9Gb#PZFe^4g6qnibR zOSDtHhJi{6)Tzc`?nXjv%^*z++qVeoE@GBT`g9C4G=s$`eA}z=LkthVmbOmQNiO>- zJC{qKaZ9W4_K{WRDMos;;FB%kBq> z&eB>+NRW{d`yr9>Y%6PIp+y5rnoB%;fLww)g|niCuI21W5ZLReLF}I8-by02zBCHR zwWdM0RO(zN*SGbb1sxMX3(kjJmQIOHZyZ_@>jFDtEZIkhO8uadEeR|mck`g4u@xm! zOK&qoo|P-k6sIa>M(5@ll5IQGw#8~x8G=>Ng*Go?I=Xi(C;h+US)}l6tJH!^m>|1g zZ3FG`#E1lBzU`jIk3@U6}7s4dF`E!(jj9+cGCuOy$wL{E4Q8^U2>puF7P z_8yzI(8Qcj6w6^WocA}crV=EA8a>2Pb{M!1GUJI6DR3i3PyhrB8pi_R?RENIn*Fpa z=8cR1wP|DQ4hEfEsi9*4P14(6E34R2TrR-6?A4rB-V{-K)W2qe(;9gpEbIS*5^Qz) zLWZW{pM+b7`+SrWF6TSgRI@H)BG@cAzJRuYKy&+MIggFKx8=_g+q&QaLl4j_8lar? z@zr5oGcX4PfPa;YY+i}$A zD+KNbQ%N@au8f>%o>?mPew}9b=uxLf+Rfe>Dc2+G%@bx;7{Izhk?EwurK?$PFgq@? zsDupUnGm;y6&xettw)*28<)eyR&^bhjFpFY+S>LSjyX@$QSgI90vB`SYnx5ou1w}fR-_T41?wCYl^+X zZgFyRRn@yu&jY0gqVb&8#^Tzz1Qb#~CQj5=|1EASD^v(p#K+#D@d0-&FKr36&yL`a z0C0@`5Vz}^bTYIc+!NOy7e7XWhLRQ5hyCa+XpR%7c5i%VrY}sQvcA;v<07qsj_Ao# zEO#ym(;l~d!1+{_vRX?y7h-d1z?^-*BEN~=4W2(klw3B;ei10uJ~;Fjs9~c^qjtOa z(r7WE>@T17IWpZ(f~%$*dFr;lBbFzcMVganB3Rib)(cbMlA}V5Lq3^J~e! zxB=Z4XR+>l?-_R0OIuH}o*d;y605STm}ZvI9=(Wk%{`~yd4t#*I?k!2^SwdA6tJX= z!vHB;H!qa1^CF*wP-XtB?QufN3Njbd(Qng5G}U}bpPZE;>C$hhBsXNXiirNTcz7c8 zr(whUtb0(H#}yUY@?F!I0q|9XCe{HRJ6cmnC02Ek25IPN%Iw^?wsE!uxj z{Fc441}QZ#!Y%P_-55J| z3uhubP!seB<>UusQP{W{YM4J$q(bGu#31tOUcf;jZo=&fP7+XZL%W|!w`uJaRaFyp zDniL*tTxu1rI#)*dGHopxEhOWLZH(0pdd{J*s$Z?5&>1f)~%JnrM?v%L=zuT%DuSa zM;9)(XC~+BO7CKLg>i1REGYNv>cZSSzZKi$OE(`t_vpRSUq#Fxw62+S1|2*|?Ed{w z$#25{Kw+;q@1Ej}#t%b&_Aw$qPKdAu_ z_a=DTWxPBbF5xAWPd{fC!An~Snq!?mSq~Ktsu~`Nas|}0I!)u`22`~T`zI!>0%Gg8 z8c?$jf$-iTbz9d&1x0IYv2j5n;4|%Gj_hWCyIcdy!?un{obk{yES70Yk~gTDecun1 z;xV{S@=9m#*sJ$odm|~L&e2mLA(VBIMjVo(S5{ZA^OPLIYkr=58K2j0jxgfN@iY`8LhDO6aUc(1x7pHQHer$^YmNf~$n2c)w3{{Gh4#4f@fed}Z;zsyNG!@78*NVJ%w za+WL=d}z8AnYPf|?}(ZI7I-G4--d&&x%Q&Ogv58{O)vsbQjf#}?)e)M}lXQCg*Zl*$CHBD}8FIKnRZv+2=N`wJc58Lofp`dW39)lBlP8AF=G6{0%S z_?mp?@$&Ed7<)2_cp!Y1Y9+u%+g&e{z}Q*`%BJ^Hlw*`Ud~63aT{@7)LEQT8FKxrZ#BL>)fg_#y?p_~ zVf#ZF5F~)4zS$p1uedds@q~zCoe7SHSXd!?z`uHui(Rv;=VYzf1Z2{(tfV>wx7q^hMpR^`V7w0hz0In-~CH;La*Zc z2&CAB6AOexWbW%i(+cQ-(gn%!_V~w+)SnByUKV z>MLj~LvVyLr~Xk6q%2s(y4}&Xxfxh~8wMX`a}762Cm{Sc*;$9KJ2=)R;YN**cVjcK zEM9uu%y+g^;{x2d)63QA<>1czv61ilO?w|~z^~_3n6r*Ao9wROSA@7SPA~k|fa6RD z4&0p#sOk^`8xiD*U4xz+@k^Qqh_A~Cx@t7kW0l~LgSVTs&l51zh8Y(Rg`O8CN3zBP ziRi2)rgJqzK0@h3zjoInF8phA?N`&gpA{jT{CjPrsvGW%%Eu`jE+R5a)7TH)=H+U# z_vfAIlvg(nF_QY&2^hGn*d+}l-feWjg=VYUPKs$|O_)*W4F- zyBJ@vkP>3h`n&-+4d8Aav<(l35UImYeL^W;Mk91n7 zM>&W4Mq{q{OE$=wtdNwHsYrMJxwl~jA$fmqcHc{KM0}gC*YoG=eb(j;4l(*^JSKS@ zU2#hG#f&QS;MX?AMJWE|z1_PI2ZD22tu^4v8oY~X{srdt^kU3>$S|NBn(slbQkCABb1+c;Cv3?>xzC&er!$NW_Z1EQVS)WCyLJe5 z%FmzBePpI!@b~gnfcBSz%*UU-uM^}t-vPn;3H&ByHZD7S*2g;`WCZ+LyRa{O&uYnQ z=RXE<5ZS0W)rvfbt#F$g0a8c7H5#kb*8y8|zn<_E<0^WAiQ8{)4?B7gvqXgVR}Eo9fCz{5E7-Xip81BD}TEy?n;IYp_@|xVU8^;u|gUQHRE`aPKcJVVWB(>=SuPfiLaF3%7A?HG;b)RXhXH-F35nVXPzPjSDa6;Fxthk zG(ls$F05?B^GISh6nthrW3#0lMFf>#VEgzh+s3(yw+fLWx;_5{NcQyj{xJ!?F}&bt zsi|>XjUKtd_Rg#5y*!u%M@tMwm^73mvuy5s`@v3@^)bS&)yfUk;j3B~m0H z?gz=28ta`8EyQ5+vn2qUN{5gOas<`G4je8l8VK~4AqOLc&)=&OT!9H98)FfH9cHI; zG40emLo{Q_UO}Y-DhWfGG)?vMH}{~hR!sZI{QXi{^!rI>Sq=-K!7wEYhyjR`qzs<$ z4mT(+S~*wTwqSzm7lox-JLL!bss&;@bV-OH73COTW%=7$Wdv2X4;(C0xqVY-hTB~I zVQ;?JNQ|7E!+Rf~KYjM+!`51JQXUnv^pd~Jcl5M}T~UXy$~ zt=KPB3yyMo%J7OvvnlzJBrm+b1=bI_nkG&=6i*#FAvCutTTC+9o;=9^^tb z4V!xHbaP67a4U+KmHQ0Q;DNxoI4RTh((C_}gcaOBHf@I%!r+V4eC2Rw8$_bt zlIOL+!D;M7qz)oAZ~LiO=A&ZKC=6HmVzfuS;Qa6sr$>I(3F#zx+yfoQVORYqb(#>*o`o5p z4^Ckf^H<}*@0dR~EK0V_rn>u@$;ioRg*~w-svshk}i;boCQF zo6G0%JgK{*7um1`7EG>OyGEqp5w5hs3TEOt0mVb1h@UmE6?_6o+m#MUX!dHr246-vNa9Kr_E-Lx(tG5{Y6;IbihkD&g-rTWZVv6nYx{gGwih9CbDlKaF+KIv-1$t1Qa-5 zRaK3M#Dz_CXt9=ZiZRtj1s;bkt;N`wdL|)#?}83D>F}_RBPB_zO%U(HU_;n*>1sYw zJ9He1T3~}UHq=4EPP$iF1V3~O0SFS7$I%;n40Q{RYp2}n4lWN^JC5V!u`8$mzR`qZ z(?mEId->P2d0R*hqYEqguSqhe&w}$4lieT%PB;F9ZkEcZ41^g*3PJKt2WsrNl`Faa z`EKjo82c-9D3So9zwzm^wPnnuqg_5sTo9nwy_%>H0Xx*RbYpWNbe?1AIzShqb_(To z+-0j3qY1UDtTs5m36%_~DRb4t28%Rfv^P;9qjCxYZ7r&B%VzgQEb@ORJbF9WdU6wMVq;vmITIU2s zF?y$|kkd7-x>Wb^zi)f32a`VUGMHI`mDmyXn+lvD6XZCRSR}c7d|*j0qF{kaR3-B7 z=4Z?6-~ZY)5DMJ{tUv((NR$3|0{Z@=Y0$K=7qK<6Gq$ib6F0H8|6jY-t~G6(Hro*Y z+57xEoWhe7D8iFa-v8;raJc86W@dz47q!U_0R`lRh2m-SXt+6lU+MgUK_nZ}biLTW z<$X00wP{>)eG1WTc-M*LAl@Yya!_~(Oe8155)Y%82o_mr&{4FWo&? z$m}Pb63DWOIMYix)eO}$lG^Vok?=+|N%9-B9y#SE1_+HO+7tfzI&gAwlIDkTLJH@j z_rE|Zh)ODAh6m6rd_hABpuqwWvX?R)p1(kK@whE^;Rnk(NW* zj-RwfnUPXJXG}M$&jmSbwjI;?jf*8Ee2@l%Dq{*Q%$X851tnY7cNH{D`ChrAM+OTe zFUV%hc8rYN$oXBrKRuPJYFBqi8tS6>t?^OE1JC{7=3`Qfl)+z&I1_%CX%`y;JgFZ6 zcrabY0R{4p*Jn2i&X_}_Q2n{Hk70w2o}{v z&om=UfuWu{Ma6Y!oU(Jr6Mvs@?@b4Fz73=dla!@CB~lJlxyCX*&+q#B0&q*Oh(Tc6 z2aZ2$kX$4w5_&>|RHwG@jk>ZewP%v>sjYn`>9>K+s*HcC%a+Ou&FqPh5JGt4~6y{s9p2B`n?$I@AI^EeAk4jRjG z>6O|1NzlMaK zacM(N)z$8xNMC285Pj`$?-anvyCkhj9_^Kh@LL?NJP5E~^KFa?r(@_~C@I<(pw>^< zvxU^n%em8L!o1E;H|)_0Sc*+wwt8yS=gdS=p-tH?U)bqnR;o%41xepLW#Smv(dMK& ziC&AAYpj5EBx5SY)fh||gvwti<61gJq=gJ8)e<8^R5!@T2NpynRl$vwTbQX#%Qe^}rjmMz_gU~P@k4=5j0)*7my+R1&VyxSw0O}EL^ft}aUrT^8>TGv8I#O{p=`n+_>tpZH zPqtovUaAVs$5@WR#dV5+i@Ik*PE%41F^Gtvj!?>DougQ+k%rK0f$}oXZ5b{h>Ko#K6?Mn$-#aP+Cfq`xDE&MX_^5WPmf}nwm zQ2JkBRj@jBd&jL%WbPG!chgKkh(&vPH=FkTH361HE-W?%z1;H7%XSIOgP=o*i-fep zfI{2m?=%AQ4E&;C%4;e03n(p*V6i~jDe_{QLV|bwfLA+jLMr& zpW%y|XN=g%-_Da%Ossy7aPO|%niwkm>37XKcN;@q6V>=`O%Z;&X6n}YMhAC(KTq)& z_y!%i|ANW*RM5p|33df zlBJJ{Rsj{k4EkNaU@@FQ+<2YYhNLl0384LmeIv6BB^jLfC}BcM)1_w#3HVEBRsr?j z*e#pQfjZ>l=edug9i=kmX3bF_C2~S)Ao|^QwyCv)&_OTT0e>{Q7(&qs3hR zKrTHg-MXFU&Z)b;&U&7%@9_DHxzOineV*RDR_*_Jn%#z(DWBn>ais+$%eI&o|v6^kqAQX;-g7|KFB zwrm=ah*Nbe>o#00d}2XoeumbYBr^@q=g4?iCNPa&*DwN7%fYx$*e)YGz3hrJLVs@e zqp4ix$l_>;CYe31x)k~8s-(a}J_9`wL>m>iZU#Kz?6!GdDI~WYU8uArlF5pz3fVOV!(08^QdKIi zE3CMIu{lV*s}Sf}$0G&pLbYV6HGjsTs6o)v9dpQ$ z9XL~8U^XISIRoljFzmSY=TEw{auO=H*`(*cD!|#2M2)7P_ z-cndb^YtSDgP^FMRK*fm>|b|la*6NlWg~9u`(r8$-ewGs`+%qI7h-dd{ZknM?5@LG zGhAGz9=t8;hkGOnBFC>6(O!sA!c?cJyr>`9uNOLx%}grki&4FYtQqqM`2>n;lcUXxRkVbEZ>5`fS9ii$i5&bD zY3(_Nn7*AW(t`4raL+*i2ycOkj=fpkMaQf5n6sV^b#hd(m34N1JPgd~nq){6s+*Fu zET$Re%r-SB?8=f@AxfNz(iQ;Nq-^CO37JPvox9A%%vpCU?vZQfXUlnQ zucnE|DA8iv&Fc^7f5ps$qv92}|MD>S{smkAzgwyQ7iN|*aW=R6pF{R#bseQmE(D+1 z+PR}14rzNVNj|?8CHAxfq%0W7;=2I|t#B8k$({u14A-|?H`4X+#Wa5=ABr3UL2HXy z&Q3E@>g;N;4Z$)w-~kZGc%XV`?qX0pwDH6Y2CCqbirUIa8 zC0-%qu;9TsDtjE_i9J!nGJB?Bo+4|gzV(1b3laq`v!KW@)0P-!RYOrRQfvbtEA2SX z^poI(h%+K|nMi)OchClt#LyF;!0#xvIaM{{6V|

3A?Ds6Fe}@n%$_ZurY#cHMPW>z1Zk{MlrI9mmg(_F_anvZu2vzbqSB0y~Fvy>MJafs;Tyz(g&} z^-SJO-`>I4QC8o|_}k9ckN2(QmPJv%43*)C9D>Rlpu+_%+be*_=bL8{FJ@Cd;?4|f zmiRpR;lz0YLiwQ8#l(totpwWtGdhgzhl6`8dw2ILVQV?`@SsT7`aeOWKyj>(NT`R# zi_6VM-$LR|E%4*Y#I$sNHixx9$B}^vZKaoqNExd}Yua_&;YfNdsLdo`5AyyH6bR}% zp@%E?`*cTrn%jZGlkVsmx^Ntn#2naIPp7pyFo0XhV3-GQ!}ud()sqDbCrJ1uWzO#R z1WnC&>(E$#(8>mF52cFEzkg!jpk;%(e0M?}Rg`?mCy4tjoYTmdW0E9a=24z%@%Zz5 zZHQYs<#@m`VUvfDNxCoYI&ILL)QIQk(X7Sws7nTvsaZPFyIpxbmqV9eVj{YNM2tfK6WULbKBJ({EkSv0lR=4xn{Jx z4k-igNjYn8P10C9)-<}bN*0@OjxUbu0p#s4>U<~C4KX&(E#dQgS>p85EM3_bWJfbx zJevq&=hhH;rndInXK#oOs4v0!aBeAfx)w%PbScbKqks z9Bq^cLkfbJSlI?9Lp!B)?Xsw(6s@s3qVur`q+vv#_}kt~{%~H`L~;ht!5+CO1t#=d zYDwWOq;*!&A!Bb!{3crDV}zPId7zN-yFhpA=&%HnvS+g1|Y`cch+};lY>9atKWoA>}Wz&iX|$#GhBv- zmp_P^rWdV37iZ#5-qez#y76vLIDjkjivz`;sbaNeU0m%8g)H>c{nI*cYfW_Y=X(Zq zONC6RNN4s0YPPq^K?b(>^|mvZ!d2y{5)4f$?m=zj`vkw)H7-HlbT1b1bTnF|=qyTO&ld+th43_uEc!PnFFS2x&cj(RHxf_wo_HB(4 zDmMj2_RR2cX0Kk8*Y(% zmn;mFs=tIz5og_G!>sDi_cDy1vs&4v$B|tfe8zJsW)$Dey7y^~K{;ubg1+kb$q+t0 zq~@k=2Wj7)dDvsnV|au-ciEF+rBhnL5cLb&nv^ z3RRKE8OzwQ=d`Ph)9g%k2D%8#9^YZRlBVpp3ishnFx8(^*+b22!$5oo)vWs=#Um`q0evCVO=D9 zGd}w~ATNZ6TN$T`4>Ehqwtx{|@AEigUCj=INrzBMi}`WJ)8&nh0RhRUd#BLc_nQ4* zA0}g0?~X2&Sbr&2Z8>-fD>v+?u>I`e!d_d%*8KsWKshR#{<}(v%Uc@B%UeYSdmD*c zG8v|DtobmkN8bE$=R-Rb9aX}dcQ84HPrjb~vf22;EyK7!yM+q$izEX2MPAP>3)ll4 zj-8Ev7Ok^tRu0pg7jAiSSt1{k;*v!|p`^+)zy`x)I!}n-Q%=il0(d$r1;*-Sm&=}E?W@G)2n8Za*dN2a_ZpWaq zkVcJcAPpsZ>DK!Q+lymJqj&d7CWvQsF|u%C@r1PXJlUg;7lj4^A1XQivg)+Gk046A zh64K$EAuds5uMqHLa_6W0+GI7t{Mic{h$E~8gwpF(2`*;Danfsj#OHvG#qi0Xj)!W zbAFRj>ge`|;UYYZP-UAdOqH5`V1Kjbj|gzPiwey&Sj+y=bLj= zAoOJm`;}h{U1l3UEY~`0e4cODZT?b(WqTXpd}p}e84OA;G4n$smSlM9Kz`=TZSK`f zoM058nB~wguFx3G(%S{MS1o8*$yLbOf?jqR(1fbQl=c`CEP6Jo3YGFjGa2zv5<2j7 z8}FN=LM5VB+{+(BF?oh?)@iLy9K9g={!R`mVQL>ENpqUIcgE}P4>AFXaFk%aBLWk= zsrqq)c2=jsgS+YYY!M`YDmUdh#y$7y9{YKN19iqcTsdRb$$RgdJvrd~4VpJWVI6bw$ z#fGm-Zh$w4U5@^-&0%tC)|{~VEecc?$a|`|**YW%lhK#ObxyFHJ|V*4zF=jwylW<2 zWq5;Y8X!F7O1NS!Hfk%)kw<9)xK)vxSY0VoRyuk6&1&9k^C;OvS*Fm$3zG)02J|mX zd`NsJXX##5_Z`mSIvRb@nH<13NO`Pmo`s(~0YXo!wrf))V#~d_D276Y({Ni6a>P40 znzfEhZ|c1~%&@C`lx9Ch@~CLA`O2&Qa+Z4Lgiuj6VOrntIu%sUhrw=GTQxMxF62Ri zjUTZ(q1MtIKw82%dfgIkCn&z_sH%9FN>4rje~063N7ca2A<o!FW_Exg2JjU`5~WgjjBmI=>nlaHDg9-skYVmh8@d8ea6 zH>i16I0G!l=54^Ful}K+CR(kE{?wDBAmfVmW-cS9Rt6QpB@Z5|y?RG4b))1U=l#Sk zJ0qzc2dzr2r5cUL_1W03TRjh~bloR+^AA>QNiqqWjlmNXCr1r6)LH_KxwlO$IZr=Bn4ah_VML!YbWi8>{oQFpVc&|^Hvcyhnrckhh*Av1>GXu5P_5rTwvgLa|GqyciuUE z_c|^a*@SW%bKZ?G?FsVE3kAXqqK^w3{iBK%(?h#@?>=gmoCpuu&xna}?W|3oQ0^8t z21SJpc9lHhZg~-v*UtnAiT@%&w<)|bu;6W@X}3vFVMQrXJ$U#7{baq*1MQB_;d4`V z(@|bdthBthZX`HV*vg%+zW=2~Q~!WMrM?o2*nR>Y*?-pE@bSjzNr{Ep;LdRWbgnSn zYa~s^N81q~siTdu<*Ue`d|7$wy6Swzhesrd=2j0!J@bl796mX5ouwwddNFFz(k*q% z?%Z?UGaAgUp)IQjDOqzws+)xc+gzAY=#$Y1qL#GxX7RIhUB|82 zeAf@)3W4(|fyEz0c_3;eOxe%2dd8vax@)mNV8uR<#MAL!(?w6y$bQmMCl)q#gw@`&%uAxjQ6fKH`^x1Gd0D%gl zo-{+w;F$D!{W*gpAH8>dZf8B@70SI@28Ori`eiI$AyS-;8=mhG-LM~@jr%))g+H6# z^ehB_;gw17g>A4GJe!&-!F?$fF&KkNK54`y=993rh)-#O`j82}$w`3elgitxQ-U~X zW5n&S?cxyWW6Vant8 z%~-w4W-LWjM| z&?3>5O>8f+55J2Unj>54D@;ZXQ;X&z>4T-3q3!fT6sFxVd!i~& zh>}jVm$+Ios^q_OA z!j?Yx==;v?`%lwFX+M=er9JVIH}~MMt*3T&w6>$2)~H9vmeAR^DuxR-QagMxqjn}{ z(Qqe0IyTi*{5&|?7Piig>L6p80K^8=r9jhK0J9j;hrLIAMCw^6C8|3O>tL*F9hkx&tJZdPf_7$ zm}WoqlU4#cYXEE3QDTS-L`sgvsD5xoajnji zWDiszjuN;G$~p&pv3wpXARd%v-!-rKT766PZWY}do{@tTu=QobKqNlM*xnd8c}-gk zBu`u7`Ls|z+C)Dtxe7>z7<{+BYAr%z481ppugOOH=fm7E$In zllpBn##<{WkmDg}R$hFRXA6gL53!yzo~`tocs-`srLj)NMr8J|pq1AsiYQ}5R=V|= z5h}hwwL;V4)YCbEGN(H&L`et*$IwY+Z%G9`9N69#_NbaWm}VB3{hta%FJr|mjne_z zdbvQ&^Wc3o`11JnxD77f8&}pkd&RqXww#BdEt?S)$~mouv4~jP($x&OrnPg-M$HJf zoXe7+ht~pm4lJg2kIHH}x^*%p%}sd+WqHbSr(;@u=l$HgZPy>bxqJz=-Td-(Aer+) zh(ldCb0F0~?ezTRjh9Uj+HRJ>jiB0hKtO;gJrEfYWdS+~Sy2XQ2_X?#B@uc@SI1cm zO^3HVn84P`N&8$SbEw=@R&%`d;EI)i5@2Uyy){KlAbB})EmV0gJ@J$C1K#*%?`$KN z6IGd9Hi-{YRqLNpw^RI4(vLOwD`%*8b>a&h-gmReeGyX6lc8)$Yo+g+H{y_VL(y&Z zI3J7&aqb*xeRyEeIzLQq#lqoyTDVv;Q-oc&^W|hKuSTu7wCip1*w`nJhgBLOE*vgP zohJ<_E)%sb9QTRlmL?#1oock^=jl9;yyhdl%GQ=7#~NOPQ?0KtG_kXIK1;OanPPpW zQi%?p;wb;zNzgftO6LA9jRGF6Xdaxtij550(<7%vk;SSwXWy}8)K=`#V7OZ4xJmpj zjkr52w2?N0b+f_Seg%uZ0qfFS&kOOw512m-SB&mM7u7ZjBs|V528q+lBm{Q6b`GhX z+e{A+aMc=2_6fA*YSQZK*X9H^5imo(QDt9B5>BULa(3k()qz!yj?I8f08KkEK)Abr z`KEt&TyLa3DHmn5a3_-_2mUUi2ahx69a@>UNkdYfke@UYI^PN8NC|Q2i6%TZa|1_> zDaIurbZ6aDG;zeBq~9lJU~@Buw@rs+$V6*c_QW<|d=|Ul=sqO1nBEJfT3s2V=|9x@ zcvfwz$-sYd8-swTN$ylKI#tu8j46q~-yce*m)APaEmnCGw|I(H^Vvp-jqcYk(a%}* z2-)3HSdpwjin5T~WK`>kQH8CQp+%|K>g-8*U$fMonX(LZK^Av=PE8qaIUONeeaa|8 zHCB&$5r~~ZD4_XK9(AN~Y)GL^Da8&gQd3sY3b8RR(kD{qqh0oa>R7*qnr!R1(XL#b z$O9Tgv6xtu_Vxza2^BFE83k_YSy7?^g{Q zF{xHxP29Nl7lUiMC~$d&16ytL-aI`4pR%6k`V$SLe&FAXBu2qZ?W8n@p*qRkC3-*t znH<=K`5OGuEwLAV)$iCSVo6rdm}*gAZJ~}H*)QNXFJvQ!&LOSZZaps?RYVB9$M;#x zkT2D%gRtdx7;GTps3P13Jw6!)Nb(R-Q5+^npYNNn8CH_7ELt=uGE5*+?}Q{owO}@& zOuPcgnksS@^kq!qI=yQA?_g9PkkT)JyjOV6`vCzSbeiPlLy~*-8*Y$1e1gnuCZ37K zwmHQfAhh?WyrJx>mSNg>hu*fO&q*2JL3DGBX6|uIcEcUEZ3J%U7k8BOYA3*-rqa9I z!tttt$_I^1ROL0ZCl_T(=vfbz*V8xbq(oVqO)-tZ4p5Qh3c{#t@f(x|s_}t+RhROC zf?>H`&IM&&iLZkA$-|n+SyQLsU8jZmDzr{7<;J9>qI{e)4XgVL*FYYQJSOe5BGzD( z<(?`WSa3w-H+rD17)4cydn@eGGYk!}MDB;@bb|F|yQaJzDd0@TRp-w@A9wg`;2!Yn zqo>Ow+)oRJkO;66Dq1+qi)Emz}rHWN*Nd znT?&c*oxtYrUOV50c*!N1b=5-ElI4(R@yW=5!A*{ybG<_=)}*gZSBBg(Xx%nX%$Ia zY<(@Xkrw40#Qe##vvJ?0>m3@d8a_v>SGC?J^^KCiFd7$a1bsm#CZ>|+YzfQ28+Ilh z6fYU`2thO$^KMVIM}M9tPM|x2aL!*>aEX~w@K9oRrPGB zKWU{7%PJiO>Ao-wL^!*%+J_i)G)ZVhE9*m|TJe*7(?y$u#tSju8p{Ec6<7-rQB)}`&7|Fqo zCD;zniL7xN=+r>D#tre)iM4(9JZ9Q7%1I$C=EY(5j}SLr=8V7MNK;#RtSP%khJ~(v zZ)#VXi_%gb`kcvOq(pe+oNs3c@{ZEE7c3Or3lu6es*O651`OVGwmrfTCzR(g$WPRC z)B(msWp)MumoYFnV(mKJs0US5!q8eVWKV|<471C zRDW<4;6!n$Ynk>rk^Yq1e@q9Q0+QccGf>a^YRIqxQoxv-r3BS%jJcw^Gz?+iV%I7T zNo)V$L5iCMRHtFAiSU=M^!7bPR{L#H-US7`npIK|Eckv(SzEs+!=U(M5UMlBsyuzv zF%C$JYVAaHOe!dy%9gmn-pu|cZ%if4SQW#Mqp{U6??X!~?CS(!z5~-QS{Oiaf7L*Y zc-r+Ob0N9DPU+alOjfh@Q)J{v9DfjKrv-NOyN?1^qog9)J50#D@Vil&agRLFX+Kq4 zt)YE^h{i0yB=yZ6v4}HZn8@``3)*yRE9J->(&?4D_YNlNxyWM$-Yt%{65Q~hj5wwF zNrI*MJ^}Kvz-8GbH<~Q{VVUQY$ku3aJ@?>FT?pT+A&{66IR@Hw%w`Qd7Yhm@31hBs znvZ6}7)adGGU3r=ja(gYIm_RY&n3M817}cG66i%EM$j4P9z8Bt;7rz z0>y^os$H0+(0eZ;pLhn>Gd+U3m91qQG$I(+ZupFgYxzSY9CrFjwX$58sy3;a$k)>z zWNlu}*%^j;onhi*Lg-44+|+q+YM1A7Y1+3SQu<=i2clb<6*3QE7lhOmA`*RMQ`u;J zqPw_kD0+NxNx+Hx!sXqAwON?f>D}8 z4R%kZm2sENn4box_A5{_+V$4H`EZmBvZaC!@940b=}Ysz*Ze&yI}O|O*4s>t#KC)E zolGGw1JtK*Hv3+w7@X8C?-B2cS`d}JLRr{xfgMD3K@#AJb$nQs3 zf_2RjD4v!aIFx(=^m2kfLg&{fCPva{T7DHrvVxyrZ^|KP=IWW*vrn#N*o(Dp67_1~ zjnou$%DdBujF zUH2As+_h$A=~NE~Hf!qY2g+7$=7PK5o9-U2zK7cgU&C7vO9^jqM3bpgG&UTK6=0=| z1IoR8e_LNkrWVPOrBi#6 zRjbWmd|#D}HxGOQMf(V*TUT(#Qm6m5=(-pBq8+%_1F_yM=>o&#ml<2z>gKq~y47jy zRrqe6iJj|uidy?R17X%1pWK7v?t`4agBtZUZo7|&$Ri-OQC+1VRoCYOg8L~-An$n? z)Mu5#0bt?+J4V4e<;5PU!if_oJ`w?Krz47= zJMdoMHM#jm-FYvB9Z?tt4%gij(D}jcXI)8NsxZAFJPeANL(xmiNCl^?+7S%!>CM*g zcdBP@bt=gxIm*(%HD7~kDpB>L1aZpF{22*IYgdFlcUOJ^EKw)La;Y;Fm7Mzh3^^M|XX@BRwFDf-*R7(=&aQXlh zcj=@IRUADux~0o;lulA`pOw15qixu)!gQ2vnT6u+I?q&Y`11l~#E)=gASPO=w^F6v zqM#=1gtMN>g9Ho*-JCSH~!#9 zkDUCS4rU(M?w>Aw#v)YzvWM6ZnG5Na5B>E-@XLF`FQSDXmbKB&W<3{uI$A}UQYj!b ztcV}nsa_OHu)rvYDXX!dq0HdtuVmS<*?FocU^L`$?1beVL4n>fO(4jKT6j{*u$jHS zwAAnD8MF;=#D(kkbxTpcR@SNz{1Ipr2nOH##YW#^OH-Gs1llbS*Dp8>f&~SpkRX(L z`pY{$Ptrd-jCw8Y-+6&3e2ZDtx-rP)b0$t;5wN?ftat>`e57l!;}(^e?}M&|TjNjO z4d!_sLyq~iz23byr%6B4*t08*YcH<3wbPU2OQKEj#ont`x0@lGW8wNpWbfSk{xFA+$FkPoimfA zml6F*0R-e?dj7{77r(&1?eEV8FcCoW;`q;>-T<2U{qlyu_cy*D82ZzT7lZQcxqz~` z{Nj(3M!yoc=)Uyhm5X2efB)x#K=OYR`1h#NpD0mWqBQmwO8VcH|LqNSbG;aY1 zs{VA4>L*PLefvMsrM*N~|Jrm7ZOv`|Nci#x7haq2BXiq7(xtxi!Jn>8_eOHyy4Xtl zhl6TASzo^;835##fg%O|t_WLI>{7TgT z7&zuXjvU<&(jXVKwQfM$^lwUW(bezUb3r=q2Ba?z8!|I8{_(>v+sMHUr~`Mj{K-+= z{_)lSNaP-{ne&g*{@(uWSBh61F6kwTUVowZZFTe~Js6M+rzmF7tGfiOuZ99G=6V06 z2LgnEw!hH(X%+(CoZ8jR<-bB*e7deYwH*Q=Pevd@F2afyvNf{xKQj&)TL69l0_CcA@DRKa$OTJ6 z!0~TKee3Uyn6D~Dx7xG_yLsdO)GO_lF)sqKfP=Y+D{xn;sJXGF(SM4RL}<%r91a9Tn*6HTYdpFMl7_jhh_#`O z5pZf-+}P6gKfL^fEIVI_7j6R@$p;wPWi<)+zag58v7?#IfAho*trxQo@B|OE=(_9; zUx(ZT<)`R=Zuq^bk`=nl)|G&ln#H;54awqff(6J=+Q!=SKgWodu4i=$FfI%r5{g{X z2I};iV5nHz8ynh~TAM#IHu}lie?r=meeo{_1}X~(C>Mv+emvRU#@RQ4{6#JP6KCdw zhOjY^z|;d_pZ^C4@SE*zUU(B6F=K0EdwolJCwp5P2V+6=Z|#k)4%S@Ga;^iAzpxWt z4a|3d$%5GnDwZCv2F$f505NP}X z4|3W6!tdP#Lyd!zgH2b~*hR(K-1R>PufI`xhY{f9HXy;viGVmb=nYiz0zk=8|G)K~ zU^jt39I)nAfThc2!XVU5KxEBr{-*Fdp|R<-NFX4ZKnZy{JA96C6DR=Zw`l;;9o*q4 zfSqT6KfEk6HoO~RD4E&V|F_IwJln7ifq{7ngyG97fJbsekiQsEhc?)k2Y`DY0YaAW zzvgq{11-sKf&{1l5P*&4^&QRrf(SX6h1v~xU1scW_n7_w&GzP^xe20xfdi0S7&?AO z{tK$Q*_g^*pg>>lzZ%Ajm~Mg!sK#}3H(S@Q9Qwc@J_D?a=LeU-FW{TBZwUG4{5N`& zf-xQ#Lu$YeUv`4cdN%GmQDBo3621Lp|7sq$? z4J-j!{z$)t^&R#9GX$Khh?Q*v`46?))pXVN(M?c)+Qskd&MmUieQ3ZS@Br(-oPak* z-VlqORR-`j|H)Asp>Z)I8IX}gUG-=VB1iu9ny#yMF#A!2Y!{e!)0Def7bZ8}1X7KSm5ogo(35}iE@gAz#J8iq zmF<5DwpS{m@-2}27y)cv_Gddo*TwuXH}PBME~ewwv62tK0C}DQ)^It*-X6Uv&~Imw z&O?xL(Ex6;03fzYgXRXT#9S{O|I0*DRo}}JLSP!M09Y~-x&*N>aRUf}9}{tZoknU_ zEnPPU+y@dMwabA(cj12l{M$@{7+;F!=gv4Jo8~`5w6j(aqyEI%RXE(x7*0%+U2wNvdB}aQ>eXIX8 zrY0X5;#5HW5&#_sT<^b6wzmT`*frJfABKJjqClMar#~W4HVIgo+Sr>rnpyqXjU*Ix ziv<8*aUb{!;eWs3!gB?{-RLWXf#t2g+V;gH46Y4wl`0Tg(SS<$vTa)<-U#te6;uH6 z^O^>LtxA9`(MxRI0!;pTw*8NAC9IwGEzONY|EWg*EJ}I$H;?Q9OgDfz!AqDNK*4we z%zvtai+cOdc;&{hCq4jP8-OQu2@eM6MtHwY%v^`jr)aG?MSv-00V8->XZCP!1pJH6 z{5ij^TZfZi2GHC{u8J0f=zm32azFOhBw3fl~6aBZ#K@U-5ohPY$YO z3K{|ab4}^$Bvd5b{|fedKMHzE!nF&`Cx`G~wG2h!{}t_TuI^ZOq!}nl>4(opNar6oe@Y{E@yd`2{#1!vsLq(tESa{ z59ycX2bXz6pzo1K>7T;q_sXB!G8M{$2P{c>UafV=a{f2O-(z*ti_E(KMJf%DTVAep z8rp7%CFo>g@*jojMW)R5U{kCg@QktyS3OnW&~;IM2=AXGTYey&G`z|2ERf8#!vqlU~ZQr`UDyLkNMrN+J8x+KcN4rq3#4+?-Bts zHv^_jFNZTQmYZS=DGL2(K@!^6u_+7W%Wy!_b9tJ6`|eFK{t@l(LyXA$J#}rs98`cr zzf#l4;2B$X9S|A z;3dr%w!J>mPwW1hCc1|x&~X4GMG92dZ2P1{mH0REhQ&9fl!G{f3=c%?S4a;3x2LINMrxC$MXPx0)Q?`UmCct zPyWAv|7y@9{5@nBO9N*B@@4ld4ooEesaX8gnOq3jkit z<*&n9n5i~L1ZYt!All35?s+#yS2ni#XPN)H=zZd4<*b1Io&)7+LPM z10X*VVBJFO5^D*aHv&=9_{rMe)WjgK!0!#fnL1!2{Fgv&`>qfA6Yuwvau@X&56s%| zYrrBGfpz=K5%by0zo1>cvs=;F!O8MJHauRyT)n9N2VdFVFGsEi^Sg1npnmnL@t@Sq z0N(y+Sy!33eDV0NVd(V=j+fga4>1nB?7ybI!2@2C4o{CM#u#DCmY_v^=BOk`iZ zujnUziH$$gcltlK7hR=&_0pQ3v@_mchxU)2?SBo-S1--@2^73_9iU&Y(74LP)mHOA zX_xI?hxQL9{$}A<`&<9Sc?N8u`IEYS8wlWv)XUwjuQGDAQ|nIvuJh{ve4k+Xz0bee zsO~2~G6cl+IrzUx{DmD{Z5Q;DxIH|?&x3luG!Ocf{|gFNk2L#T^g; zfG-390Lnj#$q2|wh>9pF)5(bDsOs45Gaz`2?enSo@ZcoMza>DOQIsI@H-c>R98F;z#yPd^L+zU7`ciAmP{3K6qK71NZ1IzUeFW-9quCy;r&X<~NQ_ME9P-(o7Mts%H(~@r@AhwQ5yQ2c)@lM;VsMeaZ#I zWO=hGb7Cf5tm7cvT zXK>^?7n&_4YMw!PT_f~Bg`p(8+X~X}bA2YlIS9YNvCCmx(~&S0WALwhGuW1Yk-%o* zt!(mrlxIxAH!i!RSH>0#FA#JtWt;MEQ;1pNV2N0ax@$ZL7tfcG&b`8wK^rRg;|GQW z=&3(7dTH#h;;pugaa77B%15R8X0_ zcDl>DcoxW?D%~4Efmos;s!22f69Leq8a+~HX}c;Ebk!8&HSk_2DDBcDd9Y5V|H2V+ z=JJ@Y`nu9%F%i1$)c{Wl2%djlhLlRpte{%1iWI~yB2TcG;lOBw{SIa{4*O=f7ynmf#W}{;$MBC{>yfZ>@Dp6#L!=N$kW39PwY_s zWrzNMT9>hl&7b-6*VpCzrw&p4n|1y7xv~4x%TD(nSTX#)(M*4`)3pDAEwewrXbk^> zsoy}fVq#$U6UYADnf%ACa`*fbLnQysEpr1~Gm}4q8PUJ7;Nomy{dau`fb`!`?*h^B zvW5o$(4qO4o4B-ukch032%WRL^OmNT)5b8W?{n>{W2uq_SZNN61@=iq{b6XekcDu& zEm=|+X&pf;SluWcLFC6HPg-|Cv9a5ms!S=X#Kl_U$z9HMb_hb=tJXuqCgrVeT7}d3 z5VPE;kVcsdc~5RH-QbQfyQCL_Ua#-RR8o}dz-+I_qh;^T45yX$+!UiD@rdfUzC z+f`Y!dR5KfM%L2Oov%luW|SMd+y1~?2ZGy5s~fu-{`UR~D343C_RbEi-;4iFynpTS zzT{HJ0x-qNF?|;svtMC`J=Ypbp-KZXaJI92i;JLZ3Wbc?EtLW`wP+cXfr_0BYwC;3 zp2%KfifhnP7Gf{@d<0aha>^>spk@lqA$7dnRNGd>b#VD!Q0R#?XG;Zk>?6~YaQ*xP zcx7v+K)O#^6+nu90Un%S?7+18hu!+j1ZS(^>X<-ZsTQ??L2F4^7cLX%qAJ^drf?nw zqpLgrye_0hVsbucI$-XjAq@8}>f-qAvi|Ik%uE%UoKZv8fux1%xS4R z_{eTNSDG;P>?pV4M7$4kFJQ!^DlA+)ZPtdzX!G<=RB7s9?pCl2v~E=%CI@kOq{X_{JPA+KS}{&i73T-V26a z3_DPXs?K+m2kCI=23TbDOVdtFsy9drE9J+?)Uh4{R9VHuRo_kk*Kp`vQA=qE{zT3N z|Ic^=1k{`XauW!Ox6)gDD?-q$utC%XU{6f3k>I8?Rl z9)!H@r(U33e1c4@rhXY!_9a!m0Mxt`0bmY|2M~Qc(;Izx+fs(uAVci)1^3@1hoGMO zPQy+Os`{%(b<&~VbLiYKG5j0Bz5~W*sPdRQl8Q2>51&NH>l+vikR$AEWt%0ThpNbO zhNCp}1W!o|NdQhfsJhinl+VcBa_lPeNPG$6WX)*77p=X=4!&0ys8G91$}LGrB?P(_ z7&VPo90PdF`VbA+5NI;Uep{=U*mZ{GH@4DHOrU7M!i@1OM9~z>_~!9JE7)FpYsTZ7 z4a{iL_)!Sx(;uRV^~i64oF@;XmKy;g5o#k;x%*s}Oy5w9f$#`xy#=!BdH_~85G1yX zi=tD^S$?7vz($0_SAhCsLisAU8jVvyK)Ljiahn|~S|f-umyBLd^>TnuCN(*~9a1r31| zl#BonL5Ndnnpk(hcp(l_hAv%L{R{+O03Vs=l~LAj3*96$TpWzP-jG!zw)GB7;A=2p zY0WA(62SFd45UD>60FZ3__i1wwCaGI%SJeP1UiBDzMFlTbwnVRJK_)zFR-VRCChW{ zx$1{LTC(@VXviA8Yq!#z60k0&W=z9?sT1QjI}q8qMs-h$my&auK_4J-W9AE_B$ki>k25Z4ewkXhR__}In1Gdt7xJ{ zEIf)ZhN<3VCy^0lBI8QiluL`1KM*y5-Hevo1w4Q5cCR7kAe52-YO+ol7aD&HwBN8K zo*fl4BOd`*vE#Mz7Ggh|cO*X2FQT2%6AZIh+a!EeFy)6)At&d-MLZOG-eHrnT#Tv? zk-5m%`!Ku?kJi>E{f_Po!7Cnk1AA%C4lt!#i(IY_CP?;JGV(-XFOx#SWAd($hC*CM zpll8+bztHkrybdF5EdaYesHY3cZ3cz;|ZHGj1J0=s|= zrn7X5ELx^;ikE8GwG%@gh(_+p0$}p2OFt$}#)dMW+!3}`wx$MHO`1%*x1Ig4Q@uiel+A5tP!ppiZJ}noMYD-WW@Tm$4Io#G^X5dA3*XuQw9ZUJ;b^bU zRNfoya7dL_#yT)(N{z@FS0HC_7;Rm=c*z2|QbC4xcDgMHqB195LUiTmdE?WUY${8w>Qc%N+cT>GAtG z%s!-hkwDeDJdT`K}83rJ+M>`dy6_G z*l5&ZS23k}0?x714yg*gyc!M`PV4vA1&*FIzvCWhcAo+sY( zD1*0Yuhmwpe0}uyOg8DR`V8>5>8}Pa!#X#z9$D42dT6b0OaULR4U}YB;hdQVboN-Z z`<#{^REc@YfL9Q7ULc0_1UId9#}`CT{E_z@fVHi}Mz5sHjj|^5udX#Lu(I@;a@iVj zy!TY)|jJBU01=KF+}AgG~C=U}3og#7>(U6{On60s*k@5(LUxV!)nM zDkg}wUD1;iY_orPvu)F-Q|wCj&S4Wd7jL4SAl_~hS#$1UL&VyS%$$H1ofLcT%9FKK z%{A5MLBv~`P`55%^47rBf)u9#YuDb`@^t!y1_K#Rs6mSByO&0xJL;PAn`gHNY;)AK zc$>wla4%bSvGUqFk7XJSrYH2y<+z!KR=y7I?yqs(=A+_uGUC)}8C7)K-mUGCQ;e5h zlgdISAV+_9r*&c0tPyP}AE8UYrV2FM2Kk`{0JFV`*H!O`z=07aJ{t$_peu?~I&m(r zKx%QRx8o0UBML#!?tYsMxHC0WIGE|L3NaeRMXy*eow$DhSN_hT6Gso7*KG?;)3k{> zpd_E^EK9dxaSYW}tr|=Y;8I+0AvqLw>H%{;cg^omwhpI9D*?>NW`*pGZo2S7iE^8& z2EjGz{aOJ!9rU{YPK}Ge!iK?@$>S=xDJdG1z{C9G%= z{^5Q92@Ox<^B%S%z7*8|JNVa|;O9Bsr)b5+fezBIEx*0M{$5eW95N718v-kurahr_ zOO*1Y+Ga~C@_c^&2If<{n^Z*s<7wYl7qoylGUT3hTtNoJinkj2pT#Hp`{T}j;n&c{ zoLIqMSBmnjvNjdKo`4AeD17I8ok3OBW^Rq?)K>uRpBVIl<>h9e0Oa}x2RDI{c~4IB z{`(I!Be24lOsck>;igXo7-5x5F_N`av#=JkgM0m$6kz2 zyxUrIo1MeA(pZk-T30v2nL&g)WS@@yy?R6R#q6gZ&J%CcJXb-*5QxmoSaHjZIrN8P<-hit<{%PS9%O}q!N-_DV8NYtN;ZnDdo$}BT>^1$!N$r z9o&NQ`F`N8joBenfBP z39u`~&ZR5X0hf#n%K_VsMfx1Vh&zyyRhIfTHx_f!(p@hs7CyPH(wa}%3tt3b#a?b8 zI~Hy7r}?lT@!ZwVw!pX)_2}IID8Xd8y2W6*+l)+7XKrDlKoi(J>P83HI2Lch{E}+p zT~93_BZrlV!K$tl?WFqRtcmv6+Tkv8A3jr$F;*`jPhaZ>ZY>yYizCyC?IIvpqZT7@ zWT1l6N78_srmRFDvx64m6R38TGoCut#>J-Lt>P4&-wM^#IYZud*|Brc$jO#fGuC7#ymc1U1|s=AyIPq2BEyMml8=uf zt-GWpg+#N;bc^|hhPzlDu$zLdq4coo>ZlxF-jYh7Tv>^D24uL@okvP0SmHz`{6y7+ zM*6TV{t7t_f-SIB2h_kCRaEcU{uZU$XIwl1li2K(&AQG>3wlQ-sBcWfu_X38GAdX-|F^amBY$>C+!`gda9I0 zX+f4QTl#{yEnC5;^U`D`^$9c&BD3XHu>4~a`e-Xb){Dqt#o#gU;zq$qYgIKIFTbNE zq&56_nz$TG+b1k}=sGz~vAW57&@3FO%>n8`sP;IK)EZMX%kJ6(8pC3-I_R2YcKp(7 z>xMbLiF&&OGBai%XAhd6AhKunlq3SDpPxPJUL~U9sKvprGhTi)QK42zI6Rp@41+;v zE2jHqW-$F4snGL7CAw%=eWw$;eo6w@lLA|EyfR!7%LG_kjDAG)p&(Dy8BJ<&S?RgT z?TfK#N4~W?Xcn(OLT9m+4W-~QG?XGL9A&Nzoae_Q9sXhuQS`{^<_~IABdY19+-fEp z*^2_wxz?y}sgD+<;(_ZT8^rM+-(@Kf4zf7ytka3;=-lF9#)o|7vSU*xI`|D>*xw7})$* zfXYeQu|*a`8Sd4nyc4{w7t32yIOd66#TLEE`dVJ-I;RLj5ri!nu;ZA?w+rF5011h9rP=@|R zk?Pw;!_Gw|@`6WSZ8JipsqC1Oc7^1yaNqrc9iUv^MWeqG=t9b{dE?ExV^Ljx6QI3O zeBw@Qe{|dc!{Z~H?Yj9u6o4H=uxW3s)gg1#CQv!lwca9xDiRB`Rr;(PlEA#Nwe;ai zt{W*ts-*{w!luk!+p^Ee2iFQ}DtYu=l)>S6=cH9*If7?r=8&^4s6;$rNUi8wMjG!L z6pMdfrnt4J*-<%V--*n+Rv$?Z^@g$(v8j`g#M328iF4Pu5c3+tP6ndXC5c0!X6aGC{gd9e#5_j=T zVNQkeXK+e`-j5zmgOAXvN3PK5pLY~bxgT><>Fg`l%xi@bY}>HcWJPY#?*+hT)@&cj zigT^WmDgs}$b8*`o+k)Tj7%>*@L4i-p6nKNSZq0cXz^@I=w-w49=FtwiuRV0Jw*c8 z+5Aa4KJ(!8PrD-hVz9rQ;dP~UgHljoRlxIgnh|X_!Er7C!5xMHK&KlPD1p01xjgAG zY42Wrg_wumtLz*zf}N)8rpetTn}AHF+o@+I+%2ZOJRqK(@ab}PL3jsFByM1;Q?1v+ zLVnGw#V=8h_M>}icMyzZ(|tn!9e96a1JPMI4kW*UXZ;&^eE%u%q{md75D|=kl~3Cd4zfzf=3z${O~c(BpY&(5zJ5%(=8yDra1# zcoC_(u0R2I(I@mN#zN~86~Adk7V5qU*Gsb#tmS*9e%lKWVYdiwhrRBDdV}eX{$4Y^_O`0{+U!}HF zNJpr394sp~Gna}xl?#nVbg1HNN3!|%@fK_yRnwVdhk!^otU5AFx>|J+D;aFiI#ZK# z&8zEas!Wd?h_*{NL;~>b?1#!LE08&82HJjlYKFR@onGH`A{sSF8=ELSO60O(Ce|cq z^3qGuw&r~Cy`YfVakO-Um>hSN+EFLD1n}&*Q;$q7HJpm@M!~om*F(3{gxd2)4PYR0 zbY7}a%(m)2OgZ}M%PDLk|7ub0y#3;|mO71j`fPGh0(daJ|P+_l8)N zGV#wG^2Ja2*h9=252#HRz`0O|V;w&JKD2sG*CRs18$Yn#`!$0;5YY@}RoM+j zyH&u-*R-+&WwQn?7S^wAjbl)Y-t8@HT$tb9Nbg?(?pS3eKgt;B%$ zUB#4C==nnIJPGl%`6!jBm#-oH4RfrBsT3l;fqQN1uCDVg5~A!bN08=^vQ_K}Mytw% zG+gw^W_pyO59GZN+0aJ4UVwiFAjL7QAo%YA9hcuJx#(X8;2$k`Ndw2f-2neL4oj4D z9yLd z_V9%E;wx9QyU{BUL5TGAy)h zq_sl#WqMob7qxnJO2q4NU%NUdQlvi&W*2cY7`n{G&if7+pSk+)i*)IslAPmG#F65t zdx_(MCAllcH})$WurLlxM@4+5vOMc3z=1d@g!mwGRjF;O^{kqz6ph6Jy?lhqrU1#i;A*_ICj*;4JNN zCl9a&?!US}CJ_!mV}vGiAY0pgd_`ca)&g3mO;ZW|2p&w+&GFudP&-l;Dj6}5ta8Bx zh%F>iPLJzVyGTXSbO%J2$1tC~5~L1-NIkuj9?&de6$XBc=3)xSbE z-O}|K_cDd!6=ihmk|FSKzR!vUw@ZFvjjQ7uRAx7-P&nqa*~Z(<_wesb0V=-!Pa_)w z;E!0ZutrCU`a9P5ga0S7{-2MUh^@1u$KSFnWi2^m1%ywyZULPVReoC{2y^=WNFt~q zDG_OgBP2#v0X?{h0KECDA=P7S9SHF)> zUl4t$nZh>zPTcVQT&4v}FTIQm2t46ighor|GHJ5FR|q`DL8;B;jedv58moz^NNSwW z&rQ0W1J9up5udaT&r7<2e9V5=qZXDnbgsJ=tP6-DLn${swUswP+EB&*`}yQ6qtF0h z+&eLiWp-naIp@m{X{H$j?Yb5aAv4)b!xF`Hlqahmjp8KtX(o5Z8JqH_PlH)n@%@=Y z8ZWUE6I+yETlJDelW*f`HhUc3T4Mq?ky{QPZxc7x&IMAE2}u?M3tCllVCIJ4Ln%5F z?TPd8IzI3sH#g^2Bru%HG`q*7bgRp3G4aT!HA-fD3MD~(x9PHu*hjCR6$Y+sTqL@$ zAl%x={9(uv&0@qK+VlGt59}Bpx+~IaXd=3tNqDrES!mO|9GM;#BUB~`gJp?yIT+1~ zA`UspXp5&QzR_%}xzAa+S1(QJ7_?;^f&n+m@}~F=&Fb#T7JLg25O$2n)M%w@A=DLT zb=H9;W+_Kt8MN033XQ^|D^RilPsTLF_|~}(k!$WASrv*hk409%Jo)*|oyXNWmOLxw z_XhpK^#W7hQLyc%tzdY%+cNbGTPfXMPDVw~%Bd-N%n0-d4784*mN-XMqfER5SDO4_ z>(6>;b7)llK&T$+Ba+1wFr#~gN>4A&7Jx7e;grpgcv_g0Yl+uk0cz)h+8w+l_LJb% zH_puef-+a%DtE($8=2M}%ppb|^-aE!POy6Jda*#R`C|XAoG$cBq5AAwZbm9MF)TMb zL!|#mk=I9n=4)U}kkL(@TlynFv!y>g$8kXHJ0trT^Jbw~WxtI=b|F4lTc6wmwc7*m zUbZI4e89sTyYM`C)$pPaW*-xgdV!*v#2qWr`;-GUBUUL1YndemZxPtr?k~Xf`x0pC zvvoe!hld*3;+uML1FSGexkw4Q#H4wg!Xm^__Jq*6%F6HMeE%HW$qs<7FngwEM!EB%pbPF`7q4SwL zb%77@9DwH{$*2X#yJl%m^vr>3bkGuo(R$=>*2Z(JrPZcCbp_^|zm|`naBRO@zf=D{ z%CkT2Gqj|tXTQ!WqyU!&6NL<1+@?un8=jO-!R1@E&CK1H!|Wk98Ig|cGd-M~4A12J zY{DVR=qAgJIGh*_lZ;u#GR-nNq6E%4%-X?C20iYu&AYno@`MSMVExK{MLF(wte@rj zt>13Q2CPLY-~yEAC?ZWU&CJ8Fq4HZZ8WaPq@{RxASjK%BB|Pn<(T{#6RgB!cM#NIG z=v0H?ItKHcm7oe3uCVCOPA9UJF4Me$O$);m-dT-PYUt7l0iy&}R^wB!yQ6XTI(n9g zzQQ@_VyjUDTy%5QbE`d~V6M@-mP!FXplTH=Kao=1SJ)sQ;ahUkZ6vOD zk7yg@4bCCDk_#M%TK$C45|;JK2bw+2^C6k8L_Ci%*n(GKbs2wEJwi}8M$j$xvmbeI za6NapuX0A&Qwc(PBQX!N><-ipeq3{UAK-sKdw-PFh=VyXpnw1XTEE{MfBEeFEu;8{ zFfS7?B|E@?B2v526ySU6)(^K1i6)Ins7aDv90U>nO@NHGypp8Gx=c|63mC1h&_4|Y zBp2uPtgF(>&%37^m}6*GY-hy309BX1RPOnQ4TB#H#wx7PyQ0~0#3WBRNm_Gl-oWn2 zJSb5L%)p#`3!2sseS6zrDYRILz^u)|@+2n+T1yi+YG#Fq<)BX;wZe@B& zI`aO6oiEtQ97%V^qBha*PRL`_De-fi40Dn;M=VaJZi;O%X6u96*1}DR-18Qa-O#qt zO{r1cb~InTW3wOByneb$?caE?QQy!)jgBh0D^xHbBX`ut^L2_jzYg@9{=C7Hg#xk<)ain@{BQV#{h&x z{#u$xRaAqzr>&I1t3@>I+GHbuD{PZI`9-nt3#}q`Jc0 zWwh3srFGTn7T$_xE34LOAM;D0XTKgVGspYcN5Ee1=gn)bo!6dwz8S8#-sfFLqRg3% zU(TdHJ8~Om7Wm)s-A}`O9X06r68A7Mb5r&>;XhV|X5K0Da-Zg*?|wzV@TKgD@V%aq z8hB}hstI4ra6eR}>E0{VH{UtYcV89gjn03KzGDl1%*&ZPP(Qyv@$q#_^tvX!rM-t% zebmDA-p<=~KX4K5B))%aOZmlb`Jr(7-OX?KdWL;ol)0VJGkvIGejbrGcg!D#KN@ey1uSWdGrtVADh8@g^ZE^^u@e0nKe!)7!bxJ8MoA4)3^J?#(Na|`pq0hTG%IIg13RN=xp1^E2fq;^$$+vP_j+c8-#_PF0G}E%iQMPN*C3<-TfG_U>-%R1L=(@l<2*xd zyTz^wOIpq&P(7Qxbhsh?^70RBnOfE*JBVB0gJWo^iTz9E8J&d(V9Vu644uZPw7~=t zG;E>=9}d~P+V>W8oPsu;8lYwq(CjN0cAr_%*;}ZfPssM`P~8}hv^OaXX18J(so16( z1F;fs){UNAom+oWHYxxCCMG+t)dGX4#ULG@OHR1DQRK${XeBFOpcz^}sK*PhvanJ~ zn~0(e12-58C1|Ao!J=TJAP##i-_R^hV?r|Jn#BWuVJ`}q$_NR>E`Giz&bQFS7!}i2 zkN^@@Dr?zbnh|L=Jg)Fkyhupc*3Ahu**x&0o*RiZHI{fcslA#WN$4V68i45zhNj|I z2NWgh?J}kuxlrhk#x39+uNa8=gGq-*C@_|eP+ow{h_Pl&O;HY(j$9{8hd?O(EP941 z4D}LL3>J@P6X9CY)c|Qj{WOaU&3MB1$ksq;qb$SQ>U#eayHpSs-lUmCgN$Lbdrrra z5tcU^AK4=MIa`lzM1h34_T~YHaS*9Ie-(F@4%G*U)ue7us(dkl&{oh67+`Qy>iKy& zL`kem^ikK@C9EyzNbI(`0U0cIr=nrnF6{#+4^ZtbNd^tpj0)hrwgjlbeNzDDf^Gjf ze2I*{VL%aT0DjDG@W&8k$O_3w3lJ3VhAE#RSF@-0P0-W4wRm4AUTr!DDP7|OxLCOR z_pER5So5cJ9mE3-1VW2ezXwG5#KlkNT$;nUSak=` zJ>9E^f4&gK#4ZqH)uM01GHKHckTPjg4VW-#(+!|voEj{%7Q@Mt>x;ncrGPn*!a+w7 zhE1s_ZIVf5IZW6BkhoR^0(pX6=oT{}Z4`s_*tmR)}TM(aGZVPjvVXd}>Y9dK;aNm@G3yTSf@eLLfb0bDls%e5&%IO^-zZe-`@(DX2q@4%B0m*_wSizv4S0U?0YJNzwcKP zWeDA8R1y<~E;dT#qAoxrW(6ng>&6lTnT^@k%L3VXAA$xy^$#n;dS+yyz~pQ6;HYs3 zWQR7Fh*1*EnaWDoKe4cO)I6Z=Qn}(K0Vfn;^L_ITJd2J?IT5|$`7qMWhlDA`V^(On zdjRQx_xCz?U-Qb|tZhI_GzUFj3ZwCwaxbMrS&B9R2`d|6SP>=xFS-{X*4W)$1KYVu zdb4^>tE-L{E}HN5P|UEY$z-FX=N%n;7>{4HkZ5V}vK7>vU&yI&akdebrorW6_PRh> z$c7hERrFgXLLY~=EW}hRX;lb>renjam?uSvSwSg0FRVl;>5~6(70ep1>Q?1h5IA?I zFJ$DTnKlqLqTtNdLrVrXQ?sa2He2>QVPInu*tOd{f8NHgv$}4LcmkzBpk5&g+$}}Y zLTOU3Wz%(F`6im|-c`f)wqJT{kc3#dV$)2sve-$Pf~FMI0@e5G**0eB>#cG79j<6F z9Js|N9e6y{bZaqesNHgrJ%}Uz2p6=Rv15$Rq{AhnHZugDxn&UE-yNlT1!$}ecC5HZ zW?jT$WAF~nNc}^j2UE}B0p3mF;5(?#Ij^DjdiNR#^EM*WqxrH})wbMz*P{{SUCF#o z`Nh_7gvU+x!&j?=Re5Gj@#RZPFVxO2&Uv_9DL%1pl#gAiJkTXE3UVxpyC2}qPjN3o zawVrTm1YIbs^<~0VpBW%GmTAr7`=h5u8s;dzakN;CrTc5D@eA#D_0{VEUVcvTx`JQg4Y3GC4l_R(DUit`4l2a* z>RxB)4;7RG%wnRR0a|Pzy(bwX|2-%2dyu3Bu1bOgxkBbLz?%yIFJxOQ&}k(=D+O*- z@+eg|apeP?mPG-`zIMqcuhvK7EuB@aezjG2q-fC_=y(tYXa1n!1m12v{AfZhLJ@?O zYQI6}E^u;Z92ri@{$mKK5X<9B-Dbr2H?R6HvP>B2aOufwhWgZwBJb{z< zJZE+vXfAx0^f&osq%i%}4SyBLZM%^g9PtRMqLXiRlL>I^!wm@Pk*H6LKnNRUb{Izs zHc#5CzNViwU<5t=N^!H<0-4w}qu9kBKh_B|{o+->r+^+*O)5}Bi`CM66Bnsz3>0Zv z)nOEVgt#R9=EGu2ZjShY&hkdLjbC%bDWBTZyn}m;X0=T**eTlFgr&~FnZMl>F(thC{_N9 z%!$olJ2^+lA)k37)a0}-rppYyHQ`vKPL|^BLO&?SN3PY?OU!7 zLu*W12h5uWZHgdIis-t*%oWr-B!EG3s@HY%H?R@@m=V1HgnPTY*QAvT~zBFlwA0x<}% zN;3eHabS|ALn2QGLR#tva-!_DC+~VVlg^a=bO*dV4q+G|>Igz#AmoKL{a%Lb{Y}~d zjAueB8MBxIsJ{v`w{eOfIpus)Jk~H?8{-ht1mQUx$jh$OeSmS(@?^^h%DS|L*Hli| zctxa%iPnAba!o8M$Hk#rMcBk6o()CUx_cSYC!$DIlO_#_CMxr+2iN5u5XJs+y@lK< zVgiM0LuHA%qKQsGN?=nO&$eK!D=@M>hU$eobEwka4*b!coYVt$)01{<5Pc3%SFZIQ z>_5w8+vN90xP%<;R=(CzrgVaH5F zlI?-ATDwx~?W$8{_p(Xtt0ncUd+=ah2y7;7kb~ouMUA1_5iUReMDDubO8?ly=TiSs z`}7d_jvr5W_r0i!bZkP@f$|_^UtI=JcCn?b60BVT=%(CMc$Z374&8nw#UK~Ou-bxZ zPpIpj2e4o2)6GdkO*5v=3445vPKD6~$C~Z~T^Opl*If67>Z3C~((4uC2iQa{i>uxX z(s3}gg_q)TcR!}wHv>5g%YBNJ>NGm*@DA`~DPyDsC? zQ!9BIaPqxv-D=UA- ztNorgB)3s}g;1kJ^g9Lz98tKt6H@Mj2TnX#GaZvco{hv)g-SD)(FViwsCwz7l$*sOJf7g|Y!bOfx@K!*w zic5Sc{oeGLP0I;+QA$zw@Tq*9%R-=}u%GKEPkY&Gqz{)Ax0h`}zoMIM0jKzx%gQT4 zoE_9mDyav!g=6`~IwoFmwbY&D{p>s4Ed>WR6x@tB$2tJS?ScORWct3B@|fKG*e{f+ zlQIj+F9?Nq818$G^}ZQG%RG^Kcf6r}P{~`lQ%&E5nv=9sQD02Z15{8Wc9dR#>I~sp zc-(s!Z=nmpZW(|+yFD(!$tHT}yB?a+_XdLNBD>1b=RKoa3?Fa;J!p^R?Vo^MhX6AW zyK=KeEyTiv0>;Wqf|myHgUoL6Z$U02+G^1U(RTU5pNV8QwY%YVKmmGOJ;#*|Zq5AvO`87oS&;u>SA>2)Wb15T>+JMj zT?&?bJa%4rzM3(eM7WRgZhI$b>=n__9RHw5_KrBSu1?PxcHM% z5h}Ox@r6T3#aHaoJ$3Ebot-lDjx4?}-(Mt!B94j5(uxwZ=4(_ET;EYzK&Cjn_8iQw z!eVe2uA9zda!>`3T^r}Ff@7vl+x$>4n*Pac>A2n=;`XChu#TDOivsrqFmZjoC9lFj;p&hcz)GYwXH9y8#de>m4 z=V7R{sHK`dONnea?Wf%8CcMut&^UKgcWUf_g&TTc^JYy8Z(kzLd1%9B#zs%;av5rG z<1nS713UQE+JTk!ptZ5J+}2IEm4B`=Pw5U;y@%uk2S;^tR0g!m9;ey-U419+Ci!B( zQ>i!msmoI>Fg2?hmzf*Jsxv{u3J)h=%Ll)u&~*bwt9k3qVNo!+;JEzO9VjU6%y%uy z5?6ae5G+q*OMN~DrUl84DMvQ$`vPV^yvza(X$QH7Xg3vBK++@__c%9LUde3_`L0Cf zITxrL^Gx4K`pf`&I(>gyI{iT7q*{KZb+^@x%Q5zi%rPg&ls9zGls9@Zp#II)>+hN`addD!3Ze1hN%mDdXAC$CMqDK7q5`txn6M7@5yYa5U52n-yM#(-=}#z?>F@LVgR~ALRh4;W%s4A zAhTr;Xmpb}+=nH)atFKo9o8N<%{BO`QDt$)~IhLJyPL5rBFN0|-w}>6P&Nfu- zwxD!U_<$e3|AYgfWBIVJGz3lEa-nM3xqjc~eC+ z%%~_6Ajecl7;pOCeG-Fg`Lw^M05rBQX;f4^jL9>y5!qp_{@5zC(SB7?9m`whe$~@# zWD+l^sjoYfl6z#MvfTB<72(C;(AgGL)?B3KTIYSz6$q6?VKP6sf&bAjoQUCdKU?ea zJr?%^SQ8hHsEj_oVUel@-#*8&{`ESyWY~{CX8s$L_?_f;v4e>r0{dWv5Z&2{JLGVD z43hW)R>K=qoRTRV6n&tPQyFQ)^L&lu2(kzsnmFSd+Sp&wgE{20zA{VAnYwr%hPsI+ zwB*fqr(&m#Uh0dMV7{cOLauu_QYYR6z4ioHbdC8;->PxQCHF$0DF~rn@7YxC z0`cnmVqf?7lRnf1%h_YXV_X|@sv2Zu(%4TsOtURcXQ#)2`h;V435%50#iS(=hgk%3 zTcLfkf%jOJIA;q>nsMeDfTVPVyH6Hhv1D?Y8=cUHH`V3!Bs`EP^eiK5yyKcYdZ@}~ zEG6uHdCOXkX0-72om)*g__)n;^5Upnl9oX|PN}M@T9!U?EeUT-ZO~{O^7i}1QpU%d zY#9O_Fd^kF9$8u3I_$D6@dzht5JYXakGnba9$mYKhxGy>6WJ8XrhrZN4I=$IAA7<% zsE}PD)HURtP2QUb}L7-YfSRQN|j@>ubvB*WM}4^(Oty*{C-$GP1z!#`vS8+UWSC9jGt8+$U)$inMN=kC{zT9 z$o4S7Ljo@&Mnip3)27ngs#--8y2X4;5w%)V;ycCqaz(S|GiX}Jl8%wz_Rr|^I^NpF?CAfXtKK#D$1-w4!m5Bp>R9^iHXOv!DTiy`8 z26x}S02+M#3u;uD#;?pFVqWg^5xYQ$14dt8Zt;CcG`YJ2C2g;$bAj&k$n$e z?!IPpZiLyT;HFaCFcVR~Rc?t&2aJf98vaV2WvgRJ zgxZ9hJCrz#21&Up9u^VV0JBM2##u?+n!0R{PPniw;2mpAxG3SpWXy#E`|cs?Writ1 z%pRtRyJBr|Tfau+_9&m04G1mvMnnYI;LL=H!DdY3#fzQNN5{nPZgU6ILrZ9i(GE2wy$C zT2Z2xoo2}&%OswV)TltGlQf5WZ{=jqy3?%JF*ZJ%P|oKE?>iw_o=6<)V4sk-z~}B; zc2_n%&cwpzYt1y02Zys^>FeZ9C%!dfZ=sE2YdD~FvGd-M#tJ^+Y_Szpn_N9v*~Qr? zgvrgfHB5wP0gb)8Lqe9C4Y%3TCHz>>AD*SxZ)!7|%nX}0`Fw_(W$Z_nf4;2PuD!)R=Rt%khCB;r%BTc;pn+B1 z$dfyQ%dpybW>VM~**LH3(RgO%inbc+!nR72!C^CX=xuPjdicn;Z(Z;3@~-_zQ>3(rz)g1uCzxlDhiiC= z-&EV~XGqs8ai)!}^TgXR%R{X#$<9&dJr+QTW2`8*-;Q!IrQAIC)EeXusWZpyS(ET- zqA~1omh`D&P)`1R-XtKNc4@IeDzBKU<%L$7J%Lq#dD-a75OBBnJL5x9aWtZY6Yv-xl5nA|f_PMZrTQ14eP>>@> z&UVN{g)_3$tLaH%dF6r&zHsGXB^Msim@?5lhaK^dJ^d&`!QrmWHIc?Hlhvxc8#+~@ zKZKJ(42Y8mZ(yjL9JqO7_U^V^`|g$t&5a29A6K52L!0d|tZhZ?cj=^2bB-_9oG@w^ zq`aZEI}WBH_70r612%yKdKVD>d$OGp$pCxxgMkO|J zm89n{2K@s)`l;RM=q{ zPPO5338LXeB{AnCH+F*4WZ^qUz0(J*8G7UbEd(-sRX7$C8a+R4h9Y2v%OG}JGVOKY z_|fx|y^;97C}1V+v&S(Pe4zuudnPqfXjKOj;M~Qqge@|Of1S9;aaM|{8`vT^1Yea{>uxYFK7pEOul+NyB9|^(4 z-=r)%kLpUqC$1X~eJ=a_2AE{Uy?}frv*;`B+#Z(&|PwN=L6+-a=kgQ{?=6C8M-vkan{2te}@rTM0Wkn{+$3 zfhxUWI~`@oBMMJhz4ULBo&^?n>!L0Vb&m+ok0#A0B@N%Xji{!845>8b{v$?Y5eReGEY3tS&LutGNy&J>Nt%vs(M^8b^DEIb?TTz%Gd{6iC(#P_ z9z}!@!n;$ov(ctu4DVBOGAL{?`X9Ta-SLhvK4i{o`Krx+_mt-i%)x!$z-i6D|7ahc z5IUg^IdIwaPI7hM-NMfCaFG8%)vFoyslL#?7`Ve)on~BOov&B1=3Wbw``2$TRJhrOtaXmSN@qE2+s$$@?zn-Y{?{JJYsG9Onw75F+TA`Ur2rQ(8TsH;@-sZ zdh+Gi@2@uIAne!ltqqarZ9LjMc&w97!*0^#eG!B-1|8FubtfRzL#)PiLyax#LVUhE zRgClFFmG7XTFrrJD1fsytU4y2R{N)@7wI~Ql@lb%7YhTcKwY7P~50 zywkJLk?$m|#B_rO)R_TT?9$ztnd}!}TlEsUhL~7RdtnnJ?Y|{G6zeX>4x=e0Uo98w zknHOBLzbQ)CJmL%x-M}E&VAd)gK^U!*^dv(=cNq?gL&PwjI6pG_Ymr|_g#DSh9C48 z>fbD^SL0?G5^|rJ8h7aj`3#$!nslJY+5MCDw8mKZ`@e>=CAAqM-u98)d*hH5ngx{7 z2%7}7)6yp&>~wdjCxsN~J?~+!4ts5ii_B=Fe4CAq9lrN1hU0+GtUYzg4U^Bbs~tjP zK2^}z6}v_FV_f!bTf^AlV#Tw-nTKM>_UBT8h>9WHg;CPI)*(x}0Pm^;G$wj~n!UrT zuYz0vOXFy&$wp4zpr zORG-nh|AH}ySO{iw`Cz$&a&*2rudB`X!ovh_zS)YJ80TP7EwcEj3R(qX7v3!InxOd z+)bblEAfC)<%@5nr&G&4l=pTwK5>C^Xdr`g$@jCrvU3kIeOgvoXjX+c$jae^(UL~T zUp4C20^KE5DLrl#d*+Qik+`g39Ztm)$6*Z45Gl?WTRS4g3#w_Yc8pAcwTC%_PYkc5 zpXe;G9~E(mefl;Xr+fcf?9ZCQH&W`@yf<)bavL)-(?|h%R2qj2<#hzkW_AWMtk|EMmbkwzhd<8Wy%lmK^HYRf+|R z4Q{5(Gg?;L8@2+7Yn?C+*Yvd4Hoa%PoSmFVgo9RxoM#1J{r3cK$6g0VUi*EB1}Lf! z_px%|Ovsf!a4*s38TVs-g1V#L+E2%Z#EJ*1^)XZ*oV{& zRE^w2y_*9y7?yXc5Z=Q0+YQ=!xCEUZ!Wa6~82`Q*34&lDDi3?h2m6vAcZPdO`;q^C_XzTZ?;JBU zH@V5&^JWRcewAHGk9`*e_C>Ov0QO}(kPp#A zjqt^={vq`A1`~@0>jLBQXMBWz{F*!=y~ly~z32EWMl!j`qgq}1 zLr;qG9S5ZvZf~XtH|n-8TlTJGhI+nSyVeMwnWCewrg~McVCwXEGkL8wn`Wbjy1svR zo|T%kfTreD!6*r1%A7Uo14jN?UCqCYXe{(yEm#>9n~TA$aN{L@CYKRnESzR=BgM&# zBab5VqJ6k+tSZCau&J1RD?{^ZQin{!b^ zGWKn8uU3+b?~}|4lDSdCOsv8ynbQyHJ^adN3*KyLyPElEVcWj}+;KiOc(V(J^!$S)zXoYMR5waD{;!*7V%+bvHk#W)< zO3jL!1xK;EnkyX`23IqA&D^rSxKGD4xe!w`>KC`n?=711oNOu+ESpqmW#Wq%05U*T zC`P&RO~+~i(f3HrSUjIY#{^4VE^{K;RM+j2&rEN7wzS{FC;!BEfU@i-NmttV!=F?3 z!8-M(_?~dv_Us;rjKQr%isA-F=)tY`|#23$ovr*vlFu)judb{aAvoc^d0y%>uXk>TF96;i-6J}x&i z&hOk3Rn}A+ZTMR$Ib5&N?pRnr5$w>}@_?=MIfW-@* z5`KKXW<*BSx}K9*%RZ^%ur-|RGE?RkTaL6zPCRK-G1=>?&ATBFzEmO+Xl6-{sscGg zWHaK+jZ57;3@m5nxHTIvO;oFZNW0`83d?s1Z#`1UHce9M5DJ(qiUS^?D_~YI9ijsY zpv@4|SS%5s@dvDNCyOL?iIxVn2T=zaY>o5;@)T

rLKlIgU%f4UTrlTt*{`K)C92 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

BB*U`*Mu(Y4U9*zJ7lSmKJDte%csUwR(Tk zL9%zU@C)=nvT08XzBcE62!jBg_G{6c?xab=W&!|3ZCW87MpBs5(djqq*ZCkK@B5p- z(Ge|anN`rHr*a-|SYy2kzI;vwTG7ljFU-h?JD&d06wIOTxXGLf6Bx2DTnW}!g=rR{ zLi^Y3AxoaYYICPJr81eQ2p)o1vTwITTZ;eAmumq+Ml0#=KTVB5WA|nQOXkFT)d2-F z6i?q|Lapj~;B}-LqWW{l8VaM_<9lb1VA&-^TBJ4l8GiXQqHn;O)p>I0xv|OFF#M)u z&VrlYp6wgF-7%8f&J%5@0mxWBOLZS~y7Fo$qbb%`jlrCtj-3z36D_bAYk#W3ho6FFE<+JaYa#W`aZNRcPJ(21ybO4v35}TF(nv3uxP=4 zhj|y^M|bE7dt|Gd#@bDQg(FQ1N3yo{g!f>ZV;GW|bp9jmY2%!AGiN-V5TCx_9J48^ zB)lkhRs**rwLXkqup7%8m(I#A9O$&5<5WSj(pnjlsi62;Ky-a05V&(P^}VAhOI+p{ z=+tHeAloX|l(Ed{@s+6}D|(5}c|$E`0gXd)qjl)wMzfhH*@v+sx_#m%imfs=CQE$lYxy2SQJ=|;+r+X*j{bq@6WKfLBuYBK(&+GX|)%VuN%nY5h7v zG9g~jIj>ugdMnKP-6WoLp_}dxaWF#DA_m7UOs6-Eh3^&Z`ru|+-)8AE)53utK~viH z(CJD;W(3+1;X(EGoU72C!D__l3mh6*Sz^fU9O0X+>E<$@$Tx~|QE#$EjbHOK(B&om zAV}3W&C;MRD_GAC$w_=uh>nKL30z?x@~A_NB2bup#BN@QYlPq{1KPyCe6#NQv{9G& z38Qz05x4vBHhcL#P$6!Z9XoOk2z>o;d^OP(+ffv`_MfcIOe*v_BIL&Ma?Hi(6VSq2)&o zg~v2U;=V5}7&BEgf?ZCOB7s*;rY=JyTM+5nMFOk&!jJI`@V{T06%mhW*47@NI zgHth}s1{>P^Ebho)TgMj9}9gjq7rGxc&c?&i(zJYpBBBJ`x3tI8OXwN0Oo~)@qCy? zrH`owh&_|NRdAb|W_uU>M+6}j`7}35Dn`trbs6)1rb~T6Skw|OGj?6Ag&@udz`ris z+DsKstPD3AW$T|}9*#i|zawPty zI`SuPwOwxQv1F@hfXcsfzg1+&AxRZyOe+>WC4aUe`pQM+q<2_h06sUF*B|giv0U#^ zX^gVkuM(ajqS-yW=6Dpas^uRWH~Ujw1P_FlWO-XtIiX&lVI_J4)%h7nj+>;`E?nnghT3eT_9 zUM=6cGF@?P(XDCjXzsYG-g0f(SoX<&e!nwilKH@*;CJtN_TK(>>YQQh{7kXS24_gi zz9*E^LMMwGcx-zV7n8HlnQtw+l{iQulm4B6y zjE|-iR|%g8h^2WcV%P8#E=(bxQm_b?WY$SXnn(4rDD-Bd-IgYwj$A{71^iSJARD4);^Ams#ofFcAp%T|Qx$p)46pod zR*0T9Uhxk-?NeTGxld^kDN!OdsBTo{Q3R-!scjkTMc|a_Jk9ewH2%_p6jo(?)6#q; zlD$=tCi#@7MfJn1YQ1X{LX>k<4BKpzBL#^Qc9Eix`kifTvEuIm@r+VQ&#C;e*pPm_ zb(v93HRU=-!>#ajxQb-88d3$;8P(zZFcXS&9o+CnEE+lv$o4J=!y&0OkUsUER@zIs-$a&=mpz1|gYJnJm z@q}bok-=K2Yd_qx1jV|F+Dv=|+if~I-g>hNEqA&WJM!_v-n6LLVrU4_#QJ_!T_7WW zrithE+MYQFXNrP`2Bq!UAQ=n#2zqG6eWr!n@ww$P|whm z`t(SXs>e%A5dND=k>|*ULM=L)L)j&)Z9_w%`%bHh7w~%>)!^qb3|dBcGcA{7nmFkO z4-ZwA&MvjI&<0VT`V1vv+1odYIz=&Y=BU#=tum@qQK}u|x}VL)*=apKV?l^Q~FBOnXLjY0C9q`O^)|cA<@| zzbU`Ms$x}-j|XhxNVvQ4_&5mFv=$f88e3f30;uPop5|mr+BP#4jE$cYL(lUsg%W_& zdReHEVFqqRn35VB2$#qC$mnew2b+JFQ8T}}mtk2ZlFQZ`KrYZ7@)!m}6|J=P?VlM+ z1+E4Wc0nFsm1q0b0AVCO1ifI0O4y~u?5^lK9(g~G6B`9Y5(;aah68&$BIZ=0eq)Ez zK#r`94ewu}lgbBh&OCL`IY*9H4p~ezEz^m5Qzj%xM7%fgZUi`4 zKvTQZigZty8-Sbcf-LFLGxvpG-1{) zR|+O}ipRlPX$m3=Ydjo<{&D8Ssf)_+BC~WobRCMH64PMy6=1%Cx7q zglwN^9!SC|nvKPpX(5@C8sGVIU17cw92ClfS`?t8B z_VIAvYZIIrB4(2}pHrhhTh&Kqj*daxB}T+wG)ib+dWDg)j26%HE}X-ag+`z<7jL_9 zJbvSHW%o63`TEsdxXT64Ox%cK`GSbMWcF!;(p|nJ%iBjL4LurU$Z1<(^9MYLGxX5n zSg`DK*_60uRbzm%@21MJL$~QOakhtfH3~!W2h}({^z0tSFqFSPol6Xw@0(C;FOt30 z>%!zY`#jd~(}nXWTPI5m!R47duq4xLo1==qn#YeNW58Tzap?()W7wUnumq0x__r*c z0op}Nbe*Y3s$skpKg`=1)dmmpT%nG+u8MiBft@o#Y*)_UKLks-&*-wQi@UhCgx?{D zwnmbN&o_RjS4^guN640Zc4GDP*+B((xozr3NP$tW=a1P(#MN_DQ{lx7MTi1h|MX#h zr)OiXG?Jr=Q0>;$oBY@0P89K_*Nh(QBT({w>RUI1f3fP9#l=f7Ajc;A2JNF-0&zx| zgy>L?W6KhTD!q1*7r=#^AL8Oo1^5u|EIF|0ELb3Z5hxKqW6Z)!**5fyMCr`d6D=Vh z6hhc74ar_SqkKz`-ibJj4u#^UW!oUc=1V+zfUQC5iTl$Bk@@4T?FOmbovG%P-q!N9l>d|yl>PpzrW zwCobaoykDh+E!{2zwsa;CBw>`nq(N}BHSkM37oG4O~)q0Q+jN?@Sa#ySU3Vt*8;`N zJa`5h$F1DyTH&9%#9t~-rhsJ}vSUCR^A$fy9dCE|ROyU~q>fG#Vj{ySBLro}aw0s& zP-00t_PADOI?m0MZSX`*gfwQXL@-Xu?&wKmgZvy=5H}3JI$AOXSS68t6Fw%dE7Fd za)O^Y`KR#7{fb}GP(FiI^>*EG>Yy~f6V{pHWMupAWUj&f23i3P5)T5b(RdaZ%pNCz zx;IMuw>-fGX6G-iU>XbWc@yaZ2suKtEr&xq;U0ln6c73`E4*D-F2`1zzc3NI!nkk7 zoZ+>=!U{1)m4h0ULO>OY!K|slO{pPbG=KeSZpw&I5WB-6mi}0(P>MHHhPa2@(xDpyvaPuQ zNpaXt6M)MYWm4M*XA1&X`$kvu@?WCc#K`bo+az~D3`u?dow#eLRv0YqzFYH`YY03s&Q}DZ0bRVbyqnjG+<}?6P zHJ!g0#TcRQ5A=bC`hhgJB9Ss_R_g38Gs>L-ZV(8~qK~7VqPwisFzIEMOj$a_Mhdrr&k^wE}MkTy`;g6t_V-@OAgVhh}06b21}4%vnP z3wG%95DP&L0JQ(832v}a#LWP-BgUEFd&rFM0&SEI?2t60j7%D;uQ#@{^Gf*b;21Y# z*P;HC%N8)u_CV0-;bGY*zFnG;rS=@u20fg^kjw%)8s}&++s!fxFm?P6uL_oW6zcmr zS9RZv88|pK;2!~`r??6KD*o3=EX#T*9T&QjJX*m4K+3cUW6lYiob0g{|1u4sC7Y*& zlgUf8Q$C+GC(M2rC}5%(4m(Jr9ZV?3gzgpX(?f08h@XSXY&6d@UTc5V9?8qi%o(DA zNA6pnUvR=*$O@V^lsD3{$a9ivoA}2Sum+*&?YokZIwe>L0v5^pGZe;|nbF3@=r(0b z?&AGbEfQ|4Q1BufP)v|fYy>Jh;NFg^Yypmb;|`T%OgW`waKaRc^pV~jrab8kf4s}u zIn8pns+k2?g^y-nz5#ze)LmYaS=y7`CYQ}PrZ{^{XN0TXP zTjnjFuQZUZ#OaOW%|FV}QiF)F(W#+Ny5!yK0z6Yrs)6Wj}poy|a2~XJ0$g z@yB$gp^^*kkC}tfw72%{C);)%$C?f2MVeqy=cYidw41Tawxe<*9kXE3WbSEw33`ZA zB`{W`Gs;~VmM^q1tc{^;vjMoM@}y01lq=b`sctx++nAWk_%(6;9#NO3_w$?tti}K^9y0n z#Pzm?`lgBPMGM9|^}}gKHtdI;K;OFKj}R_R3byMVdn_`y*voKgMqH?XP`q?JQ)|3X z!5%Qd=MJ#8wh(T!UHTj&xEW6?8$O<7tCKs!JjBc1RVklkGKuDyF$HFdcIg{$G1g!H z1pb-a1@ZYYZPFOtec3#5?J`|v09j-FHm?is3n#Yg^ z#0iGbf`r5i{vrKw5r=8}pmciu<@Czv^h)UTiWGj9fT#1dxX(0l>{vK;B=I5RAbFQj z09KaXQ(wV9;jJorL&MVt->N@+USRR@8D6khqbyU@Bf32F!Dk)!IZMX9#PmobZDch+ zb>v2wKVC2Th*Tm)=Es>_1!tf=0T7>Fv+71=<&h$PJV8|gu~y1imF#7KiQuW@O3El1 zvYW~h>N6Ypm$Q)sC^$+Usr3$KOlk_@&_q+s=+{+qP}(U_H_qSYYA}giQ%f_i+h`zZ)+~-2H%4WQx z`FHF$2fe5X@kQE+P7@iLsWUz0!K_2A*WgcwDXT86POT4c)f$*xUS1B|87NJjn|tFT zojB12a2uc>rh9rCS}&nuInw%VlBOP;pvp*{G~WoxOMuTK#k zYMSsFeZ#(6P&l?Lb)S?ibVjeRM(ZiJA#P+DfwtKKcMsvoV7&q@9X3K|f%?n#oqGCi z$kHTP>%TH%`;I*Vl4>QJjdGU_*R?~zZXz_5XN+o8eVf{LNWQL)SEu}Z*C7g z-csL;1w5muQ`T!k6w5e+_&*q-mT|@?e>ah?A(O4-jT-)-lv;^1X#c`;ZZ_vo_d}Cz zI#np+jq|z|tzPblt!gTgI*O95-;nx*`40LvEr36~I*H>cs~3L7`-;O&1SZY?`xWs^ zj%IJ;eRj*)5HiilZ$CF{`rMhD9-{ySl1^Fwu_thup3>GW?Xoey!Zjuw+0Ju91h_mN z+2Q;9-vR^vi;QkX&4l-3IyL_zQqlWQ7qtHZ`s7_*99&(LU7Sn}ZGYlDEPn!1{w>-= z!QRHw_+Nfh%}ToVNP;N5z%(>%3uu2smbIEy^EYB<*~ErO842ekO7Q8;*5nK_O;fMv zmfx+t?}ov9S!G%7!C!yUeb5TYR>%+ern*mOww!0Sa_o2c{XiX{u{pE*k7*Ly68kG7 znsG{2S$gaWi;dSsL`R=t>==rxVsb9@vJCeV5`X&%`ac^JU4_NY0k`eWhd@+gakN#kU9ki+N&TMHv z_dRMHnEP~e+M9@qbtqTF3GPRA@{p~H4dfeYZ_QkR4=Y&QpwV07Y z$O*B8eVB+-3tpJ^0zxx$aeZI4)!r7~7lU#CUMA+9Bk7hW2q|O}(p3Bvekg+j{bRYC zBw^8OkWQ{bo}8avmF=(kvxc~jRRDr+Iyt9_R+qr6O<>(INU(Z5TpX(8bal(sI4?7T zL?_F3i>_#XK#XYRKVRsu=!&zfz7K$miHOq3W#QIJ?rEl%xItASXW%2iJ3Tpd0f9wyMUqgc;U>acy9*Mic6yVphw^M?I{1z{xD;((Dt83(o%b2%vX5k@p{%=Twu z8$5&tIAZH|6zy;i*U2?`h9}81L=73o$y6a7EohK{w;@T9w5Xhtwo>c7$<*vEtG?NWt#ZvuDsSb=<|#Qh z0`6j^E%%&NmHKy@0-AT6F5hL6VN2@KgrncM=~gw~Y^?b0%dDVtp&f$W>_=DI; zVm)AKw5taFKw?6_BVtQ54GtnF=3;t+W1uLwTqFnSAtn#?0Vn3{VN*D|Nmn>Cliq+O zW|o86&?J*ye-)FSv16?3%%lgd{g?-`{kRAA?U+Z}>5lO|AKln10RF@)1pZ|Duqa|) z-LkaJGm`dSl@T|c)O$=m^txv`W+?&PjP`DHml7VjW7^ zWu#amLo4RtCgeK0g%1C%u2JgRu`s>Oma81Aeg}&-_wTv8a{uRCON|P-{3?6nw6=yR zz+njuH?64ADVQ?zyj4g?*a}lQstgNC&%W`2_+S1f6 zO-xrk;bqXd)T7<6RU8s(+g5u1)#j619o&Q$Xy@xnESBJy)K%z6=9{?3-+0qw45&&A zEoLX4=g}T^Eq9xj@Mv$l9sk-ZG zZQedxC^4~{NNS2atg)>6ER#fd>PX$OD|5^dvGnh&kK01_WdP0WdwPj4iuUZ@Pr$`3 zc?3<(-w?a4OOJ#?PLLlY?DLV}icw*6Qr*X(woL`N4%*RD?hM<~Iigc2=XVpSE%OOO_Jj^|4(%cv{b&j4OWOnlD4$Tx-H>G)8 zh%zU^$zsiN*vOs z)9wBW??r}CE@medu^@+hHU!C7RD$`PVst0Y2sZtSr+p7GOchCeR>mgT_mPb}Z`MQ}(t{+69q5|qsK(v6C@q|7m zRFe_FgNA|DgdHq_p=6$(N)GQGOmU>mvXk-7haQ|6>fPJ1I3UK_#+s!K3EvA`FuUP> z+;*OQn>pO^eEIu~4UmHYO&rYzi?zW@GN%X$EQy+fC3L1VUo-C%7paHpL-meH6^OcN zFU8~{->x^p;9S}~06VFx?To8G#Toav$IxpfvU`Si*Tdj6`j^{HOU^On2A>JH8^gfd zs@BNY8c$H7TN;P(bMp0F#>WQH%S~pKrjS*s&g9fgRxa(1bUx7;lfPh|1I|rJW9hB4 zkXPJIPel}vLP+d+!g&m_7()wiGWN(l&67gHNxUu zc8=o|0XdNZnkKPsbrNRV&K%MD$z$k$dRj3P0ke2VOhUGG2BsL7N>1g30&BfVP>ii4Lyr1&4!+V_$ zvkTrjAFEUq$9krvX7SQeUNKsm>dNPx`e)fR&N5vCJb^r>+)@_2<>;CrZ>w~Lv_gj_ zScwlfFeB>Iog47`2rbANu4;Q914LS34fl%HS@(0efXsQJfWYk z(pRkB8~FQip2TEtWRo}rM4?(CZLt>%im+xMXCes{am-_zgk{9y%Q=!H6rpQ!$0UU4 zD8(FgiNI}qtb`s(?po-E*erB51x{wo2<|X%E2565^1Lm`szlrE*9K>e6geqon#H2tpAUFTaL=6(vMLyZ&I*{ zCa{Hy0twPBU~;*C`Cf?jga$Q_f9hEfs}0%sK?AlqI@BlfH&BUG<NV;Fez| zy)CWZ=NM;vPY?_q6DdVARBwlz($r5h+u?t=e`XDX7Uc_^a6BQ z``Vo;M}K^#pOq%e$j3m{`Eg0RsL?OZ>G+HsYI)w~RE!b0{=eyyY&1D#~wz$KDMG`q&)|Tqj{B za3AJ$k*5iJs)W?4q1s^w>*`f@h4bsFxaw06@!A7bVX&c#E{w!o3Qq1T2?KCGZ+}*| zBZ3H?i_p=)RdRl55xf9(Wa)qv(tI}a&n;yhOrA@Lt~OQTTK1|zi;VSAxi}E(I@>Lx zP0tmSF&-H=tQeiAJZs5HWClrY#=M)+yc8=w2>LLQ+&GBF%0TD5q?dY$szKEGOj9YIa?s3S7G0gYC2uyu^2X!F}FI zB2c_kA2t&^%$r(aZ~T1-hy$3pC#WsCZW%$3>uFNu@1SeRqwt?X1ap*he+;=~qHFtwvnUyH`xC`*b`!JKLvDudU* zXc^IeAh&EG{YudLL~pq!a4R7F^T2PI*E+P2u9Q5`Bb4|dp#H_n<(8l~W9nw${dYTG z4hjGSba~9qqNATzLZqx3@PcP?g&@>Ly0e^8IJmnsBty=eBUP6u?|=a;?EN8c&ewrp zhXA-;elolnCYgwqc!lX}fyse4mq)r6fZ}FAX9jm&&<$JCl)O1Z%9pWaz9lO57}v#) z_?{5&clOE;>^76=#jgq4(O%%({f7MivSo%Sp4oVBgwl+bHqE_R0x4YSC_OF@g8}GkwZ`A%MC%+K;lVL0|OHIed z?pTBj$pZPNg5zTdXq@SSHAD05xDMh8TkRrvQ`Fnl7F4GzRcIDd+o^t-eC=~mBLQ?a z&ozpw&|e?ix0cDOj*& zr17Uk8`{S{(pIde!PZqe{u1kOZxa%8vuw1Vv{Yx#J)sJJxee03k^OlCRA&fJ4+O+4 zJX3ej1OrV&(dkzWy$b0qKsZZ0t27TSPp(dFZ!hbixVg+6tXsSH8)Mid1W$~2XGai` znTe&!!zs=xdX^z}d(6-JTV4pb*v%qR#rawRR2YFAjHHjS!zp;n7?`Is#2Se>apx!A z_YJ&iS>ti)2+VFu^n0F5J+(pJitu+XnP40ULI4Q7Cpb@?_Vx&Fodt%wW360~k{R7J zVj#Zuf(I6fh82V{%**8-&RYVlP(;E2Bhc-4KG9MC_61;!RHaAwJsQ=az?>U(UlOnhUvN5$>Xp8#xVP*AsnE~ng9DU+Uwx{ z56r0lu|N3V?cfiyOh@?z_xp=*pL8EJkchS%!ybYHD%YQaU`Yd{Y^-$Vg4k0?$HQ=Z zFmhYXy{-M%c8Bm~$F$w$%7xW+Xp`H9uG@7-P3LW6=k2eX1)uL*-o)^>*}`Mvub1z? zoqpf?2g>O9ywC>q77qo`@Dv<3gE-lD1<3gKgy8V+4oL9hC&@N=f1D1BoL-Eb+=r$+ z1My!Su!viRyaxY8`i8s94V3q~qinyo#4kNS zMtWyPI_(0NA3L6v;*zKGkh<}fV|r;Kq58gw$MNyCQKK-|zbgdOf7-|Nmh4Y6{YLe? zt>W{B)lXZr_ozqNRk@?(d}|53eXYZRA3N!6@LUMH-T$li0l=SJgnxWE>Y>&z@BK>Y zOP1hEm!&^8+55Dw{@RT5Db{b_{fg^*E6n}1H;8{v&iUDx{WWZ8Pe%G#71#?|Zr#at zdj)4}vDr?zL>b@MElN2Hx_Ku4@cVXYYU(!i&eEC(M00()WuzRcOUNlYrli}=e$gvs>RnZb0+ z*&Z4*mNmj%=6&W1WWpUH&BnY>Jz6#q1J$T2OsULmN69#HYM~S) zYN~t^mvQ*nBUKywddcgk|x907v-}Zi`}(rCGj)B>8o1Hh(94P%D0Qiut-d4 zryx>fd;;khh#iNtiqK|0$ICMj>3uQd7I_8YTA{Mt+&#l}<~&5}_7%nPg=t}-3)tKD z(-qh)(I`ZI?nHd?mbF*Y%AO^v-dpkkX6ItD<0)fnpV&tfJ-IAb?NN~lmBqVIAc-C8 z6|iU1V#O(Q9fmE+`7J(XLe_B?^$^=_q|ybM*CA|!GBE5m_65toNSXny+-%V#w4*K3 z1y3DPP9!Qv=j@$VOhL3RqAbPqr_GoVn~P`H2bvOE)Lbd1gphk+EvUA#D_8_;j4>G?YMJ-#EqE&B-W{;BPk8D>&OHx(piU zW9rN)Azvt&_sP|}7v5(osBiYv@mYu+hECz{i?sb_YqsaCFJ9=VX#TAxR-8PU$&l~H zER>5ZSK$>gNr!`P0yWNfh%>2B%pc5ZoMR?p)Iy4>m?^OM{OWMbHc>H2=xpp{;lPl~ zkYp>y!DwSy5M}f>n#z7==Ep;nCM7}nQ7HQ!74}qIA->@{jUy#tt&2||O)5y4W)^1H zNGeQj%Hwok2{W2)KGVv{mke=vt@!3!F=O4Nu%R+cW`m}Y?TVyy@2;azkIGFl#ETVoI1>#0QB#zoXPy)qH2QeklS@?O-GKxHPMERAGJ<4r8 zslb9Z|0YIzd9w<99*v(bjp4{#$87~xD07C$n-7{w3;EdxrpperiLSazr`thn zFaq2?B?4y>Km}ED07d5~r-IWrSprH|IY9qozsM+wnj~6JR9aprvPDt%&h?l^WtW)Q zfo!iTQb9E_q@pT={8pJx7y0I^<2R!&+TJv91nCq_Wj5C;B7n;5D2Ujo!l*r^IIP1c zkNBvnNJuq$qnq1_f~X>zQm%H-*Cjs8$YvCvQ67$^N`n-osz|K^blI@KJr3v<47eBk z3#^?>l?HjTgug~%NJ@1n3QUz{gSx6Ah8{C#itFccTx=JGol8OGLI2G#-|x^{asTs| z`+OoXb{HByEV{S?(@>A1qCC6pj#_3TozPgA1uZG1hKBH{Xy&gQ>5$X-V8kOGn!Jje zrfBYZ0k%(r6Nx)vncii+^%#$>Lp%y7nu^XFlSV6h`GOnm5q_nk7D<60YBtC1HcG-#Ln4DdZL$Y-a9(FRKa#KmC z&+v?GK@9gMmv-k$D3?8&Ms5iet^`#Bfv(gBmZPeM{#dFWG65_4{NT#!L1JW8a%=_| zwi)Wsz_7K?W#eSa9taz>Y@Nxl7-M^{Ci_z`+9pRbMl|_zD#dhb2NCve2T(pCHL|Qg zuK`7cIZBY4S<$BFc#WcA)yadh}ARkUvC1Eg6s~F4iVwr9}u8Gnb>`r0b9H6X* zccX`Ih0>0lL|LF$e#P2Gg5RA#gxOiG2@%@CKeOD_CL2919bERp+Ake+C#fc>Z}Wm} zbg*q^g~+-q@P4KZr6(3lqt%=1Zq90hdS4W0aJiu#;XybyhFRvcGXn71%Y6Q)hoD#8 zG@GrQY3c)}*QmLIGb?)#PU8DqurK3|462w6A#1VdTnyYe>E`j!AwIVhDXO}BKqVWj zK=O-EM91~UcR7LXC_PEbcE8)*Xr0H8!+TwJQPTV-dVrVl=>C4A`$PAq zGas=i9_vapJ$qJ|m0Z;`l4U}N-MZYZ zuWD@D?LuRJ)7WuKA|wLYUqr6J*a{ODveQRNDI_=~ZzjlI2*ybYz^D)$Nd(~3zio`* zV5=HF1hIl)HM+6!(C46_U&}88gM#}J%y;&@L4`GCjFt;Wh$zmE6U9hyVh)FvTP}9l zNQo%RM;`W}NN5Mc5_K;Qt1ji+a&#o})5pUU-Io+*dHqW$IhMg?@UrrYl>F*9#}!1E zPuq8?_*lcy%g03!#VN{0>u<{>k60>u2)u{SO_$ir7?vaP$H00G?pcEp$o7-G%~y79 zldp7#765LLw_l^(V>3FXEhqoM7jzH4)24L_pl(!wY^o~C|WAJfjL|E2e)0k81 zT*fHQ^2T~vihR)mqESx5Y$lzPHs^2~L72f4V@+_;xK87fN;%bh_Wu&Jjd_9oXe6m0{q9jd|s z^fjLj$lar)!RQ|tRa}%rrLAtbNL}usWLn5G#Qabx@w2 zGjcAJ{V_CZDf133c8i6nx1PHJ|5Og|@5Y|zQg*)+*I^{=vMRBLq|a*WR52db4OifS zvc-|ZGO@)(|F~Bx2c;a6Ay{`URu%5s$vmxpFVekzJUVlU6`J*ABJBc>%|<&=_q7w&z#*_t~rU5&Yt zleB=>uOn%IQV?57KGL$Pz3HSgJWqSNU}qOnssSmwWZYmOl%Wx$X#{%`VYU>>#uDjD zc|2R#&hHPeRbAtR^Ug=D0J;(JSfE15JZXgZkZ`@H{msyoSU5%@V)i%`MoV{tE=?N( z8S2)l0d)KCt`h&uQ>H~b!S`HcU<+he-zfEW>i&4G{h1SXzY zD3wMJU|$gvD2SlAxDKmtygM3cH^mdgrTc-83K00_7wW5W<|V4$zH0r@0idUtOfa2< zeCu-5KT5F4rs6hgx+L#KC6#4k#<_dSlKL;eVwbXn<%eIv{x4GV&neY=G<_lcAT?e;{u}?ZHN?M;B}ZBNA11>W z7}|=RdgRi|L349?T{q3pYp|semP}?o>q`6@pKKc92u)|!dWg!WD%lDd-z)Hk;s`Tz zMP?tcPkILPZuVo&<;VNyA-O-;1@xG)usu9&`r4BA@BlFn+x?J8N9 zhPB@j@eLgEd1s#K5uS`*Cd^wg{h?IOz9qK`Z<_elCG;vZco0MQGbSbCD4n{Ver#~0 z@?T@j?&O}ilUY-OB;HW^W$LxK!9+q(6xgI95lB9ZnMhYOy-Nm+zlQ1zG|i?2dhp<7 zLfwaDe1s)#XO2I+lcg6(i?eJ@0aq>vpn^X>c%y;w=8vZemI|m$<|=(D73*iCV8Szx zgXucvRa`n%t|t)`2_p7|VlPDw*?j=qqoNZamHzuL&j`xh{~~ZuQ9$q^Q+pI;A>9eV9n5dC7#E?G|A# zeq}>r%&?pE5Wl3g=C`l?!nneSx*|Dl9eqds+H8Umx`{v8Ub?}%DO&@MG|3=|(tETd z`R}m&y~~xF=TD(c{1n=MoYKq2qGammYU%V(rmC^2!#}nM|GJDS+dnWM2Cs5{O*4qd z7l5l_mFKw$*@9=6AR6-KWn6yX5q z#PH12%k|q#b_O#u|9?d(0=9$TmG<3HghplgEc@-kuXfo;X~*P@4xs{Fd{)I$Wt*Wn;ezH5{{%s!DgtP7@k1 z4eyTBWj1sdc=VNOFP^ibd44HOF60p&B1UiwM$1 zh|$8FHDRB=b?By?-eT1(5r4y*M?m&+UAjd+e^T%?<-RbPM?zG&d?iW=vwc}9H{_GG zfLh{aE&qzza|%JLv)%-p{U_i+j>%18`ht~(VJJ^pJ=D5sWJ;8Gor)4Fi^+iEW0Qt@ zlKa3|`@PW4ry&GA(bkJe|4yJCrlP^>Z;J=%Gt~(F=&Uv8(eZ92lKTKy0MCoV<+4@xKjk|KO`9VLu-i-|?~%gBS+J^{+3CCz1^wem^@%h5K z2eeEE49@48(ay8Tb~%PO4MmQG%l9ErNd;VzhCq@XqXOt7@dL6QYnG8lXTuclbAD*M zg&uo4-dQ~)V2mOeh7(7WW=nD2z?-~cHYX6e;%9hg1t$>qvx@T&&G!&&qAowVrXcPX zPF|QzhqxWALZd8RW`8gu=*^caD69*^W|GY?_yqUyZZ1bd#Nde%V8m3I@BdqLP-ikB zKgbVmrz!kD!0!H8=Kk+$p5}t|P+49+-C}2^&*-W)0UG3@5gHQ$Ae7J`p$2Kp0Aa}w zCG;dA{*i@31Kn7wE_Fat+@#R8fF_fKqgq!ruaq=5`)O;}H@oe!SJk}dIqzm=u#X#j z$NT2_y|(@3eYrZ_`g<}ApXZGQfEGSmGAIb+j3_x+o^)YLrFRCxZFf2YM~*X)L#1~V z?9!z%ES()6fd2R(-QE@*HQC-47)7nxH38}A0qg$Tlpyb5#Z^b=b_m-6z18mMfDF}M zZcv`v5XtT^$Zr2YEw?>p)K2{#4zHaT_;#o>+k^c^%~2lgX84!NlsW#eWm+Jx$?do zOAr6cARU~814nWiQ@p7Wa*TvQIh?+J7@PrOId3F;`O%_R6)fN32>C-svjyg=3{c6KV;~mZ)2@(&&sHNC&4wZZd@Su zr#ug_k-dBGX>Lkjui;-9eYGfd+?MmT?XNM&Er<51AGoW%rwRNH_u_P4L&JG*!MzO2 zekl%T^m)Jhq(^%X`8DKjA0qvn?(xuXnT!4IuX-2ng4S|@iURfyGT=S;#Vvs#5(UZ- zg!WTopgXB>g*L9AD}vfj{RZv`LD8{Y7BPY_);BOxO@0X#ytnku}}SoN0N7 zZHCZ@i`T@32`1hVFzH^!UzS981+=xSthFk)y|t;f;SLHV!0y*vp4Z!4Zz=8hog==0 za78<9oAZbo6w=V>&u!s`<|Lk;qugFZP#)|$Hd=1Ro_)K0LK`LK{na35|IIW|J-v#2 zCss)K6D|92^$==MUN*IPdwsDy*%9tBka77Hj|Z3LDXiPwW9vns)3Ug#-_pOTZwVt2 znHFPboikfI+rVJ6E;S$ni?9g^8~hl0NZRRZpI;Web`AX${m@1t^H$EnJBNBjCO|Tk z&?m{%RL|C9GJYl(WoyE5LPCv#Xz>Su3@hwC(6nYpz`d@vp(;v%QQabm8f#@0)Eh*k zb{h}U^U}McH_Idf8v#f6%Ru9njBzDoX%MPpa7KRESl3mlTwQ0+xW=1l0x#l)YJm6?-{ zjux$o3Qm^Bf}RrZgsr(g@ESY)LFP9Ry9JpAyJ`t@IhNj@{z)?YL(dI9)J3VL~DD_B} z8!r%T)`+C*dGxugLZ7T>g--WIee+LfH_y+@ZbJN*X+iDc)gMBQ>yw(O#~zxK;W$RT zamDsd$&0u*NWhQ=htfG|B49$Pjy z@>{owpOC%;$Ee{F`>3U1En=+Hp`jzWqm#H_bQZf`p&cD(x`gcbnPD%wGyPkLv+^53 zCyOgcNqk1p_)dmm9^SpOHzhp}uWmm4BjB%q{e>iJ|U(mcKDxj6Lhe& z)jSKkYOzB(0|k7G^KHaG2{2j0+g{;ykMEz3SE=?mgOW#hzYgl#IaB_`L3+rgvCmch z>NM>g!M-P|#wqbnB$y$Ur*}*A9zi-CgG88?y~5z{b0rr{bO zxR}ONd&_6#2hs#LRVI|0PM*G^xRe9h86%l7!5rSXw&i~R=;>3dpfNVnY|ynf z1a@1Fg}7|K15M13vC=zuUVRnvLI-ZIr3K5B(KGDzzr=+!~Yp_vrJOc98P@NYN=NxFhUwXX&PE!0^L- zv??A@L29^e+?LI&^O;KP;_RH=q`?TqqGsis?cljpMEDa0xzZc4rB=_LgK%G_f;|Gk zIO>(7&b)5b+z9IlfV@9jccQd$l0epNq0?u-#x~TmWY`U%G87a!`L|t08dj{_b>w!U z9qq?ADapw@%RpPq6`2fkD6nBx0qt=V2`off>~P=c*~kUvup>>ofKA%Y^jRX}qQ!Gv z{XNS{Wzs(K5^J%qSNS?hL_?!DqR`^mTmsD;EPfj)#zoRSkK-XhNv6d6@!|Z$m;}4= z?f_i!LR#HS{_{y=I8q=eo&&=2LB(%NRnI0bkHZ);Pmwv4 zndYA7C*EYY%a&_1a2|oOPUei&d6H)*zn^^%6jm?jHnGsrVQw$(&R)x;JLZ1vmyWjp zXyuV9lKH%;Yt@czDIkyRL>@O0|J+AWkpLvR;hg8)ulFTfMvyx(INJlZa?y1;S9d$U90Q6Cw4NJuuD3a!GZo@`=X z6wpuRq9%g$fJK%D6}4FDJ7!BAd2-0(jCyghUg_7 zCS8BpC@|bIpVazy5IT8x8YfS0!?>MQ z{B^~H0`0@>aPi$8`ABJ(V4?XhiK}=|teH{J$}@v_Y?gY&)v5y=*=*{WMG^9OVzvZO zh}yO42)bl&cWWVZZI*drFV_9T18=$(r~Ok>pDn0xg2{Y+Wc2WOvH_yP2nuG)ER8Zl zR5j}ZArE-NWsM-jyarul?jbo@9TGaR*IG03%(mbsRUIlS7RQXX>`rxy1F3rNrc~9- z%kvlq?^<|~Cp_U+($(KaNo|1{5;av7A+j`Q)~{>UqP0|fB@vfnixHQ@uvou|!HkKk zgn?^25|;$7jL_S*cpT-{i1E32MUu$dhMAQZIk=RAP={2&9`M)~AlIU4lNpDX;!c1C zl~6*_mC-;+moav#!QydZ2?jhnWh8o92ZRydgQ5-Sr1mpQb?K4=443AH`Bbd&b zCI1?MNEE*AF4zkhSu|kVexYVpE=7wuqur69A81JOy3{ZF`*&UN{%=3nWor=g4~5a> zEjK=c1hpf{cGxBq?Y`UM$1dUY3u_ue~9!K}NPbcL4tUfaNIK`>_=O>qj%!C(Rq*J$ zN*iB-!OSU0;{^%QRPm7Kjg}Jm!TjAOIq4LO^Tzm5t@SEX<~c}{qL>9_b#8-(y}P?? zQ>{I?e$5fPf0P`U_rz!;GOuW^#nv2YN6I~E9ZSh_E&(keX@(5?U|fb=6i5sq6P`ZD zxsT(`Xu_mMD5a!njnQBX2&Y2E$O)Z{E5C9T<)}azi68ZUQZeDH8N0%D<^J6O<_hEx?Q|cOmN#N_c zzONH|e>@mH&QF?|-gz=kQ+uu|ThLW;2urAPq9SM%Vw_tr;v3`FfHG-7+&v%zIo3)H zdY?f!GUGy;&W)Q=>YV1L%C?U3Zj)BeiilEvgB6P#`-6w&&VH~b_SM1d#CE^KF9%x4 zPTd}X4XD+JIw@;pU>i>s1>6gw>_KAQI4iz`1g?;`D6kCczRTL^csaY+i7-sOQy0fq zj$0Nz`q8pF3*j2Mk)mm>_#+SWnKEtbXARuiqi7*DQb#U9h>y5?sq2UYo&ZhGkB|+I zCl@RowjJBFq&l|Tsl%lH;3wAR6xQaNoM%>uC^2wREOc`eUL|ict2hK4QfgR^BH5~H z`kX0N;bA1E5(6&EVrgvL8L>yqS_j}yMtCY{@n5fX+TecZL?~;P88=oE zoF0o;x@9WAlQJ4Gwv9*t*x-xXw%H(d@6Wd=sb46J~sB z&eCbw&+rU(r{ue<=g_RDYs4?r;Oa#F#nJ0&!Dt@gxDZM?tASD`ZREy~k987^a1Wn= zI-P5&6hAFI67>4_<(z0~%s(VFj{z72Tot2mmqx5eyK*{tm%@b71lVARJcb{Gy+=8t?Lp@5ZTL%uC;u zCEqm9y=LcrIq$QY@3X>qy|GH)Sq0l@_u56(y~cm^gKj6@f8BNH z{Pod1y@xKZ_On>wXS!rJ;YIYd;ru3F@^^r3nhv46qOx`IszNhnrmW zB~+puy9-No725j%KNRhH$Nt*+QDchr0lY)1@m<^!bAgF;^NVb2nPud%F)B8&yT}6p zhq9j^MDwl=)Y}cmo2^U!3LoxEpX`;{QbrO;-v}GTmE#o{JQk<}x7@Z#jl3zgn|c}=CfqQ&h2#P-eNUeZjRQS- zD;yqF{GJnf1s%Afa7c=)gE_@y%mh&CgM36Mh(@1>OS|ANlRZS5Ey$%xZ%{S21kG0@ zsoMY{bPZp0@?@^e z8A~}PLYwBd_-?+mND~6 znlO%lcoEQd;gkY)^~eekSy&=g>+#~OTBQ4hLUS}mV%QrM!;vattb+~6FC+Nj)(OIJ zUvhJZYB4enO~?#TVVu+PlOAx7z-unSDqcCB|5#Ssbnkv?Ob% zghdtrW;fv4gMwI1h($~m^?*J80KkY=!dT?lOyLwU{zFr0MVjP+js#}uYu4$OM!iEM zyh#Y7#0=1q1Z6PBfG1^rS{*b~LMo$0uYO;Xs> zJ%Uy62xp!qpQftfhQ8wSE)P)9V1|YvIap=Bf`P%P45oIl;LtfNpr^viH;J`OltE1P-E-?RO9$Bf*UT^b1*`eSXBqm zREP2CK)oN&c1By;IV zWHg(@Sp_oD)r|elY=)Pskc_Z=IdfGdyJEe+HI_BJXP` z*>1kiY7T(!0hr^u(Dss!N_vFwE->oq7&b zF|ya@0^ltXTTKx}a3&eTflQd#A=0{@zyZmVE?U>&%(Bi+qn^d~f7FFrDI_;Iz{Akj z@j_{FYirzUcj?*n_h$GlQrl02w1aIj%uh!B1=)7TK{>C@0PH6f`NT%k=Wc-c1yp&L zHW%6(3im;q9n>49_W^7(%-`?!!K@SM7eIYy?|}S;YuE3-ulGT|6?Z#`ey4v&`T-Dn zC(I$`^_(r>AxLqTS=WC#05}=~#gBY`2fiQ74-LzQkby$hFi+^jpnY_pk`Na%5OQq9 zqXy015-I7?k{+$c2>NS?;w#Q@(@|TM=tOv@N~M3e|4dslftVu^TW=A+{8$ChDGrDUn6% zue**^Nz!lK-T^2pQv~wed<8a<5oa8|{^O+y5%8-~)T7&mF=d?~>hUo1!*vslvPBKJ zw@K2rNUe6qq9l*P#DO!ab3atItN;cP563&NmRE!)Sb;rE2(`7XmeYMlr`yjr2S886 zWiiNDrI~ws!G-XkE0&2 zyBQAnEAb%Lbr^O-T9lK^b;y_H!;(Xd_vMe(nC9)xN+X(f^&qH;69B(U%k3H^MDA*d zrqZ9F`pwfiBC_8~CY*@1yJ_(0dJp-M5~#^;1B@0qGo9Z7bSxcj!}h2K2lczXk#xB& ze7qFpW(ahI8EQ?yI`<~tL7+sj2*wTWF~Oy0v?iABT6F_!ps$b9l^+}dkW?nFgt{Qz?$M6I^N>RLgW3;lDbV@D zR1eZbj%)X2?y(E6T2o)UEQeqP?rza!s8+I6JY;Uj45_CGvVukNMxF2B4<0*w;l@w(XHa|;D>je^D_2NTid z8RI61z>UJEyeybY(n5_n^59BXQ1D2Z*`KakEZ>n>w{7HC!}k7=o`YJw~^ z@ZeXRoiTsGu)H%T5_%BWsDCsvcp|()X6MP-3kc_{s#gl$#$?0~)7oAF!0o{^}+*L`#xC4@A1I)#h zWFNnyKNTb=Vx{bPBdnR44^=7Kjakn_Nn3G$KW?C~#w6~gfh;Q_`DW4esX|p125lm| z{%nd&>{~Hal-f1Z_kQgFC_tjv@Y;_-p=108qelpa<$BvOExOG+*vfI0gl9=|NK37CwNk z(^cnnB8eoERuFD@xy@!?LAHkkAHekw9-L4PXVo|@rN8RK$#pP=sU2iUt(le#$J$w( zkK37V9ALiky~Iy87NNDXfCxSUDtPx?FiH;x3vYU<-?3^Z+@oE8@Orw`ula!SlIz1a z*$J*F#Z!vyU)WoUpa~E>-n!HEFo4CjGanRuf7;c3eu+Do<_6J25_KUfb!$woA=E>T z-u!^?%@nV!AvyXs&XGrXfC?1Lds=U1A9z+D=&LrMzLt4J5rOSQJ+Z46m4E=wa%H=I6B zs$Qb~MJQ6&Nwg!)DAy#cHe`}?!$aE@N=t8&v-!dWS4lf4N?mJr_?ZZhnv7qWhKdTi zPdV{(b;VK_w}|b8GR;YZp6zg)CsEGGT&b*+TpUxj{p>cP#L`JzZ^P`ASSy*|;2)vA z`Ch=1zhPABN&~lrvG$4SP5)>{p3HJAqMnq4 z%%)O)BkhXvLQ}Bu0~n)6DcLl&-INdNxXWUZ`hB3xX#9F|R1Li6fO*A$wT9DY7&3X| zvnqMj<{KON!#(I#YljyAijsvFO18w<)Rp6v!|vd}FY_bkn@@;cpDO#0SS9&fxqE{E zdCB{4_kRbu>L=o-A6cGTf0uor{|8U`SM08S&iX^*7d2r2W#*Iq{|WK@x29MUL1&Y% zIIVwQTdR})%FXj*jPx#}adt52Qz2ZnD&M#5UOYZ%CHRx=pANs^){%xRgcQW5Fvi-cTfT)7mUiWdJKJZ|3Rf*q98 znTgJccd_w_6wtbN1shZ!yZ`OcsEgK*ty>dMu62W}ySD33y-Zt*rm_)-F~T@ma1^fJ zJUl2L_h~!^?_#~VEvxb;Mz8i&mtsVeU|{ypU&;AV1Ys3_J*4}BH3eC0&Js{KMS;+j zBh@DbD@1}AAM*;Uubz39sjZ%HKn3X@viQ9Z1NM@=iBD}5xnaRKpc;5|V1U<%FY!>> zUmuBkXBd9@TLZ`FrwFDv2Srv?iyM)qKiY}xD})wtc0>IM8>m=S`_1&U(?(C-$YXmr zWmGywusIR!)DKu>%%~GL{!|+V%sJ|$`g5#Dmy76|96O?rgC1Lg!CPL;(fLmjkzQ<6 z4GoSdl$8)SoM^E?lLa^r|Gg&7QdAx>X)Q5~7BUnsDO|zE1)(w^MXuoi*a{6`;3KHy zW1#E>QbUFqKMeEC9xm~Evz+x6igLfT$+&#&H<1Y>`MjSfrNuCmG-rPtXJ9&O$XGW< z0ZJ&Rp8;i_SCJdj%Ivtnw23{U6?d>y+xoyCKm*1t_-biQ8VMw23P+J0xLRk}Vyr2W z-WiqZG+9p!HtjVMZZVB)t4Vn%&oA=(vvBU51Cj)OHcvl~{W)x>%AX!{An8k57Q^SS z^FXFGK%-1&bo*z9BiPcr)2BI{cW!KTFwAweGQ}A8^t^L=NqolR{}R6hpQszom-scl zkQtGGB>w-(oRK$hGW*~4AjOJ0a{r%k&Zg72oPdHz1?;V_1%s7}5i6_&MS{&7R>EJ{ zefGq~Y{benbAwjEH~ClyS?2Bg2gP3YNeR-vz}>-gI+yEo`{U%>)AN_&Ln*XI4J3ls zsMaw9!#l|?HAeMUetRQ}gsgAM8n-?yt^882gfv(?i zjoedjz7hi$DtRVETM#XhSc-~%=0X)*d((j_(&Df?z)s_{}!!8yc1Hhk~)yvSvOZxk#mnCt{rHC4(1-#XXNf^>*~<`<#wGb*C+q(86wGC z;AxY^@Ks$9ac87nFq2VeEB&_uf;fp#8d<4JxO1e5DVY|&PxeOC7=uFz`mRH*%_R z8T-Xw9oSj!Z#Srdko6GWdQ>dq6TE^Chqs)tNyYC5nCQNN|L58JFElVI^Nf_>%Sf#Q z{q395Ka$^9Lc#wFp!|QhI92{jj4qu`bod}d5kIJ?Xe3+ZuL{HX`-KA%{C<&K8>ow_ zE3TTjO7)55zEft1{}KwokLA7E4g4H&Gi^=bbxI8Rm9fsn+%f>%V=Jvc^SEPk&g2u=Y9qluoI=74h)|N<=CstvOp5!40zL=l6=G$wYB5Vc>Nuc z!88R@kqQrH8w{!v%)YCh_;$;#ry{n_{BDxLb&Wce*gq75;~Hn3WTsU_c1-v9iZsfP z45YU9OiYD~JV}|!UURHN$WpxXJk2X&Ezfkzv*9pU(}g-h%$k5EiFv9i4l^vyef;b+ z1;&Z1b7^{EdO-~Vq6x>$@Zx)G1E8lv%e5|Z5ahv?G@B%NU=N!8OO@~(-C~}Kc*Oqm zQiCnEr{e4_ZjNmUDwNcW0{TS@VhN9(3ZHNy9yK9NG?9!jd@2GkR4NS5?J1H8jw;Vf zMEE&8%^?cy0G%^w>sYlXU+p=@CgS7<(;iCgn=L7|k+sZmadR%4Kn|YC_*az32(-5{ z9+eng^dV%P91x)mf7!yXF!u~ZZzLL;UHLn8?kNcT0+`q-=vEaJ+%ja3ic+0CPk?_1 zw=%?xf|I)F*qOMa&3c)~j3#AS;0HmOkHDs6 zDPmF}!|sL{l8jP6Q+-JFljd|366Av2ZL2~%dpBcg)eX!H0@c*1w# z?~X{)04xG!{v(i}f_X-I-eA0&i>8PjM7sIEtnOHGz5f}=e=S3QUGn2E@xFaa`=ZSL z+56x>1Nq;Up?_~d&Dvj01dGjlM?TEyWBbHVgiu<70|f&?L*GJZtyV~^{1IGGLnh;* zg1)K<6#AOKtV5dU+8|+)&GobtbR_i@W|lgYF3l~qwJM!jYdt*{XG)cSeJ>vmGNJaH zL3n-nE?qBOE_q%#TyJiR<$Bzc!Xy`U>Diu-DQ!~7Xr_X{JT#fy>$`=3&8(RCu+TzY z$s-w{`Tdm$FB1n@b{hc7e6^@uJwvK!g=k9EyhXyX9FQvE*bY#8dXnss%%c}~Y!2qh(;lT~PL^F$>yi8u{EM6i1b9sH;?Un2FIC1`Uy4NGa8{MvT2zA0w zI<#!KJaaf@+g||1<4v1}zaHeR*cD>B35&%)7y+7p=c7A=_iR%_aFLj&g~_=xxXk3` z9grIjC@u0-&NFmapAUG!g!h%2er|EfxxaGlddrGcy}cz$KsP!R;kYB^xHDdP(b0H{ z0MvRsvEZ}ZkeztVh(SKTHf%#Wyuk;L@g*FN0J|>ta<8yK-j&flrBmKQV|}MTDGht$ zF6l+iZO6~G9PZZeK9W;?FA5`{-RVC?Lwu+cdy$VH@je1$>5g2%F7S=_b<$sZLO=Hl zEAzSEOg|!{-ctE}lMj1?cYDVK{*IAurLOdL*1j#g$a#Fm9fF#Fh-JWoUx+z$#~zsA zk6C|G9_=K_c{!2W-Y`9El>c}_fhqC=NMbxDG1Y0bugiN5^CjeHk@Z(FD`SBba0A_p zEjz@Xz3%c%3diGyh1KqF%cOTGo31F6No869@5XeHtCbL=KyCAzqOsKZ{a!1xVk`=w zz#_~ju1Z2YmW4uS?uxhrNfT=lqzIK3u-$9%C!l*u7-ydUc9~vKW$ITIozJ z!CIBX(R2Fjz~2C41Hcl1a2CtV3Qoo>%4QQM`uD*a7R=BdGD!XK;nh&Sx)%tmjC$fa zdmv>kEuJPGR3U!FW&17 zQPC2CB`YnW^@8|iQPvhPr2I4*vnUqMwQTU@`{YEj@$(Q?t6W!y#~jO_McPJ5LwE#t z0L?c8O|MmPC5@j8=FzlsZWN<{JdUig-@-Jril{NcSjY;9B4|dz*>ma?W-z8{gN+f@ z;j`=NGr|_PGEJ>NU|E&HJ(adh=hyvw z>QrT=ZJqw#@s1ZNm~(QBiiG#5IOpCM`ENK3esI>sO%)Z;U6k-*1K}F8L37?z<7ueU zHIioNPfZLsP_#B{U4$r>Kdj99#is|%4D*ad2+&e`c#b6jq4|D}a%vI!j-u=<#y5}N zLY8%;2<91ni1pCzjcofEYSZD=X_CCu4J-lH=cc;VsirK!NRdKXNUO@tqEk3Lhe=O! zg#)m|hg_~@HI?O?Knx3+ph86H7uFENYrK(PzX$W&fn(V%3>E3WgxLnlUdLb==%K-c zQ2WxB7BuIPz5&z8{qNQhy7cpmCA6wgThtI`!`L%HuMd8*DA8KI3p2KodFN3hZql40 z!`lvyY_v)HGP8zg2}Xiu3c&~=##cPC!6rofh9-4_%_s6(n zAiAF8b+-r#C%1FJis5Rv)oV!OdPb#0Pf5RP8P18ygKs9uEX5>Ka=)OYc|dFJYYw+G zjFDeJ-OC8Y>r?z-!;7|t`+=RH@EwW4dZ@{{_?+4D!2UFC10yU(5Y3&$;*@3d zpUnUkd{Imr#H~`6GFBk+^*oZo#7Ra&HB}KYb;pV(wc*?pPk)N}zP*B~x@IA1n#GX~ z?noX^VY6C{Ep+QHv&RRO_KN!3B_2}N44d0}&Xi6yt{=wnOEP$nA~78{2N*!v_pPt`K?w^*&#ITK2o zIz-~dxnX_pGDfVypG@Zqaxo(uOFjH`OavY~L%5nL92GqSC8cyo4Jkt5cJ1qS+OO`I zm1`8E&5~`RmUQkD*jnd+kye^jG)q_s3Vke~=`N%0AOCKo3h5Wnca@CCB6s|su@L6o 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%0D$sp#}GGCfL`-zWn;Xf#NADSDipmNf{WX4$74V8 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 literal 0 HcmV?d00001 diff --git a/edexOsgi/build.edex/esb/bin/setup.env b/edexOsgi/build.edex/esb/bin/setup.env index 3661f632b4..d8ed5468ae 100644 --- a/edexOsgi/build.edex/esb/bin/setup.env +++ b/edexOsgi/build.edex/esb/bin/setup.env @@ -47,6 +47,7 @@ export EBXML_REGISTRY_FEDERATION_ENABLED=false export HTTP_PORT=9581 export HTTP_SERVER=http://localhost:${HTTP_PORT}/services export JMS_SERVER=tcp://localhost:5672 +export JMS_VIRTUALHOST=edex export RADAR_SERVER=tcp://localhost:8813 export DATADELIVERY_SERVER=http://${DATADELIVERY_HOST}:${DATADELIVERY_PORT}/services export EBXML_REGISTRY_SERVICE=http://${EBXML_REGISTRY_HOST}:${EBXML_REGISTRY_PORT}/services diff --git a/edexOsgi/build.edex/esb/conf/modes.xml b/edexOsgi/build.edex/esb/conf/modes.xml index 09c3b0ad4c..86d13b4bcd 100644 --- a/edexOsgi/build.edex/esb/conf/modes.xml +++ b/edexOsgi/build.edex/esb/conf/modes.xml @@ -113,6 +113,58 @@ cpgsrv-spring.xml .*sbn-simulator.* + + distribution-spring.xml + manualIngest-common.xml + manualIngest-spring.xml + shef-ingest.xml + shef-common.xml + ohd-common.xml + alarmWhfs-spring.xml + arealffgGenerator-spring.xml + arealQpeGen-spring.xml + DPADecoder-spring.xml + dqcPreprocessor-spring.xml + floodArchiver-spring.xml + freezingLevel-spring.xml + hpeDHRDecoder-spring.xml + ihfsDbPurge-spring.xml + logFilePurger-spring.xml + mpeFieldgen-spring.xml + mpeHpeFilePurge-spring.xml + mpeLightningSrv-ingest.xml + mpeProcessGrib-spring.xml + ohdSetupService-spring.xml + pointDataRetrievel-spring.xml + q2FileProcessor-spring.xml + satpre-spring.xml + purge-logs.xml + + + ohd-common.xml + database-common.xml + ohd-request.xml + alertviz-request.xml + auth-common.xml + auth-request.xml + menus-request.xml + utility-request.xml + management-common.xml + management-request.xml + manualIngest-common.xml + manualIngest-request.xml + nwsauth-request.xml + persist-request.xml + site-common.xml + site-request.xml + time-common.xml + units-common.xml + useradmin-common.xml + useradmin-request.xml + event-common.xml + eventbus-common.xml + edex-request.xml + time-common.xml auth-common.xml @@ -225,7 +277,6 @@ time-common.xml auth-common.xml nwsauth-request.xml - grid-staticdata-process.xml grid-common.xml gridcoverage-.*.xml parameter-common.xml @@ -351,7 +402,6 @@ obs-ogc.xml--> - + diff --git a/edexOsgi/build.edex/esb/etc/ingestHydro.sh b/edexOsgi/build.edex/esb/etc/ingestHydro.sh new file mode 100644 index 0000000000..3ef1b62953 --- /dev/null +++ b/edexOsgi/build.edex/esb/etc/ingestHydro.sh @@ -0,0 +1,29 @@ +#!/bin/bash +## +# 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. +## + +export INIT_MEM=412 # in Meg +export MAX_MEM=796 # in Meg + +export METADATA_POOL_MIN=4 +export EDEX_DEBUG_PORT=5006 +export EDEX_JMX_PORT=1617 +export LOG4J_CONF=log4j-ingest.xml +export MGMT_PORT=9602 diff --git a/edexOsgi/build.edex/esb/etc/requestHydro.sh b/edexOsgi/build.edex/esb/etc/requestHydro.sh new file mode 100644 index 0000000000..4d07d95073 --- /dev/null +++ b/edexOsgi/build.edex/esb/etc/requestHydro.sh @@ -0,0 +1,36 @@ +#!/bin/bash +## +# 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. +## +export INIT_MEM=128 # in Meg +if [ "$EDEX_ARCH" == "64-bit" ]; then + export MAX_MEM=1648 # in Meg +else + export MAX_MEM=880 # in Meg +fi +export SERIALIZE_POOL_MAX_SIZE=24 +export SERIALIZE_STREAM_INIT_SIZE_MB=2 +export SERIALIZE_STREAM_MAX_SIZE_MB=8 + + +export JMS_POOL_MIN=8 +export JMS_POOL_MAX=24 +export EDEX_DEBUG_PORT=5005 +export EDEX_JMX_PORT=1616 +export MGMT_PORT=9601 diff --git a/edexOsgi/com.raytheon.edex.plugin.airep/src/com/raytheon/edex/plugin/airep/AirepDecoder.java b/edexOsgi/com.raytheon.edex.plugin.airep/src/com/raytheon/edex/plugin/airep/AirepDecoder.java index a3e0b510ba..d9dbd0556c 100644 --- a/edexOsgi/com.raytheon.edex.plugin.airep/src/com/raytheon/edex/plugin/airep/AirepDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.airep/src/com/raytheon/edex/plugin/airep/AirepDecoder.java @@ -47,19 +47,18 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * } * * - * + * *

  * 
  * SOFTWARE HISTORY
  * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * 20080103            384 jkorman     Initial Coding.
- * 20080408           1039 jkorman     Added traceId for tracing data.
- * 11/11/08           1684 chammack    Camel Refactor
- * ======================================
- * AWIPS2 DR Work
- * 20120911           1011 jkorman     Added decode of AIREP turbulence.
+ * Jan 03, 2008 384        jkorman     Initial Coding.
+ * Apr 08, 2008 1039       jkorman     Added traceId for tracing data.
+ * Nov 11, 2008 1684       chammack    Camel Refactor
+ * Sep 11, 2012 1011       jkorman     Added decode of AIREP turbulence.
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
  * 
* * @author jkorman @@ -103,19 +102,19 @@ public class AirepDecoder extends AbstractDecoder { try { WMOHeader wmoHeader = input.wmoHeader; - if(wmoHeader != null) { + if (wmoHeader != null) { traceId = wmoHeader.getWmoHeader().replace(" ", "_"); logger.info(traceId + "- AirepDecoder.decode()"); Calendar refTime = TimeTools.findDataTime( wmoHeader.getYYGGgg(), header); - if(refTime != null) { - report = populateRecord(new AirepParser(input.report, refTime)); + if (refTime != null) { + report = populateRecord(new AirepParser(input.report, + refTime)); } } if (report != null) { report.setTraceId(traceId); - report.setPluginName(PLUGIN_NAME); try { report.constructDataURI(); } catch (PluginException e) { @@ -182,17 +181,17 @@ public class AirepDecoder extends AbstractDecoder { } AirepParser.Turbulence turb = parser.getTurbulence(); int t = -1; - if(turb != null) { + if (turb != null) { t = turb.getTurbulence() << 4; } - if(flightConditions > -1) { - if(t > -1) { + if (flightConditions > -1) { + if (t > -1) { record.setFlightConditions(flightConditions | t); } else { record.setFlightConditions(flightConditions); } } else { - if(t > -1) { + if (t > -1) { record.setFlightConditions(t); } } diff --git a/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/BinLightningDecoder.java b/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/BinLightningDecoder.java index 40a557f8ec..9d1894ecfb 100644 --- a/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/BinLightningDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/BinLightningDecoder.java @@ -64,18 +64,21 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20070810 379 jkorman Initial Coding from prototype. - * 20070817 379 jkorman Changed log info to debug in decode(). - * 20070821 379 jkorman Added SFPA41 lightning data pattern. - * 20070912 379 jkorman Code review cleanup. - * 20070920 379 jkorman Check for null persistence time. - * 20070924 379 jkorman Removed HDFGroup code. Set insert_time + * Aug 10, 2007 379 jkorman Initial Coding from prototype. + * Aug 17, 2007 379 jkorman Changed log info to debug in decode(). + * Aug 21, 2007 379 jkorman Added SFPA41 lightning data pattern. + * Sep 12, 2007 379 jkorman Code review cleanup. + * Sep 20, 2007 379 jkorman Check for null persistence time. + * Sep 24, 2007 379 jkorman Removed HDFGroup code. Set insert_time * directly in decode. - * 20070926 379 jkorman Updated to set DataTime. - * 20080318 1026 jkorman Added debug strike info. - * 20080408 1039 jkorman Added traceId for tracing data. - * 11/11/08 1684 chammack Refactored for camel integration - * 20130503 DCS 112 Wufeng Zhou Modified to be able to handle both the new encrypted data and legacy bit-shifted data + * Sep 26, 2007 379 jkorman Updated to set DataTime. + * Mar 18, 2008 1026 jkorman Added debug strike info. + * Apr 08, 2008 1039 jkorman Added traceId for tracing data. + * Nov 11, 2008 1684 chammack Refactored for camel integration + * May 03, 2013 DCS 112 Wufeng Zhou Modified to be able to handle both the + * new encrypted data and legacy bit-shifted + * data + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -90,9 +93,9 @@ public class BinLightningDecoder extends AbstractDecoder { // Allow ingest up to 10 minutes into the future. private static final long TEN_MINUTES = 10 * 60 * 1000L; - private SimpleDateFormat SDF; + private final SimpleDateFormat SDF; - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); /** * Default lightning strike type for FLASH messages. RT_FLASH documents @@ -101,7 +104,7 @@ public class BinLightningDecoder extends AbstractDecoder { public LtgStrikeType DEFAULT_FLASH_TYPE = LtgStrikeType.STRIKE_CG; private String traceId = null; - + /** * Construct a BinLightning decoder. Calling hasNext() after construction * will return false, decode() will return a null. @@ -118,9 +121,10 @@ public class BinLightningDecoder extends AbstractDecoder { * @throws DecoderException * Thrown if no data is available. */ - public PluginDataObject[] decode(byte[] data, Headers headers) throws DecoderException { + public PluginDataObject[] decode(byte[] data, Headers headers) + throws DecoderException { - //String traceId = null; + // String traceId = null; PluginDataObject[] reports = new PluginDataObject[0]; if (data != null) { @@ -131,43 +135,56 @@ public class BinLightningDecoder extends AbstractDecoder { Calendar baseTime = TimeTools.findDataTime(wmoHdr.getYYGGgg(), headers); - - // Because binary nature of the encrypted data, the string created with its byte[] array may not have the same length of the byte[] array length - // So when DecoderTools.stripWMOHeader() assumes byte[] length == String length in it logic, it is observed that it may return a shorter byte[] than - // the real data array. (Looks like a bug???) -// byte[] pdata = DecoderTools.stripWMOHeader(data, SFUS_PATTERN); -// if (pdata == null) { -// pdata = DecoderTools.stripWMOHeader(data, SFPA_PATTERN); -// } - // instead the following is used to strip WMO header a little more safely. + + // Because binary nature of the encrypted data, the string + // created with its byte[] array may not have the same length of + // the byte[] array length + // So when DecoderTools.stripWMOHeader() assumes byte[] length + // == String length in it logic, it is observed that it may + // return a shorter byte[] than + // the real data array. (Looks like a bug???) + // byte[] pdata = DecoderTools.stripWMOHeader(data, + // SFUS_PATTERN); + // if (pdata == null) { + // pdata = DecoderTools.stripWMOHeader(data, SFPA_PATTERN); + // } + // instead the following is used to strip WMO header a little + // more safely. byte[] pdata = null; - if (wmoHdr.isValid() && wmoHdr.getMessageDataStart() > 0) { - pdata = new byte[data.length - wmoHdr.getMessageDataStart()]; - System.arraycopy(data, wmoHdr.getMessageDataStart(), pdata, 0, data.length - wmoHdr.getMessageDataStart()); - } - + if (wmoHdr.isValid() && (wmoHdr.getMessageDataStart() > 0)) { + pdata = new byte[data.length - wmoHdr.getMessageDataStart()]; + System.arraycopy(data, wmoHdr.getMessageDataStart(), pdata, + 0, data.length - wmoHdr.getMessageDataStart()); + } + if ((pdata == null) || (pdata.length == 0)) { return new PluginDataObject[0]; } - + // - // Modified by Wufeng Zhou to handle both legacy bit-shifted and new encryted data + // Modified by Wufeng Zhou to handle both legacy bit-shifted and + // new encryted data // - // Preserved the legacy decoding in BinLigntningDecoderUtil.decodeBitShiftedBinLightningData(), and added logic to process - // both encrypted data and legacy data - // - - List strikes = BinLigntningDecoderUtil.decodeBinLightningData(data, pdata, traceId, baseTime.getTime()); + // Preserved the legacy decoding in + // BinLigntningDecoderUtil.decodeBitShiftedBinLightningData(), + // and added logic to process + // both encrypted data and legacy data + // + + List strikes = BinLigntningDecoderUtil + .decodeBinLightningData(data, pdata, traceId, + baseTime.getTime()); if (strikes == null) { // keep-alive record, log and return - logger.info(traceId + " - found keep-alive record. ignore for now."); - return reports; + logger.info(traceId + + " - found keep-alive record. ignore for now."); + return reports; } // // Done MOD by Wufeng Zhou // - + // post processing data - if not keep-alive record BinLightningRecord report = null; if (strikes.size() > 0) { @@ -182,22 +199,22 @@ public class BinLightningDecoder extends AbstractDecoder { Calendar c = TimeTools.copy(baseTime); if (c == null) { - throw new DecoderException(traceId + " - Error decoding times"); + throw new DecoderException(traceId + + " - Error decoding times"); } - //report.setInsertTime(c); // OB13.4 source code does not have this line anymore, WZ 05/03/2013 + // report.setInsertTime(c); // OB13.4 source code does not have + // this line anymore, WZ 05/03/2013 Calendar cStart = report.getStartTime(); - if (cStart.getTimeInMillis() > c.getTimeInMillis() - + TEN_MINUTES) { - synchronized (SDF) { - logger.info("Discarding future data for " + traceId - + " at " + SDF.format(cStart.getTime())); - } + if (cStart.getTimeInMillis() > (c.getTimeInMillis() + TEN_MINUTES)) { + synchronized (SDF) { + logger.info("Discarding future data for " + traceId + + " at " + SDF.format(cStart.getTime())); + } } else { Calendar cStop = report.getStopTime(); - TimeRange range = new TimeRange( - cStart.getTimeInMillis(), + TimeRange range = new TimeRange(cStart.getTimeInMillis(), cStop.getTimeInMillis()); DataTime dataTime = new DataTime(cStart, range); @@ -205,19 +222,19 @@ public class BinLightningDecoder extends AbstractDecoder { if (report != null) { report.setTraceId(traceId); - report.setPluginName("binlightning"); try { report.constructDataURI(); reports = new PluginDataObject[] { report }; } catch (PluginException e) { - logger.error("Error constructing datauri", e); - throw new DecoderException("Error constructing datauri", e); + logger.error("Error constructing datauri", e); + throw new DecoderException( + "Error constructing datauri", e); } } } } } else { - logger.error("No WMOHeader found in data"); + logger.error("No WMOHeader found in data"); } return reports; } diff --git a/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosData.java b/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosData.java index 4e3febcf4b..d5d8c9ca18 100644 --- a/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosData.java +++ b/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosData.java @@ -59,6 +59,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * May 02, 2013 1970 bgonzale Removed Table annotation, changed from * Entity annotation to MappedSuperClass. * May 14, 2013 1869 bsteffen Remove DataURI column from bufrmos. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -75,123 +76,126 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; public abstract class BufrMosData extends PersistablePluginDataObject implements IPersistable, IPointData { - public static enum MOSType { - ETA, GFS, AVN, LAMP, HPC, MRF, NGM - }; + public static enum MOSType { + ETA, GFS, AVN, LAMP, HPC, MRF, NGM + }; - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public static final String MOS_DATA = "Data"; + public static final String MOS_DATA = "Data"; - // Text of the WMO header - @Transient - @XmlAttribute - @DynamicSerializeElement - private String wmoHeader; + // Text of the WMO header + @Transient + @XmlAttribute + @DynamicSerializeElement + private String wmoHeader; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView = null; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView = null; - @ManyToOne(cascade = { CascadeType.REFRESH }) - @PrimaryKeyJoinColumn - @DataURI(position = 1, embedded = true) - @XmlElement - @DynamicSerializeElement - private BufrMosDataLocation location; + @ManyToOne(cascade = { CascadeType.REFRESH }) + @PrimaryKeyJoinColumn + @DataURI(position = 1, embedded = true) + @XmlElement + @DynamicSerializeElement + private BufrMosDataLocation location; - /** - * Create an empty MOSData object. - */ - public BufrMosData() { - this.pluginName = "bufrmos" + getType(); - } + /** + * Create an empty MOSData object. + */ + public BufrMosData() { + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public BufrMosData(String uri) { - super(uri); - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public BufrMosData(String uri) { + super(uri); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } - /** - * @return the type - */ - public abstract MOSType getType(); + /** + * @return the type + */ + public abstract MOSType getType(); - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * - * @param dataURI - */ - @Override - public void setDataURI(String dataURI) { - identifier = dataURI; - } + /** + * + * @param dataURI + */ + @Override + public void setDataURI(String dataURI) { + identifier = dataURI; + } - public BufrMosDataLocation getLocation() { - return location; - } + public BufrMosDataLocation getLocation() { + return location; + } - public void setLocation(BufrMosDataLocation mosLocation) { - this.location = mosLocation; - } + public void setLocation(BufrMosDataLocation mosLocation) { + this.location = mosLocation; + } - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - } + @Override + public String getPluginName() { + return "bufrmos" + getType(); + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.bufrua/src/com/raytheon/edex/plugin/bufrua/decoder/AbstractBUFRUAAdapter.java b/edexOsgi/com.raytheon.edex.plugin.bufrua/src/com/raytheon/edex/plugin/bufrua/decoder/AbstractBUFRUAAdapter.java index 33a15728a1..fae74720fd 100644 --- a/edexOsgi/com.raytheon.edex.plugin.bufrua/src/com/raytheon/edex/plugin/bufrua/decoder/AbstractBUFRUAAdapter.java +++ b/edexOsgi/com.raytheon.edex.plugin.bufrua/src/com/raytheon/edex/plugin/bufrua/decoder/AbstractBUFRUAAdapter.java @@ -51,6 +51,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * Mar 03, 2008 969 jkorman Initial implementation. * May 09, 2013 1869 bsteffen Modified D2D time series of point data to * work without dataURI. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -110,7 +111,6 @@ public abstract class AbstractBUFRUAAdapter extends BUFRPointDataAdapter if ((obsData != null) && (wmoStaId != null)) { // pickup the data. - obsData.setPluginName(getPluginName()); obsData.setWmoHeader(wmoHeader.getWmoHeader()); Calendar validTime = obsData.getValidTime(); diff --git a/edexOsgi/com.raytheon.edex.plugin.ccfp/src/com/raytheon/edex/plugin/ccfp/CcfpDecoder.java b/edexOsgi/com.raytheon.edex.plugin.ccfp/src/com/raytheon/edex/plugin/ccfp/CcfpDecoder.java index 494b368d88..7dd70eccd7 100644 --- a/edexOsgi/com.raytheon.edex.plugin.ccfp/src/com/raytheon/edex/plugin/ccfp/CcfpDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.ccfp/src/com/raytheon/edex/plugin/ccfp/CcfpDecoder.java @@ -43,11 +43,12 @@ import com.vividsolutions.jts.io.WKTReader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 03/03/2007 908 bwoodle initial creation - * 12/03/2008 chammack Camel refactor - * 09/15/2009 3027 njensen Patterns constants - * 09/21/2009 3072 bsteffen Fixed Decoding of Line Records - * 01/02/2013 DCS 135 tk handle coverage value Line records + * Mar 03, 2007 908 bwoodle initial creation + * Dec 03, 2008 chammack Camel refactor + * Sep 15, 2009 3027 njensen Patterns constants + * Sep 21, 2009 3072 bsteffen Fixed Decoding of Line Records + * Jan 02, 2013 DCS 135 tk handle coverage value Line records + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -86,7 +87,8 @@ public class CcfpDecoder extends AbstractDecoder { private static final String SPACE = " "; - private static final PluginDataObject [] EMPTY_PDO = new PluginDataObject [0]; + private static final PluginDataObject[] EMPTY_PDO = new PluginDataObject[0]; + /** * Constructor * @@ -95,10 +97,11 @@ public class CcfpDecoder extends AbstractDecoder { public CcfpDecoder() throws DecoderException { } - public PluginDataObject[] decode(String msg, Headers headers) throws PluginException { + public PluginDataObject[] decode(String msg, Headers headers) + throws PluginException { + + PluginDataObject[] data = null; - PluginDataObject [] data = null; - Calendar baseTime = null; WMOHeader wmoHdr = new WMOHeader(msg.getBytes()); if (wmoHdr.isValid()) { @@ -106,7 +109,7 @@ public class CcfpDecoder extends AbstractDecoder { } else { baseTime = TimeTools.getSystemCalendar(); } - + CcfpRecord record = new CcfpRecord(); record.setMessageData(msg); CcfpLocation location = new CcfpLocation(); @@ -116,18 +119,20 @@ public class CcfpDecoder extends AbstractDecoder { try { WKTReader wktReader = new WKTReader(); if (matcher.find()) { - Calendar start = TimeTools.getBaseCalendar(Integer - .parseInt(matcher.group(1)), Integer.parseInt(matcher - .group(2)), Integer.parseInt(matcher.group(3))); - start.set(Calendar.HOUR_OF_DAY, Integer.parseInt(matcher - .group(4))); - Calendar valid = TimeTools.getBaseCalendar(Integer - .parseInt(matcher.group(5)), Integer.parseInt(matcher - .group(6)), Integer.parseInt(matcher.group(7))); - valid.set(Calendar.HOUR_OF_DAY, Integer.parseInt(matcher - .group(8))); - TimeRange range = new TimeRange(start.getTime(), valid - .getTime()); + Calendar start = TimeTools.getBaseCalendar( + Integer.parseInt(matcher.group(1)), + Integer.parseInt(matcher.group(2)), + Integer.parseInt(matcher.group(3))); + start.set(Calendar.HOUR_OF_DAY, + Integer.parseInt(matcher.group(4))); + Calendar valid = TimeTools.getBaseCalendar( + Integer.parseInt(matcher.group(5)), + Integer.parseInt(matcher.group(6)), + Integer.parseInt(matcher.group(7))); + valid.set(Calendar.HOUR_OF_DAY, + Integer.parseInt(matcher.group(8))); + TimeRange range = new TimeRange(start.getTime(), + valid.getTime()); record.setDataTime(new DataTime(start.getTime().getTime(), range)); record.setProducttype(matcher.group(9)); @@ -147,8 +152,7 @@ public class CcfpDecoder extends AbstractDecoder { record.setTops(Integer.parseInt(matcher.group(4))); record.setSpeed(Integer.parseInt(matcher.group(5))); record.setDirection(Integer.parseInt(matcher.group(6))); - location - .setBoxLat(Double.parseDouble(matcher.group(8)) * 0.1); + location.setBoxLat(Double.parseDouble(matcher.group(8)) * 0.1); location.setBoxLong(Double.parseDouble(matcher.group(9)) * -0.1); String templatlonpairs = matcher.group(7); @@ -157,8 +161,7 @@ public class CcfpDecoder extends AbstractDecoder { wtk.append("POLYGON(("); if (matcher.find()) { wtk.append(Double.toString(Integer.parseInt(matcher - .group(2)) - * -0.1)); + .group(2)) * -0.1)); wtk.append(SPACE); wtk.append(Double.toString(Integer.parseInt(matcher .group(1)) * 0.1)); @@ -167,8 +170,7 @@ public class CcfpDecoder extends AbstractDecoder { wtk.append(COMMA); wtk.append(SPACE); wtk.append(Double.toString(Integer.parseInt(matcher - .group(2)) - * -0.1)); + .group(2)) * -0.1)); wtk.append(SPACE); wtk.append(Double.toString(Integer.parseInt(matcher .group(1)) * 0.1)); @@ -180,30 +182,30 @@ public class CcfpDecoder extends AbstractDecoder { } else if (record.getProducttype().equals("LINE")) { matcher = LINE_PATTERN.matcher(msg); if (matcher.find()) { - record.setCoverage(Integer.parseInt(matcher.group(1))); // change to group 1 + // change to group 1 + record.setCoverage(Integer.parseInt(matcher.group(1))); record.setConf(null); record.setGrowth(null); record.setTops(null); record.setSpeed(null); record.setDirection(null); - String templatlonpairs = matcher.group(2); // change to group 2 + // change to group 2 + String templatlonpairs = matcher.group(2); matcher = PAIR_PATTERN.matcher(templatlonpairs); StringBuffer wtk = new StringBuffer(); wtk.append("LINESTRING("); if (matcher.find()) { - - Double lon = Integer.parseInt(matcher - .group(2)) * -0.1; + + Double lon = Integer.parseInt(matcher.group(2)) * -0.1; String lonStr = Double.toString(lon); - Double lat = Integer.parseInt(matcher - .group(1)) * 0.1; + Double lat = Integer.parseInt(matcher.group(1)) * 0.1; String latStr = Double.toString(lat); location.setBoxLong(lon); location.setBoxLat(lat); - + wtk.append(lonStr); wtk.append(SPACE); wtk.append(latStr); @@ -212,8 +214,7 @@ public class CcfpDecoder extends AbstractDecoder { wtk.append(COMMA); wtk.append(SPACE); wtk.append(Double.toString(Integer.parseInt(matcher - .group(2)) - * -0.1)); + .group(2)) * -0.1)); wtk.append(SPACE); wtk.append(Double.toString(Integer.parseInt(matcher .group(1)) * 0.1)); @@ -228,8 +229,7 @@ public class CcfpDecoder extends AbstractDecoder { logger.error("Unable to decode CCFP", e); } data = EMPTY_PDO; - if(record != null) { - record.setPluginName(PLUGIN_NAME); + if (record != null) { try { record.constructDataURI(); record.setInsertTime(baseTime); diff --git a/edexOsgi/com.raytheon.edex.plugin.ccfp/src/com/raytheon/edex/plugin/ccfp/CcfpRecord.java b/edexOsgi/com.raytheon.edex.plugin.ccfp/src/com/raytheon/edex/plugin/ccfp/CcfpRecord.java index a88e9ffa48..340a2922a7 100644 --- a/edexOsgi/com.raytheon.edex.plugin.ccfp/src/com/raytheon/edex/plugin/ccfp/CcfpRecord.java +++ b/edexOsgi/com.raytheon.edex.plugin.ccfp/src/com/raytheon/edex/plugin/ccfp/CcfpRecord.java @@ -51,13 +51,16 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 03/03/2007 908 bwoodle initial creation - * 09/15/2009 3027 njensen Use dates for times - * 09/21/2009 3072 bsteffen Removed times because they are stored in DataTime - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime + * Mar 03, 2007 908 bwoodle initial creation + * Sep 15, 2009 3027 njensen Use dates for times + * Sep 21, 2009 3072 bsteffen Removed times because they are stored in + * DataTime + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -72,12 +75,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ccfp", - indexes = { - @Index(name = "ccfp_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ccfp", indexes = { @Index(name = "ccfp_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -299,4 +298,9 @@ public class CcfpRecord extends PluginDataObject implements ISpatialEnabled { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ccfp"; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFED2DDao.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFED2DDao.java index be7fe5a742..e68d4a8a47 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFED2DDao.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFED2DDao.java @@ -48,14 +48,17 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 03/20/13 #1774 randerso Refactored out of GFEDao - * 04/04/13 #1787 randerso Fixed to support changes to D2D grid location - * Additional cleanup to move the D2D to GFE translation - * logic into D2DGridDatabase. - * 05/03/13 #1974 randerso Changed queryByParmId to look for parm with duration - * suffix first. - * 05/22/13 #1974 randerso Fix bug introduced by the previous fix where query for - * T (T%hr) returned TP6hr + * Mar 20, 2013 1774 randerso Refactored out of GFEDao + * Apr 04, 2013 1787 randerso Fixed to support changes to D2D grid + * location Additional cleanup to move the + * D2D to GFE translation logic into + * D2DGridDatabase. + * May 03, 2013 1974 randerso Changed queryByParmId to look for parm + * with duration suffix first. + * May 22, 2013 1974 randerso Fix bug introduced by the previous fix + * where query for T (T%hr) returned TP6hr + * Jun 13, 2013 2044 randerso Cleaned up JavaDoc + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -135,7 +138,6 @@ public class GFED2DDao extends GridDao { GridRecord retVal = (GridRecord) s.get(GridRecord.class, rawTimes.get(forecastTime)); - retVal.setPluginName(GridConstants.GRID); return retVal; } finally { diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java index 5ea9c066f0..619a4f31ff 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java @@ -95,6 +95,7 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery; * 05/20/13 #2127 rjpeter Set session's to read only and switched to stateless where possible. * 08/08/13 DR16485 ryu Remove call to getDatabaseId() from getMaxInsertTimeByDbId() * so new GFE databases aren't accidentally created. + * 09/30/2013 #2147 rferrel Changes to archive hdf5 files. * * * @author bphillip @@ -106,6 +107,7 @@ public class GFEDao extends DefaultPluginDao { public GFEDao() throws PluginException { super("gfe"); + this.pathProvider = new GFEPathProvider(); } /** @@ -115,6 +117,7 @@ public class GFEDao extends DefaultPluginDao { */ public GFEDao(String pluginName) throws PluginException { super(pluginName); + this.pathProvider = new GFEPathProvider(); } /** diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEPathProvider.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEPathProvider.java new file mode 100644 index 0000000000..9a0d37c4e5 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEPathProvider.java @@ -0,0 +1,97 @@ +/** + * 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.edex.plugin.gfe.db.dao; + +import java.io.File; + +import com.raytheon.edex.plugin.gfe.server.database.GridDatabase; +import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord; +import com.raytheon.uf.common.dataplugin.gfe.util.GfeUtil; +import com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider; +import com.raytheon.uf.common.dataplugin.persist.IPersistable; + +/** + * Provider for GFE that uses the GfeUtil to get the HDF5 path and file names. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Sep 23, 2013            rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public class GFEPathProvider extends DefaultPathProvider { + + /** + * Constructor. + */ + public GFEPathProvider() { + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider#getHDFFileName + * (java.lang.String, + * com.raytheon.uf.common.dataplugin.persist.IPersistable) + */ + @Override + public String getHDFFileName(String pluginName, IPersistable persistable) { + String name = null; + if (persistable instanceof GFERecord) { + GFERecord gfeRecord = (GFERecord) persistable; + File hdf5File = GfeUtil.getHdf5File(GridDatabase.gfeBaseDataDir, + gfeRecord.getParmId(), gfeRecord.getTimeRange()); + name = hdf5File.toString(); + name = name.substring(name.lastIndexOf(File.separator) + 1); + } + return name; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider#getHDFPath + * (java.lang.String, + * com.raytheon.uf.common.dataplugin.persist.IPersistable) + */ + @Override + public String getHDFPath(String pluginName, IPersistable persistable) { + String path = null; + path = super.getHDFPath(pluginName, persistable); + if (persistable instanceof GFERecord) { + GFERecord gfeRecord = (GFERecord) persistable; + File pathDir = GfeUtil.getHdf5Dir(GridDatabase.gfeBaseDataDir, + gfeRecord.getDbId()); + path = pathDir.toString(); + path = path.substring(pluginName.length() + 1); + } + return path; + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.goessounding/src/com/raytheon/edex/plugin/goessounding/GOESSoundingDecoder.java b/edexOsgi/com.raytheon.edex.plugin.goessounding/src/com/raytheon/edex/plugin/goessounding/GOESSoundingDecoder.java index dc928a2ffb..58719652ca 100644 --- a/edexOsgi/com.raytheon.edex.plugin.goessounding/src/com/raytheon/edex/plugin/goessounding/GOESSoundingDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.goessounding/src/com/raytheon/edex/plugin/goessounding/GOESSoundingDecoder.java @@ -61,6 +61,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * Apr 14, 2008 1077 jkorman Initial implementation. * Nov 25, 2008 1684 chammack Camel Refactor * May 15, 2013 1869 bsteffen Remove DataURI from goes/poes soundings. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -74,7 +75,7 @@ public class GOESSoundingDecoder extends AbstractDecoder implements public static final String PLUGIN_NAME = "goessounding"; /** The logger */ - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); private PointDataDescription pdd; @@ -131,7 +132,7 @@ public class GOESSoundingDecoder extends AbstractDecoder implements PluginDataObject[] decodedData = null; - if (input != null && input.getDocumentData().length > 0) { + if ((input != null) && (input.getDocumentData().length > 0)) { WMOHeader wmoHeader = input.getWmoHeader(); @@ -153,7 +154,6 @@ public class GOESSoundingDecoder extends AbstractDecoder implements container, this.pdd, dao); if (soundingData != null) { soundingData.setTraceId(traceId); - soundingData.setPluginName(PLUGIN_NAME); PointDataView pdv = soundingData.getPointDataView(); pdv.setString("wmoHeader", soundingData.getWmoHeader()); diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/GribDecoder.py b/edexOsgi/com.raytheon.edex.plugin.grib/GribDecoder.py index 4b8f61f5f2..d5a0190ae4 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/GribDecoder.py +++ b/edexOsgi/com.raytheon.edex.plugin.grib/GribDecoder.py @@ -70,8 +70,6 @@ from com.raytheon.uf.common.parameter import Parameter; from com.raytheon.uf.common.parameter.mapping import ParameterMapper; -PLUGIN_NAME = "grid" - # Static values for accessing parameter lookup tables PARAMETER_TABLE = "4.2" GENPROCESS_TABLE = "A" @@ -131,7 +129,7 @@ THINNED_GRID_VALUES = THINNED_GRID_PT_MAP.values() # 04/7/09 #1994 bphillip Initial Creation. # Mar 25, 2013 1821 bsteffen Reshape grib data arrays in # place to improve performance. -# +# Sep 04, 2013 2298 rjpeter Removed setPluginName call class GribDecoder(): ## @@ -403,7 +401,6 @@ class GribDecoder(): # Construct the GribRecord record = GridRecord() - record.setPluginName(PLUGIN_NAME) record.setDataTime(dataTime) record.setMessageData(numpyDataArray) record.setLocation(gdsSectionValues['coverage']) diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/Grib1Decoder.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/Grib1Decoder.java index 928f65818c..bfcba2b243 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/Grib1Decoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/Grib1Decoder.java @@ -92,8 +92,10 @@ import com.raytheon.uf.common.util.mapping.MultipleMappingException; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 3/11/10 4758 bphillip Initial Creation - * Feb 15, 2013 1638 mschenke Moved array based utilities from Util into ArraysUtil + * Mar 11, 2010 4758 bphillip Initial Creation + * Feb 15, 2013 1638 mschenke Moved array based utilities from Util + * into ArraysUtil + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -236,7 +238,7 @@ public class Grib1Decoder extends AbstractDecoder { .getGrib2Parameter(centerAlias, subcenterAlias, tableAlias, pdsVars.getParameterNumber()); - if (parameter == null || parameter.getName().equals(MISSING)) { + if ((parameter == null) || parameter.getName().equals(MISSING)) { try { logger.warn("Unable to map Grib 1 parameter to equivalent Grib 2 parameter for center [" + centerid @@ -294,7 +296,7 @@ public class Grib1Decoder extends AbstractDecoder { // unidata does not handle isEnsemble call when // octet size is less than 40. - if (pdsVars.getLength() > 40 && pdsVars.isEnsemble()) { + if ((pdsVars.getLength() > 40) && pdsVars.isEnsemble()) { // rcg: added code to get perturbation int pos42 = pdsVars.getOctet(42); int pos43 = pdsVars.getOctet(43); @@ -363,13 +365,13 @@ public class Grib1Decoder extends AbstractDecoder { int timeRange = pdsVars.getTimeRangeIndicator(); // Check for initialization of average or accumulation parameters - if ((AVG_ACCUM_LIST.contains(timeRange) && dataTime - .getValidPeriod().getDuration() == 0)) { + if ((AVG_ACCUM_LIST.contains(timeRange) && (dataTime + .getValidPeriod().getDuration() == 0))) { statusHandler.handle(Priority.EVENTA, "Discarding empty accumulation grid"); return null; - } else if ((gdsVars != null && gdsVars.isThin()) - || (gdsVars == null && (gridCoverage instanceof LatLonGridCoverage && ((LatLonGridCoverage) gridCoverage) + } else if (((gdsVars != null) && gdsVars.isThin()) + || ((gdsVars == null) && ((gridCoverage instanceof LatLonGridCoverage) && ((LatLonGridCoverage) gridCoverage) .isThin()))) { // Unfortunately the UCAR Decoder does Cubic Spline // interpolation, however we want to do simpler linear @@ -468,7 +470,7 @@ public class Grib1Decoder extends AbstractDecoder { if (newAbbr == null) { if (!parameterName.equals(MISSING) - && dataTime.getValidPeriod().getDuration() > 0) { + && (dataTime.getValidPeriod().getDuration() > 0)) { parameterAbbreviation = parameterAbbreviation + String.valueOf(dataTime.getValidPeriod() .getDuration() / 3600000) + "hr"; @@ -485,7 +487,6 @@ public class Grib1Decoder extends AbstractDecoder { parameterAbbreviation = e.getArbitraryMapping(); } - retVal.setPluginName("grid"); Parameter param = new Parameter(parameterAbbreviation, parameterName, parameterUnit); GribParamTranslator.getInstance().getParameterNameAlias(modelName, @@ -530,7 +531,7 @@ public class Grib1Decoder extends AbstractDecoder { for (int row = 0; row < rowCount; row++) { for (int column = 0; column < columnCount; column++) { - newGrid[row][column] = data[row * columnCount + column]; + newGrid[row][column] = data[(row * columnCount) + column]; } } @@ -569,8 +570,8 @@ public class Grib1Decoder extends AbstractDecoder { total -= 1; trail = inData[inIndex++]; } - outData[outIndex++] = inData[inIndex] * total + trail - * (1 - total); + outData[outIndex++] = (inData[inIndex] * total) + + (trail * (1 - total)); total += dx; } outData[outIndex++] = inData[inIndex++]; @@ -594,7 +595,7 @@ public class Grib1Decoder extends AbstractDecoder { for (int row = 0; row < rowCount; row++) { for (int column = 0; column < columnCount; column++) { - newGrid[row * columnCount + column] = data[row][column]; + newGrid[(row * columnCount) + column] = data[row][column]; } } return newGrid; @@ -663,7 +664,7 @@ public class Grib1Decoder extends AbstractDecoder { private void correctForScanMode(float[] data, int nx, int ny, boolean bmsExists, int scanMode) { for (int i = 0; i < data.length; i++) { - if (bmsExists && data[i] == -9999) { + if (bmsExists && (data[i] == -9999)) { data[i] = -999999; } } @@ -884,7 +885,7 @@ public class Grib1Decoder extends AbstractDecoder { GridCoverage grid = GribSpatialCache.getInstance().getGrid(coverage); - if (grid == null && gridNumber != 255) { + if ((grid == null) && (gridNumber != 255)) { // 255 is specifically reserved to non-defined grids and should not // use the gridNumber as a lookup value @@ -929,7 +930,7 @@ public class Grib1Decoder extends AbstractDecoder { int subcenterId, int process, GridCoverage grid) { GridModel gridModel = GribModelLookup.getInstance().getModel(centerId, subcenterId, grid, process); - if (gridModel != null && gridModel.getAnalysisOnly()) { + if ((gridModel != null) && gridModel.getAnalysisOnly()) { time.getUtilityFlags().remove(FLAG.FCST_USED); } } @@ -1175,7 +1176,7 @@ public class Grib1Decoder extends AbstractDecoder { level1Value = lval1; break; default: - if (ltype1 > 99 && ltype1 < 200) { + if ((ltype1 > 99) && (ltype1 < 200)) { level1Type = 255; logger.warn("GRIB1 level " + ltype1 + " not recognized"); } @@ -1234,7 +1235,7 @@ public class Grib1Decoder extends AbstractDecoder { } // Scale the level one value if necessary - if (scaleFactor1 == 0 || value1 == 0) { + if ((scaleFactor1 == 0) || (value1 == 0)) { levelOneValue = value1; } else { levelOneValue = new Double((float) (value1 * Math.pow(10, @@ -1249,13 +1250,13 @@ public class Grib1Decoder extends AbstractDecoder { } else if (levelTwoNumber == 1) { levelTwoValue = Level.getInvalidLevelValue(); } else { - if (scaleFactor2 == 0 || value2 == 0) { + if ((scaleFactor2 == 0) || (value2 == 0)) { levelTwoValue = value2; } else { levelTwoValue = (value2 * Math.pow(10, scaleFactor2 * -1)); } } - if (levelName.equals("SFC") && levelOneValue != 0) { + if (levelName.equals("SFC") && (levelOneValue != 0)) { levelOneValue = 0.0; } if (levelName.equals("EATM")) { @@ -1289,7 +1290,7 @@ public class Grib1Decoder extends AbstractDecoder { } if (lon >= 180) { - lon = (180 - lon % 180) * -1; + lon = (180 - (lon % 180)) * -1; } else if (lon < -180) { lon = (180 - (-lon % 180)); } @@ -1313,7 +1314,7 @@ public class Grib1Decoder extends AbstractDecoder { } if (lat > 90) { - lat = 90 - lat % 90; + lat = 90 - (lat % 90); } else if (lat < -90) { lat = (90 - (-lat % 90)) * -1; } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/GridToGribConverter.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/GridToGribConverter.java index f5a6dcad2e..96c02d3394 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/GridToGribConverter.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/GridToGribConverter.java @@ -35,7 +35,8 @@ import com.raytheon.uf.edex.database.DataAccessLayerException; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * May 4, 2012 bsteffen Initial creation + * May 04, 2012 bsteffen Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -62,10 +63,9 @@ public class GridToGribConverter { GridRecord grid = records[i]; GribRecord grib = new GribRecord(); GribModel model = new GribModel(); - grib.setPluginName("grib"); grib.setDataTime(grid.getDataTime()); model.setModelName(grid.getDatasetId()); - if (grid.getSecondaryId() != null + if ((grid.getSecondaryId() != null) && grid.getSecondaryId().startsWith("Version")) { grib.setGridVersion(Integer.parseInt(grid.getSecondaryId() .replace("Version", ""))); @@ -108,31 +108,31 @@ public class GridToGribConverter { model.setTypeEnsemble(3); } Object centerid = grid.getExtraAttribute("centerid"); - if (centerid != null && centerid instanceof Integer) { + if ((centerid != null) && (centerid instanceof Integer)) { model.setCenterid((Integer) centerid); } Object subcenterid = grid.getExtraAttribute("subcenterid"); - if (subcenterid != null && subcenterid instanceof Integer) { + if ((subcenterid != null) && (subcenterid instanceof Integer)) { model.setSubcenterid((Integer) subcenterid); } Object genprocess = grid.getExtraAttribute("genprocess"); - if (genprocess != null && genprocess instanceof Integer) { + if ((genprocess != null) && (genprocess instanceof Integer)) { model.setGenprocess((Integer) genprocess); } Object backGenprocess = grid.getExtraAttribute("backGenprocess"); - if (backGenprocess != null && backGenprocess instanceof Integer) { + if ((backGenprocess != null) && (backGenprocess instanceof Integer)) { model.setBackGenprocess((Integer) backGenprocess); } Object pdsTemplate = grid.getExtraAttribute("pdsTemplate"); - if (pdsTemplate != null && pdsTemplate instanceof Integer) { + if ((pdsTemplate != null) && (pdsTemplate instanceof Integer)) { model.setPdsTemplate((Integer) pdsTemplate); } Object gridid = grid.getExtraAttribute("gridid"); - if (gridid != null && gridid instanceof String) { + if ((gridid != null) && (gridid instanceof String)) { model.setGridid((String) gridid); } Object numForecasts = grid.getExtraAttribute("numForecasts"); - if (numForecasts != null && numForecasts instanceof Integer) { + if ((numForecasts != null) && (numForecasts instanceof Integer)) { model.setNumForecasts((Integer) numForecasts); } model.setLevel(grid.getLevel()); diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CPCoutlookGribPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CPCoutlookGribPostProcessor.java index 68b69a2195..93278b301f 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CPCoutlookGribPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CPCoutlookGribPostProcessor.java @@ -24,7 +24,6 @@ import java.util.Calendar; import com.raytheon.edex.plugin.grib.exception.GribException; import com.raytheon.uf.common.dataplugin.PluginException; -import com.raytheon.uf.common.dataplugin.grid.GridConstants; import com.raytheon.uf.common.dataplugin.grid.GridRecord; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -51,7 +50,8 @@ import com.raytheon.uf.common.time.DataTime; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 03/09/11 4243 porricel Initial Creation + * Mar 09, 2011 4243 porricel Initial Creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -84,7 +84,6 @@ public class CPCoutlookGribPostProcessor implements IDecoderPostProcessor { record.setDataURI(null); try { - record.setPluginName(GridConstants.GRID); record.constructDataURI(); } catch (PluginException e) { statusHandler.handle(Priority.PROBLEM, diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/EnsembleGridAssembler.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/EnsembleGridAssembler.java index f7ea833ca0..2316f22239 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/EnsembleGridAssembler.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/EnsembleGridAssembler.java @@ -69,10 +69,11 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 4/09/10 4638 bphillip Initial Creation + * Apr 09, 2010 4638 bphillip Initial Creation * Mar 14, 2013 1794 djohnson FileUtil.listFiles now returns List. * Mar 27, 2013 1821 bsteffen Reduce db and pypies requests in grid * assembler. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -231,7 +232,6 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor { newRecord.setEnsembleId(record.getEnsembleId()); newRecord.setDataTime(record.getDataTime()); newRecord.setDataURI(null); - newRecord.setPluginName(GridConstants.GRID); newRecord.setInsertTime(Calendar.getInstance()); try { newRecord.constructDataURI(); @@ -319,7 +319,7 @@ public class EnsembleGridAssembler implements IDecoderPostProcessor { } else { Util.insertSubgrid(assembledData, Util.resizeDataTo2D( (float[]) record.getMessageData(), coverage.getNx(), - coverage.getNy()), nx * modIndex - modIndex, 0, nx, ny); + coverage.getNy()), (nx * modIndex) - modIndex, 0, nx, ny); } assembledRecord.setMessageData(Util.resizeDataTo1D(assembledData, diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GFSProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GFSProcessor.java index 39bb547b18..fcb8386692 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GFSProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GFSProcessor.java @@ -53,6 +53,7 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 25, 2011 rgeorge Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -69,7 +70,7 @@ public class GFSProcessor extends SixHrPrecipGridProcessor { public GridRecord[] process(GridRecord record) throws GribException { // Post process the data if this is a Total Precipitation grid if (record.getParameter().getAbbreviation().equals("TP12hr") - && record.getDataTime().getFcstTime() / 3600 > 180) { + && ((record.getDataTime().getFcstTime() / 3600) > 180)) { return super.process(record); } return new GridRecord[] { record }; @@ -86,6 +87,7 @@ public class GFSProcessor extends SixHrPrecipGridProcessor { * @return The generated 6-hr precipitation grids * @throws GribException */ + @Override protected synchronized GridRecord[] generate6hrPrecipGrids(GridRecord record) throws GribException { List generated6hrPrecips = new ArrayList(); @@ -111,11 +113,11 @@ public class GFSProcessor extends SixHrPrecipGridProcessor { Collections.sort(precipInventory, comparator); // loop through set, find twelve hour gaps and create new 6hr records. - for (int i = 0; i < precipInventory.size() - 1; i++) { + for (int i = 0; i < (precipInventory.size() - 1); i++) { GridRecord sequence1Record = precipInventory.get(i); GridRecord sequence2Record = precipInventory.get(i + 1); - if (sequence1Record.getDataTime().getFcstTime() == sequence2Record - .getDataTime().getFcstTime() - SECONDS_IN_12_HRS) { + if (sequence1Record.getDataTime().getFcstTime() == (sequence2Record + .getDataTime().getFcstTime() - SECONDS_IN_12_HRS)) { // we have a 12Hr gap generated6hrPrecips.add(calculate6hrPrecip(sequence1Record, sequence2Record)); @@ -226,7 +228,6 @@ public class GFSProcessor extends SixHrPrecipGridProcessor { record.setDataTime(newDataTime); record.setDataURI(null); try { - record.setPluginName(GridConstants.GRID); record.constructDataURI(); } catch (PluginException e) { statusHandler.handle(Priority.PROBLEM, diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/Nam80PostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/Nam80PostProcessor.java index 8e1ccf307c..0819c6dd0c 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/Nam80PostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/Nam80PostProcessor.java @@ -47,7 +47,8 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Nov 17, 2011 bphillip Initial creation + * Nov 17, 2011 bphillip Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -169,14 +170,14 @@ public class Nam80PostProcessor implements IDecoderPostProcessor { float[] newData = null; float[] tp6Data = null; if (tp12HrRecord.getMessageData() == null) { - newData = (float[]) ((FloatDataRecord) dao.getHDF5Data( - tp12HrRecord, -1)[0]).getFloatData(); + newData = ((FloatDataRecord) dao.getHDF5Data(tp12HrRecord, -1)[0]) + .getFloatData(); } else { newData = (float[]) tp12HrRecord.getMessageData(); } if (tp6HrRecord.getMessageData() == null) { - tp6Data = (float[]) ((FloatDataRecord) dao.getHDF5Data( - tp6HrRecord, -1)[0]).getFloatData(); + tp6Data = ((FloatDataRecord) dao.getHDF5Data(tp6HrRecord, -1)[0]) + .getFloatData(); } else { tp6Data = (float[]) tp6HrRecord.getMessageData(); } @@ -197,7 +198,7 @@ public class Nam80PostProcessor implements IDecoderPostProcessor { Calendar refTime = tp12HrRecord.getDataTime().getRefTimeAsCalendar(); Date start = new Date(tp12HrRecord.getDataTime().getValidPeriod() .getEnd().getTime() - - SECONDS_IN_6_HRS * 1000); + - (SECONDS_IN_6_HRS * 1000)); DataTime newDataTime = new DataTime(refTime, tp12HrRecord.getDataTime() .getFcstTime(), new TimeRange(start, tp12HrRecord.getDataTime() @@ -208,7 +209,6 @@ public class Nam80PostProcessor implements IDecoderPostProcessor { newRecord.getInfo().setId(null); newRecord.setDataURI(null); try { - newRecord.setPluginName(GridConstants.GRID); newRecord.constructDataURI(); } catch (PluginException e) { throw new GribException("Error constructing dataURI!", e); diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/SixHrPrecipGridProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/SixHrPrecipGridProcessor.java index ba46ff2b56..404fd23597 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/SixHrPrecipGridProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/SixHrPrecipGridProcessor.java @@ -26,7 +26,6 @@ import java.util.List; import com.raytheon.edex.plugin.grib.exception.GribException; import com.raytheon.uf.common.dataplugin.PluginException; -import com.raytheon.uf.common.dataplugin.grid.GridConstants; import com.raytheon.uf.common.dataplugin.grid.GridRecord; import com.raytheon.uf.common.datastorage.records.FloatDataRecord; import com.raytheon.uf.common.parameter.Parameter; @@ -48,6 +47,7 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 25, 2011 rgeorge Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -107,8 +107,7 @@ public abstract class SixHrPrecipGridProcessor implements IDecoderPostProcessor // previous grid else { for (GridRecord rec : precipInventory) { - if (rec.getDataTime().getFcstTime() == currentFcstTime - - SECONDS_IN_6_HRS) { + if (rec.getDataTime().getFcstTime() == (currentFcstTime - SECONDS_IN_6_HRS)) { tp6hrRecords.add(calculate6hrPrecip(rec, record)); } } @@ -218,7 +217,6 @@ public abstract class SixHrPrecipGridProcessor implements IDecoderPostProcessor record.setDataTime(newDataTime); record.setDataURI(null); try { - record.setPluginName(GridConstants.GRID); record.constructDataURI(); } catch (PluginException e) { statusHandler.handle(Priority.PROBLEM, diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java index fb3dd3c854..fc51bd5885 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java @@ -26,7 +26,6 @@ import java.util.List; import com.raytheon.edex.plugin.grib.exception.GribException; import com.raytheon.uf.common.dataplugin.PluginException; -import com.raytheon.uf.common.dataplugin.grid.GridConstants; import com.raytheon.uf.common.dataplugin.grid.GridRecord; import com.raytheon.uf.common.datastorage.records.FloatDataRecord; import com.raytheon.uf.common.parameter.Parameter; @@ -47,7 +46,8 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 24, 2012 DR 14299 M. Porricelli Initial creation + * Jan 24, 2012 14299 M. Porricelli Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -108,8 +108,7 @@ public abstract class ThreeHrPrecipGridProcessor implements // previous grid else { for (GridRecord rec : precipInventory) { - if (rec.getDataTime().getFcstTime() == currentFcstTime - - SECONDS_IN_3_HRS) { + if (rec.getDataTime().getFcstTime() == (currentFcstTime - SECONDS_IN_3_HRS)) { tp3hrRecords.add(calculate3hrPrecip(rec, record)); } } @@ -220,7 +219,6 @@ public abstract class ThreeHrPrecipGridProcessor implements record.setDataTime(newDataTime); record.setDataURI(null); try { - record.setPluginName(GridConstants.GRID); record.constructDataURI(); } catch (PluginException e) { statusHandler.handle(Priority.PROBLEM, diff --git a/edexOsgi/com.raytheon.edex.plugin.ldadhydro/res/spring/ldadhydro-common.xml b/edexOsgi/com.raytheon.edex.plugin.ldadhydro/res/spring/ldadhydro-common.xml index 2213be0afe..df81cd861b 100644 --- a/edexOsgi/com.raytheon.edex.plugin.ldadhydro/res/spring/ldadhydro-common.xml +++ b/edexOsgi/com.raytheon.edex.plugin.ldadhydro/res/spring/ldadhydro-common.xml @@ -2,9 +2,6 @@ - - - @@ -12,12 +9,8 @@ - - - - + - diff --git a/edexOsgi/com.raytheon.edex.plugin.ldadhydro/res/spring/ldadhydro-ingest.xml b/edexOsgi/com.raytheon.edex.plugin.ldadhydro/res/spring/ldadhydro-ingest.xml index 3cfd3faf96..fda646aaea 100644 --- a/edexOsgi/com.raytheon.edex.plugin.ldadhydro/res/spring/ldadhydro-ingest.xml +++ b/edexOsgi/com.raytheon.edex.plugin.ldadhydro/res/spring/ldadhydro-ingest.xml @@ -4,9 +4,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - - + diff --git a/edexOsgi/com.raytheon.edex.plugin.ldadhydro/src/com/raytheon/edex/plugin/ldadhydro/dao/HydroDecoder.java b/edexOsgi/com.raytheon.edex.plugin.ldadhydro/src/com/raytheon/edex/plugin/ldadhydro/dao/HydroDecoder.java index c871cca1d3..46865d1d68 100644 --- a/edexOsgi/com.raytheon.edex.plugin.ldadhydro/src/com/raytheon/edex/plugin/ldadhydro/dao/HydroDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.ldadhydro/src/com/raytheon/edex/plugin/ldadhydro/dao/HydroDecoder.java @@ -64,9 +64,10 @@ import com.raytheon.uf.common.time.DataTime; * * SOFTWARE HISTORY * - * ate Ticket# Engineer Description - * ----------- ---------- ----------- -------------------------- - * 9/30/09 vkorolev Initial creation + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Sep 30, 2009 vkorolev Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * 10/16/13 DR 16685 M.Porricelli Add error checking for date * format * @@ -79,8 +80,6 @@ public class HydroDecoder extends AbstractDecoder implements IBinaryDecoder { private static final String BAD_PROPERTY_FMT = "NumberFormatException setting property %s.%s(%s %s)"; - private final String PLUGIN_NAME; - private String traceId = null; public SimpleDateFormat sdf = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); @@ -89,10 +88,6 @@ public class HydroDecoder extends AbstractDecoder implements IBinaryDecoder { public Properties configFile = new Properties(); - public HydroDecoder(String pluginName) throws DecoderException { - PLUGIN_NAME = pluginName; - } - public void setTraceId(String id) { traceId = id; } @@ -156,7 +151,6 @@ public class HydroDecoder extends AbstractDecoder implements IBinaryDecoder { HydroLdadRecord record = new HydroLdadRecord(); SurfaceObsLocation location = new SurfaceObsLocation(); record.setDataProvider(dd.provider); - record.setPluginName(PLUGIN_NAME); record.setStationType(dd.type); record.setReportTime(dd.reportTime); // Loop through fields @@ -332,8 +326,7 @@ public class HydroDecoder extends AbstractDecoder implements IBinaryDecoder { Class cls = record.getClass(); Field fieldlist[] = cls.getDeclaredFields(); - for (int i = 0; i < fieldlist.length; i++) { - Field fld = fieldlist[i]; + for (Field fld : fieldlist) { System.out.println("name = " + fld.getName()); // System.out.println("decl class = " + // fld.getDeclaringClass()); diff --git a/edexOsgi/com.raytheon.edex.plugin.ldadmanual/res/spring/ldadmanual-common.xml b/edexOsgi/com.raytheon.edex.plugin.ldadmanual/res/spring/ldadmanual-common.xml index 937888fc1c..5e9bde03fa 100644 --- a/edexOsgi/com.raytheon.edex.plugin.ldadmanual/res/spring/ldadmanual-common.xml +++ b/edexOsgi/com.raytheon.edex.plugin.ldadmanual/res/spring/ldadmanual-common.xml @@ -2,9 +2,6 @@ - - - @@ -12,9 +9,6 @@ - - - diff --git a/edexOsgi/com.raytheon.edex.plugin.ldadmanual/res/spring/ldadmanual-ingest.xml b/edexOsgi/com.raytheon.edex.plugin.ldadmanual/res/spring/ldadmanual-ingest.xml index 9bfdd35584..08bb3d9182 100644 --- a/edexOsgi/com.raytheon.edex.plugin.ldadmanual/res/spring/ldadmanual-ingest.xml +++ b/edexOsgi/com.raytheon.edex.plugin.ldadmanual/res/spring/ldadmanual-ingest.xml @@ -4,9 +4,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - - + diff --git a/edexOsgi/com.raytheon.edex.plugin.ldadmanual/src/com/raytheon/edex/plugin/ldadmanual/dao/ManualDecoder.java b/edexOsgi/com.raytheon.edex.plugin.ldadmanual/src/com/raytheon/edex/plugin/ldadmanual/dao/ManualDecoder.java index d2e88d62b6..7b1ac16bec 100644 --- a/edexOsgi/com.raytheon.edex.plugin.ldadmanual/src/com/raytheon/edex/plugin/ldadmanual/dao/ManualDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.ldadmanual/src/com/raytheon/edex/plugin/ldadmanual/dao/ManualDecoder.java @@ -27,7 +27,6 @@ import java.io.StringReader; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -63,9 +62,10 @@ import com.raytheon.uf.common.time.DataTime; * * SOFTWARE HISTORY * - * ate Ticket# Engineer Description - * ----------- ---------- ----------- -------------------------- - * 9/30/09 vkorolev Initial creation + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Sep 30, 2009 vkorolev Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author vkorolev @@ -73,9 +73,6 @@ import com.raytheon.uf.common.time.DataTime; */ public class ManualDecoder extends AbstractDecoder implements IBinaryDecoder { - - private final String PLUGIN_NAME; - private String traceId = null; public SimpleDateFormat sdf = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); @@ -84,10 +81,6 @@ public class ManualDecoder extends AbstractDecoder implements IBinaryDecoder public Properties configFile = new Properties(); - public ManualDecoder(String pluginName) throws DecoderException { - PLUGIN_NAME = pluginName; - } - public void setTraceId(String id) { traceId = id; } @@ -151,7 +144,6 @@ public class ManualDecoder extends AbstractDecoder implements IBinaryDecoder ManualLdadRecord record = new ManualLdadRecord(); SurfaceObsLocation location = new SurfaceObsLocation(); record.setProviderId(dd.provider); - record.setPluginName(PLUGIN_NAME); // record.setReportType???(dd.type)); // record.set???(dd.reportTime); // Loop through fields @@ -241,14 +233,13 @@ public class ManualDecoder extends AbstractDecoder implements IBinaryDecoder * @throws ClassNotFoundException * @throws Throwable */ - - @SuppressWarnings("unchecked") public void setProperty(String name, Object obj, String value, String vunit) { String prop = Character.toUpperCase(name.charAt(0)) + name.substring(1); String mname = "set" + prop; Object val = null; try { + @SuppressWarnings("rawtypes") Class cls = obj.getClass(); Field fld = cls.getDeclaredField(name); Class clazz = fld.getType(); @@ -301,27 +292,4 @@ public class ManualDecoder extends AbstractDecoder implements IBinaryDecoder } return; } - - // List of Fields in record - @SuppressWarnings("unchecked") - public static void main(String args[]) { - ManualLdadRecord record = new ManualLdadRecord(); - try { - Class cls = record.getClass(); - - Field fieldlist[] = cls.getDeclaredFields(); - for (int i = 0; i < fieldlist.length; i++) { - Field fld = fieldlist[i]; - System.out.println("name = " + fld.getName()); - // System.out.println("decl class = " + - // fld.getDeclaringClass()); - System.out.println("type = " + fld.getType()); - int mod = fld.getModifiers(); - System.out.println("modifiers = " + Modifier.toString(mod)); - System.out.println("-----"); - } - } catch (Throwable e) { - System.err.println(e); - } - } } diff --git a/edexOsgi/com.raytheon.edex.plugin.ldadmanual/src/com/raytheon/edex/plugin/ldadmanual/dao/ManualLdadRecord.java b/edexOsgi/com.raytheon.edex.plugin.ldadmanual/src/com/raytheon/edex/plugin/ldadmanual/dao/ManualLdadRecord.java index e68fdf830f..55473e338e 100644 --- a/edexOsgi/com.raytheon.edex.plugin.ldadmanual/src/com/raytheon/edex/plugin/ldadmanual/dao/ManualLdadRecord.java +++ b/edexOsgi/com.raytheon.edex.plugin.ldadmanual/src/com/raytheon/edex/plugin/ldadmanual/dao/ManualLdadRecord.java @@ -65,12 +65,13 @@ import com.vividsolutions.jts.geom.Geometry; * * Date Ticket# Engineer Description * ----------- ---------- ----------- -------------------------- - * 9/30/09 vkorolev Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. - * May 07, 2013 1869 bsteffen Remove dataURI column from + * Sep 30, 2009 vkorolev Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. - * + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author vkorolev @@ -84,25 +85,20 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ldad_manual", - indexes = { - @Index(name = "ldad_manual_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ldad_manual", indexes = { @Index(name = "ldad_manual_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize +public class ManualLdadRecord extends PluginDataObject implements + ISpatialEnabled, IDecoderGettable { -public class ManualLdadRecord extends PluginDataObject implements ISpatialEnabled, -IDecoderGettable { - private static final long serialVersionUID = 1L; public static final String OBS_TEXT = "text"; - + public static final Unit LENGTH_UNIT = SI.METER; - + public static final Unit TEMPERATURE_UNIT = SI.KELVIN; public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; @@ -124,727 +120,752 @@ IDecoderGettable { PARM_MAP.put("PMSL", PRES_SLP); PARM_MAP.put("NLAT", STA_LAT); PARM_MAP.put("NLON", STA_LON); - PARM_MAP.put("STA","STA"); - PARM_MAP.put("stationid","STA"); - PARM_MAP.put("message",OBS_TEXT); - PARM_MAP.put(OBS_TEXT,OBS_TEXT); + PARM_MAP.put("STA", "STA"); + PARM_MAP.put("stationid", "STA"); + PARM_MAP.put("message", OBS_TEXT); + PARM_MAP.put(OBS_TEXT, OBS_TEXT); } - // Time of the observation. @DataURI(position = 2) @Column @XmlAttribute @DynamicSerializeElement private Calendar observationTime; - - //Location + + // Location @Embedded @DataURI(position = 3, embedded = true) @XmlElement @DynamicSerializeElement - private SurfaceObsLocation location; //latitude, longitude, elevation, stationId - - //Provider of data + private SurfaceObsLocation location; // latitude, longitude, elevation, + // stationId + + // Provider of data @DataURI(position = 1) @Column @DynamicSerializeElement - @XmlElement - private String providerId; //* "050183" Data Provider - - //Name of station + @XmlElement + private String providerId; // * "050183" Data Provider + + // Name of station @Column @DynamicSerializeElement @XmlElement - private String stationName; //* "ALLENSPARK CO-OP" - - // Home WFO Id for the LDAD data + private String stationName; // * "ALLENSPARK CO-OP" + + // Home WFO Id for the LDAD data @Column @DynamicSerializeElement @XmlElement - private String homeWFO; //* "SJU" - - //Type of report + private String homeWFO; // * "SJU" + + // Type of report @Column @DynamicSerializeElement @XmlElement - private Short reportType; // short - // 1 - Regular - // 2 - Corrected - - //Units Code + private Short reportType; // short + // 1 - Regular + // 2 - Corrected + + // Units Code @Column @DynamicSerializeElement @XmlElement - private Short unitsCode; // short - // 8 - English - // 9 - Standard International - - //Current 24 hr precipitation total + private Short unitsCode; // short + // 8 - English + // 9 - Standard International + + // Current 24 hr precipitation total @Column @DynamicSerializeElement @XmlElement - private Float code10; // inches - - //Incremental precip since previous 7 a.m. + private Float code10; // inches + + // Incremental precip since previous 7 a.m. @Column @DynamicSerializeElement @XmlElement - private Float code11; // inches - - //Precip Criteria report from flash flood observer + private Float code11; // inches + + // Precip Criteria report from flash flood observer @Column @DynamicSerializeElement @XmlElement - private Float code12; // inches - - //4 hr precip total at previous 7 a.m. criteria report + private Float code12; // inches + + // 4 hr precip total at previous 7 a.m. criteria report @Column @DynamicSerializeElement @XmlElement - private Float code13; // inches - - //24 hr precipitation total at 7 a.m. 2 days ago + private Float code13; // inches + + // 24 hr precipitation total at 7 a.m. 2 days ago @Column @DynamicSerializeElement @XmlElement - private Float code14; // inches - - //Storm total precipitation + private Float code14; // inches + + // Storm total precipitation @Column @DynamicSerializeElement @XmlElement - private Float code15; // inches - - //Weekly total precipitation + private Float code15; // inches + + // Weekly total precipitation @Column @DynamicSerializeElement @XmlElement - private Float code16; // inches - - //Monthly total precipitation + private Float code16; // inches + + // Monthly total precipitation @Column @DynamicSerializeElement @XmlElement - private Float code17; // inches - - //Off-Time precipitation report + private Float code17; // inches + + // Off-Time precipitation report @Column @DynamicSerializeElement @XmlElement - private Float code18; // inches - - //Short intense precipitation durations + private Float code18; // inches + + // Short intense precipitation durations @Column @DynamicSerializeElement @XmlElement - private Float code19; // hours - - //Precipitation type + private Float code19; // hours + + // Precipitation type @Column @DynamicSerializeElement @XmlElement - private Short code20; // short - // 0 "Ice Prism" - // 1 "Rain" - // 2 "Freezing Rain" - // 3 "Drizzle" - // 4 "Freezing Drizzle" - // 5 "Snow" - // 6 "Snow Pellets" - // 7 "Snow Grains" - // 8 "Ice Pellets" - // 9 "Hail" - - //Current air temperature + private Short code20; // short + // 0 "Ice Prism" + // 1 "Rain" + // 2 "Freezing Rain" + // 3 "Drizzle" + // 4 "Freezing Drizzle" + // 5 "Snow" + // 6 "Snow Pellets" + // 7 "Snow Grains" + // 8 "Ice Pellets" + // 9 "Hail" + + // Current air temperature @Column @DynamicSerializeElement @XmlElement - private Float code21; // degrees F - - //Daily maximum air temperature + private Float code21; // degrees F + + // Daily maximum air temperature @Column @DynamicSerializeElement @XmlElement - private Float code22; // degrees F - - //Daily minimum air temperature + private Float code22; // degrees F + + // Daily minimum air temperature @Column @DynamicSerializeElement @XmlElement - private Float code23; // degrees F - - //Average weekly maximum air temperature + private Float code23; // degrees F + + // Average weekly maximum air temperature @Column @DynamicSerializeElement @XmlElement - private Float code24; // degrees F - - //Average weekly minimum air temperature + private Float code24; // degrees F + + // Average weekly minimum air temperature @Column @DynamicSerializeElement @XmlElement - private Float code25; // degrees F - - //Current water temperature + private Float code25; // degrees F + + // Current water temperature @Column @DynamicSerializeElement @XmlElement - private Float code26; // degrees F - - //Daily maximum soil temperature + private Float code26; // degrees F + + // Daily maximum soil temperature @Column @DynamicSerializeElement @XmlElement - private Float code27; // degrees F - - //Daily minimum soil temperature + private Float code27; // degrees F + + // Daily minimum soil temperature @Column @DynamicSerializeElement @XmlElement - private Float code28; // degrees F - - //Wet Bulb temperature + private Float code28; // degrees F + + // Wet Bulb temperature @Column @DynamicSerializeElement @XmlElement - private Float code29; // degrees F - - //Number of hours temperature is below 25 degrees F + private Float code29; // degrees F + + // Number of hours temperature is below 25 degrees F @Column @DynamicSerializeElement @XmlElement - private Float code30; // Hours - - //Number of hours temperature is below 32 degrees F + private Float code30; // Hours + + // Number of hours temperature is below 32 degrees F @Column @DynamicSerializeElement @XmlElement - private Float code31; // Hours - - //Dew point temperature + private Float code31; // Hours + + // Dew point temperature @Column @DynamicSerializeElement @XmlElement - private Float code32; // degrees F - - //River Stage at specified ob time + private Float code32; // degrees F + + // River Stage at specified ob time @Column @DynamicSerializeElement @XmlElement - private Float code33; // feet - - //River Stage at previous 1 a.m. + private Float code33; // feet + + // River Stage at previous 1 a.m. @Column @DynamicSerializeElement @XmlElement - private Float code34; // feet - - //River Stage at previous 7 p.m. + private Float code34; // feet + + // River Stage at previous 7 p.m. @Column @DynamicSerializeElement @XmlElement - private Float code35; // feet - - //River Stage at previous 1 p.m. + private Float code35; // feet + + // River Stage at previous 1 p.m. @Column @DynamicSerializeElement @XmlElement - private Float code36; // feet - - //River Stage at previous 7 a.m. + private Float code36; // feet + + // River Stage at previous 7 a.m. @Column @DynamicSerializeElement @XmlElement - private Float code37; // feet - - //River Stage at 7 a.m. 2 days ago + private Float code37; // feet + + // River Stage at 7 a.m. 2 days ago @Column @DynamicSerializeElement @XmlElement - private Float code38; // feet - - //River Stage at observed crest time + private Float code38; // feet + + // River Stage at observed crest time @Column @DynamicSerializeElement @XmlElement - private String code39; // char - // Chars0_1 "month" - // Chars2_3 "day" - // Chars4_5 "hour" - // Chars6_7 "minute" - - //River Stage at observed crest + private String code39; // char + // Chars0_1 "month" + // Chars2_3 "day" + // Chars4_5 "hour" + // Chars6_7 "minute" + + // River Stage at observed crest @Column @DynamicSerializeElement @XmlElement - private Float code40; // feet - - //River Stage Trend + private Float code40; // feet + + // River Stage Trend @Column @DynamicSerializeElement @XmlElement private Short code41; // short - // 0" "River below flood stage - Stationary" - // 1" "River below flood stage - Rising" - // 3" "River below flood stage - Falling" - // 4" "River above flood stage - Stationary" - // 5" "River above flood stage - Rising" - // 6" "River above flood stage - Falling" - - //private Double code42;--?????????????????????????????????????? - - //River Discharge instantaneous measured Kilo Cubic Feet Per Second + // 0" "River below flood stage - Stationary" + // 1" "River below flood stage - Rising" + // 3" "River below flood stage - Falling" + // 4" "River above flood stage - Stationary" + // 5" "River above flood stage - Rising" + // 6" "River above flood stage - Falling" + + // private Double code42;--?????????????????????????????????????? + + // River Discharge instantaneous measured Kilo Cubic Feet Per Second @Column @DynamicSerializeElement @XmlElement - private Float code43; // kcfs - - //River Discharge mean daily measured + private Float code43; // kcfs + + // River Discharge mean daily measured @Column @DynamicSerializeElement @XmlElement - private Float code44; // kcfs - - //River Discharge instantaneous computed + private Float code44; // kcfs + + // River Discharge instantaneous computed @Column @DynamicSerializeElement @XmlElement - private Float code45; // kcfs - - //River Discharge mean daily computed + private Float code45; // kcfs + + // River Discharge mean daily computed @Column @DynamicSerializeElement @XmlElement - private Float code46; // kcfs - - //River Discharge instantaneous from rating + private Float code46; // kcfs + + // River Discharge instantaneous from rating @Column @DynamicSerializeElement @XmlElement - private Float code47; // kcfs - - //River Discharge mean daily from rating + private Float code47; // kcfs + + // River Discharge mean daily from rating @Column @DynamicSerializeElement @XmlElement - private Float code48; // kcfs - - //River Discharge peak + private Float code48; // kcfs + + // River Discharge peak @Column @DynamicSerializeElement @XmlElement - private Float code49; // kcfs - - //River Discharge canal diversion + private Float code49; // kcfs + + // River Discharge canal diversion @Column @DynamicSerializeElement @XmlElement - private Float code50; // kcfs - - //private Float code51; //?????????????????????????????????? - - //Reservoir pool elevation at specified ob time + private Float code50; // kcfs + + // private Float code51; //?????????????????????????????????? + + // Reservoir pool elevation at specified ob time @Column @DynamicSerializeElement @XmlElement - private Float code52; // feet - - //Reservoir pool elevation at previous 6Z + private Float code52; // feet + + // Reservoir pool elevation at previous 6Z @Column @DynamicSerializeElement @XmlElement - private Float code53; // feet - - //Reservoir pool forecast, Day 1 + private Float code53; // feet + + // Reservoir pool forecast, Day 1 @Column @DynamicSerializeElement @XmlElement - private Float code54; // feet - - //Reservoir pool forecast, Day 2 + private Float code54; // feet + + // Reservoir pool forecast, Day 2 @Column @DynamicSerializeElement @XmlElement - private Float code55; // feet - - //Reservoir pool forecast, Day 3 + private Float code55; // feet + + // Reservoir pool forecast, Day 3 @Column @DynamicSerializeElement @XmlElement - private Float code56; // feet - - //Reservoir tailwater elevation + private Float code56; // feet + + // Reservoir tailwater elevation @Column @DynamicSerializeElement @XmlElement - private Float code57; // feet - - //Reservoir inflow, instantanious + private Float code57; // feet + + // Reservoir inflow, instantanious @Column @DynamicSerializeElement @XmlElement - private Float code58; // kcfs - - //Reservoir inflow, mean daily + private Float code58; // kcfs + + // Reservoir inflow, mean daily @Column @DynamicSerializeElement @XmlElement - private Float code59; // kcfs - - //Reservoir outflow, instantanious + private Float code59; // kcfs + + // Reservoir outflow, instantanious @Column @DynamicSerializeElement @XmlElement - private Float code60; // kcfs - - //Reservoir outflow, mean daily + private Float code60; // kcfs + + // Reservoir outflow, mean daily @Column @DynamicSerializeElement @XmlElement - private Float code61; // kcfs - - //Reservoir outflow forecast, mean daily, Day 1 + private Float code61; // kcfs + + // Reservoir outflow forecast, mean daily, Day 1 @Column @DynamicSerializeElement @XmlElement - private Float code62; // kcfs - - //Reservoir outflow forecast, mean daily, Day 2 + private Float code62; // kcfs + + // Reservoir outflow forecast, mean daily, Day 2 @Column @DynamicSerializeElement @XmlElement - private Float code63; // kcfs - - //Reservoir outflow forecast, mean daily, Day 3 + private Float code63; // kcfs + + // Reservoir outflow forecast, mean daily, Day 3 @Column @DynamicSerializeElement @XmlElement - private Float code64; // kcfs - - //Reservoir storage at specified ob time KAF=thousand acre feet + private Float code64; // kcfs + + // Reservoir storage at specified ob time KAF=thousand acre feet @Column @DynamicSerializeElement @XmlElement - private Float code65; // kaf - - //Reservoir evaporation, 24 hour total, computed + private Float code65; // kaf + + // Reservoir evaporation, 24 hour total, computed @Column @DynamicSerializeElement @XmlElement - private Float code66; // inches - - //Snow cover, areal extent + private Float code66; // inches + + // Snow cover, areal extent @Column @DynamicSerializeElement @XmlElement - private Float code67; // percent - - //Snow depth, total on ground + private Float code67; // percent + + // Snow depth, total on ground @Column @DynamicSerializeElement @XmlElement - private Float code68; // inches - - //Snow depth, new snow + private Float code68; // inches + + // Snow depth, new snow @Column @DynamicSerializeElement @XmlElement - private Float code69; // inches - - //Snow density + private Float code69; // inches + + // Snow density @Column @DynamicSerializeElement @XmlElement - private Float code70; // inches/inches - - //Snow, Water equivalent, total of snow and ice on ground + private Float code70; // inches/inches + + // Snow, Water equivalent, total of snow and ice on ground @Column @DynamicSerializeElement @XmlElement - private Float code71; // inches - + private Float code71; // inches + // Snow report ref LDAD Table? @Column @DynamicSerializeElement @XmlElement - private String code72; - //FirstDigit0 "Snow structure - no report" - //FirstDigit1 "Snow structure - losely packed" - //FirstDigit2 "Snow structure - densely packed" - //SecondDigit0 "Base of snowcover - no report" - //SecondDigit1 "Base of snowcover - wet snow" - //SecondDigit2 "Base of snowcover - dry snow" - //SecondDigit3 "Base of snowcover - ice layer" - //ThirdDigit0 "Surface of snowcover - no report" - //ThirdDigit1 "Surface of snowcover - snow crust" - //ThirdDigit2 "Surface of snowcover - loose" - //ThirdDigit3 "Surface of snowcover - ice" - //FourthDigit0 "Area description - no report" - //FourthDigit1 "Area description - uniform" - //FourthDigit2 "Area description - some drifts" - //FourthDigit3 "Area description - drifts" - - //Ice cover, areal extent + private String code72; + + // FirstDigit0 "Snow structure - no report" + // FirstDigit1 "Snow structure - losely packed" + // FirstDigit2 "Snow structure - densely packed" + // SecondDigit0 "Base of snowcover - no report" + // SecondDigit1 "Base of snowcover - wet snow" + // SecondDigit2 "Base of snowcover - dry snow" + // SecondDigit3 "Base of snowcover - ice layer" + // ThirdDigit0 "Surface of snowcover - no report" + // ThirdDigit1 "Surface of snowcover - snow crust" + // ThirdDigit2 "Surface of snowcover - loose" + // ThirdDigit3 "Surface of snowcover - ice" + // FourthDigit0 "Area description - no report" + // FourthDigit1 "Area description - uniform" + // FourthDigit2 "Area description - some drifts" + // FourthDigit3 "Area description - drifts" + + // Ice cover, areal extent @Column @DynamicSerializeElement @XmlElement - private Float code73; // percent - - //Ice extent from reporting area, up to downstream + private Float code73; // percent + + // Ice extent from reporting area, up to downstream @Column @DynamicSerializeElement @XmlElement - private Float code74; // miles - - //Ice open water, extent from reporting area, up or downstream + private Float code74; // miles + + // Ice open water, extent from reporting area, up or downstream @Column @DynamicSerializeElement @XmlElement - private Float code75; // miles - - //Ice thickness + private Float code75; // miles + + // Ice thickness @Column @DynamicSerializeElement @XmlElement - private Float code76; // inches - + private Float code76; // inches + // Ice report ref LDAD Table @Column @DynamicSerializeElement @XmlElement - private String code77; - // FirstDigit0 "Ice structure - no report" - // FirstDigit1 "Ice structure - breaking ice" - // FirstDigit2 "Ice structure - floating (running)" - // FirstDigit3 "Ice structure - hanging" - // FirstDigit4 "Ice structure - honeycomb" - // FirstDigit5 "Ice structure - layered" - // FirstDigit6 "Ice structure - rotten" - // FirstDigit7 "Ice structure - stationary" - // FirstDigit8 "Ice structure - stopped" - // FirstDigit9 "Ice structure - slush" - // SecondDigit0 "Ice type - no report" - // SecondDigit1 "Ice type - anchor (also bottom ice)" - // SecondDigit2 "Ice type - cake" - // SecondDigit3 "Ice type - clear" - // SecondDigit4 "Ice type - frazzle" - // SecondDigit5 "Ice type - ice gorge (also jammed ice)" - // SecondDigit6 "Ice type - locally formed" - // SecondDigit7 "Ice type - sheet ice" - // SecondDigit8 "Ice type - sheet ice (also on bridges)" - // SecondDigit9 "Ice type - shore ice" - // ThirdDigit0 "Ice cover - no ice" - // ThirdDigit1 "Ice cover - 1/10 cover" - // ThirdDigit2 "Ice cover - 2/10 cover" - // ThirdDigit3 "Ice cover - 3/10 cover" - // ThirdDigit4 "Ice cover - 4/10 cover" - // ThirdDigit5 "Ice cover - 5/10 cover" - // ThirdDigit6 "Ice cover - 6/10 cover" - // ThirdDigit7 "Ice cover - 7/10 cover" - // ThirdDigit8 "Ice cover - 8/10 - 9/10 cover" - // ThirdDigit9 "Ice cover - fully covered" - - //Depth of frost - @Column - @DynamicSerializeElement - @XmlElement - private Float code78; // inches - - //Depth of frost thawed - @Column - @DynamicSerializeElement - @XmlElement - private Float code79; // inches - - //Frost structure report - @Column - @DynamicSerializeElement - @XmlElement - private Short code80; // short - // 0 "Frost intensity - no frost" - // 1 "Frost intensity - light frost" - // 2 "Frost intensity - moderate frost" - // 3 "Frost intensity - heavy frost" - - //Surface frost intensity - @Column - @DynamicSerializeElement - @XmlElement - private Short code81; //short - // 0 "Frost intensity - no frost" - // 1 "Frost intensity - light frost" - // 2 "Frost intensity - moderate frost" - // 3 "Frost intensity - heavy frost" - - //State of ground - @Column - @DynamicSerializeElement - @XmlElement - private Short code82; // short - // 0 Surface of ground dry" - // 1 Surface of ground moist" - // 2 Surface of ground wet" - // 3 Flooded" - // 5 Glaze on ground" - // 6 Loose dry dust or sand not covering ground completely" - // 7 Thin cover of loose dry dust or sand covering ground completely" - // 8 Moderate or thick cover of loose dry dust or sand covering ground completely" - // 9 Ground extra dry with cracks" - // 10 Ground predominately covered with ice" - // 11 Compact or wet snow (with or without ice) covering less than one half of the ground" - // 12 Compact or wet snow (with or without ice) covering less than one half of the ground but not completely covered" - // 13 Even layer of comapct or wet snow covering ground completely" - // 14 Uneven layer of comapct or wet snow covering ground completely" - // 15 Loose dry snow covering less than one half of the ground" - // 16 Loose dry snow covering at least one half of the ground (but not completely)" - // 17 Even layers of loose dry snow covering ground completely" - // 18 Uneven layers of loose dry snow covering ground completely" - // 19 Snow covering ground completely; Deep drifts" - // 20 Sleet or hail covering ground completely" - - //Soil moisture - @Column - @DynamicSerializeElement - @XmlElement - private Float code83; // inches - - //Present weather - @Column - @DynamicSerializeElement - @XmlElement - private Short code84; // short - // 5 "Haze" - // 7 "Dust or sand raised by wind" - // 8 "Well developed dust whirls or sand whirls" - // 13 "Lightning (no thunder heard)" - // 17 "Thunderstorm, but no precip at ob time" - // 19 "Funnel cloud at or within sight of station during previous hour or at ob time" - // 41 "Fog or ice fog in patches" - // 42 "Fog or ice fog (sky visible)" - // 43 "Fog or ice fog (sky not visible)" - // 51 "Drizzle, not freezing, slight at ob time" - // 53 "Drizzle, not freezing, moderate at ob time" - // 55 "Drizzle, not freezing, heavy at ob time" - // 56 "Drizzle, freezing, light" - // 57 "Drizzle, freezing, moderate or heavy" - // 61 "Rain, not freezing, continuous, slight at ob time" - // 63 "Rain, not freezing, continuous, moderate at ob time" - // 65 "Rain, not freezing, continuous, heavy at ob time" - // 66 "Rain, freezing, light" - // 67 "Rain, freezing, moderate or heavy" - // 68 "Rain or drizzle and snow, light" - // 69 "Rain or drizzle and snow, moderate or heavy" - // 71 "Snow, continuous, light" - // 73 "Snow, continuous, moderate" - // 75 "Snow, continuous, heavy" - // 79 "Ice Pellets or sleet" - // 80 "Rainshower, light" - // 81 "Rainshower, moderate or heavy" - // 82 "Rainshower, violent" - // 83 "Rain and snowshowers, light" - // 84 "Rain and snowshowers, moderate or heavy" - // 85 "Snowshowers, light" - // 86 "Snowshowers, moderate or heavy" - // 89 "Showers of hail, with or without rain or rain and snow mixed at ob time" - // 95 "Thunderstorm, slight or moderate, without hail, but with rain and/or snow" - // 96 "Thunderstorm, slight or moderate, with hail" - // 97 "Thunderstorm, heavy, without hail, but with rain and/or snow" - // 98 "Thunderstorm, with dust or sand storm" - // 99 "Thunderstorm, heavy with hail" - - //Past 6 hour weather - @Column - @DynamicSerializeElement - @XmlElement - private Short code85; // short - // 0 "Cloud covering one half or less of the sky throughout the appropriate period" - // 1 "Cloud covering more than one half the sky throughout the appropriate period and covering one half or less during part of the period" - // 2 "Cloud covering more than one half the sky throughout the appropriate period" - // 3 "Sandstorm, duststrom, or blowing snow" - // 4 "Fog or ice fog or thick haze" - // 5 "Drizzle" - // 6 "Rain" - // 7 "Snow, or rain and snow mixed" - // 8 "Showers" - // 9 "Thunderstorm(s) with or without precip" + private String code77; - //Relative humidity + // FirstDigit0 "Ice structure - no report" + // FirstDigit1 "Ice structure - breaking ice" + // FirstDigit2 "Ice structure - floating (running)" + // FirstDigit3 "Ice structure - hanging" + // FirstDigit4 "Ice structure - honeycomb" + // FirstDigit5 "Ice structure - layered" + // FirstDigit6 "Ice structure - rotten" + // FirstDigit7 "Ice structure - stationary" + // FirstDigit8 "Ice structure - stopped" + // FirstDigit9 "Ice structure - slush" + // SecondDigit0 "Ice type - no report" + // SecondDigit1 "Ice type - anchor (also bottom ice)" + // SecondDigit2 "Ice type - cake" + // SecondDigit3 "Ice type - clear" + // SecondDigit4 "Ice type - frazzle" + // SecondDigit5 "Ice type - ice gorge (also jammed ice)" + // SecondDigit6 "Ice type - locally formed" + // SecondDigit7 "Ice type - sheet ice" + // SecondDigit8 "Ice type - sheet ice (also on bridges)" + // SecondDigit9 "Ice type - shore ice" + // ThirdDigit0 "Ice cover - no ice" + // ThirdDigit1 "Ice cover - 1/10 cover" + // ThirdDigit2 "Ice cover - 2/10 cover" + // ThirdDigit3 "Ice cover - 3/10 cover" + // ThirdDigit4 "Ice cover - 4/10 cover" + // ThirdDigit5 "Ice cover - 5/10 cover" + // ThirdDigit6 "Ice cover - 6/10 cover" + // ThirdDigit7 "Ice cover - 7/10 cover" + // ThirdDigit8 "Ice cover - 8/10 - 9/10 cover" + // ThirdDigit9 "Ice cover - fully covered" + + // Depth of frost @Column @DynamicSerializeElement @XmlElement - private Float code86; // percent - - //Evaporation, measured, Class A pan or other + private Float code78; // inches + + // Depth of frost thawed @Column @DynamicSerializeElement @XmlElement - private Float code87; // inches - - //Wind speed + private Float code79; // inches + + // Frost structure report @Column @DynamicSerializeElement @XmlElement - private Float code88; // miles per hour - - //Wind direction + private Short code80; // short + // 0 "Frost intensity - no frost" + // 1 "Frost intensity - light frost" + // 2 "Frost intensity - moderate frost" + // 3 "Frost intensity - heavy frost" + + // Surface frost intensity @Column @DynamicSerializeElement @XmlElement - private Float code89; // tens of degrees - - //Sunshine, hours per day + private Short code81; // short + // 0 "Frost intensity - no frost" + // 1 "Frost intensity - light frost" + // 2 "Frost intensity - moderate frost" + // 3 "Frost intensity - heavy frost" + + // State of ground + @Column + @DynamicSerializeElement + @XmlElement + private Short code82; // short + // 0 Surface of ground dry" + // 1 Surface of ground moist" + // 2 Surface of ground wet" + // 3 Flooded" + // 5 Glaze on ground" + // 6 Loose dry dust or sand not covering ground + // completely" + // 7 Thin cover of loose dry dust or sand covering + // ground completely" + // 8 Moderate or thick cover of loose dry dust or sand + // covering ground completely" + // 9 Ground extra dry with cracks" + // 10 Ground predominately covered with ice" + // 11 Compact or wet snow (with or without ice) + // covering less than one half of the ground" + // 12 Compact or wet snow (with or without ice) + // covering less than one half of the ground but not + // completely covered" + // 13 Even layer of comapct or wet snow covering + // ground completely" + // 14 Uneven layer of comapct or wet snow covering + // ground completely" + // 15 Loose dry snow covering less than one half of + // the ground" + // 16 Loose dry snow covering at least one half of the + // ground (but not completely)" + // 17 Even layers of loose dry snow covering ground + // completely" + // 18 Uneven layers of loose dry snow covering ground + // completely" + // 19 Snow covering ground completely; Deep drifts" + // 20 Sleet or hail covering ground completely" + + // Soil moisture + @Column + @DynamicSerializeElement + @XmlElement + private Float code83; // inches + + // Present weather + @Column + @DynamicSerializeElement + @XmlElement + private Short code84; // short + // 5 "Haze" + // 7 "Dust or sand raised by wind" + // 8 "Well developed dust whirls or sand whirls" + // 13 "Lightning (no thunder heard)" + // 17 "Thunderstorm, but no precip at ob time" + // 19 + // "Funnel cloud at or within sight of station during previous hour or at ob time" + // 41 "Fog or ice fog in patches" + // 42 "Fog or ice fog (sky visible)" + // 43 "Fog or ice fog (sky not visible)" + // 51 "Drizzle, not freezing, slight at ob time" + // 53 "Drizzle, not freezing, moderate at ob time" + // 55 "Drizzle, not freezing, heavy at ob time" + // 56 "Drizzle, freezing, light" + // 57 "Drizzle, freezing, moderate or heavy" + // 61 + // "Rain, not freezing, continuous, slight at ob time" + // 63 + // "Rain, not freezing, continuous, moderate at ob time" + // 65 + // "Rain, not freezing, continuous, heavy at ob time" + // 66 "Rain, freezing, light" + // 67 "Rain, freezing, moderate or heavy" + // 68 "Rain or drizzle and snow, light" + // 69 "Rain or drizzle and snow, moderate or heavy" + // 71 "Snow, continuous, light" + // 73 "Snow, continuous, moderate" + // 75 "Snow, continuous, heavy" + // 79 "Ice Pellets or sleet" + // 80 "Rainshower, light" + // 81 "Rainshower, moderate or heavy" + // 82 "Rainshower, violent" + // 83 "Rain and snowshowers, light" + // 84 "Rain and snowshowers, moderate or heavy" + // 85 "Snowshowers, light" + // 86 "Snowshowers, moderate or heavy" + // 89 + // "Showers of hail, with or without rain or rain and snow mixed at ob time" + // 95 + // "Thunderstorm, slight or moderate, without hail, but with rain and/or snow" + // 96 "Thunderstorm, slight or moderate, with hail" + // 97 + // "Thunderstorm, heavy, without hail, but with rain and/or snow" + // 98 "Thunderstorm, with dust or sand storm" + // 99 "Thunderstorm, heavy with hail" + + // Past 6 hour weather + @Column + @DynamicSerializeElement + @XmlElement + private Short code85; // short + // 0 + // "Cloud covering one half or less of the sky throughout the appropriate period" + // 1 + // "Cloud covering more than one half the sky throughout the appropriate period and covering one half or less during part of the period" + // 2 + // "Cloud covering more than one half the sky throughout the appropriate period" + // 3 "Sandstorm, duststrom, or blowing snow" + // 4 "Fog or ice fog or thick haze" + // 5 "Drizzle" + // 6 "Rain" + // 7 "Snow, or rain and snow mixed" + // 8 "Showers" + // 9 "Thunderstorm(s) with or without precip" + + // Relative humidity + @Column + @DynamicSerializeElement + @XmlElement + private Float code86; // percent + + // Evaporation, measured, Class A pan or other + @Column + @DynamicSerializeElement + @XmlElement + private Float code87; // inches + + // Wind speed + @Column + @DynamicSerializeElement + @XmlElement + private Float code88; // miles per hour + + // Wind direction + @Column + @DynamicSerializeElement + @XmlElement + private Float code89; // tens of degrees + + // Sunshine, hours per day @Column @DynamicSerializeElement @XmlElement private Float code90; // hours - - //Solar energy, accumulated incoming + + // Solar energy, accumulated incoming @Column @DynamicSerializeElement @XmlElement - private Float code91; // ly - + private Float code91; // ly + // short Dew intensity @Column @DynamicSerializeElement @XmlElement - private Short code92; - // 0 "No dew" - // 1 "Light dew" - // 2 "Moderate dew" - // 3 "Heavy dew" - - //Leaf wetness + private Short code92; + + // 0 "No dew" + // 1 "Light dew" + // 2 "Moderate dew" + // 3 "Heavy dew" + + // Leaf wetness @Column @DynamicSerializeElement @XmlElement private Float code93; // hours ???????????????????? - - //Water pan temperature maximum + + // Water pan temperature maximum @Column @DynamicSerializeElement @XmlElement - private Float code94; // degrees F - - //Water pan temperature minimum + private Float code94; // degrees F + + // Water pan temperature minimum @Column @DynamicSerializeElement @XmlElement - private Float code95; // degrees F - - //24 hour wind flow + private Float code95; // degrees F + + // 24 hour wind flow @Column @DynamicSerializeElement @XmlElement - private Float code96; // miles + private Float code96; // miles // Raw observation text - ROSA raw message @Column @DynamicSerializeElement @XmlElement - private String rawMessage; //rawMessage - + private String rawMessage; // rawMessage + /** * */ @@ -861,1171 +882,1253 @@ IDecoderGettable { public ManualLdadRecord(String uri) { super(uri); } - - + + /** + * @return the code12 + */ + public Float getCode12() { + return code12; + } + + /** + * @param code12 + * the code12 to set + */ + public void setCode12(Float code12) { + this.code12 = code12; + } + + /** + * @return the code13 + */ + public Float getCode13() { + return code13; + } + + /** + * @param code13 + * the code13 to set + */ + public void setCode13(Float code13) { + this.code13 = code13; + } + + /** + * @return the code14 + */ + public Float getCode14() { + return code14; + } + + /** + * @param code14 + * the code14 to set + */ + public void setCode14(Float code14) { + this.code14 = code14; + } + + /** + * @return the code15 + */ + public Float getCode15() { + return code15; + } + + /** + * @param code15 + * the code15 to set + */ + public void setCode15(Float code15) { + this.code15 = code15; + } + + /** + * @return the code16 + */ + public Float getCode16() { + return code16; + } + + /** + * @param code16 + * the code16 to set + */ + public void setCode16(Float code16) { + this.code16 = code16; + } + + /** + * @return the code17 + */ + public Float getCode17() { + return code17; + } + + /** + * @param code17 + * the code17 to set + */ + public void setCode17(Float code17) { + this.code17 = code17; + } + + /** + * @return the code18 + */ + public Float getCode18() { + return code18; + } + + /** + * @param code18 + * the code18 to set + */ + public void setCode18(Float code18) { + this.code18 = code18; + } + + /** + * @return the code19 + */ + public Float getCode19() { + return code19; + } + + /** + * @param code19 + * the code19 to set + */ + public void setCode19(Float code19) { + this.code19 = code19; + } + + /** + * @return the code20 + */ + public Short getCode20() { + return code20; + } + + /** + * @param code20 + * the code20 to set + */ + public void setCode20(Short code20) { + this.code20 = code20; + } + + /** + * @return the code21 + */ + public Float getCode21() { + return code21; + } + + /** + * @param code21 + * the code21 to set + */ + public void setCode21(Float code21) { + this.code21 = code21; + } + + /** + * @return the code22 + */ + public Float getCode22() { + return code22; + } + + /** + * @param code22 + * the code22 to set + */ + public void setCode22(Float code22) { + this.code22 = code22; + } + + /** + * @return the code23 + */ + public Float getCode23() { + return code23; + } + + /** + * @param code23 + * the code23 to set + */ + public void setCode23(Float code23) { + this.code23 = code23; + } + + /** + * @return the code24 + */ + public Float getCode24() { + return code24; + } + + /** + * @param code24 + * the code24 to set + */ + public void setCode24(Float code24) { + this.code24 = code24; + } + + /** + * @return the code25 + */ + public Float getCode25() { + return code25; + } + + /** + * @param code25 + * the code25 to set + */ + public void setCode25(Float code25) { + this.code25 = code25; + } + + /** + * @return the code26 + */ + public Float getCode26() { + return code26; + } + + /** + * @param code26 + * the code26 to set + */ + public void setCode26(Float code26) { + this.code26 = code26; + } + + /** + * @return the code27 + */ + public Float getCode27() { + return code27; + } + + /** + * @param code27 + * the code27 to set + */ + public void setCode27(Float code27) { + this.code27 = code27; + } + + /** + * @return the code28 + */ + public Float getCode28() { + return code28; + } + + /** + * @param code28 + * the code28 to set + */ + public void setCode28(Float code28) { + this.code28 = code28; + } + + /** + * @return the code29 + */ + public Float getCode29() { + return code29; + } + + /** + * @param code29 + * the code29 to set + */ + public void setCode29(Float code29) { + this.code29 = code29; + } + + /** + * @return the code30 + */ + public Float getCode30() { + return code30; + } + + /** + * @param code30 + * the code30 to set + */ + public void setCode30(Float code30) { + this.code30 = code30; + } + + /** + * @return the code31 + */ + public Float getCode31() { + return code31; + } + + /** + * @param code31 + * the code31 to set + */ + public void setCode31(Float code31) { + this.code31 = code31; + } + + /** + * @return the code32 + */ + public Float getCode32() { + return code32; + } + + /** + * @param code32 + * the code32 to set + */ + public void setCode32(Float code32) { + this.code32 = code32; + } + + /** + * @return the code33 + */ + public Float getCode33() { + return code33; + } + + /** + * @param code33 + * the code33 to set + */ + public void setCode33(Float code33) { + this.code33 = code33; + } + + /** + * @return the code34 + */ + public Float getCode34() { + return code34; + } + + /** + * @param code34 + * the code34 to set + */ + public void setCode34(Float code34) { + this.code34 = code34; + } + + /** + * @return the code35 + */ + public Float getCode35() { + return code35; + } + + /** + * @param code35 + * the code35 to set + */ + public void setCode35(Float code35) { + this.code35 = code35; + } + + /** + * @return the code36 + */ + public Float getCode36() { + return code36; + } + + /** + * @param code36 + * the code36 to set + */ + public void setCode36(Float code36) { + this.code36 = code36; + } + + /** + * @return the code37 + */ + public Float getCode37() { + return code37; + } + + /** + * @param code37 + * the code37 to set + */ + public void setCode37(Float code37) { + this.code37 = code37; + } + + /** + * @return the code38 + */ + public Float getCode38() { + return code38; + } + + /** + * @param code38 + * the code38 to set + */ + public void setCode38(Float code38) { + this.code38 = code38; + } + + /** + * @return the code39 + */ + public String getCode39() { + return code39; + } + + /** + * @param code39 + * the code39 to set + */ + public void setCode39(String code39) { + this.code39 = code39; + } + + /** + * @return the code40 + */ + public Float getCode40() { + return code40; + } + + /** + * @param code40 + * the code40 to set + */ + public void setCode40(Float code40) { + this.code40 = code40; + } + + /** + * @return the code41 + */ + public Short getCode41() { + return code41; + } + + /** + * @param code41 + * the code41 to set + */ + public void setCode41(Short code41) { + this.code41 = code41; + } + + /** + * @return the code43 + */ + public Float getCode43() { + return code43; + } + + /** + * @param code43 + * the code43 to set + */ + public void setCode43(Float code43) { + this.code43 = code43; + } + + /** + * @return the code44 + */ + public Float getCode44() { + return code44; + } + + /** + * @param code44 + * the code44 to set + */ + public void setCode44(Float code44) { + this.code44 = code44; + } + + /** + * @return the code45 + */ + public Float getCode45() { + return code45; + } + + /** + * @param code45 + * the code45 to set + */ + public void setCode45(Float code45) { + this.code45 = code45; + } + + /** + * @return the code46 + */ + public Float getCode46() { + return code46; + } + + /** + * @param code46 + * the code46 to set + */ + public void setCode46(Float code46) { + this.code46 = code46; + } + + /** + * @return the code47 + */ + public Float getCode47() { + return code47; + } + + /** + * @param code47 + * the code47 to set + */ + public void setCode47(Float code47) { + this.code47 = code47; + } + + /** + * @return the code48 + */ + public Float getCode48() { + return code48; + } + + /** + * @param code48 + * the code48 to set + */ + public void setCode48(Float code48) { + this.code48 = code48; + } + + /** + * @return the code49 + */ + public Float getCode49() { + return code49; + } + + /** + * @param code49 + * the code49 to set + */ + public void setCode49(Float code49) { + this.code49 = code49; + } + + /** + * @return the code50 + */ + public Float getCode50() { + return code50; + } + + /** + * @param code50 + * the code50 to set + */ + public void setCode50(Float code50) { + this.code50 = code50; + } + + /** + * @return the code52 + */ + public Float getCode52() { + return code52; + } + + /** + * @param code52 + * the code52 to set + */ + public void setCode52(Float code52) { + this.code52 = code52; + } + + /** + * @return the code53 + */ + public Float getCode53() { + return code53; + } + + /** + * @param code53 + * the code53 to set + */ + public void setCode53(Float code53) { + this.code53 = code53; + } + + /** + * @return the code54 + */ + public Float getCode54() { + return code54; + } + + /** + * @param code54 + * the code54 to set + */ + public void setCode54(Float code54) { + this.code54 = code54; + } + + /** + * @return the code55 + */ + public Float getCode55() { + return code55; + } + + /** + * @param code55 + * the code55 to set + */ + public void setCode55(Float code55) { + this.code55 = code55; + } + + /** + * @return the code56 + */ + public Float getCode56() { + return code56; + } + + /** + * @param code56 + * the code56 to set + */ + public void setCode56(Float code56) { + this.code56 = code56; + } + + /** + * @return the code57 + */ + public Float getCode57() { + return code57; + } + + /** + * @param code57 + * the code57 to set + */ + public void setCode57(Float code57) { + this.code57 = code57; + } + + /** + * @return the code58 + */ + public Float getCode58() { + return code58; + } + + /** + * @param code58 + * the code58 to set + */ + public void setCode58(Float code58) { + this.code58 = code58; + } + + /** + * @return the code59 + */ + public Float getCode59() { + return code59; + } + + /** + * @param code59 + * the code59 to set + */ + public void setCode59(Float code59) { + this.code59 = code59; + } + + /** + * @return the code60 + */ + public Float getCode60() { + return code60; + } + + /** + * @param code60 + * the code60 to set + */ + public void setCode60(Float code60) { + this.code60 = code60; + } + + /** + * @return the code61 + */ + public Float getCode61() { + return code61; + } + + /** + * @param code61 + * the code61 to set + */ + public void setCode61(Float code61) { + this.code61 = code61; + } + + /** + * @return the code62 + */ + public Float getCode62() { + return code62; + } + + /** + * @param code62 + * the code62 to set + */ + public void setCode62(Float code62) { + this.code62 = code62; + } + + /** + * @return the code63 + */ + public Float getCode63() { + return code63; + } + + /** + * @param code63 + * the code63 to set + */ + public void setCode63(Float code63) { + this.code63 = code63; + } + + /** + * @return the code64 + */ + public Float getCode64() { + return code64; + } + + /** + * @param code64 + * the code64 to set + */ + public void setCode64(Float code64) { + this.code64 = code64; + } + + /** + * @return the code65 + */ + public Float getCode65() { + return code65; + } + + /** + * @param code65 + * the code65 to set + */ + public void setCode65(Float code65) { + this.code65 = code65; + } + + /** + * @return the code66 + */ + public Float getCode66() { + return code66; + } + + /** + * @param code66 + * the code66 to set + */ + public void setCode66(Float code66) { + this.code66 = code66; + } + + /** + * @return the code67 + */ + public Float getCode67() { + return code67; + } + + /** + * @param code67 + * the code67 to set + */ + public void setCode67(Float code67) { + this.code67 = code67; + } + + /** + * @return the code68 + */ + public Float getCode68() { + return code68; + } + + /** + * @param code68 + * the code68 to set + */ + public void setCode68(Float code68) { + this.code68 = code68; + } + + /** + * @return the code69 + */ + public Float getCode69() { + return code69; + } + + /** + * @param code69 + * the code69 to set + */ + public void setCode69(Float code69) { + this.code69 = code69; + } + + /** + * @return the code70 + */ + public Float getCode70() { + return code70; + } + + /** + * @param code70 + * the code70 to set + */ + public void setCode70(Float code70) { + this.code70 = code70; + } + + /** + * @return the code71 + */ + public Float getCode71() { + return code71; + } + + /** + * @param code71 + * the code71 to set + */ + public void setCode71(Float code71) { + this.code71 = code71; + } + + /** + * @return the code72 + */ + public String getCode72() { + return code72; + } + + /** + * @param code72 + * the code72 to set + */ + public void setCode72(String code72) { + this.code72 = code72; + } + + /** + * @return the code73 + */ + public Float getCode73() { + return code73; + } + + /** + * @param code73 + * the code73 to set + */ + public void setCode73(Float code73) { + this.code73 = code73; + } + + /** + * @return the code74 + */ + public Float getCode74() { + return code74; + } + + /** + * @param code74 + * the code74 to set + */ + public void setCode74(Float code74) { + this.code74 = code74; + } + + /** + * @return the code75 + */ + public Float getCode75() { + return code75; + } + + /** + * @param code75 + * the code75 to set + */ + public void setCode75(Float code75) { + this.code75 = code75; + } + + /** + * @return the code76 + */ + public Float getCode76() { + return code76; + } + + /** + * @param code76 + * the code76 to set + */ + public void setCode76(Float code76) { + this.code76 = code76; + } + + /** + * @return the code77 + */ + public String getCode77() { + return code77; + } + + /** + * @param code77 + * the code77 to set + */ + public void setCode77(String code77) { + this.code77 = code77; + } + + /** + * @return the code78 + */ + public Float getCode78() { + return code78; + } + + /** + * @param code78 + * the code78 to set + */ + public void setCode78(Float code78) { + this.code78 = code78; + } + + /** + * @return the code79 + */ + public Float getCode79() { + return code79; + } + + /** + * @param code79 + * the code79 to set + */ + public void setCode79(Float code79) { + this.code79 = code79; + } + + /** + * @return the code80 + */ + public Short getCode80() { + return code80; + } + + /** + * @param code80 + * the code80 to set + */ + public void setCode80(Short code80) { + this.code80 = code80; + } + + /** + * @return the code81 + */ + public Short getCode81() { + return code81; + } + + /** + * @param code81 + * the code81 to set + */ + public void setCode81(Short code81) { + this.code81 = code81; + } + + /** + * @return the code82 + */ + public Short getCode82() { + return code82; + } + + /** + * @param code82 + * the code82 to set + */ + public void setCode82(Short code82) { + this.code82 = code82; + } + + /** + * @return the code83 + */ + public Float getCode83() { + return code83; + } + + /** + * @param code83 + * the code83 to set + */ + public void setCode83(Float code83) { + this.code83 = code83; + } + + /** + * @return the code84 + */ + public Short getCode84() { + return code84; + } + + /** + * @param code84 + * the code84 to set + */ + public void setCode84(Short code84) { + this.code84 = code84; + } + + /** + * @return the code85 + */ + public Short getCode85() { + return code85; + } + + /** + * @param code85 + * the code85 to set + */ + public void setCode85(Short code85) { + this.code85 = code85; + } + + /** + * @return the code86 + */ + public Float getCode86() { + return code86; + } + + /** + * @param code86 + * the code86 to set + */ + public void setCode86(Float code86) { + this.code86 = code86; + } + + /** + * @return the code87 + */ + public Float getCode87() { + return code87; + } + + /** + * @param code87 + * the code87 to set + */ + public void setCode87(Float code87) { + this.code87 = code87; + } + + /** + * @return the code88 + */ + public Float getCode88() { + return code88; + } + + /** + * @param code88 + * the code88 to set + */ + public void setCode88(Float code88) { + this.code88 = code88; + } + + /** + * @return the code89 + */ + public Float getCode89() { + return code89; + } + + /** + * @param code89 + * the code89 to set + */ + public void setCode89(Float code89) { + this.code89 = code89; + } + + /** + * @return the code90 + */ + public Float getCode90() { + return code90; + } + + /** + * @param code90 + * the code90 to set + */ + public void setCode90(Float code90) { + this.code90 = code90; + } + + /** + * @return the code91 + */ + public Float getCode91() { + return code91; + } + + /** + * @param code91 + * the code91 to set + */ + public void setCode91(Float code91) { + this.code91 = code91; + } + + /** + * @return the code92 + */ + public Short getCode92() { + return code92; + } + + /** + * @param code92 + * the code92 to set + */ + public void setCode92(Short code92) { + this.code92 = code92; + } + + /** + * @return the code93 + */ + public Float getCode93() { + return code93; + } + + /** + * @param code93 + * the code93 to set + */ + public void setCode93(Float code93) { + this.code93 = code93; + } + + /** + * @return the code94 + */ + public Float getCode94() { + return code94; + } + + /** + * @param code94 + * the code94 to set + */ + public void setCode94(Float code94) { + this.code94 = code94; + } + + /** + * @return the code95 + */ + public Float getCode95() { + return code95; + } + + /** + * @param code95 + * the code95 to set + */ + public void setCode95(Float code95) { + this.code95 = code95; + } + + /** + * @return the code96 + */ + public Float getCode96() { + return code96; + } + + /** + * @param code96 + * the code96 to set + */ + public void setCode96(Float code96) { + this.code96 = code96; + } + /** - * @return the code12 - */ - public Float getCode12() { - return code12; - } - - /** - * @param code12 the code12 to set - */ - public void setCode12(Float code12) { - this.code12 = code12; - } - - /** - * @return the code13 - */ - public Float getCode13() { - return code13; - } - - /** - * @param code13 the code13 to set - */ - public void setCode13(Float code13) { - this.code13 = code13; - } - - /** - * @return the code14 - */ - public Float getCode14() { - return code14; - } - - /** - * @param code14 the code14 to set - */ - public void setCode14(Float code14) { - this.code14 = code14; - } - - /** - * @return the code15 - */ - public Float getCode15() { - return code15; - } - - /** - * @param code15 the code15 to set - */ - public void setCode15(Float code15) { - this.code15 = code15; - } - - /** - * @return the code16 - */ - public Float getCode16() { - return code16; - } - - /** - * @param code16 the code16 to set - */ - public void setCode16(Float code16) { - this.code16 = code16; - } - - /** - * @return the code17 - */ - public Float getCode17() { - return code17; - } - - /** - * @param code17 the code17 to set - */ - public void setCode17(Float code17) { - this.code17 = code17; - } - - /** - * @return the code18 - */ - public Float getCode18() { - return code18; - } - - /** - * @param code18 the code18 to set - */ - public void setCode18(Float code18) { - this.code18 = code18; - } - - /** - * @return the code19 - */ - public Float getCode19() { - return code19; - } - - /** - * @param code19 the code19 to set - */ - public void setCode19(Float code19) { - this.code19 = code19; - } - - /** - * @return the code20 - */ - public Short getCode20() { - return code20; - } - - /** - * @param code20 the code20 to set - */ - public void setCode20(Short code20) { - this.code20 = code20; - } - - /** - * @return the code21 - */ - public Float getCode21() { - return code21; - } - - /** - * @param code21 the code21 to set - */ - public void setCode21(Float code21) { - this.code21 = code21; - } - - /** - * @return the code22 - */ - public Float getCode22() { - return code22; - } - - /** - * @param code22 the code22 to set - */ - public void setCode22(Float code22) { - this.code22 = code22; - } - - /** - * @return the code23 - */ - public Float getCode23() { - return code23; - } - - /** - * @param code23 the code23 to set - */ - public void setCode23(Float code23) { - this.code23 = code23; - } - - /** - * @return the code24 - */ - public Float getCode24() { - return code24; - } - - /** - * @param code24 the code24 to set - */ - public void setCode24(Float code24) { - this.code24 = code24; - } - - /** - * @return the code25 - */ - public Float getCode25() { - return code25; - } - - /** - * @param code25 the code25 to set - */ - public void setCode25(Float code25) { - this.code25 = code25; - } - - /** - * @return the code26 - */ - public Float getCode26() { - return code26; - } - - /** - * @param code26 the code26 to set - */ - public void setCode26(Float code26) { - this.code26 = code26; - } - - /** - * @return the code27 - */ - public Float getCode27() { - return code27; - } - - /** - * @param code27 the code27 to set - */ - public void setCode27(Float code27) { - this.code27 = code27; - } - - /** - * @return the code28 - */ - public Float getCode28() { - return code28; - } - - /** - * @param code28 the code28 to set - */ - public void setCode28(Float code28) { - this.code28 = code28; - } - - /** - * @return the code29 - */ - public Float getCode29() { - return code29; - } - - /** - * @param code29 the code29 to set - */ - public void setCode29(Float code29) { - this.code29 = code29; - } - - /** - * @return the code30 - */ - public Float getCode30() { - return code30; - } - - /** - * @param code30 the code30 to set - */ - public void setCode30(Float code30) { - this.code30 = code30; - } - - /** - * @return the code31 - */ - public Float getCode31() { - return code31; - } - - /** - * @param code31 the code31 to set - */ - public void setCode31(Float code31) { - this.code31 = code31; - } - - /** - * @return the code32 - */ - public Float getCode32() { - return code32; - } - - /** - * @param code32 the code32 to set - */ - public void setCode32(Float code32) { - this.code32 = code32; - } - - /** - * @return the code33 - */ - public Float getCode33() { - return code33; - } - - /** - * @param code33 the code33 to set - */ - public void setCode33(Float code33) { - this.code33 = code33; - } - - /** - * @return the code34 - */ - public Float getCode34() { - return code34; - } - - /** - * @param code34 the code34 to set - */ - public void setCode34(Float code34) { - this.code34 = code34; - } - - /** - * @return the code35 - */ - public Float getCode35() { - return code35; - } - - /** - * @param code35 the code35 to set - */ - public void setCode35(Float code35) { - this.code35 = code35; - } - - /** - * @return the code36 - */ - public Float getCode36() { - return code36; - } - - /** - * @param code36 the code36 to set - */ - public void setCode36(Float code36) { - this.code36 = code36; - } - - /** - * @return the code37 - */ - public Float getCode37() { - return code37; - } - - /** - * @param code37 the code37 to set - */ - public void setCode37(Float code37) { - this.code37 = code37; - } - - /** - * @return the code38 - */ - public Float getCode38() { - return code38; - } - - /** - * @param code38 the code38 to set - */ - public void setCode38(Float code38) { - this.code38 = code38; - } - - /** - * @return the code39 - */ - public String getCode39() { - return code39; - } - - /** - * @param code39 the code39 to set - */ - public void setCode39(String code39) { - this.code39 = code39; - } - - /** - * @return the code40 - */ - public Float getCode40() { - return code40; - } - - /** - * @param code40 the code40 to set - */ - public void setCode40(Float code40) { - this.code40 = code40; - } - - /** - * @return the code41 - */ - public Short getCode41() { - return code41; - } - - /** - * @param code41 the code41 to set - */ - public void setCode41(Short code41) { - this.code41 = code41; - } - - /** - * @return the code43 - */ - public Float getCode43() { - return code43; - } - - /** - * @param code43 the code43 to set - */ - public void setCode43(Float code43) { - this.code43 = code43; - } - - /** - * @return the code44 - */ - public Float getCode44() { - return code44; - } - - /** - * @param code44 the code44 to set - */ - public void setCode44(Float code44) { - this.code44 = code44; - } - - /** - * @return the code45 - */ - public Float getCode45() { - return code45; - } - - /** - * @param code45 the code45 to set - */ - public void setCode45(Float code45) { - this.code45 = code45; - } - - /** - * @return the code46 - */ - public Float getCode46() { - return code46; - } - - /** - * @param code46 the code46 to set - */ - public void setCode46(Float code46) { - this.code46 = code46; - } - - /** - * @return the code47 - */ - public Float getCode47() { - return code47; - } - - /** - * @param code47 the code47 to set - */ - public void setCode47(Float code47) { - this.code47 = code47; - } - - /** - * @return the code48 - */ - public Float getCode48() { - return code48; - } - - /** - * @param code48 the code48 to set - */ - public void setCode48(Float code48) { - this.code48 = code48; - } - - /** - * @return the code49 - */ - public Float getCode49() { - return code49; - } - - /** - * @param code49 the code49 to set - */ - public void setCode49(Float code49) { - this.code49 = code49; - } - - /** - * @return the code50 - */ - public Float getCode50() { - return code50; - } - - /** - * @param code50 the code50 to set - */ - public void setCode50(Float code50) { - this.code50 = code50; - } - - /** - * @return the code52 - */ - public Float getCode52() { - return code52; - } - - /** - * @param code52 the code52 to set - */ - public void setCode52(Float code52) { - this.code52 = code52; - } - - /** - * @return the code53 - */ - public Float getCode53() { - return code53; - } - - /** - * @param code53 the code53 to set - */ - public void setCode53(Float code53) { - this.code53 = code53; - } - - /** - * @return the code54 - */ - public Float getCode54() { - return code54; - } - - /** - * @param code54 the code54 to set - */ - public void setCode54(Float code54) { - this.code54 = code54; - } - - /** - * @return the code55 - */ - public Float getCode55() { - return code55; - } - - /** - * @param code55 the code55 to set - */ - public void setCode55(Float code55) { - this.code55 = code55; - } - - /** - * @return the code56 - */ - public Float getCode56() { - return code56; - } - - /** - * @param code56 the code56 to set - */ - public void setCode56(Float code56) { - this.code56 = code56; - } - - /** - * @return the code57 - */ - public Float getCode57() { - return code57; - } - - /** - * @param code57 the code57 to set - */ - public void setCode57(Float code57) { - this.code57 = code57; - } - - /** - * @return the code58 - */ - public Float getCode58() { - return code58; - } - - /** - * @param code58 the code58 to set - */ - public void setCode58(Float code58) { - this.code58 = code58; - } - - /** - * @return the code59 - */ - public Float getCode59() { - return code59; - } - - /** - * @param code59 the code59 to set - */ - public void setCode59(Float code59) { - this.code59 = code59; - } - - /** - * @return the code60 - */ - public Float getCode60() { - return code60; - } - - /** - * @param code60 the code60 to set - */ - public void setCode60(Float code60) { - this.code60 = code60; - } - - /** - * @return the code61 - */ - public Float getCode61() { - return code61; - } - - /** - * @param code61 the code61 to set - */ - public void setCode61(Float code61) { - this.code61 = code61; - } - - /** - * @return the code62 - */ - public Float getCode62() { - return code62; - } - - /** - * @param code62 the code62 to set - */ - public void setCode62(Float code62) { - this.code62 = code62; - } - - /** - * @return the code63 - */ - public Float getCode63() { - return code63; - } - - /** - * @param code63 the code63 to set - */ - public void setCode63(Float code63) { - this.code63 = code63; - } - - /** - * @return the code64 - */ - public Float getCode64() { - return code64; - } - - /** - * @param code64 the code64 to set - */ - public void setCode64(Float code64) { - this.code64 = code64; - } - - /** - * @return the code65 - */ - public Float getCode65() { - return code65; - } - - /** - * @param code65 the code65 to set - */ - public void setCode65(Float code65) { - this.code65 = code65; - } - - /** - * @return the code66 - */ - public Float getCode66() { - return code66; - } - - /** - * @param code66 the code66 to set - */ - public void setCode66(Float code66) { - this.code66 = code66; - } - - /** - * @return the code67 - */ - public Float getCode67() { - return code67; - } - - /** - * @param code67 the code67 to set - */ - public void setCode67(Float code67) { - this.code67 = code67; - } - - /** - * @return the code68 - */ - public Float getCode68() { - return code68; - } - - /** - * @param code68 the code68 to set - */ - public void setCode68(Float code68) { - this.code68 = code68; - } - - /** - * @return the code69 - */ - public Float getCode69() { - return code69; - } - - /** - * @param code69 the code69 to set - */ - public void setCode69(Float code69) { - this.code69 = code69; - } - - /** - * @return the code70 - */ - public Float getCode70() { - return code70; - } - - /** - * @param code70 the code70 to set - */ - public void setCode70(Float code70) { - this.code70 = code70; - } - - /** - * @return the code71 - */ - public Float getCode71() { - return code71; - } - - /** - * @param code71 the code71 to set - */ - public void setCode71(Float code71) { - this.code71 = code71; - } - - /** - * @return the code72 - */ - public String getCode72() { - return code72; - } - - /** - * @param code72 the code72 to set - */ - public void setCode72(String code72) { - this.code72 = code72; - } - - /** - * @return the code73 - */ - public Float getCode73() { - return code73; - } - - /** - * @param code73 the code73 to set - */ - public void setCode73(Float code73) { - this.code73 = code73; - } - - /** - * @return the code74 - */ - public Float getCode74() { - return code74; - } - - /** - * @param code74 the code74 to set - */ - public void setCode74(Float code74) { - this.code74 = code74; - } - - /** - * @return the code75 - */ - public Float getCode75() { - return code75; - } - - /** - * @param code75 the code75 to set - */ - public void setCode75(Float code75) { - this.code75 = code75; - } - - /** - * @return the code76 - */ - public Float getCode76() { - return code76; - } - - /** - * @param code76 the code76 to set - */ - public void setCode76(Float code76) { - this.code76 = code76; - } - - /** - * @return the code77 - */ - public String getCode77() { - return code77; - } - - /** - * @param code77 the code77 to set - */ - public void setCode77(String code77) { - this.code77 = code77; - } - - /** - * @return the code78 - */ - public Float getCode78() { - return code78; - } - - /** - * @param code78 the code78 to set - */ - public void setCode78(Float code78) { - this.code78 = code78; - } - - /** - * @return the code79 - */ - public Float getCode79() { - return code79; - } - - /** - * @param code79 the code79 to set - */ - public void setCode79(Float code79) { - this.code79 = code79; - } - - /** - * @return the code80 - */ - public Short getCode80() { - return code80; - } - - /** - * @param code80 the code80 to set - */ - public void setCode80(Short code80) { - this.code80 = code80; - } - - /** - * @return the code81 - */ - public Short getCode81() { - return code81; - } - - /** - * @param code81 the code81 to set - */ - public void setCode81(Short code81) { - this.code81 = code81; - } - - /** - * @return the code82 - */ - public Short getCode82() { - return code82; - } - - /** - * @param code82 the code82 to set - */ - public void setCode82(Short code82) { - this.code82 = code82; - } - - /** - * @return the code83 - */ - public Float getCode83() { - return code83; - } - - /** - * @param code83 the code83 to set - */ - public void setCode83(Float code83) { - this.code83 = code83; - } - - /** - * @return the code84 - */ - public Short getCode84() { - return code84; - } - - /** - * @param code84 the code84 to set - */ - public void setCode84(Short code84) { - this.code84 = code84; - } - - /** - * @return the code85 - */ - public Short getCode85() { - return code85; - } - - /** - * @param code85 the code85 to set - */ - public void setCode85(Short code85) { - this.code85 = code85; - } - - /** - * @return the code86 - */ - public Float getCode86() { - return code86; - } - - /** - * @param code86 the code86 to set - */ - public void setCode86(Float code86) { - this.code86 = code86; - } - - /** - * @return the code87 - */ - public Float getCode87() { - return code87; - } - - /** - * @param code87 the code87 to set - */ - public void setCode87(Float code87) { - this.code87 = code87; - } - - /** - * @return the code88 - */ - public Float getCode88() { - return code88; - } - - /** - * @param code88 the code88 to set - */ - public void setCode88(Float code88) { - this.code88 = code88; - } - - /** - * @return the code89 - */ - public Float getCode89() { - return code89; - } - - /** - * @param code89 the code89 to set - */ - public void setCode89(Float code89) { - this.code89 = code89; - } - - /** - * @return the code90 - */ - public Float getCode90() { - return code90; - } - - /** - * @param code90 the code90 to set - */ - public void setCode90(Float code90) { - this.code90 = code90; - } - - /** - * @return the code91 - */ - public Float getCode91() { - return code91; - } - - /** - * @param code91 the code91 to set - */ - public void setCode91(Float code91) { - this.code91 = code91; - } - - /** - * @return the code92 - */ - public Short getCode92() { - return code92; - } - - /** - * @param code92 the code92 to set - */ - public void setCode92(Short code92) { - this.code92 = code92; - } - - /** - * @return the code93 - */ - public Float getCode93() { - return code93; - } - - /** - * @param code93 the code93 to set - */ - public void setCode93(Float code93) { - this.code93 = code93; - } - - /** - * @return the code94 - */ - public Float getCode94() { - return code94; - } - - /** - * @param code94 the code94 to set - */ - public void setCode94(Float code94) { - this.code94 = code94; - } - - /** - * @return the code95 - */ - public Float getCode95() { - return code95; - } - - /** - * @param code95 the code95 to set - */ - public void setCode95(Float code95) { - this.code95 = code95; - } - - /** - * @return the code96 - */ - public Float getCode96() { - return code96; - } - - /** - * @param code96 the code96 to set - */ - public void setCode96(Float code96) { - this.code96 = code96; - } - - /** * Get this observation's geometry. * * @return The geometry for this observation. @@ -2033,7 +2136,7 @@ IDecoderGettable { public Geometry getGeometry() { return location.getGeometry(); } - + /** * Get the geometry latitude. * @@ -2051,7 +2154,7 @@ IDecoderGettable { public Double getLongitude() { return location.getLongitude(); } - + /** * Get the elevation, in meters, of the observing platform or location. * @@ -2060,7 +2163,7 @@ IDecoderGettable { public Integer getElevation() { return location.getElevation(); } - + /** * @return the location */ @@ -2069,34 +2172,19 @@ IDecoderGettable { } /** - * @param location the location to set + * @param location + * the location to set */ public void setLocation(SurfaceObsLocation location) { this.location = location; } -// /** -// * -// * @return -// */ -// public String getNetworkType() { -// return networkType; -// } + @Override + public Amount getValue(String paramName) { + // TODO Auto-generated method stub + return null; + } -// /** -// * -// * @return -// */ -// public void setNetworkType(String type) { -// networkType = type; -// } - - @Override - public Amount getValue(String paramName) { - // TODO Auto-generated method stub - return null; - } - /** * @return the timeObs */ @@ -2118,7 +2206,7 @@ IDecoderGettable { public void setSpatialObject(SurfaceObsLocation loc) { location = loc; } - + /** * */ @@ -2126,10 +2214,10 @@ IDecoderGettable { public SurfaceObsLocation getSpatialObject() { return location; } - + /** - * This class implements IDecoderGettable so return this - * instance. + * This class implements IDecoderGettable so return this instance. + * * @return The reference to this instance. */ @Override @@ -2149,7 +2237,7 @@ IDecoderGettable { } else if (OBS_TEXT.equals(pName)) { retValue = getStationId(); } - + return retValue; } @@ -2157,35 +2245,7 @@ IDecoderGettable { public String[] getStrings(String paramName) { return null; } - -// @Override -// public Amount getValue(String paramName) { -// Amount a = null; -// String pName = PARM_MAP.get(paramName); -// -// if (SFC_TEMP.equals(pName)) { -// a = new Amount(temp, TEMPERATURE_UNIT); -// } else if (SFC_DWPT.equals(pName)) { -// a = new Amount(dwpt, TEMPERATURE_UNIT); -// } else if (SFC_WNDSPD.equals(pName)) { -// a = new Amount(windSpeed, WIND_SPEED_UNIT); -// } else if (SFC_WNDGST.equals(pName)) { -// a = new Amount(windGust, WIND_SPEED_UNIT); -// } else if (SFC_WNDDIR.equals(pName)) { -// a = new Amount(windDirection, WIND_DIR_UNIT); -// } else if (PRES_ALTSG.equals(pName)) { -// a = new Amount(altimeter, PRESSURE_UNIT); -// } else if (STA_LAT.equals(pName)) { -// a = new Amount(getLatitude(), LOCATION_UNIT); -// } else if (STA_LON.equals(pName)) { -// a = new Amount(getLongitude(), LOCATION_UNIT); -// } else if (PRES_SLP.equals(pName)) { -// a = new Amount(seaLevelPressure, PRESSURE_UNIT); -// } -// -// return a; -// } - + /** * */ @@ -2194,113 +2254,112 @@ IDecoderGettable { return null; } - /** - * @param providerId the providerId to set - */ - public void setProviderId(String providerId) { - this.providerId = providerId; - } + /** + * @param providerId + * the providerId to set + */ + public void setProviderId(String providerId) { + this.providerId = providerId; + } - /** - * @return the providerId - */ - public String getProviderId() { - return providerId; - } + /** + * @return the providerId + */ + public String getProviderId() { + return providerId; + } - /** - * @param stationName the stationName to set - */ - public void setStationName(String stationName) { - this.stationName = stationName; - } + /** + * @param stationName + * the stationName to set + */ + public void setStationName(String stationName) { + this.stationName = stationName; + } - /** - * @return the stationName - */ - public String getStationName() { - return stationName; - } + /** + * @return the stationName + */ + public String getStationName() { + return stationName; + } + /** + * @param homeWFO + * the homeWFO to set + */ + public void setHomeWFO(String homeWFO) { + this.homeWFO = homeWFO; + } - /** - * @param homeWFO the homeWFO to set - */ - public void setHomeWFO(String homeWFO) { - this.homeWFO = homeWFO; - } + /** + * @return the homeWFO + */ + public String getHomeWFO() { + return homeWFO; + } - /** - * @return the homeWFO - */ - public String getHomeWFO() { - return homeWFO; - } + /** + * @param reportType + * the reportType to set + */ + public void setReportType(Short reportType) { + this.reportType = reportType; + } - /** - * @param reportType the reportType to set - */ - public void setReportType(Short reportType) { - this.reportType = reportType; - } + /** + * @return the reportType + */ + public Short getReportType() { + return reportType; + } - /** - * @return the reportType - */ - public Short getReportType() { - return reportType; - } + /** + * @param unitsCode + * the unitsCode to set + */ + public void setUnitsCode(Short unitsCode) { + this.unitsCode = unitsCode; + } - /** - * @param unitsCode the unitsCode to set - */ - public void setUnitsCode(Short unitsCode) { - this.unitsCode = unitsCode; - } + /** + * @return the unitsCode + */ + public Short getUnitsCode() { + return unitsCode; + } - /** - * @return the unitsCode - */ - public Short getUnitsCode() { - return unitsCode; - } + /** + * @param code10 + * the code10 to set + */ + public void setCode10(Float code10) { + this.code10 = code10; + } - /** - * @param code10 the code10 to set - */ - public void setCode10(Float code10) { - this.code10 = code10; - } + /** + * @return the code10 + */ + public Float getCode10() { + return code10; + } - /** - * @return the code10 - */ - public Float getCode10() { - return code10; - } + /** + * @param code11 + * the code11 to set + */ + public void setCode11(Float code11) { + this.code11 = code11; + } - /** - * @param code11 the code11 to set - */ - public void setCode11(Float code11) { - this.code11 = code11; - } + /** + * @return the code11 + */ + public Float getCode11() { + return code11; + } - /** - * @return the code11 - */ - public Float getCode11() { - return code11; - } - -// /** -// * @param stationId the stationId to set -// */ -// public void setStationId(String stationId) { -// this.stationId = stationId; -// } - - /** + /** * Get the station identifier for this observation. * * @return the stationId @@ -2309,24 +2368,30 @@ IDecoderGettable { return location.getStationId(); } - /** - * @param rawMessage the rawMessage to set - */ - public void setRawMessage(String rawMessage) { - this.rawMessage = rawMessage; - } + /** + * @param rawMessage + * the rawMessage to set + */ + public void setRawMessage(String rawMessage) { + this.rawMessage = rawMessage; + } + + /** + * @return the rawMessage + */ + public String getRawMessage() { + return rawMessage; + } - /** - * @return the rawMessage - */ - public String getRawMessage() { - return rawMessage; - } @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } -} + @Override + public String getPluginName() { + return "ldadmanual"; + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.ldadprofiler/src/com/raytheon/edex/plugin/ldadprofiler/common/ProfilerLdadObs.java b/edexOsgi/com.raytheon.edex.plugin.ldadprofiler/src/com/raytheon/edex/plugin/ldadprofiler/common/ProfilerLdadObs.java index 3a5b5117f7..f9455f1d31 100644 --- a/edexOsgi/com.raytheon.edex.plugin.ldadprofiler/src/com/raytheon/edex/plugin/ldadprofiler/common/ProfilerLdadObs.java +++ b/edexOsgi/com.raytheon.edex.plugin.ldadprofiler/src/com/raytheon/edex/plugin/ldadprofiler/common/ProfilerLdadObs.java @@ -68,11 +68,13 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ----------- ---------- ----------- -------------------------- - * 10/07/09 vkorolev Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Oct 07, 2009 vkorolev Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -87,309 +89,305 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ldadprofiler", - indexes = { - @Index(name = "ldadprofiler_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ldadprofiler", indexes = { @Index(name = "ldadprofiler_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class ProfilerLdadObs extends PersistablePluginDataObject implements - ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { + ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { - public static final String PLUGIN_NAME = "ldadprofiler"; + public static final String PLUGIN_NAME = "ldadprofiler"; - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; - public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; + public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; - public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; - private static final HashMap PARM_MAP = new HashMap(); + private static final HashMap PARM_MAP = new HashMap(); - static { - PARM_MAP.put("NLAT", STA_LAT); - PARM_MAP.put("NLON", STA_LON); - PARM_MAP.put("WS", SFC_WNDSPD); - PARM_MAP.put("WD", SFC_WNDDIR); - } + static { + PARM_MAP.put("NLAT", STA_LAT); + PARM_MAP.put("NLON", STA_LON); + PARM_MAP.put("WS", SFC_WNDSPD); + PARM_MAP.put("WD", SFC_WNDDIR); + } - private static final String PRESS = "PRESS"; + private static final String PRESS = "PRESS"; - private static final String AGL = "AGL"; + private static final String AGL = "AGL"; - public static final String PRESS_PARAM_PTRN = ".*:" + PRESS + "=\\d{2,4}"; + public static final String PRESS_PARAM_PTRN = ".*:" + PRESS + "=\\d{2,4}"; - public static final String AGL_PARAM_PTRN = ".*:" + AGL + "=\\d{2,4}"; + public static final String AGL_PARAM_PTRN = ".*:" + AGL + "=\\d{2,4}"; - @Transient - private String parameterName = null; + @Transient + private String parameterName = null; - @DataURI(position = 1) - @XmlAttribute - @DynamicSerializeElement - private Integer reportType; + @DataURI(position = 1) + @XmlAttribute + @DynamicSerializeElement + private Integer reportType; - // Location - @Embedded - @DataURI(position = 2, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; // latitude, longitude, elevation, + // Location + @Embedded + @DataURI(position = 2, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; // latitude, longitude, elevation, - // stationId + // stationId - // Base time in Epoch "seconds since 1970-01-01 00:00:00 UTC" - @Column - @DynamicSerializeElement - @XmlElement - int base_time; + // Base time in Epoch "seconds since 1970-01-01 00:00:00 UTC" + @Column + @DynamicSerializeElement + @XmlElement + int base_time; - // Consensus start time offset from base_time - // "seconds since 2009/10/07 00:00:00 UTC" - @Column - @DynamicSerializeElement - @XmlElement - double start_time_offset; + // Consensus start time offset from base_time + // "seconds since 2009/10/07 00:00:00 UTC" + @Column + @DynamicSerializeElement + @XmlElement + double start_time_offset; - // Consensus end time offset from base_time - // "seconds since 2009/10/07 00:00:00 UTC" - @Column - @DynamicSerializeElement - @XmlElement - double end_time_offset; + // Consensus end time offset from base_time + // "seconds since 2009/10/07 00:00:00 UTC" + @Column + @DynamicSerializeElement + @XmlElement + double end_time_offset; - // nhts Number of heights? - @Column - @DynamicSerializeElement - @XmlElement - int nhts; + // nhts Number of heights? + @Column + @DynamicSerializeElement + @XmlElement + int nhts; - // the level data - @XmlElement - @DynamicSerializeElement - @Transient - private List levels; + // the level data + @XmlElement + @DynamicSerializeElement + @Transient + private List levels; - // The profiler observation time. - @Column - @XmlAttribute - @DynamicSerializeElement - private Calendar timeObs; + // The profiler observation time. + @Column + @XmlAttribute + @DynamicSerializeElement + private Calendar timeObs; - @Column - @XmlAttribute - @DynamicSerializeElement - private String stationName; + @Column + @XmlAttribute + @DynamicSerializeElement + private String stationName; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - /** - * @return the base_time - */ - public int getBase_time() { - return base_time; - } + /** + * @return the base_time + */ + public int getBase_time() { + return base_time; + } - /** - * @param base_time - * the base_time to set - */ - public void setBase_time(int base_time) { - this.base_time = base_time; - } + /** + * @param base_time + * the base_time to set + */ + public void setBase_time(int base_time) { + this.base_time = base_time; + } - public Calendar getTimeObs() { - return timeObs; - } + public Calendar getTimeObs() { + return timeObs; + } - public void setTimeObs(Calendar timeObs) { - this.timeObs = timeObs; - } + public void setTimeObs(Calendar timeObs) { + this.timeObs = timeObs; + } - /** - * @return the start_time_offset - */ - public double getStart_time_offset() { - return start_time_offset; - } + /** + * @return the start_time_offset + */ + public double getStart_time_offset() { + return start_time_offset; + } - /** - * @param start_time_offset - * the start_time_offset to set - */ - public void setStart_time_offset(double start_time_offset) { - this.start_time_offset = start_time_offset; - } + /** + * @param start_time_offset + * the start_time_offset to set + */ + public void setStart_time_offset(double start_time_offset) { + this.start_time_offset = start_time_offset; + } - /** - * @return the end_time_offset - */ - public double getEnd_time_offset() { - return end_time_offset; - } + /** + * @return the end_time_offset + */ + public double getEnd_time_offset() { + return end_time_offset; + } - /** - * @param end_time_offset - * the end_time_offset to set - */ - public void setEnd_time_offset(double end_time_offset) { - this.end_time_offset = end_time_offset; - } + /** + * @param end_time_offset + * the end_time_offset to set + */ + public void setEnd_time_offset(double end_time_offset) { + this.end_time_offset = end_time_offset; + } - /** - * @return the nhts - */ - public int getNhts() { - return nhts; - } + /** + * @return the nhts + */ + public int getNhts() { + return nhts; + } - /** - * @param nhts - * the nhts to set - */ - public void setNhts(int nhts) { - this.nhts = nhts; - } + /** + * @param nhts + * the nhts to set + */ + public void setNhts(int nhts) { + this.nhts = nhts; + } - /** - * @return the levels - */ - public List getLevels() { - return levels; - } + /** + * @return the levels + */ + public List getLevels() { + return levels; + } - /** - * @param levels - * the levels to set - */ - public void setLevels(List levels) { - this.levels = levels; - } + /** + * @param levels + * the levels to set + */ + public void setLevels(List levels) { + this.levels = levels; + } - /** - * @return the pointDataView - */ - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + /** + * @return the pointDataView + */ + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - public ProfilerLdadObs() { - } + public ProfilerLdadObs() { + } - /** - * @param pointDataView - * the pointDataView to set - */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + /** + * @param pointDataView + * the pointDataView to set + */ + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - // ---------------------------------------------------- + // ---------------------------------------------------- - @Override - public IDecoderGettable getDecoderGettable() { - // TODO Auto-generated method stub - return null; - } + @Override + public IDecoderGettable getDecoderGettable() { + // TODO Auto-generated method stub + return null; + } - @Override - public ISpatialObject getSpatialObject() { - // TODO Auto-generated method stub - return null; - } + @Override + public ISpatialObject getSpatialObject() { + // TODO Auto-generated method stub + return null; + } - @Override - public String getString(String paramName) { - // TODO Auto-generated method stub - return null; - } + @Override + public String getString(String paramName) { + // TODO Auto-generated method stub + return null; + } - @Override - public String[] getStrings(String paramName) { - // TODO Auto-generated method stub - return null; - } + @Override + public String[] getStrings(String paramName) { + // TODO Auto-generated method stub + return null; + } - @Override - public Amount getValue(String paramName) { - // TODO Auto-generated method stub - return null; - } + @Override + public Amount getValue(String paramName) { + // TODO Auto-generated method stub + return null; + } - @Override - public Collection getValues(String paramName) { - // TODO Auto-generated method stub - return null; - } + @Override + public Collection getValues(String paramName) { + // TODO Auto-generated method stub + return null; + } - /** - * @param location - * the location to set - */ - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + /** + * @param location + * the location to set + */ + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - /** - * @return the location - */ - public SurfaceObsLocation getLocation() { - return location; - } + /** + * @return the location + */ + public SurfaceObsLocation getLocation() { + return location; + } - /** - * @param stationName - * the stationName to set - */ - public void setStationName(String stationName) { - this.stationName = stationName; - } + /** + * @param stationName + * the stationName to set + */ + public void setStationName(String stationName) { + this.stationName = stationName; + } - /** - * @return the stationName - */ - public String getStationName() { - return stationName; - } + /** + * @return the stationName + */ + public String getStationName() { + return stationName; + } - /** - * @param parameterName - * the parameterName to set - */ - public void setParameterName(String parameterName) { - this.parameterName = parameterName; - } + /** + * @param parameterName + * the parameterName to set + */ + public void setParameterName(String parameterName) { + this.parameterName = parameterName; + } - /** - * @return the parameterName - */ - public String getParameterName() { - return parameterName; - } + /** + * @return the parameterName + */ + public String getParameterName() { + return parameterName; + } - /** - * @param reportType - * the reportType to set - */ - public void setReportType(Integer reportType) { - this.reportType = reportType; - } + /** + * @param reportType + * the reportType to set + */ + public void setReportType(Integer reportType) { + this.reportType = reportType; + } - /** - * @return the reportType - */ - public Integer getReportType() { - return reportType; - } + /** + * @return the reportType + */ + public Integer getReportType() { + return reportType; + } @Override @Column @@ -397,4 +395,9 @@ public class ProfilerLdadObs extends PersistablePluginDataObject implements public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ldadprofiler"; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingDecoder.java b/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingDecoder.java index 25a3ec5f55..e5298d6f6f 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingDecoder.java @@ -59,21 +59,24 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080303 1026 jkorman Initial implementation. - * 20080408 1039 jkorman Added traceId for tracing data. - * 11/25/08 #1684 chammack Camel Refactor - * 04/29/13 #1861 bkowal Create a separate Point Data Container for - * every record so each forecast hour will - * receive a unique hdf5 file. - * 07/03/13 #2161 bkowal Store and retrieve the Point Data Containers - * by forecast hour and reftime when completing - * a decode operation. Overrode default - * Point Data Container size. - * 07/16/13 #2161 bkowal Store the records in a container that will - * be persisted every X (configurable) seconds - * by a timer. The timer is started during spring - * initialization and destroyed during spring - * container destruction. + * Mar 03, 2008 1026 jkorman Initial implementation. + * Apr 08, 2008 1039 jkorman Added traceId for tracing data. + * Nov 25, 2008 1684 chammack Camel Refactor + * Apr 29, 2013 1861 bkowal Create a separate Point Data Container + * for every record so each forecast hour + * will receive a unique hdf5 file. + * Jul 03, 2013 2161 bkowal Store and retrieve the Point Data + * Containers by forecast hour and reftime + * when completing a decode operation. + * Overrode default Point Data Container + * size. + * Jul 16, 2013 2161 bkowal Store the records in a container that + * will be persisted every X (configurable) + * seconds by a timer. The timer is started + * during spring initialization and + * destroyed during spring container + * destruction. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -219,7 +222,6 @@ public class ModelSoundingDecoder extends AbstractDecoder implements soundingTemporalData); if (soundingData != null) { soundingData.setTraceId(traceId); - soundingData.setPluginName(PLUGIN_NAME); try { soundingData.constructDataURI(); } catch (PluginException e) { diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingSite.java b/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingSite.java index b0e832e9ad..201c62ea29 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingSite.java +++ b/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingSite.java @@ -62,11 +62,13 @@ import com.vividsolutions.jts.geom.Geometry; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080303 1026 jkorman Initial implementation. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Mar 03, 2008 1026 jkorman Initial implementation. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -911,10 +913,16 @@ public class SoundingSite extends PersistablePluginDataObject implements public void setPointDataView(PointDataView pointDataView) { this.pointDataView = pointDataView; } + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "modelsounding"; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.obs/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.edex.plugin.obs/META-INF/MANIFEST.MF index 7c388cd7e5..17b41129bd 100644 --- a/edexOsgi/com.raytheon.edex.plugin.obs/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.edex.plugin.obs/META-INF/MANIFEST.MF @@ -7,7 +7,6 @@ Eclipse-RegisterBuddy: com.raytheon.edex.common, com.raytheon.uf.common.serializ Bundle-Vendor: RAYTHEON Export-Package: com.raytheon.edex.plugin.obs, com.raytheon.edex.plugin.obs.mesowest, - com.raytheon.edex.plugin.obs.mesowest.util, com.raytheon.edex.plugin.obs.metar, com.raytheon.edex.plugin.obs.metar.util, com.raytheon.edex.uengine.tasks.obs diff --git a/edexOsgi/com.raytheon.edex.plugin.obs/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject b/edexOsgi/com.raytheon.edex.plugin.obs/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject deleted file mode 100644 index 9ec19727e4..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.obs/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject +++ /dev/null @@ -1 +0,0 @@ -com.raytheon.edex.plugin.obs.mesowest.MesowestRecord \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.obs/res/spring/obs-ingest.xml b/edexOsgi/com.raytheon.edex.plugin.obs/res/spring/obs-ingest.xml index cd52a3a7e1..5bec4f52ae 100644 --- a/edexOsgi/com.raytheon.edex.plugin.obs/res/spring/obs-ingest.xml +++ b/edexOsgi/com.raytheon.edex.plugin.obs/res/spring/obs-ingest.xml @@ -3,9 +3,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - - + diff --git a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/ObsDecoder.java b/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/ObsDecoder.java index d6b488f34c..f53857e922 100644 --- a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/ObsDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/ObsDecoder.java @@ -20,30 +20,6 @@ package com.raytheon.edex.plugin.obs; -/** - * Decoder implementation for observation data types. This class provides a - * wrapper in order to select the correct decoder based on the data type - * - *
- *                     
- * SOFTWARE HISTORY
- * 
- * Date          Ticket#     Engineer    Description
- * -----------  ----------  ----------- --------------------------
- * 4/27/07      199         bphillip    Initial creation
- * 07/31/2007          411  jkorman     Added addition logging
- * 08/10/2007          379  jkorman     Added disposal behavior.
- * 20071217            453  jkorman     Added code to check for duplicate obs.
- * 20080314            995  jkorman     Changed setDecoderStrategy to check for
- *                                      empty data.
- * 20080408           1039  jkorman     Added traceId for tracing data.  
- * Mar 19, 2013       1785  bgonzale    Added performance status handler and added
- *                                      status to decode.
- * 
- * - * @author bphillip - * @version 1 - */ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -58,24 +34,40 @@ import com.raytheon.uf.common.time.util.ITimer; import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.edex.wmo.message.WMOHeader; +/** + * Decoder implementation for observation data types. This class provides a + * wrapper in order to select the correct decoder based on the data type + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * -----------  ----------  ----------- --------------------------
+ * Apr 27, 2007 199         bphillip    Initial creation
+ * Jul 31, 2007 411         jkorman     Added addition logging
+ * Aug 10, 2007 379         jkorman     Added disposal behavior.
+ * Dec 17, 2007 453         jkorman     Added code to check for duplicate obs.
+ * Mar 14, 2008 995         jkorman     Changed setDecoderStrategy to check for
+ *                                      empty data.
+ * Apr 08, 2008 1039        jkorman     Added traceId for tracing data.  
+ * Mar 19, 2013 1785        bgonzale    Added performance status handler and added
+ *                                      status to decode.
+ * Aug 30, 2013 2298        rjpeter     Make getPluginName abstract
+ * 
+ * + * @author bphillip + * @version 1 + */ public class ObsDecoder extends AbstractDecoder { /** The logger */ - private Log logger = LogFactory.getLog(getClass()); - - private final String PLUGIN_NAME; + private final Log logger = LogFactory.getLog(getClass()); private final IPerformanceStatusHandler perfLog = PerformanceStatus .getHandler("Obs:"); private String traceId = null; - /** - * Required empty constructor. - */ - public ObsDecoder(String pluginName) { - PLUGIN_NAME = pluginName; - } - /** * * @return A decoded data record. @@ -139,13 +131,13 @@ public class ObsDecoder extends AbstractDecoder { if ('S' == header.getT1()) { switch (header.getT2()) { case 'A': { - decoder = new MetarDecoder(PLUGIN_NAME); - ((MetarDecoder) decoder).setTraceId(traceId); + decoder = new MetarDecoder(); + decoder.setTraceId(traceId); break; } case 'P': { - decoder = new MetarDecoder(PLUGIN_NAME); - ((MetarDecoder) decoder).setTraceId(traceId); + decoder = new MetarDecoder(); + decoder.setTraceId(traceId); break; } } diff --git a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/MesowestDecoder.java b/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/MesowestDecoder.java deleted file mode 100644 index 3bf446464c..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/MesowestDecoder.java +++ /dev/null @@ -1,150 +0,0 @@ -/** - * 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.edex.plugin.obs.mesowest; - -import java.text.DecimalFormat; - -import com.raytheon.edex.esb.Headers; -import com.raytheon.edex.exception.DecoderException; -import com.raytheon.edex.plugin.AbstractDecoder; -import com.raytheon.edex.util.Util; -import com.raytheon.uf.common.dataplugin.PluginDataObject; -import com.raytheon.uf.common.time.DataTime; -import com.raytheon.uf.edex.decodertools.core.DecoderTools; -import com.raytheon.uf.edex.decodertools.time.TimeTools; - -/** - * Decoder implementation for mesowest plugin - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date       	Ticket#		Engineer	Description
- * ------------	----------	-----------	--------------------------
- * 02/14/06		139			bphillip	Initial creation	
- * 11/11/08     1684        chammack    Refactored to camel interfaces
- * 
- * 
- * - * @author bphillip - * @version 1 - */ - -public class MesowestDecoder extends AbstractDecoder { - - private static final DecimalFormat DECIMALTENTHS = new DecimalFormat("#.#"); - - private static final DecimalFormat WHOLENUMBER = new DecimalFormat("#"); - - /** - * Constructor - * - * @throws DecoderException - */ - public MesowestDecoder() throws DecoderException { - } - - /* - * (non-Javadoc) - * - * @see com.raytheon.edex.plugin.IBinaryDecoder#decode(byte[]) - */ - public PluginDataObject[] decode(byte[] data, Headers headers) - throws DecoderException { - - byte[] messageData = null; - - String theMessage = new String(messageData); - - MesowestRecord record = new MesowestRecord(); - record.setMessageData(theMessage); - record.setPluginName("obs"); - record.setReportType("MESOWEST"); - record.setMessageData(theMessage); - - String[] mwObs = theMessage.split(","); - try { - if (mwObs.length >= 7) { - record.setStationID(mwObs[1]); - String timeGroup = mwObs[6].substring(6, 8) - + mwObs[6].substring(9, 13) + "Z"; - String fileName = null; - if (headers != null) { - fileName = (String) headers - .get(DecoderTools.INGEST_FILE_NAME); - } - record.setTimeObs(TimeTools - .findCurrentTime(timeGroup, fileName)); - record.setDataTime(new DataTime(Util - .findReferenceTime(timeGroup))); - record.setRefHour(Util.findReferenceHour(timeGroup)); - } - // Only want the observations in columns 7 through 15 - int mwArrayLength = mwObs.length < 17 ? mwObs.length : 17; - for (int i = 7; i < mwArrayLength; i++) { - if (i == 7 && mwObs[7].length() > 0) { - double temp = calculateCelsius(mwObs[7]); - record.setTemperature(Integer.parseInt(WHOLENUMBER - .format(temp))); - record.setTempFromTenths(Float.parseFloat(DECIMALTENTHS - .format(temp))); - } else if (i == 9 && mwObs[9].length() > 0) { - double wSpeed = Double.valueOf(mwObs[9].trim()) - .doubleValue(); - record.setWindSpeed(Integer.parseInt(WHOLENUMBER - .format(wSpeed))); - } else if (i == 10 && mwObs[10].length() > 0) { - double wGust = Double.valueOf(mwObs[10].trim()) - .doubleValue(); - record.setWindGust(Integer.parseInt(WHOLENUMBER - .format(wGust))); - } else if (i == 11 && mwObs[11].length() > 0) { - record.setWindDir(mwObs[11]); - } else if (i == 13 && mwObs[13].length() > 0) { - double dewp = calculateCelsius(mwObs[13]); - record.setDewPoint(Integer.parseInt(WHOLENUMBER - .format(dewp))); - record.setDewPointFromTenths(Float.parseFloat(DECIMALTENTHS - .format(dewp))); - } else if (i == 15 && mwObs[15].length() > 0) { - record.setSeaLevelPress(Float.parseFloat(mwObs[15])); - } else if (i == 16 && mwObs[16].length() > 0) { - record.setAltimeter(Float.parseFloat(mwObs[16])); - } - } - - } catch (Exception e) { - throw new DecoderException("Unable to decode Mesowest data", e); - } - - if (record == null) - return new PluginDataObject[0]; - return new PluginDataObject[] { record }; - } - - private double calculateCelsius(String tempString) { - double temp = Double.valueOf(tempString.trim()).doubleValue(); - double tempC = (temp - 32.0) * (5.0 / 9.0); - return tempC; - } - -} diff --git a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/MesowestRecord.java b/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/MesowestRecord.java deleted file mode 100644 index 556dd016b9..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/mesowest/MesowestRecord.java +++ /dev/null @@ -1,361 +0,0 @@ -/** - * 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.edex.plugin.obs.mesowest; - -import java.util.Calendar; - -import javax.persistence.Access; -import javax.persistence.AccessType; -import javax.persistence.Column; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -import com.raytheon.uf.common.dataplugin.IDecoderGettable; -import com.raytheon.uf.common.dataplugin.PluginDataObject; -import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; -import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; - -/** - * Record implementation for mesowest plugin - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date       	Ticket#		Engineer	Description
- * ------------	----------	-----------	--------------------------
- * 2/14/2007	139			Phillippe	Initial creation	
- * 20071129            472  jkorman     Added IDecoderGettable interface.
- * May 07, 2013	1869      	bsteffen   	Remove dataURI column from
- *                                      PluginDataObject.
- * 
- * 
- * 
- * - * @author bphillip - * @version 1 - */ -@XmlRootElement -@XmlAccessorType(XmlAccessType.NONE) -@DynamicSerialize -public class MesowestRecord extends PluginDataObject { - - private static final long serialVersionUID = 1L; - - /** A string denoting the report type */ - @XmlAttribute - @DynamicSerializeElement - private String reportType; - - /** A string denoting the reporting station */ - @XmlAttribute - @DynamicSerializeElement - private String stationID; - - /** A string denoting the time of observation */ - @XmlElement - @DynamicSerializeElement - private Calendar timeObs; - - /** A string denoting the temperature in degrees Celsius */ - @XmlAttribute - @DynamicSerializeElement - private Integer temperature; - - /** A string denoting the current temperature in tenths of degrees Celsius */ - @XmlAttribute - @DynamicSerializeElement - private Float tempFromTenths; - - /** A string denoting the wind direction in degrees from north */ - @XmlAttribute - @DynamicSerializeElement - private String windDir; - - /** A string denoting the wind speed in knots */ - @XmlAttribute - @DynamicSerializeElement - private Integer windSpeed; - - /** A string denoting the wind gusts in knots */ - @XmlAttribute - @DynamicSerializeElement - private Integer windGust; - - /** A string denoting the current dew point in degrees Celsius */ - @XmlAttribute - @DynamicSerializeElement - private Integer dewPoint; - - /** A string denoting the current dew point in tenths of degrees Celsius */ - @XmlAttribute - @DynamicSerializeElement - private Float dewPointFromTenths; - - /** A string denoting the altimeter reading in in/Hg */ - @XmlAttribute - @DynamicSerializeElement - private Float altimeter; - - /** A string denoting the sea level pressure in millibars */ - @XmlAttribute - @DynamicSerializeElement - private Float seaLevelPress; - - /** The reference hour * */ - @XmlElement - @DynamicSerializeElement - private Calendar refHour; - - /** - * No argument constructor - * - */ - public MesowestRecord() { - } - - /** - * Constructs a mesowest record from a dataURI - * - * @param uri - * The dataURI - * @param tableDef - * The table definition associated with this class - */ - public MesowestRecord(String uri) { - super(uri); - } - - /** - * @return the reportType - */ - public String getReportType() { - return reportType; - } - - /** - * @param reportType - * the reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } - - /** - * @return the altimeter - */ - public Float getAltimeter() { - return altimeter; - } - - /** - * @param altimeter - * the altimeter to set - */ - public void setAltimeter(Float altimeter) { - this.altimeter = altimeter; - } - - /** - * @return the dewPoint - */ - public Integer getDewPoint() { - return dewPoint; - } - - /** - * @param dewPoint - * the dewPoint to set - */ - public void setDewPoint(Integer dewPoint) { - this.dewPoint = dewPoint; - } - - /** - * @return the dewPointFromTenths - */ - public Float getDewPointFromTenths() { - return dewPointFromTenths; - } - - /** - * @param dewPointFromTenths - * the dewPointFromTenths to set - */ - public void setDewPointFromTenths(Float dewPointFromTenths) { - this.dewPointFromTenths = dewPointFromTenths; - } - - /** - * @return the refHour - */ - public Calendar getRefHour() { - return refHour; - } - - /** - * @param refHour - * the refHour to set - */ - public void setRefHour(Calendar refHour) { - this.refHour = refHour; - } - - /** - * @return the seaLevelPress - */ - public Float getSeaLevelPress() { - return seaLevelPress; - } - - /** - * @param seaLevelPress - * the seaLevelPress to set - */ - public void setSeaLevelPress(Float seaLevelPress) { - this.seaLevelPress = seaLevelPress; - } - - /** - * @return the stationID - */ - public String getStationID() { - return stationID; - } - - /** - * @param stationID - * the stationID to set - */ - public void setStationID(String stationID) { - this.stationID = stationID; - } - - /** - * @return the temperature - */ - public Integer getTemperature() { - return temperature; - } - - /** - * @param temperature - * the temperature to set - */ - public void setTemperature(Integer temperature) { - this.temperature = temperature; - } - - /** - * @return the tempFromTenths - */ - public Float getTempFromTenths() { - return tempFromTenths; - } - - /** - * @param tempFromTenths - * the tempFromTenths to set - */ - public void setTempFromTenths(Float tempFromTenths) { - this.tempFromTenths = tempFromTenths; - } - - /** - * @return the timeObs - */ - public Calendar getTimeObs() { - return timeObs; - } - - /** - * @param timeObs - * the timeObs to set - */ - public void setTimeObs(Calendar timeObs) { - this.timeObs = timeObs; - } - - /** - * @return the windDir - */ - public String getWindDir() { - return windDir; - } - - /** - * @param windDir - * the windDir to set - */ - public void setWindDir(String windDir) { - this.windDir = windDir; - } - - /** - * @return the windGust - */ - public Integer getWindGust() { - return windGust; - } - - /** - * @param windGust - * the windGust to set - */ - public void setWindGust(Integer windGust) { - this.windGust = windGust; - } - - /** - * @return the windSpeed - */ - public Integer getWindSpeed() { - return windSpeed; - } - - /** - * @param windSpeed - * the windSpeed to set - */ - public void setWindSpeed(Integer windSpeed) { - this.windSpeed = windSpeed; - } - - /** - * Get the IDecoderGettable reference for this record. - * - * @return The IDecoderGettable reference for this record. Null for this - * class. - */ - public IDecoderGettable getDecoderGettable() { - return null; - } - - @Override - @Column - @Access(AccessType.PROPERTY) - public String getDataURI() { - return super.getDataURI(); - } -} diff --git a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarDecoder.java b/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarDecoder.java index 357d7bd238..fd0f96eed5 100644 --- a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarDecoder.java @@ -54,29 +54,30 @@ import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; * * SOFTWARE HISTORY * - * ate Ticket# Engineer Description - * ----------- ---------- ----------- -------------------------- - * 2/14/07 139 bphillip Initial creation - * 20071029 505 jkorman Changed setting of DataTime from refhour + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 14, 2007 139 bphillip Initial creation + * Oct 29, 2007 505 jkorman Changed setting of DataTime from refhour * to observation time. - * 20071128 575 jkorman Added future obs time threshold check in + * Nov 28, 2007 575 jkorman Added future obs time threshold check in * decode. - * 12/07/07 452 bphillip Retrieve lat/lon info from station table - * 12/17/07 628 bphillip Discarding data with no station info - * 20071217 453 jkorman Major restructure of the decode method + * Dec 07, 2007 452 bphillip Retrieve lat/lon info from station table + * Dec 17, 2007 628 bphillip Discarding data with no station info + * Dec 17, 2007 453 jkorman Major restructure of the decode method * to ensure that all sections are decoded * properly. Added cleanMessage method. - * 20071218 453 jkorman Added metric winds and visibility. - * 20071221 665 jkorman Modified metric vis to ensure it is not + * Dec 18, 2007 453 jkorman Added metric winds and visibility. + * Dec 21, 2007 665 jkorman Modified metric vis to ensure it is not * decoding alstg data. Added checks for * NSC, NCD, and CAVOK. Added checks for * metric sector vis. - * 20080102 667 jkorman Added code to properly decode/store clear - * sky conditions. - * 20080116 798 jkorman Changed logging levels. - * 20080414 996 jkorman Rewrote sky cover decode section to handle - * CB/TCU and /// data. - * 11/11/08 1684 chammack Camel refactor. + * Jan 02, 2008 667 jkorman Added code to properly decode/store + * clear sky conditions. + * Jan 16, 2008 798 jkorman Changed logging levels. + * Apr 14, 2008 996 jkorman Rewrote sky cover decode section to + * handle CB/TCU and /// data. + * Nov 11, 2008 1684 chammack Camel refactor. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author bphillip @@ -185,8 +186,6 @@ public class MetarDecoder extends AbstractDecoder { public static final Pattern SUNSHINE = Pattern .compile("(\\b)98(\\d{3}|///)"); - private final String PLUGIN_NAME; - private boolean useMockInfo = false; private ObStation mockInfo = null; @@ -195,8 +194,7 @@ public class MetarDecoder extends AbstractDecoder { private String traceId = null; - public MetarDecoder(String pluginName) throws DecoderException { - PLUGIN_NAME = pluginName; + public MetarDecoder() { VIS_PARSER = new VisibilityParser(); } @@ -924,7 +922,6 @@ public class MetarDecoder extends AbstractDecoder { record.setSunshine(value); } - record.setPluginName(PLUGIN_NAME); record.constructDataURI(); record.setWmoHeader(sep.getWMOHeader().getWmoHeader()); @@ -1008,7 +1005,7 @@ public class MetarDecoder extends AbstractDecoder { StringBuilder sb = null; if (data != null) { sb = new StringBuilder(data); - for (int i = 0; i < sb.length() - 1; i++) { + for (int i = 0; i < (sb.length() - 1); i++) { if (sb.charAt(i) == '0') { sb.setCharAt(i, ' '); } diff --git a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarPointDataTransform.java b/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarPointDataTransform.java index 927378c2ff..8ca48f7421 100644 --- a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarPointDataTransform.java +++ b/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarPointDataTransform.java @@ -59,6 +59,7 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * dimensioned size. * May 09, 2013 1869 bsteffen Modified D2D time series of point data to * work without dataURI. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -68,7 +69,7 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; public class MetarPointDataTransform { - public static final String ALTIMETER = "altimeter"; + public static final String ALTIMETER = "altimeter"; public static final String SEA_LEVEL_PRESS = "seaLevelPress"; @@ -232,8 +233,9 @@ public class MetarPointDataTransform { Map pointMap = new HashMap(); for (PluginDataObject p : pdo) { - if (!(p instanceof MetarRecord)) + if (!(p instanceof MetarRecord)) { continue; + } File f = this.dao.getFullFilePath(p); PointDataContainer pdc = pointMap.get(f); @@ -254,7 +256,7 @@ public class MetarPointDataTransform { MetarRecord record) { PointDataView pdv = container.append(); - if (record.getCorrection() != null + if ((record.getCorrection() != null) && record.getCorrection().equals("COR")) { pdv.setInt(CORRECTION, 1); } else { @@ -272,12 +274,12 @@ public class MetarPointDataTransform { if (record.getSkyCoverage() != null) { int maxSize = container.getDescription(SKY_COVER) - .getDimensionAsInt(); + .getDimensionAsInt(); record.sort(record.getSkyCoverage()); Iterator scIterator = record.getSkyCoverage().iterator(); int i = 0; while (scIterator.hasNext()) { - if(i >= maxSize) { + if (i >= maxSize) { break; } // TODO: storing duplicate info like this, needs to be resolved @@ -285,8 +287,9 @@ public class MetarPointDataTransform { if (sc.getType() != null) { StringBuffer scBuffer = new StringBuffer(); scBuffer.append(sc.getType()); - if (sc.getGenus() != null) + if (sc.getGenus() != null) { scBuffer.append(sc.getGenus()); + } pdv.setString(SKY_COVER, scBuffer.toString(), i); if (sc.getType() != null) { @@ -346,7 +349,7 @@ public class MetarPointDataTransform { pdv.setFloat(SNOWFALL6_HOUR, record.getSnowFall_6Hours()); pdv.setInt(SUNSHINE, record.getSunshine()); - if (record.getWindDir() != null + if ((record.getWindDir() != null) && !record.getWindDir().equalsIgnoreCase("VRB")) { pdv.setFloat("windDir", Float.parseFloat(record.getWindDir())); } @@ -415,7 +418,6 @@ public class MetarPointDataTransform { mr.setPressChange3Hour(pdv.getNumber(PRESS_CHANGE3_HOUR).floatValue()); mr.setPressChangeChar(pdv.getString(PRESS_CHANGE_CHAR)); - mr.setPluginName("obs"); mr.setPrecip1Hour(pdv.getNumber(PRECIP1_HOUR).floatValue()); mr.setPrecip3Hour(pdv.getNumber(PRECIP3_HOUR).floatValue()); mr.setPrecip6Hour(pdv.getNumber(PRECIP6_HOUR).floatValue()); @@ -427,7 +429,7 @@ public class MetarPointDataTransform { int i = 0; Set scList = new HashSet(); for (String s : scType) { - if (s != null && !s.equals("")) { + if ((s != null) && !s.equals("")) { SkyCover skyCover = new SkyCover(); skyCover.setType(s); diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/PirepDecoder.java b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/PirepDecoder.java index dd4922a752..8d8c3f6f66 100644 --- a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/PirepDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/PirepDecoder.java @@ -59,10 +59,11 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080103 384 jkorman Initial Coding. - * 20080128 861 jkorman Add pirep layer data. - * 20080408 1039 jkorman Added traceId for tracing data. - * 11/13/08 1684 chammack Camel Refactor + * Jan 03, 2008 384 jkorman Initial Coding. + * Jan 28, 2008 861 jkorman Add pirep layer data. + * Apr 08, 2008 1039 jkorman Added traceId for tracing data. + * Nov 13, 2008 1684 chammack Camel Refactor + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author jkorman @@ -108,7 +109,6 @@ public class PirepDecoder extends AbstractDecoder { if (report != null) { report.setTraceId(traceId); - report.setPluginName(PLUGIN_NAME); try { report.constructDataURI(); } catch (PluginException e) { @@ -181,8 +181,7 @@ public class PirepDecoder extends AbstractDecoder { record.setHorzVisibility(parser.getHorxVisibility()); // Collect the decoded icing flight conditions data - List icing = parser - .getIcingLayers(); + List icing = parser.getIcingLayers(); if (icing != null) { PirepLayerData iceLayer = null; for (AircraftFlightCondition layer : icing) { @@ -250,7 +249,7 @@ public class PirepDecoder extends AbstractDecoder { } if (traceIdx >= 0) { newTrace = new StackTraceElement[traceIdx + 1]; - for (int j = 0; j < traceIdx + 1; j++) { + for (int j = 0; j < (traceIdx + 1); j++) { newTrace[j] = trace[j]; } e.setStackTrace(newTrace); diff --git a/edexOsgi/com.raytheon.edex.plugin.poessounding/src/com/raytheon/edex/plugin/poessounding/POESSoundingDecoder.java b/edexOsgi/com.raytheon.edex.plugin.poessounding/src/com/raytheon/edex/plugin/poessounding/POESSoundingDecoder.java index 52f7e87a87..9bf246cfb8 100644 --- a/edexOsgi/com.raytheon.edex.plugin.poessounding/src/com/raytheon/edex/plugin/poessounding/POESSoundingDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.poessounding/src/com/raytheon/edex/plugin/poessounding/POESSoundingDecoder.java @@ -57,6 +57,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * Mar 03, 2008 1026 jkorman Initial implementation. * Apr 08, 2008 1039 jkorman Added traceId for tracing data. * May 15, 2013 1869 bsteffen Remove DataURI from goes/poes soundings. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -70,7 +71,7 @@ public class POESSoundingDecoder extends AbstractDecoder implements public static final String PLUGIN_NAME = "poessounding"; /** The logger */ - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); private PointDataDescription pdd; @@ -118,7 +119,7 @@ public class POESSoundingDecoder extends AbstractDecoder implements PluginDataObject[] decodedData = null; - if (data != null && data.length > 0) { + if ((data != null) && (data.length > 0)) { WMOHeader wmoHeader = new WMOHeader(data, headers); @@ -144,7 +145,6 @@ public class POESSoundingDecoder extends AbstractDecoder implements container); if (soundingData != null) { soundingData.setTraceId(traceId); - soundingData.setPluginName(PLUGIN_NAME); pdoList.add(soundingData); } } diff --git a/edexOsgi/com.raytheon.edex.plugin.profiler/src/com/raytheon/edex/plugin/profiler/ProfilerDecoder.java b/edexOsgi/com.raytheon.edex.plugin.profiler/src/com/raytheon/edex/plugin/profiler/ProfilerDecoder.java index 475f038dc4..b82e388f07 100644 --- a/edexOsgi/com.raytheon.edex.plugin.profiler/src/com/raytheon/edex/plugin/profiler/ProfilerDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.profiler/src/com/raytheon/edex/plugin/profiler/ProfilerDecoder.java @@ -56,8 +56,9 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080303 969 jkorman Initial implementation. - * 20080408 1039 jkorman Added traceId for tracing data. + * Mar 03, 2008 969 jkorman Initial implementation. + * Apr 08, 2008 1039 jkorman Added traceId for tracing data. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -71,7 +72,7 @@ public class ProfilerDecoder extends AbstractDecoder implements public static final String PLUGIN_NAME = "profiler"; /** The logger */ - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); private PointDataDescription pdd; @@ -131,7 +132,7 @@ public class ProfilerDecoder extends AbstractDecoder implements PluginDataObject[] decodedData = null; - if (data != null && data.length > 0) { + if ((data != null) && (data.length > 0)) { WMOHeader wmoHeader = new WMOHeader(data, headers); if ((wmoHeader != null) && (wmoHeader.isValid())) { @@ -160,7 +161,6 @@ public class ProfilerDecoder extends AbstractDecoder implements container, traceId); if (soundingData != null) { soundingData.setTraceId(traceId); - soundingData.setPluginName(PLUGIN_NAME); try { soundingData.constructDataURI(); PointDataView view = soundingData diff --git a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecoder.java b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecoder.java index fddb62a83a..dfa8f257f0 100644 --- a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecoder.java @@ -87,12 +87,15 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 2/14/2007 139 Phillippe Initial check-in. Refactor of initial implementation. + * Feb 14, 2007 139 Phillippe Initial check-in. Refactor of initial + * implementation. * Dec 17, 2007 600 bphillip Added dao pool usage - * Dec 03, 2010 2235 cjeanbap EDEXUtility.sendMessageAlertViz() signature changed. + * Dec 03, 2010 2235 cjeanbap EDEXUtility.sendMessageAlertViz() + * signature changed. * Mar 19, 2013 1804 bsteffen Optimize decoder performance. - * Mar 19, 2013 1785 bgonzale Added performance status handler and added status - * to decode. + * Mar 19, 2013 1785 bgonzale Added performance status handler and + * added status to decode. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author bphillip @@ -130,7 +133,7 @@ public class RadarDecoder extends AbstractDecoder { private String traceId = ""; - private RadarInfoDict infoDict; + private final RadarInfoDict infoDict; private RadarStationDao radarStationDao = new RadarStationDao(); @@ -541,7 +544,6 @@ public class RadarDecoder extends AbstractDecoder { private void finalizeRecord(RadarRecord record) throws PluginException { record.setTraceId(traceId); - record.setPluginName("radar"); record.constructDataURI(); record.setInsertTime(TimeTools.getSystemCalendar()); // for GSM, we want all the messages as they have the possibility of @@ -562,7 +564,7 @@ public class RadarDecoder extends AbstractDecoder { if (symbologyBlock == null) { return; } - + int packetsKept = 0; List packetsInLyrs = new ArrayList(); @@ -587,9 +589,9 @@ public class RadarDecoder extends AbstractDecoder { GenericDataPacket genericPacket = (GenericDataPacket) packet; List components = genericPacket .getComponents(); - if (components != null - && components.size() == 1 - && components.get(0).getComponentType() == ComponentType.RADIAL) { + if ((components != null) + && (components.size() == 1) + && (components.get(0).getComponentType() == ComponentType.RADIAL)) { processRadialComponent(record, (RadialComponent) components.get(0)); } else { @@ -698,7 +700,7 @@ public class RadarDecoder extends AbstractDecoder { ClusterTask task = ClusterLockUtils.lookupLock(lockname, record.getIcao()); String formatStatus = RadarUtil.formatBits(messagePart, constants); - if (task == null || task.getExtraInfo() == null) { + if ((task == null) || (task.getExtraInfo() == null)) { ClusterLockUtils.lock(lockname, record.getIcao(), formatStatus, 30, true); EDEXUtil.sendMessageAlertViz(Priority.INFO, @@ -711,7 +713,7 @@ public class RadarDecoder extends AbstractDecoder { } if (task.getExtraInfo() != null) { - if (formatStatus != null + if ((formatStatus != null) && !formatStatus.equals(task.getExtraInfo().trim())) { String details = ""; String temp = ""; diff --git a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/dao/RadarDao.java b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/dao/RadarDao.java index c20aa289b0..cf7c22c7d5 100644 --- a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/dao/RadarDao.java +++ b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/dao/RadarDao.java @@ -27,8 +27,9 @@ package com.raytheon.edex.plugin.radar.dao; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 02/06/09 1990 bphillip Initial creation + * Feb 06, 2009 1990 bphillip Initial creation * Mar 18, 2013 1804 bsteffen Reduce useless data stored in radar hdf5 + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -120,7 +121,8 @@ public class RadarDao extends PluginDao { dataStore.addDataRecord(rec, sp); } - if (radarRec.getThresholds() != null && radarRec.getProductCode() != 2) { + if ((radarRec.getThresholds() != null) + && (radarRec.getProductCode() != 2)) { IDataRecord rec = new ShortDataRecord( RadarStoredData.THRESHOLDS_ID, radarRec.getDataURI(), radarRec.getThresholds(), 1, new long[] { 16 }); @@ -139,7 +141,7 @@ public class RadarDao extends PluginDao { } Map symData = radarRec.getSymbologyData(); - if (symData != null && !symData.isEmpty()) { + if ((symData != null) && !symData.isEmpty()) { byte[] data = DynamicSerializationManager.getManager( SerializationType.Thrift).serialize(symData); ByteDataRecord bdr = new ByteDataRecord( @@ -161,7 +163,7 @@ public class RadarDao extends PluginDao { Map>> mapProdVals = radarRec .getMapProductVals(); - if (mapProdVals != null && !mapProdVals.isEmpty()) { + if ((mapProdVals != null) && !mapProdVals.isEmpty()) { byte[] data = DynamicSerializationManager.getManager( SerializationType.Thrift).serialize(mapProdVals); ByteDataRecord bdr = new ByteDataRecord( @@ -192,7 +194,7 @@ public class RadarDao extends PluginDao { Map> mapRecVals = radarRec .getMapRecordVals(); - if (mapRecVals != null && !mapRecVals.isEmpty()) { + if ((mapRecVals != null) && !mapRecVals.isEmpty()) { byte[] data = DynamicSerializationManager.getManager( SerializationType.Thrift).serialize(mapRecVals); ByteDataRecord bdr = new ByteDataRecord( @@ -202,7 +204,7 @@ public class RadarDao extends PluginDao { } Map stormIds = radarRec.getStormIDs(); - if (stormIds != null && !stormIds.isEmpty()) { + if ((stormIds != null) && !stormIds.isEmpty()) { byte[] data = DynamicSerializationManager.getManager( SerializationType.Thrift).serialize(stormIds); ByteDataRecord bdr = new ByteDataRecord( @@ -274,7 +276,6 @@ public class RadarDao extends PluginDao { PluginDataObject[] queryResults = getMetadata(query); for (PluginDataObject obj : queryResults) { RadarRecord record = (RadarRecord) obj; - record.setPluginName(pluginName); IDataRecord[] hdf5Data = getHDF5Data(record, tile); record.setMessageData(hdf5Data[0].getDataObject()); record.setAngleData((float[]) hdf5Data[1].getDataObject()); diff --git a/edexOsgi/com.raytheon.edex.plugin.recco/src/com/raytheon/edex/plugin/recco/RECCODecoder.java b/edexOsgi/com.raytheon.edex.plugin.recco/src/com/raytheon/edex/plugin/recco/RECCODecoder.java index a4d2ec96e7..bed1dbd22a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.recco/src/com/raytheon/edex/plugin/recco/RECCODecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.recco/src/com/raytheon/edex/plugin/recco/RECCODecoder.java @@ -54,8 +54,9 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080103 384 jkorman Initial Coding. - * 11/25/08 #1684 chammack Camel Refactor + * Jan 03, 2008 384 jkorman Initial Coding. + * Nov 25, 2008 1684 chammack Camel Refactor + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author jkorman @@ -115,7 +116,6 @@ public class RECCODecoder extends AbstractDecoder { input.getWmoHeader()); if (report != null) { report.setTraceId(traceId); - report.setPluginName(PLUGIN_NAME); try { report.constructDataURI(); } catch (PluginException e) { diff --git a/edexOsgi/com.raytheon.edex.plugin.recco/src/com/raytheon/edex/plugin/recco/common/RECCORecord.java b/edexOsgi/com.raytheon.edex.plugin.recco/src/com/raytheon/edex/plugin/recco/common/RECCORecord.java index d1645ed8f5..1a9bbe9204 100644 --- a/edexOsgi/com.raytheon.edex.plugin.recco/src/com/raytheon/edex/plugin/recco/common/RECCORecord.java +++ b/edexOsgi/com.raytheon.edex.plugin.recco/src/com/raytheon/edex/plugin/recco/common/RECCORecord.java @@ -73,6 +73,7 @@ import com.vividsolutions.jts.geom.Geometry; * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * Jun 20, 2013 2128 bsteffen Ensure setDataURI sets the dataURI. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -86,12 +87,8 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "recco", - indexes = { - @Index(name = "recco_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "recco", indexes = { @Index(name = "recco_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -140,7 +137,7 @@ public class RECCORecord extends PluginDataObject implements ISpatialEnabled, @XmlAttribute private Calendar refHour; - // + // @Column @DataURI(position = 1) @DynamicSerializeElement @@ -687,6 +684,7 @@ public class RECCORecord extends PluginDataObject implements ISpatialEnabled, return a; } + @Override public String[] getStrings(String paramName) { return null; } @@ -723,4 +721,9 @@ public class RECCORecord extends PluginDataObject implements ISpatialEnabled, public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "recco"; + } } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.redbook/src/com/raytheon/edex/plugin/redbook/RedbookDecoder.java b/edexOsgi/com.raytheon.edex.plugin.redbook/src/com/raytheon/edex/plugin/redbook/RedbookDecoder.java index 063938623c..f5651117af 100644 --- a/edexOsgi/com.raytheon.edex.plugin.redbook/src/com/raytheon/edex/plugin/redbook/RedbookDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.redbook/src/com/raytheon/edex/plugin/redbook/RedbookDecoder.java @@ -47,14 +47,15 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080512 1131 jkorman Initial implementation. - * 20080529 1131 jkorman Added new Separator constructor. - * 11/11/08 1684 chammack Refactored to camel - * 20090327 2019 jkorman Added code to check for non-redbook data. - * 20120524 #647 dgilling Update persistence time in + * May 12, 2008 1131 jkorman Initial implementation. + * May 29, 2008 1131 jkorman Added new Separator constructor. + * Nov 11, 2008 1684 chammack Refactored to camel + * Mar 27, 2009 2019 jkorman Added code to check for non-redbook data. + * May 24, 2012 647 dgilling Update persistence time in * createdBackDatedVersionIfNeeded. - * Mar 19, 2013 1785 bgonzale Added performance status handler and added - * status to decode. + * Mar 19, 2013 1785 bgonzale Added performance status handler and + * added status to decode. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author jkorman @@ -95,6 +96,7 @@ public class RedbookDecoder extends AbstractDecoder { private final IPerformanceStatusHandler perfLog = PerformanceStatus .getHandler("Redbook:"); + private String traceId = null; /** @@ -142,12 +144,11 @@ public class RedbookDecoder extends AbstractDecoder { + "- File is not Redbook data. Type is " + foreign.dataType); } else { - report = new RedbookParser(traceId, data, - wmoHeader).getDecodedRecord(); + report = new RedbookParser(traceId, data, wmoHeader) + .getDecodedRecord(); } if (report != null) { report.setPersistenceTime(new Date()); - report.setPluginName(PLUGIN_NAME); try { report.constructDataURI(); @@ -219,7 +220,6 @@ public class RedbookDecoder extends AbstractDecoder { // and the Wes2Bridge archiver properly finds these backdated // records backDatedRecord.setPersistenceTime(new Date()); - backDatedRecord.setPluginName(PLUGIN_NAME); backDatedRecord.constructDataURI(); } catch (PluginException e) { logger.error(traceId + "Could not create back-dated copy of " diff --git a/edexOsgi/com.raytheon.edex.plugin.redbook/src/com/raytheon/edex/plugin/redbook/common/RedbookRecord.java b/edexOsgi/com.raytheon.edex.plugin.redbook/src/com/raytheon/edex/plugin/redbook/common/RedbookRecord.java index d6ff1ba00d..199634a1d7 100644 --- a/edexOsgi/com.raytheon.edex.plugin.redbook/src/com/raytheon/edex/plugin/redbook/common/RedbookRecord.java +++ b/edexOsgi/com.raytheon.edex.plugin.redbook/src/com/raytheon/edex/plugin/redbook/common/RedbookRecord.java @@ -61,14 +61,17 @@ import com.raytheon.uf.common.time.DataTime; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080512 1131 jkorman Initial implementation. - * 20080529 1131 jkorman getPersistenceTime now returns system time. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 20130408 1293 bkowal Removed references to hdffileid. - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. - * Apr 29, 2013 1958 bgonzale Added equals and hashcode. + * May 12, 2008 1131 jkorman Initial implementation. + * May 29, 2008 1131 jkorman getPersistenceTime now returns system + * time. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Apr 29, 2013 1958 bgonzale Added equals and hashcode. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -82,17 +85,13 @@ import com.raytheon.uf.common.time.DataTime; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "redbook", - indexes = { - @Index(name = "redbook_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "redbook", indexes = { @Index(name = "redbook_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public class RedbookRecord extends PersistablePluginDataObject - implements IPersistable, Cloneable { +public class RedbookRecord extends PersistablePluginDataObject implements + IPersistable, Cloneable { private static final long serialVersionUID = 1L; @@ -361,7 +360,8 @@ public class RedbookRecord extends PersistablePluginDataObject other.id = 0; other.dataURI = null; - Date newRefTime = new Date(dataTime.getRefTime().getTime() - 60 * 1000); + Date newRefTime = new Date(dataTime.getRefTime().getTime() + - (60 * 1000)); if (dataTime.getUtilityFlags().contains(DataTime.FLAG.FCST_USED)) { other.dataTime = new DataTime(newRefTime, dataTime.getFcstTime()); } else { @@ -380,22 +380,23 @@ public class RedbookRecord extends PersistablePluginDataObject public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((corIndicator == null) ? 0 : corIndicator.hashCode()); - result = prime * result + result = (prime * result) + ((fcstHours == null) ? 0 : fcstHours.hashCode()); - result = prime * result + ((fileId == null) ? 0 : fileId.hashCode()); - result = prime * result + result = (prime * result) + ((fileId == null) ? 0 : fileId.hashCode()); + result = (prime * result) + ((originatorId == null) ? 0 : originatorId.hashCode()); - result = prime * result + result = (prime * result) + ((productId == null) ? 0 : productId.hashCode()); - result = prime * result + Arrays.hashCode(redBookData); - result = prime * result + result = (prime * result) + Arrays.hashCode(redBookData); + result = (prime * result) + ((retentionHours == null) ? 0 : retentionHours.hashCode()); - result = prime * result + ((timeObs == null) ? 0 : timeObs.hashCode()); - result = prime * result + result = (prime * result) + + ((timeObs == null) ? 0 : timeObs.hashCode()); + result = (prime * result) + ((wmoCCCCdt == null) ? 0 : wmoCCCCdt.hashCode()); - result = prime * result + result = (prime * result) + ((wmoTTAAii == null) ? 0 : wmoTTAAii.hashCode()); return result; } @@ -407,60 +408,82 @@ public class RedbookRecord extends PersistablePluginDataObject */ @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } RedbookRecord other = (RedbookRecord) obj; if (corIndicator == null) { - if (other.corIndicator != null) + if (other.corIndicator != null) { return false; - } else if (!corIndicator.equals(other.corIndicator)) + } + } else if (!corIndicator.equals(other.corIndicator)) { return false; + } if (fcstHours == null) { - if (other.fcstHours != null) + if (other.fcstHours != null) { return false; - } else if (!fcstHours.equals(other.fcstHours)) + } + } else if (!fcstHours.equals(other.fcstHours)) { return false; + } if (fileId == null) { - if (other.fileId != null) + if (other.fileId != null) { return false; - } else if (!fileId.equals(other.fileId)) + } + } else if (!fileId.equals(other.fileId)) { return false; + } if (originatorId == null) { - if (other.originatorId != null) + if (other.originatorId != null) { return false; - } else if (!originatorId.equals(other.originatorId)) + } + } else if (!originatorId.equals(other.originatorId)) { return false; + } if (productId == null) { - if (other.productId != null) + if (other.productId != null) { return false; - } else if (!productId.equals(other.productId)) + } + } else if (!productId.equals(other.productId)) { return false; - if (!Arrays.equals(redBookData, other.redBookData)) + } + if (!Arrays.equals(redBookData, other.redBookData)) { return false; + } if (retentionHours == null) { - if (other.retentionHours != null) + if (other.retentionHours != null) { return false; - } else if (!retentionHours.equals(other.retentionHours)) + } + } else if (!retentionHours.equals(other.retentionHours)) { return false; + } if (timeObs == null) { - if (other.timeObs != null) + if (other.timeObs != null) { return false; - } else if (!timeObs.equals(other.timeObs)) + } + } else if (!timeObs.equals(other.timeObs)) { return false; + } if (wmoCCCCdt == null) { - if (other.wmoCCCCdt != null) + if (other.wmoCCCCdt != null) { return false; - } else if (!wmoCCCCdt.equals(other.wmoCCCCdt)) + } + } else if (!wmoCCCCdt.equals(other.wmoCCCCdt)) { return false; + } if (wmoTTAAii == null) { - if (other.wmoTTAAii != null) + if (other.wmoTTAAii != null) { return false; - } else if (!wmoTTAAii.equals(other.wmoTTAAii)) + } + } else if (!wmoTTAAii.equals(other.wmoTTAAii)) { return false; + } return true; } @@ -471,4 +494,8 @@ public class RedbookRecord extends PersistablePluginDataObject return super.getDataURI(); } + @Override + public String getPluginName() { + return "redbook"; + } } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java b/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java index 55827a56ef..1a6457edac 100644 --- a/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java @@ -46,9 +46,9 @@ import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.status.IPerformanceStatusHandler; import com.raytheon.uf.common.status.PerformanceStatus; import com.raytheon.uf.common.time.DataTime; -import com.raytheon.uf.common.util.ArraysUtil; import com.raytheon.uf.common.time.util.ITimer; import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.uf.common.util.ArraysUtil; import com.raytheon.uf.edex.decodertools.time.TimeTools; import com.raytheon.uf.edex.wmo.message.WMOHeader; @@ -79,7 +79,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * 01/03/2013 15294 D. Friedman Start with File instead of byte[] to * reduce memory usage. * Feb 15, 2013 1638 mschenke Moved array based utilities from Util into ArraysUtil - * + * * Mar 19, 2013 1785 bgonzale Added performance status handler and added status * to decode. * @@ -90,7 +90,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; */ public class SatelliteDecoder extends AbstractDecoder { - private String traceId = ""; + private final String traceId = ""; private static final int MAX_IMAGE_SIZE = 30000000; @@ -111,8 +111,9 @@ public class SatelliteDecoder extends AbstractDecoder { SatelliteRecord record = null; - if (file == null || (file.length() < 1)) + if ((file == null) || (file.length() < 1)) { return new PluginDataObject[0]; + } RandomAccessFile f = new RandomAccessFile(file, "r"); try { ITimer timer = TimeUtil.getTimer(); @@ -129,7 +130,8 @@ public class SatelliteDecoder extends AbstractDecoder { byteBuffer = null; } if (byteBuffer != null) { - int offsetOfDataInFile = byteBuffer.position() + GINI_HEADER_SIZE; + int offsetOfDataInFile = byteBuffer.position() + + GINI_HEADER_SIZE; Calendar calendar = Calendar.getInstance(TimeZone .getTimeZone("GMT")); int intValue = 0; @@ -140,20 +142,23 @@ public class SatelliteDecoder extends AbstractDecoder { record = new SatelliteRecord(); if (isCompressed(byteBuffer)) { - /* If the data is compressed, we assume it came from the SBN + /* + * If the data is compressed, we assume it came from the SBN * and will have a reasonable size such that we can have two - * copies of the data in memory at the same time. Ideally, + * copies of the data in memory at the same time. Ideally, * SBN decompression should be performed upstream from EDEX * and this code would be removed. */ - byte[] data = new byte[(int) file.length() - byteBuffer.position()]; + byte[] data = new byte[(int) file.length() + - byteBuffer.position()]; f.seek(byteBuffer.position()); f.readFully(data); byte[][] retVal = decompressSatellite(data); byteBuffer = ByteBuffer.wrap(retVal[0]); tempBytes = retVal[1]; } else { - /* The code bellow performs absolute gets on the buffer, so + /* + * The code bellow performs absolute gets on the buffer, so * it needs to be compacted. */ byteBuffer.compact(); @@ -255,7 +260,7 @@ public class SatelliteDecoder extends AbstractDecoder { // Get the Satellite Height int satHeight = byteBuffer.getShort(53); - if (latSub != 0 || lonSub != 0 || satHeight != 0) { + if ((latSub != 0) || (lonSub != 0) || (satHeight != 0)) { // Correct the longitude so negative is west lonSub *= -1; // Correct the height to be height above ground @@ -287,8 +292,9 @@ public class SatelliteDecoder extends AbstractDecoder { // get number of points along y-axis int ny = byteBuffer.getShort(18); - /* If input was SBN-compressed, we already have the data - * loaded. If not, load it now. + /* + * If input was SBN-compressed, we already have the data loaded. + * If not, load it now. */ if (tempBytes == null) { tempBytes = new byte[nx * ny]; @@ -433,7 +439,6 @@ public class SatelliteDecoder extends AbstractDecoder { record.setCoverage(mapCoverage); record.setPersistenceTime(TimeTools.getSystemCalendar() .getTime()); - record.setPluginName("satellite"); record.constructDataURI(); // Create the data record. IDataRecord dataRec = messageData.getStorageRecord(record, @@ -466,10 +471,11 @@ public class SatelliteDecoder extends AbstractDecoder { * @throws DecoderException * If WMO header is not found, or is incorrect. * @param messageData - * Contains the start of the satellite data file. On return, - * the position is set the beginning of the GINI header. + * Contains the start of the satellite data file. On return, the + * position is set the beginning of the GINI header. */ - private void removeWmoHeader(ByteBuffer messageData) throws DecoderException { + private void removeWmoHeader(ByteBuffer messageData) + throws DecoderException { // Copy to a char [], carefully, as creating a string from // a byte [] with binary data can create erroneous data @@ -500,7 +506,7 @@ public class SatelliteDecoder extends AbstractDecoder { * Checks to see if the current satellite product is compressed. * * Assumes messageData is a byte[]-backed ByteBuffer. - * + * * @return A boolean indicating if the file is compressed or not */ private boolean isCompressed(ByteBuffer messageData) { @@ -508,8 +514,8 @@ public class SatelliteDecoder extends AbstractDecoder { byte[] placeholder = new byte[10]; Inflater decompressor = new Inflater(); try { - decompressor.setInput(messageData.array(), - messageData.position(), messageData.remaining()); + decompressor.setInput(messageData.array(), messageData.position(), + messageData.remaining()); decompressor.inflate(placeholder); } catch (DataFormatException e) { compressed = false; @@ -539,14 +545,13 @@ public class SatelliteDecoder extends AbstractDecoder { // Allocate 30MB for a possible max size ByteArrayOutputStream bos = new ByteArrayOutputStream(MAX_IMAGE_SIZE); int totalBytesDecomp = 0; - int decompByteCounter = 0; byte[] inputArray = new byte[1024 * 10]; Inflater decompressor = new Inflater(); int index = -1; try { while (totalBytesDecomp < zSatellite.length) { - int compChunkSize = zSatellite.length - totalBytesDecomp > 10240 ? 10240 + int compChunkSize = (zSatellite.length - totalBytesDecomp) > 10240 ? 10240 : zSatellite.length - totalBytesDecomp; // copy compChunkSize compressed data from zSatellite, offset by @@ -570,9 +575,6 @@ public class SatelliteDecoder extends AbstractDecoder { throw new DecoderException( "Unable to decompress satellite data - input data appears to be truncated"); } - // add the total bytes decompressed from inflate call - decompByteCounter += inflatedBytes; - // retrieve the total compressed bytes input so far totalBytesDecomp += decompressor.getTotalIn(); @@ -641,9 +643,9 @@ public class SatelliteDecoder extends AbstractDecoder { } - if (index != -1 && (index + 3 <= inflateArray.length - 1)) { - if (!(inflateArray[index] == -1 && inflateArray[index + 1] == 0 - && inflateArray[index + 2] == -1 && inflateArray[index + 3] == 0)) { + if ((index != -1) && ((index + 3) <= (inflateArray.length - 1))) { + if (!((inflateArray[index] == -1) && (inflateArray[index + 1] == 0) + && (inflateArray[index + 2] == -1) && (inflateArray[index + 3] == 0))) { index = getIndex(inflateArray, index + 1); } } else { @@ -686,7 +688,7 @@ public class SatelliteDecoder extends AbstractDecoder { if (byteArray[0] < 0) { // remove the negative value byteArray[0] &= 127; - latitude = byteArrayToFloat(byteArray) / 10000 * -1; + latitude = (byteArrayToFloat(byteArray) / 10000) * -1; } else { latitude = byteArrayToFloat(byteArray) / 10000; } diff --git a/edexOsgi/com.raytheon.edex.plugin.sfcobs/src/com/raytheon/edex/plugin/sfcobs/SfcObsDecoder.java b/edexOsgi/com.raytheon.edex.plugin.sfcobs/src/com/raytheon/edex/plugin/sfcobs/SfcObsDecoder.java index 7d67020f90..9d20ce9b65 100644 --- a/edexOsgi/com.raytheon.edex.plugin.sfcobs/src/com/raytheon/edex/plugin/sfcobs/SfcObsDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.sfcobs/src/com/raytheon/edex/plugin/sfcobs/SfcObsDecoder.java @@ -62,16 +62,17 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20070925 391 jkorman Initial Coding. - * 20071107 391 jkorman Modified findDuplicate to use a different + * Sep 25, 2007 391 jkorman Initial Coding. + * Nov 07, 2007 391 jkorman Modified findDuplicate to use a different * dataURI query. * Dec 17, 2007 600 bphillip Added dao pool usage - * 20080123 758 jkorman Added code to remove observation with a + * Jan 23, 2008 758 jkorman Added code to remove observation with a * time in the future. - * 20080215 887 jkorman Added null checks in decode. - * 20080218 887 jkorman Reverse null checks in findDuplicate. - * Mar 19, 2013 1785 bgonzale Added performance status handler and added status - * to decode. + * Feb 15, 2008 887 jkorman Added null checks in decode. + * Feb 18, 2008 887 jkorman Reverse null checks in findDuplicate. + * Mar 19, 2013 1785 bgonzale Added performance status handler and + * added status to decode. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author jkorman @@ -87,7 +88,7 @@ public class SfcObsDecoder extends AbstractDecoder { .getHandler("SfcObs:"); /** The logger */ - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); private boolean removeNILs = true; @@ -169,7 +170,6 @@ public class SfcObsDecoder extends AbstractDecoder { } if (report != null) { report.setTraceId(traceId); - report.setPluginName(PLUGIN_NAME); try { report.constructDataURI(); } catch (PluginException e) { diff --git a/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/data/ShefRecord.java b/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/data/ShefRecord.java index 8cc186047e..c0b0419c08 100644 --- a/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/data/ShefRecord.java +++ b/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/data/ShefRecord.java @@ -47,14 +47,14 @@ import com.raytheon.uf.common.time.DataTime; /** *
  * SOFTWARE HISTORY
- * Date       	Ticket#		Engineer	Description
- * ------------	----------	-----------	--------------------------
- * June2006		3,14		Phillippe	Initial Creation.	
- * 20071129     472         jkorman     Added IDecoderGettable interface.
- * 19Mar2008    387         M. Duff     Modified to store SHEF data.
- * May 07, 2013	1869      	bsteffen   	Remove dataURI column from
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * June2006     314         Phillippe   Initial Creation.
+ * Nov 29, 2007 472         jkorman     Added IDecoderGettable interface.
+ * Mar 19, 2008 387         M. Duff     Modified to store SHEF data.
+ * May 07, 2013 1869        bsteffen    Remove dataURI column from
  *                                      PluginDataObject.
- * 
+ * Aug 30, 2013 2298        rjpeter     Make getPluginName abstract
  * 
* * @author bphillip @@ -63,21 +63,19 @@ import com.raytheon.uf.common.time.DataTime; @DynamicSerialize @XmlAccessorType(XmlAccessType.NONE) public class ShefRecord extends PluginDataObject { - + public static enum ShefType { A, B, E; } - - private static final long serialVersionUID = 2726928942130489733L; - private static final int MILLIS_PER_MINUTE = 1000 * 60; + private static final long serialVersionUID = 2726928942130489733L; /** * Collection of SHEF data values for this record */ @Transient private List dataValues = null; - + @Transient protected String rawMessage = null; @@ -127,12 +125,12 @@ public class ShefRecord extends PluginDataObject { @Transient private SHEFDate obsDate = null; - + @Transient private SHEFDate createDate = null; @Transient - private int durationValue = ParameterCode.Duration.DEFAULT.getValue(); + private final int durationValue = ParameterCode.Duration.DEFAULT.getValue(); /** * Empty constructor @@ -161,12 +159,12 @@ public class ShefRecord extends PluginDataObject { } public void addDataValue(ShefData value) { - if(dataValues == null) { + if (dataValues == null) { dataValues = new ArrayList(); } dataValues.add(value); } - + /** * Get the record type. * @@ -246,19 +244,19 @@ public class ShefRecord extends PluginDataObject { this.recordDate = recordDate; if (recordDate.length() == 4) { int year = ShefUtil.getFullYear(recordDate); - synchronized(ShefConstants.YYYYMMDD_FORMAT){ + synchronized (ShefConstants.YYYYMMDD_FORMAT) { recordDateObj = ShefConstants.YYYYMMDD_FORMAT.parse(year + recordDate); } } else if (recordDate.length() == 6) { int year = ShefUtil.getFullYear(recordDate); year = year / 100; - synchronized(ShefConstants.YYYYMMDD_FORMAT){ + synchronized (ShefConstants.YYYYMMDD_FORMAT) { recordDateObj = ShefConstants.YYYYMMDD_FORMAT.parse(year + recordDate); } } else { // recordDate length must be 8 - synchronized(ShefConstants.YYYYMMDD_FORMAT){ + synchronized (ShefConstants.YYYYMMDD_FORMAT) { recordDateObj = ShefConstants.YYYYMMDD_FORMAT.parse(recordDate); } } @@ -287,7 +285,7 @@ public class ShefRecord extends PluginDataObject { public void setObsDate(SHEFDate date) { obsDate = date; } - + /** * * @return @@ -295,7 +293,7 @@ public class ShefRecord extends PluginDataObject { public SHEFDate getObsDate() { return obsDate; } - + /** * Get the time zone code * @@ -375,7 +373,7 @@ public class ShefRecord extends PluginDataObject { * @param date */ public void setCreationDate(SHEFDate date) { - if(date != null) { + if (date != null) { createDate = date; creationDate = date.toLocal(); creationDateObj = date.toCalendar().getTime(); @@ -385,7 +383,6 @@ public class ShefRecord extends PluginDataObject { creationDateObj = null; } } - /** * Get the creation date Date object @@ -563,54 +560,15 @@ public class ShefRecord extends PluginDataObject { public IDecoderGettable getDecoderGettable() { return null; } - + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Record type = "); sb.append(shefType); - -// if(obsDate != null) { -// sb.append(obsDate.toOutString()); -// } else { -// sb.append(" 0 0 0 0 0 0"); -// } -// sb.append(" "); -// if(createDate != null) { -// sb.append(createDate.toOutString()); -// } else { -// sb.append(" 0 0 0 0 0 0"); -// } -// sb.append(" "); -// // PE -// sb.append("HG"); -// sb.append(" "); -// sb.append(String.format("%4d",durationValue)); -// sb.append(" "); -// // Type Code -// sb.append("R"); -// sb.append(" "); -// // Source Code -// sb.append("G"); -// sb.append(" "); -// // Extremnum -// sb.append("Z"); -// sb.append(" "); -// // Probability Code -// sb.append(" "); -// sb.append(" "); -// // Data Value -// sb.append("00000.000"); -// sb.append(" "); -// // Data Qualifier -// sb.append(" "); -// sb.append(" "); -// // Revision code -// sb.append((revisedRecord) ? "0" : "1"); -// sb.append(ShefConstants.EOL); -// sb.append("----------------------------------------"); - if(dataValues != null) { - for(ShefData d : dataValues) { + + if (dataValues != null) { + for (ShefData d : dataValues) { sb.append(ShefConstants.EOL); d.toString(sb); } @@ -618,11 +576,16 @@ public class ShefRecord extends PluginDataObject { sb.append(ShefConstants.EOL); return sb.toString(); } - + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "shef"; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/database/PostShef.java b/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/database/PostShef.java index b31d016b9e..e4dd5ccf43 100644 --- a/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/database/PostShef.java +++ b/edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/database/PostShef.java @@ -107,6 +107,9 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * 03/07/2013 15545 w. kwock Added Observe time to log * 03/21/2013 15967 w. kwock Fix the error in buildTsFcstRiv riverstatus table issue * 04/05/2013 16036 w. kwock Fixed no ts=RZ in ingestfilter table but posted to height table + * 10/28/2013 16711 lbousaidi if the id is not in location table,but defined in geoarea table + * data can be posted to appropriate pe-based tables only if the data + * type is not READING like in A1 code. * * * @@ -418,6 +421,18 @@ public class PostShef { if (log.isDebugEnabled()) { log.debug("DataType = " + dataType); } + + /* + * if the station_id exists in location table and + * the data type is READING then the data doesn't get posted + * to the appropriate pe-based tables to match A1 logic. + * DR16711 + */ + + if ((DataType.READING.equals(dataType)) + &&(Location.LOC_GEOAREA.equals(postLocData))) { + postLocData=Location.LOC_UNDEFINED; + } SHEFDate d = data.getObsTime(); if (d == null) { diff --git a/edexOsgi/com.raytheon.edex.plugin.shef/unit-test/test/edex/transform/shef/TestMetarToShefTransformer.java b/edexOsgi/com.raytheon.edex.plugin.shef/unit-test/test/edex/transform/shef/TestMetarToShefTransformer.java index 8a4b988f28..2c473e8bce 100644 --- a/edexOsgi/com.raytheon.edex.plugin.shef/unit-test/test/edex/transform/shef/TestMetarToShefTransformer.java +++ b/edexOsgi/com.raytheon.edex.plugin.shef/unit-test/test/edex/transform/shef/TestMetarToShefTransformer.java @@ -19,10 +19,15 @@ **/ package test.edex.transform.shef; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + import java.util.Iterator; import org.junit.Test; -import static org.junit.Assert.*; import com.raytheon.edex.transform.shef.MetarToShefTransformer; import com.raytheon.uf.common.dataplugin.IDecoderGettable; @@ -32,26 +37,25 @@ import com.raytheon.uf.common.dataplugin.PluginDataObject; * Tests extracted from MetarToShef. * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * ======================================
  * AWIPS2 DR Work
  * 20120918           1185 jkorman     Extracted from mains
- *
+ * 
  * 
- * + * * @author jkorman - * @version 1.0 + * @version 1.0 */ public class TestMetarToShefTransformer { /** - * Test that the transformer creates an empty iterator when - * given no input. + * Test that the transformer creates an empty iterator when given no input. */ @Test public void testMetarToShefInteratorA() { @@ -60,18 +64,17 @@ public class TestMetarToShefTransformer { assertNotNull(it); assertFalse(it.hasNext()); assertNull(it.next()); - - pdos = new PluginDataObject [0]; + + pdos = new PluginDataObject[0]; it = MetarToShefTransformer.iterate(pdos); assertNotNull(it); assertFalse(it.hasNext()); assertNull(it.next()); - + } - + /** - * Test that the transformer creates an non-empty iterator for - * given input. + * Test that the transformer creates an non-empty iterator for given input. */ @Test public void testMetarToShefInteratorB() { @@ -81,8 +84,20 @@ public class TestMetarToShefTransformer { public IDecoderGettable getDecoderGettable() { return null; } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.dataplugin.PluginDataObject#getPluginName + * () + */ + @Override + public String getPluginName() { + return "testMetarToShef"; + } }; - + PluginDataObject[] pdos = { p, }; Iterator it = MetarToShefTransformer.iterate(pdos); assertNotNull(it); @@ -105,9 +120,6 @@ public class TestMetarToShefTransformer { + "\r\r\n: 60000 T00330011 10078 20033 53021 931012 933025 98245 4/005=", newobs.toString()); - } - - - - + } + } diff --git a/edexOsgi/com.raytheon.edex.plugin.taf/src/com/raytheon/edex/plugin/taf/TafDecoder.java b/edexOsgi/com.raytheon.edex.plugin.taf/src/com/raytheon/edex/plugin/taf/TafDecoder.java index 2f65deae88..8b6e1fddf5 100644 --- a/edexOsgi/com.raytheon.edex.plugin.taf/src/com/raytheon/edex/plugin/taf/TafDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.taf/src/com/raytheon/edex/plugin/taf/TafDecoder.java @@ -30,18 +30,18 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; /** * - * Decoder implementation for taf plugin + * Decoder implementation for taf plugin. * *
  * 
  * SOFTWARE HISTORY
  * 
- * Date       	Ticket#		Engineer	Description
- * ------------	----------	-----------	--------------------------
- * 2/14/07		139			bphillip	Initial creation	
- * 6/21/07		180			bphillip	Updated to use new plugin pattern
- * 20080425           1001  jkorman     Extracted decoder code into TAFParser.
- * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * Feb 14, 2007 139         bphillip    Initial creation
+ * Jun 21, 2007 180         bphillip    Updated to use new plugin pattern
+ * Apr 25, 2008 1001        jkorman     Extracted decoder code into TAFParser.
+ * Aug 30, 2013 2298        rjpeter     Make getPluginName abstract
  * 
* * @author bphillip @@ -52,7 +52,7 @@ public class TafDecoder extends AbstractDecoder { // Name of the plugin controlling this decoder. public static final String PLUGIN_NAME = "TAF"; - private String traceId = ""; + private final String traceId = ""; /** * Constructor. @@ -88,12 +88,12 @@ public class TafDecoder extends AbstractDecoder { record = parser.getDecodedRecord(); if (record != null) { record.setTraceId(traceId); - record.setPluginName("taf"); record.constructDataURI(); } else { TAFParts parts = input.tafParts; - if(parts.getTafHeader() != null) { - logger.error("Could not parse TAF for input " + parts.getTafHeader() + " in file " + traceId); + if (parts.getTafHeader() != null) { + logger.error("Could not parse TAF for input " + + parts.getTafHeader() + " in file " + traceId); } else { logger.error("Could not parse file " + traceId); } @@ -107,8 +107,9 @@ public class TafDecoder extends AbstractDecoder { record = null; } - if (record == null) + if (record == null) { return new PluginDataObject[0]; + } return new PluginDataObject[] { record }; } diff --git a/edexOsgi/com.raytheon.edex.plugin.taf/src/com/raytheon/edex/plugin/taf/common/TafRecord.java b/edexOsgi/com.raytheon.edex.plugin.taf/src/com/raytheon/edex/plugin/taf/common/TafRecord.java index d48e049b54..4690840804 100644 --- a/edexOsgi/com.raytheon.edex.plugin.taf/src/com/raytheon/edex/plugin/taf/common/TafRecord.java +++ b/edexOsgi/com.raytheon.edex.plugin.taf/src/com/raytheon/edex/plugin/taf/common/TafRecord.java @@ -22,7 +22,6 @@ package com.raytheon.edex.plugin.taf.common; import java.util.Date; import java.util.HashSet; -import java.util.Iterator; import java.util.Set; import javax.persistence.Access; @@ -61,13 +60,15 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 2/14/07 139 bphillip Initial Creation - * 6/21/07 180 bphillip Updated to use new plugin pattern - * 20071129 472 jkorman Added IDecoderGettable interface. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime + * Feb 14, 2007 139 bphillip Initial Creation + * Jun 21, 2007 180 bphillip Updated to use new plugin pattern + * Nov 29, 2007 472 jkorman Added IDecoderGettable interface. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -81,12 +82,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "taf", - indexes = { - @Index(name = "taf_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "taf", indexes = { @Index(name = "taf_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize @XmlAccessorType(XmlAccessType.NONE) @XmlRootElement @@ -347,10 +344,8 @@ public class TafRecord extends PluginDataObject implements ISpatialEnabled { this.identifier = dataURI; - if (this.changeGroups != null && this.changeGroups.size() > 0) { - for (Iterator iter = this.changeGroups.iterator(); iter - .hasNext();) { - ChangeGroup group = iter.next(); + if ((this.changeGroups != null) && (this.changeGroups.size() > 0)) { + for (ChangeGroup group : this.changeGroups) { group.setParentID(this); } } @@ -391,7 +386,7 @@ public class TafRecord extends PluginDataObject implements ISpatialEnabled { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + result = (prime * result) + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); return result; } @@ -405,19 +400,23 @@ public class TafRecord extends PluginDataObject implements ISpatialEnabled { */ @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } TafRecord other = (TafRecord) obj; if (getDataURI() == null) { if (other.getDataURI() != null) { return false; } - } else if (!getDataURI().equals(other.getDataURI())) + } else if (!getDataURI().equals(other.getDataURI())) { return false; + } return true; } @@ -427,4 +426,9 @@ public class TafRecord extends PluginDataObject implements ISpatialEnabled { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "taf"; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-ingest.xml b/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-ingest.xml index 982bc1af13..945f5599a4 100644 --- a/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-ingest.xml +++ b/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-ingest.xml @@ -14,6 +14,11 @@
+ + + + diff --git a/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/TextDecoder.java b/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/TextDecoder.java index c870667d8e..b06c736958 100644 --- a/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/TextDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/TextDecoder.java @@ -66,18 +66,19 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * 2008 Aug 11 jkorman + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Aug 11, 2008 jkorman Initial creation * Jul 10, 2009 2191 rjpeter Finished implementation. - * Apr 14, 2010 4734 mhuang Corrected StdTextProduct import - * dependency + * Apr 14, 2010 4734 mhuang Corrected StdTextProduct import + * dependency * May 28, 2010 2187 cjeanbap Added StdTextProductFactory - * functionality. + * functionality. * Aug 26, 2010 2187 cjeanbap Renamed operationalMode for - * consistency. + * consistency. * Dec 13, 2010 5805 cjeanbap Parse Report to get AFOS Product Id - * Jul 16, 2013 DR 16323 D. Friedman Use concurrent map + * Jul 16, 2013 16323 D. Friedman Use concurrent map + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author @@ -99,7 +100,7 @@ public class TextDecoder extends AbstractDecoder { .getEnvProperties().getEnvValue("DEFAULTDATADIR") + "badTxt"; - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); private String pluginName; @@ -107,11 +108,11 @@ public class TextDecoder extends AbstractDecoder { private String fileName; - private TextDB textdb = new TextDB(); + private final TextDB textdb = new TextDB(); // keeps track of the headers that have been logged as not mapped and the // time it was logged, so that each one is only logged once a day - private Map notMappedHeaders = new ConcurrentHashMap(); + private final Map notMappedHeaders = new ConcurrentHashMap(); private long msgHdrLogTime = 0; @@ -158,7 +159,6 @@ public class TextDecoder extends AbstractDecoder { if (pdo != null) { pdo.setTraceId(traceId); - pdo.setPluginName(pluginName); try { pdo.constructDataURI(); } catch (PluginException e) { @@ -209,7 +209,7 @@ public class TextDecoder extends AbstractDecoder { TextRecord pdo = null; - WMOReportData rptData = (WMOReportData) separator.next(); + WMOReportData rptData = separator.next(); boolean operationalMode = true; if (rptData != null) { @@ -227,8 +227,8 @@ public class TextDecoder extends AbstractDecoder { if (afosIdContainer != null) { List afosIdList = afosIdContainer .getIdList(); - if (afosIdList != null - && afosIdList.size() > 0) { + if ((afosIdList != null) + && (afosIdList.size() > 0)) { StringTokenizer st = new StringTokenizer( rptData.getReportData(), "\n"); String potentialId = st.nextToken(); @@ -266,20 +266,20 @@ public class TextDecoder extends AbstractDecoder { + rptHdr.getCccc(); Long time = notMappedHeaders.get(key); long curTime = System.currentTimeMillis(); - if (time == null - || (curTime - time > NOT_FOUND_LOG_PERIOD)) { + if ((time == null) + || ((curTime - time) > NOT_FOUND_LOG_PERIOD)) { StringBuilder msg = new StringBuilder(200); msg.append("Could not determine AFOS id for wmo header: ["); msg.append(rptHdr.toString()); msg.append("]"); - if (msgHdr != null + if ((msgHdr != null) && !msgHdr.equals(rptHdr)) { msg.append(" incoming message header ["); msg.append(msgHdr.toString()); msg.append("]"); } - if (curTime - msgHdrLogTime > MSG_HDR_LOG_PERIOD) { + if ((curTime - msgHdrLogTime) > MSG_HDR_LOG_PERIOD) { msg.append("\nMsg for a given header will only be logged once in a " + (NOT_FOUND_LOG_PERIOD / MILLIS_PER_HOUR) + " hour period"); @@ -319,7 +319,6 @@ public class TextDecoder extends AbstractDecoder { if (pdo != null) { pdo.setTraceId(traceId); - pdo.setPluginName(pluginName); try { pdo.constructDataURI(); } catch (PluginException e) { @@ -359,8 +358,8 @@ public class TextDecoder extends AbstractDecoder { key = header.getOriginalMessage(); } Long time = notMappedHeaders.get(key); - if (time == null - || (curTime - time > NOT_FOUND_LOG_PERIOD)) { + if ((time == null) + || ((curTime - time) > NOT_FOUND_LOG_PERIOD)) { notMappedHeaders.put(key, curTime); } else { iter.remove(); @@ -387,7 +386,7 @@ public class TextDecoder extends AbstractDecoder { } } - if (curTime - msgHdrLogTime > MSG_HDR_LOG_PERIOD) { + if ((curTime - msgHdrLogTime) > MSG_HDR_LOG_PERIOD) { msg.append("\nMsg for a given header will only be logged once in a " + (NOT_FOUND_LOG_PERIOD / MILLIS_PER_HOUR) + " hour period"); diff --git a/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/TextRecord.java b/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/TextRecord.java index c7790d7afe..43a9094555 100644 --- a/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/TextRecord.java +++ b/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/TextRecord.java @@ -38,9 +38,10 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Dec 5, 2008 jkorman Initial creation + * Dec 05, 2008 jkorman Initial creation * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -108,4 +109,8 @@ public class TextRecord extends PluginDataObject { return super.getDataURI(); } + @Override + public String getPluginName() { + return "text"; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.textlightning/src/com/raytheon/edex/plugin/textlightning/TextLightningDecoder.java b/edexOsgi/com.raytheon.edex.plugin.textlightning/src/com/raytheon/edex/plugin/textlightning/TextLightningDecoder.java index 8f530a7c5d..3337e38f5a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.textlightning/src/com/raytheon/edex/plugin/textlightning/TextLightningDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.textlightning/src/com/raytheon/edex/plugin/textlightning/TextLightningDecoder.java @@ -41,22 +41,23 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * TODO Add Description * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * Mar 25, 2010            jsanchez     Initial creation
- *
+ * Mar 25, 2010            jsanchez    Initial creation
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
+ * 
  * 
- * + * * @author jsanchez - * @version 1.0 + * @version 1.0 */ public class TextLightningDecoder extends AbstractDecoder implements IBinaryDecoder { - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); private String traceId = null; @@ -74,17 +75,18 @@ public class TextLightningDecoder extends AbstractDecoder implements * @throws DecoderException * Thrown if no data is available. */ + @Override public PluginDataObject[] decode(byte[] data) throws DecoderException { ArrayList strikes = new ArrayList(); TextLightningParser parser = new TextLightningParser(data); - + LightningStrikePoint token; - while(parser.hasNext()) { + while (parser.hasNext()) { token = parser.next(); - if(token != null) { + if (token != null) { strikes.add(token); } - } + } BinLightningRecord report = null; if (strikes.size() > 0) { @@ -106,15 +108,14 @@ public class TextLightningDecoder extends AbstractDecoder implements Calendar cStart = report.getStartTime(); Calendar cStop = report.getStopTime(); - TimeRange range = new TimeRange(cStart.getTimeInMillis(), cStop - .getTimeInMillis()); + TimeRange range = new TimeRange(cStart.getTimeInMillis(), + cStop.getTimeInMillis()); DataTime dataTime = new DataTime(cStart, range); report.setDataTime(dataTime); if (report != null) { report.setTraceId(traceId); - report.setPluginName("binlightning"); try { report.constructDataURI(); } catch (PluginException e) { diff --git a/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py b/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py index 3c051d366c..d51f38ec3a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py +++ b/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py @@ -35,6 +35,7 @@ # May 07, 2013 1973 rferrel Adjust Issue and Purge times to be relative to start time. # Jun 24, 2013 DR 16317 D. Friedman If no storm line, parse storm motion from event text. # Aug 21, 2013 DR16501 m.gamazaychikov Adjusted calculation of Purge time in NoVTECWarningDecoder. +# Sep 12, 2013 DR2249 rferrel When incoming file from warngen adjust start time from file's timestamp. # # # @author rferrel @@ -111,19 +112,24 @@ class StdWarningDecoder(): self._rawMessage = text checkForWmo = True - #base time for decoder - self._time = time.time() + self._timeOffset #present time - - if TimeTools.allowArchive() : - try: - yyyymmddhh = TimeTools.getTimestamp(self._incomingFilename) - if len(yyyymmddhh) < 10: - timeTuple = time.strptime(yyyymmddhh, "%Y%m%d") - else : - timeTuple = time.strptime(yyyymmddhh, "%Y%m%d%H") - self._time = time.mktime(timeTuple) - except : - LogStream.logProblem('Unable to get timestamp from filename: "%s"' % (self._incomingFilename)) + # base time for decoder + warningTimestamp = TimeTools.getWarningTimestamp(self._incomingFilename) + if warningTimestamp is None : + # present time + self._time = time.time() + self._timeOffset + if TimeTools.allowArchive(): + try: + yyyymmddhh = TimeTools.getTimestamp(self._incomingFilename) + if len(yyyymmddhh) < 10: + timeTuple = time.strptime(yyyymmddhh, "%Y%m%d") + else : + timeTuple = time.strptime(yyyymmddhh, "%Y%m%d%H") + self._time = time.mktime(timeTuple) + except : + LogStream.logProblem('Unable to get timestamp from filename: "%s"' % (self._incomingFilename)) + else: + # Use the epoch seconds in the file generated by TextEditorDialog.java. + self._time = long(warningTimestamp) os.umask(0) #ensure proper permissions @@ -155,9 +161,8 @@ class StdWarningDecoder(): def decode(self): #get pil and date-time group - self._adjustIssueTime = True self._productPil, self._issueTime, linePos,\ - self._completeProductPil, self._issueTimeStr = self._getPilAndDTG() + self._completeProductPil = self._getPilAndDTG() # If this is a WCL - don't go any further. Run WCL procedure and exit. if self._productPil[0:3] == "WCL": @@ -411,7 +416,7 @@ usage: VTECDecoder -f productfilename -d -a activeTableName LogStream.logVerbose("Pil=", pil_search.group(0)) return (self._lines[count+1][0:3], self._dtgFromDDHHMM(dtg_search.group(1)), count+2, - pil_search.group(0), dtg_search.group(1)) + pil_search.group(0)) count = count + 1 if count >= len(self._lines)-1: LogStream.logProblem("Did not find either the product DTG" +\ @@ -830,7 +835,7 @@ usage: VTECDecoder -f productfilename -d -a activeTableName ugcs = self._expandUGC(ugcstring) records = [] for vtecS, hvtec in vtecStrings: - search = re.search(self._vtecRE, vtecS) + search = re.search(self._vtecRE, vtecS) #construct the active table entries, without the geography template = {} @@ -845,9 +850,6 @@ usage: VTECDecoder -f productfilename -d -a activeTableName template['seg'] = segment startTime, zeros = self._calcTime(search.group(6), search.group(7), self._issueTime * 1000) - if self._adjustIssueTime : - self._issueTime = self._dtgFromDDHHMM(self._issueTimeStr, startTime/1000.0) - self._adjustIssueTime = False endTime, ufn = self._calcTime(search.group(8), search.group(9), self._maxFutureTime * 1000) template['startTime'] = long(startTime) diff --git a/edexOsgi/com.raytheon.edex.uengine/src/com/raytheon/edex/uengine/tasks/query/TermQuery.java b/edexOsgi/com.raytheon.edex.uengine/src/com/raytheon/edex/uengine/tasks/query/TermQuery.java index 40982795d7..4e6ee44dcf 100644 --- a/edexOsgi/com.raytheon.edex.uengine/src/com/raytheon/edex/uengine/tasks/query/TermQuery.java +++ b/edexOsgi/com.raytheon.edex.uengine/src/com/raytheon/edex/uengine/tasks/query/TermQuery.java @@ -20,10 +20,7 @@ package com.raytheon.edex.uengine.tasks.query; -import java.util.List; - import com.raytheon.edex.uengine.exception.MicroEngineException; -import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.plugin.PluginFactory; @@ -37,12 +34,14 @@ import com.raytheon.uf.edex.database.plugin.PluginFactory; * *
  * SOFTWARE HISTORY
- * Date             PR#             Engineer            Description
- * -----------      ----------      ------------        --------------------------
- * Mar 27, 2007                     njensen             Initial Creation.
- * 9/21/2007        368             grichard            Added plugin operations from superclass.
- * 6/04/2008        875             bphillip            Refactored to use DatabaseQuery
- * 
+ * Date Ticket# Engineer Description + * ------------ ---------- ------------ ---------------------------------------- + * Mar 27, 2007 njensen Initial Creation. + * Sep 21, 2007 368 grichard Added plugin operations from + * superclass. + * Jun 04, 2008 875 bphillip Refactored to use DatabaseQuery + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract + * * * @author njensen */ @@ -61,6 +60,7 @@ public class TermQuery extends TableQuery { * @throws PluginException * @deprecated */ + @Deprecated public TermQuery(String aPlugin, String dummy1, String dummy2) throws DataAccessLayerException, PluginException { this(aPlugin); @@ -80,19 +80,6 @@ public class TermQuery extends TableQuery { this.plugin = aPlugin; } - @SuppressWarnings("unchecked") - public List execute() throws Exception { - List results = (List) super - .execute(); - - if (results != null) { - for (int i = 0; i < results.size(); i++) { - results.get(i).setPluginName(plugin); - } - } - return results; - } - /** * * @return diff --git a/edexOsgi/com.raytheon.edex.utilitysrv/src/com/raytheon/edex/services/GetServersHandler.java b/edexOsgi/com.raytheon.edex.utilitysrv/src/com/raytheon/edex/services/GetServersHandler.java index ead823087b..f276c1107b 100644 --- a/edexOsgi/com.raytheon.edex.utilitysrv/src/com/raytheon/edex/services/GetServersHandler.java +++ b/edexOsgi/com.raytheon.edex.utilitysrv/src/com/raytheon/edex/services/GetServersHandler.java @@ -43,6 +43,8 @@ import com.raytheon.uf.common.util.registry.GenericRegistry; * Jan 14, 2013 1469 bkowal No longer includes the hdf5 data directory * in the response. * May 28, 2013 1989 njensen Uses env variables instead of system props + * Aug 27, 2013 2295 bkowal Return the entire jms connection url in + * the response. * * * @@ -61,18 +63,41 @@ public class GetServersHandler extends GenericRegistry GetServersResponse response = new GetServersResponse(); String httpServer = System.getenv("HTTP_SERVER"); String jmsServer = System.getenv("JMS_SERVER"); + String jmsVirtualHost = System.getenv("JMS_VIRTUALHOST"); String pypiesServer = System.getenv("PYPIES_SERVER"); + String jmsConnectionString = this.constructJMSConnectionString( + jmsServer, jmsVirtualHost); logger.info("http.server=" + httpServer); logger.info("jms.server=" + jmsServer); + logger.info("jms.virtualhost=" + jmsVirtualHost); logger.info("pypies.server=" + pypiesServer); logger.info("server locations=" + registry); ; response.setHttpServer(httpServer); - response.setJmsServer(jmsServer); + response.setJmsConnectionString(jmsConnectionString); response.setPypiesServer(pypiesServer); response.setServerLocations(Collections.unmodifiableMap(this.registry)); return response; } + + // do not enable retry/connectdelay connection and factory will + // silently reconnect and user will never be notified qpid is down + // and cave/text workstation will just act like they are hung + // up to each individual component that opens a connection to handle + // reconnect + private String constructJMSConnectionString(String jmsServer, + String jmsVirtualHost) { + /* build the connection String that CAVE will use. */ + StringBuilder stringBuilder = new StringBuilder( + "amqp://guest:guest@__WSID__/"); + stringBuilder.append(jmsVirtualHost); + stringBuilder.append("?brokerlist='"); + stringBuilder.append(jmsServer); + stringBuilder + .append("?connecttimeout='5000'&heartbeat='0''&maxprefetch='10'&sync_publish='all'&failover='nofailover'&sync_ack='true'"); + + return stringBuilder.toString(); + } } diff --git a/edexOsgi/com.raytheon.uf.common.archive/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.archive/META-INF/MANIFEST.MF index 7fa1445e69..fdbfc9a0b5 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.archive/META-INF/MANIFEST.MF @@ -6,9 +6,14 @@ Bundle-Version: 1.0.0.qualifier Bundle-Vendor: RAYTHEON Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Export-Package: com.raytheon.uf.common.archive.config, - com.raytheon.uf.common.archive.exception + com.raytheon.uf.common.archive.config.select, + com.raytheon.uf.common.archive.exception, + com.raytheon.uf.common.archive.request Require-Bundle: com.raytheon.uf.common.util, com.raytheon.uf.common.localization, com.raytheon.uf.common.status, org.apache.commons.io, - com.raytheon.uf.common.time + com.raytheon.uf.common.time, + com.raytheon.uf.common.serialization;bundle-version="1.12.1174", + com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174", + com.raytheon.uf.common.auth;bundle-version="1.12.1174" diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java index ae9dc87732..7c7c470ed5 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java @@ -21,6 +21,8 @@ package com.raytheon.uf.common.archive.config; import java.io.File; import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.text.FieldPosition; import java.text.MessageFormat; @@ -30,10 +32,11 @@ import java.util.Calendar; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TimeZone; -import java.util.TreeSet; +import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -46,6 +49,9 @@ import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.RegexFileFilter; +import com.raytheon.uf.common.archive.config.ArchiveConstants.Type; +import com.raytheon.uf.common.archive.config.select.ArchiveSelect; +import com.raytheon.uf.common.archive.config.select.CategorySelect; import com.raytheon.uf.common.archive.exception.ArchiveException; import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext; @@ -56,6 +62,7 @@ import com.raytheon.uf.common.localization.LocalizationFileInputStream; import com.raytheon.uf.common.localization.LocalizationFileOutputStream; import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.localization.exception.LocalizationException; +import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; @@ -78,7 +85,9 @@ import com.raytheon.uf.common.util.FileUtil; * Added null check for topLevelDirs in purgeExpiredFromArchive. * Changed to use File.delete() instead of Apache FileUtil.deleteQuietly(). * Added warn logging for failure to delete. - * + * Jul 24, 2013 2221 rferrel Changes for select configuration. + * Aug 06, 2013 2224 rferrel Changes to use DataSet. + * Aug 28, 2013 2299 rferrel purgeExpiredFromArchive now returns the number of files purged. * * * @author rferrel @@ -95,7 +104,7 @@ public class ArchiveConfigManager { public final String ARCHIVE_DIR = "archiver/purger"; /** Localization manager. */ - private IPathManager pathMgr; + protected IPathManager pathMgr; private final Map archiveNameToLocalizationFileMap = new HashMap(); @@ -171,9 +180,34 @@ public class ArchiveConfigManager { } /** + * Obtain the collection of Archives setting the Categories' selections + * based on the default retention selections. + * * @return the Collection of Archives. */ public Collection getArchives() { + String fileName = ArchiveConstants.selectFileName(Type.Retention, null); + SelectConfig selections = loadSelection(fileName); + if (selections != null && !selections.isEmpty()) { + try { + for (ArchiveSelect archiveSelect : selections.getArchiveList()) { + ArchiveConfig archiveConfig = archiveMap.get(archiveSelect + .getName()); + for (CategorySelect categorySelect : archiveSelect + .getCategorySelectList()) { + CategoryConfig categoryConfig = archiveConfig + .getCategory(categorySelect.getName()); + categoryConfig.setSelectedDisplayNames(categorySelect + .getSelectList()); + } + } + } catch (NullPointerException ex) { + statusHandler + .handle(Priority.ERROR, + "Retention selection and Archive configuration no longer in sync: ", + ex); + } + } return archiveMap.values(); } @@ -254,18 +288,22 @@ public class ArchiveConfigManager { * Archive. * * @param archive - * @return the list of expired Files purged + * @return purgeCount */ - public Collection purgeExpiredFromArchive(ArchiveConfig archive) { - Collection filesPurged = new ArrayList(); + public int purgeExpiredFromArchive(ArchiveConfig archive) { String archiveRootDirPath = archive.getRootDir(); File archiveRootDir = new File(archiveRootDirPath); + String[] topLevelDirs = archiveRootDir.list(); + List topLevelDirsNotPurged = new ArrayList(); + int purgeCount = 0; if (topLevelDirs != null) { topLevelDirsNotPurged.addAll(Arrays.asList(topLevelDirs)); + topLevelDirs = null; } + for (CategoryConfig category : archive.getCategoryList()) { Calendar purgeTime = calculateExpiration(archive, category); CategoryFileDateHelper helper = new CategoryFileDateHelper( @@ -289,68 +327,92 @@ public class ArchiveConfigManager { List displayFiles = getDisplayFiles(display, null, purgeTime); for (File file : displayFiles) { - filesPurged.addAll(purgeFile(file, fileDateFilter, - archiveRootDirPath)); + purgeCount += purgeFile(file, fileDateFilter); } } } // check for other expired in top level directories not covered - // by the categories in the archives + // by the categories in the archive. Calendar defaultPurgeTime = calculateExpiration(archive, null); + IOFileFilter fileDateFilter = FileFilterUtils.and(FileFilterUtils + .fileFileFilter(), new FileDateFilter(null, defaultPurgeTime)); for (String topDirName : topLevelDirsNotPurged) { - IOFileFilter fileDateFilter = FileFilterUtils.and(FileFilterUtils - .fileFileFilter(), new FileDateFilter(null, - defaultPurgeTime)); File topLevelDir = new File(archiveRootDir, topDirName); - filesPurged.addAll(purgeFile(topLevelDir, fileDateFilter, - archiveRootDirPath)); + // Keep both top level hidden files and hidden directories. + if (!topLevelDir.isHidden()) { + purgeCount += purgeFile(topLevelDir, fileDateFilter); + } } - return filesPurged; + return purgeCount; } - private Collection purgeFile(File fileToPurge, IOFileFilter filter, - final String archiveRootDir) { - Collection filesPurged = new ArrayList(); + /** + * Recursive method for purging files. Never pass in a directory you do not + * want deleted when purging makes it an empty directory. + * + * @param fileToPurge + * @param filter + * @return purgeCount number of files and directories purged + */ + private int purgeFile(File fileToPurge, IOFileFilter filter) { + int purgeCount = 0; if (fileToPurge.isFile() && filter.accept(fileToPurge)) { if (fileToPurge.delete()) { - filesPurged.add(fileToPurge); + ++purgeCount; + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler.debug("Purged file: \"" + + fileToPurge.getAbsolutePath() + "\""); + } } else { statusHandler.warn("Failed to purge file: " + fileToPurge.getAbsolutePath()); } - } else if (fileToPurge.isDirectory()) { - Collection expiredFilesInDir = FileUtils.listFiles( - fileToPurge, filter, FileFilterUtils.trueFileFilter()); + } else if (fileToPurge.isDirectory() && !fileToPurge.isHidden()) { + // Purge only visible directories. + File[] expiredFilesInDir = fileToPurge.listFiles(); for (File dirFile : expiredFilesInDir) { - filesPurged.addAll(purgeFile(dirFile, filter, archiveRootDir)); + purgeCount += purgeFile(dirFile, filter); } - // if the directory is empty and not the archive root dir, then - // delete it - if (fileToPurge.list().length == 0 - && !fileToPurge.getAbsolutePath().equals(archiveRootDir)) { + // Attempt to delete empty directory. + if ((purgeCount >= expiredFilesInDir.length) + && (fileToPurge.list().length == 0)) { if (!fileToPurge.delete()) { statusHandler.warn("Failed to purge directory: " + fileToPurge.getAbsolutePath()); + } else { + ++purgeCount; + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler.debug("Purged directory: \"" + + fileToPurge.getAbsolutePath() + + File.separator + "\""); + } } } } - return filesPurged; + return purgeCount; } + /** + * Get expiration time for the category. + * + * @param archive + * @param category + * @return expireCal + */ private Calendar calculateExpiration(ArchiveConfig archive, CategoryConfig category) { - Calendar newCal = TimeUtil.newGmtCalendar(); + Calendar expireCal = TimeUtil.newGmtCalendar(); int retHours = category == null || category.getRetentionHours() == 0 ? archive .getRetentionHours() : category.getRetentionHours(); if (retHours != 0) { - newCal.add(Calendar.HOUR, (-1) * retHours); + expireCal.add(Calendar.HOUR, (-1) * retHours); } - return newCal; + return expireCal; } /** @@ -497,91 +559,79 @@ public class ArchiveConfigManager { */ private List getDisplayFiles(DisplayData displayData, long startTime, long endTime) { + List fileList = new LinkedList(); ArchiveConfig archiveConfig = displayData.archiveConfig; - CategoryConfig categoryConfig = displayData.categoryConfig; - String[] indexValues = categoryConfig.getDateGroupIndices().split( - "\\s*,\\s*"); - int yearIndex = Integer.parseInt(indexValues[0]); - int monthIndex = Integer.parseInt(indexValues[1]); - int dayIndex = Integer.parseInt(indexValues[2]); - int hourIndex = Integer.parseInt(indexValues[3]); + for (CategoryDataSet dataSet : displayData.dataSets) { - String filePatternStr = categoryConfig.getFilePattern(); + int[] timeIndices = dataSet.getTimeIndices(); - boolean dirOnly = (filePatternStr == null) - || ".*".equals(filePatternStr); + String filePatternStr = dataSet.getFilePattern(); - List dirs = displayData.dirs; + boolean dirOnly = dataSet.isDirOnly(); - int beginIndex = archiveConfig.getRootDir().length(); + List dirs = displayData.dirsMap.get(dataSet); - Calendar fileCal = TimeUtil.newCalendar(); - fileCal.setTimeZone(TimeZone.getTimeZone("UTC")); + int beginIndex = archiveConfig.getRootDir().length(); - List fileList = new ArrayList(); + Calendar fileCal = TimeUtil.newCalendar(); + fileCal.setTimeZone(TimeZone.getTimeZone("UTC")); - if (dirOnly) { - for (String dirPattern : categoryConfig.getDirPatternList()) { - Pattern pattern = Pattern.compile(dirPattern); + if (dirOnly) { + for (String dirPattern : dataSet.getDirPatterns()) { + Pattern pattern = dataSet.getPattern(dirPattern); - for (File dir : dirs) { - String path = dir.getAbsolutePath().substring(beginIndex); - Matcher matcher = pattern.matcher(path); - if (matcher.matches()) { - int year = Integer.parseInt(matcher.group(yearIndex)); - // Adjust month value to Calendar's 0 - 11 - int month = Integer.parseInt(matcher.group(monthIndex)) - 1; - int day = Integer.parseInt(matcher.group(dayIndex)); - int hour = Integer.parseInt(matcher.group(hourIndex)); - fileCal.set(year, month, day, hour, 0, 0); - long fileTime = fileCal.getTimeInMillis(); - if ((startTime <= fileTime) && (fileTime < endTime)) { - fileList.add(dir); - } - } - } - } - } else { - for (String dirPattern : categoryConfig.getDirPatternList()) { - Pattern pattern = Pattern.compile(dirPattern + File.separator - + categoryConfig.getFilePattern()); - final Pattern filePattern = Pattern.compile("^" - + filePatternStr + "$"); - for (File dir : dirs) { - List fList = FileUtil.listDirFiles(dir, - new FileFilter() { - - @Override - public boolean accept(File pathname) { - return filePattern.matcher( - pathname.getName()).matches(); - } - }, false); - for (File file : fList) { - String path = file.getAbsolutePath().substring( + for (File dir : dirs) { + String path = dir.getAbsolutePath().substring( beginIndex); Matcher matcher = pattern.matcher(path); if (matcher.matches()) { - int year = Integer.parseInt(matcher - .group(yearIndex)); - // Adjust month value to Calendar's 0 - 11 - int month = Integer.parseInt(matcher - .group(monthIndex)) - 1; - int day = Integer.parseInt(matcher.group(dayIndex)); - int hour = Integer.parseInt(matcher - .group(hourIndex)); - fileCal.set(year, month, day, hour, 0, 0); - long fileTime = fileCal.getTimeInMillis(); + Long fileTime = dataSet.getMatchTimeInMilliseconds( + timeIndices, matcher); + if (fileTime == null) { + fileTime = dir.lastModified(); + } if ((startTime <= fileTime) && (fileTime < endTime)) { - fileList.add(file); + fileList.add(dir); + } + } + } + } + } else { + for (String dirPattern : dataSet.getDirPatterns()) { + Pattern pattern = dataSet.getPattern(dirPattern); + final Pattern filePattern = Pattern.compile("^" + + filePatternStr + "$"); + for (File dir : dirs) { + List fList = FileUtil.listDirFiles(dir, + new FileFilter() { + + @Override + public boolean accept(File pathname) { + return filePattern.matcher( + pathname.getName()).matches(); + } + }, false); + for (File file : fList) { + String path = file.getAbsolutePath().substring( + beginIndex); + Matcher matcher = pattern.matcher(path); + if (matcher.matches()) { + Long timestamp = dataSet + .getMatchTimeInMilliseconds( + timeIndices, matcher); + long fileTime = timestamp == null ? file + .lastModified() : timestamp.longValue(); + if ((startTime <= fileTime) + && (fileTime < endTime)) { + fileList.add(file); + } } } } } } } - return fileList; } @@ -593,15 +643,13 @@ public class ArchiveConfigManager { * @param categoryConfig * @return dirs */ - private List getDirs(ArchiveConfig archiveConfig, - CategoryConfig categoryConfig) { + private List getDirs(File rootFile, CategoryDataSet dataSet) { List resultDirs = new ArrayList(); - File rootFile = new File(archiveConfig.getRootDir()); List dirs = new ArrayList(); List tmpDirs = new ArrayList(); List swpDirs = null; - for (String dirPattern : categoryConfig.getDirPatternList()) { + for (String dirPattern : dataSet.getDirPatterns()) { String[] subExpr = dirPattern.split(File.separator); dirs.clear(); dirs.add(rootFile); @@ -630,20 +678,6 @@ public class ArchiveConfigManager { return resultDirs; } - /** - * Get the Display labels matching the pattern for the archive data's - * category. Assumes the archive data's root directory is the mount point to - * start the search. - * - * @param archiveName - * @param categoryName - * @return displayInfoList order by display label - */ - public List getDisplayData(String archiveName, - String categoryName) { - return getDisplayData(archiveName, categoryName, false); - } - /** * Get the Display labels matching the pattern for the archive data's * category. Assumes the archive data's root directory is the mount point to @@ -661,50 +695,60 @@ public class ArchiveConfigManager { Map> displayMap = new HashMap>(); ArchiveConfig archiveConfig = archiveMap.get(archiveName); + String rootDirName = archiveConfig.getRootDir(); CategoryConfig categoryConfig = findCategory(archiveConfig, categoryName); - List dirPatternList = categoryConfig.getDirPatternList(); + File rootFile = new File(rootDirName); + TreeMap displays = new TreeMap(); + for (CategoryDataSet dataSet : categoryConfig.getDataSetList()) { + List dataSetDirPatterns = dataSet.getDirPatterns(); - // index for making directory paths' relative to the root path. - List dirs = getDirs(archiveConfig, categoryConfig); + List dirs = getDirs(rootFile, dataSet); - File rootFile = new File(archiveMap.get(archiveName).getRootDir()); - int beginIndex = rootFile.getAbsolutePath().length() + 1; - List patterns = new ArrayList(dirPatternList.size()); + int beginIndex = rootFile.getAbsolutePath().length() + 1; + List patterns = new ArrayList( + dataSetDirPatterns.size()); - for (String dirPattern : dirPatternList) { - Pattern pattern = Pattern.compile("^" + dirPattern + "$"); - patterns.add(pattern); - } + for (String dirPattern : dataSetDirPatterns) { + Pattern pattern = Pattern.compile("^" + dirPattern + "$"); + patterns.add(pattern); + } - TreeSet displays = new TreeSet( - String.CASE_INSENSITIVE_ORDER); + MessageFormat msgfmt = new MessageFormat(dataSet.getDisplayLabel()); + StringBuffer sb = new StringBuffer(); + FieldPosition pos0 = new FieldPosition(0); - MessageFormat msgfmt = new MessageFormat(categoryConfig.getDisplay()); - StringBuffer sb = new StringBuffer(); - FieldPosition pos0 = new FieldPosition(0); + for (File dir : dirs) { + String path = dir.getAbsolutePath().substring(beginIndex); + for (Pattern pattern : patterns) { + Matcher matcher = pattern.matcher(path); + if (matcher.matches()) { + sb.setLength(0); + String[] args = new String[matcher.groupCount() + 1]; + args[0] = matcher.group(); + for (int i = 1; i < args.length; ++i) { + args[i] = matcher.group(i); + } + String displayLabel = msgfmt.format(args, sb, pos0) + .toString(); + List displayDirs = displayMap.get(displayLabel); + if (displayDirs == null) { + displayDirs = new ArrayList(); + displayMap.put(displayLabel, displayDirs); + } + displayDirs.add(dir); + DisplayData displayData = displays.get(displayLabel); + if (displayData == null) { + displayData = new DisplayData(archiveConfig, + categoryConfig, dataSet, displayLabel); + displays.put(displayLabel, displayData); + } else if (!displayData.dataSets.contains(dataSet)) { + displayData.dataSets.add(dataSet); + } - for (File dir : dirs) { - String path = dir.getAbsolutePath().substring(beginIndex); - for (Pattern pattern : patterns) { - Matcher matcher = pattern.matcher(path); - if (matcher.matches()) { - sb.setLength(0); - String[] args = new String[matcher.groupCount() + 1]; - args[0] = matcher.group(); - for (int i = 1; i < args.length; ++i) { - args[i] = matcher.group(i); + displayData.dirsMap.put(dataSet, displayDirs); + break; } - String displayLabel = msgfmt.format(args, sb, pos0) - .toString(); - List displayDirs = displayMap.get(displayLabel); - if (displayDirs == null) { - displayDirs = new ArrayList(); - displayMap.put(displayLabel, displayDirs); - } - displayDirs.add(dir); - displays.add(displayLabel); - break; } } } @@ -712,15 +756,7 @@ public class ArchiveConfigManager { List displayDataList = new ArrayList( displays.size()); - for (String displayLabel : displays) { - DisplayData displayData = new DisplayData(archiveConfig, - categoryConfig, displayLabel, displayMap.get(displayLabel)); - if (setSelect) { - displayData.setSelected(categoryConfig - .getSelectedDisplayNames().contains(displayLabel)); - } - displayDataList.add(displayData); - } + displayDataList.addAll(displays.values()); return displayDataList; } @@ -788,4 +824,176 @@ public class ArchiveConfigManager { return archiveConfig; } + /** + * Delete the selection localized site configuration file. + * + * @param fileName + * @throws LocalizationOpFailedException + */ + public void deleteSelection(String fileName) + throws LocalizationOpFailedException { + LocalizationContext siteContext = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile lFile = pathMgr.getLocalizationFile(siteContext, + ARCHIVE_DIR + "/" + fileName); + lFile.delete(); + } + + /** + * Load the localized site select configuration file. + * + * @param fileName + * @return selectConfig + */ + public SelectConfig loadSelection(String fileName) { + SelectConfig selections = null; + LocalizationContext siteContext = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile lFile = pathMgr.getLocalizationFile(siteContext, + ARCHIVE_DIR + "/" + fileName); + if (lFile.exists()) { + FileInputStream stream = null; + try { + stream = lFile.openInputStream(); + selections = unmarshallSelectionStream(stream); + } catch (LocalizationException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + e); + } catch (IOException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + e); + } finally { + if (stream != null) { + try { + stream.close(); + } catch (IOException ex) { + // Ignore + } + } + } + } + return selections; + } + + // TODO possible future methods for supporting importing and exporting + // select configurations. + // + // public SelectConfig importSelections(File selectFile) throws IOException + // { + // SelectConfig selections = null; + // FileInputStream stream = new FileInputStream(selectFile); + // selections = unmarshallSelectionStream(stream); + // return selections; + // } + // + // public boolean exportSelections(SelectConfig selections, File selectFile) + // throws IOException, LocalizationException { + // FileOutputStream stream = null; + // try { + // stream = new FileOutputStream(selectFile); + // marshalSelectStream(selections, stream); + // } finally { + // if (stream != null) { + // try { + // stream.close(); + // } catch (IOException ex) { + // // Ignore + // } + // } + // } + // return false; + // } + + /** + * Get a list of selection names based on the select configuration files in + * the type's directory. + * + * @param type + * @return selectNames + */ + public String[] getSelectionNames(ArchiveConstants.Type type) { + LocalizationFile[] files = pathMgr.listStaticFiles(ARCHIVE_DIR + + IPathManager.SEPARATOR + type.selectionDir, + new String[] { ArchiveConstants.configFileExt }, false, true); + String[] names = new String[files.length]; + int extLen = ArchiveConstants.configFileExt.length(); + int i = 0; + StringBuilder sb = new StringBuilder(); + for (LocalizationFile lFile : files) { + sb.setLength(0); + sb.append(lFile.getName()); + sb.setLength(sb.length() - extLen); + names[i] = sb.substring(sb.lastIndexOf(IPathManager.SEPARATOR) + 1); + ++i; + } + Arrays.sort(names, String.CASE_INSENSITIVE_ORDER); + return names; + } + + /** + * Save the selections configuration in the desired file. + * + * @param selections + * @param fileName + * @throws LocalizationException + * @throws IOException + */ + public void saveSelections(SelectConfig selections, String fileName) + throws LocalizationException, IOException { + LocalizationFileOutputStream stream = null; + LocalizationContext siteContext = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile lFile = pathMgr.getLocalizationFile(siteContext, + ARCHIVE_DIR + IPathManager.SEPARATOR + fileName); + + try { + stream = lFile.openOutputStream(); + marshalSelectStream(selections, stream); + } finally { + if (stream != null) { + try { + stream.closeAndSave(); + } catch (Exception ex) { + // Ignore + } + } + } + } + + /** + * load select configuration from the stream. + * + * @param stream + * @return selectConfig + * @throws IOException + */ + private SelectConfig unmarshallSelectionStream(FileInputStream stream) + throws IOException { + SelectConfig selections = null; + try { + selections = JAXB.unmarshal(stream, SelectConfig.class); + } finally { + if (stream != null) { + try { + stream.close(); + } catch (IOException ex) { + // ignore + } + } + } + return selections; + } + + /** + * Save select configuration to the desired stream. + * + * @param selections + * @param stream + * @throws IOException + * @throws LocalizationException + */ + private void marshalSelectStream(SelectConfig selections, + FileOutputStream stream) throws IOException, LocalizationException { + JAXB.marshal(selections, stream); + } } diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConstants.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConstants.java new file mode 100644 index 0000000000..71f1e6af2c --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConstants.java @@ -0,0 +1,112 @@ +/** + * 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.common.archive.config; + +import java.util.regex.Pattern; + +import com.raytheon.uf.common.localization.IPathManager; + +/** + * Constants used by purger and GUIs. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 23, 2013 #2221      rferrel     Initial creation
+ * Aug 26, 2013 #2225      rferrel     Added tar extension.
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public class ArchiveConstants { + + /** Pattern to find slashes in a string. */ + private final static Pattern slashPattern = Pattern.compile("[/\\\\]+"); + + /** Pattern to find white space in a string. */ + private final static Pattern wsPattern = Pattern.compile("\\s+"); + + /** Default selection name to display. */ + public static final String defaultSelectName = "DEFAULT"; + + /** Extension to use for creating a configuration's file name. */ + public static final String configFileExt = ".xml"; + + /** Types of select configuration and their relative localized directory. */ + public enum Type { + Retention("retention" + IPathManager.SEPARATOR), Case("case" + + IPathManager.SEPARATOR); + + public final String selectionDir; + + private Type(String selectionDir) { + this.selectionDir = selectionDir; + } + } + + /** Extension for compressed tar files. */ + public final static String TAR_EXTENSION = ".tgz"; + + /** + * Do not allow an instance of this class. + */ + private ArchiveConstants() { + } + + /** + * Get relative path file name for a select configuration file based on type + * and name. + * + * @param type + * @param name + * - when null use the default select name. + * @return fileName + */ + public static final String selectFileName(Type type, String name) { + String fileName = name; + if (fileName == null) { + fileName = defaultSelectName; + } else { + fileName = convertToFileName(name); + } + return type.selectionDir + fileName + configFileExt; + } + + /** + * Convert name to fileName by trimming whitespace, converting slashes to + * hyphens and embedded whitespace to underscore. + * + * @param name + * - must not be null + * @return fileName + */ + public static final String convertToFileName(String name) { + String fileName = name.trim(); + fileName = slashPattern.matcher(fileName).replaceAll("-"); + fileName = wsPattern.matcher(fileName).replaceAll("_"); + return fileName; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryConfig.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryConfig.java index a97dcf22d3..42f5ba8d9a 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryConfig.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryConfig.java @@ -39,10 +39,13 @@ import javax.xml.bind.annotation.XmlRootElement; * <name>redbook</name> * <!-- When 0 default to the parent archive's retentionHours --> * <retentionHours>0</retentionHours> - * <dirPattern>hdf5/(redbook)</dirPattern> - * <displayLabel>{1}</displayLabel> - * <filePattern>redbook-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..*</filePattern> - * <dateGroupIndices>2,3,4,5</dateGroupIndices> + * <dataSet> + * <dirPattern>hdf5/(redbook)</dirPattern> + * <displayLabel>{1}</displayLabel> + * <filePattern>redbook-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..*</filePattern> + * <timeType>Date</timeType> + * <dateGroupIndices>2,3,4,5</dateGroupIndices> + * </dataSet> * </category> * * @@ -52,9 +55,12 @@ import javax.xml.bind.annotation.XmlRootElement; * <category> * <name>Model grib</name> * <retentionHours>0</retentionHours> - * <dirPattern>grib/(\d{4})(\d{2})(\d{2})/(\d{2})/(.*)</dirPattern> - * <displayLabel>{5}</displayLabel> - * <dateGroupIndices>1,2,3,4</dateGroupIndices> + * <dataSet> + * <dirPattern>grib/(\d{4})(\d{2})(\d{2})/(\d{2})/(.*)</dirPattern> + * <displayLabel>{5}</displayLabel> + * <timeType>Date</timeType> + * <dateGroupIndices>1,2,3,4</dateGroupIndices> + * </dataSet> * </category> * * @@ -65,6 +71,7 @@ import javax.xml.bind.annotation.XmlRootElement; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * May 1, 2013 1966 rferrel Initial creation + * Aug 03, 2013 2224 rferrel Changes to include DataSet. * * * @@ -88,63 +95,8 @@ public class CategoryConfig implements Comparable { @XmlElement(name = "extRetentionHours") private int retentionHours; - /** - * A regex pattern to find directories controlled by the category. These - * directories should be relative to the parent archive's directory. For - * example: - * - *
-     * <dirPattern>grib2/\d{8}/\d{2}/(.*)/</dirPattern>
-     * 
- */ - @XmlElement(name = "dirPattern") - private List dirPatternList; - - /** - * Use to display the information found by the dirPattern. Any groups in the - * dirPatern may be displayed. For example: - * - *
-     * <dirName>(grib2)/(\d{4})(\d{2})(\d{2})/(\d{2})/(.*)</dirName>
-     * <displayLabel>{1} - {6}</displayLabel>
-     * 
- * - * The {1} will be replaced by the first group (grib2) in the regex - * expression in dirName. The {6} is the sixth group (.*). {0} is the whole - * expression match. - */ - @XmlElement(name = "displayLabel") - private String display; - - /** - * A comma separated list of 4 numbers representing the group indices - * specifying the location of the numeric date time stamp. The indices must - * be in the order of year, month, day and hour. The group numbering starts - * with the first group in the dirPattern and continues with any grouping in - * the filePattern. - * - *
-     *   <dirPattern>hdf5/(redbook)</dirPattern>
-     *   <displayLabel>{1}</displayLabel>
-     *   <filePattern>redbook-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..*</filePattern>
-     *   <dateGroupIndices>2,3,4,5</dateGroupIndices>
-     * 
- */ - @XmlElement(name = "dateGroupIndices") - private String dateGroupIndices; - - /** - * A saveDir directory may contain files with data for several days. This - * allows any of the year, month, day and hour to be part of a file name. - * Default is all files in the directory. For example: - * - *
-     * <saveDir>hd5/redbook/(^/]*//)</saveDir>
-     * <saveFile>redbook-${YYYY}-${MM}-${DD}-${HH}\..*<saveFiles>
-     * 
- */ - @XmlElement(name = "filePattern") - private String filePattern; + @XmlElement(name = "dataSet") + private List dataSetList; @XmlElement(name = "selectedDisplayName") private final Collection selectedDisplayNames = new TreeSet(); @@ -188,76 +140,12 @@ public class CategoryConfig implements Comparable { this.retentionHours = retentionHours; } - /** - * Obtain the list of directory patterns. - * - * @return dirPatternList - */ - public List getDirPatternList() { - return new ArrayList(dirPatternList); + public List getDataSetList() { + return new ArrayList(dataSetList); } - /** - * Set the directory pattern list; must not be null. - * - * @param dirPatternList - */ - public void setDirPatternList(List dirPatternList) { - this.dirPatternList = dirPatternList; - } - - /** - * Get the display label pattern. - * - * @return display - */ - public String getDisplay() { - return display == null ? "" : display; - } - - /** - * Set the display label pattern. - * - * @param display - */ - public void setDisplay(String display) { - this.display = display; - } - - /** - * Get the save directory pattern.. - * - * @return dateGroups - */ - public String getDateGroupIndices() { - return dateGroupIndices; - } - - /** - * Set the save directory pattern; must not be null. - * - * @param saveDir - */ - public void setDateGroupIndices(String dateGroupIndices) { - this.dateGroupIndices = dateGroupIndices; - } - - /** - * Get the save files pattern. - * - * @return saveFiles - */ - public String getFilePattern() { - return filePattern; - } - - /** - * Set the save files pattern; may be null. - * - * @param saveFiles - */ - public void setFilePattern(String filePattern) { - this.filePattern = filePattern; + public void setDataSetList(List dataSetList) { + this.dataSetList = dataSetList; } public Collection getSelectedDisplayNames() { @@ -285,9 +173,9 @@ public class CategoryConfig implements Comparable { */ @Override public int compareTo(CategoryConfig o) { - return getDisplay().compareToIgnoreCase(o.getDisplay()); + return getName().compareToIgnoreCase(o.getName()); } - + /* * (non-Javadoc) * @@ -298,13 +186,10 @@ public class CategoryConfig implements Comparable { StringBuilder sb = new StringBuilder(); sb.append("Category [ name: ").append(getName()); sb.append(", retentionHours: ").append(getRetentionHours()); - sb.append(", dirPatternList[ "); - for (String dirPattern : getDirPatternList()) { - sb.append(" \"").append(dirPattern).append("\","); + sb.append(", dataSetList[ "); + for (CategoryDataSet dataSet : getDataSetList()) { + sb.append(dataSet).append(", "); } - sb.append("], filePattern: ").append(getFilePattern()); - sb.append(", displayLabel: ").append(getDisplay()); - sb.append(", dateGroupIndices: ").append(getDateGroupIndices()); sb.append(", selectedDisplayNames: "); if (selectedDisplayNames == null) { sb.append("null"); diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryDataSet.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryDataSet.java new file mode 100644 index 0000000000..a68e9f887f --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryDataSet.java @@ -0,0 +1,294 @@ +/** + * 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.common.archive.config; + +import java.io.File; +import java.util.Calendar; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.common.time.util.TimeUtil; + +/** + * A grouping of data set information used in a category. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 6, 2013  #2224      rferrel     Initial creation
+ * Oct 02, 2013 #2147      rferrel     Allow Date to ignore hour in time stamp.
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ +@XmlAccessorType(XmlAccessType.NONE) +@XmlRootElement(name = "dataSet") +public class CategoryDataSet { + public static final int YEAR_INDEX = 0; + + public static final int MONTH_INDEX = 1; + + public static final int DAY_INDEX = 2; + + public static final int HOUR_INDEX = 3; + + public static final int TIMESTAMP_INDEX = 0; + + /** + * Types of times and the number of indices for getting the time stamp from + * patterns. + */ + public static enum TimeType { + Date(4), EpochSec(1), EpochMS(1), File(0); + + private final int numIndices; + + private TimeType(int numIndices) { + this.numIndices = numIndices; + } + + public int getNumGroupIndices() { + return numIndices; + } + } + + /** + * List of directory patterns. + */ + @XmlElement(name = "dirPattern") + private List dirPatterns; + + /** + * Optional file pattern. + */ + @XmlElement(name = "filePattern") + private String filePattern; + + @XmlElement(name = "timeType") + private TimeType timeType = TimeType.Date; + + /** + * The display label. + */ + @XmlElement(name = "displayLabel") + private String displayLabel; + + private int[] timeIndices = null; + + /** + * The index with group number for getting desired parts of the TimeType. + */ + @XmlElement(name = "dateGroupIndices") + private String dateGroupIndices = ""; + + public List getDirPatterns() { + return dirPatterns; + } + + public void setDirPatterns(List dirPatterns) { + this.dirPatterns = dirPatterns; + } + + public String getFilePattern() { + return filePattern; + } + + public void setFilePattern(String filePattern) { + this.filePattern = filePattern; + } + + public TimeType getTimeType() { + return timeType; + } + + public void setTimeType(TimeType timeType) { + this.timeType = timeType; + } + + public String getDisplayLabel() { + return displayLabel; + } + + public void setDisplayLabel(String displayLabel) { + this.displayLabel = displayLabel; + } + + public String getDateGroupIndices() { + return dateGroupIndices; + } + + public void setDateGroupIndices(String dateGroupIndices) { + this.dateGroupIndices = dateGroupIndices; + this.timeIndices = null; + } + + /** + * Get the array of time indices based on time type and date group indices. + * + * @return timeIndices + */ + public int[] getTimeIndices() { + if (timeIndices == null) { + timeIndices = new int[timeType.getNumGroupIndices()]; + if (timeIndices.length > 0) { + String[] indexValues = getDateGroupIndices().split("\\s*,\\s*"); + for (int index = 0; index < timeIndices.length; ++index) { + if (indexValues.length > index) { + timeIndices[index] = Integer + .parseInt(indexValues[index]); + } else { + timeIndices[index] = -1; + } + } + } + } + return timeIndices; + } + + /** + * Get the Pattern for dirPattern. + * + * @param dirPattern + * + * @return pattern or null if dirPattern not in the list of directory + * patterns. + */ + public Pattern getPattern(String dirPattern) { + Pattern pattern = null; + if (dirPatterns.contains(dirPattern)) { + if (isDirOnly()) { + pattern = Pattern.compile(dirPattern); + } else { + pattern = Pattern.compile(dirPattern + File.separator + + getFilePattern()); + } + } + return pattern; + } + + /** + * + * @return true when only the dirPatterns should be used. + */ + public boolean isDirOnly() { + return filePattern == null || filePattern.equals(".*"); + } + + /** + * Get time stamp for file based on time type. + * + * @param timeIndices + * @param matcher + * @return fileTime + */ + public Long getMatchTimeInMilliseconds(int[] timeIndices, Matcher matcher) { + return CategoryDataSet.getMatchTimeInMilliseconds(timeType, + timeIndices, matcher); + } + + /** + * Get file time based on time type. Assumes the matcher is set up matching + * a file's path name so the groups in the matcher can be used to get the + * time stamp. + * + * @param timeType + * @param timeIndices + * @param matcher + * @return fileTime or null if time type does not get time using the + * matcher. + */ + public static Long getMatchTimeInMilliseconds( + CategoryDataSet.TimeType timeType, int[] timeIndices, + Matcher matcher) { + Long fileTime = null; + switch (timeType) { + case Date: + Calendar fileCal = TimeUtil.newGmtCalendar(); + int year = Integer.parseInt(matcher + .group(timeIndices[CategoryDataSet.YEAR_INDEX])); + // Adjust month value to Calendar's 0 - 11 + int month = Integer.parseInt(matcher + .group(timeIndices[CategoryDataSet.MONTH_INDEX])) - 1; + int day = Integer.parseInt(matcher + .group(timeIndices[CategoryDataSet.DAY_INDEX])); + + // Default to last hour of the day. + int hour = 23; + + if (timeIndices[CategoryDataSet.HOUR_INDEX] >= 0) { + hour = Integer.parseInt(matcher + .group(timeIndices[CategoryDataSet.HOUR_INDEX])); + } + + fileCal.set(year, month, day, hour, 0, 0); + fileTime = fileCal.getTimeInMillis(); + break; + case EpochMS: + fileTime = Long.parseLong(matcher + .group(timeIndices[CategoryDataSet.TIMESTAMP_INDEX])); + break; + case EpochSec: + fileTime = Long.parseLong(matcher + .group(timeIndices[CategoryDataSet.TIMESTAMP_INDEX])); + fileTime *= TimeUtil.MILLIS_PER_SECOND; + break; + case File: + fileTime = null; + break; + default: + fileTime = null; + break; + } + return fileTime; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder("DataSet[ "); + sb.append("TimeType: ").append(getTimeType()); + sb.append(", dateGroupIndices: ").append(getDateGroupIndices()); + sb.append(", isDirOnly: ").append(isDirOnly()); + sb.append(", displayLabel: ").append(getDisplayLabel()); + sb.append(", dirPatterns[ "); + for (String dirPattern : getDirPatterns()) { + sb.append(dirPattern).append(", "); + } + sb.append("], filePattern: ").append( + filePattern == null ? "null" : filePattern); + sb.append("]"); + return sb.toString(); + } +} diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryFileDateHelper.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryFileDateHelper.java index 4534160878..6f87b7e73d 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryFileDateHelper.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryFileDateHelper.java @@ -40,6 +40,8 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 21, 2013 1965 bgonzale Initial creation + * Aug 03, 2013 2224 rferrel Changes for new configuration files. + * Aug 28, 2013 2299 rferrel Changes in IFileDateHelper. * * * @@ -56,13 +58,11 @@ public class CategoryFileDateHelper implements IFileDateHelper { private final Pattern categoryTopLevelDirPattern; - private final int yearIndex; + private final CategoryDataSet.TimeType timeType; - private final int monthIndex; + private final boolean isDirOnly; - private final int dayIndex; - - private final int hourIndex; + private final int[] timeIndices; /** * Initialization constructor. @@ -76,13 +76,13 @@ public class CategoryFileDateHelper implements IFileDateHelper { */ public CategoryDateInfo(Pattern datePattern, Pattern categoryTopLevelDirPattern, - int yearIndex, int monthIndex, int dayIndex, int hourIndex) { + CategoryDataSet.TimeType timeType, boolean isDirOnly, + int[] timeIndices) { this.datePattern = datePattern; this.categoryTopLevelDirPattern = categoryTopLevelDirPattern; - this.yearIndex = yearIndex; - this.monthIndex = monthIndex; - this.dayIndex = dayIndex; - this.hourIndex = hourIndex; + this.timeType = timeType; + this.isDirOnly = isDirOnly; + this.timeIndices = timeIndices; } } @@ -91,8 +91,6 @@ public class CategoryFileDateHelper implements IFileDateHelper { private final String rootDir; - private final boolean isDirOnly; - /** * Initialization constructor. * @@ -101,38 +99,37 @@ public class CategoryFileDateHelper implements IFileDateHelper { * categoryTopLevelDirPattern */ public CategoryFileDateHelper(CategoryConfig config, String rootDir) { - List categoryDirPatternList = config.getDirPatternList(); - this.dateInfoList = new ArrayList( - categoryDirPatternList.size()); - - String filePatternStr = config.getFilePattern(); this.rootDir = rootDir; - this.isDirOnly = (filePatternStr == null) - || ".*".equals(filePatternStr); + List categoryDataSetList = config.getDataSetList(); + int size = 0; + for (CategoryDataSet dataSet : categoryDataSetList) { + size += dataSet.getDirPatterns().size(); + } - for (String patternString : categoryDirPatternList) { - Pattern datePattern = null; - if (isDirOnly) { - datePattern = Pattern.compile(patternString); - } else { - datePattern = Pattern.compile(patternString + File.separator - + config.getFilePattern()); + this.dateInfoList = new ArrayList( + size); + + boolean isDirOnly; + CategoryDataSet.TimeType timeType; + for (CategoryDataSet dataSet : categoryDataSetList) { + isDirOnly = dataSet.isDirOnly(); + timeType = dataSet.getTimeType(); + + for (String patternString : dataSet.getDirPatterns()) { + Pattern datePattern = dataSet.getPattern(patternString); + int dirSeparatorIndex = patternString + .indexOf(File.separatorChar); + patternString = dirSeparatorIndex > patternString.length() + || dirSeparatorIndex < 0 ? patternString + : patternString.substring(0, dirSeparatorIndex); + Pattern categoryTopLevelDirPattern = Pattern + .compile(patternString); + int[] timeIndices = dataSet.getTimeIndices(); + + dateInfoList.add(new CategoryDateInfo(datePattern, + categoryTopLevelDirPattern, timeType, isDirOnly, + timeIndices)); } - int dirSeparatorIndex = patternString.indexOf(File.separatorChar); - patternString = dirSeparatorIndex > patternString.length() - || dirSeparatorIndex < 0 ? patternString : patternString - .substring(0, dirSeparatorIndex); - Pattern categoryTopLevelDirPattern = Pattern.compile(patternString); - String[] indexValues = config.getDateGroupIndices().split( - "\\s*,\\s*"); - int yearIndex = Integer.parseInt(indexValues[0]); - int monthIndex = Integer.parseInt(indexValues[1]); - int dayIndex = Integer.parseInt(indexValues[2]); - int hourIndex = Integer.parseInt(indexValues[3]); - - dateInfoList.add(new CategoryDateInfo(datePattern, - categoryTopLevelDirPattern, yearIndex, monthIndex, - dayIndex, hourIndex)); } } @@ -141,40 +138,43 @@ public class CategoryFileDateHelper implements IFileDateHelper { * * @see * com.raytheon.uf.common.archive.config.IFileDateHelper#getFileDate(java - * .lang.String) + * .io.File) */ @Override - public Calendar getFileDate(String filenamePath) { - String pathForPatternCheck = filenamePath.substring(rootDir.length()); - pathForPatternCheck = isDirOnly ? FilenameUtils - .getFullPathNoEndSeparator(pathForPatternCheck) - : pathForPatternCheck; + public Calendar getFileDate(File file) { + String filenamePath = file.getAbsolutePath(); + String pathForFilePatternCheck = filenamePath.substring(rootDir + .length()); + String pathForDirPatternCheck = FilenameUtils + .getFullPathNoEndSeparator(pathForFilePatternCheck); Calendar result = null; + Long timestamp = null; for (CategoryDateInfo dateInfo : dateInfoList) { - Matcher matcher = dateInfo.datePattern.matcher(pathForPatternCheck); + Matcher matcher = null; + if (dateInfo.isDirOnly) { + matcher = dateInfo.datePattern.matcher(pathForDirPatternCheck); + } else { + matcher = dateInfo.datePattern.matcher(pathForFilePatternCheck); + } if (matcher.matches()) { - int year = Integer.parseInt(matcher.group(dateInfo.yearIndex)); - // Adjust month value to Calendar's 0 - 11 - int month = Integer - .parseInt(matcher.group(dateInfo.monthIndex)) - 1; - int day = Integer.parseInt(matcher.group(dateInfo.dayIndex)); - int hour = Integer.parseInt(matcher.group(dateInfo.hourIndex)); - - result = TimeUtil.newGmtCalendar(); - result.set(year, month, day, hour, 0, 0); + timestamp = CategoryDataSet.getMatchTimeInMilliseconds( + dateInfo.timeType, dateInfo.timeIndices, matcher); break; } } - if (result == null) { - // no matching pattern, use file last modified date - File file = new File(filenamePath); - long lastModifiedMillis = file.lastModified(); - result = TimeUtil.newGmtCalendar(); - result.setTimeInMillis(lastModifiedMillis); + if (timestamp == null) { + // no matching pattern, use file last modified date + timestamp = file.lastModified(); } + + // TODO future speed improvement refactor IFileDateHelper to have a + // method that returns a long instead of Calendar. That will prevent + // converting Calendar to long then back to a Calendar. + result = TimeUtil.newGmtCalendar(); + result.setTimeInMillis(timestamp); return result; } diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/DisplayData.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/DisplayData.java index a1d7f5ee19..7f6d22cadc 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/DisplayData.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/DisplayData.java @@ -1,8 +1,11 @@ package com.raytheon.uf.common.archive.config; import java.io.File; +import java.util.ArrayList; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.raytheon.uf.common.util.SizeUtil; @@ -18,6 +21,9 @@ import com.raytheon.uf.common.util.SizeUtil; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 7, 2013 1966 rferrel Initial creation + * Aug 02, 2013 2224 rferrel Changes to include DataSet in configuration. + * Aug 06, 2013 2222 rferrel Changes to display all selected data. + * Aug 14, 2013 2220 rferrel Add priority comparator. * * * @@ -45,7 +51,34 @@ public class DisplayData implements Comparable { public static final Comparator LABEL_ORDER = new Comparator() { @Override public int compare(DisplayData o1, DisplayData o2) { - return o1.displayLabel.compareToIgnoreCase(o2.displayLabel); + int result = o1.getArchiveName().compareToIgnoreCase( + o2.getArchiveName()); + if (result == 0) { + result = o1.getCategoryName().compareToIgnoreCase( + o2.getCategoryName()); + } + if (result == 0) { + result = o1.displayLabel.compareToIgnoreCase(o2.displayLabel); + } + return result; + } + }; + + /** Comparator for priority ordering for priority queue. */ + public static final Comparator PRIORITY_ORDER = new Comparator() { + + @Override + public int compare(DisplayData o1, DisplayData o2) { + if (o1.visible != o2.visible) { + return o1.visible ? -1 : +1; + } else if (o1.visible) { + return LABEL_ORDER.compare(o1, o2); + } + + if (o1.selected != o2.selected) { + return o1.selected ? -1 : +1; + } + return LABEL_ORDER.compare(o1, o2); } }; @@ -61,21 +94,28 @@ public class DisplayData implements Comparable { /** The data's category configuration. */ protected final CategoryConfig categoryConfig; + protected final List dataSets = new ArrayList( + 1); + /** The display label for this data. */ protected final String displayLabel; /** - * List of directories for the display label matching the category's - * directory pattern and found under the archive's root directory. + * Mappings of a list of directories for the display label matching the data + * set's directory patterns and found under the archive's root directory. */ - protected final List dirs; + protected final Map> dirsMap = new HashMap>(); /** - * For use by GUI to indicate. Use to indicate selected for retention or for - * placing in a case. + * For use by GUI to indicate display label's row is selected. */ private boolean selected = false; + /** + * Indicates data is visible in the display. + */ + private boolean visible = false; + /** For use by GUI for indicating the size of the directories' contents. */ private long size = UNKNOWN_SIZE; @@ -84,15 +124,16 @@ public class DisplayData implements Comparable { * * @param archiveConfig * @param categoryConfig + * @param dataSet * @param displayLabel - * @param dirs */ public DisplayData(ArchiveConfig archiveConfig, - CategoryConfig categoryConfig, String displayLabel, List dirs) { + CategoryConfig categoryConfig, CategoryDataSet dataSet, + String displayLabel) { this.archiveConfig = archiveConfig; this.categoryConfig = categoryConfig; this.displayLabel = displayLabel; - this.dirs = dirs; + this.dataSets.add(dataSet); } /** @@ -113,6 +154,14 @@ public class DisplayData implements Comparable { this.selected = selected; } + public boolean isVisible() { + return visible; + } + + public void setVisible(boolean visible) { + this.visible = visible; + } + /** * * @return displayLabel. @@ -225,4 +274,30 @@ public class DisplayData implements Comparable { } return result; } + + public String getArchiveName() { + return archiveConfig.getName(); + } + + public String getCategoryName() { + return categoryConfig.getName(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder("DisplayData["); + sb.append("displayLabel: ").append(displayLabel); + sb.append(", isVisible: ").append(isVisible()); + sb.append(", isSlected: ").append(isSelected()); + sb.append(", size: ").append(size); + sb.append(", category.name: ").append(categoryConfig.getName()); + sb.append(", archive.name: ").append(archiveConfig.getName()) + .append("]"); + return sb.toString(); + } } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/FileDateFilter.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/FileDateFilter.java index 16dc9fd732..d349faf652 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/FileDateFilter.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/FileDateFilter.java @@ -40,6 +40,7 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 18, 2013 1965 bgonzale Initial creation + * Aug 28, 2013 2299 rferrel Reject hidden directories. * * * @@ -79,7 +80,9 @@ public class FileDateFilter implements IOFileFilter { this.end = end; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.apache.commons.io.filefilter.IOFileFilter#accept(java.io.File) */ @Override @@ -90,16 +93,16 @@ public class FileDateFilter implements IOFileFilter { return accept(new File(dirName), fileName); } - /* (non-Javadoc) - * @see org.apache.commons.io.filefilter.IOFileFilter#accept(java.io.File, java.lang.String) + /* + * (non-Javadoc) + * + * @see org.apache.commons.io.filefilter.IOFileFilter#accept(java.io.File, + * java.lang.String) */ @Override public boolean accept(File dir, String name) { - String dirPath = dir.getAbsolutePath(); - boolean endsWithSeparator = dirPath.endsWith(File.separator); - dirPath = endsWithSeparator ? dirPath : dirPath + File.separator; - String fileFullPath = dirPath + name; - Calendar fileDate = helper.getFileDate(fileFullPath); + File file = new File(dir, name); + Calendar fileDate = helper.getFileDate(file); boolean isAfterEqualsStart = start == null || fileDate.after(start) || fileDate.equals(start); boolean isBeforeEqualsEnd = end == null || fileDate.before(end) @@ -112,9 +115,8 @@ public class FileDateFilter implements IOFileFilter { */ private static final IFileDateHelper DEFAULT_FILE_DATE_HELPER = new IFileDateHelper() { @Override - public Calendar getFileDate(String filenamePath) { + public Calendar getFileDate(File file) { // use file last modified date - File file = new File(filenamePath); long lastModifiedMillis = file.lastModified(); Calendar result = TimeUtil.newGmtCalendar(); result.setTimeInMillis(lastModifiedMillis); diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/IFileDateHelper.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/IFileDateHelper.java index 16a4f24d0c..368e6fe6d4 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/IFileDateHelper.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/IFileDateHelper.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.common.archive.config; +import java.io.File; import java.util.Calendar; /** @@ -31,6 +32,7 @@ import java.util.Calendar; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 21, 2013 bgonzale Initial creation + * Aug 28, 2013 2299 rferrel Change getFileDate argument. * * * @@ -40,6 +42,12 @@ import java.util.Calendar; public interface IFileDateHelper { - public Calendar getFileDate(String filenamePath); + /** + * Get data associated with the file. + * + * @param file + * @return calendar + */ + public Calendar getFileDate(File file); } diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/SelectConfig.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/SelectConfig.java new file mode 100644 index 0000000000..babc5a51ae --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/SelectConfig.java @@ -0,0 +1,192 @@ +/** + * 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.common.archive.config; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.common.archive.config.select.ArchiveSelect; +import com.raytheon.uf.common.archive.config.select.CategorySelect; + +/** + * Select configuraton information for retention and case creation. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 19, 2013 2221       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +@XmlAccessorType(XmlAccessType.NONE) +@XmlRootElement(name = "selection") +public class SelectConfig { + /** + * Name of selection. + */ + @XmlElement(name = "name") + private String name; + + /** + * Hours to back off Start time from the End time. + */ + @XmlElement(name = "startRetentionHours") + private long starRetentionHours = 24L; + + /** + * List of archives + */ + @XmlElement(name = "archive") + private final List archiveList = new ArrayList(); + + /** + * Constructor. + */ + public SelectConfig() { + super(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getStarRetentionHours() { + return starRetentionHours; + } + + public void setStarRetentionHours(long startRetentionHours) { + this.starRetentionHours = startRetentionHours; + } + + public List getArchiveList() { + return archiveList; + } + + public void setArchiveList(List archiveList) { + this.archiveList.clear(); + this.archiveList.addAll(archiveList); + } + + public void add(ArchiveSelect archiveSelect) { + archiveList.add(archiveSelect); + } + + /** + * + * @return true when no selections + */ + public boolean isEmpty() { + return archiveList.isEmpty(); + } + + /** + * Get a list of selected display names for the archive and its category. + * + * @param archiveName + * @param categoryName + * @return displayLabelList may be an empty list. + */ + public List getSelectedList(String archiveName, String categoryName) { + ArchiveSelect archiveSelect = getArchive(archiveName); + if (archiveSelect == null || archiveSelect.isEmpty()) { + return new ArrayList(0); + } + CategorySelect categorySelect = getCategorySelect(categoryName, + archiveSelect); + if (categorySelect == null || categorySelect.isEmpty()) { + return new ArrayList(0); + } + + List selected = categorySelect.getSelectList(); + + return selected; + } + + /** + * Find archive with given name + * + * @param archiveName + * @return archive select or null if none found. message + */ + private ArchiveSelect getArchive(String archiveName) { + if (!archiveList.isEmpty()) { + for (ArchiveSelect archiveSelect : archiveList) { + if (archiveName.equals(archiveSelect.getName())) { + return archiveSelect; + } + } + } + return null; + } + + /** + * Find category for the given name under the desired archive. + * + * @param categoryName + * @param archiveSelect + * @return categorySelect or null if none found + */ + private CategorySelect getCategorySelect(String categoryName, + ArchiveSelect archiveSelect) { + if (!archiveSelect.isEmpty()) { + for (CategorySelect categorySelect : archiveSelect + .getCategorySelectList()) { + if (categoryName.equals(categorySelect.getName())) { + return categorySelect; + } + } + } + return null; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("selectData [name: ").append(getName()); + sb.append(", startRetentionHours: ").append(getStarRetentionHours()); + sb.append("["); + for (ArchiveSelect archiveConfig : getArchiveList()) { + sb.append(archiveConfig).append(", "); + } + sb.append("]]"); + return sb.toString(); + } +} diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/ArchiveSelect.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/ArchiveSelect.java new file mode 100644 index 0000000000..3d339147f5 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/ArchiveSelect.java @@ -0,0 +1,104 @@ +/** + * 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.common.archive.config.select; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Select configuration archive information. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 19, 2013 2221       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +@XmlAccessorType(XmlAccessType.NONE) +@XmlRootElement(name = "archive") +public class ArchiveSelect { + /** + * The archive name. + */ + @XmlElement(name = "name") + private String name; + + /** + * List of categories with selections. + */ + @XmlElement(name = "category") + private final List categorySelectList = new ArrayList(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getCategorySelectList() { + return categorySelectList; + } + + public void setCategorySelectList(List categorySelectList) { + this.categorySelectList.clear(); + this.categorySelectList.addAll(categorySelectList); + } + + public void add(CategorySelect categorySelect) { + categorySelectList.add(categorySelect); + } + + public boolean isEmpty() { + return categorySelectList.isEmpty(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Archive Select [name : ").append(getName()); + sb.append("["); + for (CategorySelect categorySelect : categorySelectList) { + sb.append(categorySelect).append(", "); + } + sb.append("]"); + return sb.toString(); + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/CategorySelect.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/CategorySelect.java new file mode 100644 index 0000000000..5d4d2c5ec0 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/CategorySelect.java @@ -0,0 +1,98 @@ +/** + * 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.common.archive.config.select; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Select configuration class that contains a list of selected display labels + * for a given category. It is assumed this is associated with a given archive. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 19, 2013 2221       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ +@XmlAccessorType(XmlAccessType.NONE) +@XmlRootElement(name = "archive") +public class CategorySelect { + /** + * The category name. + */ + @XmlElement(name = "name") + private String name; + + /** + * List of selected labels. + */ + @XmlElement(name = "selectedDisplayName") + private final List selectList = new ArrayList(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getSelectList() { + return selectList; + } + + public void setSelectList(List selectList) { + this.selectList.clear(); + this.selectList.addAll(selectList); + } + + public void add(String displayName) { + selectList.add(displayName); + } + + public boolean isEmpty() { + return selectList.isEmpty(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("CategorySelect [ name: ").append(getName()); + sb.append("[ "); + for (String select : getSelectList()) { + sb.append("\"").append(select).append("\", "); + } + sb.append("]"); + return sb.toString(); + } +} diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/request/ArchiveAdminAuthRequest.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/request/ArchiveAdminAuthRequest.java new file mode 100644 index 0000000000..375c5e8d48 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/request/ArchiveAdminAuthRequest.java @@ -0,0 +1,107 @@ +/** + * 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.common.archive.request; + +import com.raytheon.uf.common.auth.req.AbstractPrivilegedRequest; +import com.raytheon.uf.common.serialization.ISerializableObject; +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * Class with the serialized data for the Archive Admin. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Oct 02, 2013 2326       rferrel    Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ +@DynamicSerialize +public class ArchiveAdminAuthRequest extends AbstractPrivilegedRequest + implements ISerializableObject { + + @DynamicSerializeElement + private String roleId = null; + + @DynamicSerializeElement + private boolean authorized = false; + + @DynamicSerializeElement + private String notAuthorizedMessage = "Not Authorized"; + + /** + * Constructor + */ + public ArchiveAdminAuthRequest() { + + } + + /** + * @param roleId + * the roleId to set + */ + public void setRoleId(String roleId) { + this.roleId = roleId; + } + + /** + * @return the roleId + */ + public String getRoleId() { + return roleId; + } + + /** + * @return the authorized + */ + public boolean isAuthorized() { + return authorized; + } + + /** + * @param authorized + * the authorized to set + */ + public void setAuthorized(boolean authorized) { + this.authorized = authorized; + } + + /** + * @return the notAuthorizedMessage + */ + public String getNotAuthorizedMessage() { + return notAuthorizedMessage; + } + + /** + * @param notAuthorizedMessage + * the failureMessage to set + */ + public void setNotAuthorizedMessage(String notAuthorizedMessage) { + this.notAuthorizedMessage = notAuthorizedMessage; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.acars/src/com/raytheon/uf/common/dataplugin/acars/ACARSRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.acars/src/com/raytheon/uf/common/dataplugin/acars/ACARSRecord.java index 83e2a76d8e..3934a16ec6 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.acars/src/com/raytheon/uf/common/dataplugin/acars/ACARSRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.acars/src/com/raytheon/uf/common/dataplugin/acars/ACARSRecord.java @@ -65,15 +65,17 @@ import com.vividsolutions.jts.geom.Geometry; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 21, 2009 1939 jkorman Initial creation - * Apr 09, 2009 952 jsanchez Updated getValue method. - * Added a getMessageData method. - * Apr 21, 2009 2245 jsanchez Returned temperature unit to kelvin. - * May 21, 2009 2338 jsanchez Updated the getMessageData. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Jan 21, 2009 1939 jkorman Initial creation + * Apr 09, 2009 952 jsanchez Updated getValue method. Added a + * getMessageData method. + * Apr 21, 2009 2245 jsanchez Returned temperature unit to kelvin. + * May 21, 2009 2338 jsanchez Updated the getMessageData. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -87,12 +89,8 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "acars", - indexes = { - @Index(name = "acars_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "acars", indexes = { @Index(name = "acars_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -698,9 +696,9 @@ public class ACARSRecord extends PluginDataObject implements ISpatialEnabled, a = new Amount(getLatitude(), LOCATION_UNIT); } else if (STA_LON.equals(pName)) { a = new Amount(getLongitude(), LOCATION_UNIT); - } else if (UA_FLTLVL.equals(pName) && getFlightLevel() != null) { + } else if (UA_FLTLVL.equals(pName) && (getFlightLevel() != null)) { a = new Amount(getFlightLevel().intValue(), FLIGHT_LEVEL_UNIT); - } else if (SFC_DWPT.equals(pName) && getDwpt() != null) { + } else if (SFC_DWPT.equals(pName) && (getDwpt() != null)) { a = new Amount(getDwpt(), TEMPERATURE_UNIT); } @@ -724,47 +722,53 @@ public class ACARSRecord extends PluginDataObject implements ISpatialEnabled, return String.format(TEXT_FMT, getTailNumber(), getTimeObs()); } - - - - - - - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + result = (prime * result) + ((tailNumber == null) ? 0 : tailNumber.hashCode()); - result = prime * result + ((timeObs == null) ? 0 : timeObs.hashCode()); + result = (prime * result) + + ((timeObs == null) ? 0 : timeObs.hashCode()); return result; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } ACARSRecord other = (ACARSRecord) obj; if (tailNumber == null) { - if (other.tailNumber != null) + if (other.tailNumber != null) { return false; - } else if (!tailNumber.equals(other.tailNumber)) + } + } else if (!tailNumber.equals(other.tailNumber)) { return false; + } if (timeObs == null) { - if (other.timeObs != null) + if (other.timeObs != null) { return false; - } else if (!timeObs.equals(other.timeObs)) + } + } else if (!timeObs.equals(other.timeObs)) { return false; + } return true; } @@ -782,7 +786,7 @@ public class ACARSRecord extends PluginDataObject implements ISpatialEnabled, if (this == other) { result = EQUAL; } else { - if(getTailNumber().equals(getTailNumber())) { + if (getTailNumber().equals(getTailNumber())) { result = timeObs.compareTo(other.timeObs); } else { result = getTailNumber().compareTo(other.getTailNumber()); @@ -790,11 +794,16 @@ public class ACARSRecord extends PluginDataObject implements ISpatialEnabled, } return result; } - + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "acars"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.acarssounding/src/com/raytheon/uf/common/dataplugin/acarssounding/ACARSSoundingRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.acarssounding/src/com/raytheon/uf/common/dataplugin/acarssounding/ACARSSoundingRecord.java index 7529a40c9c..54f4ed92a9 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.acarssounding/src/com/raytheon/uf/common/dataplugin/acarssounding/ACARSSoundingRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.acarssounding/src/com/raytheon/uf/common/dataplugin/acarssounding/ACARSSoundingRecord.java @@ -64,11 +64,13 @@ import com.vividsolutions.jts.geom.Geometry; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20090403 1939 jkorman Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Apr 03, 2009 1939 jkorman Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -82,12 +84,8 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "acarssounding", - indexes = { - @Index(name = "acarssounding_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "acarssounding", indexes = { @Index(name = "acarssounding_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -122,12 +120,12 @@ public class ACARSSoundingRecord extends PluginDataObject implements @XmlElement private String tailNumber; - // Flight phase (A[scending] D[escending]) + // Flight phase (A[scending] D[escending]) @Column(length = 1) @DynamicSerializeElement @XmlElement private String phase = null; - + // oldest observation time in this sounding @Column @DynamicSerializeElement @@ -139,7 +137,7 @@ public class ACARSSoundingRecord extends PluginDataObject implements @DynamicSerializeElement @XmlElement private Long newestTime = Long.MIN_VALUE; - + // The level data for this observation. @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = FetchType.EAGER) @XmlElement @@ -261,7 +259,7 @@ public class ACARSSoundingRecord extends PluginDataObject implements public void setTailNumber(String tailNumber) { this.tailNumber = tailNumber; } - + /** * @return the phase */ @@ -270,7 +268,8 @@ public class ACARSSoundingRecord extends PluginDataObject implements } /** - * @param phase the phase to set + * @param phase + * the phase to set */ public void setPhase(String phase) { this.phase = phase; @@ -284,7 +283,8 @@ public class ACARSSoundingRecord extends PluginDataObject implements } /** - * @param oldestTime the oldestTime to set + * @param oldestTime + * the oldestTime to set */ public void setOldestTime(Long oldestTime) { this.oldestTime = oldestTime; @@ -298,7 +298,8 @@ public class ACARSSoundingRecord extends PluginDataObject implements } /** - * @param newestTime the newestTime to set + * @param newestTime + * the newestTime to set */ public void setNewestTime(Long newestTime) { this.newestTime = newestTime; @@ -328,17 +329,17 @@ public class ACARSSoundingRecord extends PluginDataObject implements * @param cloud */ public void addLevel(ACARSSoundingLayer level) { - if(level != null) { + if (level != null) { level.setParent(this); if (levels == null) { levels = new HashSet(); } levels.add(level); long cTime = level.getTimeObs().getTimeInMillis(); - if(cTime < oldestTime) { + if (cTime < oldestTime) { oldestTime = cTime; } - if(cTime > newestTime) { + if (cTime > newestTime) { newestTime = cTime; } } @@ -386,4 +387,9 @@ public class ACARSSoundingRecord extends PluginDataObject implements public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "acarssounding"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.airep/src/com/raytheon/uf/common/dataplugin/airep/AirepRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.airep/src/com/raytheon/uf/common/dataplugin/airep/AirepRecord.java index d03ca0e507..d1803bda21 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.airep/src/com/raytheon/uf/common/dataplugin/airep/AirepRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.airep/src/com/raytheon/uf/common/dataplugin/airep/AirepRecord.java @@ -69,16 +69,19 @@ import com.vividsolutions.jts.geom.Geometry; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080103 384 jkorman Initial Coding. - * 20080107 720 jkorman remove default assignments from attributes. - * 20120405 435 dgilling Prevent NullPointerExceptions in + * Jan 03, 2008 384 jkorman Initial Coding. + * Jan 07, 2008 720 jkorman remove default assignments from + * attributes. + * Apr 05, 2012 435 dgilling Prevent NullPointerExceptions in * buildMessageData(). - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 20120911 1011 jkorman Added ability to report turbulence from decoded - * TB group. - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Sep 11, 2012 1011 jkorman Added ability to report turbulence from + * decoded TB group. + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -92,12 +95,8 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "airep", - indexes = { - @Index(name = "airep_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "airep", indexes = { @Index(name = "airep_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -330,7 +329,7 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled, */ public String getReportData() { String s = null; - if (messageData != null && messageData instanceof String) { + if ((messageData != null) && (messageData instanceof String)) { s = (String) messageData; } else { s = buildMessageData(); @@ -593,7 +592,7 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled, a = new Amount(this.getLatitude(), LOCATION_UNIT); } else if (STA_LON.equals(pName)) { a = new Amount(this.getLongitude(), LOCATION_UNIT); - } else if (UA_FLTLVL.equals(pName) && getFlightLevel() != null) { + } else if (UA_FLTLVL.equals(pName) && (getFlightLevel() != null)) { a = new Amount(this.getFlightLevel().intValue(), ALTITUDE_UNIT); } @@ -627,7 +626,7 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled, String[] retValue = null; String value = null; - if ("FLT_HZD".matches(paramName) && flightHazard != null) { + if ("FLT_HZD".matches(paramName) && (flightHazard != null)) { if (flightHazard != null) { retValue = new String[] { flightHazard.toString() }; } @@ -720,7 +719,7 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled, boolean validLocation = (location != null); StringBuilder messageData = new StringBuilder("ARP "); - if (validLocation && getStationId() != null) { + if (validLocation && (getStationId() != null)) { messageData.append(getStationId()); } messageData.append(' '); @@ -739,7 +738,7 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled, } messageData.append(" F"); - if (validLocation && getFlightLevel() != null) { + if (validLocation && (getFlightLevel() != null)) { int flightLevel = (int) ftToHft.convert(getFlightLevel()); messageData.append(flightLevel); } @@ -761,7 +760,7 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled, messageData.append(windSpeed.intValue()); messageData.append("KT"); } - if(flightConditions != null) { + if (flightConditions != null) { int turb = flightConditions >> 4; if ((turb & 0x80) > 0) { messageData.append(" TB"); @@ -831,7 +830,7 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled, public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + result = (prime * result) + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); return result; } @@ -871,4 +870,9 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled, public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "airep"; + } } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.binlightning/src/com/raytheon/uf/common/dataplugin/binlightning/BinLightningRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.binlightning/src/com/raytheon/uf/common/dataplugin/binlightning/BinLightningRecord.java index 3de0e749e4..e6d780cf60 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.binlightning/src/com/raytheon/uf/common/dataplugin/binlightning/BinLightningRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.binlightning/src/com/raytheon/uf/common/dataplugin/binlightning/BinLightningRecord.java @@ -62,24 +62,27 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * * Date Ticket# Engineer Description * ---------- ---------- ----------- -------------------------- - * 20070810 379 jkorman Initial Coding from prototype. - * 20070817 379 jkorman Fixed convert(). Was writing day into + * Aug 10, 2007 379 jkorman Initial Coding from prototype. + * Aug 17, 2007 379 jkorman Fixed convert(). Was writing day into * hours field of new calendar. - * 20070920 379 jkorman Modified getPersistenceTime. - * 20070921 379 jkorman Modified get/set start/stop times due + * Sep 20, 2007 379 jkorman Modified getPersistenceTime. + * Sep 21, 2007 379 jkorman Modified get/set start/stop times due * to JiBX problems. - * 20070924 379 jkorman Removed Group, added insert_time and - * (set/get)ers to make DataURI work. - * 20071129 472 jkorman Added IDecoderGettable interface. - * 20080107 720 jkorman remove default assignments from attributes. - * 20080708 1174 jkorman Added persistenceTime handling. - * 20090206 1990 bphillip Removed populateDataStore method - * 20130227 DCS 152 jgerth/elau Support for WWLLN and multiple sources - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 20130408 1293 bkowal Removed references to hdffileid. - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Sep 24, 2007 379 jkorman Removed Group, added insert_time and + * (set/get)ers to make DataURI work. + * Nov 29, 2007 472 jkorman Added IDecoderGettable interface. + * Jan 07, 2008 720 jkorman remove default assignments from + * attributes. + * Jul 08, 2008 1174 jkorman Added persistenceTime handling. + * Feb 06, 2009 1990 bphillip Removed populateDataStore method + * Feb 27, 2013 DCS 152 jgerth/elau Support for WWLLN and multiple sources + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -93,17 +96,13 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "binlightning", - indexes = { - @Index(name = "binlightning_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "binlightning", indexes = { @Index(name = "binlightning_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @DynamicSerialize @XmlAccessorType(XmlAccessType.NONE) -public class BinLightningRecord extends - PersistablePluginDataObject implements IPersistable { +public class BinLightningRecord extends PersistablePluginDataObject implements + IPersistable { /** Serializable id * */ private static final long serialVersionUID = 1L; @@ -159,7 +158,7 @@ public class BinLightningRecord extends @DynamicSerializeElement @XmlAttribute private Calendar stopTime; - + // JJG - source of lightning data @Column(length = 5) @DataURI(position = 3) @@ -221,8 +220,8 @@ public class BinLightningRecord extends */ @SuppressWarnings("unused") private void updatePersistenceTime() { - if (startTimeMillis != Long.MAX_VALUE - && stopTimeMillis != Long.MIN_VALUE) { + if ((startTimeMillis != Long.MAX_VALUE) + && (stopTimeMillis != Long.MIN_VALUE)) { persistTime = (startTimeMillis + stopTimeMillis) / 2; setPersistenceTime(TimeTools.newCalendar(persistTime).getTime()); } else { @@ -238,24 +237,25 @@ public class BinLightningRecord extends * A strike report to add. */ public void addStrike(LightningStrikePoint strike) { - // jjg add - if (lightSource == null) { - if (strike.getLightSource() == null) { - lightSource = (String) "NLDN"; - } else if (strike.getLightSource().isEmpty()) { - lightSource = (String) "UNKN"; - } else { - lightSource = (String) strike.getLightSource(); - } - } else { - if (strike.getLightSource() == null) { - lightSource = (String) "NLDN"; - } else if (!lightSource.equals(strike.getLightSource())) - lightSource = (String) "UNKN"; - } - // end + // jjg add + if (lightSource == null) { + if (strike.getLightSource() == null) { + lightSource = "NLDN"; + } else if (strike.getLightSource().isEmpty()) { + lightSource = "UNKN"; + } else { + lightSource = strike.getLightSource(); + } + } else { + if (strike.getLightSource() == null) { + lightSource = "NLDN"; + } else if (!lightSource.equals(strike.getLightSource())) { + lightSource = "UNKN"; + } + } + // end - if (insertIndex < obsTimes.length) { + if (insertIndex < obsTimes.length) { long t1 = startTimeMillis; Calendar c = TimeTools.getBaseCalendar(strike.getYear(), @@ -445,7 +445,7 @@ public class BinLightningRecord extends public void setLightSource(String lightSource) { this.lightSource = lightSource; } - + /** * Get the IDecoderGettable reference for this record. * @@ -506,4 +506,9 @@ public class BinLightningRecord extends public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "binlightning"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrascat/src/com/raytheon/uf/common/dataplugin/bufrascat/AScatObs.java b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrascat/src/com/raytheon/uf/common/dataplugin/bufrascat/AScatObs.java index fe1843e13e..2e1c4f8a27 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrascat/src/com/raytheon/uf/common/dataplugin/bufrascat/AScatObs.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrascat/src/com/raytheon/uf/common/dataplugin/bufrascat/AScatObs.java @@ -60,6 +60,7 @@ import com.vividsolutions.jts.geom.Geometry; * PluginDataObject. * May 17, 2013 1869 bsteffen Remove DataURI column from sat plot * types. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -74,283 +75,283 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "bufrascat", - indexes = { - @Index(name = "bufrascat_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "bufrascat", indexes = { @Index(name = "bufrascat_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class AScatObs extends PersistablePluginDataObject implements ISpatialEnabled, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - @DataURI(position = 1) - @DynamicSerializeElement - private Integer satId; + @DataURI(position = 1) + @DynamicSerializeElement + private Integer satId; - @Embedded - @DataURI(position = 2, embedded = true) - @DynamicSerializeElement - private SurfaceObsLocation location; + @Embedded + @DataURI(position = 2, embedded = true) + @DynamicSerializeElement + private SurfaceObsLocation location; - // Text of the WMO header - @Column(length = 32) - @DynamicSerializeElement - private String wmoHeader; + // Text of the WMO header + @Column(length = 32) + @DynamicSerializeElement + private String wmoHeader; - @DynamicSerializeElement - @Transient - private Integer orbitNumber; + @DynamicSerializeElement + @Transient + private Integer orbitNumber; - // The observation time. - @DynamicSerializeElement - @Transient - private Calendar validTime; + // The observation time. + @DynamicSerializeElement + @Transient + private Calendar validTime; - @DynamicSerializeElement - @Transient - private Double windDir; + @DynamicSerializeElement + @Transient + private Double windDir; - @DataURI(position = 3) - @DynamicSerializeElement - private Float windSpd; + @DataURI(position = 3) + @DynamicSerializeElement + private Float windSpd; - @DynamicSerializeElement - @Transient - private Double probRain; + @DynamicSerializeElement + @Transient + private Double probRain; - @DynamicSerializeElement - @Transient - private Integer rainIndex; + @DynamicSerializeElement + @Transient + private Integer rainIndex; - /** - * Empty constructor. - */ - public AScatObs() { - } + /** + * Empty constructor. + */ + public AScatObs() { + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public AScatObs(String uri) { - super(uri); - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public AScatObs(String uri) { + super(uri); + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } - /** - * Was this location defined from the station catalog? False if not. - * - * @return Was this location defined from the station catalog? - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } + /** + * Was this location defined from the station catalog? False if not. + * + * @return Was this location defined from the station catalog? + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } - /** - * @return the location - */ - public SurfaceObsLocation getLocation() { - return location; - } + /** + * @return the location + */ + public SurfaceObsLocation getLocation() { + return location; + } - /** - * @param location - * the location to set - */ - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + /** + * @param location + * the location to set + */ + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - /** - * @return the satId - */ - public Integer getSatId() { - return satId; - } + /** + * @return the satId + */ + public Integer getSatId() { + return satId; + } - /** - * @param satId - * the satId to set - */ - public void setSatId(Integer satId) { - this.satId = satId; - } + /** + * @param satId + * the satId to set + */ + public void setSatId(Integer satId) { + this.satId = satId; + } - /** - * @return the orbitNumber - */ - public Integer getOrbitNumber() { - return orbitNumber; - } + /** + * @return the orbitNumber + */ + public Integer getOrbitNumber() { + return orbitNumber; + } - /** - * @param orbitNumber - * the orbitNumber to set - */ - public void setOrbitNumber(Integer orbitNumber) { - this.orbitNumber = orbitNumber; - } + /** + * @param orbitNumber + * the orbitNumber to set + */ + public void setOrbitNumber(Integer orbitNumber) { + this.orbitNumber = orbitNumber; + } - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * @return the windDir - */ - public Double getWindDir() { - return windDir; - } + /** + * @return the windDir + */ + public Double getWindDir() { + return windDir; + } - /** - * @param windDir - * the windDir to set - */ - public void setWindDir(Double windDir) { - this.windDir = windDir; - } + /** + * @param windDir + * the windDir to set + */ + public void setWindDir(Double windDir) { + this.windDir = windDir; + } - /** - * @return the windSpd - */ - public Float getWindSpd() { - return windSpd; - } + /** + * @return the windSpd + */ + public Float getWindSpd() { + return windSpd; + } - /** - * @param windSpd - * the windSpd to set - */ - public void setWindSpd(Float windSpd) { - this.windSpd = windSpd; - } + /** + * @param windSpd + * the windSpd to set + */ + public void setWindSpd(Float windSpd) { + this.windSpd = windSpd; + } - /** - * @return the probRain - */ - public Double getProbRain() { - return probRain; - } + /** + * @return the probRain + */ + public Double getProbRain() { + return probRain; + } - /** - * @param probRain - * the probRain to set - */ - public void setProbRain(Double probRain) { - this.probRain = probRain; - } + /** + * @param probRain + * the probRain to set + */ + public void setProbRain(Double probRain) { + this.probRain = probRain; + } - /** - * @return the rainIndex - */ - public Integer getRainIndex() { - return rainIndex; - } + /** + * @return the rainIndex + */ + public Integer getRainIndex() { + return rainIndex; + } - /** - * @param rainIndex - * the rainIndex to set - */ - public void setRainIndex(Integer rainIndex) { - this.rainIndex = rainIndex; - } + /** + * @param rainIndex + * the rainIndex to set + */ + public void setRainIndex(Integer rainIndex) { + this.rainIndex = rainIndex; + } - /** - * Get the observation time for this data. - * - * @return The data observation time. - */ - public Calendar getValidTime() { - return validTime; - } + /** + * Get the observation time for this data. + * + * @return The data observation time. + */ + public Calendar getValidTime() { + return validTime; + } - /** - * Set the observation time for this data. - * - * @param timeObs - * The data observation time. - */ - public void setValidTime(Calendar time) { - validTime = time; - } + /** + * Set the observation time for this data. + * + * @param timeObs + * The data observation time. + */ + public void setValidTime(Calendar time) { + validTime = time; + } - @Override - public ISpatialObject getSpatialObject() { - return location; - } + @Override + public ISpatialObject getSpatialObject() { + return location; + } - /** + /** * */ - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - /** + /** * */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + @Override + public String getPluginName() { + return "bufrascat"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrhdw/src/com/raytheon/uf/common/dataplugin/bufrhdw/BufrHDWObs.java b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrhdw/src/com/raytheon/uf/common/dataplugin/bufrhdw/BufrHDWObs.java index 805bfd631b..ee2fec58b5 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrhdw/src/com/raytheon/uf/common/dataplugin/bufrhdw/BufrHDWObs.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrhdw/src/com/raytheon/uf/common/dataplugin/bufrhdw/BufrHDWObs.java @@ -59,6 +59,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * PluginDataObject. * May 17, 2013 1869 bsteffen Remove DataURI column from sat plot * types. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -73,557 +74,557 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "bufrhdw", - indexes = { - @Index(name = "bufrhdw_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "bufrhdw", indexes = { @Index(name = "bufrhdw_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class BufrHDWObs extends PersistablePluginDataObject implements ISpatialEnabled, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - // The observation time. - @DataURI(position = 1) - @DynamicSerializeElement - private String satType; - - @DataURI(position = 2) - @DynamicSerializeElement - private Double pressure; - - @Embedded - @DataURI(position = 3, embedded = true) - @DynamicSerializeElement - private SurfaceObsLocation location; - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - // Text of the WMO header - @Column(length = 32) - @DynamicSerializeElement - private String wmoHeader; - - // The observation time. - @Column - @DynamicSerializeElement - private Calendar validTime; - - @DynamicSerializeElement - @Transient - private Double windDir; - - @DynamicSerializeElement - @Transient - private Double windSpd; - - @DynamicSerializeElement - @Transient - private Double satelliteID; - - @DynamicSerializeElement - @Transient - private Double originatingID; - - @DynamicSerializeElement - @Transient - private Double satelliteClass; - - @DynamicSerializeElement - @Transient - private Double sgmtSzX; - - @DynamicSerializeElement - @Transient - private Double sgmtSzY; - - @DynamicSerializeElement - @Transient - private Integer satelliteInstr; - - @DynamicSerializeElement - @Transient - private Integer satelliteWindMethod; - - @DynamicSerializeElement - @Transient - private Double satelliteFreq; - - @DynamicSerializeElement - @Transient - private Double satelliteBandWidth; - - @DynamicSerializeElement - @Transient - private Double coldestTemp; - - @DynamicSerializeElement - @Transient - private Integer heightMethod; - - @DynamicSerializeElement - @Transient - private Integer tracerCorrelation; - - @DynamicSerializeElement - @Transient - private Integer landSea; - - @DynamicSerializeElement - @Transient - private Double satelliteZenith; - - @DynamicSerializeElement - @Transient - private Integer firstGuess; - - @DynamicSerializeElement - @Transient - private Integer timeSignificance; - - /** - * Empty constructor. - */ - public BufrHDWObs() { - } - - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public BufrHDWObs(String uri) { - super(uri); - } - - /** - * Get the observation time for this data. - * - * @return The data observation time. - */ - public Calendar getValidTime() { - return validTime; - } - - /** - * Set the observation time for this data. - * - * @param timeObs - * The data observation time. - */ - public void setValidTime(Calendar time) { - validTime = time; - } - - /** - * @return the satType - */ - public String getSatType() { - return satType; - } - - /** - * @param satType - * the satType to set - */ - public void setSatType(String type) { - satType = type; - } - - /** - * @param satType - * the satType to set - */ - public void setSatType(BUFRHDWSatType type) { - satType = type.toString(); - } - - /** - * @return the location - */ - public SurfaceObsLocation getLocation() { - return location; - } - - /** - * @param location - * the location to set - */ - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } - - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } - - /** - * @return the windDir - */ - public Double getWindDir() { - return windDir; - } - - /** - * @param windDir - * the windDir to set - */ - public void setWindDir(Double direction) { - windDir = direction; - } - - /** - * @return the windSpd - */ - public Double getWindSpd() { - return windSpd; - } - - /** - * @param windSpd - * the windSpd to set - */ - public void setWindSpd(Double speed) { - windSpd = speed; - } - - /** - * @return the pressure - */ - public Double getPressure() { - return pressure; - } - - /** - * @param pressure - * the pressure to set - */ - public void setPressure(Double pressure) { - this.pressure = pressure; - } - - /** - * @return the satelliteID - */ - public Double getSatelliteID() { - return satelliteID; - } - - /** - * @param satelliteID - * the satelliteID to set - */ - public void setSatelliteID(Double satelliteID) { - this.satelliteID = satelliteID; - } - - /** - * @return the originatingID - */ - public Double getOriginatingID() { - return originatingID; - } - - /** - * @param originatingID - * the originatingID to set - */ - public void setOriginatingID(Double originatingID) { - this.originatingID = originatingID; - } - - /** - * @return the satelliteClass - */ - public Double getSatelliteClass() { - return satelliteClass; - } - - /** - * @param satelliteClass - * the satelliteClass to set - */ - public void setSatelliteClass(Double satelliteClass) { - this.satelliteClass = satelliteClass; - } - - /** - * @return the sgmtSzX - */ - public Double getSgmtSzX() { - return sgmtSzX; - } - - /** - * @param sgmtSzX - * the sgmtSzX to set - */ - public void setSgmtSzX(Double sgmtSzX) { - this.sgmtSzX = sgmtSzX; - } - - /** - * @return the sgmtSzY - */ - public Double getSgmtSzY() { - return sgmtSzY; - } - - /** - * @param sgmtSzY - * the sgmtSzY to set - */ - public void setSgmtSzY(Double sgmtSzY) { - this.sgmtSzY = sgmtSzY; - } - - /** - * @return the satelliteInstr - */ - public Integer getSatelliteInstr() { - return satelliteInstr; - } - - /** - * @param satelliteInstr - * the satelliteInstr to set - */ - public void setSatelliteInstr(Integer satelliteInstr) { - this.satelliteInstr = satelliteInstr; - } - - /** - * @return the satelliteWindMethod - */ - public Integer getSatelliteWindMethod() { - return satelliteWindMethod; - } - - /** - * @param satelliteWindMethod - * the satelliteWindMethod to set - */ - public void setSatelliteWindMethod(Integer satelliteWindMethod) { - this.satelliteWindMethod = satelliteWindMethod; - } - - /** - * @return the satelliteFreq - */ - public Double getSatelliteFreq() { - return satelliteFreq; - } - - /** - * @param satelliteFreq - * the satelliteFreq to set - */ - public void setSatelliteFreq(Double satelliteFreq) { - this.satelliteFreq = satelliteFreq; - } - - /** - * @return the satelliteBandWidth - */ - public Double getSatelliteBandWidth() { - return satelliteBandWidth; - } - - /** - * @param satelliteBandWidth - * the satelliteBandWidth to set - */ - public void setSatelliteBandWidth(Double satelliteBandWidth) { - this.satelliteBandWidth = satelliteBandWidth; - } - - /** - * @return the coldestTemp - */ - public Double getColdestTemp() { - return coldestTemp; - } - - /** - * @param coldestTemp - * the coldestTemp to set - */ - public void setColdestTemp(Double coldestTemp) { - this.coldestTemp = coldestTemp; - } - - /** - * @return the heightMethod - */ - public Integer getHeightMethod() { - return heightMethod; - } - - /** - * @param heightMethod - * the heightMethod to set - */ - public void setHeightMethod(Integer heightMethod) { - this.heightMethod = heightMethod; - } - - /** - * @return the tracerCorrelation - */ - public Integer getTracerCorrelation() { - return tracerCorrelation; - } - - /** - * @param tracerCorrelation - * the tracerCorrelation to set - */ - public void setTracerCorrelation(Integer tracerCorrelation) { - this.tracerCorrelation = tracerCorrelation; - } - - /** - * @return the landSea - */ - public Integer getLandSea() { - return landSea; - } - - /** - * @param landSea - * the landSea to set - */ - public void setLandSea(Integer landSea) { - this.landSea = landSea; - } - - /** - * @return the satelliteZenith - */ - public Double getSatelliteZenith() { - return satelliteZenith; - } - - /** - * @param satelliteZenith - * the satelliteZenith to set - */ - public void setSatelliteZenith(Double satelliteZenith) { - this.satelliteZenith = satelliteZenith; - } - - /** - * @return the firstGuess - */ - public Integer getFirstGuess() { - return firstGuess; - } - - /** - * @param firstGuess - * the firstGuess to set - */ - public void setFirstGuess(Integer firstGuess) { - this.firstGuess = firstGuess; - } - - /** - * @return the timeSignificance - */ - public Integer getTimeSignificance() { - return timeSignificance; - } - - /** - * @param timeSignificance - * the timeSignificance to set - */ - public void setTimeSignificance(Integer timeSignificance) { - this.timeSignificance = timeSignificance; - } - - @Override - public ISpatialObject getSpatialObject() { - return null; - } - - /** + // The observation time. + @DataURI(position = 1) + @DynamicSerializeElement + private String satType; + + @DataURI(position = 2) + @DynamicSerializeElement + private Double pressure; + + @Embedded + @DataURI(position = 3, embedded = true) + @DynamicSerializeElement + private SurfaceObsLocation location; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + // Text of the WMO header + @Column(length = 32) + @DynamicSerializeElement + private String wmoHeader; + + // The observation time. + @Column + @DynamicSerializeElement + private Calendar validTime; + + @DynamicSerializeElement + @Transient + private Double windDir; + + @DynamicSerializeElement + @Transient + private Double windSpd; + + @DynamicSerializeElement + @Transient + private Double satelliteID; + + @DynamicSerializeElement + @Transient + private Double originatingID; + + @DynamicSerializeElement + @Transient + private Double satelliteClass; + + @DynamicSerializeElement + @Transient + private Double sgmtSzX; + + @DynamicSerializeElement + @Transient + private Double sgmtSzY; + + @DynamicSerializeElement + @Transient + private Integer satelliteInstr; + + @DynamicSerializeElement + @Transient + private Integer satelliteWindMethod; + + @DynamicSerializeElement + @Transient + private Double satelliteFreq; + + @DynamicSerializeElement + @Transient + private Double satelliteBandWidth; + + @DynamicSerializeElement + @Transient + private Double coldestTemp; + + @DynamicSerializeElement + @Transient + private Integer heightMethod; + + @DynamicSerializeElement + @Transient + private Integer tracerCorrelation; + + @DynamicSerializeElement + @Transient + private Integer landSea; + + @DynamicSerializeElement + @Transient + private Double satelliteZenith; + + @DynamicSerializeElement + @Transient + private Integer firstGuess; + + @DynamicSerializeElement + @Transient + private Integer timeSignificance; + + /** + * Empty constructor. + */ + public BufrHDWObs() { + } + + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public BufrHDWObs(String uri) { + super(uri); + } + + /** + * Get the observation time for this data. + * + * @return The data observation time. + */ + public Calendar getValidTime() { + return validTime; + } + + /** + * Set the observation time for this data. + * + * @param timeObs + * The data observation time. + */ + public void setValidTime(Calendar time) { + validTime = time; + } + + /** + * @return the satType + */ + public String getSatType() { + return satType; + } + + /** + * @param satType + * the satType to set + */ + public void setSatType(String type) { + satType = type; + } + + /** + * @param satType + * the satType to set + */ + public void setSatType(BUFRHDWSatType type) { + satType = type.toString(); + } + + /** + * @return the location + */ + public SurfaceObsLocation getLocation() { + return location; + } + + /** + * @param location + * the location to set + */ + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } + + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } + + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } + + /** + * @return the windDir + */ + public Double getWindDir() { + return windDir; + } + + /** + * @param windDir + * the windDir to set + */ + public void setWindDir(Double direction) { + windDir = direction; + } + + /** + * @return the windSpd + */ + public Double getWindSpd() { + return windSpd; + } + + /** + * @param windSpd + * the windSpd to set + */ + public void setWindSpd(Double speed) { + windSpd = speed; + } + + /** + * @return the pressure + */ + public Double getPressure() { + return pressure; + } + + /** + * @param pressure + * the pressure to set + */ + public void setPressure(Double pressure) { + this.pressure = pressure; + } + + /** + * @return the satelliteID + */ + public Double getSatelliteID() { + return satelliteID; + } + + /** + * @param satelliteID + * the satelliteID to set + */ + public void setSatelliteID(Double satelliteID) { + this.satelliteID = satelliteID; + } + + /** + * @return the originatingID + */ + public Double getOriginatingID() { + return originatingID; + } + + /** + * @param originatingID + * the originatingID to set + */ + public void setOriginatingID(Double originatingID) { + this.originatingID = originatingID; + } + + /** + * @return the satelliteClass + */ + public Double getSatelliteClass() { + return satelliteClass; + } + + /** + * @param satelliteClass + * the satelliteClass to set + */ + public void setSatelliteClass(Double satelliteClass) { + this.satelliteClass = satelliteClass; + } + + /** + * @return the sgmtSzX + */ + public Double getSgmtSzX() { + return sgmtSzX; + } + + /** + * @param sgmtSzX + * the sgmtSzX to set + */ + public void setSgmtSzX(Double sgmtSzX) { + this.sgmtSzX = sgmtSzX; + } + + /** + * @return the sgmtSzY + */ + public Double getSgmtSzY() { + return sgmtSzY; + } + + /** + * @param sgmtSzY + * the sgmtSzY to set + */ + public void setSgmtSzY(Double sgmtSzY) { + this.sgmtSzY = sgmtSzY; + } + + /** + * @return the satelliteInstr + */ + public Integer getSatelliteInstr() { + return satelliteInstr; + } + + /** + * @param satelliteInstr + * the satelliteInstr to set + */ + public void setSatelliteInstr(Integer satelliteInstr) { + this.satelliteInstr = satelliteInstr; + } + + /** + * @return the satelliteWindMethod + */ + public Integer getSatelliteWindMethod() { + return satelliteWindMethod; + } + + /** + * @param satelliteWindMethod + * the satelliteWindMethod to set + */ + public void setSatelliteWindMethod(Integer satelliteWindMethod) { + this.satelliteWindMethod = satelliteWindMethod; + } + + /** + * @return the satelliteFreq + */ + public Double getSatelliteFreq() { + return satelliteFreq; + } + + /** + * @param satelliteFreq + * the satelliteFreq to set + */ + public void setSatelliteFreq(Double satelliteFreq) { + this.satelliteFreq = satelliteFreq; + } + + /** + * @return the satelliteBandWidth + */ + public Double getSatelliteBandWidth() { + return satelliteBandWidth; + } + + /** + * @param satelliteBandWidth + * the satelliteBandWidth to set + */ + public void setSatelliteBandWidth(Double satelliteBandWidth) { + this.satelliteBandWidth = satelliteBandWidth; + } + + /** + * @return the coldestTemp + */ + public Double getColdestTemp() { + return coldestTemp; + } + + /** + * @param coldestTemp + * the coldestTemp to set + */ + public void setColdestTemp(Double coldestTemp) { + this.coldestTemp = coldestTemp; + } + + /** + * @return the heightMethod + */ + public Integer getHeightMethod() { + return heightMethod; + } + + /** + * @param heightMethod + * the heightMethod to set + */ + public void setHeightMethod(Integer heightMethod) { + this.heightMethod = heightMethod; + } + + /** + * @return the tracerCorrelation + */ + public Integer getTracerCorrelation() { + return tracerCorrelation; + } + + /** + * @param tracerCorrelation + * the tracerCorrelation to set + */ + public void setTracerCorrelation(Integer tracerCorrelation) { + this.tracerCorrelation = tracerCorrelation; + } + + /** + * @return the landSea + */ + public Integer getLandSea() { + return landSea; + } + + /** + * @param landSea + * the landSea to set + */ + public void setLandSea(Integer landSea) { + this.landSea = landSea; + } + + /** + * @return the satelliteZenith + */ + public Double getSatelliteZenith() { + return satelliteZenith; + } + + /** + * @param satelliteZenith + * the satelliteZenith to set + */ + public void setSatelliteZenith(Double satelliteZenith) { + this.satelliteZenith = satelliteZenith; + } + + /** + * @return the firstGuess + */ + public Integer getFirstGuess() { + return firstGuess; + } + + /** + * @param firstGuess + * the firstGuess to set + */ + public void setFirstGuess(Integer firstGuess) { + this.firstGuess = firstGuess; + } + + /** + * @return the timeSignificance + */ + public Integer getTimeSignificance() { + return timeSignificance; + } + + /** + * @param timeSignificance + * the timeSignificance to set + */ + public void setTimeSignificance(Integer timeSignificance) { + this.timeSignificance = timeSignificance; + } + + @Override + public ISpatialObject getSpatialObject() { + return null; + } + + /** * */ - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - /** + /** * */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - /** - * Returns the hashCode for this object. This implementation returns the - * hashCode of the generated dataURI. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); - return result; - } + /** + * Returns the hashCode for this object. This implementation returns the + * hashCode of the generated dataURI. + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); + return result; + } - /** - * Checks if this record is equal to another by checking the generated - * dataURI. - * - * @param obj - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - BufrHDWObs other = (BufrHDWObs) obj; - if (getDataURI() == null) { - if (other.getDataURI() != null) { - return false; - } - } else if (!getDataURI().equals(other.getDataURI())) { - return false; - } - return true; - } + /** + * Checks if this record is equal to another by checking the generated + * dataURI. + * + * @param obj + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + BufrHDWObs other = (BufrHDWObs) obj; + if (getDataURI() == null) { + if (other.getDataURI() != null) { + return false; + } + } else if (!getDataURI().equals(other.getDataURI())) { + return false; + } + return true; + } + @Override + public String getPluginName() { + return "bufrhdw"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrmthdw/src/com/raytheon/uf/common/dataplugin/bufrmthdw/BufrMTHDWObs.java b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrmthdw/src/com/raytheon/uf/common/dataplugin/bufrmthdw/BufrMTHDWObs.java index 70694a43fe..967b670180 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrmthdw/src/com/raytheon/uf/common/dataplugin/bufrmthdw/BufrMTHDWObs.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrmthdw/src/com/raytheon/uf/common/dataplugin/bufrmthdw/BufrMTHDWObs.java @@ -59,6 +59,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * PluginDataObject. * May 17, 2013 1869 bsteffen Remove DataURI column from sat plot * types. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -73,557 +74,557 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "bufrmthdw", - indexes = { - @Index(name = "bufrmthdw_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "bufrmthdw", indexes = { @Index(name = "bufrmthdw_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class BufrMTHDWObs extends PersistablePluginDataObject implements ISpatialEnabled, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - // The observation time. - @DataURI(position = 1) - @DynamicSerializeElement - private String satType; - - @DataURI(position = 2) - @DynamicSerializeElement - private Double pressure; - - @Embedded - @DataURI(position = 3, embedded = true) - @DynamicSerializeElement - private SurfaceObsLocation location; - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - // Text of the WMO header - @Column(length = 32) - @DynamicSerializeElement - private String wmoHeader; - - // The observation time. - @Column - @DynamicSerializeElement - private Calendar validTime; - - @DynamicSerializeElement - @Transient - private Double windDir; - - @DynamicSerializeElement - @Transient - private Double windSpd; - - @DynamicSerializeElement - @Transient - private Double satelliteID; - - @DynamicSerializeElement - @Transient - private Double originatingID; - - @DynamicSerializeElement - @Transient - private Double satelliteClass; - - @DynamicSerializeElement - @Transient - private Double sgmtSzX; - - @DynamicSerializeElement - @Transient - private Double sgmtSzY; - - @DynamicSerializeElement - @Transient - private Integer satelliteInstr; - - @DynamicSerializeElement - @Transient - private Integer satelliteWindMethod; - - @DynamicSerializeElement - @Transient - private Double satelliteFreq; - - @DynamicSerializeElement - @Transient - private Double satelliteBandWidth; - - @DynamicSerializeElement - @Transient - private Double coldestTemp; - - @DynamicSerializeElement - @Transient - private Integer heightMethod; - - @DynamicSerializeElement - @Transient - private Integer tracerCorrelation; - - @DynamicSerializeElement - @Transient - private Integer landSea; - - @DynamicSerializeElement - @Transient - private Double satelliteZenith; - - @DynamicSerializeElement - @Transient - private Integer firstGuess; - - @DynamicSerializeElement - @Transient - private Integer timeSignificance; - - /** - * Empty constructor. - */ - public BufrMTHDWObs() { - } - - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public BufrMTHDWObs(String uri) { - super(uri); - } - - /** - * Get the observation time for this data. - * - * @return The data observation time. - */ - public Calendar getValidTime() { - return validTime; - } - - /** - * Set the observation time for this data. - * - * @param timeObs - * The data observation time. - */ - public void setValidTime(Calendar time) { - validTime = time; - } - - /** - * @return the satType - */ - public String getSatType() { - return satType; - } - - /** - * @param satType - * the satType to set - */ - public void setSatType(String type) { - satType = type; - } - - /** - * @param satType - * the satType to set - */ - public void setSatType(BUFRMTHDWSatType type) { - satType = type.toString(); - } - - /** - * @return the location - */ - public SurfaceObsLocation getLocation() { - return location; - } - - /** - * @param location - * the location to set - */ - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } - - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } - - /** - * @return the windDir - */ - public Double getWindDir() { - return windDir; - } - - /** - * @param windDir - * the windDir to set - */ - public void setWindDir(Double direction) { - windDir = direction; - } - - /** - * @return the windSpd - */ - public Double getWindSpd() { - return windSpd; - } - - /** - * @param windSpd - * the windSpd to set - */ - public void setWindSpd(Double speed) { - windSpd = speed; - } - - /** - * @return the pressure - */ - public Double getPressure() { - return pressure; - } - - /** - * @param pressure - * the pressure to set - */ - public void setPressure(Double pressure) { - this.pressure = pressure; - } - - /** - * @return the satelliteID - */ - public Double getSatelliteID() { - return satelliteID; - } - - /** - * @param satelliteID - * the satelliteID to set - */ - public void setSatelliteID(Double satelliteID) { - this.satelliteID = satelliteID; - } - - /** - * @return the originatingID - */ - public Double getOriginatingID() { - return originatingID; - } - - /** - * @param originatingID - * the originatingID to set - */ - public void setOriginatingID(Double originatingID) { - this.originatingID = originatingID; - } - - /** - * @return the satelliteClass - */ - public Double getSatelliteClass() { - return satelliteClass; - } - - /** - * @param satelliteClass - * the satelliteClass to set - */ - public void setSatelliteClass(Double satelliteClass) { - this.satelliteClass = satelliteClass; - } - - /** - * @return the sgmtSzX - */ - public Double getSgmtSzX() { - return sgmtSzX; - } - - /** - * @param sgmtSzX - * the sgmtSzX to set - */ - public void setSgmtSzX(Double sgmtSzX) { - this.sgmtSzX = sgmtSzX; - } - - /** - * @return the sgmtSzY - */ - public Double getSgmtSzY() { - return sgmtSzY; - } - - /** - * @param sgmtSzY - * the sgmtSzY to set - */ - public void setSgmtSzY(Double sgmtSzY) { - this.sgmtSzY = sgmtSzY; - } - - /** - * @return the satelliteInstr - */ - public Integer getSatelliteInstr() { - return satelliteInstr; - } - - /** - * @param satelliteInstr - * the satelliteInstr to set - */ - public void setSatelliteInstr(Integer satelliteInstr) { - this.satelliteInstr = satelliteInstr; - } - - /** - * @return the satelliteWindMethod - */ - public Integer getSatelliteWindMethod() { - return satelliteWindMethod; - } - - /** - * @param satelliteWindMethod - * the satelliteWindMethod to set - */ - public void setSatelliteWindMethod(Integer satelliteWindMethod) { - this.satelliteWindMethod = satelliteWindMethod; - } - - /** - * @return the satelliteFreq - */ - public Double getSatelliteFreq() { - return satelliteFreq; - } - - /** - * @param satelliteFreq - * the satelliteFreq to set - */ - public void setSatelliteFreq(Double satelliteFreq) { - this.satelliteFreq = satelliteFreq; - } - - /** - * @return the satelliteBandWidth - */ - public Double getSatelliteBandWidth() { - return satelliteBandWidth; - } - - /** - * @param satelliteBandWidth - * the satelliteBandWidth to set - */ - public void setSatelliteBandWidth(Double satelliteBandWidth) { - this.satelliteBandWidth = satelliteBandWidth; - } - - /** - * @return the coldestTemp - */ - public Double getColdestTemp() { - return coldestTemp; - } - - /** - * @param coldestTemp - * the coldestTemp to set - */ - public void setColdestTemp(Double coldestTemp) { - this.coldestTemp = coldestTemp; - } - - /** - * @return the heightMethod - */ - public Integer getHeightMethod() { - return heightMethod; - } - - /** - * @param heightMethod - * the heightMethod to set - */ - public void setHeightMethod(Integer heightMethod) { - this.heightMethod = heightMethod; - } - - /** - * @return the tracerCorrelation - */ - public Integer getTracerCorrelation() { - return tracerCorrelation; - } - - /** - * @param tracerCorrelation - * the tracerCorrelation to set - */ - public void setTracerCorrelation(Integer tracerCorrelation) { - this.tracerCorrelation = tracerCorrelation; - } - - /** - * @return the landSea - */ - public Integer getLandSea() { - return landSea; - } - - /** - * @param landSea - * the landSea to set - */ - public void setLandSea(Integer landSea) { - this.landSea = landSea; - } - - /** - * @return the satelliteZenith - */ - public Double getSatelliteZenith() { - return satelliteZenith; - } - - /** - * @param satelliteZenith - * the satelliteZenith to set - */ - public void setSatelliteZenith(Double satelliteZenith) { - this.satelliteZenith = satelliteZenith; - } - - /** - * @return the firstGuess - */ - public Integer getFirstGuess() { - return firstGuess; - } - - /** - * @param firstGuess - * the firstGuess to set - */ - public void setFirstGuess(Integer firstGuess) { - this.firstGuess = firstGuess; - } - - /** - * @return the timeSignificance - */ - public Integer getTimeSignificance() { - return timeSignificance; - } - - /** - * @param timeSignificance - * the timeSignificance to set - */ - public void setTimeSignificance(Integer timeSignificance) { - this.timeSignificance = timeSignificance; - } - - @Override - public ISpatialObject getSpatialObject() { - return null; - } - - /** + // The observation time. + @DataURI(position = 1) + @DynamicSerializeElement + private String satType; + + @DataURI(position = 2) + @DynamicSerializeElement + private Double pressure; + + @Embedded + @DataURI(position = 3, embedded = true) + @DynamicSerializeElement + private SurfaceObsLocation location; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + // Text of the WMO header + @Column(length = 32) + @DynamicSerializeElement + private String wmoHeader; + + // The observation time. + @Column + @DynamicSerializeElement + private Calendar validTime; + + @DynamicSerializeElement + @Transient + private Double windDir; + + @DynamicSerializeElement + @Transient + private Double windSpd; + + @DynamicSerializeElement + @Transient + private Double satelliteID; + + @DynamicSerializeElement + @Transient + private Double originatingID; + + @DynamicSerializeElement + @Transient + private Double satelliteClass; + + @DynamicSerializeElement + @Transient + private Double sgmtSzX; + + @DynamicSerializeElement + @Transient + private Double sgmtSzY; + + @DynamicSerializeElement + @Transient + private Integer satelliteInstr; + + @DynamicSerializeElement + @Transient + private Integer satelliteWindMethod; + + @DynamicSerializeElement + @Transient + private Double satelliteFreq; + + @DynamicSerializeElement + @Transient + private Double satelliteBandWidth; + + @DynamicSerializeElement + @Transient + private Double coldestTemp; + + @DynamicSerializeElement + @Transient + private Integer heightMethod; + + @DynamicSerializeElement + @Transient + private Integer tracerCorrelation; + + @DynamicSerializeElement + @Transient + private Integer landSea; + + @DynamicSerializeElement + @Transient + private Double satelliteZenith; + + @DynamicSerializeElement + @Transient + private Integer firstGuess; + + @DynamicSerializeElement + @Transient + private Integer timeSignificance; + + /** + * Empty constructor. + */ + public BufrMTHDWObs() { + } + + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public BufrMTHDWObs(String uri) { + super(uri); + } + + /** + * Get the observation time for this data. + * + * @return The data observation time. + */ + public Calendar getValidTime() { + return validTime; + } + + /** + * Set the observation time for this data. + * + * @param timeObs + * The data observation time. + */ + public void setValidTime(Calendar time) { + validTime = time; + } + + /** + * @return the satType + */ + public String getSatType() { + return satType; + } + + /** + * @param satType + * the satType to set + */ + public void setSatType(String type) { + satType = type; + } + + /** + * @param satType + * the satType to set + */ + public void setSatType(BUFRMTHDWSatType type) { + satType = type.toString(); + } + + /** + * @return the location + */ + public SurfaceObsLocation getLocation() { + return location; + } + + /** + * @param location + * the location to set + */ + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } + + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } + + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } + + /** + * @return the windDir + */ + public Double getWindDir() { + return windDir; + } + + /** + * @param windDir + * the windDir to set + */ + public void setWindDir(Double direction) { + windDir = direction; + } + + /** + * @return the windSpd + */ + public Double getWindSpd() { + return windSpd; + } + + /** + * @param windSpd + * the windSpd to set + */ + public void setWindSpd(Double speed) { + windSpd = speed; + } + + /** + * @return the pressure + */ + public Double getPressure() { + return pressure; + } + + /** + * @param pressure + * the pressure to set + */ + public void setPressure(Double pressure) { + this.pressure = pressure; + } + + /** + * @return the satelliteID + */ + public Double getSatelliteID() { + return satelliteID; + } + + /** + * @param satelliteID + * the satelliteID to set + */ + public void setSatelliteID(Double satelliteID) { + this.satelliteID = satelliteID; + } + + /** + * @return the originatingID + */ + public Double getOriginatingID() { + return originatingID; + } + + /** + * @param originatingID + * the originatingID to set + */ + public void setOriginatingID(Double originatingID) { + this.originatingID = originatingID; + } + + /** + * @return the satelliteClass + */ + public Double getSatelliteClass() { + return satelliteClass; + } + + /** + * @param satelliteClass + * the satelliteClass to set + */ + public void setSatelliteClass(Double satelliteClass) { + this.satelliteClass = satelliteClass; + } + + /** + * @return the sgmtSzX + */ + public Double getSgmtSzX() { + return sgmtSzX; + } + + /** + * @param sgmtSzX + * the sgmtSzX to set + */ + public void setSgmtSzX(Double sgmtSzX) { + this.sgmtSzX = sgmtSzX; + } + + /** + * @return the sgmtSzY + */ + public Double getSgmtSzY() { + return sgmtSzY; + } + + /** + * @param sgmtSzY + * the sgmtSzY to set + */ + public void setSgmtSzY(Double sgmtSzY) { + this.sgmtSzY = sgmtSzY; + } + + /** + * @return the satelliteInstr + */ + public Integer getSatelliteInstr() { + return satelliteInstr; + } + + /** + * @param satelliteInstr + * the satelliteInstr to set + */ + public void setSatelliteInstr(Integer satelliteInstr) { + this.satelliteInstr = satelliteInstr; + } + + /** + * @return the satelliteWindMethod + */ + public Integer getSatelliteWindMethod() { + return satelliteWindMethod; + } + + /** + * @param satelliteWindMethod + * the satelliteWindMethod to set + */ + public void setSatelliteWindMethod(Integer satelliteWindMethod) { + this.satelliteWindMethod = satelliteWindMethod; + } + + /** + * @return the satelliteFreq + */ + public Double getSatelliteFreq() { + return satelliteFreq; + } + + /** + * @param satelliteFreq + * the satelliteFreq to set + */ + public void setSatelliteFreq(Double satelliteFreq) { + this.satelliteFreq = satelliteFreq; + } + + /** + * @return the satelliteBandWidth + */ + public Double getSatelliteBandWidth() { + return satelliteBandWidth; + } + + /** + * @param satelliteBandWidth + * the satelliteBandWidth to set + */ + public void setSatelliteBandWidth(Double satelliteBandWidth) { + this.satelliteBandWidth = satelliteBandWidth; + } + + /** + * @return the coldestTemp + */ + public Double getColdestTemp() { + return coldestTemp; + } + + /** + * @param coldestTemp + * the coldestTemp to set + */ + public void setColdestTemp(Double coldestTemp) { + this.coldestTemp = coldestTemp; + } + + /** + * @return the heightMethod + */ + public Integer getHeightMethod() { + return heightMethod; + } + + /** + * @param heightMethod + * the heightMethod to set + */ + public void setHeightMethod(Integer heightMethod) { + this.heightMethod = heightMethod; + } + + /** + * @return the tracerCorrelation + */ + public Integer getTracerCorrelation() { + return tracerCorrelation; + } + + /** + * @param tracerCorrelation + * the tracerCorrelation to set + */ + public void setTracerCorrelation(Integer tracerCorrelation) { + this.tracerCorrelation = tracerCorrelation; + } + + /** + * @return the landSea + */ + public Integer getLandSea() { + return landSea; + } + + /** + * @param landSea + * the landSea to set + */ + public void setLandSea(Integer landSea) { + this.landSea = landSea; + } + + /** + * @return the satelliteZenith + */ + public Double getSatelliteZenith() { + return satelliteZenith; + } + + /** + * @param satelliteZenith + * the satelliteZenith to set + */ + public void setSatelliteZenith(Double satelliteZenith) { + this.satelliteZenith = satelliteZenith; + } + + /** + * @return the firstGuess + */ + public Integer getFirstGuess() { + return firstGuess; + } + + /** + * @param firstGuess + * the firstGuess to set + */ + public void setFirstGuess(Integer firstGuess) { + this.firstGuess = firstGuess; + } + + /** + * @return the timeSignificance + */ + public Integer getTimeSignificance() { + return timeSignificance; + } + + /** + * @param timeSignificance + * the timeSignificance to set + */ + public void setTimeSignificance(Integer timeSignificance) { + this.timeSignificance = timeSignificance; + } + + @Override + public ISpatialObject getSpatialObject() { + return null; + } + + /** * */ - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - /** + /** * */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - /** - * Returns the hashCode for this object. This implementation returns the - * hashCode of the generated dataURI. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); - return result; - } + /** + * Returns the hashCode for this object. This implementation returns the + * hashCode of the generated dataURI. + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); + return result; + } - /** - * Checks if this record is equal to another by checking the generated - * dataURI. - * - * @param obj - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - BufrMTHDWObs other = (BufrMTHDWObs) obj; - if (getDataURI() == null) { - if (other.getDataURI() != null) { - return false; - } - } else if (!getDataURI().equals(other.getDataURI())) { - return false; - } - return true; - } + /** + * Checks if this record is equal to another by checking the generated + * dataURI. + * + * @param obj + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + BufrMTHDWObs other = (BufrMTHDWObs) obj; + if (getDataURI() == null) { + if (other.getDataURI() != null) { + return false; + } + } else if (!getDataURI().equals(other.getDataURI())) { + return false; + } + return true; + } + @Override + public String getPluginName() { + return "bufrmthdw"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrncwf/src/com/raytheon/uf/common/dataplugin/ncwf/BUFRncwf.java b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrncwf/src/com/raytheon/uf/common/dataplugin/ncwf/BUFRncwf.java index 6c27068227..a81679b54d 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrncwf/src/com/raytheon/uf/common/dataplugin/ncwf/BUFRncwf.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrncwf/src/com/raytheon/uf/common/dataplugin/ncwf/BUFRncwf.java @@ -60,10 +60,12 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Aug 17, 2009 jkorman Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -77,213 +79,215 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "bufrncwf", - indexes = { - @Index(name = "bufrncwf_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "bufrncwf", indexes = { @Index(name = "bufrncwf_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class BUFRncwf extends PersistablePluginDataObject implements - ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { + ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - @Embedded - @DataURI(position = 1, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; + @Embedded + @DataURI(position = 1, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; - @Transient - @XmlElement - @DynamicSerializeElement - private NCWFFeature detection; + @Transient + @XmlElement + @DynamicSerializeElement + private NCWFFeature detection; - @Transient - @XmlElement - @DynamicSerializeElement - private NCWFFeature forecast; + @Transient + @XmlElement + @DynamicSerializeElement + private NCWFFeature forecast; - @Transient - @XmlAttribute - @DynamicSerializeElement - private Double stormDir; + @Transient + @XmlAttribute + @DynamicSerializeElement + private Double stormDir; - @Transient - @XmlAttribute - @DynamicSerializeElement - private Double stormSpeed; + @Transient + @XmlAttribute + @DynamicSerializeElement + private Double stormSpeed; - @Transient - @XmlAttribute - @DynamicSerializeElement - private Double stormTop; + @Transient + @XmlAttribute + @DynamicSerializeElement + private Double stormTop; - /** - * Empty constructor. - */ - public BUFRncwf() { - } + /** + * Empty constructor. + */ + public BUFRncwf() { + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public BUFRncwf(String uri) { - super(uri); - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public BUFRncwf(String uri) { + super(uri); + } - /** - * @return the location - */ - public SurfaceObsLocation getLocation() { - return location; - } + /** + * @return the location + */ + public SurfaceObsLocation getLocation() { + return location; + } - /** - * @param location - * the location to set - */ - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + /** + * @param location + * the location to set + */ + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - /** - * @return the detection - */ - public NCWFFeature getDetection() { - return detection; - } + /** + * @return the detection + */ + public NCWFFeature getDetection() { + return detection; + } - /** - * @param detection - * the detection to set - */ - public void setDetection(NCWFFeature detection) { - this.detection = detection; - } + /** + * @param detection + * the detection to set + */ + public void setDetection(NCWFFeature detection) { + this.detection = detection; + } - /** - * @return the forecast - */ - public NCWFFeature getForecast() { - return forecast; - } + /** + * @return the forecast + */ + public NCWFFeature getForecast() { + return forecast; + } - /** - * @param forecast - * the forecast to set - */ - public void setForecast(NCWFFeature forecast) { - this.forecast = forecast; - } + /** + * @param forecast + * the forecast to set + */ + public void setForecast(NCWFFeature forecast) { + this.forecast = forecast; + } - /** - * @return the stormDir - */ - public Double getStormDir() { - return stormDir; - } + /** + * @return the stormDir + */ + public Double getStormDir() { + return stormDir; + } - /** - * @param stormDir - * the stormDir to set - */ - public void setStormDir(Double stormDir) { - this.stormDir = stormDir; - } + /** + * @param stormDir + * the stormDir to set + */ + public void setStormDir(Double stormDir) { + this.stormDir = stormDir; + } - /** - * @return the stormSpeed - */ - public Double getStormSpeed() { - return stormSpeed; - } + /** + * @return the stormSpeed + */ + public Double getStormSpeed() { + return stormSpeed; + } - /** - * @param stormSpeed - * the stormSpeed to set - */ - public void setStormSpeed(Double stormSpeed) { - this.stormSpeed = stormSpeed; - } + /** + * @param stormSpeed + * the stormSpeed to set + */ + public void setStormSpeed(Double stormSpeed) { + this.stormSpeed = stormSpeed; + } - /** - * @return the stormTop - */ - public Double getStormTop() { - return stormTop; - } + /** + * @return the stormTop + */ + public Double getStormTop() { + return stormTop; + } - /** - * @param stormTop - * the stormTop to set - */ - public void setStormTop(Double stormTop) { - this.stormTop = stormTop; - } + /** + * @param stormTop + * the stormTop to set + */ + public void setStormTop(Double stormTop) { + this.stormTop = stormTop; + } - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } - @Override - public ISpatialObject getSpatialObject() { - return location; - } + @Override + public ISpatialObject getSpatialObject() { + return location; + } - @Override - public String getString(String paramName) { - return null; - } + @Override + public String getString(String paramName) { + return null; + } - @Override - public String[] getStrings(String paramName) { - return null; - } + @Override + public String[] getStrings(String paramName) { + return null; + } - @Override - public Amount getValue(String paramName) { - return null; - } + @Override + public Amount getValue(String paramName) { + return null; + } - @Override - public Collection getValues(String paramName) { - return null; - } + @Override + public Collection getValues(String paramName) { + return null; + } - /** + /** * */ - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - /** + /** * */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "bufrncwf"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrquikscat/src/com/raytheon/uf/common/dataplugin/bufrquikscat/QUIKScatObs.java b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrquikscat/src/com/raytheon/uf/common/dataplugin/bufrquikscat/QUIKScatObs.java index 6f1637c721..2463ebf132 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrquikscat/src/com/raytheon/uf/common/dataplugin/bufrquikscat/QUIKScatObs.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrquikscat/src/com/raytheon/uf/common/dataplugin/bufrquikscat/QUIKScatObs.java @@ -61,11 +61,13 @@ import com.vividsolutions.jts.geom.Geometry; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jun 18, 2009 2520 jkorman Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Jun 18, 2009 2520 jkorman Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -79,324 +81,326 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "bufrquikscat", - indexes = { - @Index(name = "bufrquikscat_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "bufrquikscat", indexes = { @Index(name = "bufrquikscat_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class QUIKScatObs extends PersistablePluginDataObject implements - ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { + ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - @DataURI(position = 1) - @XmlAttribute - @DynamicSerializeElement - private Integer satId; + @DataURI(position = 1) + @XmlAttribute + @DynamicSerializeElement + private Integer satId; - @Embedded - @DataURI(position = 2, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; + @Embedded + @DataURI(position = 2, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; - // Text of the WMO header - @Column(length = 32) - @DynamicSerializeElement - @XmlElement - private String wmoHeader; + // Text of the WMO header + @Column(length = 32) + @DynamicSerializeElement + @XmlElement + private String wmoHeader; - @XmlAttribute - @DynamicSerializeElement - @Transient - private Integer orbitNumber; + @XmlAttribute + @DynamicSerializeElement + @Transient + private Integer orbitNumber; - // The observation time. - @XmlAttribute - @DynamicSerializeElement - @Transient - private Calendar timeObs; + // The observation time. + @XmlAttribute + @DynamicSerializeElement + @Transient + private Calendar timeObs; - @XmlAttribute - @DynamicSerializeElement - @Transient - private Double windDir; + @XmlAttribute + @DynamicSerializeElement + @Transient + private Double windDir; - @XmlAttribute - @DynamicSerializeElement - @Transient - private Double windSpd; + @XmlAttribute + @DynamicSerializeElement + @Transient + private Double windSpd; - @XmlAttribute - @DynamicSerializeElement - @Transient - private Double probRain; + @XmlAttribute + @DynamicSerializeElement + @Transient + private Double probRain; - @XmlAttribute - @DynamicSerializeElement - @Transient - private Integer rainIndex; + @XmlAttribute + @DynamicSerializeElement + @Transient + private Integer rainIndex; - /** - * Empty constructor. - */ - public QUIKScatObs() { - } + /** + * Empty constructor. + */ + public QUIKScatObs() { + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public QUIKScatObs(String uri) { - super(uri); - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public QUIKScatObs(String uri) { + super(uri); + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } - /** - * Was this location defined from the station catalog? False if not. - * - * @return Was this location defined from the station catalog? - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } + /** + * Was this location defined from the station catalog? False if not. + * + * @return Was this location defined from the station catalog? + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } - /** - * @return the location - */ - public SurfaceObsLocation getLocation() { - return location; - } + /** + * @return the location + */ + public SurfaceObsLocation getLocation() { + return location; + } - /** - * @param location - * the location to set - */ - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + /** + * @param location + * the location to set + */ + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - /** - * @return the satId - */ - public Integer getSatId() { - return satId; - } + /** + * @return the satId + */ + public Integer getSatId() { + return satId; + } - /** - * @param satId - * the satId to set - */ - public void setSatId(Integer satId) { - this.satId = satId; - } + /** + * @param satId + * the satId to set + */ + public void setSatId(Integer satId) { + this.satId = satId; + } - /** - * @return the orbitNumber - */ - public Integer getOrbitNumber() { - return orbitNumber; - } + /** + * @return the orbitNumber + */ + public Integer getOrbitNumber() { + return orbitNumber; + } - /** - * @param orbitNumber - * the orbitNumber to set - */ - public void setOrbitNumber(Integer orbitNumber) { - this.orbitNumber = orbitNumber; - } + /** + * @param orbitNumber + * the orbitNumber to set + */ + public void setOrbitNumber(Integer orbitNumber) { + this.orbitNumber = orbitNumber; + } - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * @return the windDir - */ - public Double getWindDir() { - return windDir; - } + /** + * @return the windDir + */ + public Double getWindDir() { + return windDir; + } - /** - * @param windDir - * the windDir to set - */ - public void setWindDir(Double windDir) { - this.windDir = windDir; - } + /** + * @param windDir + * the windDir to set + */ + public void setWindDir(Double windDir) { + this.windDir = windDir; + } - /** - * @return the windSpd - */ - public Double getWindSpd() { - return windSpd; - } + /** + * @return the windSpd + */ + public Double getWindSpd() { + return windSpd; + } - /** - * @param windSpd - * the windSpd to set - */ - public void setWindSpd(Double windSpd) { - this.windSpd = windSpd; - } + /** + * @param windSpd + * the windSpd to set + */ + public void setWindSpd(Double windSpd) { + this.windSpd = windSpd; + } - /** - * @return the probRain - */ - public Double getProbRain() { - return probRain; - } + /** + * @return the probRain + */ + public Double getProbRain() { + return probRain; + } - /** - * @param probRain - * the probRain to set - */ - public void setProbRain(Double probRain) { - this.probRain = probRain; - } + /** + * @param probRain + * the probRain to set + */ + public void setProbRain(Double probRain) { + this.probRain = probRain; + } - /** - * @return the rainIndex - */ - public Integer getRainIndex() { - return rainIndex; - } + /** + * @return the rainIndex + */ + public Integer getRainIndex() { + return rainIndex; + } - /** - * @param rainIndex - * the rainIndex to set - */ - public void setRainIndex(Integer rainIndex) { - this.rainIndex = rainIndex; - } + /** + * @param rainIndex + * the rainIndex to set + */ + public void setRainIndex(Integer rainIndex) { + this.rainIndex = rainIndex; + } - /** - * Get the observation time for this data. - * - * @return The data observation time. - */ - public Calendar getTimeObs() { - return timeObs; - } + /** + * Get the observation time for this data. + * + * @return The data observation time. + */ + public Calendar getTimeObs() { + return timeObs; + } - /** - * Set the observation time for this data. - * - * @param timeObs - * The data observation time. - */ - public void setTimeObs(Calendar timeObs) { - this.timeObs = timeObs; - } + /** + * Set the observation time for this data. + * + * @param timeObs + * The data observation time. + */ + public void setTimeObs(Calendar timeObs) { + this.timeObs = timeObs; + } - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } - @Override - public ISpatialObject getSpatialObject() { - return location; - } + @Override + public ISpatialObject getSpatialObject() { + return location; + } - @Override - public String getString(String paramName) { - return null; - } + @Override + public String getString(String paramName) { + return null; + } - @Override - public String[] getStrings(String paramName) { - return null; - } + @Override + public String[] getStrings(String paramName) { + return null; + } - @Override - public Amount getValue(String paramName) { - return null; - } + @Override + public Amount getValue(String paramName) { + return null; + } - @Override - public Collection getValues(String paramName) { - return null; - } + @Override + public Collection getValues(String paramName) { + return null; + } - /** + /** * */ - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - /** + /** * */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "bufrquikscat"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrsigwx/src/com/raytheon/uf/common/dataplugin/bufrsigwx/SigWxData.java b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrsigwx/src/com/raytheon/uf/common/dataplugin/bufrsigwx/SigWxData.java index 86c66ac5ff..054de56379 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrsigwx/src/com/raytheon/uf/common/dataplugin/bufrsigwx/SigWxData.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrsigwx/src/com/raytheon/uf/common/dataplugin/bufrsigwx/SigWxData.java @@ -60,10 +60,12 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 18, 2009 jkorman Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -77,250 +79,251 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "bufrsigwx", - indexes = { - @Index(name = "bufrswigwx_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "bufrsigwx", indexes = { @Index(name = "bufrswigwx_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) public class SigWxData extends PersistablePluginDataObject implements - IDecoderGettable, IPointData, IPersistable { + IDecoderGettable, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Column - @DataURI(position = 1) - @XmlElement - @DynamicSerializeElement - private SigWxLayer wxLayer; + @Column + @DataURI(position = 1) + @XmlElement + @DynamicSerializeElement + private SigWxLayer wxLayer; - @Column - @DataURI(position = 2) - @XmlElement - @DynamicSerializeElement - private SigWxType wxType; + @Column + @DataURI(position = 2) + @XmlElement + @DynamicSerializeElement + private SigWxType wxType; - @Column - @DataURI(position = 3) - @XmlAttribute - @DynamicSerializeElement - private Integer key; + @Column + @DataURI(position = 3) + @XmlAttribute + @DynamicSerializeElement + private Integer key; - @Column - @XmlAttribute - @DynamicSerializeElement - private Integer baseHeight; + @Column + @XmlAttribute + @DynamicSerializeElement + private Integer baseHeight; - @Column - @XmlAttribute - @DynamicSerializeElement - private Integer topHeight; + @Column + @XmlAttribute + @DynamicSerializeElement + private Integer topHeight; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - // Text of the WMO header - @Column(length = 32) - @DynamicSerializeElement - @XmlElement - private String wmoHeader; + // Text of the WMO header + @Column(length = 32) + @DynamicSerializeElement + @XmlElement + private String wmoHeader; - @Transient - @DynamicSerializeElement - @XmlElement - private TropopauseLayerData tropData; + @Transient + @DynamicSerializeElement + @XmlElement + private TropopauseLayerData tropData; - /** - * Empty constructor. - */ - public SigWxData() { - } + /** + * Empty constructor. + */ + public SigWxData() { + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public SigWxData(String uri) { - super(uri); - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public SigWxData(String uri) { + super(uri); + } - /** - * @return the wxLayer - */ - public SigWxLayer getWxLayer() { - return wxLayer; - } + /** + * @return the wxLayer + */ + public SigWxLayer getWxLayer() { + return wxLayer; + } - /** - * @param wxLayer - * the wxLayer to set - */ - public void setWxLayer(SigWxLayer wxLayer) { - this.wxLayer = wxLayer; - } + /** + * @param wxLayer + * the wxLayer to set + */ + public void setWxLayer(SigWxLayer wxLayer) { + this.wxLayer = wxLayer; + } - /** - * @return the wxType - */ - public SigWxType getWxType() { - return wxType; - } + /** + * @return the wxType + */ + public SigWxType getWxType() { + return wxType; + } - /** - * @param wxType - * the wxType to set - */ - public void setWxType(SigWxType wxType) { - this.wxType = wxType; - } + /** + * @param wxType + * the wxType to set + */ + public void setWxType(SigWxType wxType) { + this.wxType = wxType; + } - /** - * @return the baseHeight - */ - public Integer getBaseHeight() { - return baseHeight; - } + /** + * @return the baseHeight + */ + public Integer getBaseHeight() { + return baseHeight; + } - /** - * @param baseHeight - * the baseHeight to set - */ - public void setBaseHeight(Integer baseHeight) { - this.baseHeight = baseHeight; - } + /** + * @param baseHeight + * the baseHeight to set + */ + public void setBaseHeight(Integer baseHeight) { + this.baseHeight = baseHeight; + } - /** - * @return the topHeight - */ - public Integer getTopHeight() { - return topHeight; - } + /** + * @return the topHeight + */ + public Integer getTopHeight() { + return topHeight; + } - /** - * @param topHeight - * the topHeight to set - */ - public void setTopHeight(Integer topHeight) { - this.topHeight = topHeight; - } + /** + * @param topHeight + * the topHeight to set + */ + public void setTopHeight(Integer topHeight) { + this.topHeight = topHeight; + } - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * @return the tropData - */ - public TropopauseLayerData getTropData() { - return tropData; - } + /** + * @return the tropData + */ + public TropopauseLayerData getTropData() { + return tropData; + } - /** - * @param tropData - * the tropData to set - */ - public void setTropData(TropopauseLayerData tropData) { - this.tropData = tropData; - } + /** + * @param tropData + * the tropData to set + */ + public void setTropData(TropopauseLayerData tropData) { + this.tropData = tropData; + } - /** - * @return the key - */ - public Integer getKey() { - return key; - } + /** + * @return the key + */ + public Integer getKey() { + return key; + } - /** - * @param key - * the key to set - */ - public void setKey(Integer key) { - this.key = key; - } + /** + * @param key + * the key to set + */ + public void setKey(Integer key) { + this.key = key; + } - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } - @Override - public String getString(String paramName) { - return null; - } + @Override + public String getString(String paramName) { + return null; + } - @Override - public String[] getStrings(String paramName) { - return null; - } + @Override + public String[] getStrings(String paramName) { + return null; + } - @Override - public Amount getValue(String paramName) { - return null; - } + @Override + public Amount getValue(String paramName) { + return null; + } - @Override - public Collection getValues(String paramName) { - return null; - } + @Override + public Collection getValues(String paramName) { + return null; + } - /** + /** * */ - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - /** + /** * */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - /** - * - * @return - */ - public final SigWxData copyObs() { - SigWxData obs = new SigWxData(); + /** + * + * @return + */ + public final SigWxData copyObs() { + SigWxData obs = new SigWxData(); - obs.dataTime = dataTime.clone(); - obs.pluginName = pluginName; + obs.dataTime = dataTime.clone(); - obs.baseHeight = baseHeight; - obs.topHeight = topHeight; - obs.wxLayer = wxLayer; - obs.wxType = wxType; - obs.wmoHeader = wmoHeader; + obs.baseHeight = baseHeight; + obs.topHeight = topHeight; + obs.wxLayer = wxLayer; + obs.wxType = wxType; + obs.wmoHeader = wmoHeader; + + return obs; + } - return obs; - } @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "bufrsigwx"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrssmi/src/com/raytheon/uf/common/dataplugin/bufrssmi/SSMIScanData.java b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrssmi/src/com/raytheon/uf/common/dataplugin/bufrssmi/SSMIScanData.java index 0ff6dd03bb..16eaed9154 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrssmi/src/com/raytheon/uf/common/dataplugin/bufrssmi/SSMIScanData.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrssmi/src/com/raytheon/uf/common/dataplugin/bufrssmi/SSMIScanData.java @@ -61,6 +61,7 @@ import com.vividsolutions.jts.geom.Geometry; * PluginDataObject. * May 17, 2013 1869 bsteffen Remove DataURI column from sat plot * types. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -75,300 +76,300 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "bufrssmi", - indexes = { - @Index(name = "bufrssmi_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "bufrssmi", indexes = { @Index(name = "bufrssmi_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class SSMIScanData extends PersistablePluginDataObject implements ISpatialEnabled, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @DataURI(position = 1) - @XmlAttribute - @DynamicSerializeElement - private Integer satId; + @DataURI(position = 1) + @XmlAttribute + @DynamicSerializeElement + private Integer satId; - @Embedded - @DataURI(position = 2, embedded = true) - @DynamicSerializeElement - private SurfaceObsLocation location; + @Embedded + @DataURI(position = 2, embedded = true) + @DynamicSerializeElement + private SurfaceObsLocation location; - @DynamicSerializeElement - @Transient - private Integer orbitNumber; + @DynamicSerializeElement + @Transient + private Integer orbitNumber; - @DynamicSerializeElement - @Transient - private Integer scanNumber; + @DynamicSerializeElement + @Transient + private Integer scanNumber; - @DynamicSerializeElement - @Transient - private Integer posNumber; + @DynamicSerializeElement + @Transient + private Integer posNumber; - // The profiler observation time. - @Column - @DynamicSerializeElement - private Calendar timeObs; + // The profiler observation time. + @Column + @DynamicSerializeElement + private Calendar timeObs; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - // Text of the WMO header - @Column(length = 32) - @DynamicSerializeElement - private String wmoHeader; + // Text of the WMO header + @Column(length = 32) + @DynamicSerializeElement + private String wmoHeader; - /** - * Empty constructor. - */ - public SSMIScanData() { - } + /** + * Empty constructor. + */ + public SSMIScanData() { + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public SSMIScanData(String uri) { - super(uri); - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public SSMIScanData(String uri) { + super(uri); + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } - /** - * Was this location defined from the station catalog? False if not. - * - * @return Was this location defined from the station catalog? - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } + /** + * Was this location defined from the station catalog? False if not. + * + * @return Was this location defined from the station catalog? + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } - /** - * @return the satId - */ - public Integer getSatId() { - return satId; - } + /** + * @return the satId + */ + public Integer getSatId() { + return satId; + } - /** - * @param satId - * the satId to set - */ - public void setSatId(Integer satId) { - this.satId = satId; - } + /** + * @param satId + * the satId to set + */ + public void setSatId(Integer satId) { + this.satId = satId; + } - /** - * @return the orbitNumber - */ - public Integer getOrbitNumber() { - return orbitNumber; - } + /** + * @return the orbitNumber + */ + public Integer getOrbitNumber() { + return orbitNumber; + } - /** - * @param orbitNumber - * the orbitNumber to set - */ - public void setOrbitNumber(Integer orbitNumber) { - this.orbitNumber = orbitNumber; - } + /** + * @param orbitNumber + * the orbitNumber to set + */ + public void setOrbitNumber(Integer orbitNumber) { + this.orbitNumber = orbitNumber; + } - /** - * @return the scanNumber - */ - public Integer getScanNumber() { - return scanNumber; - } + /** + * @return the scanNumber + */ + public Integer getScanNumber() { + return scanNumber; + } - /** - * @param scanNumber - * the scanNumber to set - */ - public void setScanNumber(Integer scanNumber) { - this.scanNumber = scanNumber; - } + /** + * @param scanNumber + * the scanNumber to set + */ + public void setScanNumber(Integer scanNumber) { + this.scanNumber = scanNumber; + } - /** - * @return the posNumber - */ - public Integer getPosNumber() { - return posNumber; - } + /** + * @return the posNumber + */ + public Integer getPosNumber() { + return posNumber; + } - /** - * @param posNumber - * the posNumber to set - */ - public void setPosNumber(Integer posNumber) { - this.posNumber = posNumber; - } + /** + * @param posNumber + * the posNumber to set + */ + public void setPosNumber(Integer posNumber) { + this.posNumber = posNumber; + } - /** - * Get the observation time for this data. - * - * @return The data observation time. - */ - public Calendar getTimeObs() { - return timeObs; - } + /** + * Get the observation time for this data. + * + * @return The data observation time. + */ + public Calendar getTimeObs() { + return timeObs; + } - /** - * Set the observation time for this data. - * - * @param timeObs - * The data observation time. - */ - public void setTimeObs(Calendar timeObs) { - this.timeObs = timeObs; - } + /** + * Set the observation time for this data. + * + * @param timeObs + * The data observation time. + */ + public void setTimeObs(Calendar timeObs) { + this.timeObs = timeObs; + } - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } - public SurfaceObsLocation getLocation() { - return location; - } + public SurfaceObsLocation getLocation() { + return location; + } - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - /** + /** * */ - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - /** + /** * */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - /** - * - * @return - */ - public final SSMIScanData copyObs() { - SSMIScanData obs = new SSMIScanData(); + /** + * + * @return + */ + public final SSMIScanData copyObs() { + SSMIScanData obs = new SSMIScanData(); - obs.dataTime = dataTime.clone(); - obs.timeObs = TimeTools.copy(timeObs); - obs.orbitNumber = orbitNumber; - obs.satId = satId; - obs.scanNumber = scanNumber; - obs.wmoHeader = wmoHeader; + obs.dataTime = dataTime.clone(); + obs.timeObs = TimeTools.copy(timeObs); + obs.orbitNumber = orbitNumber; + obs.satId = satId; + obs.scanNumber = scanNumber; + obs.wmoHeader = wmoHeader; - return obs; - } + return obs; + } - /** - * Returns the hashCode for this object. This implementation returns the - * hashCode of the generated dataURI. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); - return result; - } + /** + * Returns the hashCode for this object. This implementation returns the + * hashCode of the generated dataURI. + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); + return result; + } - /** - * Checks if this record is equal to another by checking the generated - * dataURI. - * - * @param obj - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - SSMIScanData other = (SSMIScanData) obj; - if (getDataURI() == null) { - if (other.getDataURI() != null) { - return false; - } - } else if (!getDataURI().equals(other.getDataURI())) { - return false; - } - return true; - } + /** + * Checks if this record is equal to another by checking the generated + * dataURI. + * + * @param obj + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + SSMIScanData other = (SSMIScanData) obj; + if (getDataURI() == null) { + if (other.getDataURI() != null) { + return false; + } + } else if (!getDataURI().equals(other.getDataURI())) { + return false; + } + return true; + } + @Override + public String getPluginName() { + return "bufrssmi"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrua/src/com/raytheon/uf/common/dataplugin/bufrua/UAObs.java b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrua/src/com/raytheon/uf/common/dataplugin/bufrua/UAObs.java index 89ecdfa76c..3aae4061d0 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.bufrua/src/com/raytheon/uf/common/dataplugin/bufrua/UAObs.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.bufrua/src/com/raytheon/uf/common/dataplugin/bufrua/UAObs.java @@ -93,6 +93,7 @@ import com.vividsolutions.jts.geom.Geometry; * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * Jun 20, 2013 2128 bsteffen Ensure setDataURI sets the dataURI. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -106,73 +107,69 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "bufrua", - indexes = { - @Index(name = "bufrua_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "bufrua", indexes = { @Index(name = "bufrua_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class UAObs extends PersistablePluginDataObject implements - ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { + ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private static final Comparator corComparator = new Comparator() { - @Override - public int compare(UAObs a, UAObs b) { - int compValue = 0; - String wmoA = a.getWmoHeader(); - String wmoB = b.getWmoHeader(); + private static final Comparator corComparator = new Comparator() { + @Override + public int compare(UAObs a, UAObs b) { + int compValue = 0; + String wmoA = a.getWmoHeader(); + String wmoB = b.getWmoHeader(); - if (wmoA != null) { - if (wmoB != null) { - compValue = wmoA.compareTo(wmoB); - } - } - if (compValue != 0) { - compValue *= -1; - } - return compValue; - } - }; + if (wmoA != null) { + if (wmoB != null) { + compValue = wmoA.compareTo(wmoB); + } + } + if (compValue != 0) { + compValue *= -1; + } + return compValue; + } + }; - public static final Unit DISTANCE_UNIT = SI.METER; + public static final Unit DISTANCE_UNIT = SI.METER; - public static final Unit TEMPERATURE_UNIT = SI.KELVIN; + public static final Unit TEMPERATURE_UNIT = SI.KELVIN; - public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; + public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; - public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; - public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; - private static final HashMap PARM_MAP = new HashMap(); - static { - PARM_MAP.put("GH", UA_GEOHGT); - PARM_MAP.put("Px", UA_PRESSURE); + private static final HashMap PARM_MAP = new HashMap(); + static { + PARM_MAP.put("GH", UA_GEOHGT); + PARM_MAP.put("Px", UA_PRESSURE); - PARM_MAP.put("T", SFC_TEMP); - PARM_MAP.put("DpT", SFC_DWPT); + PARM_MAP.put("T", SFC_TEMP); + PARM_MAP.put("DpT", SFC_DWPT); - PARM_MAP.put("WS", SFC_WNDSPD); - PARM_MAP.put("WD", SFC_WNDDIR); + PARM_MAP.put("WS", SFC_WNDSPD); + PARM_MAP.put("WD", SFC_WNDDIR); - PARM_MAP.put("NLAT", STA_LAT); - PARM_MAP.put("NLON", STA_LON); - } + PARM_MAP.put("NLAT", STA_LAT); + PARM_MAP.put("NLON", STA_LON); + } - public static final String UA_PARAM_PTRN = ".*:PRESS=\\d{2,4}"; + public static final String UA_PARAM_PTRN = ".*:PRESS=\\d{2,4}"; - // Non persisted value. Hold the last requested parameter name. - @Transient - private String parameterName = null; + // Non persisted value. Hold the last requested parameter name. + @Transient + private String parameterName = null; - // Non persisted value. Hold the last requested level value. - @Transient - private Integer levelId; + // Non persisted value. Hold the last requested level value. + @Transient + private Integer levelId; // Time of the observation. @Column @@ -186,268 +183,268 @@ public class UAObs extends PersistablePluginDataObject implements @DynamicSerializeElement private Calendar refHour; - // The observation report type. - @DataURI(position = 1) - @Column - @XmlAttribute - @DynamicSerializeElement - private Integer reportType; + // The observation report type. + @DataURI(position = 1) + @Column + @XmlAttribute + @DynamicSerializeElement + private Integer reportType; - @Embedded - @DataURI(position = 4, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; + @Embedded + @DataURI(position = 4, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; - // Correction indicator from wmo header - @DataURI(position = 2) - @Column - @XmlAttribute - @DynamicSerializeElement - private String corIndicator; + // Correction indicator from wmo header + @DataURI(position = 2) + @Column + @XmlAttribute + @DynamicSerializeElement + private String corIndicator; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - // Text of the WMO header - @DataURI(position = 3) - @Column - @XmlAttribute - @DynamicSerializeElement - private String wmoHeader; + // Text of the WMO header + @DataURI(position = 3) + @Column + @XmlAttribute + @DynamicSerializeElement + private String wmoHeader; - // Station pressure in Pascals. - @Column - @XmlAttribute - @DynamicSerializeElement - private Integer pressure_station; + // Station pressure in Pascals. + @Column + @XmlAttribute + @DynamicSerializeElement + private Integer pressure_station; - // The total cloud cover in 1/8s coverage. - @Column - @XmlAttribute - @DynamicSerializeElement - private Integer totalCloudCover; + // The total cloud cover in 1/8s coverage. + @Column + @XmlAttribute + @DynamicSerializeElement + private Integer totalCloudCover; - // The platform directio in angular degrees. - @Column - @XmlAttribute - @DynamicSerializeElement - private Integer platformDirection; + // The platform directio in angular degrees. + @Column + @XmlAttribute + @DynamicSerializeElement + private Integer platformDirection; - // The platform movement in meters per second. - @Column - @XmlAttribute - @DynamicSerializeElement - private Double platformMovement; + // The platform movement in meters per second. + @Column + @XmlAttribute + @DynamicSerializeElement + private Double platformMovement; - // ICAO of station if known. - @Column - @XmlAttribute - @DynamicSerializeElement - private String stationName; + // ICAO of station if known. + @Column + @XmlAttribute + @DynamicSerializeElement + private String stationName; - // The level data for this observation. - @Transient - @XmlElement - @DynamicSerializeElement - private List levels; + // The level data for this observation. + @Transient + @XmlElement + @DynamicSerializeElement + private List levels; - @Column(insertable = false, updatable = false) - @XmlAttribute - @DynamicSerializeElement - private Integer idx; + @Column(insertable = false, updatable = false) + @XmlAttribute + @DynamicSerializeElement + private Integer idx; - public void setIdx(Integer idx) { - this.idx = idx; - } + public void setIdx(Integer idx) { + this.idx = idx; + } - public Integer getIdx() { - return idx; - } + public Integer getIdx() { + return idx; + } - /** - * Empty constructor. - */ - public UAObs() { - } + /** + * Empty constructor. + */ + public UAObs() { + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public UAObs(String uri) { - super(uri); - corIndicator = "null".equals(corIndicator) ? null : corIndicator; - if (location != null) { - String staId = location.getStationId(); - location.setStationId("null".equals(staId) ? null : staId); - } - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public UAObs(String uri) { + super(uri); + corIndicator = "null".equals(corIndicator) ? null : corIndicator; + if (location != null) { + String staId = location.getStationId(); + location.setStationId("null".equals(staId) ? null : staId); + } + } - /** - * Get the set of levels for this observation. - * - * @return The level data. - */ - public List getLevels() { - return levels; - } + /** + * Get the set of levels for this observation. + * + * @return The level data. + */ + public List getLevels() { + return levels; + } - /** - * Set the set of levels for this observation. - * - * @param levels - * the levels to set - */ - public void setLevels(List levels) { - this.levels = levels; - } + /** + * Set the set of levels for this observation. + * + * @param levels + * the levels to set + */ + public void setLevels(List levels) { + this.levels = levels; + } - /** - * - * @param cloud - */ - public void addLevel(UAObsLevel level) { - if (levels == null) { - levels = new ArrayList(); - } - levels.add(level); - } + /** + * + * @param cloud + */ + public void addLevel(UAObsLevel level) { + if (levels == null) { + levels = new ArrayList(); + } + levels.add(level); + } - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * Get the report correction indicator. - * - * @return The corIndicator - */ - public String getCorIndicator() { - return corIndicator; - } + /** + * Get the report correction indicator. + * + * @return The corIndicator + */ + public String getCorIndicator() { + return corIndicator; + } - /** - * Set the report correction indicator. - * - * @param corIndicator - * The corIndicator. - */ - public void setCorIndicator(String corIndicator) { - this.corIndicator = corIndicator; - } + /** + * Set the report correction indicator. + * + * @param corIndicator + * The corIndicator. + */ + public void setCorIndicator(String corIndicator) { + this.corIndicator = corIndicator; + } - /** - * Get the report data for this observation. - * - * @return The Report data. - */ - public String getReportData() { - String s = null; - if (messageData instanceof String) { - s = (String) messageData; - } - return s; - } + /** + * Get the report data for this observation. + * + * @return The Report data. + */ + public String getReportData() { + String s = null; + if (messageData instanceof String) { + s = (String) messageData; + } + return s; + } - /** - * Set the report data for this observation. - * - * @param reportData - * The Report data. - */ - public void setReportData(String reportData) { - messageData = reportData; - } + /** + * Set the report data for this observation. + * + * @param reportData + * The Report data. + */ + public void setReportData(String reportData) { + messageData = reportData; + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } - /** - * Get whether the location for this observation is defined. - * - * @return Is this location defined. - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } + /** + * Get whether the location for this observation is defined. + * + * @return Is this location defined. + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } - /** - * Get the observation report type. - * - * @return the reportType - */ - public Integer getReportType() { - return reportType; - } + /** + * Get the observation report type. + * + * @return the reportType + */ + public Integer getReportType() { + return reportType; + } - /** - * Set the observation report type. - * - * @param reportType - * the reportType to set - */ - public void setReportType(Integer reportType) { - this.reportType = reportType; + /** + * Set the observation report type. + * + * @param reportType + * the reportType to set + */ + public void setReportType(Integer reportType) { + this.reportType = reportType; } /** @@ -482,453 +479,459 @@ public class UAObs extends PersistablePluginDataObject implements */ public void setRefHour(Calendar refHour) { this.refHour = refHour; - } + } - /** - * Get the station pressure at the observation site. - * - * @return the pressure_station - */ - public Integer getPressure_station() { - return pressure_station; - } + /** + * Get the station pressure at the observation site. + * + * @return the pressure_station + */ + public Integer getPressure_station() { + return pressure_station; + } - /** - * Set the station pressure at the observation site. - * - * @param pressure_station - * the pressure_station to set - */ - public void setPressure_station(Integer pressure_station) { - this.pressure_station = pressure_station; - } + /** + * Set the station pressure at the observation site. + * + * @param pressure_station + * the pressure_station to set + */ + public void setPressure_station(Integer pressure_station) { + this.pressure_station = pressure_station; + } - /** - * Get the total clould cover (n/8s). - * - * @return the totalCloudCover - */ - public Integer getTotalCloudCover() { - return totalCloudCover; - } + /** + * Get the total clould cover (n/8s). + * + * @return the totalCloudCover + */ + public Integer getTotalCloudCover() { + return totalCloudCover; + } - /** - * Get the direction the platform is moving. (Valid only for mobile - * observations i.e. TEMPSHIP. - * - * @return the platformDirection - */ - public Integer getPlatformDirection() { - return platformDirection; - } + /** + * Get the direction the platform is moving. (Valid only for mobile + * observations i.e. TEMPSHIP. + * + * @return the platformDirection + */ + public Integer getPlatformDirection() { + return platformDirection; + } - /** - * Set the direction the platform is moving. (Valid only for mobile - * observations i.e. TEMPSHIP. - * - * @param platformDirection - * the platformDirection to set - */ - public void setPlatformDirection(Integer platformDirection) { - this.platformDirection = platformDirection; - } + /** + * Set the direction the platform is moving. (Valid only for mobile + * observations i.e. TEMPSHIP. + * + * @param platformDirection + * the platformDirection to set + */ + public void setPlatformDirection(Integer platformDirection) { + this.platformDirection = platformDirection; + } - /** - * Get the movement of the platform in meters per second. - * - * @return The platform movement in meters per second. - */ - public Double getPlatformMovement() { - return platformMovement; - } + /** + * Get the movement of the platform in meters per second. + * + * @return The platform movement in meters per second. + */ + public Double getPlatformMovement() { + return platformMovement; + } - /** - * Set the movement of the platform in meters per second. - * - * @param shipMovement - * The platform movement in meters per second. - */ - public void setPlatformMovement(Double platformMovement) { - this.platformMovement = platformMovement; - } + /** + * Set the movement of the platform in meters per second. + * + * @param shipMovement + * The platform movement in meters per second. + */ + public void setPlatformMovement(Double platformMovement) { + this.platformMovement = platformMovement; + } - /** - * Set the total clould cover (n/8s). - * - * @param totalCloudCover - * the totalCloudCover to set - */ - public void setTotalCloudCover(Integer totalCloudCover) { - this.totalCloudCover = totalCloudCover; - } + /** + * Set the total clould cover (n/8s). + * + * @param totalCloudCover + * the totalCloudCover to set + */ + public void setTotalCloudCover(Integer totalCloudCover) { + this.totalCloudCover = totalCloudCover; + } - /** - * @return the stationName - */ - public String getStationName() { - return stationName; - } + /** + * @return the stationName + */ + public String getStationName() { + return stationName; + } - /** - * @param stationName - * the stationName to set - */ - public void setStationName(String stationName) { - this.stationName = stationName; - } + /** + * @param stationName + * the stationName to set + */ + public void setStationName(String stationName) { + this.stationName = stationName; + } - /** - * Set the data uri for this observation. - * - * @param A - * data uri. - */ - @Override - public void setDataURI(String dataURI) { + /** + * Set the data uri for this observation. + * + * @param A + * data uri. + */ + @Override + public void setDataURI(String dataURI) { super.setDataURI(dataURI); - identifier = dataURI; - } + identifier = dataURI; + } - /** - * Get the IDecoderGettable reference for this record. - * - * @return The IDecoderGettable reference for this record. - */ - @Override - public IDecoderGettable getDecoderGettable() { - return this; - } + /** + * Get the IDecoderGettable reference for this record. + * + * @return The IDecoderGettable reference for this record. + */ + @Override + public IDecoderGettable getDecoderGettable() { + return this; + } - /** + /** * */ - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - /** + /** * */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public String getString(String paramName) { - if ("STA".matches(paramName)) { - return this.getStationId(); - } - return null; - } + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public String getString(String paramName) { + if ("STA".matches(paramName)) { + return this.getStationId(); + } + return null; + } - /** - * Get the value and units of a named parameter within this observation. The - * parameter name may include level information for these observation data. - * The format for parameter is: - * - *
-	 *    "parameterName" may be one of 
-	 *        "GH"  geopotential height
-	 *        "Px"  pressure
-	 *        "T"   temperature
-	 *        "DpT" dewpoint
-	 *        "WS"  wind speed
-	 *        "WD"  wind direction
-	 *    followed by a level specification ":PRESS=xxxx" where xxxx is a level
-	 *    in hPa (millibars). To retrieve the temperature from the 850hPa level
-	 *    use the following getValue("T:PRESS=850");
-	 *    
-	 *    Some data is specific to the observation, latitude/longitude for
-	 *    example. These data may be retrieved using the parameter minus any level
-	 *    information as follows
-	 *    "NLAT"  station latitude
-	 *    "NLON"  station longitude
-	 * 
- * - * If the sounding data defines a surface level, and a request for a level - * below surface is requested, a null value is returned. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return An Amount with value and units. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Amount getValue(String paramName) { - Amount a = null; + /** + * Get the value and units of a named parameter within this observation. The + * parameter name may include level information for these observation data. + * The format for parameter is: + * + *
+     *    "parameterName" may be one of 
+     *        "GH"  geopotential height
+     *        "Px"  pressure
+     *        "T"   temperature
+     *        "DpT" dewpoint
+     *        "WS"  wind speed
+     *        "WD"  wind direction
+     *    followed by a level specification ":PRESS=xxxx" where xxxx is a level
+     *    in hPa (millibars). To retrieve the temperature from the 850hPa level
+     *    use the following getValue("T:PRESS=850");
+     *    
+     *    Some data is specific to the observation, latitude/longitude for
+     *    example. These data may be retrieved using the parameter minus any level
+     *    information as follows
+     *    "NLAT"  station latitude
+     *    "NLON"  station longitude
+     * 
+ * + * If the sounding data defines a surface level, and a request for a level + * below surface is requested, a null value is returned. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return An Amount with value and units. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Amount getValue(String paramName) { + Amount a = null; - if (parseParameter(paramName)) { - String pName = PARM_MAP.get(parameterName); - if ((pName != null) && (levels != null) && (levels.size() > 0)) { + if (parseParameter(paramName)) { + String pName = PARM_MAP.get(parameterName); + if ((pName != null) && (levels != null) && (levels.size() > 0)) { - UAObsLevel obsLevel = getLevel(levelId); - if (obsLevel != null) { - Integer iValue = null; - Double dValue = null; - if (UA_GEOHGT.equals(pName)) { - iValue = obsLevel.getGeoHeight(); - if (iValue != null) { - a = new Amount(iValue, DISTANCE_UNIT); - } - } else if (SFC_TEMP.equals(pName)) { - dValue = obsLevel.getTemp(); - if (dValue != null) { - a = new Amount(dValue, TEMPERATURE_UNIT); - } - } else if (SFC_DWPT.equals(pName)) { - dValue = obsLevel.getDwpt(); - if (dValue != null) { - a = new Amount(dValue, TEMPERATURE_UNIT); - } - } else if (SFC_WNDSPD.equals(pName)) { - dValue = obsLevel.getWindSpeed(); - if (dValue != null) { - a = new Amount(dValue, WIND_SPEED_UNIT); - } - } else if (SFC_WNDDIR.equals(pName)) { - iValue = obsLevel.getWindDirection(); - if (iValue != null) { - a = new Amount(iValue, WIND_DIR_UNIT); - } - } - } - } - } else { - // Assume we are trying to get an observation attribute. - String pName = PARM_MAP.get(paramName); - if (STA_LAT.equals(pName)) { - a = new Amount(this.getLatitude(), LOCATION_UNIT); - } else if (STA_LON.equals(pName)) { - a = new Amount(this.getLongitude(), LOCATION_UNIT); - } - } - return a; - } + UAObsLevel obsLevel = getLevel(levelId); + if (obsLevel != null) { + Integer iValue = null; + Double dValue = null; + if (UA_GEOHGT.equals(pName)) { + iValue = obsLevel.getGeoHeight(); + if (iValue != null) { + a = new Amount(iValue, DISTANCE_UNIT); + } + } else if (SFC_TEMP.equals(pName)) { + dValue = obsLevel.getTemp(); + if (dValue != null) { + a = new Amount(dValue, TEMPERATURE_UNIT); + } + } else if (SFC_DWPT.equals(pName)) { + dValue = obsLevel.getDwpt(); + if (dValue != null) { + a = new Amount(dValue, TEMPERATURE_UNIT); + } + } else if (SFC_WNDSPD.equals(pName)) { + dValue = obsLevel.getWindSpeed(); + if (dValue != null) { + a = new Amount(dValue, WIND_SPEED_UNIT); + } + } else if (SFC_WNDDIR.equals(pName)) { + iValue = obsLevel.getWindDirection(); + if (iValue != null) { + a = new Amount(iValue, WIND_DIR_UNIT); + } + } + } + } + } else { + // Assume we are trying to get an observation attribute. + String pName = PARM_MAP.get(paramName); + if (STA_LAT.equals(pName)) { + a = new Amount(this.getLatitude(), LOCATION_UNIT); + } else if (STA_LON.equals(pName)) { + a = new Amount(this.getLongitude(), LOCATION_UNIT); + } + } + return a; + } - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Collection getValues(String paramName) { - return null; - } + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Collection getValues(String paramName) { + return null; + } - /** - * Determine if the parameter is a level request, and parse out the pressure - * level and parameter name if so. - * - * @param parameter - * The parameter string to parse. - * @return This is a level parameter. - */ - private boolean parseParameter(String parameter) { - boolean goodParse = false; - Pattern p = Pattern.compile(UA_PARAM_PTRN); - Matcher m = p.matcher(parameter); - if (m.find()) { - int start = parameter.indexOf(":PRESS="); - if (start > 0) { - parameterName = parameter.substring(0, start); - start += ":PRESS=".length(); - levelId = Integer.parseInt(parameter.substring(start)); - } - goodParse = true; - } - return goodParse; - } + /** + * Determine if the parameter is a level request, and parse out the pressure + * level and parameter name if so. + * + * @param parameter + * The parameter string to parse. + * @return This is a level parameter. + */ + private boolean parseParameter(String parameter) { + boolean goodParse = false; + Pattern p = Pattern.compile(UA_PARAM_PTRN); + Matcher m = p.matcher(parameter); + if (m.find()) { + int start = parameter.indexOf(":PRESS="); + if (start > 0) { + parameterName = parameter.substring(0, start); + start += ":PRESS=".length(); + levelId = Integer.parseInt(parameter.substring(start)); + } + goodParse = true; + } + return goodParse; + } - /** - * Get a specified pressure level data if it exists. If the specified level - * is below the declared surface pressure a null reference is returned. - * - * @param level - * A pressure level to get. - * @return The requested level, if found, null reference if not. - */ - private UAObsLevel getLevel(Integer level) { - UAObsLevel retValue = null; - if (level != null) { - level = level * 100; - for (UAObsLevel l : levels) { - if (IDecoderConstants.MANPRE_LEVEL.equals(l.getVertSig()) - || IDecoderConstants.SIGPRE_LEVEL - .equals(l.getVertSig())) { + /** + * Get a specified pressure level data if it exists. If the specified level + * is below the declared surface pressure a null reference is returned. + * + * @param level + * A pressure level to get. + * @return The requested level, if found, null reference if not. + */ + private UAObsLevel getLevel(Integer level) { + UAObsLevel retValue = null; + if (level != null) { + level = level * 100; + for (UAObsLevel l : levels) { + if (IDecoderConstants.MANPRE_LEVEL.equals(l.getVertSig()) + || IDecoderConstants.SIGPRE_LEVEL + .equals(l.getVertSig())) { - if (level.equals(l.getPressure())) { - retValue = l; - break; - } - } - } - } - if (retValue != null) { - UAObsLevel sfc = getSurfaceLevel(); - if (sfc != null) { - if (LayerTools.isLowerThan(sfc, retValue)) { - retValue = null; - } - } - } - return retValue; - } + if (level.equals(l.getPressure())) { + retValue = l; + break; + } + } + } + } + if (retValue != null) { + UAObsLevel sfc = getSurfaceLevel(); + if (sfc != null) { + if (LayerTools.isLowerThan(sfc, retValue)) { + retValue = null; + } + } + } + return retValue; + } - /** - * Get the defined surface level. If a surface level cannot be found, then - * return null. - * - * @return The surface level found, or null. - */ - private UAObsLevel getSurfaceLevel() { - UAObsLevel retValue = null; - if (levels != null) { - for (UAObsLevel level : levels) { - if (IDecoderConstants.SFC_LEVEL.equals(level.getVertSig())) { - retValue = level; - break; - } - } - } - return retValue; - } + /** + * Get the defined surface level. If a surface level cannot be found, then + * return null. + * + * @return The surface level found, or null. + */ + private UAObsLevel getSurfaceLevel() { + UAObsLevel retValue = null; + if (levels != null) { + for (UAObsLevel level : levels) { + if (IDecoderConstants.SFC_LEVEL.equals(level.getVertSig())) { + retValue = level; + break; + } + } + } + return retValue; + } - @Override - public String[] getStrings(String paramName) { - // TODO Auto-generated method stub - return null; - } + @Override + public String[] getStrings(String paramName) { + // TODO Auto-generated method stub + return null; + } - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } - public SurfaceObsLocation getLocation() { - if (location == null) { - location = new SurfaceObsLocation(); - } - return location; - } + public SurfaceObsLocation getLocation() { + if (location == null) { + location = new SurfaceObsLocation(); + } + return location; + } - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - /** - * Returns the hashCode for this object. This implementation returns the - * hashCode of the generated dataURI. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); - return result; - } + /** + * Returns the hashCode for this object. This implementation returns the + * hashCode of the generated dataURI. + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); + return result; + } - /** - * Checks if this record is equal to another by checking the generated - * dataURI. - * - * @param obj - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - UAObs other = (UAObs) obj; - if (getDataURI() == null) { - if (other.getDataURI() != null) { - return false; - } - } else if (!getDataURI().equals(other.getDataURI())) { - return false; - } - return true; - } + /** + * Checks if this record is equal to another by checking the generated + * dataURI. + * + * @param obj + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + UAObs other = (UAObs) obj; + if (getDataURI() == null) { + if (other.getDataURI() != null) { + return false; + } + } else if (!getDataURI().equals(other.getDataURI())) { + return false; + } + return true; + } - /** - * Returns a - * - * @param obsList - * @return - */ - public static final List sortByCorrection(List obsList) { + /** + * Returns a + * + * @param obsList + * @return + */ + public static final List sortByCorrection(List obsList) { - // No need to sort for null, empty, or one item. - if ((obsList != null) && (obsList.size() > 1)) { - Collections.sort(obsList, getCorComparator()); - } - return obsList; - } + // No need to sort for null, empty, or one item. + if ((obsList != null) && (obsList.size() > 1)) { + Collections.sort(obsList, getCorComparator()); + } + return obsList; + } - public static Comparator getCorComparator() { - return corComparator; - } + public static Comparator getCorComparator() { + return corComparator; + } - @Override - public String toString() { - return wmoHeader; - } + @Override + public String toString() { + return wmoHeader; + } - public static final void main(String[] args) { + public static final void main(String[] args) { - List obsList = new ArrayList(); - UAObs obsA = new UAObs(); - obsA.setWmoHeader("IUSZ42 KWBC 271845 CCA"); - obsList.add(obsA); - UAObs obsB = new UAObs(); - obsB.setWmoHeader("IUSZ42 KWBC 271835 CCA"); - obsList.add(obsB); - UAObs obs = new UAObs(); - obs.setWmoHeader("IUSZ42 KWBC 271815"); - obsList.add(obs); - obs = new UAObs(); - obs.setWmoHeader("IUSZ42 KWBC 271825 CCA"); - obsList.add(obs); + List obsList = new ArrayList(); + UAObs obsA = new UAObs(); + obsA.setWmoHeader("IUSZ42 KWBC 271845 CCA"); + obsList.add(obsA); + UAObs obsB = new UAObs(); + obsB.setWmoHeader("IUSZ42 KWBC 271835 CCA"); + obsList.add(obsB); + UAObs obs = new UAObs(); + obs.setWmoHeader("IUSZ42 KWBC 271815"); + obsList.add(obs); + obs = new UAObs(); + obs.setWmoHeader("IUSZ42 KWBC 271825 CCA"); + obsList.add(obs); - System.out.println(obsList); - obsList = sortByCorrection(obsList); - System.out.println(obsList); + System.out.println(obsList); + obsList = sortByCorrection(obsList); + System.out.println(obsList); - int c = UAObs.getCorComparator().compare(obsA, obsB); - System.out.println(c); + int c = UAObs.getCorComparator().compare(obsA, obsB); + System.out.println(c); - UAObs test = new UAObs( - "/bufrua/2011-10-07_00:00:00.0/2022/null/IUSZ52_KWBC_070040/72634/44.90833/-84.71944"); + UAObs test = new UAObs( + "/bufrua/2011-10-07_00:00:00.0/2022/null/IUSZ52_KWBC_070040/72634/44.90833/-84.71944"); - System.out.println(test.dataURI); + System.out.println(test.dataURI); + + } - } @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "bufrua"; + } } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.cwa/src/com/raytheon/uf/common/dataplugin/cwa/CWARecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.cwa/src/com/raytheon/uf/common/dataplugin/cwa/CWARecord.java index 58f715f75b..4a372e7c0e 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.cwa/src/com/raytheon/uf/common/dataplugin/cwa/CWARecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.cwa/src/com/raytheon/uf/common/dataplugin/cwa/CWARecord.java @@ -56,11 +56,13 @@ import com.vividsolutions.jts.geom.Coordinate; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Feb 1, 2010 jsanchez Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Feb 01, 2010 jsanchez Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -74,132 +76,134 @@ import com.vividsolutions.jts.geom.Coordinate; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "cwa", - indexes = { - @Index(name = "cwa_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "cwa", indexes = { @Index(name = "cwa_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class CWARecord extends PersistablePluginDataObject implements - IPointData, IPersistable { + IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - // Text of the WMO header - @Transient - @XmlElement - @DynamicSerializeElement - private String wmoHeader = ""; + // Text of the WMO header + @Transient + @XmlElement + @DynamicSerializeElement + private String wmoHeader = ""; - @Transient - @XmlElement - @DynamicSerializeElement - private CWADimension dimension; + @Transient + @XmlElement + @DynamicSerializeElement + private CWADimension dimension; - @DataURI(position = 1, embedded = true) - @XmlElement - @DynamicSerializeElement - private String eventId; + @DataURI(position = 1, embedded = true) + @XmlElement + @DynamicSerializeElement + private String eventId; - @Transient - @XmlElement - @DynamicSerializeElement - private Coordinate[] coordinates; + @Transient + @XmlElement + @DynamicSerializeElement + private Coordinate[] coordinates; - @Transient - @XmlElement - @DynamicSerializeElement - private String text; + @Transient + @XmlElement + @DynamicSerializeElement + private String text; - public CWADimension getDimension() { - return dimension; - } + public CWADimension getDimension() { + return dimension; + } - public void setDimension(CWADimension dimension) { - this.dimension = dimension; - } + public void setDimension(CWADimension dimension) { + this.dimension = dimension; + } - public String getWmoHeader() { - return wmoHeader; - } + public String getWmoHeader() { + return wmoHeader; + } - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - public Coordinate[] getCoordinates() { - return coordinates; - } + public Coordinate[] getCoordinates() { + return coordinates; + } - public void setCoordinates(Coordinate[] coordinates) { - this.coordinates = coordinates; - } + public void setCoordinates(Coordinate[] coordinates) { + this.coordinates = coordinates; + } - public String getEventId() { - return eventId; - } + public String getEventId() { + return eventId; + } - public void setEventId(String eventId) { - this.eventId = eventId; - } + public void setEventId(String eventId) { + this.eventId = eventId; + } - /** - * Set the data uri for this observation. - * - * @param dataURI - */ - @Override - public void setDataURI(String dataURI) { - super.setDataURI(dataURI); - identifier = dataURI; - } + /** + * Set the data uri for this observation. + * + * @param dataURI + */ + @Override + public void setDataURI(String dataURI) { + super.setDataURI(dataURI); + identifier = dataURI; + } - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } - public String getText() { - return text; - } + public String getText() { + return text; + } - public void setText(String text) { - this.text = text; - } + public void setText(String text) { + this.text = text; + } - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Calendar c = getDataTime().getRefTimeAsCalendar(); + if (c != null) { + sb.append(String.format("CWA:%1$tY%1$tm%1$td%1$tH%1$tM", + getDataTime().getRefTimeAsCalendar())); + } else { + sb.append("CWA:YYYYMMDDHHmm"); + } + return sb.toString(); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - Calendar c = getDataTime().getRefTimeAsCalendar(); - if (c != null) { - sb.append(String.format("CWA:%1$tY%1$tm%1$td%1$tH%1$tM", - getDataTime().getRefTimeAsCalendar())); - } else { - sb.append("CWA:YYYYMMDDHHmm"); - } - return sb.toString(); - } @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "cwa"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.cwat/src/com/raytheon/uf/common/dataplugin/cwat/CWATRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.cwat/src/com/raytheon/uf/common/dataplugin/cwat/CWATRecord.java index 8de22de896..ff8fa266ce 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.cwat/src/com/raytheon/uf/common/dataplugin/cwat/CWATRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.cwat/src/com/raytheon/uf/common/dataplugin/cwat/CWATRecord.java @@ -73,12 +73,14 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 06/03/09 2037 D. Hladky Initial release - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 04/08/13 1293 bkowal Removed references to hdffileid. - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Jun 03, 2009 2037 D. Hladky Initial release + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -452,9 +454,9 @@ public class CWATRecord extends PersistablePluginDataObject try { IDataRecord[] dataRec = dataStore.retrieve(getDataURI()); - for (int i = 0; i < dataRec.length; i++) { - if (dataRec[i] instanceof ShortDataRecord) { - setDataArray(((ShortDataRecord) dataRec[i]).getShortData()); + for (IDataRecord element : dataRec) { + if (element instanceof ShortDataRecord) { + setDataArray(((ShortDataRecord) element).getShortData()); } } retrieveMapFromDataStore(dataStore); @@ -574,4 +576,9 @@ public class CWATRecord extends PersistablePluginDataObject public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "cwat"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPRecord.java index 139a2b9826..f00d3f8b0d 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPRecord.java @@ -77,18 +77,22 @@ import com.raytheon.uf.common.time.util.ImmutableDate; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 06/03/09 2521 D. Hladky Initial release - * 01/27/13 1478 D. Hladky OUN memory help - * Feb 28, 2013 1729 dhladky Supressed un-necessary debug loggers - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 8, 2013 1293 bkowal Removed references to hdffileid. - * April, 9 2013 1890 dhladky Moved dates to referenced map in record rather than multiple dates in FFMPBasin objs. + * Jun 03, 2009 2521 D. Hladky Initial release + * Jan 27, 2013 1478 D. Hladky OUN memory help + * Feb 28, 2013 1729 dhladky Supressed un-necessary debug loggers + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. + * April, 9 2013 1890 dhladky Moved dates to referenced map in record + * rather than multiple dates in + * FFMPBasin objs. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * Apr 16, 2013 1912 bsteffen Initial bulk hdf5 access for ffmp - * Apr 18, 2013 1919 dhladky Added method for VGB loading + * Apr 18, 2013 1919 dhladky Added method for VGB loading * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * Jul 15, 2013 2184 dhladky Remove all HUC's for storage except ALL + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -102,18 +106,13 @@ import com.raytheon.uf.common.time.util.ImmutableDate; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ffmp", - indexes = { - @Index(name = "ffmp_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) - +@org.hibernate.annotations.Table(appliesTo = "ffmp", indexes = { @Index(name = "ffmp_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public class FFMPRecord extends PersistablePluginDataObject - implements IPersistable { +public class FFMPRecord extends PersistablePluginDataObject implements + IPersistable { private static final long serialVersionUID = 76774564365671L; @@ -273,8 +272,8 @@ public class FFMPRecord extends PersistablePluginDataObject String unit = null; if (field == FIELDS.RATE) { unit = "in/hr"; - } else if (field == FIELDS.QPE || field == FIELDS.QPF - || field == FIELDS.GUIDANCE || field == FIELDS.DIFF) { + } else if ((field == FIELDS.QPE) || (field == FIELDS.QPF) + || (field == FIELDS.GUIDANCE) || (field == FIELDS.DIFF)) { unit = "in"; } else if (field == FIELDS.RATIO) { unit = "%"; @@ -394,7 +393,7 @@ public class FFMPRecord extends PersistablePluginDataObject LinkedHashMap map = template.getMap(getSiteKey(), domain.getCwa(), FFMPRecord.ALL); - if (map != null && !map.isEmpty()) { + if ((map != null) && !map.isEmpty()) { fbd.addBasins(datastoreFile, uri, getSiteKey(), domain.getCwa(), FFMPRecord.ALL, sourceName, idate, map.keySet(), aggregate); @@ -446,7 +445,7 @@ public class FFMPRecord extends PersistablePluginDataObject LinkedHashMap map = template.getMap(getSiteKey(), domain.getCwa(), huc); - if (map != null && map.get(pfaf) != null) { + if ((map != null) && (map.get(pfaf) != null)) { int index = 0; for (Long pfafToCheck : map.keySet()) { @@ -696,4 +695,9 @@ public class FFMPRecord extends PersistablePluginDataObject public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ffmp"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.fog/src/com/raytheon/uf/common/dataplugin/fog/FogRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.fog/src/com/raytheon/uf/common/dataplugin/fog/FogRecord.java index 137c5a7b06..a2314248a7 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.fog/src/com/raytheon/uf/common/dataplugin/fog/FogRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.fog/src/com/raytheon/uf/common/dataplugin/fog/FogRecord.java @@ -62,12 +62,14 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 12/12/09 D. Hladky Initial release - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 04/08/13 1293 bkowal Removed references to hdffileid. + * Dec 12, 2009 D. Hladky Initial release + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -81,17 +83,13 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "fog", - indexes = { - @Index(name = "fog_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "fog", indexes = { @Index(name = "fog_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public class FogRecord extends PersistablePluginDataObject - implements IPersistable { +public class FogRecord extends PersistablePluginDataObject implements + IPersistable { private static final long serialVersionUID = 76774564365671L; @@ -429,14 +427,14 @@ public class FogRecord extends PersistablePluginDataObject } public GridGeometry2D getGridGeometry2D() { - return gridGeometry2D; - } + return gridGeometry2D; + } - public void setGridGeometry2D(GridGeometry2D gridGeometry2D) { - this.gridGeometry2D = gridGeometry2D; - } + public void setGridGeometry2D(GridGeometry2D gridGeometry2D) { + this.gridGeometry2D = gridGeometry2D; + } - /** + /** * Set the VIS pixel array * * @param data_array @@ -652,28 +650,31 @@ public class FogRecord extends PersistablePluginDataObject // then means both vis_range and ir_range store range of vis if (getRangeType(j) == IMAGE_GROUP.TWILIGHT_GROUP) { - if (i <= getVisRange(j).getEnd() && i >= getVisRange(j).getStart()) { + if ((i <= getVisRange(j).getEnd()) + && (i >= getVisRange(j).getStart())) { return IMAGE_GROUP.VIS_GROUP; } - else if (i <= getIRRange(j).getEnd() - && i >= getIRRange(j).getStart()) { + else if ((i <= getIRRange(j).getEnd()) + && (i >= getIRRange(j).getStart())) { return IMAGE_GROUP.IR_GROUP; } else { return IMAGE_GROUP.TWILIGHT_GROUP; } } else if (getRangeType(j) == IMAGE_GROUP.VIS_GROUP) { - if ((i <= getVisRange(j).getEnd() && i >= getVisRange(j).getStart()) - || (i <= getIRRange(j).getEnd() && i >= getIRRange(j) - .getStart())) { + if (((i <= getVisRange(j).getEnd()) && (i >= getVisRange(j) + .getStart())) + || ((i <= getIRRange(j).getEnd()) && (i >= getIRRange(j) + .getStart()))) { return IMAGE_GROUP.VIS_GROUP; } else { return IMAGE_GROUP.TWILIGHT_GROUP; } } else { - if ((i <= getVisRange(j).getEnd() && i >= getVisRange(j).getStart()) - || (i <= getIRRange(j).getEnd() && i >= getIRRange(j) - .getStart())) { + if (((i <= getVisRange(j).getEnd()) && (i >= getVisRange(j) + .getStart())) + || ((i <= getIRRange(j).getEnd()) && (i >= getIRRange(j) + .getStart()))) { return IMAGE_GROUP.IR_GROUP; } else { return IMAGE_GROUP.TWILIGHT_GROUP; @@ -704,10 +705,16 @@ public class FogRecord extends PersistablePluginDataObject public Calendar getRefHour() { return refHour; } + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "fog"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.fssobs/src/com/raytheon/uf/common/dataplugin/fssobs/FSSObsRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.fssobs/src/com/raytheon/uf/common/dataplugin/fssobs/FSSObsRecord.java index 3d9e1d9dd1..8389e5d301 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.fssobs/src/com/raytheon/uf/common/dataplugin/fssobs/FSSObsRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.fssobs/src/com/raytheon/uf/common/dataplugin/fssobs/FSSObsRecord.java @@ -26,6 +26,7 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; + import org.hibernate.annotations.Index; import com.raytheon.uf.common.dataplugin.IDecoderGettable; @@ -48,1219 +49,1187 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "fssobs", - indexes = { - @Index(name = "fssobs_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "fssobs", indexes = { @Index(name = "fssobs_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class FSSObsRecord extends PersistablePluginDataObject implements - ISpatialEnabled, IDecoderGettable, IPersistable, IPointData { + ISpatialEnabled, IDecoderGettable, IPersistable, IPointData { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public static final String PLUGIN_NAME = "fssobs"; + public static final String PLUGIN_NAME = "fssobs"; - private static final int MISSING = -9999; + private static final int MISSING = -9999; - // UNITS + // UNITS - public static final Unit TEMPERATURE_UNIT = SI.CELSIUS; + public static final Unit TEMPERATURE_UNIT = SI.CELSIUS; - public static final Unit WIND_SPEED_UNIT = NonSI.KNOT; + public static final Unit WIND_SPEED_UNIT = NonSI.KNOT; - public static final Unit HEIGHT_UNIT = SI.METER; + public static final Unit HEIGHT_UNIT = SI.METER; - public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; - public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; - public static final Unit PRESSURE_UNIT = SI.HECTO(SI.PASCAL); + public static final Unit PRESSURE_UNIT = SI.HECTO(SI.PASCAL); - public static final Unit PRECIP_UNIT = NonSI.INCH; + public static final Unit PRECIP_UNIT = NonSI.INCH; - public static final Unit WAVE_UNIT = SI.METER; + public static final Unit WAVE_UNIT = SI.METER; - public static final Unit VISIBILITY_UNIT = NonSI.MILE; + public static final Unit VISIBILITY_UNIT = NonSI.MILE; - public static final Unit CLOUD_COVER = NonSI.OCTET; + public static final Unit CLOUD_COVER = NonSI.OCTET; - /** Metar specific parameter keys */ - public static final class ParameterKey { - public static final String SFC_ALTIMETER = "SFC.PRESS.ALTIMETER"; + /** Metar specific parameter keys */ + public static final class ParameterKey { + public static final String SFC_ALTIMETER = "SFC.PRESS.ALTIMETER"; - public static final String PRESSURE_CHANGE = "PCHNG"; + public static final String PRESSURE_CHANGE = "PCHNG"; - public static final String VISIBILITY = "VIS"; + public static final String VISIBILITY = "VIS"; - public static final String PRECIPITATION_1HR = "PR1HR"; - } + public static final String PRECIPITATION_1HR = "PR1HR"; + } - private static final HashMap PARM_MAP = new HashMap(); - static { - PARM_MAP.put("NLAT", STA_LAT); - PARM_MAP.put("NLON", STA_LON); - PARM_MAP.put("rawMessage", "rawMessage"); - } - - /** is feature new **/ - @Transient - @DynamicSerializeElement - @XmlElement - public boolean isNew = true; - - // Current CWA (WFO) - @Column - @DataURI(position = 2) - @DynamicSerializeElement - @XmlElement(nillable = false) - private String cwa; - - // Monitor which should use this station record - // fog = "fog" - // safeseas = "ss" - // snow = "snow" - @Column - @DataURI(position = 4) - @DynamicSerializeElement - @XmlElement - private String monitorUse = ""; - - // Station name - @Column - @DynamicSerializeElement - @XmlElement - private String stnName; - - /* From ============ObReport================= */ - - @XmlElement - @DynamicSerializeElement - @Column - @DataURI(position = 1) - protected String reportType; - - @Embedded - @DataURI(position = 3, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; - - // Observing platform identifier (same as stationID) - @Transient - @XmlElement - @DynamicSerializeElement - private String platformId; - - // Indicator of whether observing platform is stationary - @Transient - @DynamicSerializeElement - @XmlElement - private boolean isStationary; - - // Actual time of the observation - @Transient - @DynamicSerializeElement - @XmlElement - private Calendar timeObs; - - // Time of the observation to the nearest hour. - @XmlElement - @DynamicSerializeElement - @Column - private Calendar refHour; - - // Raw message - @Transient - @DynamicSerializeElement - @XmlElement - private String rawMessage; - - // Observed wind speed in knots - @Transient - @DynamicSerializeElement - @XmlElement - private float windSpeed = -9999;; - - // Wind gust in knots - @Transient - @DynamicSerializeElement - @XmlElement - private float windGust = -9999;; - - // Observed maximum wind speed in knots - @Transient - @DynamicSerializeElement - @XmlElement - private float maxWindSpeed = -9999; - - // Observed wind direction in azimuth degrees - @Transient - @DynamicSerializeElement - @XmlElement - private float windDir; - - // Observed wind chill in Fahrenheit - @Transient - @DynamicSerializeElement - @XmlElement - private float windChill = -9999; - - // Observed high resolution wave height in - @Transient - @DynamicSerializeElement - @XmlElement - private float highResWaveHeight = -9999; - - // Observed wave steepness in seconds ??? None - @Transient - @DynamicSerializeElement - @XmlElement - private float waveSteepness = -9999; - - // Observed visibility in Statute miles - @Transient - @DynamicSerializeElement - @XmlElement - private float visibility = -9999; - - // Observed visibility in meters for Maritime obs. - @Transient - @DynamicSerializeElement - @XmlElement - private float horzVisibility = -9999; - - // Observed temperature in degrees in Farenheit - @Transient - @DynamicSerializeElement - @XmlElement - private float temperature = -9999; - - // in feet - @Transient - @XmlElement - @DynamicSerializeElement - private Double waveHeight = -9999.0; - - // in seconds - @Transient - @XmlElement - @DynamicSerializeElement - private Integer wavePeriod = -9999; - - // in Azimuth degrees - @Transient - @XmlElement - @DynamicSerializeElement - private Double primarySwellWaveDir = -9999.0; - - // in seconds - @Transient - @XmlElement - @DynamicSerializeElement - private Integer primarySwellWavePeriod = -9999; - - // in feet - @Transient - @XmlElement - @DynamicSerializeElement - private Double primarySwellWaveHeight = -9999.0; - - // in Azimuth degrees - @Transient - @XmlElement - @DynamicSerializeElement - private Double secondarySwellWaveDir = -9999.0; - - // in seconds - @Transient - @XmlElement - @DynamicSerializeElement - private Integer secondarySwellWavePeriod = -9999; - - // in feet - @Transient - @XmlElement - @DynamicSerializeElement - private Double secondarySwellWaveHeight = -9999.0; - - // // Pressure in inches of mercury - // @Transient - // @DynamicSerializeElement - // @XmlElement - // private float pressure = -9999; - - // Three-hour pressure change in thousandths of an inch of mercury ???? - @Transient - @DynamicSerializeElement - @XmlElement - private float pressChange3Hour = -9999f; - - // Pressure change character for metar plot model - /** A string denoting the pressure tendency(rising or falling) */ - @Transient - @DynamicSerializeElement - @XmlElement - private String pressChangeChar; - - // Observed dewpoint in degrees Farenheit - @Transient - @DynamicSerializeElement - @XmlElement - private float dewpoint = -9999f; - - // Observed sea surface temperature in degrees in Farenheit - @Transient - @DynamicSerializeElement - @XmlElement - private float seaSurfaceTemp = -9999f; - - // the sea level pressure in hPa - @XmlElement - @DynamicSerializeElement - @Transient - private float seaLevelPress = -9999f; - - // Altimeter setting in mm Hg. - @Transient - @XmlElement - @DynamicSerializeElement - private float pressureAltimeter = -9999f; - - // Observed hourly precipitation in inches - @Transient - @DynamicSerializeElement - @XmlElement - private float hourlyPrecip = -9999f; - - // Observed snow depth in inch - @Transient - @DynamicSerializeElement - @XmlElement - private float snowDepth = -9999f; - - // Observed snow increasing rapidly, hourly total in inches - @Transient - @DynamicSerializeElement - @XmlElement - private float snincrHourly = -9999f; - - // Observed snow increasing rapidly, total in inches - @Transient - @DynamicSerializeElement - @XmlElement - private float snincrTotal = -9999f; - - // Observed frostbite time in minutes - @Transient - @DynamicSerializeElement - @XmlElement - private float frostbiteTime; - - // present weather conditions for metar plot model - @Transient - @DynamicSerializeElement - @XmlElement - private String[] presWeather; - - // Observed relative humidity in percent - @Transient - @DynamicSerializeElement - @XmlElement - private float relativeHumidity = -9999f; - - // Observed ceiling in feet above ground level - @Transient - @DynamicSerializeElement - @XmlElement - private float ceiling = -9999f; - - // Observed dewpoint depression in Farenheit - @Transient - @DynamicSerializeElement - @XmlElement - private float dewpointDepr = -9999f; - - @XmlElement - @DynamicSerializeElement - @Transient - private String[] skyCover; - - @XmlElement - @DynamicSerializeElement - @Transient - private int totCloudAmount = -9999; - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - // ---------------------------------------------------------------------------------------------------- - public FSSObsRecord() { - } - - public FSSObsRecord(String uri) { - super(uri); - } - - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } - - @Override - public Amount getValue(String paramName) { - Amount a = null; - - String pName = PARM_MAP.get(paramName); - - if (SFC_TEMP.equals(pName) && (temperature != -9999f)) { - a = new Amount(temperature, TEMPERATURE_UNIT); - } else if (SFC_DWPT.equals(pName) && (dewpoint != -9999f)) { - a = new Amount(dewpoint, TEMPERATURE_UNIT); - } else if (SFC_WNDSPD.equals(pName) && (windSpeed != -9999f)) { - a = new Amount(windSpeed, WIND_SPEED_UNIT); - } else if (SFC_WNDDIR.equals(pName) && (windDir != -9999f)) { - a = new Amount(windDir, WIND_DIR_UNIT); - } else if (SFC_WNDGST.equals(pName) && (windGust != -9999f)) { - a = new Amount(windGust, WIND_SPEED_UNIT); - } else if (PRES_SLP.equals(pName) && (seaLevelPress != -9999f)) { - a = new Amount(seaLevelPress, PRESSURE_UNIT); - // } else if (PRES_ALTSG.equals(pName) && (pressureAltimeter != - // -9999f)) { - // a = new Amount(pressureAltimeter, PRESSURE_UNIT); - } else if (STA_LAT.equals(pName)) { - a = new Amount(this.getLatitude(), LOCATION_UNIT); - } else if (STA_LON.equals(pName)) { - a = new Amount(this.getLongitude(), LOCATION_UNIT); - } else if ("WT".equals(pName) && this.seaSurfaceTemp != -9999f) { - a = new Amount(this.seaSurfaceTemp, TEMPERATURE_UNIT); - } else if ("WH".equals(pName)) { - a = new Amount(waveHeight, WAVE_UNIT); - } else if ("SWP".equals(pName)) { - a = new Amount(primarySwellWavePeriod, WAVE_UNIT); - } else if ("SWH".equals(pName)) { - a = new Amount(primarySwellWaveHeight, WAVE_UNIT); - // } else if ("PCHNG".equals(pName) && pressChange3Hour != MISSING) - // { - // a = new Amount(pressChange3Hour, PRESSURE_UNIT); - } else if ("PKWND".equals(paramName) && maxWindSpeed != MISSING) { - a = new Amount(maxWindSpeed, WIND_SPEED_UNIT); - } else if ("SWS".equals(paramName) || "SWGS".equals(paramName)) { - a = new Amount(1, WIND_SPEED_UNIT); - } else if ("SWD".equals(paramName) && primarySwellWaveDir != MISSING) { - a = new Amount(primarySwellWaveDir, WIND_DIR_UNIT); - } - - return a; - } - - /** - * @return the isNew - */ - public boolean getIsNew() { - return isNew; - } - - /** - * @return the cwa - */ - public String getCwa() { - return cwa; - } - - /** - * @param monitorUse - * the monitorUse to set - */ - public void setMonitorUse(String monitorUse) { - this.monitorUse = monitorUse; - } - - /** - * @return the monitorUse - */ - public String getMonitorUse() { - return monitorUse; - } - - /** - * @return the stnName - */ - public String getStnName() { - return stnName; - } - - /** - * @return the reportType - */ - public String getReportType() { - return reportType; - } - - /** - * @return the location - */ - public SurfaceObsLocation getLocation() { - return location; - } - - /** - * @param platformId - * the platformId to set - */ - public void setPlatformId(String platformId) { - this.platformId = platformId; - } - - /** - * @return the platformId - */ - public String getPlatformId() { - return platformId; - } - - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } - - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } - - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } - - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } - - /** - * @return the isStationary - */ - public boolean isStationary() { - return isStationary; - } - - /** - * @return the refHour - */ - public Calendar getRefHour() { - return refHour; - } - - /** - * @return the rawMessage - */ - public String getRawMessage() { - return rawMessage; - } - - /** - * @return the windSpeed - */ - public float getWindSpeed() { - return windSpeed; - } - - /** - * @return the windGust - */ - public float getWindGust() { - return windGust; - } - - /** - * @return the maxWindSpeed - */ - public float getMaxWindSpeed() { - return maxWindSpeed; - } - - /** - * @return the windDir - */ - public float getWindDir() { - return windDir; - } - - /** - * @return the windChill - */ - public float getWindChill() { - return windChill; - } - - // /** - // * @return the highResWaveHeight - // */ - // public float getHighResWaveHeight() { - // return highResWaveHeight; - // } - - /** - * @return the waveSteepness - */ - public float getWaveSteepness() { - return waveSteepness; - } - - /** - * @return the visibility - */ - public float getVisibility() { - return visibility; - } - - /** - * @return the temperature - */ - public float getTemperature() { - return temperature; - } - - /** - * @return the waveHeight - */ - public Double getWaveHeight() { - return waveHeight; - } - - /** - * @return the wavePeriod - */ - public Integer getWavePeriod() { - return wavePeriod; - } - - /** - * @return the primarySwellWaveDir - */ - public Double getPrimarySwellWaveDir() { - return primarySwellWaveDir; - } - - /** - * @return the primarySwellWavePeriod - */ - public Integer getPrimarySwellWavePeriod() { - return primarySwellWavePeriod; - } - - /** - * @return the primarySwellWaveHeight - */ - public Double getPrimarySwellWaveHeight() { - return primarySwellWaveHeight; - } - - /** - * @return the secondarySwellWaveDir - */ - public Double getSecondarySwellWaveDir() { - return secondarySwellWaveDir; - } - - /** - * @return the secondarySwellWavePeriod - */ - public Integer getSecondarySwellWavePeriod() { - return secondarySwellWavePeriod; - } - - /** - * @return the secondarySwellWaveHeight - */ - public Double getSecondarySwellWaveHeight() { - return secondarySwellWaveHeight; - } - - // /** - // * @return the pressure - // */ - // public float getPressure() { - // return pressure; - // } - // - // - // /** - // * @return the pressChangeChar - // */ - // public String getPressChangeChar() { - // return pressChangeChar; - // } - - /** - * @return the dewpoint - */ - public float getDewpoint() { - return dewpoint; - } - - /** - * @return the seaSurfaceTemp - */ - public float getSeaSurfaceTemp() { - return seaSurfaceTemp; - } - - /** - * @return the seaLevelPress - */ - public float getSeaLevelPress() { - return seaLevelPress; - } - - /** - * @param pressureAltimeter - * the pressureAltimeter to set - */ - public void setPressureAltimeter(float pressureAltimeter) { - this.pressureAltimeter = pressureAltimeter; - } - - /** - * @return the pressureAltimeter - */ - public float getPressureAltimeter() { - return pressureAltimeter; - } - - /** - * @param pressChange3Hour - * the pressChange3Hour to set - */ - public void setPressChange3Hour(float pressChange3Hour) { - this.pressChange3Hour = pressChange3Hour; - } - - /** - * @return the pressChange3Hour - */ - public float getPressChange3Hour() { - return pressChange3Hour; - } - - /** - * @return the snowDepth - */ - public float getSnowDepth() { - return snowDepth; - } - - /** - * @return the snincrHourly - */ - public float getSnincrHourly() { - return snincrHourly; - } - - /** - * @return the snincrTotal - */ - public float getSnincrTotal() { - return snincrTotal; - } - - /** - * @return the frostbiteTime - */ - public float getFrostbiteTime() { - return frostbiteTime; - } - - /** - * @return the relativeHumidity - */ - public float getRelativeHumidity() { - return relativeHumidity; - } - - /** - * @param ceiling - * the ceiling to set - */ - public void setCeiling(float ceiling) { - this.ceiling = ceiling; - } - - /** - * @return the ceiling - */ - public float getCeiling() { - return ceiling; - } - - /** - * @return the dewpointDepr - */ - public float getDewpointDepr() { - return dewpointDepr; - } - - /** - * @param isNew - * the isNew to set - */ - public void setIsNew(boolean isNew) { - this.isNew = isNew; - } - - /** - * @param cwa - * the cwa to set - */ - public void setCwa(String cwa) { - this.cwa = cwa; - } - - /** - * @param stnName - * the stnName to set - */ - public void setStnName(String stnName) { - this.stnName = stnName; - } - - /** - * @param reportType - * the reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } - - /** - * @param location - * the location to set - */ - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - /** - * @param isStationary - * the isStationary to set - */ - public void setIsStationary(boolean isStationary) { - this.isStationary = isStationary; - } - - public boolean getIsStationary() { - return isStationary; - } - - /** - * @param timeObs - * the timeObs to set - */ - public void setTimeObs(Calendar timeObs) { - this.timeObs = timeObs; - } - - /** - * @return the timeObs - */ - public Calendar getTimeObs() { - return timeObs; - } - - /** - * @param refHour - * the refHour to set - */ - public void setRefHour(Calendar refHour) { - this.refHour = refHour; - } - - /** - * @param rawMessage - * the rawMessage to set - */ - public void setRawMessage(String rawMessage) { - this.rawMessage = rawMessage; - } - - /** - * @param windSpeed - * the windSpeed to set - */ - public void setWindSpeed(float windSpeed) { - this.windSpeed = windSpeed; - } - - /** - * @param windGust - * the windGust to set - */ - public void setWindGust(float windGust) { - this.windGust = windGust; - } - - /** - * @param maxWindSpeed - * the maxWindSpeed to set - */ - public void setMaxWindSpeed(float maxWindSpeed) { - this.maxWindSpeed = maxWindSpeed; - } - - /** - * @param windDir - * the windDir to set - */ - public void setWindDir(float windDir) { - this.windDir = windDir; - } - - /** - * @param windChill - * the windChill to set - */ - public void setWindChill(float windChill) { - this.windChill = windChill; - } - - public void setHighResWaveHeight(float highResWaveHeight) { - this.highResWaveHeight = highResWaveHeight; - } - - public float getHighResWaveHeight() { - return highResWaveHeight; - } - - /** - * @param waveSteepness - * the waveSteepness to set - */ - public void setWaveSteepness(float waveSteepness) { - this.waveSteepness = waveSteepness; - } - - /** - * @param visibility - * the visibility to set - */ - public void setVisibility(float visibility) { - this.visibility = visibility; - } - - /** - * @param horzVisibility - * the horzVisibility to set - */ - public void setHorzVisibility(float horzVisibility) { - this.horzVisibility = horzVisibility; - } - - /** - * @return the horzVisibility - */ - public float getHorzVisibility() { - return horzVisibility; - } - - /** - * @param temperature - * the temperature to set - */ - public void setTemperature(float temperature) { - this.temperature = temperature; - } - - /** - * @param waveHeight - * the waveHeight to set - */ - public void setWaveHeight(Double waveHeight) { - this.waveHeight = waveHeight; - } - - /** - * @param wavePeriod - * the wavePeriod to set - */ - public void setWavePeriod(Integer wavePeriod) { - this.wavePeriod = wavePeriod; - } - - /** - * @param primarySwellWaveDir - * the primarySwellWaveDir to set - */ - public void setPrimarySwellWaveDir(Double primarySwellWaveDir) { - this.primarySwellWaveDir = primarySwellWaveDir; - } - - /** - * @param primarySwellWavePeriod - * the primarySwellWavePeriod to set - */ - public void setPrimarySwellWavePeriod(Integer primarySwellWavePeriod) { - this.primarySwellWavePeriod = primarySwellWavePeriod; - } - - /** - * @param primarySwellWaveHeight - * the primarySwellWaveHeight to set - */ - public void setPrimarySwellWaveHeight(Double primarySwellWaveHeight) { - this.primarySwellWaveHeight = primarySwellWaveHeight; - } - - /** - * @param secondarySwellWaveDir - * the secondarySwellWaveDir to set - */ - public void setSecondarySwellWaveDir(Double secondarySwellWaveDir) { - this.secondarySwellWaveDir = secondarySwellWaveDir; - } - - /** - * @param secondarySwellWavePeriod - * the secondarySwellWavePeriod to set - */ - public void setSecondarySwellWavePeriod(Integer secondarySwellWavePeriod) { - this.secondarySwellWavePeriod = secondarySwellWavePeriod; - } - - /** - * @param secondarySwellWaveHeight - * the secondarySwellWaveHeight to set - */ - public void setSecondarySwellWaveHeight(Double secondarySwellWaveHeight) { - this.secondarySwellWaveHeight = secondarySwellWaveHeight; - } - - /** - * @param pressChangeChar - * the pressChangeChar to set - */ - public void setPressChangeChar(String pressChangeChar) { - this.pressChangeChar = pressChangeChar; - } - - /** - * @return the pressChangeChar - */ - public String getPressChangeChar() { - return pressChangeChar; - } - - /** - * @param dewpoint - * the dewpoint to set - */ - public void setDewpoint(float dewpoint) { - this.dewpoint = dewpoint; - } - - /** - * @param seaSurfaceTemp - * the seaSurfaceTemp to set - */ - public void setSeaSurfaceTemp(float seaSurfaceTemp) { - this.seaSurfaceTemp = seaSurfaceTemp; - } - - /** - * @param seaLevelPress - * the seaLevelPress to set - */ - public void setSeaLevelPress(float seaLevelPress) { - this.seaLevelPress = seaLevelPress; - } - - /** - * @param hourlyPrecip - * the hourlyPrecip to set - */ - public void setHourlyPrecip(float hourlyPrecip) { - this.hourlyPrecip = hourlyPrecip; - } - - /** - * @return the hourlyPrecip - */ - public float getHourlyPrecip() { - return hourlyPrecip; - } - - /** - * @param snowDepth - * the snowDepth to set - */ - public void setSnowDepth(float snowDepth) { - this.snowDepth = snowDepth; - } - - /** - * @param snincrHourly - * the snincrHourly to set - */ - public void setSnincrHourly(float snincrHourly) { - this.snincrHourly = snincrHourly; - } - - /** - * @param snincrTotal - * the snincrTotal to set - */ - public void setSnincrTotal(float snincrTotal) { - this.snincrTotal = snincrTotal; - } - - /** - * @param frostbiteTime - * the frostbiteTime to set - */ - public void setFrostbiteTime(float frostbiteTime) { - this.frostbiteTime = frostbiteTime; - } - - /** - * @param relativeHumidity - * the relativeHumidity to set - */ - public void setRelativeHumidity(float relativeHumidity) { - this.relativeHumidity = relativeHumidity; - } - - /** - * @param presWeather - * the presWeather to set - */ - public void setPresWeather(String[] presWeather) { - this.presWeather = presWeather; - } - - /** - * @return the presWeather - */ - public String[] getPresWeather() { - return presWeather; - } - - /** - * @param dewpointDepr - * the dewpointDepr to set - */ - public void setDewpointDepr(float dewpointDepr) { - this.dewpointDepr = dewpointDepr; - } - - /** - * @return the skyCover - */ - public String[] getSkyCover() { - return skyCover; - } - - /** - * @param skyCover - * the skyCover to set - */ - public void setSkyCover(String[] skyCover) { - this.skyCover = skyCover; - } - - /** - * @param totCloudAmount - * the totCloudAmount to set - */ - public void setTotCloudAmount(int totCloudAmount) { - this.totCloudAmount = totCloudAmount; - } - - /** - * @return the totCloudAmount - */ - public int getTotCloudAmount() { - return totCloudAmount; - } - - @Override - public Collection getValues(String paramName) { - return null; - } - - @Override - public String getString(String paramName) { - return null; - } - - @Override - public String[] getStrings(String paramName) { - return null; - } - - @Override - public ISpatialObject getSpatialObject() { - return location; - } - - /** - * @param pointDataView - * the pointDataView to set - */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } - - /** - * @return the pointDataView - */ - @Override - public PointDataView getPointDataView() { - return pointDataView; - } - - /** - * Used for debugging. - */ - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("fssObsRec:\n\t"); - if (this != null) { - sb.append(this.getDataURI() + "\n\t"); - sb.append(this.getLocation().getStationId() + " ===> " - + this.getStnName() + "\n\t"); - sb.append("Latitude = " + this.getLocation().getLatitude() + "\n\t"); - sb.append("Longitude = " + this.getLocation().getLongitude() - + "\n\t"); - sb.append(this.getReportType() + "\n\t"); - sb.append("Visibility = " + this.getVisibility() + "\n\t"); - sb.append("Temperature = " + this.getTemperature() + "\n\t"); - sb.append(this.getDataTime().getRefTime() + "\n"); - } - return sb.toString(); - } + private static final HashMap PARM_MAP = new HashMap(); + static { + PARM_MAP.put("NLAT", STA_LAT); + PARM_MAP.put("NLON", STA_LON); + PARM_MAP.put("rawMessage", "rawMessage"); + } + + /** is feature new **/ + @Transient + @DynamicSerializeElement + @XmlElement + public boolean isNew = true; + + // Current CWA (WFO) + @Column + @DataURI(position = 2) + @DynamicSerializeElement + @XmlElement(nillable = false) + private String cwa; + + // Monitor which should use this station record + // fog = "fog" + // safeseas = "ss" + // snow = "snow" + @Column + @DataURI(position = 4) + @DynamicSerializeElement + @XmlElement + private String monitorUse = ""; + + // Station name + @Column + @DynamicSerializeElement + @XmlElement + private String stnName; + + /* From ============ObReport================= */ + + @XmlElement + @DynamicSerializeElement + @Column + @DataURI(position = 1) + protected String reportType; + + @Embedded + @DataURI(position = 3, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; + + // Observing platform identifier (same as stationID) + @Transient + @XmlElement + @DynamicSerializeElement + private String platformId; + + // Indicator of whether observing platform is stationary + @Transient + @DynamicSerializeElement + @XmlElement + private boolean isStationary; + + // Actual time of the observation + @Transient + @DynamicSerializeElement + @XmlElement + private Calendar timeObs; + + // Time of the observation to the nearest hour. + @XmlElement + @DynamicSerializeElement + @Column + private Calendar refHour; + + // Raw message + @Transient + @DynamicSerializeElement + @XmlElement + private String rawMessage; + + // Observed wind speed in knots + @Transient + @DynamicSerializeElement + @XmlElement + private float windSpeed = -9999;; + + // Wind gust in knots + @Transient + @DynamicSerializeElement + @XmlElement + private float windGust = -9999;; + + // Observed maximum wind speed in knots + @Transient + @DynamicSerializeElement + @XmlElement + private float maxWindSpeed = -9999; + + // Observed wind direction in azimuth degrees + @Transient + @DynamicSerializeElement + @XmlElement + private float windDir; + + // Observed wind chill in Fahrenheit + @Transient + @DynamicSerializeElement + @XmlElement + private float windChill = -9999; + + // Observed high resolution wave height in + @Transient + @DynamicSerializeElement + @XmlElement + private float highResWaveHeight = -9999; + + // Observed wave steepness in seconds ??? None + @Transient + @DynamicSerializeElement + @XmlElement + private float waveSteepness = -9999; + + // Observed visibility in Statute miles + @Transient + @DynamicSerializeElement + @XmlElement + private float visibility = -9999; + + // Observed visibility in meters for Maritime obs. + @Transient + @DynamicSerializeElement + @XmlElement + private float horzVisibility = -9999; + + // Observed temperature in degrees in Farenheit + @Transient + @DynamicSerializeElement + @XmlElement + private float temperature = -9999; + + // in feet + @Transient + @XmlElement + @DynamicSerializeElement + private Double waveHeight = -9999.0; + + // in seconds + @Transient + @XmlElement + @DynamicSerializeElement + private Integer wavePeriod = -9999; + + // in Azimuth degrees + @Transient + @XmlElement + @DynamicSerializeElement + private Double primarySwellWaveDir = -9999.0; + + // in seconds + @Transient + @XmlElement + @DynamicSerializeElement + private Integer primarySwellWavePeriod = -9999; + + // in feet + @Transient + @XmlElement + @DynamicSerializeElement + private Double primarySwellWaveHeight = -9999.0; + + // in Azimuth degrees + @Transient + @XmlElement + @DynamicSerializeElement + private Double secondarySwellWaveDir = -9999.0; + + // in seconds + @Transient + @XmlElement + @DynamicSerializeElement + private Integer secondarySwellWavePeriod = -9999; + + // in feet + @Transient + @XmlElement + @DynamicSerializeElement + private Double secondarySwellWaveHeight = -9999.0; + + // Three-hour pressure change in thousandths of an inch of mercury ???? + @Transient + @DynamicSerializeElement + @XmlElement + private float pressChange3Hour = -9999f; + + // Pressure change character for metar plot model + /** A string denoting the pressure tendency(rising or falling) */ + @Transient + @DynamicSerializeElement + @XmlElement + private String pressChangeChar; + + // Observed dewpoint in degrees Farenheit + @Transient + @DynamicSerializeElement + @XmlElement + private float dewpoint = -9999f; + + // Observed sea surface temperature in degrees in Farenheit + @Transient + @DynamicSerializeElement + @XmlElement + private float seaSurfaceTemp = -9999f; + + // the sea level pressure in hPa + @XmlElement + @DynamicSerializeElement + @Transient + private float seaLevelPress = -9999f; + + // Altimeter setting in mm Hg. + @Transient + @XmlElement + @DynamicSerializeElement + private float pressureAltimeter = -9999f; + + // Observed hourly precipitation in inches + @Transient + @DynamicSerializeElement + @XmlElement + private float hourlyPrecip = -9999f; + + // Observed snow depth in inch + @Transient + @DynamicSerializeElement + @XmlElement + private float snowDepth = -9999f; + + // Observed snow increasing rapidly, hourly total in inches + @Transient + @DynamicSerializeElement + @XmlElement + private float snincrHourly = -9999f; + + // Observed snow increasing rapidly, total in inches + @Transient + @DynamicSerializeElement + @XmlElement + private float snincrTotal = -9999f; + + // Observed frostbite time in minutes + @Transient + @DynamicSerializeElement + @XmlElement + private float frostbiteTime; + + // present weather conditions for metar plot model + @Transient + @DynamicSerializeElement + @XmlElement + private String[] presWeather; + + // Observed relative humidity in percent + @Transient + @DynamicSerializeElement + @XmlElement + private float relativeHumidity = -9999f; + + // Observed ceiling in feet above ground level + @Transient + @DynamicSerializeElement + @XmlElement + private float ceiling = -9999f; + + // Observed dewpoint depression in Farenheit + @Transient + @DynamicSerializeElement + @XmlElement + private float dewpointDepr = -9999f; + + @XmlElement + @DynamicSerializeElement + @Transient + private String[] skyCover; + + @XmlElement + @DynamicSerializeElement + @Transient + private int totCloudAmount = -9999; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + // ---------------------------------------------------------------------------------------------------- + public FSSObsRecord() { + } + + public FSSObsRecord(String uri) { + super(uri); + } + + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } + + @Override + public Amount getValue(String paramName) { + Amount a = null; + + String pName = PARM_MAP.get(paramName); + + if (SFC_TEMP.equals(pName) && (temperature != -9999f)) { + a = new Amount(temperature, TEMPERATURE_UNIT); + } else if (SFC_DWPT.equals(pName) && (dewpoint != -9999f)) { + a = new Amount(dewpoint, TEMPERATURE_UNIT); + } else if (SFC_WNDSPD.equals(pName) && (windSpeed != -9999f)) { + a = new Amount(windSpeed, WIND_SPEED_UNIT); + } else if (SFC_WNDDIR.equals(pName) && (windDir != -9999f)) { + a = new Amount(windDir, WIND_DIR_UNIT); + } else if (SFC_WNDGST.equals(pName) && (windGust != -9999f)) { + a = new Amount(windGust, WIND_SPEED_UNIT); + } else if (PRES_SLP.equals(pName) && (seaLevelPress != -9999f)) { + a = new Amount(seaLevelPress, PRESSURE_UNIT); + // } else if (PRES_ALTSG.equals(pName) && (pressureAltimeter != + // -9999f)) { + // a = new Amount(pressureAltimeter, PRESSURE_UNIT); + } else if (STA_LAT.equals(pName)) { + a = new Amount(this.getLatitude(), LOCATION_UNIT); + } else if (STA_LON.equals(pName)) { + a = new Amount(this.getLongitude(), LOCATION_UNIT); + } else if ("WT".equals(pName) && (this.seaSurfaceTemp != -9999f)) { + a = new Amount(this.seaSurfaceTemp, TEMPERATURE_UNIT); + } else if ("WH".equals(pName)) { + a = new Amount(waveHeight, WAVE_UNIT); + } else if ("SWP".equals(pName)) { + a = new Amount(primarySwellWavePeriod, WAVE_UNIT); + } else if ("SWH".equals(pName)) { + a = new Amount(primarySwellWaveHeight, WAVE_UNIT); + // } else if ("PCHNG".equals(pName) && pressChange3Hour != MISSING) + // { + // a = new Amount(pressChange3Hour, PRESSURE_UNIT); + } else if ("PKWND".equals(paramName) && (maxWindSpeed != MISSING)) { + a = new Amount(maxWindSpeed, WIND_SPEED_UNIT); + } else if ("SWS".equals(paramName) || "SWGS".equals(paramName)) { + a = new Amount(1, WIND_SPEED_UNIT); + } else if ("SWD".equals(paramName) && (primarySwellWaveDir != MISSING)) { + a = new Amount(primarySwellWaveDir, WIND_DIR_UNIT); + } + + return a; + } + + /** + * @return the isNew + */ + public boolean getIsNew() { + return isNew; + } + + /** + * @return the cwa + */ + public String getCwa() { + return cwa; + } + + /** + * @param monitorUse + * the monitorUse to set + */ + public void setMonitorUse(String monitorUse) { + this.monitorUse = monitorUse; + } + + /** + * @return the monitorUse + */ + public String getMonitorUse() { + return monitorUse; + } + + /** + * @return the stnName + */ + public String getStnName() { + return stnName; + } + + /** + * @return the reportType + */ + public String getReportType() { + return reportType; + } + + /** + * @return the location + */ + public SurfaceObsLocation getLocation() { + return location; + } + + /** + * @param platformId + * the platformId to set + */ + public void setPlatformId(String platformId) { + this.platformId = platformId; + } + + /** + * @return the platformId + */ + public String getPlatformId() { + return platformId; + } + + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } + + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } + + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } + + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } + + /** + * @return the isStationary + */ + public boolean isStationary() { + return isStationary; + } + + /** + * @return the refHour + */ + public Calendar getRefHour() { + return refHour; + } + + /** + * @return the rawMessage + */ + public String getRawMessage() { + return rawMessage; + } + + /** + * @return the windSpeed + */ + public float getWindSpeed() { + return windSpeed; + } + + /** + * @return the windGust + */ + public float getWindGust() { + return windGust; + } + + /** + * @return the maxWindSpeed + */ + public float getMaxWindSpeed() { + return maxWindSpeed; + } + + /** + * @return the windDir + */ + public float getWindDir() { + return windDir; + } + + /** + * @return the windChill + */ + public float getWindChill() { + return windChill; + } + + /** + * @return the waveSteepness + */ + public float getWaveSteepness() { + return waveSteepness; + } + + /** + * @return the visibility + */ + public float getVisibility() { + return visibility; + } + + /** + * @return the temperature + */ + public float getTemperature() { + return temperature; + } + + /** + * @return the waveHeight + */ + public Double getWaveHeight() { + return waveHeight; + } + + /** + * @return the wavePeriod + */ + public Integer getWavePeriod() { + return wavePeriod; + } + + /** + * @return the primarySwellWaveDir + */ + public Double getPrimarySwellWaveDir() { + return primarySwellWaveDir; + } + + /** + * @return the primarySwellWavePeriod + */ + public Integer getPrimarySwellWavePeriod() { + return primarySwellWavePeriod; + } + + /** + * @return the primarySwellWaveHeight + */ + public Double getPrimarySwellWaveHeight() { + return primarySwellWaveHeight; + } + + /** + * @return the secondarySwellWaveDir + */ + public Double getSecondarySwellWaveDir() { + return secondarySwellWaveDir; + } + + /** + * @return the secondarySwellWavePeriod + */ + public Integer getSecondarySwellWavePeriod() { + return secondarySwellWavePeriod; + } + + /** + * @return the secondarySwellWaveHeight + */ + public Double getSecondarySwellWaveHeight() { + return secondarySwellWaveHeight; + } + + /** + * @return the dewpoint + */ + public float getDewpoint() { + return dewpoint; + } + + /** + * @return the seaSurfaceTemp + */ + public float getSeaSurfaceTemp() { + return seaSurfaceTemp; + } + + /** + * @return the seaLevelPress + */ + public float getSeaLevelPress() { + return seaLevelPress; + } + + /** + * @param pressureAltimeter + * the pressureAltimeter to set + */ + public void setPressureAltimeter(float pressureAltimeter) { + this.pressureAltimeter = pressureAltimeter; + } + + /** + * @return the pressureAltimeter + */ + public float getPressureAltimeter() { + return pressureAltimeter; + } + + /** + * @param pressChange3Hour + * the pressChange3Hour to set + */ + public void setPressChange3Hour(float pressChange3Hour) { + this.pressChange3Hour = pressChange3Hour; + } + + /** + * @return the pressChange3Hour + */ + public float getPressChange3Hour() { + return pressChange3Hour; + } + + /** + * @return the snowDepth + */ + public float getSnowDepth() { + return snowDepth; + } + + /** + * @return the snincrHourly + */ + public float getSnincrHourly() { + return snincrHourly; + } + + /** + * @return the snincrTotal + */ + public float getSnincrTotal() { + return snincrTotal; + } + + /** + * @return the frostbiteTime + */ + public float getFrostbiteTime() { + return frostbiteTime; + } + + /** + * @return the relativeHumidity + */ + public float getRelativeHumidity() { + return relativeHumidity; + } + + /** + * @param ceiling + * the ceiling to set + */ + public void setCeiling(float ceiling) { + this.ceiling = ceiling; + } + + /** + * @return the ceiling + */ + public float getCeiling() { + return ceiling; + } + + /** + * @return the dewpointDepr + */ + public float getDewpointDepr() { + return dewpointDepr; + } + + /** + * @param isNew + * the isNew to set + */ + public void setIsNew(boolean isNew) { + this.isNew = isNew; + } + + /** + * @param cwa + * the cwa to set + */ + public void setCwa(String cwa) { + this.cwa = cwa; + } + + /** + * @param stnName + * the stnName to set + */ + public void setStnName(String stnName) { + this.stnName = stnName; + } + + /** + * @param reportType + * the reportType to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } + + /** + * @param location + * the location to set + */ + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } + + /** + * @param isStationary + * the isStationary to set + */ + public void setIsStationary(boolean isStationary) { + this.isStationary = isStationary; + } + + public boolean getIsStationary() { + return isStationary; + } + + /** + * @param timeObs + * the timeObs to set + */ + public void setTimeObs(Calendar timeObs) { + this.timeObs = timeObs; + } + + /** + * @return the timeObs + */ + public Calendar getTimeObs() { + return timeObs; + } + + /** + * @param refHour + * the refHour to set + */ + public void setRefHour(Calendar refHour) { + this.refHour = refHour; + } + + /** + * @param rawMessage + * the rawMessage to set + */ + public void setRawMessage(String rawMessage) { + this.rawMessage = rawMessage; + } + + /** + * @param windSpeed + * the windSpeed to set + */ + public void setWindSpeed(float windSpeed) { + this.windSpeed = windSpeed; + } + + /** + * @param windGust + * the windGust to set + */ + public void setWindGust(float windGust) { + this.windGust = windGust; + } + + /** + * @param maxWindSpeed + * the maxWindSpeed to set + */ + public void setMaxWindSpeed(float maxWindSpeed) { + this.maxWindSpeed = maxWindSpeed; + } + + /** + * @param windDir + * the windDir to set + */ + public void setWindDir(float windDir) { + this.windDir = windDir; + } + + /** + * @param windChill + * the windChill to set + */ + public void setWindChill(float windChill) { + this.windChill = windChill; + } + + public void setHighResWaveHeight(float highResWaveHeight) { + this.highResWaveHeight = highResWaveHeight; + } + + public float getHighResWaveHeight() { + return highResWaveHeight; + } + + /** + * @param waveSteepness + * the waveSteepness to set + */ + public void setWaveSteepness(float waveSteepness) { + this.waveSteepness = waveSteepness; + } + + /** + * @param visibility + * the visibility to set + */ + public void setVisibility(float visibility) { + this.visibility = visibility; + } + + /** + * @param horzVisibility + * the horzVisibility to set + */ + public void setHorzVisibility(float horzVisibility) { + this.horzVisibility = horzVisibility; + } + + /** + * @return the horzVisibility + */ + public float getHorzVisibility() { + return horzVisibility; + } + + /** + * @param temperature + * the temperature to set + */ + public void setTemperature(float temperature) { + this.temperature = temperature; + } + + /** + * @param waveHeight + * the waveHeight to set + */ + public void setWaveHeight(Double waveHeight) { + this.waveHeight = waveHeight; + } + + /** + * @param wavePeriod + * the wavePeriod to set + */ + public void setWavePeriod(Integer wavePeriod) { + this.wavePeriod = wavePeriod; + } + + /** + * @param primarySwellWaveDir + * the primarySwellWaveDir to set + */ + public void setPrimarySwellWaveDir(Double primarySwellWaveDir) { + this.primarySwellWaveDir = primarySwellWaveDir; + } + + /** + * @param primarySwellWavePeriod + * the primarySwellWavePeriod to set + */ + public void setPrimarySwellWavePeriod(Integer primarySwellWavePeriod) { + this.primarySwellWavePeriod = primarySwellWavePeriod; + } + + /** + * @param primarySwellWaveHeight + * the primarySwellWaveHeight to set + */ + public void setPrimarySwellWaveHeight(Double primarySwellWaveHeight) { + this.primarySwellWaveHeight = primarySwellWaveHeight; + } + + /** + * @param secondarySwellWaveDir + * the secondarySwellWaveDir to set + */ + public void setSecondarySwellWaveDir(Double secondarySwellWaveDir) { + this.secondarySwellWaveDir = secondarySwellWaveDir; + } + + /** + * @param secondarySwellWavePeriod + * the secondarySwellWavePeriod to set + */ + public void setSecondarySwellWavePeriod(Integer secondarySwellWavePeriod) { + this.secondarySwellWavePeriod = secondarySwellWavePeriod; + } + + /** + * @param secondarySwellWaveHeight + * the secondarySwellWaveHeight to set + */ + public void setSecondarySwellWaveHeight(Double secondarySwellWaveHeight) { + this.secondarySwellWaveHeight = secondarySwellWaveHeight; + } + + /** + * @param pressChangeChar + * the pressChangeChar to set + */ + public void setPressChangeChar(String pressChangeChar) { + this.pressChangeChar = pressChangeChar; + } + + /** + * @return the pressChangeChar + */ + public String getPressChangeChar() { + return pressChangeChar; + } + + /** + * @param dewpoint + * the dewpoint to set + */ + public void setDewpoint(float dewpoint) { + this.dewpoint = dewpoint; + } + + /** + * @param seaSurfaceTemp + * the seaSurfaceTemp to set + */ + public void setSeaSurfaceTemp(float seaSurfaceTemp) { + this.seaSurfaceTemp = seaSurfaceTemp; + } + + /** + * @param seaLevelPress + * the seaLevelPress to set + */ + public void setSeaLevelPress(float seaLevelPress) { + this.seaLevelPress = seaLevelPress; + } + + /** + * @param hourlyPrecip + * the hourlyPrecip to set + */ + public void setHourlyPrecip(float hourlyPrecip) { + this.hourlyPrecip = hourlyPrecip; + } + + /** + * @return the hourlyPrecip + */ + public float getHourlyPrecip() { + return hourlyPrecip; + } + + /** + * @param snowDepth + * the snowDepth to set + */ + public void setSnowDepth(float snowDepth) { + this.snowDepth = snowDepth; + } + + /** + * @param snincrHourly + * the snincrHourly to set + */ + public void setSnincrHourly(float snincrHourly) { + this.snincrHourly = snincrHourly; + } + + /** + * @param snincrTotal + * the snincrTotal to set + */ + public void setSnincrTotal(float snincrTotal) { + this.snincrTotal = snincrTotal; + } + + /** + * @param frostbiteTime + * the frostbiteTime to set + */ + public void setFrostbiteTime(float frostbiteTime) { + this.frostbiteTime = frostbiteTime; + } + + /** + * @param relativeHumidity + * the relativeHumidity to set + */ + public void setRelativeHumidity(float relativeHumidity) { + this.relativeHumidity = relativeHumidity; + } + + /** + * @param presWeather + * the presWeather to set + */ + public void setPresWeather(String[] presWeather) { + this.presWeather = presWeather; + } + + /** + * @return the presWeather + */ + public String[] getPresWeather() { + return presWeather; + } + + /** + * @param dewpointDepr + * the dewpointDepr to set + */ + public void setDewpointDepr(float dewpointDepr) { + this.dewpointDepr = dewpointDepr; + } + + /** + * @return the skyCover + */ + public String[] getSkyCover() { + return skyCover; + } + + /** + * @param skyCover + * the skyCover to set + */ + public void setSkyCover(String[] skyCover) { + this.skyCover = skyCover; + } + + /** + * @param totCloudAmount + * the totCloudAmount to set + */ + public void setTotCloudAmount(int totCloudAmount) { + this.totCloudAmount = totCloudAmount; + } + + /** + * @return the totCloudAmount + */ + public int getTotCloudAmount() { + return totCloudAmount; + } + + @Override + public Collection getValues(String paramName) { + return null; + } + + @Override + public String getString(String paramName) { + return null; + } + + @Override + public String[] getStrings(String paramName) { + return null; + } + + @Override + public ISpatialObject getSpatialObject() { + return location; + } + + /** + * @param pointDataView + * the pointDataView to set + */ + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + + /** + * @return the pointDataView + */ + @Override + public PointDataView getPointDataView() { + return pointDataView; + } + + /** + * Used for debugging. + */ + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("fssObsRec:\n\t"); + if (this != null) { + sb.append(this.getDataURI() + "\n\t"); + sb.append(this.getLocation().getStationId() + " ===> " + + this.getStnName() + "\n\t"); + sb.append("Latitude = " + this.getLocation().getLatitude() + "\n\t"); + sb.append("Longitude = " + this.getLocation().getLongitude() + + "\n\t"); + sb.append(this.getReportType() + "\n\t"); + sb.append("Visibility = " + this.getVisibility() + "\n\t"); + sb.append("Temperature = " + this.getTemperature() + "\n\t"); + sb.append(this.getDataTime().getRefTime() + "\n"); + } + return sb.toString(); + } @Override @Column @@ -1268,4 +1237,9 @@ public class FSSObsRecord extends PersistablePluginDataObject implements public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "fssobs"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GFERecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GFERecord.java index 7cf79598ea..347f7eab1e 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GFERecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GFERecord.java @@ -25,6 +25,7 @@ package com.raytheon.uf.common.dataplugin.gfe.db.objects; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Date; import java.util.List; import java.util.TimeZone; @@ -47,6 +48,7 @@ import org.hibernate.annotations.OnDeleteAction; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.annotations.DataURI; import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory; +import com.raytheon.uf.common.dataplugin.persist.IPersistable; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.time.DataTime; @@ -77,6 +79,8 @@ import com.raytheon.uf.common.time.TimeRange; * PluginDataObject. * May 13, 2013 1869 bsteffen Remove DataURI column from GFE. * Jun 20, 2013 2127 rjpeter Added OnDelete annotation. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract + * Sep 20, 2013 2147 rferrel Changes to archive hdf5 files. * * * @@ -95,7 +99,7 @@ import com.raytheon.uf.common.time.TimeRange; "refTime", "forecastTime" }) }) @DynamicSerialize @BatchSize(size = 500) -public class GFERecord extends PluginDataObject { +public class GFERecord extends PluginDataObject implements IPersistable { private static final long serialVersionUID = 1L; @@ -151,7 +155,6 @@ public class GFERecord extends PluginDataObject { * The parm Info */ public GFERecord(ParmID parmId, TimeRange timeRange) { - this.pluginName = "gfe"; Calendar cal = (Calendar) Calendar.getInstance( TimeZone.getTimeZone("GMT")).clone(); cal.setTime(timeRange.getStart()); @@ -276,4 +279,21 @@ public class GFERecord extends PluginDataObject { } } } + + @Override + public String getPluginName() { + return "gfe"; + } + + @Override + public Date getPersistenceTime() { + return getInsertTime().getTime(); + } + + @Override + public void setPersistenceTime(Date persistTime) { + Calendar pTime = Calendar.getInstance(); + pTime.setTime(persistTime); + setInsertTime(pTime); + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.goessounding/src/com/raytheon/uf/common/dataplugin/goessounding/GOESSounding.java b/edexOsgi/com.raytheon.uf.common.dataplugin.goessounding/src/com/raytheon/uf/common/dataplugin/goessounding/GOESSounding.java index a588315d39..ec39c88693 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.goessounding/src/com/raytheon/uf/common/dataplugin/goessounding/GOESSounding.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.goessounding/src/com/raytheon/uf/common/dataplugin/goessounding/GOESSounding.java @@ -62,6 +62,7 @@ import com.vividsolutions.jts.geom.Geometry; * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * May 15, 2013 1869 bsteffen Remove DataURI from goes/poes soundings. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -76,348 +77,348 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "goessounding", - indexes = { - @Index(name = "goessounding_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "goessounding", indexes = { @Index(name = "goessounding_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class GOESSounding extends PersistablePluginDataObject implements ISpatialEnabled, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Embedded - @DataURI(position = 1, embedded = true) - @DynamicSerializeElement - private SurfaceObsLocation location; + @Embedded + @DataURI(position = 1, embedded = true) + @DynamicSerializeElement + private SurfaceObsLocation location; - // The bounding box that contains this observation. + // The bounding box that contains this observation. @Column(name = "boxGeometry", columnDefinition = "geometry") @Type(type = "com.raytheon.edex.db.objects.hibernate.GeometryType") - @DynamicSerializeElement - private Geometry boxGeometry; + @DynamicSerializeElement + private Geometry boxGeometry; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - // Text of the WMO header - @Transient - @DynamicSerializeElement - private String wmoHeader; + // Text of the WMO header + @Transient + @DynamicSerializeElement + private String wmoHeader; - @Transient - @DynamicSerializeElement - private Integer satId; + @Transient + @DynamicSerializeElement + private Integer satId; - @Transient - @DynamicSerializeElement - private Integer satInstrument; + @Transient + @DynamicSerializeElement + private Integer satInstrument; - @Transient - @DynamicSerializeElement - private Integer qualityInfo; + @Transient + @DynamicSerializeElement + private Integer qualityInfo; - @Transient - @DynamicSerializeElement - private Integer sounderChannels; + @Transient + @DynamicSerializeElement + private Integer sounderChannels; - @Transient - @DynamicSerializeElement - private Double solarElevation; + @Transient + @DynamicSerializeElement + private Double solarElevation; - // The profiler observation time. - @Transient - @DynamicSerializeElement - private Calendar timeObs; + // The profiler observation time. + @Transient + @DynamicSerializeElement + private Calendar timeObs; - @Transient - @DynamicSerializeElement - private List soundingLevels; + @Transient + @DynamicSerializeElement + private List soundingLevels; - /** - * Create an empty ProfilerObs object. - */ - public GOESSounding() { - } + /** + * Create an empty ProfilerObs object. + */ + public GOESSounding() { + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public GOESSounding(String uri) { - super(uri); - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public GOESSounding(String uri) { + super(uri); + } - /** - * Get the observation time for this data. - * - * @return The data observation time. - */ - public Calendar getTimeObs() { - return timeObs; - } + /** + * Get the observation time for this data. + * + * @return The data observation time. + */ + public Calendar getTimeObs() { + return timeObs; + } - /** - * Set the observation time for this data. - * - * @param timeObs - * The data observation time. - */ - public void setTimeObs(Calendar timeObs) { - this.timeObs = timeObs; - } + /** + * Set the observation time for this data. + * + * @param timeObs + * The data observation time. + */ + public void setTimeObs(Calendar timeObs) { + this.timeObs = timeObs; + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } - /** - * Was this location defined from the station catalog? False if not. - * - * @return Was this location defined from the station catalog? - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } + /** + * Was this location defined from the station catalog? False if not. + * + * @return Was this location defined from the station catalog? + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } - /** - * Set the WMOHeader of the file that contained this data. - * - * @return The wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * Set the WMOHeader of the file that contained this data. + * + * @return The wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * Get the WMOHeader of the file that contained this data. - * - * @param wmoHeader - * The WMOHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * Get the WMOHeader of the file that contained this data. + * + * @param wmoHeader + * The WMOHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * @return the satId - */ - public Integer getSatId() { - return satId; - } + /** + * @return the satId + */ + public Integer getSatId() { + return satId; + } - /** - * @param satId - * the satId to set - */ - public void setSatId(Integer satId) { - this.satId = satId; - } + /** + * @param satId + * the satId to set + */ + public void setSatId(Integer satId) { + this.satId = satId; + } - /** - * @return the satInstrument - */ - public Integer getSatInstrument() { - return satInstrument; - } + /** + * @return the satInstrument + */ + public Integer getSatInstrument() { + return satInstrument; + } - /** - * @param satInstrument - * the satInstrument to set - */ - public void setSatInstrument(Integer satInstrument) { - this.satInstrument = satInstrument; - } + /** + * @param satInstrument + * the satInstrument to set + */ + public void setSatInstrument(Integer satInstrument) { + this.satInstrument = satInstrument; + } - /** - * @return the qualityInfo - */ - public Integer getQualityInfo() { - return qualityInfo; - } + /** + * @return the qualityInfo + */ + public Integer getQualityInfo() { + return qualityInfo; + } - /** - * @param qualityInfo - * the qualityInfo to set - */ - public void setQualityInfo(Integer qualityInfo) { - this.qualityInfo = qualityInfo; - } + /** + * @param qualityInfo + * the qualityInfo to set + */ + public void setQualityInfo(Integer qualityInfo) { + this.qualityInfo = qualityInfo; + } - /** - * Get the satellite channels used to to create the sounding data. - * - *
-	 *  bit  Channel  Wavelength
-	 *   #            micrometers
-	 *   1       1      14.71
-	 *   2       2      14.37
-	 *   3       3      14.06
-	 *   4       4      13.64
-	 *   5       5      13.37
-	 *   6       6      12.66
-	 *   7       7      12.02
-	 *   8       8      11.03
-	 *   9       9       9.71
-	 *  10      10       7.43
-	 *  11      11       7.02
-	 *  12      12       6.51
-	 *  13      13       4.57
-	 *  14      14       4.52
-	 *  15      15       4.45
-	 *  16      16       4.13
-	 *  17      17       3.98
-	 *  18      18       3.74
-	 *  19      19       0.969
-	 *  All 20    Missing value
-	 * 
- * - * @return The sounder channels. - */ - public Integer getSounderChannels() { - return sounderChannels; - } + /** + * Get the satellite channels used to to create the sounding data. + * + *
+     *  bit  Channel  Wavelength
+     *   #            micrometers
+     *   1       1      14.71
+     *   2       2      14.37
+     *   3       3      14.06
+     *   4       4      13.64
+     *   5       5      13.37
+     *   6       6      12.66
+     *   7       7      12.02
+     *   8       8      11.03
+     *   9       9       9.71
+     *  10      10       7.43
+     *  11      11       7.02
+     *  12      12       6.51
+     *  13      13       4.57
+     *  14      14       4.52
+     *  15      15       4.45
+     *  16      16       4.13
+     *  17      17       3.98
+     *  18      18       3.74
+     *  19      19       0.969
+     *  All 20    Missing value
+     * 
+ * + * @return The sounder channels. + */ + public Integer getSounderChannels() { + return sounderChannels; + } - /** - * Get the satellite channels used to to create the sounding data. - * - * @param sounderChannels - * The sounder channels. - */ - public void setSounderChannels(Integer sounderChannels) { - this.sounderChannels = sounderChannels; - } + /** + * Get the satellite channels used to to create the sounding data. + * + * @param sounderChannels + * The sounder channels. + */ + public void setSounderChannels(Integer sounderChannels) { + this.sounderChannels = sounderChannels; + } - /** - * Get the bounding box that contains this observation. - * - * @return The bounding box Geometry. - */ - public Geometry getBoxGeometry() { - return boxGeometry; - } + /** + * Get the bounding box that contains this observation. + * + * @return The bounding box Geometry. + */ + public Geometry getBoxGeometry() { + return boxGeometry; + } - /** - * Set the bounding box that contains this observation. - * - * @param boxGeometry - * The bounding box Geometry. - */ - public void setBoxGeometry(Geometry boxGeometry) { - this.boxGeometry = boxGeometry; - } + /** + * Set the bounding box that contains this observation. + * + * @param boxGeometry + * The bounding box Geometry. + */ + public void setBoxGeometry(Geometry boxGeometry) { + this.boxGeometry = boxGeometry; + } - /** - * @return the solarElevation - */ - public Double getSolarElevation() { - return solarElevation; - } + /** + * @return the solarElevation + */ + public Double getSolarElevation() { + return solarElevation; + } - /** - * @param solarElevation - * the solarElevation to set - */ - public void setSolarElevation(Double solarElevation) { - this.solarElevation = solarElevation; - } + /** + * @param solarElevation + * the solarElevation to set + */ + public void setSolarElevation(Double solarElevation) { + this.solarElevation = solarElevation; + } - /** - * @return the soundingLevels - */ - public List getSoundingLevels() { - return soundingLevels; - } + /** + * @return the soundingLevels + */ + public List getSoundingLevels() { + return soundingLevels; + } - /** - * @param soundingLevels - * the soundingLevels to set - */ - public void setSoundingLevels(List soundingLevels) { - this.soundingLevels = soundingLevels; - } + /** + * @param soundingLevels + * the soundingLevels to set + */ + public void setSoundingLevels(List soundingLevels) { + this.soundingLevels = soundingLevels; + } - /** - * @param soundingLevels - * the soundingLevels to set - */ - public void addSoundingLevel(GOESSoundingLevel soundingLevel) { - if (soundingLevels == null) { - soundingLevels = new ArrayList(); - } - soundingLevels.add(soundingLevel); - } + /** + * @param soundingLevels + * the soundingLevels to set + */ + public void addSoundingLevel(GOESSoundingLevel soundingLevel) { + if (soundingLevels == null) { + soundingLevels = new ArrayList(); + } + soundingLevels.add(soundingLevel); + } - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - public SurfaceObsLocation getLocation() { - return location; - } + public SurfaceObsLocation getLocation() { + return location; + } - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + @Override + public String getPluginName() { + return "goessounding"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/GribRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/GribRecord.java index 6dc4dbf6b1..3af072fc9d 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/GribRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/GribRecord.java @@ -65,12 +65,14 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 4/7/09 1994 bphillip Initial Creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 04/08/13 1293 bkowal Removed references to hdffileid. + * Apr 07, 2009 1994 bphillip Initial Creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -84,12 +86,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "grib", - indexes = { - @Index(name = "grib_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "grib", indexes = { @Index(name = "grib_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -238,7 +236,6 @@ public class GribRecord extends PersistablePluginDataObject implements this.insertTime = (Calendar) recordToCopy.insertTime.clone(); } this.messageData = recordToCopy.messageData; - this.pluginName = recordToCopy.pluginName; this.gridVersion = recordToCopy.gridVersion; if (recordToCopy.hybridCoordList != null) { this.hybridCoordList = Arrays.copyOf(recordToCopy.hybridCoordList, @@ -278,8 +275,9 @@ public class GribRecord extends PersistablePluginDataObject implements @Override public Date getPersistenceTime() { Calendar c = getInsertTime(); - if (c == null) + if (c == null) { return null; + } return c.getTime(); } @@ -526,6 +524,7 @@ public class GribRecord extends PersistablePluginDataObject implements this.resCompFlags = resCompFlags; } + @Override public void setId(int id) { this.id = id; } @@ -566,34 +565,37 @@ public class GribRecord extends PersistablePluginDataObject implements public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + gridVersion; - result = prime * result + Arrays.hashCode(hybridCoordList); - result = prime * result + (hybridGrid ? 1231 : 1237); - result = prime * result + (isVector ? 1231 : 1237); - result = prime * result + Arrays.hashCode(localSection); - result = prime * result + (localSectionUsed ? 1231 : 1237); - result = prime * result + localTableVersion; - result = prime * result + masterTableVersion; - result = prime * result + result = (prime * result) + gridVersion; + result = (prime * result) + Arrays.hashCode(hybridCoordList); + result = (prime * result) + (hybridGrid ? 1231 : 1237); + result = (prime * result) + (isVector ? 1231 : 1237); + result = (prime * result) + Arrays.hashCode(localSection); + result = (prime * result) + (localSectionUsed ? 1231 : 1237); + result = (prime * result) + localTableVersion; + result = (prime * result) + masterTableVersion; + result = (prime * result) + ((modelInfo == null) ? 0 : modelInfo.hashCode()); - result = prime * result + processedDataType; - result = prime * result + productionStatus; - result = prime * result + refTimeSignificance; - result = prime * result + result = (prime * result) + processedDataType; + result = (prime * result) + productionStatus; + result = (prime * result) + refTimeSignificance; + result = (prime * result) + ((resCompFlags == null) ? 0 : resCompFlags.hashCode()); - result = prime * result + (thinnedGrid ? 1231 : 1237); - result = prime * result + Arrays.hashCode(thinnedPts); + result = (prime * result) + (thinnedGrid ? 1231 : 1237); + result = (prime * result) + Arrays.hashCode(thinnedPts); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } GribRecord other = (GribRecord) obj; if (!this.dataTime.getRefTimeAsCalendar().equals( other.getDataTime().getRefTimeAsCalendar())) { @@ -606,42 +608,59 @@ public class GribRecord extends PersistablePluginDataObject implements return false; } - if (gridVersion != other.gridVersion) + if (gridVersion != other.gridVersion) { return false; - if (!Arrays.equals(hybridCoordList, other.hybridCoordList)) + } + if (!Arrays.equals(hybridCoordList, other.hybridCoordList)) { return false; - if (hybridGrid != other.hybridGrid) + } + if (hybridGrid != other.hybridGrid) { return false; - if (isVector != other.isVector) + } + if (isVector != other.isVector) { return false; - if (!Arrays.equals(localSection, other.localSection)) + } + if (!Arrays.equals(localSection, other.localSection)) { return false; - if (localSectionUsed != other.localSectionUsed) + } + if (localSectionUsed != other.localSectionUsed) { return false; - if (localTableVersion != other.localTableVersion) + } + if (localTableVersion != other.localTableVersion) { return false; - if (masterTableVersion != other.masterTableVersion) + } + if (masterTableVersion != other.masterTableVersion) { return false; + } if (modelInfo == null) { - if (other.modelInfo != null) + if (other.modelInfo != null) { return false; - } else if (!modelInfo.equals(other.modelInfo)) + } + } else if (!modelInfo.equals(other.modelInfo)) { return false; - if (processedDataType != other.processedDataType) + } + if (processedDataType != other.processedDataType) { return false; - if (productionStatus != other.productionStatus) + } + if (productionStatus != other.productionStatus) { return false; - if (refTimeSignificance != other.refTimeSignificance) + } + if (refTimeSignificance != other.refTimeSignificance) { return false; + } if (resCompFlags == null) { - if (other.resCompFlags != null) + if (other.resCompFlags != null) { return false; - } else if (!resCompFlags.equals(other.resCompFlags)) + } + } else if (!resCompFlags.equals(other.resCompFlags)) { return false; - if (thinnedGrid != other.thinnedGrid) + } + if (thinnedGrid != other.thinnedGrid) { return false; - if (!Arrays.equals(thinnedPts, other.thinnedPts)) + } + if (!Arrays.equals(thinnedPts, other.thinnedPts)) { return false; + } return true; } @@ -651,4 +670,9 @@ public class GribRecord extends PersistablePluginDataObject implements public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "grib"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridRecord.java index 29f006cc84..13701da938 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grid/src/com/raytheon/uf/common/dataplugin/grid/GridRecord.java @@ -61,11 +61,13 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * May 21, 2012 bsteffen Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * May 21, 2012 bsteffen Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -79,12 +81,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "grid", - indexes = { - @Index(name = "grid_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "grid", indexes = { @Index(name = "grid_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class GridRecord extends PersistablePluginDataObject implements ISpatialEnabled { @@ -110,7 +108,6 @@ public class GridRecord extends PersistablePluginDataObject implements } public GridRecord(GridRecord record) { - this.pluginName = record.getPluginName(); this.dataTime = record.getDataTime(); this.info = new GridInfoRecord(record.getInfoNotNull()); if (record.getExtraAttributes() != null) { @@ -236,24 +233,29 @@ public class GridRecord extends PersistablePluginDataObject implements public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + ((info == null) ? 0 : info.hashCode()); + result = (prime * result) + ((info == null) ? 0 : info.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } GridRecord other = (GridRecord) obj; if (info == null) { - if (other.info != null) + if (other.info != null) { return false; - } else if (!info.equals(other.info)) + } + } else if (!info.equals(other.info)) { return false; + } return true; } @@ -263,4 +265,9 @@ public class GridRecord extends PersistablePluginDataObject implements public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "grid"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ldadhydro/src/com/raytheon/uf/common/dataplugin/ldadhydro/HydroLdadRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ldadhydro/src/com/raytheon/uf/common/dataplugin/ldadhydro/HydroLdadRecord.java index ea11d952f7..83add3d259 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ldadhydro/src/com/raytheon/uf/common/dataplugin/ldadhydro/HydroLdadRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ldadhydro/src/com/raytheon/uf/common/dataplugin/ldadhydro/HydroLdadRecord.java @@ -70,11 +70,13 @@ import com.vividsolutions.jts.geom.Geometry; * * Date Ticket# Engineer Description * ----------- ---------- ----------- -------------------------- - * 9/30/09 vkorolev Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Sep 30, 2009 vkorolev Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -89,1073 +91,1075 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ldadhydro", - indexes = { - @Index(name = "ldadhydro_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ldadhydro", indexes = { @Index(name = "ldadhydro_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class HydroLdadRecord extends PersistablePluginDataObject implements - ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { + ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public static final String OBS_TEXT = "text"; + public static final String OBS_TEXT = "text"; - public static final Unit LENGTH_UNIT = SI.METER; + public static final Unit LENGTH_UNIT = SI.METER; - public static final Unit TEMPERATURE_UNIT = SI.KELVIN; + public static final Unit TEMPERATURE_UNIT = SI.KELVIN; - public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; + public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; - public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; - public static final Unit PRESSURE_UNIT = SI.PASCAL; + public static final Unit PRESSURE_UNIT = SI.PASCAL; - public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; - private static final HashMap PARM_MAP = new HashMap(); - static { - PARM_MAP.put("T", SFC_TEMP); - PARM_MAP.put("DpT", SFC_DWPT); - PARM_MAP.put("WS", SFC_WNDSPD); - PARM_MAP.put("WD", SFC_WNDDIR); - PARM_MAP.put("WGS", SFC_WNDGST); - PARM_MAP.put("ASET", "SFC.PRESS.ALTIMETER"); - PARM_MAP.put("PMSL", PRES_SLP); - PARM_MAP.put("NLAT", STA_LAT); - PARM_MAP.put("NLON", STA_LON); - PARM_MAP.put("STA", "STA"); - PARM_MAP.put("stationId", "STA"); - PARM_MAP.put("message", OBS_TEXT); - PARM_MAP.put(OBS_TEXT, OBS_TEXT); - } + private static final HashMap PARM_MAP = new HashMap(); + static { + PARM_MAP.put("T", SFC_TEMP); + PARM_MAP.put("DpT", SFC_DWPT); + PARM_MAP.put("WS", SFC_WNDSPD); + PARM_MAP.put("WD", SFC_WNDDIR); + PARM_MAP.put("WGS", SFC_WNDGST); + PARM_MAP.put("ASET", "SFC.PRESS.ALTIMETER"); + PARM_MAP.put("PMSL", PRES_SLP); + PARM_MAP.put("NLAT", STA_LAT); + PARM_MAP.put("NLON", STA_LON); + PARM_MAP.put("STA", "STA"); + PARM_MAP.put("stationId", "STA"); + PARM_MAP.put("message", OBS_TEXT); + PARM_MAP.put(OBS_TEXT, OBS_TEXT); + } - // Time of the observation. - @DataURI(position = 2) - @Column - @XmlAttribute - @DynamicSerializeElement - private Calendar observationTime; + // Time of the observation. + @DataURI(position = 2) + @Column + @XmlAttribute + @DynamicSerializeElement + private Calendar observationTime; - // numeric WMO identification number - @Column - @XmlElement - @DynamicSerializeElement - private long numericWMOid; + // numeric WMO identification number + @Column + @XmlElement + @DynamicSerializeElement + private long numericWMOid; - // latitude, longitude, elevation, stationId="RALC2" - @Embedded - @DataURI(position = 3, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; + // latitude, longitude, elevation, stationId="RALC2" + @Embedded + @DataURI(position = 3, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; - // Data Provider station Id - @Column - @XmlElement - @DynamicSerializeElement - private String providerId; // * "110" "FA6026DA" + // Data Provider station Id + @Column + @XmlElement + @DynamicSerializeElement + private String providerId; // * "110" "FA6026DA" - @Column - @XmlElement - @DynamicSerializeElement - private String stationName; // * "Ralston_Res" + @Column + @XmlElement + @DynamicSerializeElement + private String stationName; // * "Ralston_Res" - // Handbook Id (AFOS id or SHEF id) - @Column - @XmlElement - @DynamicSerializeElement - private String handbook5Id; + // Handbook Id (AFOS id or SHEF id) + @Column + @XmlElement + @DynamicSerializeElement + private String handbook5Id; - // Home WFO Id for the LDAD data - @Column - @XmlElement - @DynamicSerializeElement - private String homeWFO; + // Home WFO Id for the LDAD data + @Column + @XmlElement + @DynamicSerializeElement + private String homeWFO; - // LDAD hydro station type. - @Column - @XmlElement - @DynamicSerializeElement - private String stationType; + // LDAD hydro station type. + @Column + @XmlElement + @DynamicSerializeElement + private String stationType; - // LDAD hydro data provider - @DataURI(position = 1) - @Column - @XmlElement - @DynamicSerializeElement - private String dataProvider; + // LDAD hydro data provider + @DataURI(position = 1) + @Column + @XmlElement + @DynamicSerializeElement + private String dataProvider; - // time data was processed by the provider - @Column - @XmlElement - @DynamicSerializeElement - private double reportTime; // * 1.247436157E9 + // time data was processed by the provider + @Column + @XmlElement + @DynamicSerializeElement + private double reportTime; // * 1.247436157E9 - // * time data was received - @Column - @XmlElement - @DynamicSerializeElement - private Double receivedTime; // seconds since 1-1-1970 + // * time data was received + @Column + @XmlElement + @DynamicSerializeElement + private Double receivedTime; // seconds since 1-1-1970 - // Below surface - @Column - @XmlElement - @DynamicSerializeElement - private Float belowSurface; // meter + // Below surface + @Column + @XmlElement + @DynamicSerializeElement + private Float belowSurface; // meter - // River stage - @Column - @XmlElement - @DynamicSerializeElement - private Float riverStage; // meter + // River stage + @Column + @XmlElement + @DynamicSerializeElement + private Float riverStage; // meter - // Pool elevation - @Column - @XmlElement - @DynamicSerializeElement - private Float poolElevation; // meter + // Pool elevation + @Column + @XmlElement + @DynamicSerializeElement + private Float poolElevation; // meter - // Tail water stage - @Column - @XmlElement - @DynamicSerializeElement - private Float tailwaterStage; // meter + // Tail water stage + @Column + @XmlElement + @DynamicSerializeElement + private Float tailwaterStage; // meter - // River velocity - @Column - @XmlElement - @DynamicSerializeElement - private Float riverVelocity; // kph + // River velocity + @Column + @XmlElement + @DynamicSerializeElement + private Float riverVelocity; // kph - // River inflow - @Column - @XmlElement - @DynamicSerializeElement - private Float riverInflow; // meter^3 / sec + // River inflow + @Column + @XmlElement + @DynamicSerializeElement + private Float riverInflow; // meter^3 / sec - // River flow - @Column - @XmlElement - @DynamicSerializeElement - private Float riverFlow; // meter^3 / sec + // River flow + @Column + @XmlElement + @DynamicSerializeElement + private Float riverFlow; // meter^3 / sec - // Computed outflow - @Column - @XmlElement - @DynamicSerializeElement - private Float computedOutflow; // meter^3 / sec + // Computed outflow + @Column + @XmlElement + @DynamicSerializeElement + private Float computedOutflow; // meter^3 / sec - // Water temperature - @Column - @XmlElement - @DynamicSerializeElement - private Float waterTemperature; // kelvin + // Water temperature + @Column + @XmlElement + @DynamicSerializeElement + private Float waterTemperature; // kelvin - // Battery voltage - @Column - @XmlElement - @DynamicSerializeElement - private Float voltageBattery; // volt + // Battery voltage + @Column + @XmlElement + @DynamicSerializeElement + private Float voltageBattery; // volt - // Water conductance - @Column - @XmlElement - @DynamicSerializeElement - private Float waterConductance; // umhos/cm + // Water conductance + @Column + @XmlElement + @DynamicSerializeElement + private Float waterConductance; // umhos/cm - // Water oxygen - @Column - @XmlElement - @DynamicSerializeElement - private Float waterOxygen; // mg/l + // Water oxygen + @Column + @XmlElement + @DynamicSerializeElement + private Float waterOxygen; // mg/l - // Water PH - @Column - @XmlElement - @DynamicSerializeElement - private Float waterPH; // pH + // Water PH + @Column + @XmlElement + @DynamicSerializeElement + private Float waterPH; // pH - // Relative humidity - @Column - @XmlElement - @DynamicSerializeElement - private Float relHumidity; + // Relative humidity + @Column + @XmlElement + @DynamicSerializeElement + private Float relHumidity; - // River stage & flow - time of last change (ALERT) - @Column - @XmlElement - @DynamicSerializeElement - private Double riverReportChangeTime; // seconds since 1970-1-1 00:00:00.0 + // River stage & flow - time of last change (ALERT) + @Column + @XmlElement + @DynamicSerializeElement + private Double riverReportChangeTime; // seconds since 1970-1-1 00:00:00.0 - // Observation air temperature in degrees Kelvin. - @Column - @DynamicSerializeElement - @XmlElement - private Float temperature; + // Observation air temperature in degrees Kelvin. + @Column + @DynamicSerializeElement + @XmlElement + private Float temperature; - // Observation dewpoint temperature in degrees Kelvin. - @Column - @DynamicSerializeElement - @XmlElement - private Float dewpoint; + // Observation dewpoint temperature in degrees Kelvin. + @Column + @DynamicSerializeElement + @XmlElement + private Float dewpoint; - // Observation wind direction in angular degrees. - @Column - @DynamicSerializeElement - @XmlElement - private Float windDir; + // Observation wind direction in angular degrees. + @Column + @DynamicSerializeElement + @XmlElement + private Float windDir; - // Observation wind speed in meters per second. - @Column - @DynamicSerializeElement - @XmlElement - private Float windSpeed; + // Observation wind speed in meters per second. + @Column + @DynamicSerializeElement + @XmlElement + private Float windSpeed; - // Wind speed peak - @Column - @XmlElement - @DynamicSerializeElement - private Float windSpeedPeak; + // Wind speed peak + @Column + @XmlElement + @DynamicSerializeElement + private Float windSpeedPeak; - // Observation wind gust in meters per second. - @Column - @DynamicSerializeElement - @XmlElement - private Double windGust; + // Observation wind gust in meters per second. + @Column + @DynamicSerializeElement + @XmlElement + private Double windGust; - // precip accumulation with an unknown time period in mm. - @Column - @DynamicSerializeElement - @XmlElement - private Float precipAccum; // mm + // precip accumulation with an unknown time period in mm. + @Column + @DynamicSerializeElement + @XmlElement + private Float precipAccum; // mm - // 5 minute precip accumulation - @Column - @DynamicSerializeElement - @XmlElement - private Float precip5min; // mm + // 5 minute precip accumulation + @Column + @DynamicSerializeElement + @XmlElement + private Float precip5min; // mm - // 1 hour precip accumulation - @Column - @DynamicSerializeElement - @XmlElement - private Float precip1hr; // mm + // 1 hour precip accumulation + @Column + @DynamicSerializeElement + @XmlElement + private Float precip1hr; // mm - // 3 hour precip accumulation - @Column - @DynamicSerializeElement - @XmlElement - private Float precip3hr; // float precip3hr mm + // 3 hour precip accumulation + @Column + @DynamicSerializeElement + @XmlElement + private Float precip3hr; // float precip3hr mm - // 6 hour precip accumulation - @Column - @DynamicSerializeElement - @XmlElement - private Float precip6hr; // float precip6hr mm + // 6 hour precip accumulation + @Column + @DynamicSerializeElement + @XmlElement + private Float precip6hr; // float precip6hr mm - // 12 hour precip accumulation mm - @Column - @XmlElement - @DynamicSerializeElement - private Float precip12hr; + // 12 hour precip accumulation mm + @Column + @XmlElement + @DynamicSerializeElement + private Float precip12hr; - // 18 hour precip accumulation mm - @Column - @XmlElement - @DynamicSerializeElement - private Float precip18hr; + // 18 hour precip accumulation mm + @Column + @XmlElement + @DynamicSerializeElement + private Float precip18hr; - // 24 hour precip accumulation - @Column - @DynamicSerializeElement - @XmlElement - private Float precip24hr; // mm + // 24 hour precip accumulation + @Column + @DynamicSerializeElement + @XmlElement + private Float precip24hr; // mm - // Raw text LDAD hydro report - @Column - @DynamicSerializeElement - @XmlElement - private String rawMessage; + // Raw text LDAD hydro report + @Column + @DynamicSerializeElement + @XmlElement + private String rawMessage; - private PointDataView pointDataView; + private PointDataView pointDataView; - /** + /** * */ - public HydroLdadRecord() { - } + public HydroLdadRecord() { + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - */ - public HydroLdadRecord(String uri) { - super(uri); - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + */ + public HydroLdadRecord(String uri) { + super(uri); + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } - /** - * @return the location - */ - public SurfaceObsLocation getLocation() { - return location; - } + /** + * @return the location + */ + public SurfaceObsLocation getLocation() { + return location; + } - /** - * @param location - * the location to set - */ - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + /** + * @param location + * the location to set + */ + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - /** - * @return the timeObs - */ - public Calendar getObservationTime() { - return observationTime; - } + /** + * @return the timeObs + */ + public Calendar getObservationTime() { + return observationTime; + } - /** - * @param observationTime - * the observationTime to set - */ - public void setObservationTime(Calendar timeObs) { - this.observationTime = timeObs; - } + /** + * @param observationTime + * the observationTime to set + */ + public void setObservationTime(Calendar timeObs) { + this.observationTime = timeObs; + } - /** - * @return the windSpeed - */ - public Float getWindSpeed() { - return windSpeed; - } + /** + * @return the windSpeed + */ + public Float getWindSpeed() { + return windSpeed; + } - /** - * @param windSpeed - * the windSpeed to set - */ - public void setWindSpeed(Float windSpeed) { - this.windSpeed = windSpeed; - } + /** + * @param windSpeed + * the windSpeed to set + */ + public void setWindSpeed(Float windSpeed) { + this.windSpeed = windSpeed; + } - /** - * @return the windGust - */ - public Double getWindGust() { - return windGust; - } + /** + * @return the windGust + */ + public Double getWindGust() { + return windGust; + } - /** - * @param windGust - * the windGust to set - */ - public void setWindGust(Double windGust) { - this.windGust = windGust; - } + /** + * @param windGust + * the windGust to set + */ + public void setWindGust(Double windGust) { + this.windGust = windGust; + } - /** + /** * */ - public void setSpatialObject(SurfaceObsLocation loc) { - location = loc; - } + public void setSpatialObject(SurfaceObsLocation loc) { + location = loc; + } - /** + /** * */ - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } - /** - * This class implements IDecoderGettable so return this instance. - * - * @return The reference to this instance. - */ - @Override - public IDecoderGettable getDecoderGettable() { - return this; - } + /** + * This class implements IDecoderGettable so return this instance. + * + * @return The reference to this instance. + */ + @Override + public IDecoderGettable getDecoderGettable() { + return this; + } - /** + /** * */ - @Override - public String getString(String paramName) { - String retValue = null; - String pName = PARM_MAP.get(paramName); - if ("STA".matches(pName)) { - retValue = getStationId(); - } else if (OBS_TEXT.equals(pName)) { - retValue = getStationId(); - } + @Override + public String getString(String paramName) { + String retValue = null; + String pName = PARM_MAP.get(paramName); + if ("STA".matches(pName)) { + retValue = getStationId(); + } else if (OBS_TEXT.equals(pName)) { + retValue = getStationId(); + } - return retValue; - } + return retValue; + } - @Override - public String[] getStrings(String paramName) { - return null; - } + @Override + public String[] getStrings(String paramName) { + return null; + } - @Override - public Amount getValue(String paramName) { - Amount a = null; - String pName = PARM_MAP.get(paramName); + @Override + public Amount getValue(String paramName) { + Amount a = null; + String pName = PARM_MAP.get(paramName); - if (SFC_TEMP.equals(pName)) { - a = new Amount(temperature, TEMPERATURE_UNIT); - } else if (SFC_DWPT.equals(pName)) { - a = new Amount(dewpoint, TEMPERATURE_UNIT); - } else if (SFC_WNDSPD.equals(pName)) { - a = new Amount(windSpeed, WIND_SPEED_UNIT); - } else if (SFC_WNDGST.equals(pName)) { - a = new Amount(windGust, WIND_SPEED_UNIT); - } else if (SFC_WNDDIR.equals(pName)) { - a = new Amount(windDir, WIND_DIR_UNIT); - } else if (STA_LAT.equals(pName)) { - a = new Amount(getLatitude(), LOCATION_UNIT); - } else if (STA_LON.equals(pName)) { - a = new Amount(getLongitude(), LOCATION_UNIT); - } + if (SFC_TEMP.equals(pName)) { + a = new Amount(temperature, TEMPERATURE_UNIT); + } else if (SFC_DWPT.equals(pName)) { + a = new Amount(dewpoint, TEMPERATURE_UNIT); + } else if (SFC_WNDSPD.equals(pName)) { + a = new Amount(windSpeed, WIND_SPEED_UNIT); + } else if (SFC_WNDGST.equals(pName)) { + a = new Amount(windGust, WIND_SPEED_UNIT); + } else if (SFC_WNDDIR.equals(pName)) { + a = new Amount(windDir, WIND_DIR_UNIT); + } else if (STA_LAT.equals(pName)) { + a = new Amount(getLatitude(), LOCATION_UNIT); + } else if (STA_LON.equals(pName)) { + a = new Amount(getLongitude(), LOCATION_UNIT); + } - return a; - } + return a; + } - /** + /** * */ - @Override - public Collection getValues(String paramName) { - return null; - } - - /** - * @param providerId - * the providerId to set - */ - public void setProviderId(String providerId) { - this.providerId = providerId; - } - - /** - * @return the providerId - */ - public String getProviderId() { - return providerId; - } - - /** - * @param stationName - * the stationName to set - */ - public void setStationName(String stationName) { - this.stationName = stationName; - } - - /** - * @return the stationName - */ - public String getStationName() { - return stationName; - } - - /** - * @param handbook5Id - * the handbook5Id to set - */ - public void setHandbook5Id(String handbook5Id) { - this.handbook5Id = handbook5Id; - } - - /** - * @return the handbook5Id - */ - public String getHandbook5Id() { - return handbook5Id; - } - - /** - * @param homeWFO - * the homeWFO to set - */ - public void setHomeWFO(String homeWFO) { - this.homeWFO = homeWFO; - } - - /** - * @return the homeWFO - */ - public String getHomeWFO() { - return homeWFO; - } - - /** - * @param stationType - * the stationType to set - */ - public void setStationType(String stationType) { - this.stationType = stationType; - } - - /** - * @return the stationType - */ - public String getStationType() { - return stationType; - } - - /** - * @param dataProvider - * the dataProvider to set - */ - public void setDataProvider(String dataProvider) { - this.dataProvider = dataProvider; - } - - /** - * @return the dataProvider - */ - public String getDataProvider() { - return dataProvider; - } - - /** - * @param receivedTime - * the receivedTime to set - */ - public void setReceivedTime(Double receivedTime) { - this.receivedTime = receivedTime; - } - - /** - * @return the receivedTime - */ - public Double getReceivedTime() { - return receivedTime; - } - - /** - * @param belowSurface - * the belowSurface to set - */ - public void setBelowSurface(Float belowSurface) { - this.belowSurface = belowSurface; - } - - /** - * @return the belowSurface - */ - public Float getBelowSurface() { - return belowSurface; - } - - /** - * @param riverStage - * the riverStage to set - */ - public void setRiverStage(Float riverStage) { - this.riverStage = riverStage; - } - - /** - * @return the riverStage - */ - public Float getRiverStage() { - return riverStage; - } - - /** - * @param poolElevation - * the poolElevation to set - */ - public void setPoolElevation(Float poolElevation) { - this.poolElevation = poolElevation; - } - - /** - * @return the poolElevation - */ - public Float getPoolElevation() { - return poolElevation; - } - - /** - * @param tailwaterStage - * the tailwaterStage to set - */ - public void setTailwaterStage(Float tailwaterStage) { - this.tailwaterStage = tailwaterStage; - } - - /** - * @return the tailwaterStage - */ - public Float getTailwaterStage() { - return tailwaterStage; - } - - /** - * @param riverVelocity - * the riverVelocity to set - */ - public void setRiverVelocity(Float riverVelocity) { - this.riverVelocity = riverVelocity; - } - - /** - * @return the riverVelocity - */ - public Float getRiverVelocity() { - return riverVelocity; - } - - /** - * @param riverInflow - * the riverInflow to set - */ - public void setRiverInflow(Float riverInflow) { - this.riverInflow = riverInflow; - } - - /** - * @return the riverInflow - */ - public Float getRiverInflow() { - return riverInflow; - } - - /** - * @param riverFlow - * the riverFlow to set - */ - public void setRiverFlow(Float riverFlow) { - this.riverFlow = riverFlow; - } - - /** - * @return the riverFlow - */ - public Float getRiverFlow() { - return riverFlow; - } - - /** - * @param computedOutflow - * the computedOutflow to set - */ - public void setComputedOutflow(Float computedOutflow) { - this.computedOutflow = computedOutflow; - } - - /** - * @return the computedOutflow - */ - public Float getComputedOutflow() { - return computedOutflow; - } - - /** - * @param waterTemperature - * the waterTemperature to set - */ - public void setWaterTemperature(Float waterTemperature) { - this.waterTemperature = waterTemperature; - } - - /** - * @return the waterTemperature - */ - public Float getWaterTemperature() { - return waterTemperature; - } - - /** - * @param voltageBattery - * the voltageBattery to set - */ - public void setVoltageBattery(Float voltageBattery) { - this.voltageBattery = voltageBattery; - } - - /** - * @return the voltageBattery - */ - public Float getVoltageBattery() { - return voltageBattery; - } - - /** - * @param waterConductance - * the waterConductance to set - */ - public void setWaterConductance(Float waterConductance) { - this.waterConductance = waterConductance; - } - - /** - * @return the waterConductance - */ - public Float getWaterConductance() { - return waterConductance; - } - - /** - * @param waterOxygen - * the waterOxygen to set - */ - public void setWaterOxygen(Float waterOxygen) { - this.waterOxygen = waterOxygen; - } - - /** - * @return the waterOxygen - */ - public Float getWaterOxygen() { - return waterOxygen; - } - - /** - * @param waterPH - * the waterPH to set - */ - public void setWaterPH(Float waterPH) { - this.waterPH = waterPH; - } - - /** - * @return the waterPH - */ - public Float getWaterPH() { - return waterPH; - } - - /** - * @param riverReportChangeTime - * the riverReportChangeTime to set - */ - public void setRiverReportChangeTime(Double riverReportChangeTime) { - this.riverReportChangeTime = riverReportChangeTime; - } - - /** - * @return the riverReportChangeTime - */ - public Double getRiverReportChangeTime() { - return riverReportChangeTime; - } - - /** - * @param precip12hr - * the precip12hr to set - */ - public void setPrecip12hr(Float precip12hr) { - this.precip12hr = precip12hr; - } - - /** - * @return the precip12hr - */ - public Float getPrecip12hr() { - return precip12hr; - } - - /** - * @param precip18hr - * the precip18hr to set - */ - public void setPrecip18hr(Float precip18hr) { - this.precip18hr = precip18hr; - } - - /** - * @return the precip18hr - */ - public Float getPrecip18hr() { - return precip18hr; - } - - /** - * @param temperature - * the temperature to set - */ - public void setTemperature(Float temperature) { - this.temperature = temperature; - } - - /** - * @return the temperature - */ - public Float getTemperature() { - return temperature; - } - - /** - * @param dewpoint - * the dewpoint to set - */ - public void setDewpoint(Float dewpoint) { - this.dewpoint = dewpoint; - } - - /** - * @return the dewpoint - */ - public Float getDewpoint() { - return dewpoint; - } - - /** - * @param windDir - * the windDir to set - */ - public void setWindDir(Float windDir) { - this.windDir = windDir; - } - - /** - * @return the windDir - */ - public Float getWindDir() { - return windDir; - } - - /** - * @param windSpeedPeak - * the windSpeedPeak to set - */ - public void setWindSpeedPeak(Float windSpeedPeak) { - this.windSpeedPeak = windSpeedPeak; - } - - /** - * @return the windSpeedPeak - */ - public Float getWindSpeedPeak() { - return windSpeedPeak; - } - - /** - * @param precipAccum - * the precipAccum to set - */ - public void setPrecipAccum(Float precipAccum) { - this.precipAccum = precipAccum; - } - - /** - * @return the precipAccum - */ - public Float getPrecipAccum() { - return precipAccum; - } - - /** - * @param precip5min - * the precip5min to set - */ - public void setPrecip5min(Float precip5min) { - this.precip5min = precip5min; - } - - /** - * @return the precip5min - */ - public Float getPrecip5min() { - return precip5min; - } - - /** - * @param precip1hr - * the precip1hr to set - */ - public void setPrecip1hr(Float precip1hr) { - this.precip1hr = precip1hr; - } - - /** - * @return the precip1hr - */ - public Float getPrecip1hr() { - return precip1hr; - } - - /** - * @param precip3hr - * the precip3hr to set - */ - public void setPrecip3hr(Float precip3hr) { - this.precip3hr = precip3hr; - } - - /** - * @return the precip3hr - */ - public Float getPrecip3hr() { - return precip3hr; - } - - /** - * @param precip6hr - * the precip6hr to set - */ - public void setPrecip6hr(Float precip6hr) { - this.precip6hr = precip6hr; - } - - /** - * @return the precip6hr - */ - public Float getPrecip6hr() { - return precip6hr; - } - - /** - * @param precip24hr - * the precip24hr to set - */ - public void setPrecip24hr(Float precip24hr) { - this.precip24hr = precip24hr; - } - - /** - * @return the precip24hr - */ - public Float getPrecip24hr() { - return precip24hr; - } - - /** - * @param rawMessage - * the rawMessage to set - */ - public void setRawMessage(String rawMessage) { - this.rawMessage = rawMessage; - } - - /** - * @return the rawMessage - */ - public String getRawMessage() { - return rawMessage; - } - - /** - * @param relHumidity - * the relHumidity to set - */ - public void setRelHumidity(Float relHumidity) { - this.relHumidity = relHumidity; - } - - /** - * @return the relHumidity - */ - public Float getRelHumidity() { - return relHumidity; - } - - /** - * @param numericWMOid - * the numericWMOid to set - */ - public void setNumericWMOid(long numericWMOid) { - this.numericWMOid = numericWMOid; - } - - /** - * @return the numericWMOid - */ - public long getNumericWMOid() { - return numericWMOid; - } - - /** - * @param l - * the reportTime to set - */ - public void setReportTime(long l) { - this.reportTime = l; - } - - /** - * @return the reportTime - */ - public Double getReportTime() { - return reportTime; - } - - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - - } - - /** - * @return the pointDataView - */ - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } + @Override + public Collection getValues(String paramName) { + return null; + } + + /** + * @param providerId + * the providerId to set + */ + public void setProviderId(String providerId) { + this.providerId = providerId; + } + + /** + * @return the providerId + */ + public String getProviderId() { + return providerId; + } + + /** + * @param stationName + * the stationName to set + */ + public void setStationName(String stationName) { + this.stationName = stationName; + } + + /** + * @return the stationName + */ + public String getStationName() { + return stationName; + } + + /** + * @param handbook5Id + * the handbook5Id to set + */ + public void setHandbook5Id(String handbook5Id) { + this.handbook5Id = handbook5Id; + } + + /** + * @return the handbook5Id + */ + public String getHandbook5Id() { + return handbook5Id; + } + + /** + * @param homeWFO + * the homeWFO to set + */ + public void setHomeWFO(String homeWFO) { + this.homeWFO = homeWFO; + } + + /** + * @return the homeWFO + */ + public String getHomeWFO() { + return homeWFO; + } + + /** + * @param stationType + * the stationType to set + */ + public void setStationType(String stationType) { + this.stationType = stationType; + } + + /** + * @return the stationType + */ + public String getStationType() { + return stationType; + } + + /** + * @param dataProvider + * the dataProvider to set + */ + public void setDataProvider(String dataProvider) { + this.dataProvider = dataProvider; + } + + /** + * @return the dataProvider + */ + public String getDataProvider() { + return dataProvider; + } + + /** + * @param receivedTime + * the receivedTime to set + */ + public void setReceivedTime(Double receivedTime) { + this.receivedTime = receivedTime; + } + + /** + * @return the receivedTime + */ + public Double getReceivedTime() { + return receivedTime; + } + + /** + * @param belowSurface + * the belowSurface to set + */ + public void setBelowSurface(Float belowSurface) { + this.belowSurface = belowSurface; + } + + /** + * @return the belowSurface + */ + public Float getBelowSurface() { + return belowSurface; + } + + /** + * @param riverStage + * the riverStage to set + */ + public void setRiverStage(Float riverStage) { + this.riverStage = riverStage; + } + + /** + * @return the riverStage + */ + public Float getRiverStage() { + return riverStage; + } + + /** + * @param poolElevation + * the poolElevation to set + */ + public void setPoolElevation(Float poolElevation) { + this.poolElevation = poolElevation; + } + + /** + * @return the poolElevation + */ + public Float getPoolElevation() { + return poolElevation; + } + + /** + * @param tailwaterStage + * the tailwaterStage to set + */ + public void setTailwaterStage(Float tailwaterStage) { + this.tailwaterStage = tailwaterStage; + } + + /** + * @return the tailwaterStage + */ + public Float getTailwaterStage() { + return tailwaterStage; + } + + /** + * @param riverVelocity + * the riverVelocity to set + */ + public void setRiverVelocity(Float riverVelocity) { + this.riverVelocity = riverVelocity; + } + + /** + * @return the riverVelocity + */ + public Float getRiverVelocity() { + return riverVelocity; + } + + /** + * @param riverInflow + * the riverInflow to set + */ + public void setRiverInflow(Float riverInflow) { + this.riverInflow = riverInflow; + } + + /** + * @return the riverInflow + */ + public Float getRiverInflow() { + return riverInflow; + } + + /** + * @param riverFlow + * the riverFlow to set + */ + public void setRiverFlow(Float riverFlow) { + this.riverFlow = riverFlow; + } + + /** + * @return the riverFlow + */ + public Float getRiverFlow() { + return riverFlow; + } + + /** + * @param computedOutflow + * the computedOutflow to set + */ + public void setComputedOutflow(Float computedOutflow) { + this.computedOutflow = computedOutflow; + } + + /** + * @return the computedOutflow + */ + public Float getComputedOutflow() { + return computedOutflow; + } + + /** + * @param waterTemperature + * the waterTemperature to set + */ + public void setWaterTemperature(Float waterTemperature) { + this.waterTemperature = waterTemperature; + } + + /** + * @return the waterTemperature + */ + public Float getWaterTemperature() { + return waterTemperature; + } + + /** + * @param voltageBattery + * the voltageBattery to set + */ + public void setVoltageBattery(Float voltageBattery) { + this.voltageBattery = voltageBattery; + } + + /** + * @return the voltageBattery + */ + public Float getVoltageBattery() { + return voltageBattery; + } + + /** + * @param waterConductance + * the waterConductance to set + */ + public void setWaterConductance(Float waterConductance) { + this.waterConductance = waterConductance; + } + + /** + * @return the waterConductance + */ + public Float getWaterConductance() { + return waterConductance; + } + + /** + * @param waterOxygen + * the waterOxygen to set + */ + public void setWaterOxygen(Float waterOxygen) { + this.waterOxygen = waterOxygen; + } + + /** + * @return the waterOxygen + */ + public Float getWaterOxygen() { + return waterOxygen; + } + + /** + * @param waterPH + * the waterPH to set + */ + public void setWaterPH(Float waterPH) { + this.waterPH = waterPH; + } + + /** + * @return the waterPH + */ + public Float getWaterPH() { + return waterPH; + } + + /** + * @param riverReportChangeTime + * the riverReportChangeTime to set + */ + public void setRiverReportChangeTime(Double riverReportChangeTime) { + this.riverReportChangeTime = riverReportChangeTime; + } + + /** + * @return the riverReportChangeTime + */ + public Double getRiverReportChangeTime() { + return riverReportChangeTime; + } + + /** + * @param precip12hr + * the precip12hr to set + */ + public void setPrecip12hr(Float precip12hr) { + this.precip12hr = precip12hr; + } + + /** + * @return the precip12hr + */ + public Float getPrecip12hr() { + return precip12hr; + } + + /** + * @param precip18hr + * the precip18hr to set + */ + public void setPrecip18hr(Float precip18hr) { + this.precip18hr = precip18hr; + } + + /** + * @return the precip18hr + */ + public Float getPrecip18hr() { + return precip18hr; + } + + /** + * @param temperature + * the temperature to set + */ + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + /** + * @return the temperature + */ + public Float getTemperature() { + return temperature; + } + + /** + * @param dewpoint + * the dewpoint to set + */ + public void setDewpoint(Float dewpoint) { + this.dewpoint = dewpoint; + } + + /** + * @return the dewpoint + */ + public Float getDewpoint() { + return dewpoint; + } + + /** + * @param windDir + * the windDir to set + */ + public void setWindDir(Float windDir) { + this.windDir = windDir; + } + + /** + * @return the windDir + */ + public Float getWindDir() { + return windDir; + } + + /** + * @param windSpeedPeak + * the windSpeedPeak to set + */ + public void setWindSpeedPeak(Float windSpeedPeak) { + this.windSpeedPeak = windSpeedPeak; + } + + /** + * @return the windSpeedPeak + */ + public Float getWindSpeedPeak() { + return windSpeedPeak; + } + + /** + * @param precipAccum + * the precipAccum to set + */ + public void setPrecipAccum(Float precipAccum) { + this.precipAccum = precipAccum; + } + + /** + * @return the precipAccum + */ + public Float getPrecipAccum() { + return precipAccum; + } + + /** + * @param precip5min + * the precip5min to set + */ + public void setPrecip5min(Float precip5min) { + this.precip5min = precip5min; + } + + /** + * @return the precip5min + */ + public Float getPrecip5min() { + return precip5min; + } + + /** + * @param precip1hr + * the precip1hr to set + */ + public void setPrecip1hr(Float precip1hr) { + this.precip1hr = precip1hr; + } + + /** + * @return the precip1hr + */ + public Float getPrecip1hr() { + return precip1hr; + } + + /** + * @param precip3hr + * the precip3hr to set + */ + public void setPrecip3hr(Float precip3hr) { + this.precip3hr = precip3hr; + } + + /** + * @return the precip3hr + */ + public Float getPrecip3hr() { + return precip3hr; + } + + /** + * @param precip6hr + * the precip6hr to set + */ + public void setPrecip6hr(Float precip6hr) { + this.precip6hr = precip6hr; + } + + /** + * @return the precip6hr + */ + public Float getPrecip6hr() { + return precip6hr; + } + + /** + * @param precip24hr + * the precip24hr to set + */ + public void setPrecip24hr(Float precip24hr) { + this.precip24hr = precip24hr; + } + + /** + * @return the precip24hr + */ + public Float getPrecip24hr() { + return precip24hr; + } + + /** + * @param rawMessage + * the rawMessage to set + */ + public void setRawMessage(String rawMessage) { + this.rawMessage = rawMessage; + } + + /** + * @return the rawMessage + */ + public String getRawMessage() { + return rawMessage; + } + + /** + * @param relHumidity + * the relHumidity to set + */ + public void setRelHumidity(Float relHumidity) { + this.relHumidity = relHumidity; + } + + /** + * @return the relHumidity + */ + public Float getRelHumidity() { + return relHumidity; + } + + /** + * @param numericWMOid + * the numericWMOid to set + */ + public void setNumericWMOid(long numericWMOid) { + this.numericWMOid = numericWMOid; + } + + /** + * @return the numericWMOid + */ + public long getNumericWMOid() { + return numericWMOid; + } + + /** + * @param l + * the reportTime to set + */ + public void setReportTime(long l) { + this.reportTime = l; + } + + /** + * @return the reportTime + */ + public Double getReportTime() { + return reportTime; + } + + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + + } + + /** + * @return the pointDataView + */ + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ldadhydro"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ldadmesonet/src/com/raytheon/uf/common/dataplugin/ldadmesonet/LdadmesonetPointDataTransform.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ldadmesonet/src/com/raytheon/uf/common/dataplugin/ldadmesonet/LdadmesonetPointDataTransform.java index b075a2479f..ed82b06a2f 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ldadmesonet/src/com/raytheon/uf/common/dataplugin/ldadmesonet/LdadmesonetPointDataTransform.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ldadmesonet/src/com/raytheon/uf/common/dataplugin/ldadmesonet/LdadmesonetPointDataTransform.java @@ -25,9 +25,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.ldadmesonet.dao.LdadMesonetDao; import com.raytheon.uf.common.pointdata.PointDataContainer; @@ -44,7 +41,8 @@ import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 10/09/09 DR2814 vkorolev Initial creation + * Oct 09, 2009 DR2814 vkorolev Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -53,108 +51,173 @@ import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; */ public class LdadmesonetPointDataTransform { - - private Log logger = LogFactory.getLog(getClass()); - + private LdadMesonetDao dao; private PointDataDescription description; - //------------------Common params (From OBS plugin)---------------------------- - private static final String PRESS_CHANGE3_HOUR = "pressChange3Hour"; + + // ------------------Common params (From OBS + // plugin)---------------------------- + private static final String PRESS_CHANGE3_HOUR = "pressChange3Hour"; + private static final String PRESS_CHANGE_CHAR = "pressChangeChar"; + private static final String ALTIMETER = "altimeter"; + private static final String WIND_GUST = "windGust"; + private static final String WIND_SPEED = "windSpeed"; + private static final String DEWPOINT = "dewpoint"; + private static final String TEMPERATURE = "temperature"; + private static final String PRES_WEATHER = "presWeather"; + private static final String VISIBILITY = "visibility"; + private static final String LONGITUDE = "longitude"; + private static final String LATITUDE = "latitude"; - private static final String ELEVATION = "elevation"; + + private static final String ELEVATION = "elevation"; + private static final String STATION_NAME = "stationName"; + private static final String DATAURI = "dataURI"; - //------------------From LDAD mesonet netCDF------------------------ + + // ------------------From LDAD mesonet netCDF------------------------ private static final String STORAGE_TYPE = "storageType"; + private static final String STATION_ID = "stationId"; + private static final String DATA_PROVIDER = "dataProvider"; + private static final String HOME_WFO = "homeWFO"; + private static final String OBSERVATION_TIME = "observationTime"; + private static final String PROVIDER_ID = "providerId"; + private static final String HANDBOOK5_ID = "handbook5Id"; + private static final String STATION_TYPE = "stationType"; + private static final String REPORT_TIME = "reportTime"; + private static final String RECEIVED_TIME = "receivedTime"; + private static final String NUMERICAL_WMO_ID = "numericWMOid"; + private static final String DATA_PLATFORM_TYPE = "dataPlatformType"; + private static final String PLATFORM_TRUE_DIRECTION = "platformTrueDirection"; + private static final String PLARFORM_TRUE_SPEED = "platformTrueSpeed"; + private static final String TEMP_CHANGE_TIME = "tempChangeTime"; + private static final String WET_BULB_TEMPERATURE = "wetBulbTemperature"; + private static final String RH_CHANGE_TIME = "rhChangeTime"; + private static final String STATION_PRESSURE = "stationPressure"; + private static final String STATION_PRESS_CHANGE_TIME = "stationPressChangeTime"; + private static final String WIND_DIR_CHANGE_TIME = "windDirChangeTime"; + private static final String WIND_SPEED_CHANGE_TIME = "windSpeedChangeTime"; + private static final String WIND_GUST_CHANGE_TIME = "windGustChangeTime"; + private static final String WIND_DIR_MIN = "windDirMin"; + private static final String WIND_DIR_MAX = "windDirMax"; + private static final String VISIBILITY_STATUS = "visibilityStatus"; + private static final String TOTAL_CLOUD_COVER = "totalCloudCover"; + private static final String CLOUD_BASE_HEIGHT = "cloudBaseHeight"; + private static final String LOW_LEVEL_CLOUD_TYPE = "lowLevelCloudType"; + private static final String MID_LEVEL_CLOUD_TYPE = "midLevelCloudType"; + private static final String HIGH_LEVEL_CLOUD_TYPE = "highLevelCloudType"; + private static final String MAX_TEMP_RECORD_PERIOD = "maxTempRecordPeriod"; + private static final String MAXIMUM_TEMPERATURE = "maximumTemperature"; + private static final String MIN_TEMP_RECORD_PERIOD = "minTempRecordPeriod"; + private static final String MINIMUM_TEMPERATURE = "minimumTemperature"; + private static final String PRECIP_ACCUM = "precipAccum"; + private static final String PRECIP_TYPE = "precipType"; + private static final String PRECIP_INTENSITY = "precipIntensity"; + private static final String TIME_SINCE_LAST_PCP = "timeSinceLastPcp"; + private static final String SOLAR_RADIATION = "solarRadiation"; + private static final String SOLAR_RAD_CHANGE_TIME = "solarRadChangeTime"; + private static final String SEA_SURFACE_TEMP = "seaSurfaceTemp"; + private static final String WAVE_PERIOD = "wavePeriod"; + private static final String WAVE_HEIGHT = "waveHeight"; + private static final String RAW_MESONET = "rawMessage"; + private static final String REL_HUMIDITY = "relHumidity"; + private static final String WIND_DIR = "windDir"; + private static final String PRESSURE = "pressure"; + private static final String SEA_LEVEL_PRESSURE = "seaLevelPressure"; + private static final String PRECIP_RATE = "precipRate"; + private static final String FUEL_TEMPERATURE = "fuelTemperature"; + private static final String FUEL_MOISTURE = "fuelMoisture"; + private static final String SOIL_TEMPERATURE = "soilTemperature"; + private static final String SOIL_MOISTURE = "soilMoisture"; - + /** * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! It is important to * keep this up to date or risk breaking backwards compatibility * */ private static final String[] ALL_PARAMS = { PRESS_CHANGE3_HOUR, - PRESS_CHANGE_CHAR, ALTIMETER, WIND_GUST, WIND_SPEED, DEWPOINT, + PRESS_CHANGE_CHAR, ALTIMETER, WIND_GUST, WIND_SPEED, DEWPOINT, TEMPERATURE, PRES_WEATHER, VISIBILITY, LONGITUDE, LATITUDE, SEA_LEVEL_PRESSURE, STATION_NAME, DATAURI, STORAGE_TYPE, ELEVATION, - STATION_ID, DATA_PROVIDER, HOME_WFO, OBSERVATION_TIME, PROVIDER_ID, - HANDBOOK5_ID, STATION_TYPE, REPORT_TIME, RECEIVED_TIME, - NUMERICAL_WMO_ID, DATA_PLATFORM_TYPE, PLATFORM_TRUE_DIRECTION, - PLARFORM_TRUE_SPEED, TEMP_CHANGE_TIME, WET_BULB_TEMPERATURE, - RH_CHANGE_TIME, STATION_PRESSURE, STATION_PRESS_CHANGE_TIME, - WIND_DIR_CHANGE_TIME, WIND_SPEED_CHANGE_TIME, - WIND_GUST_CHANGE_TIME, WIND_DIR_MIN, WIND_DIR_MAX, - VISIBILITY_STATUS, TOTAL_CLOUD_COVER, CLOUD_BASE_HEIGHT, - LOW_LEVEL_CLOUD_TYPE, MID_LEVEL_CLOUD_TYPE, HIGH_LEVEL_CLOUD_TYPE, - MAX_TEMP_RECORD_PERIOD, MAXIMUM_TEMPERATURE, - MIN_TEMP_RECORD_PERIOD, MINIMUM_TEMPERATURE, PRECIP_ACCUM, PRECIP_TYPE, - PRECIP_INTENSITY, TIME_SINCE_LAST_PCP, SOLAR_RADIATION, - SOLAR_RAD_CHANGE_TIME, SEA_SURFACE_TEMP, WAVE_PERIOD, WAVE_HEIGHT, - RAW_MESONET, REL_HUMIDITY, WIND_DIR, PRESSURE, SEA_LEVEL_PRESSURE, - PRECIP_RATE, FUEL_TEMPERATURE, FUEL_MOISTURE, SOIL_TEMPERATURE, - SOIL_MOISTURE - }; + STATION_ID, DATA_PROVIDER, HOME_WFO, OBSERVATION_TIME, PROVIDER_ID, + HANDBOOK5_ID, STATION_TYPE, REPORT_TIME, RECEIVED_TIME, + NUMERICAL_WMO_ID, DATA_PLATFORM_TYPE, PLATFORM_TRUE_DIRECTION, + PLARFORM_TRUE_SPEED, TEMP_CHANGE_TIME, WET_BULB_TEMPERATURE, + RH_CHANGE_TIME, STATION_PRESSURE, STATION_PRESS_CHANGE_TIME, + WIND_DIR_CHANGE_TIME, WIND_SPEED_CHANGE_TIME, + WIND_GUST_CHANGE_TIME, WIND_DIR_MIN, WIND_DIR_MAX, + VISIBILITY_STATUS, TOTAL_CLOUD_COVER, CLOUD_BASE_HEIGHT, + LOW_LEVEL_CLOUD_TYPE, MID_LEVEL_CLOUD_TYPE, HIGH_LEVEL_CLOUD_TYPE, + MAX_TEMP_RECORD_PERIOD, MAXIMUM_TEMPERATURE, + MIN_TEMP_RECORD_PERIOD, MINIMUM_TEMPERATURE, PRECIP_ACCUM, + PRECIP_TYPE, PRECIP_INTENSITY, TIME_SINCE_LAST_PCP, + SOLAR_RADIATION, SOLAR_RAD_CHANGE_TIME, SEA_SURFACE_TEMP, + WAVE_PERIOD, WAVE_HEIGHT, RAW_MESONET, REL_HUMIDITY, WIND_DIR, + PRESSURE, SEA_LEVEL_PRESSURE, PRECIP_RATE, FUEL_TEMPERATURE, + FUEL_MOISTURE, SOIL_TEMPERATURE, SOIL_MOISTURE }; public static final String ALL_PARAMS_LIST; static { @@ -192,11 +255,12 @@ public class LdadmesonetPointDataTransform { if (pdo.length > 0) { Map pointMap = new HashMap(); - + for (PluginDataObject p : pdo) { - if (!(p instanceof MesonetLdadRecord)) + if (!(p instanceof MesonetLdadRecord)) { continue; - + } + File f = this.dao.getFullFilePath(p); PointDataContainer pdc = pointMap.get(f); @@ -213,228 +277,198 @@ public class LdadmesonetPointDataTransform { return pdo; } - // private PointDataDescription getDescription(String type) - // throws JAXBException { - // InputStream is = this.getClass().getResourceAsStream( - // "/res/pointdata/" + type + ".xml"); - // if (is == null) { - // throw new RuntimeException("Cannot find descriptor for: " + type); - // } - // return PointDataDescription.fromStream(is); - // - // } - private PointDataView buildView(PointDataContainer container, - MesonetLdadRecord record) { + MesonetLdadRecord record) { PointDataView pdv = container.append(); - - -// if (record.getStationName()!=null) { -// pdv.setString(STATION_NAME, record.getStationName()); -// } - if (record.getRawMessage()!=null) { - pdv.setString(RAW_MESONET, record.getRawMessage()); - } - if (record.getSeaLevelPressure()!=null) { - pdv.setFloat(SEA_LEVEL_PRESSURE, record.getSeaLevelPressure()); - } - // if (record.getLocation()!=null) { - // pdv.setFloat(LATITUDE, (float) record.getLatitude()); - // pdv.setFloat(LONGITUDE, (float) record.getLongitude()); - // pdv.setFloat(ELEVATION, record.getElevation()); - // } - if (record.getObservationTime()!=null) { + + if (record.getRawMessage() != null) { + pdv.setString(RAW_MESONET, record.getRawMessage()); + } + if (record.getSeaLevelPressure() != null) { + pdv.setFloat(SEA_LEVEL_PRESSURE, record.getSeaLevelPressure()); + } + + if (record.getObservationTime() != null) { pdv.setLong(OBSERVATION_TIME, record.getDataTime().getRefTime() .getTime()); - } - if (record.getVisibility()!=null) { - pdv.setFloat(VISIBILITY, record.getVisibility()); - } - if (record.getTemperature()!=null) { - pdv.setFloat(TEMPERATURE, record.getTemperature()); - } - if (record.getDewpoint()!=null) { - pdv.setFloat(DEWPOINT, record.getDewpoint()); - } - if (record.getWindSpeed()!=null) { - pdv.setFloat(WIND_SPEED, record.getWindSpeed()); - } - if (record.getWindGust()!=null) { - pdv.setFloat(WIND_GUST, record.getWindGust()); - } - if (record.getAltimeter()!=null) { - pdv.setFloat(ALTIMETER, record.getAltimeter()); - } - if (record.getPressChangeChar()!=null) { - pdv.setInt(PRESS_CHANGE_CHAR, record.getPressChangeChar() - .intValue()); - } - if (record.getPressChange3Hour()!=null) { - pdv.setFloat(PRESS_CHANGE3_HOUR, record.getPressChange3Hour()); - } - //pdv.setString(DATAURI, record.getDataURI()); - -//--------------------------------------LDAD mesonet specific------------------------ - -// if (record.getDataProvider()!=null) { -// pdv.setString(DATA_PROVIDER, record.getDataProvider()); -// } -// if (record.getHomeWFO()!=null) { -// pdv.setString(HOME_WFO, record.getHomeWFO()); -// } -// if (record.getProviderId()!=null) { -// pdv.setString(PROVIDER_ID, record.getProviderId()); -// } -// if (record.getHandbook5Id()!=null) { -// pdv.setString(HANDBOOK5_ID, record.getHandbook5Id()); -// } -// if (record.getStationType()!=null) { -// pdv.setString(STATION_TYPE, record.getStationType()); -// } - if (record.getReportTime()!=null) { - pdv.setLong(REPORT_TIME, record.getReportTime()); - } - if (record.getReceivedTime()!=null) { - pdv.setLong(RECEIVED_TIME, record.getReceivedTime().longValue()); - } - if (record.getNumericWMOid()!=null) { - pdv.setLong(NUMERICAL_WMO_ID, record.getNumericWMOid()); - } - if (record.getDataPlatformType()!=null) { - pdv.setInt(DATA_PLATFORM_TYPE, record.getDataPlatformType().intValue()); - } - if (record.getPlatformTrueDirection()!=null) { - pdv.setFloat(PLATFORM_TRUE_DIRECTION, record.getPlatformTrueDirection()); - } - if (record.getPlatformTrueSpeed()!=null) { - pdv.setFloat(PLARFORM_TRUE_SPEED, record.getPlatformTrueSpeed()); - } - if (record.getTempChangeTime()!=null) { - pdv.setLong(TEMP_CHANGE_TIME, record.getTempChangeTime() - .longValue()); - } - if (record.getWetBulbTemperature()!=null) { - pdv.setFloat(WET_BULB_TEMPERATURE, record.getWetBulbTemperature()); - } - if (record.getRhChangeTime()!=null) { - pdv.setLong(RH_CHANGE_TIME, record.getRhChangeTime().longValue()); - } - if (record.getStationPressure()!=null) { - pdv.setFloat(STATION_PRESSURE, record.getStationPressure()); - } - if (record.getStationPressChangeTime()!=null) { - pdv.setLong(STATION_PRESS_CHANGE_TIME, record.getStationPressChangeTime().longValue()); - } - if (record.getWindDirChangeTime()!=null) { - pdv.setLong(WIND_DIR_CHANGE_TIME, record.getWindDirChangeTime() - .longValue()); - } - if (record.getWindSpeedChangeTime()!=null) { - pdv.setLong(WIND_SPEED_CHANGE_TIME, record.getWindSpeedChangeTime() - .longValue()); - } - if (record.getWindGustChangeTime()!=null) { - pdv.setLong(WIND_GUST_CHANGE_TIME, record.getWindGustChangeTime() - .longValue()); - } - if (record.getWindDirMin()!=null) { - pdv.setFloat(WIND_DIR_MIN, record.getWindDirMin()); - } - if (record.getWindDirMax()!=null) { - pdv.setFloat(WIND_DIR_MAX, record.getWindDirMax()); - } - if (record.getVisibilityStatus()!=null) { - pdv.setString(VISIBILITY_STATUS, record.getVisibilityStatus()); - } - if (record.getTotalCloudCover()!=null) { - pdv.setFloat(TOTAL_CLOUD_COVER, record.getTotalCloudCover()); - } - if (record.getCloudBaseHeight()!=null) { - pdv.setInt(CLOUD_BASE_HEIGHT, record.getCloudBaseHeight() - .intValue()); - } - if (record.getLowLevelCloudType()!=null) { - pdv.setInt(LOW_LEVEL_CLOUD_TYPE, record.getLowLevelCloudType() - .intValue()); - } - if (record.getMidLevelCloudType()!=null) { - pdv.setInt(MID_LEVEL_CLOUD_TYPE, record.getMidLevelCloudType() - .intValue()); - } - if (record.getHighLevelCloudType()!=null) { - pdv.setInt(HIGH_LEVEL_CLOUD_TYPE, record.getHighLevelCloudType() - .intValue()); - } - if (record.getMinTempRecordPeriod()!=null) { - pdv.setInt(MAX_TEMP_RECORD_PERIOD, record.getMinTempRecordPeriod() - .intValue()); - } - if (record.getMaximumTemperature()!=null) { - pdv.setFloat(MAXIMUM_TEMPERATURE, record.getMaximumTemperature()); - } - if (record.getMinTempRecordPeriod()!=null) { - pdv.setInt(MIN_TEMP_RECORD_PERIOD, record.getMinTempRecordPeriod() - .intValue()); - } - if (record.getMinimumTemperature()!=null) { - pdv.setFloat(MINIMUM_TEMPERATURE, record.getMinimumTemperature()); - } - if (record.getPrecipAccum()!=null) { - pdv.setFloat(PRECIP_ACCUM, record.getPrecipAccum()); - } - if (record.getPrecipType()!=null) { - pdv.setInt(PRECIP_TYPE, record.getPrecipType().intValue()); - } - if (record.getPrecipIntensity()!=null) { - pdv.setInt(PRECIP_INTENSITY, record.getPrecipIntensity().intValue()); - } - if (record.getTimeSinceLastPcp()!=null) { - pdv.setLong(TIME_SINCE_LAST_PCP, record.getTimeSinceLastPcp() - .longValue()); - } - if (record.getSolarRadiation()!=null) { - pdv.setFloat(SOLAR_RADIATION, record.getSolarRadiation()); - } - if (record.getSolarRadChangeTime()!=null) { - pdv.setLong(SOLAR_RAD_CHANGE_TIME, record.getSolarRadChangeTime().longValue()); - } - if (record.getSeaSurfaceTemp()!=null) { - pdv.setFloat(SEA_SURFACE_TEMP, record.getSeaSurfaceTemp()); - } - if (record.getWavePeriod()!=null) { - pdv.setFloat(WAVE_PERIOD, record.getWavePeriod()); - } - if (record.getWaveHeight()!=null) { - pdv.setFloat(WAVE_HEIGHT, record.getWaveHeight()); - } - if (record.getRelHumidity()!=null) { - pdv.setFloat(REL_HUMIDITY, record.getRelHumidity()); - } - if (record.getWindDir()!=null) { - pdv.setFloat(WIND_DIR, record.getWindDir()); - } - if (record.getPressure()!=null) { - pdv.setFloat(PRESSURE, record.getPressure()); - } - if (record.getSeaLevelPressure()!=null) { - pdv.setFloat(SEA_LEVEL_PRESSURE, record.getSeaLevelPressure()); - } - if (record.getPrecipRate()!=null) { - pdv.setFloat(PRECIP_RATE, record.getPrecipRate()); - } - if (record.getFuelTemperature()!=null) { - pdv.setFloat(FUEL_TEMPERATURE, record.getFuelTemperature()); - } - if (record.getFuelMoisture()!=null) { - pdv.setFloat(FUEL_MOISTURE, record.getFuelMoisture()); - } - if (record.getSoilTemperature()!=null) { - pdv.setFloat(SOIL_TEMPERATURE, record.getSoilTemperature()); - } - if (record.getSoilMoisture()!=null) { - pdv.setFloat(SOIL_MOISTURE, record.getSoilMoisture()); - } - return pdv; + } + if (record.getVisibility() != null) { + pdv.setFloat(VISIBILITY, record.getVisibility()); + } + if (record.getTemperature() != null) { + pdv.setFloat(TEMPERATURE, record.getTemperature()); + } + if (record.getDewpoint() != null) { + pdv.setFloat(DEWPOINT, record.getDewpoint()); + } + if (record.getWindSpeed() != null) { + pdv.setFloat(WIND_SPEED, record.getWindSpeed()); + } + if (record.getWindGust() != null) { + pdv.setFloat(WIND_GUST, record.getWindGust()); + } + if (record.getAltimeter() != null) { + pdv.setFloat(ALTIMETER, record.getAltimeter()); + } + if (record.getPressChangeChar() != null) { + pdv.setInt(PRESS_CHANGE_CHAR, record.getPressChangeChar() + .intValue()); + } + if (record.getPressChange3Hour() != null) { + pdv.setFloat(PRESS_CHANGE3_HOUR, record.getPressChange3Hour()); + } + + // --------------------------------------LDAD mesonet + // specific------------------------ + + if (record.getReportTime() != null) { + pdv.setLong(REPORT_TIME, record.getReportTime()); + } + if (record.getReceivedTime() != null) { + pdv.setLong(RECEIVED_TIME, record.getReceivedTime().longValue()); + } + if (record.getNumericWMOid() != null) { + pdv.setLong(NUMERICAL_WMO_ID, record.getNumericWMOid()); + } + if (record.getDataPlatformType() != null) { + pdv.setInt(DATA_PLATFORM_TYPE, record.getDataPlatformType() + .intValue()); + } + if (record.getPlatformTrueDirection() != null) { + pdv.setFloat(PLATFORM_TRUE_DIRECTION, + record.getPlatformTrueDirection()); + } + if (record.getPlatformTrueSpeed() != null) { + pdv.setFloat(PLARFORM_TRUE_SPEED, record.getPlatformTrueSpeed()); + } + if (record.getTempChangeTime() != null) { + pdv.setLong(TEMP_CHANGE_TIME, record.getTempChangeTime() + .longValue()); + } + if (record.getWetBulbTemperature() != null) { + pdv.setFloat(WET_BULB_TEMPERATURE, record.getWetBulbTemperature()); + } + if (record.getRhChangeTime() != null) { + pdv.setLong(RH_CHANGE_TIME, record.getRhChangeTime().longValue()); + } + if (record.getStationPressure() != null) { + pdv.setFloat(STATION_PRESSURE, record.getStationPressure()); + } + if (record.getStationPressChangeTime() != null) { + pdv.setLong(STATION_PRESS_CHANGE_TIME, record + .getStationPressChangeTime().longValue()); + } + if (record.getWindDirChangeTime() != null) { + pdv.setLong(WIND_DIR_CHANGE_TIME, record.getWindDirChangeTime() + .longValue()); + } + if (record.getWindSpeedChangeTime() != null) { + pdv.setLong(WIND_SPEED_CHANGE_TIME, record.getWindSpeedChangeTime() + .longValue()); + } + if (record.getWindGustChangeTime() != null) { + pdv.setLong(WIND_GUST_CHANGE_TIME, record.getWindGustChangeTime() + .longValue()); + } + if (record.getWindDirMin() != null) { + pdv.setFloat(WIND_DIR_MIN, record.getWindDirMin()); + } + if (record.getWindDirMax() != null) { + pdv.setFloat(WIND_DIR_MAX, record.getWindDirMax()); + } + if (record.getVisibilityStatus() != null) { + pdv.setString(VISIBILITY_STATUS, record.getVisibilityStatus()); + } + if (record.getTotalCloudCover() != null) { + pdv.setFloat(TOTAL_CLOUD_COVER, record.getTotalCloudCover()); + } + if (record.getCloudBaseHeight() != null) { + pdv.setInt(CLOUD_BASE_HEIGHT, record.getCloudBaseHeight() + .intValue()); + } + if (record.getLowLevelCloudType() != null) { + pdv.setInt(LOW_LEVEL_CLOUD_TYPE, record.getLowLevelCloudType() + .intValue()); + } + if (record.getMidLevelCloudType() != null) { + pdv.setInt(MID_LEVEL_CLOUD_TYPE, record.getMidLevelCloudType() + .intValue()); + } + if (record.getHighLevelCloudType() != null) { + pdv.setInt(HIGH_LEVEL_CLOUD_TYPE, record.getHighLevelCloudType() + .intValue()); + } + if (record.getMinTempRecordPeriod() != null) { + pdv.setInt(MAX_TEMP_RECORD_PERIOD, record.getMinTempRecordPeriod() + .intValue()); + } + if (record.getMaximumTemperature() != null) { + pdv.setFloat(MAXIMUM_TEMPERATURE, record.getMaximumTemperature()); + } + if (record.getMinTempRecordPeriod() != null) { + pdv.setInt(MIN_TEMP_RECORD_PERIOD, record.getMinTempRecordPeriod() + .intValue()); + } + if (record.getMinimumTemperature() != null) { + pdv.setFloat(MINIMUM_TEMPERATURE, record.getMinimumTemperature()); + } + if (record.getPrecipAccum() != null) { + pdv.setFloat(PRECIP_ACCUM, record.getPrecipAccum()); + } + if (record.getPrecipType() != null) { + pdv.setInt(PRECIP_TYPE, record.getPrecipType().intValue()); + } + if (record.getPrecipIntensity() != null) { + pdv.setInt(PRECIP_INTENSITY, record.getPrecipIntensity().intValue()); + } + if (record.getTimeSinceLastPcp() != null) { + pdv.setLong(TIME_SINCE_LAST_PCP, record.getTimeSinceLastPcp() + .longValue()); + } + if (record.getSolarRadiation() != null) { + pdv.setFloat(SOLAR_RADIATION, record.getSolarRadiation()); + } + if (record.getSolarRadChangeTime() != null) { + pdv.setLong(SOLAR_RAD_CHANGE_TIME, record.getSolarRadChangeTime() + .longValue()); + } + if (record.getSeaSurfaceTemp() != null) { + pdv.setFloat(SEA_SURFACE_TEMP, record.getSeaSurfaceTemp()); + } + if (record.getWavePeriod() != null) { + pdv.setFloat(WAVE_PERIOD, record.getWavePeriod()); + } + if (record.getWaveHeight() != null) { + pdv.setFloat(WAVE_HEIGHT, record.getWaveHeight()); + } + if (record.getRelHumidity() != null) { + pdv.setFloat(REL_HUMIDITY, record.getRelHumidity()); + } + if (record.getWindDir() != null) { + pdv.setFloat(WIND_DIR, record.getWindDir()); + } + if (record.getPressure() != null) { + pdv.setFloat(PRESSURE, record.getPressure()); + } + if (record.getSeaLevelPressure() != null) { + pdv.setFloat(SEA_LEVEL_PRESSURE, record.getSeaLevelPressure()); + } + if (record.getPrecipRate() != null) { + pdv.setFloat(PRECIP_RATE, record.getPrecipRate()); + } + if (record.getFuelTemperature() != null) { + pdv.setFloat(FUEL_TEMPERATURE, record.getFuelTemperature()); + } + if (record.getFuelMoisture() != null) { + pdv.setFloat(FUEL_MOISTURE, record.getFuelMoisture()); + } + if (record.getSoilTemperature() != null) { + pdv.setFloat(SOIL_TEMPERATURE, record.getSoilTemperature()); + } + if (record.getSoilMoisture() != null) { + pdv.setFloat(SOIL_MOISTURE, record.getSoilMoisture()); + } + return pdv; } public static MesonetLdadRecord toMesonetLdadRecord(PointDataView pdv) { @@ -445,14 +479,13 @@ public class LdadmesonetPointDataTransform { pdv.getString(STATION_ID)); Double lat = pdv.getNumber(LATITUDE).doubleValue(); Double lon = pdv.getNumber(LONGITUDE).doubleValue(); - loc.assignLocation(lat,lon); + loc.assignLocation(lat, lon); loc.setElevation(pdv.getNumber(ELEVATION).intValue()); mr.setLocation(loc); - mr.setPluginName("ldadmesonet"); mr.setReportType(pdv.getString(STORAGE_TYPE)); mr.setProviderId(pdv.getString(PROVIDER_ID)); mr.setPressChange3Hour(pdv.getNumber(PRESS_CHANGE3_HOUR).floatValue()); - mr.setPressChangeChar((short) pdv.getInt(PRESS_CHANGE_CHAR)); + mr.setPressChangeChar((short) pdv.getInt(PRESS_CHANGE_CHAR)); mr.setSeaLevelPressure(pdv.getNumber(SEA_LEVEL_PRESSURE).floatValue()); mr.setTemperature(pdv.getNumber(TEMPERATURE).floatValue()); mr.setVisibility(pdv.getNumber(VISIBILITY).floatValue()); @@ -461,50 +494,53 @@ public class LdadmesonetPointDataTransform { mr.setWindSpeed(pdv.getFloat(WIND_SPEED)); mr.setDataURI(pdv.getString(DATAURI)); mr.setReceivedTime(pdv.getNumber(RECEIVED_TIME).doubleValue()); -//---------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------- mr.setTempChangeTime(pdv.getNumber(TEMP_CHANGE_TIME).doubleValue()); - mr.setWetBulbTemperature(pdv.getFloat(WET_BULB_TEMPERATURE)); - mr.setRhChangeTime((Double) pdv.getNumber(RH_CHANGE_TIME)); - mr.setStationPressure(pdv.getFloat(STATION_PRESSURE)); - mr.setStationPressChangeTime((Double) pdv.getNumber(STATION_PRESS_CHANGE_TIME)); - mr.setWindDirChangeTime((Double) pdv.getNumber(WIND_DIR_CHANGE_TIME)); - mr.setWindSpeedChangeTime((Double) pdv.getNumber(WIND_SPEED_CHANGE_TIME)); - mr.setWindGustChangeTime((Double) pdv.getNumber(WIND_GUST_CHANGE_TIME)); + mr.setWetBulbTemperature(pdv.getFloat(WET_BULB_TEMPERATURE)); + mr.setRhChangeTime((Double) pdv.getNumber(RH_CHANGE_TIME)); + mr.setStationPressure(pdv.getFloat(STATION_PRESSURE)); + mr.setStationPressChangeTime((Double) pdv + .getNumber(STATION_PRESS_CHANGE_TIME)); + mr.setWindDirChangeTime((Double) pdv.getNumber(WIND_DIR_CHANGE_TIME)); + mr.setWindSpeedChangeTime((Double) pdv + .getNumber(WIND_SPEED_CHANGE_TIME)); + mr.setWindGustChangeTime((Double) pdv.getNumber(WIND_GUST_CHANGE_TIME)); mr.setWindDirMin(pdv.getFloat(WIND_DIR_MIN)); mr.setWindDirMax(pdv.getFloat(WIND_DIR_MAX)); - mr.setVisibilityStatus(pdv.getString(VISIBILITY_STATUS )); - mr.setTotalCloudCover(pdv.getFloat(TOTAL_CLOUD_COVER )); + mr.setVisibilityStatus(pdv.getString(VISIBILITY_STATUS)); + mr.setTotalCloudCover(pdv.getFloat(TOTAL_CLOUD_COVER)); mr.setCloudBaseHeight((Short) pdv.getNumber(CLOUD_BASE_HEIGHT)); mr.setLowLevelCloudType((Short) pdv.getNumber(LOW_LEVEL_CLOUD_TYPE)); - mr.setMidLevelCloudType((Short) pdv.getNumber(MID_LEVEL_CLOUD_TYPE )); - mr.setHighLevelCloudType((Short) pdv.getNumber(HIGH_LEVEL_CLOUD_TYPE )); - mr.setMaxTempRecordPeriod((Short) pdv.getNumber(MAX_TEMP_RECORD_PERIOD )); - mr.setMaximumTemperature(pdv.getFloat(MAXIMUM_TEMPERATURE )); - mr.setMinTempRecordPeriod((Short) pdv.getNumber(MIN_TEMP_RECORD_PERIOD )); - mr.setMaximumTemperature(pdv.getFloat(MINIMUM_TEMPERATURE )); - mr.setPrecipAccum(pdv.getFloat(PRECIP_ACCUM )); - mr.setPrecipType((Short) pdv.getNumber(PRECIP_TYPE )); - mr.setPrecipIntensity((Short) pdv.getNumber(PRECIP_INTENSITY )); - mr.setTimeSinceLastPcp((Double) pdv.getNumber(TIME_SINCE_LAST_PCP )); - mr.setSolarRadiation(pdv.getFloat(SOLAR_RADIATION )); - mr.setSolarRadChangeTime((Double) pdv.getNumber(SOLAR_RAD_CHANGE_TIME )); - mr.setSeaSurfaceTemp(pdv.getFloat(SEA_SURFACE_TEMP )); - mr.setWavePeriod(pdv.getFloat(WAVE_PERIOD )); - mr.setWaveHeight(pdv.getFloat(WAVE_HEIGHT )); + mr.setMidLevelCloudType((Short) pdv.getNumber(MID_LEVEL_CLOUD_TYPE)); + mr.setHighLevelCloudType((Short) pdv.getNumber(HIGH_LEVEL_CLOUD_TYPE)); + mr.setMaxTempRecordPeriod((Short) pdv.getNumber(MAX_TEMP_RECORD_PERIOD)); + mr.setMaximumTemperature(pdv.getFloat(MAXIMUM_TEMPERATURE)); + mr.setMinTempRecordPeriod((Short) pdv.getNumber(MIN_TEMP_RECORD_PERIOD)); + mr.setMaximumTemperature(pdv.getFloat(MINIMUM_TEMPERATURE)); + mr.setPrecipAccum(pdv.getFloat(PRECIP_ACCUM)); + mr.setPrecipType((Short) pdv.getNumber(PRECIP_TYPE)); + mr.setPrecipIntensity((Short) pdv.getNumber(PRECIP_INTENSITY)); + mr.setTimeSinceLastPcp((Double) pdv.getNumber(TIME_SINCE_LAST_PCP)); + mr.setSolarRadiation(pdv.getFloat(SOLAR_RADIATION)); + mr.setSolarRadChangeTime((Double) pdv.getNumber(SOLAR_RAD_CHANGE_TIME)); + mr.setSeaSurfaceTemp(pdv.getFloat(SEA_SURFACE_TEMP)); + mr.setWavePeriod(pdv.getFloat(WAVE_PERIOD)); + mr.setWaveHeight(pdv.getFloat(WAVE_HEIGHT)); mr.setRawMessage(pdv.getString(RAW_MESONET)); - mr.setRelHumidity(pdv.getFloat(REL_HUMIDITY)); - mr.setWindDir(pdv.getFloat(WIND_DIR )); - mr.setPressure(pdv.getFloat(PRESSURE )); - mr.setSeaLevelPressure(pdv.getFloat(SEA_LEVEL_PRESSURE )); - mr.setPrecipRate(pdv.getFloat(PRECIP_RATE )); - mr.setFuelTemperature(pdv.getFloat(FUEL_TEMPERATURE )); - mr.setFuelMoisture(pdv.getFloat(FUEL_MOISTURE )); - mr.setSoilTemperature(pdv.getFloat(SOIL_TEMPERATURE )); - mr.setSoilMoisture(pdv.getFloat(SOIL_MOISTURE )); + mr.setRelHumidity(pdv.getFloat(REL_HUMIDITY)); + mr.setWindDir(pdv.getFloat(WIND_DIR)); + mr.setPressure(pdv.getFloat(PRESSURE)); + mr.setSeaLevelPressure(pdv.getFloat(SEA_LEVEL_PRESSURE)); + mr.setPrecipRate(pdv.getFloat(PRECIP_RATE)); + mr.setFuelTemperature(pdv.getFloat(FUEL_TEMPERATURE)); + mr.setFuelMoisture(pdv.getFloat(FUEL_MOISTURE)); + mr.setSoilTemperature(pdv.getFloat(SOIL_TEMPERATURE)); + mr.setSoilMoisture(pdv.getFloat(SOIL_MOISTURE)); return mr; } - public static MesonetLdadRecord[] toMesonetLdadRecords(PointDataContainer container) { + public static MesonetLdadRecord[] toMesonetLdadRecords( + PointDataContainer container) { List records = new ArrayList(); container.setCurrentSz(container.getAllocatedSz()); for (int i = 0; i < container.getCurrentSz(); i++) { diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ldadmesonet/src/com/raytheon/uf/common/dataplugin/ldadmesonet/MesonetLdadRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ldadmesonet/src/com/raytheon/uf/common/dataplugin/ldadmesonet/MesonetLdadRecord.java index c8b169b277..0889f89703 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ldadmesonet/src/com/raytheon/uf/common/dataplugin/ldadmesonet/MesonetLdadRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ldadmesonet/src/com/raytheon/uf/common/dataplugin/ldadmesonet/MesonetLdadRecord.java @@ -60,6 +60,7 @@ import com.vividsolutions.jts.geom.Geometry; * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * May 15, 2013 1869 bsteffen Remove DataURI column from ldadmesonet. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -76,1590 +77,1590 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ldadmesonet", - indexes = { - @Index(name = "ldadmesonet_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ldadmesonet", indexes = { @Index(name = "ldadmesonet_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class MesonetLdadRecord extends PersistablePluginDataObject implements ISpatialEnabled, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; private static final String OBS_TIME_FMT = "%1$tY/% * @@ -86,475 +88,477 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "lsr", - indexes = { - @Index(name = "lsr_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "lsr", indexes = { @Index(name = "lsr_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class LocalStormReport extends PersistablePluginDataObject implements - ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { - - private static final long serialVersionUID = 1L; - - private static final int MISSING = -9999; - - public static final Unit TEMPERATURE_UNIT = SI.KELVIN; - - public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; - - public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; - - public static final Unit PRESSURE_UNIT = SI.PASCAL; - - public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; - - public static final Unit WAVE_UNIT = SI.METER; - - public static final Unit VISIBILITY_UNIT = NonSI.MILE; - - public static final Unit CLOUD_COVER = NonSI.OCTET; - - // - @DataURI(position = 1) - @Column - @XmlElement - @DynamicSerializeElement - private LSREventType eventType; - - // Correction indicator from wmo header - @DataURI(position = 2) - @Column - @XmlElement - @DynamicSerializeElement - private String corIndicator; - - @Embedded - @DataURI(position = 3, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - // Text of the WMO header - @Transient - @XmlElement - @DynamicSerializeElement - private String wmoHeader = ""; - - // Text of the office - @XmlElement - @DynamicSerializeElement - private String officeid = ""; - - // - @Transient - @XmlElement - @DynamicSerializeElement - private String cityLoc = ""; - - // - @Transient - @XmlElement - @DynamicSerializeElement - private String source = ""; - - // - @Transient - @XmlElement - @DynamicSerializeElement - private String countyLoc = ""; - - // - @Transient - @XmlElement - @DynamicSerializeElement - private String stateLoc = ""; - - // - @Transient - @XmlElement - @DynamicSerializeElement - private String remarks = ""; - - // - @Transient - @XmlElement - @DynamicSerializeElement - private Float magnitude = -9999.0f; - - // 0 = unknown - // 1 = estimated - // 2 = measured - // 3 = - // 4 = - @Transient - @XmlElement - @DynamicSerializeElement - private Integer magQual = MISSING; - - // - @Transient - @XmlElement - @DynamicSerializeElement - private Integer injuries = MISSING; - - // - @Transient - @XmlElement - @DynamicSerializeElement - private Integer fatalities = MISSING; - - /** - * Empty default constructor - */ - public LocalStormReport() { - } - - /** - * Construct an instance of this class using the supplied datauri. - * - * @param dataUri - */ - public LocalStormReport(String dataUri) { - super(dataUri); - } - - /** - * @return the eventType - */ - public LSREventType getEventType() { - return eventType; - } - - /** - * @param eventType - * the eventType to set - */ - public void setEventType(LSREventType eventType) { - this.eventType = eventType; - } - - /** - * @return the corIndicator - */ - public String getCorIndicator() { - return corIndicator; - } - - /** - * @param corIndicator - * the corIndicator to set - */ - public void setCorIndicator(String corIndicator) { - this.corIndicator = corIndicator; - } - - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } - - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } - - /** - * @return the officeid - */ - public String getOfficeid() { - return officeid; - } - - /** - * @param officeid - * the officeid to set - */ - public void setOfficeid(String officeid) { - this.officeid = officeid; - } - - /** - * @return the cityLoc - */ - public String getCityLoc() { - return cityLoc; - } - - /** - * @param cityLoc - * the cityLoc to set - */ - public void setCityLoc(String cityLoc) { - this.cityLoc = cityLoc; - } - - /** - * @return the source - */ - public String getSource() { - return source; - } - - /** - * @param source - * the source to set - */ - public void setSource(String source) { - this.source = source; - } - - /** - * @return the countyLoc - */ - public String getCountyLoc() { - return countyLoc; - } - - /** - * @param countyLoc - * the countyLoc to set - */ - public void setCountyLoc(String countyLoc) { - this.countyLoc = countyLoc; - } - - /** - * @return the stateLoc - */ - public String getStateLoc() { - return stateLoc; - } - - /** - * @param stateLoc - * the stateLoc to set - */ - public void setStateLoc(String stateLoc) { - this.stateLoc = stateLoc; - } - - /** - * @return the remarks - */ - public String getRemarks() { - return remarks; - } - - /** - * @param remarks - * the remarks to set - */ - public void setRemarks(String remarks) { - this.remarks = remarks; - } - - /** - * @return the magnitude - */ - public Float getMagnitude() { - return magnitude; - } - - /** - * @param magnitude - * the magnitude to set - */ - public void setMagnitude(Float magnitude) { - this.magnitude = magnitude; - } - - /** - * @return the magQual - */ - public Integer getMagQual() { - return magQual; - } - - /** - * @param magQual - * the magQual to set - */ - public void setMagQual(Integer magQual) { - this.magQual = magQual; - } - - /** - * @return the injuries - */ - public Integer getInjuries() { - return injuries; - } - - /** - * @param injuries - * the injuries to set - */ - public void setInjuries(Integer injuries) { - this.injuries = injuries; - } - - /** - * @return the fatalities - */ - public Integer getFatalities() { - return fatalities; - } - - /** - * @param fatalities - * the fatalities to set - */ - public void setFatalities(Integer fatalities) { - this.fatalities = fatalities; - } - - /** - * Set the data uri for this observation. - * - * @param dataURI - */ - @Override - public void setDataURI(String dataURI) { - super.setDataURI(dataURI); - identifier = dataURI; - } - - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } - - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } - - public SurfaceObsLocation getLocation() { - return location; - } - - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } - - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } - - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } - - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } - - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } - - /** - * Get whether the location for this observation is defined. - * - * @return Is this location defined. - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } - - @Override - public Amount getValue(String paramName) { - return null; - } - - @Override - public String getString(String paramName) { - return null; - } - - @Override - public String[] getStrings(String paramName) { - return null; - } - - @Override - public Collection getValues(String paramName) { - return null; - } - - @Override - public PointDataView getPointDataView() { - return pointDataView; - } - - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - Calendar c = getDataTime().getRefTimeAsCalendar(); - if (c != null) { - sb.append(String.format("LSR:%1$tY%1$tm%1$td%1$tH%1$tM", - getDataTime().getRefTimeAsCalendar())); - } else { - sb.append("LSR:YYYYMMDDHHmm"); - } - sb.append(String.format("%6.2f %7.2f:", getLatitude(), getLongitude())); - sb.append(String.format("%s:", cityLoc)); - sb.append(String.format("%s:", eventType.getEventName())); - sb.append(String.format("%5.2f:%s", getMagnitude(), getEventType() - .getEventUnits())); - return sb.toString(); - } + ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { + + private static final long serialVersionUID = 1L; + + private static final int MISSING = -9999; + + public static final Unit TEMPERATURE_UNIT = SI.KELVIN; + + public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; + + public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; + + public static final Unit PRESSURE_UNIT = SI.PASCAL; + + public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; + + public static final Unit WAVE_UNIT = SI.METER; + + public static final Unit VISIBILITY_UNIT = NonSI.MILE; + + public static final Unit CLOUD_COVER = NonSI.OCTET; + + // + @DataURI(position = 1) + @Column + @XmlElement + @DynamicSerializeElement + private LSREventType eventType; + + // Correction indicator from wmo header + @DataURI(position = 2) + @Column + @XmlElement + @DynamicSerializeElement + private String corIndicator; + + @Embedded + @DataURI(position = 3, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + // Text of the WMO header + @Transient + @XmlElement + @DynamicSerializeElement + private String wmoHeader = ""; + + // Text of the office + @XmlElement + @DynamicSerializeElement + private String officeid = ""; + + // + @Transient + @XmlElement + @DynamicSerializeElement + private String cityLoc = ""; + + // + @Transient + @XmlElement + @DynamicSerializeElement + private String source = ""; + + // + @Transient + @XmlElement + @DynamicSerializeElement + private String countyLoc = ""; + + // + @Transient + @XmlElement + @DynamicSerializeElement + private String stateLoc = ""; + + // + @Transient + @XmlElement + @DynamicSerializeElement + private String remarks = ""; + + // + @Transient + @XmlElement + @DynamicSerializeElement + private Float magnitude = -9999.0f; + + // 0 = unknown + // 1 = estimated + // 2 = measured + // 3 = + // 4 = + @Transient + @XmlElement + @DynamicSerializeElement + private Integer magQual = MISSING; + + // + @Transient + @XmlElement + @DynamicSerializeElement + private Integer injuries = MISSING; + + // + @Transient + @XmlElement + @DynamicSerializeElement + private Integer fatalities = MISSING; + + /** + * Empty default constructor + */ + public LocalStormReport() { + } + + /** + * Construct an instance of this class using the supplied datauri. + * + * @param dataUri + */ + public LocalStormReport(String dataUri) { + super(dataUri); + } + + /** + * @return the eventType + */ + public LSREventType getEventType() { + return eventType; + } + + /** + * @param eventType + * the eventType to set + */ + public void setEventType(LSREventType eventType) { + this.eventType = eventType; + } + + /** + * @return the corIndicator + */ + public String getCorIndicator() { + return corIndicator; + } + + /** + * @param corIndicator + * the corIndicator to set + */ + public void setCorIndicator(String corIndicator) { + this.corIndicator = corIndicator; + } + + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } + + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } + + /** + * @return the officeid + */ + public String getOfficeid() { + return officeid; + } + + /** + * @param officeid + * the officeid to set + */ + public void setOfficeid(String officeid) { + this.officeid = officeid; + } + + /** + * @return the cityLoc + */ + public String getCityLoc() { + return cityLoc; + } + + /** + * @param cityLoc + * the cityLoc to set + */ + public void setCityLoc(String cityLoc) { + this.cityLoc = cityLoc; + } + + /** + * @return the source + */ + public String getSource() { + return source; + } + + /** + * @param source + * the source to set + */ + public void setSource(String source) { + this.source = source; + } + + /** + * @return the countyLoc + */ + public String getCountyLoc() { + return countyLoc; + } + + /** + * @param countyLoc + * the countyLoc to set + */ + public void setCountyLoc(String countyLoc) { + this.countyLoc = countyLoc; + } + + /** + * @return the stateLoc + */ + public String getStateLoc() { + return stateLoc; + } + + /** + * @param stateLoc + * the stateLoc to set + */ + public void setStateLoc(String stateLoc) { + this.stateLoc = stateLoc; + } + + /** + * @return the remarks + */ + public String getRemarks() { + return remarks; + } + + /** + * @param remarks + * the remarks to set + */ + public void setRemarks(String remarks) { + this.remarks = remarks; + } + + /** + * @return the magnitude + */ + public Float getMagnitude() { + return magnitude; + } + + /** + * @param magnitude + * the magnitude to set + */ + public void setMagnitude(Float magnitude) { + this.magnitude = magnitude; + } + + /** + * @return the magQual + */ + public Integer getMagQual() { + return magQual; + } + + /** + * @param magQual + * the magQual to set + */ + public void setMagQual(Integer magQual) { + this.magQual = magQual; + } + + /** + * @return the injuries + */ + public Integer getInjuries() { + return injuries; + } + + /** + * @param injuries + * the injuries to set + */ + public void setInjuries(Integer injuries) { + this.injuries = injuries; + } + + /** + * @return the fatalities + */ + public Integer getFatalities() { + return fatalities; + } + + /** + * @param fatalities + * the fatalities to set + */ + public void setFatalities(Integer fatalities) { + this.fatalities = fatalities; + } + + /** + * Set the data uri for this observation. + * + * @param dataURI + */ + @Override + public void setDataURI(String dataURI) { + super.setDataURI(dataURI); + identifier = dataURI; + } + + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } + + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } + + public SurfaceObsLocation getLocation() { + return location; + } + + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } + + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } + + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } + + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } + + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } + + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } + + /** + * Get whether the location for this observation is defined. + * + * @return Is this location defined. + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } + + @Override + public Amount getValue(String paramName) { + return null; + } + + @Override + public String getString(String paramName) { + return null; + } + + @Override + public String[] getStrings(String paramName) { + return null; + } + + @Override + public Collection getValues(String paramName) { + return null; + } + + @Override + public PointDataView getPointDataView() { + return pointDataView; + } + + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Calendar c = getDataTime().getRefTimeAsCalendar(); + if (c != null) { + sb.append(String.format("LSR:%1$tY%1$tm%1$td%1$tH%1$tM", + getDataTime().getRefTimeAsCalendar())); + } else { + sb.append("LSR:YYYYMMDDHHmm"); + } + sb.append(String.format("%6.2f %7.2f:", getLatitude(), getLongitude())); + sb.append(String.format("%s:", cityLoc)); + sb.append(String.format("%s:", eventType.getEventName())); + sb.append(String.format("%5.2f:%s", getMagnitude(), getEventType() + .getEventUnits())); + return sb.toString(); + } + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "lsr"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.npp.crimss/src/com/raytheon/uf/common/dataplugin/npp/crimss/CrimssRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.npp.crimss/src/com/raytheon/uf/common/dataplugin/npp/crimss/CrimssRecord.java index f924464cad..84bb14f688 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.npp.crimss/src/com/raytheon/uf/common/dataplugin/npp/crimss/CrimssRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.npp.crimss/src/com/raytheon/uf/common/dataplugin/npp/crimss/CrimssRecord.java @@ -43,10 +43,11 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Dec 2, 2011 bsteffen Initial creation + * Dec 02, 2011 bsteffen Initial creation * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -84,4 +85,8 @@ public class CrimssRecord extends NPPSoundingRecord { return super.getDataURI(); } + @Override + public String getPluginName() { + return "crimss"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.npp.nucaps/src/com/raytheon/uf/common/dataplugin/npp/nucaps/NucapsRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.npp.nucaps/src/com/raytheon/uf/common/dataplugin/npp/nucaps/NucapsRecord.java index 055dc9e102..b77931e636 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.npp.nucaps/src/com/raytheon/uf/common/dataplugin/npp/nucaps/NucapsRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.npp.nucaps/src/com/raytheon/uf/common/dataplugin/npp/nucaps/NucapsRecord.java @@ -43,10 +43,11 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 15, 2013 mschenke Initial creation + * Jan 15, 2013 mschenke Initial creation * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -92,4 +93,8 @@ public class NucapsRecord extends NPPSoundingRecord { return super.getDataURI(); } + @Override + public String getPluginName() { + return "nucaps"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.npp.viirs/src/com/raytheon/uf/common/dataplugin/npp/viirs/VIIRSDataRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.npp.viirs/src/com/raytheon/uf/common/dataplugin/npp/viirs/VIIRSDataRecord.java index 5bfa9b08bd..a6f5a1a84d 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.npp.viirs/src/com/raytheon/uf/common/dataplugin/npp/viirs/VIIRSDataRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.npp.viirs/src/com/raytheon/uf/common/dataplugin/npp/viirs/VIIRSDataRecord.java @@ -53,11 +53,13 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Nov 30, 2011 mschenke Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Nov 30, 2011 mschenke Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -71,12 +73,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "viirs", - indexes = { - @Index(name = "viirs_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "viirs", indexes = { @Index(name = "viirs_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class VIIRSDataRecord extends PersistablePluginDataObject implements ISpatialEnabled { @@ -127,7 +125,6 @@ public class VIIRSDataRecord extends PersistablePluginDataObject implements private VIIRSSpatialCoverage coverage; public VIIRSDataRecord() { - setPluginName(VIIRSDataRecord.class.getAnnotation(Table.class).name()); } /* @@ -256,8 +253,9 @@ public class VIIRSDataRecord extends PersistablePluginDataObject implements @Override public Date getPersistenceTime() { Calendar c = getInsertTime(); - if (c == null) + if (c == null) { return null; + } return c.getTime(); } @@ -296,10 +294,16 @@ public class VIIRSDataRecord extends PersistablePluginDataObject implements public IDecoderGettable getDecoderGettable() { return null; } + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "viirs"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.obs/src/com/raytheon/uf/common/dataplugin/obs/metar/MetarRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.obs/src/com/raytheon/uf/common/dataplugin/obs/metar/MetarRecord.java index a864957ea4..173fad6ece 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.obs/src/com/raytheon/uf/common/dataplugin/obs/metar/MetarRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.obs/src/com/raytheon/uf/common/dataplugin/obs/metar/MetarRecord.java @@ -25,7 +25,6 @@ import java.util.Calendar; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.SortedSet; @@ -76,24 +75,28 @@ import com.raytheon.uf.common.time.util.TimeUtil; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ---------- ---------- ----------- -------------------------- - * 02/14/07 139 bphillip Initial creation - * Nov 15, 2007 njensen Added static units info. - * 20071129 472 jkorman Added IDecoderGettable interface. - * 20071204 472 jkorman getValue was using wrong select value. - * Dec 07,2007 452 bphillip Added station lat/lon - * 20071217 472 jkorman Changed to use ALTIMETER_UNIT. - * 20071221 666 jkorman Modified to default all numerics to -9999. - * 20090423 2338 jsanchez Implemented precip plots, cloud/vis. - * Added @DynamicSerializeElement to location. - * 20090528 2225 jsanchez Implemented tempFromTenths and dewPointFromTenths. - * 20090629 2538 jsanchez Made the sort public. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. - * May 07, 2013 1869 bsteffen Remove dataURI column from + * Date Ticket# Engineer Description + * ------------ ---------- ----------- --------------------------------------- + * Feb 14, 2007 139 bphillip Initial creation + * Nov 15, 2007 njensen Added static units info. + * Nov 29, 2007 472 jkorman Added IDecoderGettable interface. + * Dec 04, 2007 472 jkorman getValue was using wrong select value. + * Dec 07, 2007 452 bphillip Added station lat/lon + * Dec 17, 2007 472 jkorman Changed to use ALTIMETER_UNIT. + * Dec 21, 2007 666 jkorman Modified to default all numerics to + * -9999. + * Apr 23, 2009 2338 jsanchez Implemented precip plots, cloud/vis. + * Added @DynamicSerializeElement to + * location. + * May 28, 2009 2225 jsanchez Implemented tempFromTenths and + * dewPointFromTenths. + * Jun 29, 2009 2538 jsanchez Made the sort public. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. - * + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author bphillip @@ -106,1611 +109,1612 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "obs", - indexes = { - @Index(name = "obs_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "obs", indexes = { @Index(name = "obs_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class MetarRecord extends PersistablePluginDataObject implements - ISpatialEnabled, IDecoderGettable, IPointData { + ISpatialEnabled, IDecoderGettable, IPointData { - public static final String PLUGIN_NAME = "obs"; + public static final String PLUGIN_NAME = "obs"; - public static final String STATION_ID = "stationId"; + public static final String STATION_ID = "stationId"; - public static final Unit TEMPERATURE_UNIT = SI.CELSIUS; + public static final Unit TEMPERATURE_UNIT = SI.CELSIUS; - public static final Unit WIND_SPEED_UNIT = NonSI.KNOT; + public static final Unit WIND_SPEED_UNIT = NonSI.KNOT; - public static final Unit HEIGHT_UNIT = SI.METER; + public static final Unit HEIGHT_UNIT = SI.METER; - public static final Unit VISIBILITY_UNIT = SI.KILO(NonSI.MILE); + public static final Unit VISIBILITY_UNIT = SI.KILO(NonSI.MILE); - public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; - public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; - public static final Unit PRESSURE_UNIT = SI.HECTO(SI.PASCAL); + public static final Unit PRESSURE_UNIT = SI.HECTO(SI.PASCAL); - public static final Unit ALTIMETER_UNIT = SI.PASCAL; + public static final Unit ALTIMETER_UNIT = SI.PASCAL; - public static final Unit PRECIP_UNIT = NonSI.INCH; + public static final Unit PRECIP_UNIT = NonSI.INCH; - /** Metar specific parameter keys */ - public static final class ParameterKey { - public static final String SFC_ALTIMETER = "SFC.PRESS.ALTIMETER"; + /** Metar specific parameter keys */ + public static final class ParameterKey { + public static final String SFC_ALTIMETER = "SFC.PRESS.ALTIMETER"; - public static final String PRESSURE_CHANGE = "PCHNG"; + public static final String PRESSURE_CHANGE = "PCHNG"; - public static final String VISIBILITY = "VIS"; + public static final String VISIBILITY = "VIS"; - public static final String PRECIPITATION_1HR = "PR1HR"; + public static final String PRECIPITATION_1HR = "PR1HR"; - public static final String PRECIPITATION_3HR = "PR3HR"; + public static final String PRECIPITATION_3HR = "PR3HR"; - public static final String PRECIPITATION_6HR = "PR6HR"; + public static final String PRECIPITATION_6HR = "PR6HR"; - public static final String PRECIPITATION_24HR = "PR24HR"; - } + public static final String PRECIPITATION_24HR = "PR24HR"; + } - /** Parameter keys used in the legacy system */ - public static final class LegacyParameterKey { + /** Parameter keys used in the legacy system */ + public static final class LegacyParameterKey { - public static final String TEMPERATURE = "T"; + public static final String TEMPERATURE = "T"; - public static final String DEW_POINT = "DpT"; + public static final String DEW_POINT = "DpT"; - public static final String WIND_SPEED = "wSp"; + public static final String WIND_SPEED = "wSp"; - public static final String WIND_DIRECTION = "WD"; + public static final String WIND_DIRECTION = "WD"; - public static final String WIND_GUST = "Gust"; + public static final String WIND_GUST = "Gust"; - public static final String ALTIMETER = "Alti"; + public static final String ALTIMETER = "Alti"; - public static final String SEA_LEVEL_PRESSURE = "msl-P"; + public static final String SEA_LEVEL_PRESSURE = "msl-P"; - public static final String PRESSURE_CHANGE_3HR = "PT3"; + public static final String PRESSURE_CHANGE_3HR = "PT3"; - public static final String VISABILITY = "Vis"; + public static final String VISABILITY = "Vis"; - public static final String PRECIPITATION_1HR = "TP"; + public static final String PRECIPITATION_1HR = "TP"; - public static final String PRECIPITATION_3HR = "TP3hr"; + public static final String PRECIPITATION_3HR = "TP3hr"; - public static final String PRECIPITATION_6HR = "TP6hr"; + public static final String PRECIPITATION_6HR = "TP6hr"; - public static final String PRECIPITATION_24HR = "TP24hr"; + public static final String PRECIPITATION_24HR = "TP24hr"; - // public static final String SNOW_DEPTH = "snow"; - // - // public static final String SNOW_WATER = "weqs"; - // - // public static final String SNOWFALL6_HOUR = "TP24hr"; - // - // public static final String SUNSHINE = "msun"; - // - // public static final String TEMP_MAX_6HOUR = "t6xc"; - // - // public static final String TEMP_MIN_6HOUR = "t6nc"; + // public static final String SNOW_DEPTH = "snow"; + // + // public static final String SNOW_WATER = "weqs"; + // + // public static final String SNOWFALL6_HOUR = "TP24hr"; + // + // public static final String SUNSHINE = "msun"; + // + // public static final String TEMP_MAX_6HOUR = "t6xc"; + // + // public static final String TEMP_MIN_6HOUR = "t6nc"; - private String value; + private String value; - /** - * - * @param value - * the value of this legacy parameter key - */ - public void setValue(String value) { - this.value = value; - } + /** + * + * @param value + * the value of this legacy parameter key + */ + public void setValue(String value) { + this.value = value; + } - /** - * - * @return the value of this legacy parameter key - */ - public String getValue() { - return value; - } + /** + * + * @return the value of this legacy parameter key + */ + public String getValue() { + return value; + } - } + } - /** Serializable id * */ - private static final long serialVersionUID = 1L; + /** Serializable id * */ + private static final long serialVersionUID = 1L; + + /** + * Maps common AWIPS I keys to IDecoderGettable and newer parameter key + * constants + */ + private static final HashMap PARM_MAP = new HashMap(); + static { + PARM_MAP.put(LegacyParameterKey.TEMPERATURE, SFC_TEMP); + PARM_MAP.put(LegacyParameterKey.DEW_POINT, SFC_DWPT); + PARM_MAP.put(LegacyParameterKey.WIND_SPEED, SFC_WNDSPD); + PARM_MAP.put(LegacyParameterKey.WIND_DIRECTION, SFC_WNDDIR); + PARM_MAP.put(LegacyParameterKey.WIND_GUST, SFC_WNDGST); + PARM_MAP.put(LegacyParameterKey.ALTIMETER, ParameterKey.SFC_ALTIMETER); + PARM_MAP.put(LegacyParameterKey.SEA_LEVEL_PRESSURE, PRES_SLP); + PARM_MAP.put("NLAT", STA_LAT); + PARM_MAP.put("NLON", STA_LON); + PARM_MAP.put(LegacyParameterKey.PRESSURE_CHANGE_3HR, + ParameterKey.PRESSURE_CHANGE); + // PARM_MAP.put("T24", "T24"); // not used + // PARM_MAP.put("DpT24", "DpT24"); // not used + // PARM_MAP.put("WS24", "WS24"); // not used + // PARM_MAP.put("WD24", "WD24"); // not used + // PARM_MAP.put("WGS24", "WGS24"); // not used + // PARM_MAP.put("ASET24", "ASET24"); // not used + // PARM_MAP.put("HIWC", "HIWC"); // not used + PARM_MAP.put(LegacyParameterKey.VISABILITY, ParameterKey.VISIBILITY); + PARM_MAP.put(LegacyParameterKey.PRECIPITATION_1HR, + ParameterKey.PRECIPITATION_1HR); + PARM_MAP.put(LegacyParameterKey.PRECIPITATION_3HR, + ParameterKey.PRECIPITATION_3HR); + PARM_MAP.put(LegacyParameterKey.PRECIPITATION_6HR, + ParameterKey.PRECIPITATION_6HR); + PARM_MAP.put(LegacyParameterKey.PRECIPITATION_24HR, + ParameterKey.PRECIPITATION_24HR); + } + + @Transient + private String sampleType = null; + + @Transient + private boolean isSkyCoverageSorted = false; + + @XmlElement + @DynamicSerializeElement + @Transient + private String report; + + @XmlElement + @DynamicSerializeElement + @Transient + private String wmoHeader; + + /** Nominal Time extracted from WMO header * */ + @XmlElement + @DynamicSerializeElement + @Transient + private String nominalTime; + + /** A string denoting the time of observation */ + @XmlElement + @DynamicSerializeElement + @Transient + private Calendar timeObs; + + /** Report type extracted from WMO header * */ + @XmlElement + @DynamicSerializeElement + @Column + @DataURI(position = 1) + protected String reportType; + + /** A string denoting if this report is a correction */ + @XmlElement + @DynamicSerializeElement + @Column + @DataURI(position = 2) + private String correction; + + @Embedded + @DataURI(position = 3, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; + + /** A string denoting the type of automated station (AO1 or AO2) */ + @XmlElement + @DynamicSerializeElement + @Transient + private String autoStationType; + + @XmlElement + @DynamicSerializeElement + @Transient + private String skyKey; + + @XmlElement + @DynamicSerializeElement + @Transient + private Set skyCoverage = new HashSet(); + + /** A string denoting the vertical visibility */ + @XmlElement + @DynamicSerializeElement + @Transient + private int vertVisibility = -9999; + + /** A string denoting the lowest layer of clouds */ + @XmlElement + @DynamicSerializeElement + @Transient + private int skyLayerBase = -9999; + + /** The visibility in statute miles */ + @XmlElement + @DynamicSerializeElement + @Transient + private float visibility = -9999; + + /** A String used as the foreign key to the present weather table * */ + @XmlElement + @DynamicSerializeElement + @Transient + private String weatherKey; + + /** A Set of present weather conditions * */ + @DynamicSerializeElement + @XmlElement + @Transient + private List weatherCondition = new ArrayList(); + + /** A string denoting the sea level pressure in millibars */ + @XmlElement + @DynamicSerializeElement + @Transient + private float seaLevelPress = -9999; + + /** A string denoting the temperature in degrees Celsius */ + @XmlElement + @DynamicSerializeElement + @Transient + private int temperature = -9999; + + /** A string denoting the current temperature in tenths of degrees Celsius */ + @XmlElement + @DynamicSerializeElement + @Transient + private float tempFromTenths = -9999; + + /** A string denoting the current dew point in degrees Celsius */ + @XmlElement + @DynamicSerializeElement + @Transient + private int dewPoint = -9999; + + /** A string denoting the current dew point in tenths of degrees Celsius */ + @XmlElement + @DynamicSerializeElement + @Transient + private float dewPointFromTenths = -9999; + + @XmlElement + @DynamicSerializeElement + @Transient + private String windDir; + + @XmlElement + @DynamicSerializeElement + @Transient + private int windSpeed = -9999; + + @XmlElement + @DynamicSerializeElement + @Transient + private int windGust = -9999; + + @XmlElement + @DynamicSerializeElement + @Transient + private int pkWndDir = -9999; + + @XmlElement + @DynamicSerializeElement + @Transient + private int pkWndSpd = -9999; + + @XmlElement + @DynamicSerializeElement + @Transient + private Calendar pkWndTime = null; + + @XmlElement + @DynamicSerializeElement + @Transient + private float altimeterInPa = -9999; + + @XmlElement + @DynamicSerializeElement + @Transient + private float altimeter = -9999; + + @XmlElement + @DynamicSerializeElement + @Transient + private float minTemp24Hour = -9999; + + @XmlElement + @DynamicSerializeElement + @Transient + private float maxTemp24Hour = -9999; + + @XmlElement + @DynamicSerializeElement + @Transient + private float minTemp6Hour = -9999; + + @XmlElement + @DynamicSerializeElement + @Transient + private float maxTemp6Hour = -9999; + + /** A string denoting inches of precipitation observed in the last hour */ + @XmlElement + @DynamicSerializeElement + @Transient + private float precip1Hour = -9999; + + /** A string denoting inches of precipitation observed in the last 3 hours */ + @XmlElement + @DynamicSerializeElement + @Transient + private float precip3Hour = -9999; + + /** A string denoting inches of precipitation observed in the last 6 hours */ + @XmlElement + @DynamicSerializeElement + @Transient + private float precip6Hour = -9999; + + /** A string denoting inches of precipitation observed in the last 24 hours */ + @XmlElement + @DynamicSerializeElement + @Transient + private float precip24Hour = -9999; + + /** A string denoting the pressure tendency(rising or falling) */ + @XmlElement + @DynamicSerializeElement + @Transient + private String pressChangeChar; + + /** A string denoting the pressure change observed in the past 3 hrs. */ + @XmlElement + @DynamicSerializeElement + @Transient + private float pressChange3Hour = -9999; + + // Amount of snow on the ground in inches. + @XmlElement + @DynamicSerializeElement + @Transient + private int snowDepth = -9999; + + // Water equivalent in 0.1 inch increments. + @XmlElement + @DynamicSerializeElement + @Transient + private float snowWater = -9999; + + // Snow fall last 6 hours. + @XmlElement + @DynamicSerializeElement + @Transient + private float snowFall_6Hours = -9999; + + // Number of minutes of sunshine. + @XmlElement + @DynamicSerializeElement + @Transient + private int sunshine = -9999; + + @XmlElement + @DynamicSerializeElement + @Column + private Calendar refHour; + + @DynamicSerializeElement + @Embedded + private PointDataView pointDataView; + + public MetarRecord() { + } + + /** + * Constructs a metar record from a dataURI + * + * @param uri + * The dataURI + * @param tableDef + * The table definition associated with this class + */ + public MetarRecord(String uri) { + super(uri); + } + + /** + * @return the serialVersionUID + */ + public static long getSerialVersionUID() { + return serialVersionUID; + } + + /** + * @return the altimeter + */ + public float getAltimeter() { + return altimeter; + } + + /** + * @param altimeter + * the altimeter to set + */ + public void setAltimeter(float altimeter) { + this.altimeter = altimeter; + } + + /** + * @return the altimeterInPa + */ + public float getAltimeterInPa() { + return altimeterInPa; + } + + /** + * @param altimeterInPa + * the altimeterInPa to set + */ + public void setAltimeterInPa(float altimeterInPa) { + this.altimeterInPa = altimeterInPa; + } + + /** + * @return the autoStationType + */ + public String getAutoStationType() { + return autoStationType; + } + + /** + * @param autoStationType + * the autoStationType to set + */ + public void setAutoStationType(String autoStationType) { + this.autoStationType = autoStationType; + } + + /** + * @return the correction + */ + public String getCorrection() { + return correction; + } + + /** + * @param correction + * the correction to set + */ + public void setCorrection(String correction) { + this.correction = correction; + } + + /** + * @return the dewPoint + */ + public int getDewPoint() { + return dewPoint; + } + + /** + * @param dewPoint + * the dewPoint to set + */ + public void setDewPoint(int dewPoint) { + this.dewPoint = dewPoint; + } + + /** + * @return the dewPointFromTenths + */ + public float getDewPointFromTenths() { + return dewPointFromTenths; + } + + /** + * @param dewPointFromTenths + * the dewPointFromTenths to set + */ + public void setDewPointFromTenths(float dewPointFromTenths) { + this.dewPointFromTenths = dewPointFromTenths; + } + + /** + * @return the maxTemp24Hour + */ + public float getMaxTemp24Hour() { + return maxTemp24Hour; + } + + /** + * @param maxTemp24Hour + * the maxTemp24Hour to set + */ + public void setMaxTemp24Hour(float maxTemp24Hour) { + this.maxTemp24Hour = maxTemp24Hour; + } + + /** + * @return the minTemp24Hour + */ + public float getMinTemp24Hour() { + return minTemp24Hour; + } + + /** + * @param minTemp24Hour + * the minTemp24Hour to set + */ + public void setMinTemp24Hour(float minTemp24Hour) { + this.minTemp24Hour = minTemp24Hour; + } + + /** + * @return the minTemp6Hour + */ + public float getMinTemp6Hour() { + return minTemp6Hour; + } + + /** + * @param minTemp6Hour + * the minTemp6Hour to set + */ + public void setMinTemp6Hour(float minTemp6Hour) { + this.minTemp6Hour = minTemp6Hour; + } + + /** + * @return the maxTemp6Hour + */ + public float getMaxTemp6Hour() { + return maxTemp6Hour; + } + + /** + * @param maxTemp6Hour + * the maxTemp6Hour to set + */ + public void setMaxTemp6Hour(float maxTemp6Hour) { + this.maxTemp6Hour = maxTemp6Hour; + } + + /** + * @return the precip1Hour + */ + public float getPrecip1Hour() { + return precip1Hour; + } + + /** + * @param precip1Hour + * the precip1Hour to set + */ + public void setPrecip1Hour(float precip1Hour) { + this.precip1Hour = precip1Hour; + } + + /** + * @return the precip3Hour + */ + public float getPrecip3Hour() { + return precip3Hour; + } + + /** + * @param precip3Hour + * the precip3Hour to set + */ + public void setPrecip3Hour(float precip3Hour) { + this.precip3Hour = precip3Hour; + } + + /** + * @return the precip6Hour + */ + public float getPrecip6Hour() { + return precip6Hour; + } + + /** + * @param precip6Hour + * the precip6Hour to set + */ + public void setPrecip6Hour(float precip6Hour) { + this.precip6Hour = precip6Hour; + } + + /** + * @return the precip24Hour + */ + public float getPrecip24Hour() { + return precip24Hour; + } + + /** + * @param precip24Hour + * the precip24Hour to set + */ + public void setPrecip24Hour(float precip24Hour) { + this.precip24Hour = precip24Hour; + } + + /** + * @return the pressChange3Hour + */ + public float getPressChange3Hour() { + return pressChange3Hour; + } + + /** + * @param pressChange3Hour + * the pressChange3Hour to set + */ + public void setPressChange3Hour(float pressChange3Hour) { + this.pressChange3Hour = pressChange3Hour; + } + + /** + * @return the pressChangeChar + */ + public String getPressChangeChar() { + return pressChangeChar; + } + + /** + * @param pressChangeChar + * the pressChangeChar to set + */ + public void setPressChangeChar(String pressChangeChar) { + this.pressChangeChar = pressChangeChar; + } + + /** + * @return the seaLevelPress + */ + public float getSeaLevelPress() { + return seaLevelPress; + } + + /** + * @param seaLevelPress + * the seaLevelPress to set + */ + public void setSeaLevelPress(float seaLevelPress) { + this.seaLevelPress = seaLevelPress; + } + + /** + * @return the skyLayerBase + */ + public int getSkyLayerBase() { + return skyLayerBase; + } + + /** + * @param skyLayerBase + * the skyLayerBase to set + */ + public void setSkyLayerBase(int skyLayerBase) { + this.skyLayerBase = skyLayerBase; + } + + /** + * @return the temperature + */ + public int getTemperature() { + return temperature; + } + + /** + * @param temperature + * the temperature to set + */ + public void setTemperature(int temperature) { + this.temperature = temperature; + } + + /** + * @return the tempFromTenths + */ + public float getTempFromTenths() { + return tempFromTenths; + } + + /** + * @param tempFromTenths + * the tempFromTenths to set + */ + public void setTempFromTenths(float tempFromTenths) { + this.tempFromTenths = tempFromTenths; + } + + /** + * @return the vertVisibility + */ + public int getVertVisibility() { + return vertVisibility; + } + + /** + * @param vertVisibility + * the vertVisibility to set + */ + public void setVertVisibility(int vertVisibility) { + this.vertVisibility = vertVisibility; + } + + /** + * @return the visibility + */ + public float getVisibility() { + + return visibility; + } + + /** + * @param visibility + * the visibility to set + */ + public void setVisibility(float visibility) { + this.visibility = visibility; + } + + /** + * @return the windDir + */ + public String getWindDir() { + return windDir; + } + + /** + * @param windDir + * the windDir to set + */ + public void setWindDir(String windDir) { + this.windDir = windDir; + } + + /** + * @return the windGust + */ + public int getWindGust() { + return windGust; + } + + /** + * @param windGust + * the windGust to set + */ + public void setWindGust(int windGust) { + this.windGust = windGust; + } + + /** + * @return the windSpeed + */ + public int getWindSpeed() { + return windSpeed; + } + + /** + * @param windSpeed + * the windSpeed to set + */ + public void setWindSpeed(int windSpeed) { + this.windSpeed = windSpeed; + } + + /** + * @return the pkWndDir + */ + public int getPkWndDir() { + return pkWndDir; + } + + /** + * @param pkWndDir + * the pkWndDir to set + */ + public void setPkWndDir(int pkWndDir) { + this.pkWndDir = pkWndDir; + } + + /** + * @return the pkWndSpd + */ + public int getPkWndSpd() { + return pkWndSpd; + } + + /** + * @param pkWndSpd + * the pkWndSpd to set + */ + public void setPkWndSpd(int pkWndSpd) { + this.pkWndSpd = pkWndSpd; + } + + /** + * @return the pkWndTime + */ + public Calendar getPkWndTime() { + return pkWndTime; + } + + /** + * @param pkWndTime + * the pkWndTime to set + */ + public void setPkWndTime(Calendar pkWndTime) { + this.pkWndTime = pkWndTime; + } + + /** + * @return the timeObs + */ + public Calendar getTimeObs() { + if (this.dataTime == null) { + return null; + } + return this.dataTime.getRefTimeAsCalendar(); + } + + /** + * @param timeObs + * the timeObs to set + */ + public void setTimeObs(Calendar timeObs) { + this.nominalTime = TimeUtil.formatCalendar(timeObs); + this.timeObs = timeObs; + } + + /** + * @return the skyCoverage + */ + public Set getSkyCoverage() { + return skyCoverage; + } + + /** + * @param skyCoverage + * the skyCoverage to set + */ + public void setSkyCoverage(Set skyCoverage) { + this.skyCoverage = skyCoverage; + } + + public void addSkyCoverage(SkyCover cover) { + skyCoverage.add(cover); + cover.setParentMetar(this); + } + + /** + * @return the skyKey + */ + public String getSkyKey() { + return skyKey; + } + + /** + * @param skyKey + * the skyKey to set + */ + public void setSkyKey(String skyKey) { + this.skyKey = skyKey; + } + + /** + * @return the weatherCondition + */ + public List getWeatherCondition() { + return weatherCondition; + } + + /** + * @param weatherCondition + * the weatherCondition to set + */ + public void setWeatherCondition(List weatherCondition) { + this.weatherCondition = weatherCondition; + } + + public void addWeatherCondition(WeatherCondition condition) { + this.weatherCondition.add(condition); + condition.setParentMetar(this); + } + + /** + * @return the weatherKey + */ + public String getWeatherKey() { + return weatherKey; + } + + /** + * @param weatherKey + * the weatherKey to set + */ + public void setWeatherKey(String weatherKey) { + this.weatherKey = weatherKey; + } + + /** + * @return the refHour + */ + public Calendar getRefHour() { + return refHour; + } + + /** + * @param refHour + * the refHour to set + */ + public void setRefHour(Calendar refHour) { + this.refHour = refHour; + } + + /** + * @return the snowDepth + */ + public int getSnowDepth() { + return snowDepth; + } + + /** + * @param snowDepth + * the snowDepth to set + */ + public void setSnowDepth(int snowDepth) { + this.snowDepth = snowDepth; + } + + /** + * @return the snowFall_6Hours + */ + public float getSnowFall_6Hours() { + return snowFall_6Hours; + } + + /** + * @param snowFall_6Hours + * the snowFall_6Hours to set + */ + public void setSnowFall_6Hours(float snowFall_6Hours) { + this.snowFall_6Hours = snowFall_6Hours; + } + + /** + * @return the sunshine + */ + public int getSunshine() { + return sunshine; + } + + /** + * @param sunshine + * the sunshine to set + */ + public void setSunshine(int sunshine) { + this.sunshine = sunshine; + } + + /** + * @return the snowWater + */ + public float getSnowWater() { + return snowWater; + } + + /** + * @param snowWater + * the snowWater to set + */ + public void setSnowWater(float snowWater) { + this.snowWater = snowWater; + } + + /** + * Override existing set method to modify any classes that use the dataURI + * as a foreign key + */ + @Override + public void setIdentifier(Object dataURI) { + this.identifier = dataURI; + // set the parentID to the dataURI for all values + if ((this.getWeatherCondition() != null) + && (this.getWeatherCondition().size() > 0)) { + for (WeatherCondition cond : this.getWeatherCondition()) { + cond.setParentMetar(this); + } + } + + // set the parentID to the dataURI for all values + if ((this.getSkyCoverage() != null) + && (this.getSkyCoverage().size() > 0)) { + for (SkyCover cover : this.getSkyCoverage()) { + cover.setParentMetar(this); + } + } + } + + public String getReportType() { + return reportType; + } + + public void setReportType(String reportType) { + this.reportType = reportType; + } + + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } + + public String getNominalTime() { + return nominalTime; + } + + public void setNominalTime(String nominalTime) { + this.nominalTime = nominalTime; + } + + /** + * Get the IDecoderGettable reference for this record. + * + * @return The IDecoderGettable reference for this record. + */ + @Override + public IDecoderGettable getDecoderGettable() { + return this; + } + + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public String getString(String paramName) { + if ("STA".matches(paramName)) { + return getStationId(); + } + if ("WX".matches(paramName)) { + return this.weatherKey; + } + + return null; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.dataplugin.IDecoderGettable#getValue(java.lang + * .String) + */ + @Override + public Amount getValue(String paramName) { + Amount a = null; + + String pName = paramName; + if (PARM_MAP.containsKey(paramName)) { + // we have recieved an AWIPS I parameter name + pName = PARM_MAP.get(paramName); + } + + if (SFC_TEMP.equals(pName)) { + if (tempFromTenths != -9999) { + a = new Amount(tempFromTenths, TEMPERATURE_UNIT); + } else if (temperature != -9999) { + a = new Amount(temperature, TEMPERATURE_UNIT); + } + } else if (SFC_DWPT.equals(pName)) { + if (dewPointFromTenths != -9999) { + a = new Amount(dewPointFromTenths, TEMPERATURE_UNIT); + } else if (dewPoint != -9999) { + a = new Amount(dewPoint, TEMPERATURE_UNIT); + } + } else if (SFC_WNDSPD.equals(pName)) { + a = new Amount(windSpeed, WIND_SPEED_UNIT); + } else if (SFC_WNDGST.equals(pName)) { + a = new Amount(windGust, WIND_SPEED_UNIT); + } else if (ParameterKey.PRESSURE_CHANGE.equals(pName) + && (pressChange3Hour != -9999)) { + a = new Amount(pressChange3Hour, PRESSURE_UNIT); + } else if (SFC_WNDDIR.equals(pName)) { + String windDir = getWindDir(); + if ((windDir != null) && !windDir.equalsIgnoreCase("VRB")) { + Double result = Double.parseDouble(windDir); + a = new Amount(result, WIND_DIR_UNIT); + } + } else if (PRES_ALTSG.equals(pName)) { + a = new Amount(altimeterInPa, ALTIMETER_UNIT); + } else if (STA_LAT.equals(pName)) { + a = new Amount(getLatitude(), LOCATION_UNIT); + } else if (STA_LON.equals(pName)) { + a = new Amount(getLongitude(), LOCATION_UNIT); + } else if (PRES_SLP.equals(pName)) { + a = new Amount(this.seaLevelPress, PRESSURE_UNIT); + } else if (pName.startsWith("HGT")) { + int start = "HGT".length(); + int index = Integer.parseInt(pName.substring(start)); + if ((index < skyCoverage.size()) + && (getSkyCover(index).getHeight() != null)) { + a = new Amount(getSkyCover(index).getHeight(), HEIGHT_UNIT); + } + } else if (pName.startsWith("HMSL")) { + int start = "HMSL".length(); + int index = Integer.parseInt(pName.substring(start)); + if ((index < skyCoverage.size()) + && (getSkyCover(index).getHeight() != null) + && (getSpatialObject() != null) + && (getSpatialObject().getElevation() != null)) { + a = new Amount(getSkyCover(index).getHeight() + + getSpatialObject().getElevation(), HEIGHT_UNIT); + } + } else if (ParameterKey.PRECIPITATION_1HR.equals(pName) + || ParameterKey.PRECIPITATION_24HR.equals(pName)) { + sampleType = "PR"; + if (precip1Hour != -9999) { + a = new Amount(precip1Hour, PRECIP_UNIT); + } + } else if (ParameterKey.PRECIPITATION_3HR.equals(pName)) { + sampleType = "PR"; + if (precip3Hour != -9999) { + a = new Amount(precip3Hour, PRECIP_UNIT); + } + } else if (ParameterKey.PRECIPITATION_6HR.equals(pName)) { + sampleType = "PR"; + if (precip6Hour != -9999) { + a = new Amount(precip6Hour, PRECIP_UNIT); + } + } else if (ParameterKey.VISIBILITY.equals(pName)) { + a = new Amount(visibility, VISIBILITY_UNIT); + } + + return a; + } + + /** + * Get the value and units of a named parameter within this observation that + * has a multiplicity greater than 1. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return An Amount with value and units. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Collection getValues(String paramName) { + return null; + } + + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } + + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } + + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } + + @Override + public String[] getStrings(String paramName) { + if ("SCV".matches(paramName)) { + ArrayList skyCoverage = new ArrayList(); + for (SkyCover sky : this.skyCoverage) { + skyCoverage.add(sky.getType()); + } + if (skyCoverage.size() > 0) { + return skyCoverage.toArray(new String[skyCoverage.size()]); + } + } else if ("WX".matches(paramName)) { + if (this.weatherKey != null) { + String[] presentWeather = { this.weatherKey }; + return presentWeather; + } + } else if (paramName.startsWith("CLD")) { + int start = "CLD".length(); + int index = Integer.parseInt(paramName.substring(start)); + String[] retVal = { "BLNK" }; + if (index < skyCoverage.size()) { + if (getSkyCover(index).getType() != null) { + retVal[0] = getSkyCover(index).getType(); + } + } + return retVal; + } else if (paramName.matches("CCHAR") && (pressChangeChar != null)) { + String[] changeChar = { pressChangeChar }; + return changeChar; + } + return null; + } + + @Override + public int hashCode() { + final int PRIME = 31; + int result = 1; + result = (PRIME * result) + Float.floatToIntBits(altimeter); + result = (PRIME * result) + Float.floatToIntBits(altimeterInPa); + result = (PRIME * result) + + ((autoStationType == null) ? 0 : autoStationType.hashCode()); + result = (PRIME * result) + + ((correction == null) ? 0 : correction.hashCode()); + result = (PRIME * result) + dewPoint; + result = (PRIME * result) + Float.floatToIntBits(dewPointFromTenths); + result = (PRIME * result) + Float.floatToIntBits(maxTemp24Hour); + result = (PRIME * result) + Float.floatToIntBits(minTemp24Hour); + result = (PRIME * result) + + ((nominalTime == null) ? 0 : nominalTime.hashCode()); + result = (PRIME * result) + Float.floatToIntBits(precip1Hour); + result = (PRIME * result) + Float.floatToIntBits(precip3Hour); + result = (PRIME * result) + Float.floatToIntBits(precip6Hour); + result = (PRIME * result) + Float.floatToIntBits(pressChange3Hour); + result = (PRIME * result) + + ((pressChangeChar == null) ? 0 : pressChangeChar.hashCode()); + result = (PRIME * result) + + ((refHour == null) ? 0 : refHour.hashCode()); + result = (PRIME * result) + + ((reportType == null) ? 0 : reportType.hashCode()); + result = (PRIME * result) + Float.floatToIntBits(seaLevelPress); + result = (PRIME * result) + + ((skyCoverage == null) ? 0 : skyCoverage.hashCode()); + result = (PRIME * result) + ((skyKey == null) ? 0 : skyKey.hashCode()); + result = (PRIME * result) + skyLayerBase; + result = (PRIME * result) + + ((getStationId() == null) ? 0 : getStationId().hashCode()); + long temp; + temp = Double.doubleToLongBits(getLatitude()); + result = (PRIME * result) + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(getLongitude()); + result = (PRIME * result) + (int) (temp ^ (temp >>> 32)); + result = (PRIME * result) + Float.floatToIntBits(tempFromTenths); + result = (PRIME * result) + temperature; + result = (PRIME * result) + + ((timeObs == null) ? 0 : timeObs.hashCode()); + result = (PRIME * result) + vertVisibility; + result = (PRIME * result) + +Float.floatToIntBits(visibility); + + result = (PRIME * result) + + ((weatherCondition == null) ? 0 : weatherCondition.hashCode()); + result = (PRIME * result) + + ((weatherKey == null) ? 0 : weatherKey.hashCode()); + result = (PRIME * result) + + ((windDir == null) ? 0 : windDir.hashCode()); + result = (PRIME * result) + windGust; + result = (PRIME * result) + windSpeed; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final MetarRecord other = (MetarRecord) obj; + if (Float.floatToIntBits(altimeter) != Float + .floatToIntBits(other.altimeter)) { + return false; + } + if (Float.floatToIntBits(altimeterInPa) != Float + .floatToIntBits(other.altimeterInPa)) { + return false; + } + if (autoStationType == null) { + if (other.autoStationType != null) { + return false; + } + } else if (!autoStationType.equals(other.autoStationType)) { + return false; + } + if (correction == null) { + if (other.correction != null) { + return false; + } + } else if (!correction.equals(other.correction)) { + return false; + } + if (dewPoint != other.dewPoint) { + return false; + } + if (Float.floatToIntBits(dewPointFromTenths) != Float + .floatToIntBits(other.dewPointFromTenths)) { + return false; + } + if (Float.floatToIntBits(maxTemp24Hour) != Float + .floatToIntBits(other.maxTemp24Hour)) { + return false; + } + if (Float.floatToIntBits(minTemp24Hour) != Float + .floatToIntBits(other.minTemp24Hour)) { + return false; + } + if (nominalTime == null) { + if (other.nominalTime != null) { + return false; + } + } else if (!nominalTime.equals(other.nominalTime)) { + return false; + } + if (Float.floatToIntBits(precip1Hour) != Float + .floatToIntBits(other.precip1Hour)) { + return false; + } + if (Float.floatToIntBits(precip3Hour) != Float + .floatToIntBits(other.precip3Hour)) { + return false; + } + if (Float.floatToIntBits(precip6Hour) != Float + .floatToIntBits(other.precip6Hour)) { + return false; + } + if (Float.floatToIntBits(pressChange3Hour) != Float + .floatToIntBits(other.pressChange3Hour)) { + return false; + } + if (pressChangeChar == null) { + if (other.pressChangeChar != null) { + return false; + } + } else if (!pressChangeChar.equals(other.pressChangeChar)) { + return false; + } + if (refHour == null) { + if (other.refHour != null) { + return false; + } + } else if (!refHour.equals(other.refHour)) { + return false; + } + if (reportType == null) { + if (other.reportType != null) { + return false; + } + } else if (!reportType.equals(other.reportType)) { + return false; + } + if (Float.floatToIntBits(seaLevelPress) != Float + .floatToIntBits(other.seaLevelPress)) { + return false; + } + if (skyCoverage == null) { + if (other.skyCoverage != null) { + return false; + } + } else if (!skyCoverage.equals(other.skyCoverage)) { + return false; + } + if (skyKey == null) { + if (other.skyKey != null) { + return false; + } + } else if (!skyKey.equals(other.skyKey)) { + return false; + } + if (skyLayerBase != other.skyLayerBase) { + return false; + } + + if (getStationId() == null) { + if (other.getStationId() != null) { + return false; + } + } else if (!getStationId().equals(other.getStationId())) { + return false; + } + + Double lat = location.getLatitude(); + if (lat == null) { + if (other.location.getLatitude() != null) { + return false; + } + } else { + if (!lat.equals(other.location.getLatitude())) { + return false; + } + } + Double lon = location.getLongitude(); + if (lon == null) { + if (other.location.getLongitude() != null) { + return false; + } + } else { + if (!lon.equals(other.location.getLongitude())) { + return false; + } + } + + if (Float.floatToIntBits(tempFromTenths) != Float + .floatToIntBits(other.tempFromTenths)) { + return false; + } + if (temperature != other.temperature) { + return false; + } + if (timeObs == null) { + if (other.timeObs != null) { + return false; + } + } else if (!timeObs.equals(other.timeObs)) { + return false; + } + if (vertVisibility != other.vertVisibility) { + return false; + } + if (Float.floatToIntBits(visibility) != Float + .floatToIntBits(other.visibility)) { + return false; + } + + if (weatherCondition == null) { + if (other.weatherCondition != null) { + return false; + } + } else if (!weatherCondition.equals(other.weatherCondition)) { + return false; + } + if (weatherKey == null) { + if (other.weatherKey != null) { + return false; + } + } else if (!weatherKey.equals(other.weatherKey)) { + return false; + } + if (windDir == null) { + if (other.windDir != null) { + return false; + } + } else if (!windDir.equals(other.windDir)) { + return false; + } + if (windGust != other.windGust) { + return false; + } + if (windSpeed != other.windSpeed) { + return false; + } + return true; + } + + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } + + public SurfaceObsLocation getLocation() { + return location; + } + + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } + + public String getReport() { + return report; + } + + public void setReport(String report) { + this.report = report; + } + + /** + * + * @return + */ + public String getWmoHeader() { + return wmoHeader; + } + + /** + * + * @param header + */ + public void setWmoHeader(String header) { + wmoHeader = header; + } + + @Override + public void setMessageData(Object message) { + this.messageData = message; + this.report = (String) message; + } + + @Override + public String getMessageData() { + if ((sampleType != null) && sampleType.equals("PR")) { + return getStationId(); + } + return report; + } + + private SkyCover getSkyCover(int index) { + if (!isSkyCoverageSorted) { + isSkyCoverageSorted = true; + sort(skyCoverage); + } + SkyCover[] sc = skyCoverage.toArray(new SkyCover[skyCoverage.size()]); + return sc[index]; + + } + + public void sort(Set skySet) { + SortedSet skSet = new TreeSet(); + for (SkyCover sc : skySet) { + skSet.add(sc); + } + + skyCoverage = skSet; + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() + */ + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon + * .uf.common.pointdata.PointDataView) + */ + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + + public static Set getAvailableParameters() { + return PARM_MAP.keySet(); + } - /** - * Maps common AWIPS I keys to IDecoderGettable and newer parameter key - * constants - */ - private static final HashMap PARM_MAP = new HashMap(); - static { - PARM_MAP.put(LegacyParameterKey.TEMPERATURE, SFC_TEMP); - PARM_MAP.put(LegacyParameterKey.DEW_POINT, SFC_DWPT); - PARM_MAP.put(LegacyParameterKey.WIND_SPEED, SFC_WNDSPD); - PARM_MAP.put(LegacyParameterKey.WIND_DIRECTION, SFC_WNDDIR); - PARM_MAP.put(LegacyParameterKey.WIND_GUST, SFC_WNDGST); - PARM_MAP.put(LegacyParameterKey.ALTIMETER, ParameterKey.SFC_ALTIMETER); - PARM_MAP.put(LegacyParameterKey.SEA_LEVEL_PRESSURE, PRES_SLP); - PARM_MAP.put("NLAT", STA_LAT); - PARM_MAP.put("NLON", STA_LON); - PARM_MAP.put(LegacyParameterKey.PRESSURE_CHANGE_3HR, - ParameterKey.PRESSURE_CHANGE); - // PARM_MAP.put("T24", "T24"); // not used - // PARM_MAP.put("DpT24", "DpT24"); // not used - // PARM_MAP.put("WS24", "WS24"); // not used - // PARM_MAP.put("WD24", "WD24"); // not used - // PARM_MAP.put("WGS24", "WGS24"); // not used - // PARM_MAP.put("ASET24", "ASET24"); // not used - // PARM_MAP.put("HIWC", "HIWC"); // not used - PARM_MAP.put(LegacyParameterKey.VISABILITY, ParameterKey.VISIBILITY); - PARM_MAP.put(LegacyParameterKey.PRECIPITATION_1HR, - ParameterKey.PRECIPITATION_1HR); - PARM_MAP.put(LegacyParameterKey.PRECIPITATION_3HR, - ParameterKey.PRECIPITATION_3HR); - PARM_MAP.put(LegacyParameterKey.PRECIPITATION_6HR, - ParameterKey.PRECIPITATION_6HR); - PARM_MAP.put(LegacyParameterKey.PRECIPITATION_24HR, - ParameterKey.PRECIPITATION_24HR); - } - - @Transient - private String sampleType = null; - - @Transient - private boolean isSkyCoverageSorted = false; - - @XmlElement - @DynamicSerializeElement - @Transient - private String report; - - @XmlElement - @DynamicSerializeElement - @Transient - private String wmoHeader; - - /** Nominal Time extracted from WMO header * */ - @XmlElement - @DynamicSerializeElement - @Transient - private String nominalTime; - - /** A string denoting the time of observation */ - @XmlElement - @DynamicSerializeElement - @Transient - private Calendar timeObs; - - /** Report type extracted from WMO header * */ - @XmlElement - @DynamicSerializeElement - @Column - @DataURI(position = 1) - protected String reportType; - - /** A string denoting if this report is a correction */ - @XmlElement - @DynamicSerializeElement - @Column - @DataURI(position = 2) - private String correction; - - @Embedded - @DataURI(position = 3, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; - - /** A string denoting the type of automated station (AO1 or AO2) */ - @XmlElement - @DynamicSerializeElement - @Transient - private String autoStationType; - - @XmlElement - @DynamicSerializeElement - @Transient - private String skyKey; - - @XmlElement - @DynamicSerializeElement - @Transient - private Set skyCoverage = new HashSet(); - - /** A string denoting the vertical visibility */ - @XmlElement - @DynamicSerializeElement - @Transient - private int vertVisibility = -9999; - - /** A string denoting the lowest layer of clouds */ - @XmlElement - @DynamicSerializeElement - @Transient - private int skyLayerBase = -9999; - - /** The visibility in statute miles */ - @XmlElement - @DynamicSerializeElement - @Transient - private float visibility = -9999; - - /** A String used as the foreign key to the present weather table * */ - @XmlElement - @DynamicSerializeElement - @Transient - private String weatherKey; - - /** A Set of present weather conditions * */ - @DynamicSerializeElement - @XmlElement - @Transient - private List weatherCondition = new ArrayList(); - - /** A string denoting the sea level pressure in millibars */ - @XmlElement - @DynamicSerializeElement - @Transient - private float seaLevelPress = -9999; - - /** A string denoting the temperature in degrees Celsius */ - @XmlElement - @DynamicSerializeElement - @Transient - private int temperature = -9999; - - /** A string denoting the current temperature in tenths of degrees Celsius */ - @XmlElement - @DynamicSerializeElement - @Transient - private float tempFromTenths = -9999; - - /** A string denoting the current dew point in degrees Celsius */ - @XmlElement - @DynamicSerializeElement - @Transient - private int dewPoint = -9999; - - /** A string denoting the current dew point in tenths of degrees Celsius */ - @XmlElement - @DynamicSerializeElement - @Transient - private float dewPointFromTenths = -9999; - - @XmlElement - @DynamicSerializeElement - @Transient - private String windDir; - - @XmlElement - @DynamicSerializeElement - @Transient - private int windSpeed = -9999; - - @XmlElement - @DynamicSerializeElement - @Transient - private int windGust = -9999; - - @XmlElement - @DynamicSerializeElement - @Transient - private int pkWndDir = -9999; - - @XmlElement - @DynamicSerializeElement - @Transient - private int pkWndSpd = -9999; - - @XmlElement - @DynamicSerializeElement - @Transient - private Calendar pkWndTime = null; - - @XmlElement - @DynamicSerializeElement - @Transient - private float altimeterInPa = -9999; - - @XmlElement - @DynamicSerializeElement - @Transient - private float altimeter = -9999; - - @XmlElement - @DynamicSerializeElement - @Transient - private float minTemp24Hour = -9999; - - @XmlElement - @DynamicSerializeElement - @Transient - private float maxTemp24Hour = -9999; - - @XmlElement - @DynamicSerializeElement - @Transient - private float minTemp6Hour = -9999; - - @XmlElement - @DynamicSerializeElement - @Transient - private float maxTemp6Hour = -9999; - - /** A string denoting inches of precipitation observed in the last hour */ - @XmlElement - @DynamicSerializeElement - @Transient - private float precip1Hour = -9999; - - /** A string denoting inches of precipitation observed in the last 3 hours */ - @XmlElement - @DynamicSerializeElement - @Transient - private float precip3Hour = -9999; - - /** A string denoting inches of precipitation observed in the last 6 hours */ - @XmlElement - @DynamicSerializeElement - @Transient - private float precip6Hour = -9999; - - /** A string denoting inches of precipitation observed in the last 24 hours */ - @XmlElement - @DynamicSerializeElement - @Transient - private float precip24Hour = -9999; - - /** A string denoting the pressure tendency(rising or falling) */ - @XmlElement - @DynamicSerializeElement - @Transient - private String pressChangeChar; - - /** A string denoting the pressure change observed in the past 3 hrs. */ - @XmlElement - @DynamicSerializeElement - @Transient - private float pressChange3Hour = -9999; - - // Amount of snow on the ground in inches. - @XmlElement - @DynamicSerializeElement - @Transient - private int snowDepth = -9999; - - // Water equivalent in 0.1 inch increments. - @XmlElement - @DynamicSerializeElement - @Transient - private float snowWater = -9999; - - // Snow fall last 6 hours. - @XmlElement - @DynamicSerializeElement - @Transient - private float snowFall_6Hours = -9999; - - // Number of minutes of sunshine. - @XmlElement - @DynamicSerializeElement - @Transient - private int sunshine = -9999; - - @XmlElement - @DynamicSerializeElement - @Column - private Calendar refHour; - - @DynamicSerializeElement - @Embedded - private PointDataView pointDataView; - - public MetarRecord() { - } - - /** - * Constructs a metar record from a dataURI - * - * @param uri - * The dataURI - * @param tableDef - * The table definition associated with this class - */ - public MetarRecord(String uri) { - super(uri); - } - - /** - * @return the serialVersionUID - */ - public static long getSerialVersionUID() { - return serialVersionUID; - } - - /** - * @return the altimeter - */ - public float getAltimeter() { - return altimeter; - } - - /** - * @param altimeter - * the altimeter to set - */ - public void setAltimeter(float altimeter) { - this.altimeter = altimeter; - } - - /** - * @return the altimeterInPa - */ - public float getAltimeterInPa() { - return altimeterInPa; - } - - /** - * @param altimeterInPa - * the altimeterInPa to set - */ - public void setAltimeterInPa(float altimeterInPa) { - this.altimeterInPa = altimeterInPa; - } - - /** - * @return the autoStationType - */ - public String getAutoStationType() { - return autoStationType; - } - - /** - * @param autoStationType - * the autoStationType to set - */ - public void setAutoStationType(String autoStationType) { - this.autoStationType = autoStationType; - } - - /** - * @return the correction - */ - public String getCorrection() { - return correction; - } - - /** - * @param correction - * the correction to set - */ - public void setCorrection(String correction) { - this.correction = correction; - } - - /** - * @return the dewPoint - */ - public int getDewPoint() { - return dewPoint; - } - - /** - * @param dewPoint - * the dewPoint to set - */ - public void setDewPoint(int dewPoint) { - this.dewPoint = dewPoint; - } - - /** - * @return the dewPointFromTenths - */ - public float getDewPointFromTenths() { - return dewPointFromTenths; - } - - /** - * @param dewPointFromTenths - * the dewPointFromTenths to set - */ - public void setDewPointFromTenths(float dewPointFromTenths) { - this.dewPointFromTenths = dewPointFromTenths; - } - - /** - * @return the maxTemp24Hour - */ - public float getMaxTemp24Hour() { - return maxTemp24Hour; - } - - /** - * @param maxTemp24Hour - * the maxTemp24Hour to set - */ - public void setMaxTemp24Hour(float maxTemp24Hour) { - this.maxTemp24Hour = maxTemp24Hour; - } - - /** - * @return the minTemp24Hour - */ - public float getMinTemp24Hour() { - return minTemp24Hour; - } - - /** - * @param minTemp24Hour - * the minTemp24Hour to set - */ - public void setMinTemp24Hour(float minTemp24Hour) { - this.minTemp24Hour = minTemp24Hour; - } - - /** - * @return the minTemp6Hour - */ - public float getMinTemp6Hour() { - return minTemp6Hour; - } - - /** - * @param minTemp6Hour - * the minTemp6Hour to set - */ - public void setMinTemp6Hour(float minTemp6Hour) { - this.minTemp6Hour = minTemp6Hour; - } - - /** - * @return the maxTemp6Hour - */ - public float getMaxTemp6Hour() { - return maxTemp6Hour; - } - - /** - * @param maxTemp6Hour - * the maxTemp6Hour to set - */ - public void setMaxTemp6Hour(float maxTemp6Hour) { - this.maxTemp6Hour = maxTemp6Hour; - } - - /** - * @return the precip1Hour - */ - public float getPrecip1Hour() { - return precip1Hour; - } - - /** - * @param precip1Hour - * the precip1Hour to set - */ - public void setPrecip1Hour(float precip1Hour) { - this.precip1Hour = precip1Hour; - } - - /** - * @return the precip3Hour - */ - public float getPrecip3Hour() { - return precip3Hour; - } - - /** - * @param precip3Hour - * the precip3Hour to set - */ - public void setPrecip3Hour(float precip3Hour) { - this.precip3Hour = precip3Hour; - } - - /** - * @return the precip6Hour - */ - public float getPrecip6Hour() { - return precip6Hour; - } - - /** - * @param precip6Hour - * the precip6Hour to set - */ - public void setPrecip6Hour(float precip6Hour) { - this.precip6Hour = precip6Hour; - } - - /** - * @return the precip24Hour - */ - public float getPrecip24Hour() { - return precip24Hour; - } - - /** - * @param precip24Hour - * the precip24Hour to set - */ - public void setPrecip24Hour(float precip24Hour) { - this.precip24Hour = precip24Hour; - } - - /** - * @return the pressChange3Hour - */ - public float getPressChange3Hour() { - return pressChange3Hour; - } - - /** - * @param pressChange3Hour - * the pressChange3Hour to set - */ - public void setPressChange3Hour(float pressChange3Hour) { - this.pressChange3Hour = pressChange3Hour; - } - - /** - * @return the pressChangeChar - */ - public String getPressChangeChar() { - return pressChangeChar; - } - - /** - * @param pressChangeChar - * the pressChangeChar to set - */ - public void setPressChangeChar(String pressChangeChar) { - this.pressChangeChar = pressChangeChar; - } - - /** - * @return the seaLevelPress - */ - public float getSeaLevelPress() { - return seaLevelPress; - } - - /** - * @param seaLevelPress - * the seaLevelPress to set - */ - public void setSeaLevelPress(float seaLevelPress) { - this.seaLevelPress = seaLevelPress; - } - - /** - * @return the skyLayerBase - */ - public int getSkyLayerBase() { - return skyLayerBase; - } - - /** - * @param skyLayerBase - * the skyLayerBase to set - */ - public void setSkyLayerBase(int skyLayerBase) { - this.skyLayerBase = skyLayerBase; - } - - /** - * @return the temperature - */ - public int getTemperature() { - return temperature; - } - - /** - * @param temperature - * the temperature to set - */ - public void setTemperature(int temperature) { - this.temperature = temperature; - } - - /** - * @return the tempFromTenths - */ - public float getTempFromTenths() { - return tempFromTenths; - } - - /** - * @param tempFromTenths - * the tempFromTenths to set - */ - public void setTempFromTenths(float tempFromTenths) { - this.tempFromTenths = tempFromTenths; - } - - /** - * @return the vertVisibility - */ - public int getVertVisibility() { - return vertVisibility; - } - - /** - * @param vertVisibility - * the vertVisibility to set - */ - public void setVertVisibility(int vertVisibility) { - this.vertVisibility = vertVisibility; - } - - /** - * @return the visibility - */ - public float getVisibility() { - - return visibility; - } - - /** - * @param visibility - * the visibility to set - */ - public void setVisibility(float visibility) { - this.visibility = visibility; - } - - /** - * @return the windDir - */ - public String getWindDir() { - return windDir; - } - - /** - * @param windDir - * the windDir to set - */ - public void setWindDir(String windDir) { - this.windDir = windDir; - } - - /** - * @return the windGust - */ - public int getWindGust() { - return windGust; - } - - /** - * @param windGust - * the windGust to set - */ - public void setWindGust(int windGust) { - this.windGust = windGust; - } - - /** - * @return the windSpeed - */ - public int getWindSpeed() { - return windSpeed; - } - - /** - * @param windSpeed - * the windSpeed to set - */ - public void setWindSpeed(int windSpeed) { - this.windSpeed = windSpeed; - } - - /** - * @return the pkWndDir - */ - public int getPkWndDir() { - return pkWndDir; - } - - /** - * @param pkWndDir - * the pkWndDir to set - */ - public void setPkWndDir(int pkWndDir) { - this.pkWndDir = pkWndDir; - } - - /** - * @return the pkWndSpd - */ - public int getPkWndSpd() { - return pkWndSpd; - } - - /** - * @param pkWndSpd - * the pkWndSpd to set - */ - public void setPkWndSpd(int pkWndSpd) { - this.pkWndSpd = pkWndSpd; - } - - /** - * @return the pkWndTime - */ - public Calendar getPkWndTime() { - return pkWndTime; - } - - /** - * @param pkWndTime - * the pkWndTime to set - */ - public void setPkWndTime(Calendar pkWndTime) { - this.pkWndTime = pkWndTime; - } - - /** - * @return the timeObs - */ - public Calendar getTimeObs() { - if (this.dataTime == null) { - return null; - } - return this.dataTime.getRefTimeAsCalendar(); - } - - /** - * @param timeObs - * the timeObs to set - */ - public void setTimeObs(Calendar timeObs) { - this.nominalTime = TimeUtil.formatCalendar(timeObs); - this.timeObs = timeObs; - } - - /** - * @return the skyCoverage - */ - public Set getSkyCoverage() { - return skyCoverage; - } - - /** - * @param skyCoverage - * the skyCoverage to set - */ - public void setSkyCoverage(Set skyCoverage) { - this.skyCoverage = skyCoverage; - } - - public void addSkyCoverage(SkyCover cover) { - skyCoverage.add(cover); - cover.setParentMetar(this); - } - - /** - * @return the skyKey - */ - public String getSkyKey() { - return skyKey; - } - - /** - * @param skyKey - * the skyKey to set - */ - public void setSkyKey(String skyKey) { - this.skyKey = skyKey; - } - - /** - * @return the weatherCondition - */ - public List getWeatherCondition() { - return weatherCondition; - } - - /** - * @param weatherCondition - * the weatherCondition to set - */ - public void setWeatherCondition(List weatherCondition) { - this.weatherCondition = weatherCondition; - } - - public void addWeatherCondition(WeatherCondition condition) { - this.weatherCondition.add(condition); - condition.setParentMetar(this); - } - - /** - * @return the weatherKey - */ - public String getWeatherKey() { - return weatherKey; - } - - /** - * @param weatherKey - * the weatherKey to set - */ - public void setWeatherKey(String weatherKey) { - this.weatherKey = weatherKey; - } - - /** - * @return the refHour - */ - public Calendar getRefHour() { - return refHour; - } - - /** - * @param refHour - * the refHour to set - */ - public void setRefHour(Calendar refHour) { - this.refHour = refHour; - } - - /** - * @return the snowDepth - */ - public int getSnowDepth() { - return snowDepth; - } - - /** - * @param snowDepth - * the snowDepth to set - */ - public void setSnowDepth(int snowDepth) { - this.snowDepth = snowDepth; - } - - /** - * @return the snowFall_6Hours - */ - public float getSnowFall_6Hours() { - return snowFall_6Hours; - } - - /** - * @param snowFall_6Hours - * the snowFall_6Hours to set - */ - public void setSnowFall_6Hours(float snowFall_6Hours) { - this.snowFall_6Hours = snowFall_6Hours; - } - - /** - * @return the sunshine - */ - public int getSunshine() { - return sunshine; - } - - /** - * @param sunshine - * the sunshine to set - */ - public void setSunshine(int sunshine) { - this.sunshine = sunshine; - } - - /** - * @return the snowWater - */ - public float getSnowWater() { - return snowWater; - } - - /** - * @param snowWater - * the snowWater to set - */ - public void setSnowWater(float snowWater) { - this.snowWater = snowWater; - } - - /** - * Override existing set method to modify any classes that use the dataURI - * as a foreign key - */ - @Override - public void setIdentifier(Object dataURI) { - this.identifier = dataURI; - // set the parentID to the dataURI for all values - if (this.getWeatherCondition() != null - && this.getWeatherCondition().size() > 0) { - for (Iterator iter = this.getWeatherCondition() - .iterator(); iter.hasNext();) { - WeatherCondition cond = iter.next(); - cond.setParentMetar(this); - } - } - - // set the parentID to the dataURI for all values - if (this.getSkyCoverage() != null && this.getSkyCoverage().size() > 0) { - for (Iterator iter = this.getSkyCoverage().iterator(); iter - .hasNext();) { - SkyCover cover = iter.next(); - cover.setParentMetar(this); - } - } - } - - public String getReportType() { - return reportType; - } - - public void setReportType(String reportType) { - this.reportType = reportType; - } - - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } - - public String getNominalTime() { - return nominalTime; - } - - public void setNominalTime(String nominalTime) { - this.nominalTime = nominalTime; - } - - /** - * Get the IDecoderGettable reference for this record. - * - * @return The IDecoderGettable reference for this record. - */ - @Override - public IDecoderGettable getDecoderGettable() { - return this; - } - - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public String getString(String paramName) { - if ("STA".matches(paramName)) { - return getStationId(); - } - if ("WX".matches(paramName)) { - return this.weatherKey; - } - - return null; - } - - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.dataplugin.IDecoderGettable#getValue(java.lang - * .String) - */ - @Override - public Amount getValue(String paramName) { - Amount a = null; - - String pName = paramName; - if (PARM_MAP.containsKey(paramName)) { - // we have recieved an AWIPS I parameter name - pName = PARM_MAP.get(paramName); - } - - if (SFC_TEMP.equals(pName)) { - if (tempFromTenths != -9999) { - a = new Amount(tempFromTenths, TEMPERATURE_UNIT); - } else if (temperature != -9999) { - a = new Amount(temperature, TEMPERATURE_UNIT); - } - } else if (SFC_DWPT.equals(pName)) { - if (dewPointFromTenths != -9999) { - a = new Amount(dewPointFromTenths, TEMPERATURE_UNIT); - } else if (dewPoint != -9999) { - a = new Amount(dewPoint, TEMPERATURE_UNIT); - } - } else if (SFC_WNDSPD.equals(pName)) { - a = new Amount(windSpeed, WIND_SPEED_UNIT); - } else if (SFC_WNDGST.equals(pName)) { - a = new Amount(windGust, WIND_SPEED_UNIT); - } else if (ParameterKey.PRESSURE_CHANGE.equals(pName) - && pressChange3Hour != -9999) { - a = new Amount(pressChange3Hour, PRESSURE_UNIT); - } else if (SFC_WNDDIR.equals(pName)) { - String windDir = getWindDir(); - if (windDir != null && !windDir.equalsIgnoreCase("VRB")) { - Double result = Double.parseDouble(windDir); - a = new Amount(result, WIND_DIR_UNIT); - } - } else if (PRES_ALTSG.equals(pName)) { - a = new Amount(altimeterInPa, ALTIMETER_UNIT); - } else if (STA_LAT.equals(pName)) { - a = new Amount(getLatitude(), LOCATION_UNIT); - } else if (STA_LON.equals(pName)) { - a = new Amount(getLongitude(), LOCATION_UNIT); - } else if (PRES_SLP.equals(pName)) { - a = new Amount(this.seaLevelPress, PRESSURE_UNIT); - } else if (pName.startsWith("HGT")) { - int start = "HGT".length(); - int index = Integer.parseInt(pName.substring(start)); - if (index < skyCoverage.size() - && getSkyCover(index).getHeight() != null) { - a = new Amount(getSkyCover(index).getHeight(), HEIGHT_UNIT); - } - } else if (pName.startsWith("HMSL")) { - int start = "HMSL".length(); - int index = Integer.parseInt(pName.substring(start)); - if (index < skyCoverage.size() - && getSkyCover(index).getHeight() != null - && getSpatialObject() != null - && getSpatialObject().getElevation() != null) { - a = new Amount(getSkyCover(index).getHeight() - + getSpatialObject().getElevation(), HEIGHT_UNIT); - } - } else if (ParameterKey.PRECIPITATION_1HR.equals(pName) - || ParameterKey.PRECIPITATION_24HR.equals(pName)) { - sampleType = "PR"; - if (precip1Hour != -9999) { - a = new Amount(precip1Hour, PRECIP_UNIT); - } - } else if (ParameterKey.PRECIPITATION_3HR.equals(pName)) { - sampleType = "PR"; - if (precip3Hour != -9999) { - a = new Amount(precip3Hour, PRECIP_UNIT); - } - } else if (ParameterKey.PRECIPITATION_6HR.equals(pName)) { - sampleType = "PR"; - if (precip6Hour != -9999) { - a = new Amount(precip6Hour, PRECIP_UNIT); - } - } else if (ParameterKey.VISIBILITY.equals(pName)) { - a = new Amount(visibility, VISIBILITY_UNIT); - } - - return a; - } - - /** - * Get the value and units of a named parameter within this observation that - * has a multiplicity greater than 1. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return An Amount with value and units. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Collection getValues(String paramName) { - return null; - } - - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } - - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } - - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } - - @Override - public String[] getStrings(String paramName) { - if ("SCV".matches(paramName)) { - ArrayList skyCoverage = new ArrayList(); - for (SkyCover sky : this.skyCoverage) { - skyCoverage.add(sky.getType()); - } - if (skyCoverage.size() > 0) { - return skyCoverage.toArray(new String[skyCoverage.size()]); - } - } else if ("WX".matches(paramName)) { - if (this.weatherKey != null) { - String[] presentWeather = { this.weatherKey }; - return presentWeather; - } - } else if (paramName.startsWith("CLD")) { - int start = "CLD".length(); - int index = Integer.parseInt(paramName.substring(start)); - String[] retVal = { "BLNK" }; - if (index < skyCoverage.size()) { - if (getSkyCover(index).getType() != null) { - retVal[0] = getSkyCover(index).getType(); - } - } - return retVal; - } else if (paramName.matches("CCHAR") && pressChangeChar != null) { - String[] changeChar = { pressChangeChar }; - return changeChar; - } - return null; - } - - @Override - public int hashCode() { - final int PRIME = 31; - int result = 1; - result = PRIME * result + Float.floatToIntBits(altimeter); - result = PRIME * result + Float.floatToIntBits(altimeterInPa); - result = PRIME * result - + ((autoStationType == null) ? 0 : autoStationType.hashCode()); - result = PRIME * result - + ((correction == null) ? 0 : correction.hashCode()); - result = PRIME * result + dewPoint; - result = PRIME * result + Float.floatToIntBits(dewPointFromTenths); - result = PRIME * result + Float.floatToIntBits(maxTemp24Hour); - result = PRIME * result + Float.floatToIntBits(minTemp24Hour); - result = PRIME * result - + ((nominalTime == null) ? 0 : nominalTime.hashCode()); - result = PRIME * result + Float.floatToIntBits(precip1Hour); - result = PRIME * result + Float.floatToIntBits(precip3Hour); - result = PRIME * result + Float.floatToIntBits(precip6Hour); - result = PRIME * result + Float.floatToIntBits(pressChange3Hour); - result = PRIME * result - + ((pressChangeChar == null) ? 0 : pressChangeChar.hashCode()); - result = PRIME * result + ((refHour == null) ? 0 : refHour.hashCode()); - result = PRIME * result - + ((reportType == null) ? 0 : reportType.hashCode()); - result = PRIME * result + Float.floatToIntBits(seaLevelPress); - result = PRIME * result - + ((skyCoverage == null) ? 0 : skyCoverage.hashCode()); - result = PRIME * result + ((skyKey == null) ? 0 : skyKey.hashCode()); - result = PRIME * result + skyLayerBase; - result = PRIME * result - + ((getStationId() == null) ? 0 : getStationId().hashCode()); - long temp; - temp = Double.doubleToLongBits(getLatitude()); - result = PRIME * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(getLongitude()); - result = PRIME * result + (int) (temp ^ (temp >>> 32)); - result = PRIME * result + Float.floatToIntBits(tempFromTenths); - result = PRIME * result + temperature; - result = PRIME * result + ((timeObs == null) ? 0 : timeObs.hashCode()); - result = PRIME * result + vertVisibility; - result = PRIME * result + +Float.floatToIntBits(visibility); - - result = PRIME - * result - + ((weatherCondition == null) ? 0 : weatherCondition.hashCode()); - result = PRIME * result - + ((weatherKey == null) ? 0 : weatherKey.hashCode()); - result = PRIME * result + ((windDir == null) ? 0 : windDir.hashCode()); - result = PRIME * result + windGust; - result = PRIME * result + windSpeed; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final MetarRecord other = (MetarRecord) obj; - if (Float.floatToIntBits(altimeter) != Float - .floatToIntBits(other.altimeter)) { - return false; - } - if (Float.floatToIntBits(altimeterInPa) != Float - .floatToIntBits(other.altimeterInPa)) { - return false; - } - if (autoStationType == null) { - if (other.autoStationType != null) { - return false; - } - } else if (!autoStationType.equals(other.autoStationType)) { - return false; - } - if (correction == null) { - if (other.correction != null) { - return false; - } - } else if (!correction.equals(other.correction)) { - return false; - } - if (dewPoint != other.dewPoint) { - return false; - } - if (Float.floatToIntBits(dewPointFromTenths) != Float - .floatToIntBits(other.dewPointFromTenths)) { - return false; - } - if (Float.floatToIntBits(maxTemp24Hour) != Float - .floatToIntBits(other.maxTemp24Hour)) { - return false; - } - if (Float.floatToIntBits(minTemp24Hour) != Float - .floatToIntBits(other.minTemp24Hour)) { - return false; - } - if (nominalTime == null) { - if (other.nominalTime != null) { - return false; - } - } else if (!nominalTime.equals(other.nominalTime)) { - return false; - } - if (Float.floatToIntBits(precip1Hour) != Float - .floatToIntBits(other.precip1Hour)) { - return false; - } - if (Float.floatToIntBits(precip3Hour) != Float - .floatToIntBits(other.precip3Hour)) { - return false; - } - if (Float.floatToIntBits(precip6Hour) != Float - .floatToIntBits(other.precip6Hour)) { - return false; - } - if (Float.floatToIntBits(pressChange3Hour) != Float - .floatToIntBits(other.pressChange3Hour)) { - return false; - } - if (pressChangeChar == null) { - if (other.pressChangeChar != null) { - return false; - } - } else if (!pressChangeChar.equals(other.pressChangeChar)) { - return false; - } - if (refHour == null) { - if (other.refHour != null) { - return false; - } - } else if (!refHour.equals(other.refHour)) { - return false; - } - if (reportType == null) { - if (other.reportType != null) { - return false; - } - } else if (!reportType.equals(other.reportType)) { - return false; - } - if (Float.floatToIntBits(seaLevelPress) != Float - .floatToIntBits(other.seaLevelPress)) { - return false; - } - if (skyCoverage == null) { - if (other.skyCoverage != null) { - return false; - } - } else if (!skyCoverage.equals(other.skyCoverage)) { - return false; - } - if (skyKey == null) { - if (other.skyKey != null) { - return false; - } - } else if (!skyKey.equals(other.skyKey)) { - return false; - } - if (skyLayerBase != other.skyLayerBase) { - return false; - } - - if (getStationId() == null) { - if (other.getStationId() != null) { - return false; - } - } else if (!getStationId().equals(other.getStationId())) { - return false; - } - - Double lat = location.getLatitude(); - if (lat == null) { - if (other.location.getLatitude() != null) { - return false; - } - } else { - if (!lat.equals(other.location.getLatitude())) { - return false; - } - } - Double lon = location.getLongitude(); - if (lon == null) { - if (other.location.getLongitude() != null) { - return false; - } - } else { - if (!lon.equals(other.location.getLongitude())) { - return false; - } - } - - if (Float.floatToIntBits(tempFromTenths) != Float - .floatToIntBits(other.tempFromTenths)) { - return false; - } - if (temperature != other.temperature) { - return false; - } - if (timeObs == null) { - if (other.timeObs != null) { - return false; - } - } else if (!timeObs.equals(other.timeObs)) { - return false; - } - if (vertVisibility != other.vertVisibility) { - return false; - } - if (Float.floatToIntBits(visibility) != Float - .floatToIntBits(other.visibility)) { - return false; - } - - if (weatherCondition == null) { - if (other.weatherCondition != null) { - return false; - } - } else if (!weatherCondition.equals(other.weatherCondition)) { - return false; - } - if (weatherKey == null) { - if (other.weatherKey != null) { - return false; - } - } else if (!weatherKey.equals(other.weatherKey)) { - return false; - } - if (windDir == null) { - if (other.windDir != null) { - return false; - } - } else if (!windDir.equals(other.windDir)) { - return false; - } - if (windGust != other.windGust) { - return false; - } - if (windSpeed != other.windSpeed) { - return false; - } - return true; - } - - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } - - public SurfaceObsLocation getLocation() { - return location; - } - - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - public String getReport() { - return report; - } - - public void setReport(String report) { - this.report = report; - } - - /** - * - * @return - */ - public String getWmoHeader() { - return wmoHeader; - } - - /** - * - * @param header - */ - public void setWmoHeader(String header) { - wmoHeader = header; - } - - @Override - public void setMessageData(Object message) { - this.messageData = message; - this.report = (String) message; - } - - @Override - public String getMessageData() { - if (sampleType != null && sampleType.equals("PR")) { - return getStationId(); - } - return report; - } - - private SkyCover getSkyCover(int index) { - if (!isSkyCoverageSorted) { - isSkyCoverageSorted = true; - sort(skyCoverage); - } - SkyCover[] sc = skyCoverage.toArray(new SkyCover[skyCoverage.size()]); - return sc[index]; - - } - - public void sort(Set skySet) { - SortedSet skSet = new TreeSet(); - for (SkyCover sc : skySet) { - skSet.add(sc); - } - - skyCoverage = skSet; - } - - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() - */ - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } - - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon - * .uf.common.pointdata.PointDataView) - */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } - - public static Set getAvailableParameters() { - return PARM_MAP.keySet(); - } @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "obs"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.pirep/src/com/raytheon/uf/common/dataplugin/pirep/PirepRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.pirep/src/com/raytheon/uf/common/dataplugin/pirep/PirepRecord.java index 0d9379d748..67ecda31bf 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.pirep/src/com/raytheon/uf/common/dataplugin/pirep/PirepRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.pirep/src/com/raytheon/uf/common/dataplugin/pirep/PirepRecord.java @@ -71,20 +71,21 @@ import com.vividsolutions.jts.geom.Geometry; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080103 384 jkorman Initial Coding. - * 20090408 952 jsanchez Updated getValue and getStrings methods. - * Added getMessageData method. - * 20090521 2338 jsanchez Changed the unit of the alititude. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * ====================================== - * AWIPS2 DR Work - * 08/09/2012 1011 jkorman Added separate max icing level as well - * as separated code to generate distinct max icing/turbulence levels. Removed - * code that used "display" boolean to determine data access. - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Jan 03, 2008 384 jkorman Initial Coding. + * Apr 08, 2009 952 jsanchez Updated getValue and getStrings methods. + * Added getMessageData method. + * May 21, 2009 2338 jsanchez Changed the unit of the alititude. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Aug 09, 2012 1011 jkorman Added separate max icing level as well + * as separated code to generate distinct + * max icing/turbulence levels. Removed + * code that used "display" boolean to + * determine data access. + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. - * + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author jkorman @@ -97,12 +98,8 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "pirep", - indexes = { - @Index(name = "pirep_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "pirep", indexes = { @Index(name = "pirep_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -635,14 +632,14 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, a = new Amount(this.getLatitude(), LOCATION_UNIT); } else if (STA_LON.equals(pName)) { a = new Amount(this.getLongitude(), LOCATION_UNIT); - } else if (UA_FLTLVL.equals(pName) && getFlightLevel() != null) { + } else if (UA_FLTLVL.equals(pName) && (getFlightLevel() != null)) { a = new Amount(this.getFlightLevel().intValue(), ALTITUDE_UNIT); - } else if (UA_TOPHGT.equals(pName) && maxTurbcLayerData != null - && maxTurbcLayerData.getTopLayerHeight() != null) { + } else if (UA_TOPHGT.equals(pName) && (maxTurbcLayerData != null) + && (maxTurbcLayerData.getTopLayerHeight() != null)) { a = new Amount(maxTurbcLayerData.getTopLayerHeight().intValue(), ALTITUDE_UNIT); - } else if (UA_BOTHGT.equals(pName) && maxTurbcLayerData != null - && maxTurbcLayerData.getBaseLayerHeight() != null) { + } else if (UA_BOTHGT.equals(pName) && (maxTurbcLayerData != null) + && (maxTurbcLayerData.getBaseLayerHeight() != null)) { a = new Amount(maxTurbcLayerData.getBaseLayerHeight().intValue(), ALTITUDE_UNIT); } @@ -675,7 +672,7 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, retData = new String[] { intensity }; } } - } else if ("ICT".matches(paramName) && maxIcingLayerData != null) { + } else if ("ICT".matches(paramName) && (maxIcingLayerData != null)) { if (maxIcingLayerData != null) { String type = maxIcingLayerData.getDataType(); if (type != null) { @@ -791,7 +788,7 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + result = (prime * result) + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); return result; } @@ -805,25 +802,34 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, */ @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } PirepRecord other = (PirepRecord) obj; if (getDataURI() == null) { if (other.getDataURI() != null) { return false; } - } else if (!getDataURI().equals(other.getDataURI())) + } else if (!getDataURI().equals(other.getDataURI())) { return false; + } return true; } + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } -} \ No newline at end of file + @Override + public String getPluginName() { + return "pirep"; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.poessounding/src/com/raytheon/uf/common/dataplugin/poessounding/POESSounding.java b/edexOsgi/com.raytheon.uf.common.dataplugin.poessounding/src/com/raytheon/uf/common/dataplugin/poessounding/POESSounding.java index a21ff790f7..2bdbc8a8ec 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.poessounding/src/com/raytheon/uf/common/dataplugin/poessounding/POESSounding.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.poessounding/src/com/raytheon/uf/common/dataplugin/poessounding/POESSounding.java @@ -59,6 +59,7 @@ import com.vividsolutions.jts.geom.Geometry; * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * May 15, 2013 1869 bsteffen Remove DataURI from goes/poes soundings. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -73,184 +74,174 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "poessounding", - indexes = { - @Index(name = "poessounding_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "poessounding", indexes = { @Index(name = "poessounding_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class POESSounding extends PersistablePluginDataObject implements ISpatialEnabled, IPointData { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - // The profiler observation time. - // @Column - // @DynamicSerializeElement - // @XmlElement - // private Calendar timeObs; + // Text of the WMO header + @Column(length = 32) + @DynamicSerializeElement + private String wmoHeader; - // @XmlAttribute - // @DynamicSerializeElement - // private Long fcstSeconds; + @Transient + private Set soundingLevels; - // Text of the WMO header - @Column(length = 32) - @DynamicSerializeElement - private String wmoHeader; + @Embedded + @DataURI(position = 1, embedded = true) + @DynamicSerializeElement + private SurfaceObsLocation location; - @Transient - private Set soundingLevels; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - @Embedded - @DataURI(position = 1, embedded = true) - @DynamicSerializeElement - private SurfaceObsLocation location; + /** + * Create an empty ProfilerObs object. + */ + public POESSounding() { + } - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public POESSounding(String uri) { + super(uri); + } - /** - * Create an empty ProfilerObs object. - */ - public POESSounding() { - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public POESSounding(String uri) { - super(uri); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } + /** + * Was this location defined from the station catalog? False if not. + * + * @return Was this location defined from the station catalog? + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } + /** + * Set the WMOHeader of the file that contained this data. + * + * @return The wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * Was this location defined from the station catalog? False if not. - * - * @return Was this location defined from the station catalog? - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } + /** + * Get the WMOHeader of the file that contained this data. + * + * @param wmoHeader + * The WMOHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * Set the WMOHeader of the file that contained this data. - * - * @return The wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the soundingLevels + */ + public Set getSoundingLevels() { + return soundingLevels; + } - /** - * Get the WMOHeader of the file that contained this data. - * - * @param wmoHeader - * The WMOHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param soundingLevels + * the soundingLevels to set + */ + public void setSoundingLevels(Set soundingLevels) { + this.soundingLevels = soundingLevels; + } - /** - * @return the soundingLevels - */ - public Set getSoundingLevels() { - return soundingLevels; - } + /** + * @param soundingLevels + * the soundingLevels to set + */ + public void addSoundingLevel(POESSoundingLevel soundingLevel) { + if (soundingLevels == null) { + soundingLevels = new HashSet(); + } + soundingLevels.add(soundingLevel); + } - /** - * @param soundingLevels - * the soundingLevels to set - */ - public void setSoundingLevels(Set soundingLevels) { - this.soundingLevels = soundingLevels; - } + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } - /** - * @param soundingLevels - * the soundingLevels to set - */ - public void addSoundingLevel(POESSoundingLevel soundingLevel) { - if (soundingLevels == null) { - soundingLevels = new HashSet(); - } - soundingLevels.add(soundingLevel); - } + public SurfaceObsLocation getLocation() { + return location; + } - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - public SurfaceObsLocation getLocation() { - return location; - } + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } - - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + @Override + public String getPluginName() { + return "poessounding"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.preciprate/src/com/raytheon/uf/common/dataplugin/preciprate/PrecipRateRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.preciprate/src/com/raytheon/uf/common/dataplugin/preciprate/PrecipRateRecord.java index 08e2c3dff4..001f24a6c4 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.preciprate/src/com/raytheon/uf/common/dataplugin/preciprate/PrecipRateRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.preciprate/src/com/raytheon/uf/common/dataplugin/preciprate/PrecipRateRecord.java @@ -75,12 +75,14 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 01/25/10 3796 D. Hladky Initial release - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 04/08/13 1293 bkowal Removed references to hdffileid. - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Jan 25, 2010 3796 D. Hladky Initial release + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -334,14 +336,14 @@ public class PrecipRateRecord extends PersistablePluginDataObject } if (dataRec != null) { - for (int i = 0; i < dataRec.length; i++) { - if (dataRec[i].getName().equals("Data")) { - setRawData(((ByteDataRecord) dataRec[i]).getByteData()); - } else if (dataRec[i].getName().equals("Angles")) { - setAngleData(((FloatDataRecord) dataRec[i]).getFloatData()); - } else if (dataRec[i].getName().equals("DHRMap")) { + for (IDataRecord element : dataRec) { + if (element.getName().equals("Data")) { + setRawData(((ByteDataRecord) element).getByteData()); + } else if (element.getName().equals("Angles")) { + setAngleData(((FloatDataRecord) element).getFloatData()); + } else if (element.getName().equals("DHRMap")) { try { - ByteDataRecord byteData = (ByteDataRecord) dataRec[i]; + ByteDataRecord byteData = (ByteDataRecord) element; ByteArrayInputStream bais = new ByteArrayInputStream( byteData.getByteData()); Object o = DynamicSerializationManager.getManager( @@ -616,4 +618,9 @@ public class PrecipRateRecord extends PersistablePluginDataObject public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "preciprate"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.profiler/src/com/raytheon/uf/common/dataplugin/profiler/ProfilerObs.java b/edexOsgi/com.raytheon.uf.common.dataplugin.profiler/src/com/raytheon/uf/common/dataplugin/profiler/ProfilerObs.java index 89ea424bee..d98ceee511 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.profiler/src/com/raytheon/uf/common/dataplugin/profiler/ProfilerObs.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.profiler/src/com/raytheon/uf/common/dataplugin/profiler/ProfilerObs.java @@ -71,14 +71,16 @@ import com.vividsolutions.jts.geom.Geometry; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080303 969 jkorman Initial implementation. - * 20090413 2251 jsanchez Implemented IDecoderGettable methods - * and plotted Profiler plots. - * 20090610 2489 jsanchez Updated the windSpeeed & windDirection. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Mar 03, 2008 969 jkorman Initial implementation. + * Apr 13, 2009 2251 jsanchez Implemented IDecoderGettable methods and + * plotted Profiler plots. + * Jun 10, 2009 2489 jsanchez Updated the windSpeeed & windDirection. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -92,12 +94,8 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "profiler", - indexes = { - @Index(name = "profiler_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "profiler", indexes = { @Index(name = "profiler_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -607,18 +605,20 @@ public class ProfilerObs extends PersistablePluginDataObject implements // Adjust to agl heights! Integer height = l.getLevelHeight() - getElevation(); - if (level == 1500 && height <= 1500 && height >= 1250) { + if ((level == 1500) && (height <= 1500) + && (height >= 1250)) { retValue = l; - } else if (level == 1250 && height <= 1500 - && height > 1125) { + } else if ((level == 1250) && (height <= 1500) + && (height > 1125)) { retValue = l; - } else if (level == 1000 && height <= 1125 - && height > 875) { + } else if ((level == 1000) && (height <= 1125) + && (height > 875)) { retValue = l; - } else if (level == 750 && height <= 875 - && height > 625) { + } else if ((level == 750) && (height <= 875) + && (height > 625)) { retValue = l; - } else if (level == 500 && height <= 625 && height > 0) { + } else if ((level == 500) && (height <= 625) + && (height > 0)) { retValue = l; } // No need to go higher than this. @@ -697,4 +697,9 @@ public class ProfilerObs extends PersistablePluginDataObject implements public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "profiler"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.qc/src/com/raytheon/uf/common/dataplugin/qc/QCRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.qc/src/com/raytheon/uf/common/dataplugin/qc/QCRecord.java index 42fcfbec87..01a02b4cd1 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.qc/src/com/raytheon/uf/common/dataplugin/qc/QCRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.qc/src/com/raytheon/uf/common/dataplugin/qc/QCRecord.java @@ -56,6 +56,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * May 16, 2013 1869 bsteffen Remove DataURI column from qc. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -70,1892 +71,1894 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "qc", - indexes = { - @Index(name = "qc_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "qc", indexes = { @Index(name = "qc_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class QCRecord extends PluginDataObject implements ISpatialEnabled { - private static final long serialVersionUID = -8836262244188895665L; + private static final long serialVersionUID = -8836262244188895665L; - @Transient - private Date invTime; + @Transient + private Date invTime; - /** Time to process stages 1 and 2 */ - @Transient - private int secondsStage1_2; + /** Time to process stages 1 and 2 */ + @Transient + private int secondsStage1_2; - /** Time to process stage 3 */ - @Transient - private int secondsStage3; + /** Time to process stage 3 */ + @Transient + private int secondsStage3; - /** Data provider station id */ - @Transient - private String providerId; + /** Data provider station id */ + @Transient + private String providerId; - /** Home WFO id */ - @Transient - private String homeWFO; + /** Home WFO id */ + @Transient + private String homeWFO; - /** Numeric WMO identification */ - @Transient - private int numericWMOid; + /** Numeric WMO identification */ + @Transient + private int numericWMOid; - /** LDAD Station Type */ - @Transient - private String stationType; + /** LDAD Station Type */ + @Transient + private String stationType; - /** Local data provider */ - @Transient - private String dataProvider; + /** Local data provider */ + @Transient + private String dataProvider; - @Transient - private int filterSetNum; + @Transient + private int filterSetNum; - /** List of possible QC checks */ - @Transient - private String qct; + /** List of possible QC checks */ + @Transient + private String qct; - /** List of possible IC checks */ - @Transient - private String ict; + /** List of possible IC checks */ + @Transient + private String ict; - @Embedded - @DataURI(position = 2, embedded = true) - @DynamicSerializeElement - private SurfaceObsLocation location; // latitude, longitude, elevation, + @Embedded + @DataURI(position = 2, embedded = true) + @DynamicSerializeElement + private SurfaceObsLocation location; // latitude, longitude, elevation, - @Column(nullable = false, length = 20) - @DataURI(position = 1) - @DynamicSerializeElement - private String qcType; + @Column(nullable = false, length = 20) + @DataURI(position = 1) + @DynamicSerializeElement + private String qcType; - /** Data Platform Type */ - @Transient - private int dataPlatformType; + /** Data Platform Type */ + @Transient + private int dataPlatformType; - /** Data Platform true direction */ - @Transient - private int platformTrueDirection; + /** Data Platform true direction */ + @Transient + private int platformTrueDirection; - /** Data platform true speed */ - @Transient - private int platformTrueSpeed; + /** Data platform true speed */ + @Transient + private int platformTrueSpeed; - /** Time of observation */ - @Transient - private Date observationTime; + /** Time of observation */ + @Transient + private Date observationTime; - /** Time data was processed by the provider */ - @Transient - private Date reportTime; + /** Time data was processed by the provider */ + @Transient + private Date reportTime; - /** Time data was received */ - @Transient - private Date receivedTime; + /** Time data was received */ + @Transient + private Date receivedTime; - /** Temperature reading */ - @Transient - private float temperature; + /** Temperature reading */ + @Transient + private float temperature; - /** Temperature time of last change */ - @Transient - private Date tempChangeTime; + /** Temperature time of last change */ + @Transient + private Date tempChangeTime; - /** Temperature QC summary value */ - @Transient - private String temperatureDD; + /** Temperature QC summary value */ + @Transient + private String temperatureDD; - /** Temperature QC applied word */ - @Transient - private String[] temperatureQCA; + /** Temperature QC applied word */ + @Transient + private String[] temperatureQCA; - /** Temperature QC Results word */ - @Transient - private String[] temperatureQCR; + /** Temperature QC Results word */ + @Transient + private String[] temperatureQCR; - /** Temperature QC departures */ - @Transient - private int[] temperatureQCD; + /** Temperature QC departures */ + @Transient + private int[] temperatureQCD; - /** Temperature IC applied word */ - @Transient - private String temperatureICA; + /** Temperature IC applied word */ + @Transient + private String temperatureICA; - /** Temperature IC results word */ - @Transient - private String temperatureICR; + /** Temperature IC results word */ + @Transient + private String temperatureICR; - /** Dew Point temperature */ - @Transient - private float dewpoint; + /** Dew Point temperature */ + @Transient + private float dewpoint; - /** Dew Point QC summary value */ - @Transient - private String dewpointDD; + /** Dew Point QC summary value */ + @Transient + private String dewpointDD; - /** Dew point QC applied word */ - @Transient - private String[] dewpointQCA; + /** Dew point QC applied word */ + @Transient + private String[] dewpointQCA; - /** dew point QC results word */ - @Transient - private String[] dewpointQCR; + /** dew point QC results word */ + @Transient + private String[] dewpointQCR; - /** dew point QC departures */ - @Transient - private int[] dewpointQCD; + /** dew point QC departures */ + @Transient + private int[] dewpointQCD; - /** dew point IC applied word */ - @Transient - private String dewpointICA; + /** dew point IC applied word */ + @Transient + private String dewpointICA; - /** dew point IC results word */ - @Transient - private String dewpointICR; + /** dew point IC results word */ + @Transient + private String dewpointICR; - /** wet bulb temperature */ - @Transient - private float wetBulbTemperature; + /** wet bulb temperature */ + @Transient + private float wetBulbTemperature; - /** relative humidity */ - @Transient - private float relHumidity; + /** relative humidity */ + @Transient + private float relHumidity; - /** relative humidity time of last change */ - @Transient - private Date rhChangeTime; + /** relative humidity time of last change */ + @Transient + private Date rhChangeTime; - /** relative humidity QC summary value */ - @Transient - private String relHumidityDD; + /** relative humidity QC summary value */ + @Transient + private String relHumidityDD; - /** relative humidity QC applied word */ - @Transient - private String[] relHumidityQCA; + /** relative humidity QC applied word */ + @Transient + private String[] relHumidityQCA; - /** relative humidity QC results word */ - @Transient - private String[] relHumidityQCR; + /** relative humidity QC results word */ + @Transient + private String[] relHumidityQCR; - /** relative humidity QC departures */ - @Transient - private int[] relHumidityQCD; + /** relative humidity QC departures */ + @Transient + private int[] relHumidityQCD; - /** station pressure */ - @Transient - private float stationPressure; + /** station pressure */ + @Transient + private float stationPressure; - /** station press time of last change */ - @Transient - private Date stationPressChangeTime; + /** station press time of last change */ + @Transient + private Date stationPressChangeTime; - /** station pressure QC summary value */ - @Transient - private String stationPressureDD; + /** station pressure QC summary value */ + @Transient + private String stationPressureDD; - /** station pressure QC applied word */ - @Transient - private String[] stationPressureQCA; + /** station pressure QC applied word */ + @Transient + private String[] stationPressureQCA; - /** station pressure QC results word */ - @Transient - private String[] stationPressureQCR; + /** station pressure QC results word */ + @Transient + private String[] stationPressureQCR; - /** station pressure QC departures */ - @Transient - private int[] stationPressureQCD; + /** station pressure QC departures */ + @Transient + private int[] stationPressureQCD; - /** station pressure IC applied word */ - @Transient - private String stationPressureICA; + /** station pressure IC applied word */ + @Transient + private String stationPressureICA; - /** station pressure IC results word */ - @Transient - private String stationPressureICR; + /** station pressure IC results word */ + @Transient + private String stationPressureICR; - /** sea level pressure */ - @Transient - private float seaLevelPressure; + /** sea level pressure */ + @Transient + private float seaLevelPressure; - /** Sea level pressure QC summary value */ - @Transient - private String seaLevelPressureDD; + /** Sea level pressure QC summary value */ + @Transient + private String seaLevelPressureDD; - /** sea level pressure QC applied word */ - @Transient - private String[] seaLevelPressureQCA; + /** sea level pressure QC applied word */ + @Transient + private String[] seaLevelPressureQCA; - /** sea level pressure QC results word */ - @Transient - private String[] seaLevelPressureQCR; + /** sea level pressure QC results word */ + @Transient + private String[] seaLevelPressureQCR; - /** sea level pressure QC departures */ - @Transient - private int[] seaLevelPressureQCD; + /** sea level pressure QC departures */ + @Transient + private int[] seaLevelPressureQCD; - /** sea level pressure IC applied word */ - @Transient - private String seaLevelPressureICA; + /** sea level pressure IC applied word */ + @Transient + private String seaLevelPressureICA; - /** sea level pressure IC results word */ - @Transient - private String seaLevelPressureICR; + /** sea level pressure IC results word */ + @Transient + private String seaLevelPressureICR; - /** character of pressure change */ - @Transient - private String pressChangeChar; + /** character of pressure change */ + @Transient + private String pressChangeChar; - /** 3 hour pressure change */ - @Transient - private float pressChange3Hour; + /** 3 hour pressure change */ + @Transient + private float pressChange3Hour; - /** 3h pressure change QC summary value */ - @Transient - private String pressChange3HourDD; + /** 3h pressure change QC summary value */ + @Transient + private String pressChange3HourDD; - /** 3h pressure change QC applied word */ - @Transient - private String[] pressChange3HourQCA; + /** 3h pressure change QC applied word */ + @Transient + private String[] pressChange3HourQCA; - /** 3h pressure change QC results word */ - @Transient - private String[] pressChange3HourQCR; + /** 3h pressure change QC results word */ + @Transient + private String[] pressChange3HourQCR; - /** 3h pressure change QC departures */ - @Transient - private int[] pressChange3HourQCD; + /** 3h pressure change QC departures */ + @Transient + private int[] pressChange3HourQCD; - /** 3h pressure change IC applied word */ - @Transient - private String pressChange3HourICA; + /** 3h pressure change IC applied word */ + @Transient + private String pressChange3HourICA; - /** 3h pressure change IC results word */ - @Transient - private String pressChange3HourICR; + /** 3h pressure change IC results word */ + @Transient + private String pressChange3HourICR; - /** altimeter setting */ - @Transient - private float altimeter; + /** altimeter setting */ + @Transient + private float altimeter; - /** altimeter setting QC summary value */ - @Transient - private String altimeterDD; + /** altimeter setting QC summary value */ + @Transient + private String altimeterDD; - /** altimeter setting QC applied word */ - @Transient - private String[] altimeterQCA; + /** altimeter setting QC applied word */ + @Transient + private String[] altimeterQCA; - /** altimeter setting QC results word */ - @Transient - private String[] altimeterQCR; + /** altimeter setting QC results word */ + @Transient + private String[] altimeterQCR; - /** altimeter setting QC departures */ - @Transient - private int[] altimeterQCD; + /** altimeter setting QC departures */ + @Transient + private int[] altimeterQCD; - /** wind direction */ - @Transient - private float windDir; + /** wind direction */ + @Transient + private float windDir; - /** wind direction time of last change */ - @Transient - private Date windDirChangeTime; + /** wind direction time of last change */ + @Transient + private Date windDirChangeTime; - /** wind direction QC summary value */ - @Transient - private String windDirDD; + /** wind direction QC summary value */ + @Transient + private String windDirDD; - /** wind direction QC applied word */ - @Transient - private String[] windDirQCA; + /** wind direction QC applied word */ + @Transient + private String[] windDirQCA; - /** wind direction QC results word */ - @Transient - private String[] windDirQCR; + /** wind direction QC results word */ + @Transient + private String[] windDirQCR; - /** wind direction QC departures */ - @Transient - private int[] windDirQCD; + /** wind direction QC departures */ + @Transient + private int[] windDirQCD; - /** wind direction IC applied word */ - @Transient - private String windDirICA; + /** wind direction IC applied word */ + @Transient + private String windDirICA; - /** wind direction IC results word */ - @Transient - private String windDirICR; + /** wind direction IC results word */ + @Transient + private String windDirICR; - /** wind speed */ - @Transient - private float windSpeed; + /** wind speed */ + @Transient + private float windSpeed; - /** wind speed time of last change */ - @Transient - private Date windSpeedChangeTime; + /** wind speed time of last change */ + @Transient + private Date windSpeedChangeTime; - /** wind speed QC summary value */ - @Transient - private String windSpeedDD; + /** wind speed QC summary value */ + @Transient + private String windSpeedDD; - /** wind speed QC applied word */ - @Transient - private String[] windSpeedQCA; + /** wind speed QC applied word */ + @Transient + private String[] windSpeedQCA; - /** wind speed QC results word */ - @Transient - private String[] windSpeedQCR; + /** wind speed QC results word */ + @Transient + private String[] windSpeedQCR; - /** wind speed QC departures */ - @Transient - private int[] windSpeedQCD; + /** wind speed QC departures */ + @Transient + private int[] windSpeedQCD; - /** wind speed IC applied word */ - @Transient - private String windSpeedICA; + /** wind speed IC applied word */ + @Transient + private String windSpeedICA; - /** wind speed IC results word */ - @Transient - private String windSpeedICR; + /** wind speed IC results word */ + @Transient + private String windSpeedICR; - /** wind gust */ - @Transient - private float windGust; + /** wind gust */ + @Transient + private float windGust; - /** Wind gust QC applied word */ - @Transient - private String[] windGustQCA; + /** Wind gust QC applied word */ + @Transient + private String[] windGustQCA; - /** Wind gust QC results word */ - @Transient - private String[] windGustQCR; + /** Wind gust QC results word */ + @Transient + private String[] windGustQCR; - /** Wind gust QC departures */ - @Transient - private int[] windGustQCD; + /** Wind gust QC departures */ + @Transient + private int[] windGustQCD; - /** wind direction at mininum windspeed */ - @Transient - private float windDirMin; + /** wind direction at mininum windspeed */ + @Transient + private float windDirMin; - /** wind direction at gust */ - @Transient - private float windDirMax; + /** wind direction at gust */ + @Transient + private float windDirMax; - /** wind direction at gust QC summary value */ - @Transient - private String windDirMaxDD; + /** wind direction at gust QC summary value */ + @Transient + private String windDirMaxDD; - /** wind direction at gust QC applied word */ - @Transient - private String[] windDirMaxQCA; + /** wind direction at gust QC applied word */ + @Transient + private String[] windDirMaxQCA; - /** wind direction at gust QC results word */ - @Transient - private String[] windDirMaxQCR; + /** wind direction at gust QC results word */ + @Transient + private String[] windDirMaxQCR; - /** wind direction at gust QC departures */ - @Transient - private int[] windDirMaxQCD; + /** wind direction at gust QC departures */ + @Transient + private int[] windDirMaxQCD; - /** sky cover */ - @Transient - private String skyCover; + /** sky cover */ + @Transient + private String skyCover; - /** sky cover layer base */ - @Transient - private float[] skyLayerBase; + /** sky cover layer base */ + @Transient + private float[] skyLayerBase; - /** visibility */ - @Transient - private float visibility; + /** visibility */ + @Transient + private float visibility; - /** visibility QC summary value */ - @Transient - private String visibilityDD; + /** visibility QC summary value */ + @Transient + private String visibilityDD; - /** visibility QC applied word */ - @Transient - private String[] visibilityQCA; + /** visibility QC applied word */ + @Transient + private String[] visibilityQCA; - /** visibility QC results word */ - @Transient - private String[] visibilityQCR; + /** visibility QC results word */ + @Transient + private String[] visibilityQCR; - /** visibility QC departures */ - @Transient - private int[] visibilityQCD; + /** visibility QC departures */ + @Transient + private int[] visibilityQCD; - /** visibility QC applied word */ - @Transient - private String visibilityICA; + /** visibility QC applied word */ + @Transient + private String visibilityICA; - /** visibility IC results word */ - @Transient - private String visibilityICR; + /** visibility IC results word */ + @Transient + private String visibilityICR; - /** fraction of sky covered by clouds */ - @Transient - private float totalCloudCover; + /** fraction of sky covered by clouds */ + @Transient + private float totalCloudCover; - /** height of the lowest cloud layer */ - @Transient - private String cloudBaseHeight; + /** height of the lowest cloud layer */ + @Transient + private String cloudBaseHeight; - /** present weather */ - @Transient - private String presWeather; + /** present weather */ + @Transient + private String presWeather; - /** low level cloud type */ - @Transient - private String lowLevelCloudType; + /** low level cloud type */ + @Transient + private String lowLevelCloudType; - /** middle level cloud type */ - @Transient - private String midLevelCloudType; + /** middle level cloud type */ + @Transient + private String midLevelCloudType; - /** high level cloud type */ - @Transient - private String highLevelCloudType; + /** high level cloud type */ + @Transient + private String highLevelCloudType; - /** maximum temperature recording period */ - @Transient - private String maxTempRecordPeriod; + /** maximum temperature recording period */ + @Transient + private String maxTempRecordPeriod; - /** minimum temperature recording period */ - @Transient - private String minTempRecordPeriod; + /** minimum temperature recording period */ + @Transient + private String minTempRecordPeriod; - /** minimum temperature */ - @Transient - private float minimumTemperature; + /** minimum temperature */ + @Transient + private float minimumTemperature; - /** raw precip accumulation */ - @Transient - private float rawPrecip; + /** raw precip accumulation */ + @Transient + private float rawPrecip; - /** precip accumulation */ - @Transient - private float precipAccum; + /** precip accumulation */ + @Transient + private float precipAccum; - /** precip amount QC summary value */ - @Transient - private String precipAccumDD; + /** precip amount QC summary value */ + @Transient + private String precipAccumDD; - /** precip amount QC applied word */ - @Transient - private String[] precipAccumQCA; + /** precip amount QC applied word */ + @Transient + private String[] precipAccumQCA; - /** precip amount QC results word */ - @Transient - private String[] precipAccumQCR; + /** precip amount QC results word */ + @Transient + private String[] precipAccumQCR; - /** precip amount QC departures */ - @Transient - private int[] precipAccumQCD; + /** precip amount QC departures */ + @Transient + private int[] precipAccumQCD; - /** precip amount IC applied word */ - @Transient - private String precipAccumICA; + /** precip amount IC applied word */ + @Transient + private String precipAccumICA; - /** precip amount IC results word */ - @Transient - private String precipAccumICR; + /** precip amount IC results word */ + @Transient + private String precipAccumICR; - /** precipitation rate */ - @Transient - private float precipRate; + /** precipitation rate */ + @Transient + private float precipRate; - /** precip rate QC summary value */ - @Transient - private String precipRateDD; + /** precip rate QC summary value */ + @Transient + private String precipRateDD; - /** precip rate QC applied word */ - @Transient - private String[] precipRateQCA; + /** precip rate QC applied word */ + @Transient + private String[] precipRateQCA; - /** precip rate QC results word */ - @Transient - private String[] precipRateQCR; + /** precip rate QC results word */ + @Transient + private String[] precipRateQCR; - /** precip rate QC departures */ - @Transient - private int[] precipRateQCD; + /** precip rate QC departures */ + @Transient + private int[] precipRateQCD; - /** precipitation type */ - @Transient - private String precipType; + /** precipitation type */ + @Transient + private String precipType; - /** precipitation intensity */ - @Transient - private String precipIntensity; + /** precipitation intensity */ + @Transient + private String precipIntensity; - /** time since last precip */ - @Transient - private int timeSinceLastPcp; + /** time since last precip */ + @Transient + private int timeSinceLastPcp; - /** solar radiation */ - @Transient - private float solarRadiation; + /** solar radiation */ + @Transient + private float solarRadiation; - /** solar radiation time of last change */ - @Transient - private Date solarRadiationChangeTime; + /** solar radiation time of last change */ + @Transient + private Date solarRadiationChangeTime; - /** sea surface temperature */ - @Transient - private float seaSurfaceTemp; + /** sea surface temperature */ + @Transient + private float seaSurfaceTemp; - /** Sea surface temperature QC summary value */ - @Transient - private String seaSurfaceTempDD; + /** Sea surface temperature QC summary value */ + @Transient + private String seaSurfaceTempDD; - /** Sea surface temperature QC applied word */ - @Transient - private String[] seaSurfaceTempQCA; + /** Sea surface temperature QC applied word */ + @Transient + private String[] seaSurfaceTempQCA; - /** SeaSurfaceTemp QC Results word */ - @Transient - private String[] seaSurfaceTempQCR; + /** SeaSurfaceTemp QC Results word */ + @Transient + private String[] seaSurfaceTempQCR; - /** Sea surface temperature QC departures */ - @Transient - private int[] seaSurfaceTempQCD; + /** Sea surface temperature QC departures */ + @Transient + private int[] seaSurfaceTempQCD; - /** Sea surface temperature IC applied word */ - @Transient - private String seaSurfaceTempICA; + /** Sea surface temperature IC applied word */ + @Transient + private String seaSurfaceTempICA; - /** Sea surface temperature IC results word */ - @Transient - private String seaSurfaceTempICR; + /** Sea surface temperature IC results word */ + @Transient + private String seaSurfaceTempICR; - /** wave period */ - @Transient - private float wavePeriod; + /** wave period */ + @Transient + private float wavePeriod; - /** wave height */ - @Transient - private float waveHeight; + /** wave height */ + @Transient + private float waveHeight; - /** raw text LDAD mesonet message */ - @Transient - private String rawMessage; + /** raw text LDAD mesonet message */ + @Transient + private String rawMessage; - /** Total column precipitable water vapor */ - @Transient - private float totalColumnPWV; + /** Total column precipitable water vapor */ + @Transient + private float totalColumnPWV; - /** Total GPS signal delay */ - @Transient - private float totalSignalDelay; + /** Total GPS signal delay */ + @Transient + private float totalSignalDelay; - /** Dry component GPS signal delay */ - @Transient - private float drySignalDelay; + /** Dry component GPS signal delay */ + @Transient + private float drySignalDelay; - /** Wet component GPS signal delay */ - @Transient - private float wetSignalDelay; + /** Wet component GPS signal delay */ + @Transient + private float wetSignalDelay; - /** Mean weighted temperature */ - @Transient - private float meanWeightedTemperature; + /** Mean weighted temperature */ + @Transient + private float meanWeightedTemperature; - /** Formal Error */ - @Transient - private float formalError; + /** Formal Error */ + @Transient + private float formalError; - /** Wet delay mapping function */ - @Transient - private float capPi; + /** Wet delay mapping function */ + @Transient + private float capPi; - @Column(length = 15) - private String ncSet; + @Column(length = 15) + private String ncSet; - @Embedded - @DynamicSerializeElement - private FakePointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private FakePointDataView pointDataView; - @Embeddable - @DynamicSerialize - private static class FakePointDataView { - @DynamicSerializeElement - @Column(name = "idx") - int curIdx; - } + @Embeddable + @DynamicSerialize + private static class FakePointDataView { + @DynamicSerializeElement + @Column(name = "idx") + int curIdx; + } - public QCRecord() { + public QCRecord() { - } + } - public QCRecord(String uri) { - super(uri); - } + public QCRecord(String uri) { + super(uri); + } - public Date getInvTime() { - return invTime; - } - - public void setInvTime(Date invTime) { - this.invTime = invTime; - } - - public int getSecondsStage1_2() { - return secondsStage1_2; - } - - public void setSecondsStage1_2(int secondsStage1_2) { - this.secondsStage1_2 = secondsStage1_2; - } - - public int getSecondsStage3() { - return secondsStage3; - } - - public void setSecondsStage3(int secondsStage3) { - this.secondsStage3 = secondsStage3; - } - - public String getProviderId() { - return providerId; - } - - public void setProviderId(String providerId) { - this.providerId = providerId; - } - - public String getStationId() { - return location.getStationId(); - } - - public String getHomeWFO() { - return homeWFO; - } - - public void setHomeWFO(String homeWFO) { - this.homeWFO = homeWFO; - } - - public int getNumericWMOid() { - return numericWMOid; - } - - public void setNumericWMOid(int numericWMOid) { - this.numericWMOid = numericWMOid; - } - - public String getStationType() { - return stationType; - } - - public void setStationType(String stationType) { - this.stationType = stationType; - } - - public String getDataProvider() { - return dataProvider; - } - - public void setDataProvider(String dataProvider) { - this.dataProvider = dataProvider; - } - - public int getFilterSetNum() { - return filterSetNum; - } - - public void setFilterSetNum(int filterSetNum) { - this.filterSetNum = filterSetNum; - } - - public String getQct() { - return qct; - } - - public void setQct(String qct) { - this.qct = qct; - } - - public String getIct() { - return ict; - } - - public void setIct(String ict) { - this.ict = ict; - } + public Date getInvTime() { + return invTime; + } + + public void setInvTime(Date invTime) { + this.invTime = invTime; + } + + public int getSecondsStage1_2() { + return secondsStage1_2; + } + + public void setSecondsStage1_2(int secondsStage1_2) { + this.secondsStage1_2 = secondsStage1_2; + } + + public int getSecondsStage3() { + return secondsStage3; + } + + public void setSecondsStage3(int secondsStage3) { + this.secondsStage3 = secondsStage3; + } + + public String getProviderId() { + return providerId; + } + + public void setProviderId(String providerId) { + this.providerId = providerId; + } + + public String getStationId() { + return location.getStationId(); + } + + public String getHomeWFO() { + return homeWFO; + } + + public void setHomeWFO(String homeWFO) { + this.homeWFO = homeWFO; + } + + public int getNumericWMOid() { + return numericWMOid; + } + + public void setNumericWMOid(int numericWMOid) { + this.numericWMOid = numericWMOid; + } + + public String getStationType() { + return stationType; + } + + public void setStationType(String stationType) { + this.stationType = stationType; + } + + public String getDataProvider() { + return dataProvider; + } + + public void setDataProvider(String dataProvider) { + this.dataProvider = dataProvider; + } + + public int getFilterSetNum() { + return filterSetNum; + } + + public void setFilterSetNum(int filterSetNum) { + this.filterSetNum = filterSetNum; + } + + public String getQct() { + return qct; + } + + public void setQct(String qct) { + this.qct = qct; + } + + public String getIct() { + return ict; + } + + public void setIct(String ict) { + this.ict = ict; + } - /** - * @return the location - */ - public SurfaceObsLocation getLocation() { - return location; - } - - /** - * @param location - * the location to set - */ - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - public float getLatitude() { - return location.getLatitude().floatValue(); - } - - public float getLongitude() { - return location.getLongitude().floatValue(); - } - - public float getElevation() { - return location.getElevation(); - } - - public int getDataPlatformType() { - return dataPlatformType; - } - - public void setDataPlatformType(int dataPlatformType) { - this.dataPlatformType = dataPlatformType; - } - - public int getPlatformTrueDirection() { - return platformTrueDirection; - } - - public void setPlatformTrueDirection(int platformTrueDirection) { - this.platformTrueDirection = platformTrueDirection; - } - - public int getPlatformTrueSpeed() { - return platformTrueSpeed; - } - - public void setPlatformTrueSpeed(int platformTrueSpeed) { - this.platformTrueSpeed = platformTrueSpeed; - } - - public Date getObservationTime() { - return observationTime; - } - - public void setObservationTime(Date observationTime) { - this.observationTime = observationTime; - } - - public Date getReportTime() { - return reportTime; - } - - public void setReportTime(Date reportTime) { - this.reportTime = reportTime; - } - - public Date getReceivedTime() { - return receivedTime; - } - - public void setReceivedTime(Date receivedTime) { - this.receivedTime = receivedTime; - } - - public float getTemperature() { - return temperature; - } - - public void setTemperature(float temperature) { - this.temperature = temperature; - } - - public Date getTempChangeTime() { - return tempChangeTime; - } - - public void setTempChangeTime(Date tempChangeTime) { - this.tempChangeTime = tempChangeTime; - } - - public String getTemperatureDD() { - return temperatureDD; - } - - public void setTemperatureDD(String temperatureDD) { - this.temperatureDD = temperatureDD; - } - - public String[] getTemperatureQCA() { - return temperatureQCA; - } - - public void setTemperatureQCA(String[] temperatureQCA) { - this.temperatureQCA = temperatureQCA; - } + /** + * @return the location + */ + public SurfaceObsLocation getLocation() { + return location; + } + + /** + * @param location + * the location to set + */ + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } + + public float getLatitude() { + return location.getLatitude().floatValue(); + } + + public float getLongitude() { + return location.getLongitude().floatValue(); + } + + public float getElevation() { + return location.getElevation(); + } + + public int getDataPlatformType() { + return dataPlatformType; + } + + public void setDataPlatformType(int dataPlatformType) { + this.dataPlatformType = dataPlatformType; + } + + public int getPlatformTrueDirection() { + return platformTrueDirection; + } + + public void setPlatformTrueDirection(int platformTrueDirection) { + this.platformTrueDirection = platformTrueDirection; + } + + public int getPlatformTrueSpeed() { + return platformTrueSpeed; + } + + public void setPlatformTrueSpeed(int platformTrueSpeed) { + this.platformTrueSpeed = platformTrueSpeed; + } + + public Date getObservationTime() { + return observationTime; + } + + public void setObservationTime(Date observationTime) { + this.observationTime = observationTime; + } + + public Date getReportTime() { + return reportTime; + } + + public void setReportTime(Date reportTime) { + this.reportTime = reportTime; + } + + public Date getReceivedTime() { + return receivedTime; + } + + public void setReceivedTime(Date receivedTime) { + this.receivedTime = receivedTime; + } + + public float getTemperature() { + return temperature; + } + + public void setTemperature(float temperature) { + this.temperature = temperature; + } + + public Date getTempChangeTime() { + return tempChangeTime; + } + + public void setTempChangeTime(Date tempChangeTime) { + this.tempChangeTime = tempChangeTime; + } + + public String getTemperatureDD() { + return temperatureDD; + } + + public void setTemperatureDD(String temperatureDD) { + this.temperatureDD = temperatureDD; + } + + public String[] getTemperatureQCA() { + return temperatureQCA; + } + + public void setTemperatureQCA(String[] temperatureQCA) { + this.temperatureQCA = temperatureQCA; + } - public String[] getTemperatureQCR() { - return temperatureQCR; - } + public String[] getTemperatureQCR() { + return temperatureQCR; + } - public void setTemperatureQCR(String[] temperatureQCR) { - this.temperatureQCR = temperatureQCR; - } + public void setTemperatureQCR(String[] temperatureQCR) { + this.temperatureQCR = temperatureQCR; + } - public int[] getTemperatureQCD() { - return temperatureQCD; - } + public int[] getTemperatureQCD() { + return temperatureQCD; + } - public void setTemperatureQCD(int[] temperatureQCD) { - this.temperatureQCD = temperatureQCD; - } + public void setTemperatureQCD(int[] temperatureQCD) { + this.temperatureQCD = temperatureQCD; + } - public String getTemperatureICA() { - return temperatureICA; - } + public String getTemperatureICA() { + return temperatureICA; + } - public void setTemperatureICA(String temperatureICA) { - this.temperatureICA = temperatureICA; - } + public void setTemperatureICA(String temperatureICA) { + this.temperatureICA = temperatureICA; + } - public String getTemperatureICR() { - return temperatureICR; - } + public String getTemperatureICR() { + return temperatureICR; + } - public void setTemperatureICR(String temperatureICR) { - this.temperatureICR = temperatureICR; - } + public void setTemperatureICR(String temperatureICR) { + this.temperatureICR = temperatureICR; + } - public float getDewpoint() { - return dewpoint; - } + public float getDewpoint() { + return dewpoint; + } - public void setDewpoint(float dewpoint) { - this.dewpoint = dewpoint; - } + public void setDewpoint(float dewpoint) { + this.dewpoint = dewpoint; + } - public String getDewpointDD() { - return dewpointDD; - } + public String getDewpointDD() { + return dewpointDD; + } - public void setDewpointDD(String dewpointDD) { - this.dewpointDD = dewpointDD; - } + public void setDewpointDD(String dewpointDD) { + this.dewpointDD = dewpointDD; + } - public String[] getDewpointQCA() { - return dewpointQCA; - } + public String[] getDewpointQCA() { + return dewpointQCA; + } - public void setDewpointQCA(String[] dewpointQCA) { - this.dewpointQCA = dewpointQCA; - } + public void setDewpointQCA(String[] dewpointQCA) { + this.dewpointQCA = dewpointQCA; + } - public String[] getDewpointQCR() { - return dewpointQCR; - } + public String[] getDewpointQCR() { + return dewpointQCR; + } - public void setDewpointQCR(String[] dewpointQCR) { - this.dewpointQCR = dewpointQCR; - } + public void setDewpointQCR(String[] dewpointQCR) { + this.dewpointQCR = dewpointQCR; + } - public int[] getDewpointQCD() { - return dewpointQCD; - } + public int[] getDewpointQCD() { + return dewpointQCD; + } - public void setDewpointQCD(int[] dewpointQCD) { - this.dewpointQCD = dewpointQCD; - } + public void setDewpointQCD(int[] dewpointQCD) { + this.dewpointQCD = dewpointQCD; + } - public String getDewpointICA() { - return dewpointICA; - } + public String getDewpointICA() { + return dewpointICA; + } - public void setDewpointICA(String dewpointICA) { - this.dewpointICA = dewpointICA; - } + public void setDewpointICA(String dewpointICA) { + this.dewpointICA = dewpointICA; + } - public String getDewpointICR() { - return dewpointICR; - } + public String getDewpointICR() { + return dewpointICR; + } - public void setDewpointICR(String dewpointICR) { - this.dewpointICR = dewpointICR; - } + public void setDewpointICR(String dewpointICR) { + this.dewpointICR = dewpointICR; + } - public float getWetBulbTemperature() { - return wetBulbTemperature; - } + public float getWetBulbTemperature() { + return wetBulbTemperature; + } - public void setWetBulbTemperature(float wetBulbTemperature) { - this.wetBulbTemperature = wetBulbTemperature; - } + public void setWetBulbTemperature(float wetBulbTemperature) { + this.wetBulbTemperature = wetBulbTemperature; + } - public float getRelHumidity() { - return relHumidity; - } + public float getRelHumidity() { + return relHumidity; + } - public void setRelHumidity(float relHumidity) { - this.relHumidity = relHumidity; - } + public void setRelHumidity(float relHumidity) { + this.relHumidity = relHumidity; + } - public Date getRhChangeTime() { - return rhChangeTime; - } + public Date getRhChangeTime() { + return rhChangeTime; + } - public void setRhChangeTime(Date rhChangeTime) { - this.rhChangeTime = rhChangeTime; - } + public void setRhChangeTime(Date rhChangeTime) { + this.rhChangeTime = rhChangeTime; + } - public String getRelHumidityDD() { - return relHumidityDD; - } + public String getRelHumidityDD() { + return relHumidityDD; + } - public void setRelHumidityDD(String relHumidityDD) { - this.relHumidityDD = relHumidityDD; - } + public void setRelHumidityDD(String relHumidityDD) { + this.relHumidityDD = relHumidityDD; + } - public String[] getRelHumidityQCA() { - return relHumidityQCA; - } + public String[] getRelHumidityQCA() { + return relHumidityQCA; + } - public void setRelHumidityQCA(String[] relHumidityQCA) { - this.relHumidityQCA = relHumidityQCA; - } + public void setRelHumidityQCA(String[] relHumidityQCA) { + this.relHumidityQCA = relHumidityQCA; + } - public String[] getRelHumidityQCR() { - return relHumidityQCR; - } + public String[] getRelHumidityQCR() { + return relHumidityQCR; + } - public void setRelHumidityQCR(String[] relHumidityQCR) { - this.relHumidityQCR = relHumidityQCR; - } + public void setRelHumidityQCR(String[] relHumidityQCR) { + this.relHumidityQCR = relHumidityQCR; + } - public int[] getRelHumidityQCD() { - return relHumidityQCD; - } + public int[] getRelHumidityQCD() { + return relHumidityQCD; + } - public void setRelHumidityQCD(int[] relHumidityQCD) { - this.relHumidityQCD = relHumidityQCD; - } + public void setRelHumidityQCD(int[] relHumidityQCD) { + this.relHumidityQCD = relHumidityQCD; + } - public float getStationPressure() { - return stationPressure; - } + public float getStationPressure() { + return stationPressure; + } - public void setStationPressure(float stationPressure) { - this.stationPressure = stationPressure; - } + public void setStationPressure(float stationPressure) { + this.stationPressure = stationPressure; + } - public Date getStationPressChangeTime() { - return stationPressChangeTime; - } + public Date getStationPressChangeTime() { + return stationPressChangeTime; + } - public void setStationPressChangeTime(Date stationPressChangeTime) { - this.stationPressChangeTime = stationPressChangeTime; - } + public void setStationPressChangeTime(Date stationPressChangeTime) { + this.stationPressChangeTime = stationPressChangeTime; + } - public String getStationPressureDD() { - return stationPressureDD; - } + public String getStationPressureDD() { + return stationPressureDD; + } - public void setStationPressureDD(String stationPressureDD) { - this.stationPressureDD = stationPressureDD; - } + public void setStationPressureDD(String stationPressureDD) { + this.stationPressureDD = stationPressureDD; + } - public String[] getStationPressureQCA() { - return stationPressureQCA; - } + public String[] getStationPressureQCA() { + return stationPressureQCA; + } - public void setStationPressureQCA(String[] stationPressureQCA) { - this.stationPressureQCA = stationPressureQCA; - } + public void setStationPressureQCA(String[] stationPressureQCA) { + this.stationPressureQCA = stationPressureQCA; + } - public String[] getStationPressureQCR() { - return stationPressureQCR; - } + public String[] getStationPressureQCR() { + return stationPressureQCR; + } - public void setStationPressureQCR(String[] stationPressureQCR) { - this.stationPressureQCR = stationPressureQCR; - } + public void setStationPressureQCR(String[] stationPressureQCR) { + this.stationPressureQCR = stationPressureQCR; + } - public int[] getStationPressureQCD() { - return stationPressureQCD; - } + public int[] getStationPressureQCD() { + return stationPressureQCD; + } - public void setStationPressureQCD(int[] stationPressureQCD) { - this.stationPressureQCD = stationPressureQCD; - } + public void setStationPressureQCD(int[] stationPressureQCD) { + this.stationPressureQCD = stationPressureQCD; + } - public String getStationPressureICA() { - return stationPressureICA; - } + public String getStationPressureICA() { + return stationPressureICA; + } - public void setStationPressureICA(String stationPressureICA) { - this.stationPressureICA = stationPressureICA; - } + public void setStationPressureICA(String stationPressureICA) { + this.stationPressureICA = stationPressureICA; + } - public String getStationPressureICR() { - return stationPressureICR; - } + public String getStationPressureICR() { + return stationPressureICR; + } - public void setStationPressureICR(String stationPressureICR) { - this.stationPressureICR = stationPressureICR; - } + public void setStationPressureICR(String stationPressureICR) { + this.stationPressureICR = stationPressureICR; + } - public float getSeaLevelPressure() { - return seaLevelPressure; - } + public float getSeaLevelPressure() { + return seaLevelPressure; + } - public void setSeaLevelPressure(float seaLevelPressure) { - this.seaLevelPressure = seaLevelPressure; - } + public void setSeaLevelPressure(float seaLevelPressure) { + this.seaLevelPressure = seaLevelPressure; + } - public String getSeaLevelPressureDD() { - return seaLevelPressureDD; - } + public String getSeaLevelPressureDD() { + return seaLevelPressureDD; + } - public void setSeaLevelPressureDD(String seaLevelPressureDD) { - this.seaLevelPressureDD = seaLevelPressureDD; - } + public void setSeaLevelPressureDD(String seaLevelPressureDD) { + this.seaLevelPressureDD = seaLevelPressureDD; + } - public String[] getSeaLevelPressureQCA() { - return seaLevelPressureQCA; - } + public String[] getSeaLevelPressureQCA() { + return seaLevelPressureQCA; + } - public void setSeaLevelPressureQCA(String[] seaLevelPressureQCA) { - this.seaLevelPressureQCA = seaLevelPressureQCA; - } + public void setSeaLevelPressureQCA(String[] seaLevelPressureQCA) { + this.seaLevelPressureQCA = seaLevelPressureQCA; + } - public String[] getSeaLevelPressureQCR() { - return seaLevelPressureQCR; - } + public String[] getSeaLevelPressureQCR() { + return seaLevelPressureQCR; + } - public void setSeaLevelPressureQCR(String[] seaLevelPressureQCR) { - this.seaLevelPressureQCR = seaLevelPressureQCR; - } + public void setSeaLevelPressureQCR(String[] seaLevelPressureQCR) { + this.seaLevelPressureQCR = seaLevelPressureQCR; + } - public int[] getSeaLevelPressureQCD() { - return seaLevelPressureQCD; - } + public int[] getSeaLevelPressureQCD() { + return seaLevelPressureQCD; + } - public void setSeaLevelPressureQCD(int[] seaLevelPressureQCD) { - this.seaLevelPressureQCD = seaLevelPressureQCD; - } + public void setSeaLevelPressureQCD(int[] seaLevelPressureQCD) { + this.seaLevelPressureQCD = seaLevelPressureQCD; + } - public String getSeaLevelPressureICA() { - return seaLevelPressureICA; - } + public String getSeaLevelPressureICA() { + return seaLevelPressureICA; + } - public void setSeaLevelPressureICA(String seaLevelPressureICA) { - this.seaLevelPressureICA = seaLevelPressureICA; - } + public void setSeaLevelPressureICA(String seaLevelPressureICA) { + this.seaLevelPressureICA = seaLevelPressureICA; + } - public String getSeaLevelPressureICR() { - return seaLevelPressureICR; - } + public String getSeaLevelPressureICR() { + return seaLevelPressureICR; + } - public void setSeaLevelPressureICR(String seaLevelPressureICR) { - this.seaLevelPressureICR = seaLevelPressureICR; - } + public void setSeaLevelPressureICR(String seaLevelPressureICR) { + this.seaLevelPressureICR = seaLevelPressureICR; + } - public String getPressChangeChar() { - return pressChangeChar; - } + public String getPressChangeChar() { + return pressChangeChar; + } - public void setPressChangeChar(String pressChangeChar) { - this.pressChangeChar = pressChangeChar; - } + public void setPressChangeChar(String pressChangeChar) { + this.pressChangeChar = pressChangeChar; + } - public float getPressChange3Hour() { - return pressChange3Hour; - } + public float getPressChange3Hour() { + return pressChange3Hour; + } - public void setPressChange3Hour(float pressChange3Hour) { - this.pressChange3Hour = pressChange3Hour; - } + public void setPressChange3Hour(float pressChange3Hour) { + this.pressChange3Hour = pressChange3Hour; + } - public String getPressChange3HourDD() { - return pressChange3HourDD; - } + public String getPressChange3HourDD() { + return pressChange3HourDD; + } - public void setPressChange3HourDD(String pressChange3HourDD) { - this.pressChange3HourDD = pressChange3HourDD; - } + public void setPressChange3HourDD(String pressChange3HourDD) { + this.pressChange3HourDD = pressChange3HourDD; + } - public String[] getPressChange3HourQCA() { - return pressChange3HourQCA; - } + public String[] getPressChange3HourQCA() { + return pressChange3HourQCA; + } - public void setPressChange3HourQCA(String[] pressChange3HourQCA) { - this.pressChange3HourQCA = pressChange3HourQCA; - } + public void setPressChange3HourQCA(String[] pressChange3HourQCA) { + this.pressChange3HourQCA = pressChange3HourQCA; + } - public String[] getPressChange3HourQCR() { - return pressChange3HourQCR; - } + public String[] getPressChange3HourQCR() { + return pressChange3HourQCR; + } - public void setPressChange3HourQCR(String[] pressChange3HourQCR) { - this.pressChange3HourQCR = pressChange3HourQCR; - } + public void setPressChange3HourQCR(String[] pressChange3HourQCR) { + this.pressChange3HourQCR = pressChange3HourQCR; + } - public int[] getPressChange3HourQCD() { - return pressChange3HourQCD; - } + public int[] getPressChange3HourQCD() { + return pressChange3HourQCD; + } - public void setPressChange3HourQCD(int[] pressChange3HourQCD) { - this.pressChange3HourQCD = pressChange3HourQCD; - } + public void setPressChange3HourQCD(int[] pressChange3HourQCD) { + this.pressChange3HourQCD = pressChange3HourQCD; + } - public String getPressChange3HourICA() { - return pressChange3HourICA; - } + public String getPressChange3HourICA() { + return pressChange3HourICA; + } - public void setPressChange3HourICA(String pressChange3HourICA) { - this.pressChange3HourICA = pressChange3HourICA; - } + public void setPressChange3HourICA(String pressChange3HourICA) { + this.pressChange3HourICA = pressChange3HourICA; + } - public String getPressChange3HourICR() { - return pressChange3HourICR; - } + public String getPressChange3HourICR() { + return pressChange3HourICR; + } - public void setPressChange3HourICR(String pressChange3HourICR) { - this.pressChange3HourICR = pressChange3HourICR; - } + public void setPressChange3HourICR(String pressChange3HourICR) { + this.pressChange3HourICR = pressChange3HourICR; + } - public float getAltimeter() { - return altimeter; - } + public float getAltimeter() { + return altimeter; + } - public void setAltimeter(float altimeter) { - this.altimeter = altimeter; - } + public void setAltimeter(float altimeter) { + this.altimeter = altimeter; + } - public String getAltimeterDD() { - return altimeterDD; - } + public String getAltimeterDD() { + return altimeterDD; + } - public void setAltimeterDD(String altimeterDD) { - this.altimeterDD = altimeterDD; - } + public void setAltimeterDD(String altimeterDD) { + this.altimeterDD = altimeterDD; + } - public String[] getAltimeterQCA() { - return altimeterQCA; - } + public String[] getAltimeterQCA() { + return altimeterQCA; + } - public void setAltimeterQCA(String[] altimeterQCA) { - this.altimeterQCA = altimeterQCA; - } + public void setAltimeterQCA(String[] altimeterQCA) { + this.altimeterQCA = altimeterQCA; + } - public String[] getAltimeterQCR() { - return altimeterQCR; - } + public String[] getAltimeterQCR() { + return altimeterQCR; + } - public void setAltimeterQCR(String[] altimeterQCR) { - this.altimeterQCR = altimeterQCR; - } + public void setAltimeterQCR(String[] altimeterQCR) { + this.altimeterQCR = altimeterQCR; + } - public int[] getAltimeterQCD() { - return altimeterQCD; - } + public int[] getAltimeterQCD() { + return altimeterQCD; + } - public void setAltimeterQCD(int[] altimeterQCD) { - this.altimeterQCD = altimeterQCD; - } + public void setAltimeterQCD(int[] altimeterQCD) { + this.altimeterQCD = altimeterQCD; + } - public float getWindDir() { - return windDir; - } + public float getWindDir() { + return windDir; + } - public void setWindDir(float windDir) { - this.windDir = windDir; - } + public void setWindDir(float windDir) { + this.windDir = windDir; + } - public Date getWindDirChangeTime() { - return windDirChangeTime; - } + public Date getWindDirChangeTime() { + return windDirChangeTime; + } - public void setWindDirChangeTime(Date windDirChangeTime) { - this.windDirChangeTime = windDirChangeTime; - } + public void setWindDirChangeTime(Date windDirChangeTime) { + this.windDirChangeTime = windDirChangeTime; + } - public String getWindDirDD() { - return windDirDD; - } + public String getWindDirDD() { + return windDirDD; + } - public void setWindDirDD(String windDirDD) { - this.windDirDD = windDirDD; - } + public void setWindDirDD(String windDirDD) { + this.windDirDD = windDirDD; + } - public String[] getWindDirQCA() { - return windDirQCA; - } + public String[] getWindDirQCA() { + return windDirQCA; + } - public void setWindDirQCA(String[] windDirQCA) { - this.windDirQCA = windDirQCA; - } + public void setWindDirQCA(String[] windDirQCA) { + this.windDirQCA = windDirQCA; + } - public String[] getWindDirQCR() { - return windDirQCR; - } + public String[] getWindDirQCR() { + return windDirQCR; + } - public void setWindDirQCR(String[] windDirQCR) { - this.windDirQCR = windDirQCR; - } + public void setWindDirQCR(String[] windDirQCR) { + this.windDirQCR = windDirQCR; + } - public int[] getWindDirQCD() { - return windDirQCD; - } + public int[] getWindDirQCD() { + return windDirQCD; + } - public void setWindDirQCD(int[] windDirQCD) { - this.windDirQCD = windDirQCD; - } + public void setWindDirQCD(int[] windDirQCD) { + this.windDirQCD = windDirQCD; + } - public String getWindDirICA() { - return windDirICA; - } + public String getWindDirICA() { + return windDirICA; + } - public void setWindDirICA(String windDirICA) { - this.windDirICA = windDirICA; - } + public void setWindDirICA(String windDirICA) { + this.windDirICA = windDirICA; + } - public String getWindDirICR() { - return windDirICR; - } + public String getWindDirICR() { + return windDirICR; + } - public void setWindDirICR(String windDirICR) { - this.windDirICR = windDirICR; - } + public void setWindDirICR(String windDirICR) { + this.windDirICR = windDirICR; + } - public float getWindSpeed() { - return windSpeed; - } + public float getWindSpeed() { + return windSpeed; + } - public void setWindSpeed(float windSpeed) { - this.windSpeed = windSpeed; - } + public void setWindSpeed(float windSpeed) { + this.windSpeed = windSpeed; + } - public Date getWindSpeedChangeTime() { - return windSpeedChangeTime; - } + public Date getWindSpeedChangeTime() { + return windSpeedChangeTime; + } - public void setWindSpeedChangeTime(Date windSpeedChangeTime) { - this.windSpeedChangeTime = windSpeedChangeTime; - } + public void setWindSpeedChangeTime(Date windSpeedChangeTime) { + this.windSpeedChangeTime = windSpeedChangeTime; + } - public String getWindSpeedDD() { - return windSpeedDD; - } + public String getWindSpeedDD() { + return windSpeedDD; + } - public void setWindSpeedDD(String windSpeedDD) { - this.windSpeedDD = windSpeedDD; - } + public void setWindSpeedDD(String windSpeedDD) { + this.windSpeedDD = windSpeedDD; + } - public String[] getWindSpeedQCA() { - return windSpeedQCA; - } + public String[] getWindSpeedQCA() { + return windSpeedQCA; + } - public void setWindSpeedQCA(String[] windSpeedQCA) { - this.windSpeedQCA = windSpeedQCA; - } + public void setWindSpeedQCA(String[] windSpeedQCA) { + this.windSpeedQCA = windSpeedQCA; + } - public String[] getWindSpeedQCR() { - return windSpeedQCR; - } + public String[] getWindSpeedQCR() { + return windSpeedQCR; + } - public void setWindSpeedQCR(String[] windSpeedQCR) { - this.windSpeedQCR = windSpeedQCR; - } + public void setWindSpeedQCR(String[] windSpeedQCR) { + this.windSpeedQCR = windSpeedQCR; + } - public int[] getWindSpeedQCD() { - return windSpeedQCD; - } + public int[] getWindSpeedQCD() { + return windSpeedQCD; + } - public void setWindSpeedQCD(int[] windSpeedQCD) { - this.windSpeedQCD = windSpeedQCD; - } + public void setWindSpeedQCD(int[] windSpeedQCD) { + this.windSpeedQCD = windSpeedQCD; + } - public String getWindSpeedICA() { - return windSpeedICA; - } + public String getWindSpeedICA() { + return windSpeedICA; + } - public void setWindSpeedICA(String windSpeedICA) { - this.windSpeedICA = windSpeedICA; - } + public void setWindSpeedICA(String windSpeedICA) { + this.windSpeedICA = windSpeedICA; + } - public String getWindSpeedICR() { - return windSpeedICR; - } + public String getWindSpeedICR() { + return windSpeedICR; + } - public void setWindSpeedICR(String windSpeedICR) { - this.windSpeedICR = windSpeedICR; - } + public void setWindSpeedICR(String windSpeedICR) { + this.windSpeedICR = windSpeedICR; + } - public float getWindGust() { - return windGust; - } + public float getWindGust() { + return windGust; + } - public void setWindGust(float windGust) { - this.windGust = windGust; - } + public void setWindGust(float windGust) { + this.windGust = windGust; + } - public String[] getWindGustQCA() { - return windGustQCA; - } + public String[] getWindGustQCA() { + return windGustQCA; + } - public void setWindGustQCA(String[] windGustQCA) { - this.windGustQCA = windGustQCA; - } + public void setWindGustQCA(String[] windGustQCA) { + this.windGustQCA = windGustQCA; + } - public String[] getWindGustQCR() { - return windGustQCR; - } + public String[] getWindGustQCR() { + return windGustQCR; + } - public void setWindGustQCR(String[] windGustQCR) { - this.windGustQCR = windGustQCR; - } + public void setWindGustQCR(String[] windGustQCR) { + this.windGustQCR = windGustQCR; + } - public int[] getWindGustQCD() { - return windGustQCD; - } + public int[] getWindGustQCD() { + return windGustQCD; + } - public void setWindGustQCD(int[] windGustQCD) { - this.windGustQCD = windGustQCD; - } + public void setWindGustQCD(int[] windGustQCD) { + this.windGustQCD = windGustQCD; + } - public float getWindDirMin() { - return windDirMin; - } + public float getWindDirMin() { + return windDirMin; + } - public void setWindDirMin(float windDirMin) { - this.windDirMin = windDirMin; - } + public void setWindDirMin(float windDirMin) { + this.windDirMin = windDirMin; + } - public float getWindDirMax() { - return windDirMax; - } + public float getWindDirMax() { + return windDirMax; + } - public void setWindDirMax(float windDirMax) { - this.windDirMax = windDirMax; - } + public void setWindDirMax(float windDirMax) { + this.windDirMax = windDirMax; + } - public String getWindDirMaxDD() { - return windDirMaxDD; - } + public String getWindDirMaxDD() { + return windDirMaxDD; + } - public void setWindDirMaxDD(String windDirMaxDD) { - this.windDirMaxDD = windDirMaxDD; - } + public void setWindDirMaxDD(String windDirMaxDD) { + this.windDirMaxDD = windDirMaxDD; + } - public String[] getWindDirMaxQCA() { - return windDirMaxQCA; - } + public String[] getWindDirMaxQCA() { + return windDirMaxQCA; + } - public void setWindDirMaxQCA(String[] windDirMaxQCA) { - this.windDirMaxQCA = windDirMaxQCA; - } + public void setWindDirMaxQCA(String[] windDirMaxQCA) { + this.windDirMaxQCA = windDirMaxQCA; + } - public String[] getWindDirMaxQCR() { - return windDirMaxQCR; - } + public String[] getWindDirMaxQCR() { + return windDirMaxQCR; + } - public void setWindDirMaxQCR(String[] windDirMaxQCR) { - this.windDirMaxQCR = windDirMaxQCR; - } + public void setWindDirMaxQCR(String[] windDirMaxQCR) { + this.windDirMaxQCR = windDirMaxQCR; + } - public int[] getWindDirMaxQCD() { - return windDirMaxQCD; - } + public int[] getWindDirMaxQCD() { + return windDirMaxQCD; + } - public void setWindDirMaxQCD(int[] windDirMaxQCD) { - this.windDirMaxQCD = windDirMaxQCD; - } + public void setWindDirMaxQCD(int[] windDirMaxQCD) { + this.windDirMaxQCD = windDirMaxQCD; + } - public String getSkyCover() { - return skyCover; - } + public String getSkyCover() { + return skyCover; + } - public void setSkyCover(String skyCover) { - this.skyCover = skyCover; - } + public void setSkyCover(String skyCover) { + this.skyCover = skyCover; + } - public float[] getSkyLayerBase() { - return skyLayerBase; - } + public float[] getSkyLayerBase() { + return skyLayerBase; + } - public void setSkyLayerBase(float[] skyLayerBase) { - this.skyLayerBase = skyLayerBase; - } + public void setSkyLayerBase(float[] skyLayerBase) { + this.skyLayerBase = skyLayerBase; + } - public float getVisibility() { - return visibility; - } + public float getVisibility() { + return visibility; + } - public void setVisibility(float visibility) { - this.visibility = visibility; - } + public void setVisibility(float visibility) { + this.visibility = visibility; + } - public String getVisibilityDD() { - return visibilityDD; - } + public String getVisibilityDD() { + return visibilityDD; + } - public void setVisibilityDD(String visibilityDD) { - this.visibilityDD = visibilityDD; - } + public void setVisibilityDD(String visibilityDD) { + this.visibilityDD = visibilityDD; + } - public String[] getVisibilityQCA() { - return visibilityQCA; - } + public String[] getVisibilityQCA() { + return visibilityQCA; + } - public void setVisibilityQCA(String[] visibilityQCA) { - this.visibilityQCA = visibilityQCA; - } + public void setVisibilityQCA(String[] visibilityQCA) { + this.visibilityQCA = visibilityQCA; + } - public String[] getVisibilityQCR() { - return visibilityQCR; - } + public String[] getVisibilityQCR() { + return visibilityQCR; + } - public void setVisibilityQCR(String[] visibilityQCR) { - this.visibilityQCR = visibilityQCR; - } + public void setVisibilityQCR(String[] visibilityQCR) { + this.visibilityQCR = visibilityQCR; + } - public int[] getVisibilityQCD() { - return visibilityQCD; - } + public int[] getVisibilityQCD() { + return visibilityQCD; + } - public void setVisibilityQCD(int[] visibilityQCD) { - this.visibilityQCD = visibilityQCD; - } + public void setVisibilityQCD(int[] visibilityQCD) { + this.visibilityQCD = visibilityQCD; + } - public String getVisibilityICA() { - return visibilityICA; - } + public String getVisibilityICA() { + return visibilityICA; + } - public void setVisibilityICA(String visibilityICA) { - this.visibilityICA = visibilityICA; - } + public void setVisibilityICA(String visibilityICA) { + this.visibilityICA = visibilityICA; + } - public String getVisibilityICR() { - return visibilityICR; - } + public String getVisibilityICR() { + return visibilityICR; + } - public void setVisibilityICR(String visibilityICR) { - this.visibilityICR = visibilityICR; - } + public void setVisibilityICR(String visibilityICR) { + this.visibilityICR = visibilityICR; + } - public float getTotalCloudCover() { - return totalCloudCover; - } + public float getTotalCloudCover() { + return totalCloudCover; + } - public void setTotalCloudCover(float totalCloudCover) { - this.totalCloudCover = totalCloudCover; - } + public void setTotalCloudCover(float totalCloudCover) { + this.totalCloudCover = totalCloudCover; + } - public String getCloudBaseHeight() { - return cloudBaseHeight; - } + public String getCloudBaseHeight() { + return cloudBaseHeight; + } - public void setCloudBaseHeight(String cloudBaseHeight) { - this.cloudBaseHeight = cloudBaseHeight; - } + public void setCloudBaseHeight(String cloudBaseHeight) { + this.cloudBaseHeight = cloudBaseHeight; + } - public String getPresWeather() { - return presWeather; - } + public String getPresWeather() { + return presWeather; + } - public void setPresWeather(String presWeather) { - this.presWeather = presWeather; - } + public void setPresWeather(String presWeather) { + this.presWeather = presWeather; + } - public String getLowLevelCloudType() { - return lowLevelCloudType; - } + public String getLowLevelCloudType() { + return lowLevelCloudType; + } - public void setLowLevelCloudType(String lowLevelCloudType) { - this.lowLevelCloudType = lowLevelCloudType; - } + public void setLowLevelCloudType(String lowLevelCloudType) { + this.lowLevelCloudType = lowLevelCloudType; + } - public String getMidLevelCloudType() { - return midLevelCloudType; - } + public String getMidLevelCloudType() { + return midLevelCloudType; + } - public void setMidLevelCloudType(String midLevelCloudType) { - this.midLevelCloudType = midLevelCloudType; - } + public void setMidLevelCloudType(String midLevelCloudType) { + this.midLevelCloudType = midLevelCloudType; + } - public String getHighLevelCloudType() { - return highLevelCloudType; - } + public String getHighLevelCloudType() { + return highLevelCloudType; + } - public void setHighLevelCloudType(String highLevelCloudType) { - this.highLevelCloudType = highLevelCloudType; - } + public void setHighLevelCloudType(String highLevelCloudType) { + this.highLevelCloudType = highLevelCloudType; + } - public String getMaxTempRecordPeriod() { - return maxTempRecordPeriod; - } + public String getMaxTempRecordPeriod() { + return maxTempRecordPeriod; + } - public void setMaxTempRecordPeriod(String maxTempRecordPeriod) { - this.maxTempRecordPeriod = maxTempRecordPeriod; - } + public void setMaxTempRecordPeriod(String maxTempRecordPeriod) { + this.maxTempRecordPeriod = maxTempRecordPeriod; + } - public String getMinTempRecordPeriod() { - return minTempRecordPeriod; - } + public String getMinTempRecordPeriod() { + return minTempRecordPeriod; + } - public void setMinTempRecordPeriod(String minTempRecordPeriod) { - this.minTempRecordPeriod = minTempRecordPeriod; - } + public void setMinTempRecordPeriod(String minTempRecordPeriod) { + this.minTempRecordPeriod = minTempRecordPeriod; + } - public float getMinimumTemperature() { - return minimumTemperature; - } + public float getMinimumTemperature() { + return minimumTemperature; + } - public void setMinimumTemperature(float minimumTemperature) { - this.minimumTemperature = minimumTemperature; - } + public void setMinimumTemperature(float minimumTemperature) { + this.minimumTemperature = minimumTemperature; + } - public float getRawPrecip() { - return rawPrecip; - } + public float getRawPrecip() { + return rawPrecip; + } - public void setRawPrecip(float rawPrecip) { - this.rawPrecip = rawPrecip; - } + public void setRawPrecip(float rawPrecip) { + this.rawPrecip = rawPrecip; + } - public float getPrecipAccum() { - return precipAccum; - } + public float getPrecipAccum() { + return precipAccum; + } - public void setPrecipAccum(float precipAccum) { - this.precipAccum = precipAccum; - } + public void setPrecipAccum(float precipAccum) { + this.precipAccum = precipAccum; + } - public String getPrecipAccumDD() { - return precipAccumDD; - } + public String getPrecipAccumDD() { + return precipAccumDD; + } - public void setPrecipAccumDD(String precipAccumDD) { - this.precipAccumDD = precipAccumDD; - } + public void setPrecipAccumDD(String precipAccumDD) { + this.precipAccumDD = precipAccumDD; + } - public String[] getPrecipAccumQCA() { - return precipAccumQCA; - } + public String[] getPrecipAccumQCA() { + return precipAccumQCA; + } - public void setPrecipAccumQCA(String[] precipAccumQCA) { - this.precipAccumQCA = precipAccumQCA; - } + public void setPrecipAccumQCA(String[] precipAccumQCA) { + this.precipAccumQCA = precipAccumQCA; + } - public String[] getPrecipAccumQCR() { - return precipAccumQCR; - } + public String[] getPrecipAccumQCR() { + return precipAccumQCR; + } - public void setPrecipAccumQCR(String[] precipAccumQCR) { - this.precipAccumQCR = precipAccumQCR; - } + public void setPrecipAccumQCR(String[] precipAccumQCR) { + this.precipAccumQCR = precipAccumQCR; + } - public int[] getPrecipAccumQCD() { - return precipAccumQCD; - } + public int[] getPrecipAccumQCD() { + return precipAccumQCD; + } - public void setPrecipAccumQCD(int[] precipAccumQCD) { - this.precipAccumQCD = precipAccumQCD; - } + public void setPrecipAccumQCD(int[] precipAccumQCD) { + this.precipAccumQCD = precipAccumQCD; + } - public String getPrecipAccumICA() { - return precipAccumICA; - } + public String getPrecipAccumICA() { + return precipAccumICA; + } - public void setPrecipAccumICA(String precipAccumICA) { - this.precipAccumICA = precipAccumICA; - } + public void setPrecipAccumICA(String precipAccumICA) { + this.precipAccumICA = precipAccumICA; + } - public String getPrecipAccumICR() { - return precipAccumICR; - } + public String getPrecipAccumICR() { + return precipAccumICR; + } - public void setPrecipAccumICR(String precipAccumICR) { - this.precipAccumICR = precipAccumICR; - } + public void setPrecipAccumICR(String precipAccumICR) { + this.precipAccumICR = precipAccumICR; + } - public float getPrecipRate() { - return precipRate; - } + public float getPrecipRate() { + return precipRate; + } - public void setPrecipRate(float precipRate) { - this.precipRate = precipRate; - } + public void setPrecipRate(float precipRate) { + this.precipRate = precipRate; + } - public String getPrecipRateDD() { - return precipRateDD; - } + public String getPrecipRateDD() { + return precipRateDD; + } - public void setPrecipRateDD(String precipRateDD) { - this.precipRateDD = precipRateDD; - } + public void setPrecipRateDD(String precipRateDD) { + this.precipRateDD = precipRateDD; + } - public String[] getPrecipRateQCA() { - return precipRateQCA; - } + public String[] getPrecipRateQCA() { + return precipRateQCA; + } - public void setPrecipRateQCA(String[] precipRateQCA) { - this.precipRateQCA = precipRateQCA; - } + public void setPrecipRateQCA(String[] precipRateQCA) { + this.precipRateQCA = precipRateQCA; + } - public String[] getPrecipRateQCR() { - return precipRateQCR; - } + public String[] getPrecipRateQCR() { + return precipRateQCR; + } - public void setPrecipRateQCR(String[] precipRateQCR) { - this.precipRateQCR = precipRateQCR; - } + public void setPrecipRateQCR(String[] precipRateQCR) { + this.precipRateQCR = precipRateQCR; + } - public int[] getPrecipRateQCD() { - return precipRateQCD; - } + public int[] getPrecipRateQCD() { + return precipRateQCD; + } - public void setPrecipRateQCD(int[] precipRateQCD) { - this.precipRateQCD = precipRateQCD; - } + public void setPrecipRateQCD(int[] precipRateQCD) { + this.precipRateQCD = precipRateQCD; + } - public String getPrecipType() { - return precipType; - } + public String getPrecipType() { + return precipType; + } - public void setPrecipType(String precipType) { - this.precipType = precipType; - } + public void setPrecipType(String precipType) { + this.precipType = precipType; + } - public String getPrecipIntensity() { - return precipIntensity; - } + public String getPrecipIntensity() { + return precipIntensity; + } - public void setPrecipIntensity(String precipIntensity) { - this.precipIntensity = precipIntensity; - } + public void setPrecipIntensity(String precipIntensity) { + this.precipIntensity = precipIntensity; + } - public int getTimeSinceLastPcp() { - return timeSinceLastPcp; - } + public int getTimeSinceLastPcp() { + return timeSinceLastPcp; + } - public void setTimeSinceLastPcp(int timeSinceLastPcp) { - this.timeSinceLastPcp = timeSinceLastPcp; - } + public void setTimeSinceLastPcp(int timeSinceLastPcp) { + this.timeSinceLastPcp = timeSinceLastPcp; + } - public float getSolarRadiation() { - return solarRadiation; - } + public float getSolarRadiation() { + return solarRadiation; + } - public void setSolarRadiation(float solarRadiation) { - this.solarRadiation = solarRadiation; - } + public void setSolarRadiation(float solarRadiation) { + this.solarRadiation = solarRadiation; + } - public Date getSolarRadiationChangeTime() { - return solarRadiationChangeTime; - } + public Date getSolarRadiationChangeTime() { + return solarRadiationChangeTime; + } - public void setSolarRadiationChangeTime(Date solarRadiationChangeTime) { - this.solarRadiationChangeTime = solarRadiationChangeTime; - } + public void setSolarRadiationChangeTime(Date solarRadiationChangeTime) { + this.solarRadiationChangeTime = solarRadiationChangeTime; + } - public float getSeaSurfaceTemp() { - return seaSurfaceTemp; - } + public float getSeaSurfaceTemp() { + return seaSurfaceTemp; + } - public void setSeaSurfaceTemp(float seaSurfaceTemp) { - this.seaSurfaceTemp = seaSurfaceTemp; - } + public void setSeaSurfaceTemp(float seaSurfaceTemp) { + this.seaSurfaceTemp = seaSurfaceTemp; + } - public String getSeaSurfaceTempDD() { - return seaSurfaceTempDD; - } + public String getSeaSurfaceTempDD() { + return seaSurfaceTempDD; + } - public void setSeaSurfaceTempDD(String seaSurfaceTempDD) { - this.seaSurfaceTempDD = seaSurfaceTempDD; - } + public void setSeaSurfaceTempDD(String seaSurfaceTempDD) { + this.seaSurfaceTempDD = seaSurfaceTempDD; + } - public String[] getSeaSurfaceTempQCA() { - return seaSurfaceTempQCA; - } + public String[] getSeaSurfaceTempQCA() { + return seaSurfaceTempQCA; + } - public void setSeaSurfaceTempQCA(String[] seaSurfaceTempQCA) { - this.seaSurfaceTempQCA = seaSurfaceTempQCA; - } + public void setSeaSurfaceTempQCA(String[] seaSurfaceTempQCA) { + this.seaSurfaceTempQCA = seaSurfaceTempQCA; + } - public String[] getSeaSurfaceTempQCR() { - return seaSurfaceTempQCR; - } + public String[] getSeaSurfaceTempQCR() { + return seaSurfaceTempQCR; + } - public void setSeaSurfaceTempQCR(String[] seaSurfaceTempQCR) { - this.seaSurfaceTempQCR = seaSurfaceTempQCR; - } + public void setSeaSurfaceTempQCR(String[] seaSurfaceTempQCR) { + this.seaSurfaceTempQCR = seaSurfaceTempQCR; + } - public int[] getSeaSurfaceTempQCD() { - return seaSurfaceTempQCD; - } + public int[] getSeaSurfaceTempQCD() { + return seaSurfaceTempQCD; + } - public void setSeaSurfaceTempQCD(int[] seaSurfaceTempQCD) { - this.seaSurfaceTempQCD = seaSurfaceTempQCD; - } + public void setSeaSurfaceTempQCD(int[] seaSurfaceTempQCD) { + this.seaSurfaceTempQCD = seaSurfaceTempQCD; + } - public String getSeaSurfaceTempICA() { - return seaSurfaceTempICA; - } + public String getSeaSurfaceTempICA() { + return seaSurfaceTempICA; + } - public void setSeaSurfaceTempICA(String seaSurfaceTempICA) { - this.seaSurfaceTempICA = seaSurfaceTempICA; - } + public void setSeaSurfaceTempICA(String seaSurfaceTempICA) { + this.seaSurfaceTempICA = seaSurfaceTempICA; + } - public String getSeaSurfaceTempICR() { - return seaSurfaceTempICR; - } - - public void setSeaSurfaceTempICR(String seaSurfaceTempICR) { - this.seaSurfaceTempICR = seaSurfaceTempICR; - } - - public float getWavePeriod() { - return wavePeriod; - } - - public void setWavePeriod(float wavePeriod) { - this.wavePeriod = wavePeriod; - } - - public float getWaveHeight() { - return waveHeight; - } - - public void setWaveHeight(float waveHeight) { - this.waveHeight = waveHeight; - } - - public String getRawMessage() { - return rawMessage; - } - - public void setRawMessage(String rawMessage) { - this.rawMessage = rawMessage; - } - - public float getTotalColumnPWV() { - return totalColumnPWV; - } - - public void setTotalColumnPWV(float totalColumnPWV) { - this.totalColumnPWV = totalColumnPWV; - } - - public float getTotalSignalDelay() { - return totalSignalDelay; - } - - public void setTotalSignalDelay(float totalSignalDelay) { - this.totalSignalDelay = totalSignalDelay; - } - - public float getDrySignalDelay() { - return drySignalDelay; - } - - public void setDrySignalDelay(float drySignalDelay) { - this.drySignalDelay = drySignalDelay; - } - - public float getWetSignalDelay() { - return wetSignalDelay; - } - - public void setWetSignalDelay(float wetSignalDelay) { - this.wetSignalDelay = wetSignalDelay; - } - - public float getMeanWeightedTemperature() { - return meanWeightedTemperature; - } - - public void setMeanWeightedTemperature(float meanWeightedTemperature) { - this.meanWeightedTemperature = meanWeightedTemperature; - } - - public float getFormalError() { - return formalError; - } - - public void setFormalError(float formalError) { - this.formalError = formalError; - } - - public float getCapPi() { - return capPi; - } - - public void setCapPi(float capPi) { - this.capPi = capPi; - } - - public static long getSerialVersionUID() { - return serialVersionUID; - } - - /** - * @return the ncSet - */ - public String getNcSet() { - return ncSet; - } - - /** - * @param ncSet - * the ncSet to set - */ - public void setNcSet(String ncSet) { - this.ncSet = ncSet; - } - - /** - * @return the ncIndex - */ - public int getNcIndex() { - return pointDataView != null ? pointDataView.curIdx : -1; - } - - /** - * @param ncIndex - * the ncIndex to set - */ - public void setNcIndex(int ncIndex) { - if (this.pointDataView == null) - pointDataView = new FakePointDataView(); - this.pointDataView.curIdx = ncIndex; - } - - @Override - public ISpatialObject getSpatialObject() { - return location; - } - - /** - * @return the qcType - */ - public String getQcType() { - return qcType; - } - - /** - * @param qcType - * the qcType to set - */ - public void setQcType(String qcType) { - this.qcType = qcType; - } - - public FakePointDataView getPointDataView() { - return pointDataView; - } - - public void setPointDataView(FakePointDataView pointDataView) { - this.pointDataView = pointDataView; - } + public String getSeaSurfaceTempICR() { + return seaSurfaceTempICR; + } + + public void setSeaSurfaceTempICR(String seaSurfaceTempICR) { + this.seaSurfaceTempICR = seaSurfaceTempICR; + } + + public float getWavePeriod() { + return wavePeriod; + } + + public void setWavePeriod(float wavePeriod) { + this.wavePeriod = wavePeriod; + } + + public float getWaveHeight() { + return waveHeight; + } + + public void setWaveHeight(float waveHeight) { + this.waveHeight = waveHeight; + } + + public String getRawMessage() { + return rawMessage; + } + + public void setRawMessage(String rawMessage) { + this.rawMessage = rawMessage; + } + + public float getTotalColumnPWV() { + return totalColumnPWV; + } + + public void setTotalColumnPWV(float totalColumnPWV) { + this.totalColumnPWV = totalColumnPWV; + } + + public float getTotalSignalDelay() { + return totalSignalDelay; + } + + public void setTotalSignalDelay(float totalSignalDelay) { + this.totalSignalDelay = totalSignalDelay; + } + + public float getDrySignalDelay() { + return drySignalDelay; + } + + public void setDrySignalDelay(float drySignalDelay) { + this.drySignalDelay = drySignalDelay; + } + + public float getWetSignalDelay() { + return wetSignalDelay; + } + + public void setWetSignalDelay(float wetSignalDelay) { + this.wetSignalDelay = wetSignalDelay; + } + + public float getMeanWeightedTemperature() { + return meanWeightedTemperature; + } + + public void setMeanWeightedTemperature(float meanWeightedTemperature) { + this.meanWeightedTemperature = meanWeightedTemperature; + } + + public float getFormalError() { + return formalError; + } + + public void setFormalError(float formalError) { + this.formalError = formalError; + } + + public float getCapPi() { + return capPi; + } + + public void setCapPi(float capPi) { + this.capPi = capPi; + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + /** + * @return the ncSet + */ + public String getNcSet() { + return ncSet; + } + + /** + * @param ncSet + * the ncSet to set + */ + public void setNcSet(String ncSet) { + this.ncSet = ncSet; + } + + /** + * @return the ncIndex + */ + public int getNcIndex() { + return pointDataView != null ? pointDataView.curIdx : -1; + } + + /** + * @param ncIndex + * the ncIndex to set + */ + public void setNcIndex(int ncIndex) { + if (this.pointDataView == null) { + pointDataView = new FakePointDataView(); + } + this.pointDataView.curIdx = ncIndex; + } + + @Override + public ISpatialObject getSpatialObject() { + return location; + } + + /** + * @return the qcType + */ + public String getQcType() { + return qcType; + } + + /** + * @param qcType + * the qcType to set + */ + public void setQcType(String qcType) { + this.qcType = qcType; + } + + public FakePointDataView getPointDataView() { + return pointDataView; + } + + public void setPointDataView(FakePointDataView pointDataView) { + this.pointDataView = pointDataView; + } + + @Override + public String getPluginName() { + return "qc"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.qpf/src/com/raytheon/uf/common/dataplugin/qpf/QPFRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.qpf/src/com/raytheon/uf/common/dataplugin/qpf/QPFRecord.java index 52b7ec81bb..990b1bda20 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.qpf/src/com/raytheon/uf/common/dataplugin/qpf/QPFRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.qpf/src/com/raytheon/uf/common/dataplugin/qpf/QPFRecord.java @@ -64,14 +64,16 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 2/24/09 2027 D. Hladky Initial release - * 4/27/12 #562 dgilling Rename getters/setters to - * match Java conventions. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 04/08/13 #1293 bkowal Removed references to hdffileid. + * Feb 24, 2009 2027 D. Hladky Initial release + * Apr 27, 2012 562 dgilling Rename getters/setters to match Java + * conventions. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -85,17 +87,13 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "qpf", - indexes = { - @Index(name = "qpf_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "qpf", indexes = { @Index(name = "qpf_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public class QPFRecord extends PersistablePluginDataObject - implements ISpatialEnabled, IMonitorProcessing { +public class QPFRecord extends PersistablePluginDataObject implements + ISpatialEnabled, IMonitorProcessing { private static final long serialVersionUID = 767763365671L; @@ -515,9 +513,9 @@ public class QPFRecord extends PersistablePluginDataObject try { IDataRecord[] dataRec = dataStore.retrieve(getDataURI()); - for (int i = 0; i < dataRec.length; i++) { - if (dataRec[i] instanceof FloatDataRecord) { - setDataArray(((FloatDataRecord) dataRec[i]).getFloatData()); + for (IDataRecord element : dataRec) { + if (element instanceof FloatDataRecord) { + setDataArray(((FloatDataRecord) element).getFloatData()); } } } catch (Exception se) { @@ -592,4 +590,9 @@ public class QPFRecord extends PersistablePluginDataObject public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "qpf"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.radar/src/com/raytheon/uf/common/dataplugin/radar/RadarRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.radar/src/com/raytheon/uf/common/dataplugin/radar/RadarRecord.java index 7e86311d89..93aafa1d65 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.radar/src/com/raytheon/uf/common/dataplugin/radar/RadarRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.radar/src/com/raytheon/uf/common/dataplugin/radar/RadarRecord.java @@ -118,19 +118,22 @@ import com.vividsolutions.jts.geom.Coordinate; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 02/14/2007 139 Phillippe Initial creation - * 09/14/2007 379 jkorman Added populateDataStore() and - * getPersistenceTime() from new IPersistable - * 10/09/2007 465 randerso Updated to better represent level 3 data - * 20071129 472 jkorman Added IDecoderGettable interface. - * 03/04/2013 DCS51 zwang Handle MIGFA product + * Feb 14, 2007 139 Phillippe Initial creation + * Sep 14, 2007 379 jkorman Added populateDataStore() and + * getPersistenceTime() from new + * IPersistable + * Oct 09, 2007 465 randerso Updated to better represent level 3 data + * Nov 29, 2007 472 jkorman Added IDecoderGettable interface. + * Mar 04, 2013 DCS51 zwang Handle MIGFA product * Mar 18, 2013 1804 bsteffen Remove AlphanumericValues from radar * HDF5. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime * Apr 08, 2013 1293 bkowal Removed references to hdffileid. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -144,12 +147,8 @@ import com.vividsolutions.jts.geom.Coordinate; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "radar", - indexes = { - @Index(name = "radar_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "radar", indexes = { @Index(name = "radar_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -384,7 +383,6 @@ public class RadarRecord extends PersistablePluginDataObject implements public RadarRecord(RadarRecord that) { this.id = that.id; this.dataURI = that.dataURI; - this.pluginName = that.pluginName; this.dataTime = that.dataTime; this.insertTime = that.insertTime; this.messageData = that.messageData; @@ -614,18 +612,18 @@ public class RadarRecord extends PersistablePluginDataObject implements public void setRawDataValue(int radial, int bin, byte value) { byte[] rawData = getRawData(); - if (rawData != null && numRadials != null && numBins != null) { + if ((rawData != null) && (numRadials != null) && (numBins != null)) { if ((radial < numRadials) && (bin < numBins)) { - rawData[radial * numBins + bin] = value; + rawData[(radial * numBins) + bin] = value; } } } public byte getRawDataValue(int radial, int bin) { byte[] rawData = getRawData(); - if (rawData != null && numRadials != null && numBins != null) { + if ((rawData != null) && (numRadials != null) && (numBins != null)) { if ((radial < numRadials) && (bin < numBins)) { - return rawData[radial * numBins + bin]; + return rawData[(radial * numBins) + bin]; } } return 0; @@ -638,9 +636,9 @@ public class RadarRecord extends PersistablePluginDataObject implements short[] rawShortData = getRawShortData(); byte[] rawData = getRawData(); if (rawShortData != null) { - return rawShortData[radial * numBins + bin]; + return rawShortData[(radial * numBins) + bin]; } else if (rawData != null) { - return (short) (rawData[radial * numBins + bin] & 0xFF); + return (short) (rawData[(radial * numBins) + bin] & 0xFF); } } return 0; @@ -652,9 +650,9 @@ public class RadarRecord extends PersistablePluginDataObject implements short[] rawShortData = getRawShortData(); byte[] rawData = getRawData(); if (rawShortData != null) { - return rawShortData[radial * numBins + bin] & 0xFFFF; + return rawShortData[(radial * numBins) + bin] & 0xFFFF; } else if (rawData != null) { - return rawData[radial * numBins + bin] & 0xFF; + return rawData[(radial * numBins) + bin] & 0xFF; } } return 0; @@ -892,7 +890,7 @@ public class RadarRecord extends PersistablePluginDataObject implements pix = new double[] { 129, 149 }; } - double[] data = { offset, offset + (nLevels - 1) * scale }; + double[] data = { offset, offset + ((nLevels - 1) * scale) }; rval = new PiecewisePixel(getUnitObject(), pix, data); } else { @@ -1127,7 +1125,7 @@ public class RadarRecord extends PersistablePluginDataObject implements } // distance - double mag = Math.sqrt(i * i + j * j); + double mag = Math.sqrt((i * i) + (j * j)); // 1 i or j is 1/4 km, so convert to meters mag *= 250; @@ -1201,19 +1199,19 @@ public class RadarRecord extends PersistablePluginDataObject implements private void addPacketData(double i, double j, String stormID, int type, RadarProductType productType, T currData, boolean needToConvert) { - - // Convert x/y to lon/lat - if (needToConvert) { - Coordinate coor; - - // for MIGFA, i/j unit is 1km, for other radar products, unit is 1/4km - if (type == 140) { - coor = convertStormLatLon(i * 4.0, j * 4.0); - } - else { + + // Convert x/y to lon/lat + if (needToConvert) { + Coordinate coor; + + // for MIGFA, i/j unit is 1km, for other radar products, unit is + // 1/4km + if (type == 140) { + coor = convertStormLatLon(i * 4.0, j * 4.0); + } else { coor = convertStormLatLon(i, j); - } - + } + i = coor.x; j = coor.y; } @@ -1496,11 +1494,11 @@ public class RadarRecord extends PersistablePluginDataObject implements convertLatLon = true; Map map = new HashMap(); - + for (GenericDataParameter param : packet.getParams() .values()) { - - GFMAttributeIDs id = null; + + GFMAttributeIDs id = null; id = GFMAttributeIDs.getAttribute(param.getId()); if (id != null) { @@ -1517,7 +1515,7 @@ public class RadarRecord extends PersistablePluginDataObject implements for (GenericDataComponent currComponent : packet .getFeatures().values()) { currFeature = (AreaComponent) currComponent; - //first point of GFM + // first point of GFM i = currFeature.getPoints().get(0).getCoordinate1(); j = currFeature.getPoints().get(0).getCoordinate2(); @@ -1525,7 +1523,7 @@ public class RadarRecord extends PersistablePluginDataObject implements currFeature, convertLatLon); } continue PACKET; - }else if (currPacket instanceof GenericDataPacket) { + } else if (currPacket instanceof GenericDataPacket) { // Generic Packet will contain most of the data for the // product, so, in general, nothing probably needs to be // done here @@ -1753,4 +1751,9 @@ public class RadarRecord extends PersistablePluginDataObject implements public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "radar"; + } } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.satellite/src/com/raytheon/uf/common/dataplugin/satellite/SatelliteRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.satellite/src/com/raytheon/uf/common/dataplugin/satellite/SatelliteRecord.java index 60e7602073..43d16cf8ff 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.satellite/src/com/raytheon/uf/common/dataplugin/satellite/SatelliteRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.satellite/src/com/raytheon/uf/common/dataplugin/satellite/SatelliteRecord.java @@ -57,21 +57,22 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 02/14/07 139 bphillip Initial Creation - * 20070914 379 jkorman Added populateDataStore() and - * getPersistenceTime() from new IPersistable - * 20071129 472 jkorman Added IDecoderGettable interface. - * 20081106 1515 jkorman Changed units length from 16 to 26 - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * - AWIPS2 Baseline Repository -------- - * 07/30/2012 798 jkorman Support for common satellite data. - * 03/25/2013 1823 dgilling Replace underscores with spaces in URI + * Feb 14, 2007 139 bphillip Initial Creation + * Sep 14, 2007 379 jkorman Added populateDataStore() and + * getPersistenceTime() from new + * IPersistable + * Nov 29, 2007 472 jkorman Added IDecoderGettable interface. + * Nov 06, 2008 1515 jkorman Changed units length from 16 to 26 + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Jul 30, 2012 798 jkorman Support for common satellite data. + * Mar 25, 2013 1823 dgilling Replace underscores with spaces in URI * constructor. - * 04/08/2013 1293 bkowal Removed references to hdffileid. + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. - * + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author bphillip @@ -412,4 +413,9 @@ public class SatelliteRecord extends PersistablePluginDataObject public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "satellite"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.scan/src/com/raytheon/uf/common/dataplugin/scan/ScanRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.scan/src/com/raytheon/uf/common/dataplugin/scan/ScanRecord.java index 12766b1ae7..6c8088a775 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.scan/src/com/raytheon/uf/common/dataplugin/scan/ScanRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.scan/src/com/raytheon/uf/common/dataplugin/scan/ScanRecord.java @@ -68,14 +68,16 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 03/17/10 2521 D. Hladky Initial release - * 02/01/13 1649 D. Hladky better logging, + * Mar 17, 2010 2521 D. Hladky Initial release + * Feb 01, 2013 1649 D. Hladky better logging, * Feb 28, 2013 1731 bsteffen Optimize construction of scan resource. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 8, 2013 1293 bkowal Removed references to hdffileid. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -407,4 +409,9 @@ public class ScanRecord extends PersistablePluginDataObject { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "scan"; + } } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.sfcobs/src/com/raytheon/uf/common/dataplugin/sfcobs/ObsCommon.java b/edexOsgi/com.raytheon.uf.common.dataplugin.sfcobs/src/com/raytheon/uf/common/dataplugin/sfcobs/ObsCommon.java index b2fadfe38c..74cb688e0d 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.sfcobs/src/com/raytheon/uf/common/dataplugin/sfcobs/ObsCommon.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.sfcobs/src/com/raytheon/uf/common/dataplugin/sfcobs/ObsCommon.java @@ -71,11 +71,13 @@ import com.vividsolutions.jts.geom.Geometry; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Oct 1, 2009 jkorman Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Oct 01, 2009 jkorman Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -89,1589 +91,1591 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "sfcobs", - indexes = { - @Index(name = "sfcobs_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "sfcobs", indexes = { @Index(name = "sfcobs_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class ObsCommon extends PersistablePluginDataObject implements - ISpatialEnabled, IDecoderGettable, IPointData { - - private static final long serialVersionUID = 1L; - - private static final int MISSING = -9999; - - public static final Unit TEMPERATURE_UNIT = SI.KELVIN; - - public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; - - public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; - - public static final Unit PRESSURE_UNIT = SI.PASCAL; - - public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; - - public static final Unit WAVE_UNIT = SI.METER; - - public static final Unit VISIBILITY_UNIT = NonSI.MILE; - - public static final Unit CLOUD_COVER = NonSI.OCTET; - - private static final HashMap PARM_MAP = new HashMap(); - static { - PARM_MAP.put("T", SFC_TEMP); - PARM_MAP.put("DpT", SFC_DWPT); - PARM_MAP.put("WS", SFC_WNDSPD); - PARM_MAP.put("WD", SFC_WNDDIR); - PARM_MAP.put("WGS", SFC_WNDGST); - PARM_MAP.put("Px", PRES_STATION); - PARM_MAP.put("PMSL", PRES_SLP); - PARM_MAP.put("ASET", PRES_ALTSG); - PARM_MAP.put("NLAT", STA_LAT); - PARM_MAP.put("NLON", STA_LON); - PARM_MAP.put("WT", "WT"); - PARM_MAP.put("TCC", "TCC"); - PARM_MAP.put("WP", "WP"); - PARM_MAP.put("WH", "WH"); - PARM_MAP.put("SWP", "SWP"); - PARM_MAP.put("SWH", "SWH"); - PARM_MAP.put("SWS", "SWS"); - PARM_MAP.put("SWD", "SWD"); - PARM_MAP.put("SWGS", "SWGS"); - PARM_MAP.put("PCHNG", "PCHNG"); - PARM_MAP.put("PKWND", "PKWND"); - PARM_MAP.put("VIS", "VIS"); - PARM_MAP.put("COVpct", "COVpct"); - } - - // - @DataURI(position = 1) - @Column - @XmlAttribute - @DynamicSerializeElement - @Index(name = "reporttype_index") - private Integer reportType; - - // Correction indicator from wmo header - @DataURI(position = 2) - @Column - @XmlElement - @DynamicSerializeElement - private String corIndicator; - - @Embedded - @DataURI(position = 3, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; - - // Time of the observation. - @Column - @XmlAttribute - @DynamicSerializeElement - private Calendar timeObs; - - // Time of the observation to the nearest hour. - @Column - @XmlAttribute - @DynamicSerializeElement - private Calendar refHour; - - @Transient - @XmlElement - @DynamicSerializeElement - private String obsText = ""; - - // Text of the WMO header - @Transient - @XmlElement - @DynamicSerializeElement - private String wmoHeader = ""; - - // Observation air temperature in degrees Kelvin. - @Transient - @XmlElement - @DynamicSerializeElement - private Double temp = -9999.0; - - // Observation dewpoint temperature in degrees Kelvin. - @Transient - @XmlElement - @DynamicSerializeElement - private Double dwpt = -9999.0; - - // Relative Humidity in percent. Decimal(5,2) - @Transient - @XmlElement - @DynamicSerializeElement - private Double humidity = -9999.0; - - // Observation sea surface temperature in degrees Kelvin. - @Transient - @XmlElement - @DynamicSerializeElement - private Double seaTemp = -9999.0; - - // Observation wetbulb temperature in degrees Kelvin. - @Transient - @XmlElement - @DynamicSerializeElement - private Double wetBulb = -9999.0; - - // Observation wind direction in angular degrees. Integer - @Transient - @XmlElement - @DynamicSerializeElement - private Integer windDirection = -9999; - - // Observation wind speed in meters per second. - @Transient - @XmlElement - @DynamicSerializeElement - private Double windSpeed = -9999.0; - - // Observation wind speed gust in meters per second. - @Transient - @XmlElement - @DynamicSerializeElement - private Double windGust = -9999.0; - - // Direction of the peak wind observation in angular degrees - @Transient - @XmlElement - @DynamicSerializeElement - private Integer peakWindDir = -9999; - - // Speed of the peak wind observation in meters per second. - @Transient - @XmlElement - @DynamicSerializeElement - private Double peakWindSpeed = -9999.0; - - // Time of the peak wind observation. - @Transient - @XmlElement - @DynamicSerializeElement - private Long peakWindTime = -1L; - - // The equivilent 10 meter wind speed in meters per second. - @Transient - @XmlElement - @DynamicSerializeElement - private Double wind10mSpeed = -9999.0; - - // The equivilent 20 meter wind speed in meters per second. - @Transient - @XmlElement - @DynamicSerializeElement - private Double wind20mSpeed = -9999.0; - - // Altimeter setting in Pascals. - @Transient - @XmlElement - @DynamicSerializeElement - private Integer pressureAltimeter = -9999; - - // Sea level pressure in Pascals. - @Transient - @XmlElement - @DynamicSerializeElement - private Integer pressureSealevel = -9999; - - // Station pressure in Pascals. - @Transient - @XmlElement - @DynamicSerializeElement - private Integer pressureStation = -9999; - - // Three hour pressure change in pascals. - @Transient - @XmlElement - @DynamicSerializeElement - private Double pressChange3Hr = -9999.0; - - // Three hour pressure change characteristic. - @Transient - @XmlElement - @DynamicSerializeElement - private Integer pressChangeChar = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer wx_past_1 = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer wx_past_2 = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer wx_present = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private String presWeather = null; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer wx_report_type = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer horzVisibility = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer vertVisibility = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer totalCloudCover = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer cloudBaseHeight = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer lowCloudType = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer midCloudType = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer highCloudType = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer platformDirection = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Double platformMovement = -9999.0; - - @Transient - @XmlElement - @DynamicSerializeElement - private String shipIceData = ""; - - @Transient - @XmlElement - @DynamicSerializeElement - private Double windWaveHeight = -9999.0; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer windWavePeriod = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Double waveSteepness = -9999.0; - - @Transient - @XmlElement - @DynamicSerializeElement - private Double waveHeight = -9999.0; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer wavePeriod = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Double highResWaveHeight = -9999.0; - - @Transient - @XmlElement - @DynamicSerializeElement - private Double primarySwellWaveDir = -9999.0; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer primarySwellWavePeriod = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Double primarySwellWaveHeight = -9999.0; - - @Transient - @XmlElement - @DynamicSerializeElement - private Double secondarySwellWaveDir = -9999.0; - - @Transient - @XmlElement - @DynamicSerializeElement - private Integer secondarySwellWavePeriod = -9999; - - @Transient - @XmlElement - @DynamicSerializeElement - private Double secondarySwellWaveHeight = -9999.0; - - @Transient - @XmlElement - @DynamicSerializeElement - private List ancClouds; - - @Transient - @XmlElement - @DynamicSerializeElement - private List ancWaves; - - @Transient - @XmlElement - @DynamicSerializeElement - private List ancTemp; - - @Transient - @XmlElement - @DynamicSerializeElement - private List ancPrecip; - - @Transient - @XmlElement - @DynamicSerializeElement - private List ancWinds; - - @Transient - @XmlElement - @DynamicSerializeElement - private List ancPressure; - - @Transient - @XmlElement - @DynamicSerializeElement - private List interWinds; - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - /** - * Empty default constructor - */ - public ObsCommon() { - } - - /** - * Construct an instance of this class using the supplied datauri. - * - * @param dataUri - */ - public ObsCommon(String dataUri) { - super(dataUri); - } - - /** - * @return the reportType - */ - public Integer getReportType() { - return reportType; - } - - /** - * @param reportType - * the reportType to set - */ - public void setReportType(Integer reportType) { - this.reportType = reportType; - } - - /** - * @return the corIndicator - */ - public String getCorIndicator() { - return corIndicator; - } - - /** - * @param corIndicator - * the corIndicator to set - */ - public void setCorIndicator(String corIndicator) { - this.corIndicator = corIndicator; - } - - /** - * @return the timeObs - */ - public Calendar getTimeObs() { - return timeObs; - } - - /** - * @param timeObs - * the timeObs to set - */ - public void setTimeObs(Calendar timeObs) { - this.timeObs = timeObs; - } - - /** - * @return the refHour - */ - public Calendar getRefHour() { - return refHour; - } - - /** - * @param refHour - * the refHour to set - */ - public void setRefHour(Calendar refHour) { - this.refHour = refHour; - } - - /** - * @return the obsText - */ - public String getObsText() { - return obsText; - } - - /** - * @param obsText - * the obsText to set - */ - public void setObsText(String obsText) { - this.obsText = obsText; - } - - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } - - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } - - /** - * @return the temp - */ - public Double getTemp() { - return temp; - } - - /** - * @param temp - * the temp to set - */ - public void setTemp(Double temp) { - this.temp = temp; - } - - /** - * @return the dwpt - */ - public Double getDwpt() { - return dwpt; - } - - /** - * @param dwpt - * the dwpt to set - */ - public void setDwpt(Double dwpt) { - this.dwpt = dwpt; - } - - /** - * @return the humidity - */ - public Double getHumidity() { - return humidity; - } - - /** - * @param humidity - * the humidity to set - */ - public void setHumidity(Double humidity) { - this.humidity = humidity; - } - - /** - * @return the seaTemp - */ - public Double getSeaTemp() { - return seaTemp; - } - - /** - * @param seaTemp - * the seaTemp to set - */ - public void setSeaTemp(Double seaTemp) { - this.seaTemp = seaTemp; - } - - /** - * @return the wetBulb - */ - public Double getWetBulb() { - return wetBulb; - } - - /** - * @param wetBulb - * the wetBulb to set - */ - public void setWetBulb(Double wetBulb) { - this.wetBulb = wetBulb; - } - - /** - * @return the windDirection - */ - public Integer getWindDirection() { - return windDirection; - } - - /** - * @param windDirection - * the windDirection to set - */ - public void setWindDirection(Integer windDirection) { - this.windDirection = windDirection; - } - - /** - * @return the windSpeed - */ - public Double getWindSpeed() { - return windSpeed; - } - - /** - * @param windSpeed - * the windSpeed to set - */ - public void setWindSpeed(Double windSpeed) { - this.windSpeed = windSpeed; - } - - /** - * - * @return the windGust - */ - public Double getWindGust() { - return windGust; - } - - /** - * - * @param windGust - * the windGust to set - */ - public void setWindGust(Double windGust) { - this.windGust = windGust; - } - - /** - * Get the direction of the peak wind observation. - * - * @return The direction of the peak wind observation in angular degrees - */ - public Integer getPeakWindDir() { - return peakWindDir; - } - - /** - * Set the direction of the peak wind observation. - * - * @param peakWindDir - * The direction of the peak wind observation in angular degrees - */ - public void setPeakWindDir(Integer peakWindDir) { - this.peakWindDir = peakWindDir; - } - - /** - * Get the speed of the peak wind observation. - * - * @return The speed of the peak wind observation in meters per second. - */ - public Double getPeakWindSpeed() { - return peakWindSpeed; - } - - /** - * Set the speed of the peak wind observation. - * - * @param peakWindSpeed - * The speed of the peak wind observation in meters per second. - */ - public void setPeakWindSpeed(Double peakWindSpeed) { - this.peakWindSpeed = peakWindSpeed; - } - - /** - * Set the time of the peak wind observation. - * - * @return The time of the peak wind observation (msecs from 1-1-1970). - */ - public Long getPeakWindTime() { - return peakWindTime; - } - - /** - * Get the time of the peak wind observation. - * - * @param peakWindTime - * The time of the peak wind observation (msecs from 1-1-1970). - */ - public void setPeakWindTime(Long peakWindTime) { - this.peakWindTime = peakWindTime; - } - - /** - * Get the equivilent 10 meter wind speed. - * - * @return The equivilent 10 meter wind speed in meters per second. - */ - public Double getWind10mSpeed() { - return wind10mSpeed; - } - - /** - * Set the equivilent 10 meter wind speed. - * - * @param windSpeed - * The equivilent 20 meter wind speed in meters per second. - */ - public void setWind10mSpeed(Double windSpeed) { - this.wind10mSpeed = windSpeed; - } - - /** - * Get the equivilent 20 meter wind speed. - * - * @return The equivilent 20 meter wind speed in meters per second. - */ - public Double getWind20mSpeed() { - return wind20mSpeed; - } - - /** - * Set the equivilent 20 meter wind speed. - * - * @param windSpeed - * The equivilent 20 meter wind speed in meters per second. - */ - public void setWind20mSpeed(Double windSpeed) { - this.wind20mSpeed = windSpeed; - } - - /** - * Get the altimeter setting. - * - * @return The altimeter setting in Pascals. - */ - public Integer getPressureAltimeter() { - return pressureAltimeter; - } - - /** - * Set the altimeter setting. - * - * @param pressure - * The altimeter setting in Pascals. - */ - public void setPressureAltimeter(Integer pressure) { - pressureAltimeter = pressure; - } - - /** - * Get the sea level pressure. - * - * @return The sea level pressure in Pascals. - */ - public Integer getPressureSealevel() { - return pressureSealevel; - } - - /** - * Set the sea level pressure. - * - * @param pressure - * The sea level pressure in Pascals. - */ - public void setPressureSealevel(Integer pressure) { - pressureSealevel = pressure; - } - - /** - * Get the station pressure. - * - * @return The station pressure in Pascals. - */ - public Integer getPressureStation() { - return pressureStation; - } - - /** - * Set the station pressure. - * - * @param pressure - * The station pressure in Pascals. - */ - public void setPressureStation(Integer pressure) { - this.pressureStation = pressure; - } - - /** - * Get the three hour pressure change. - * - * @return The three hour pressure change in Pascals. - */ - public Double getPressChange3Hr() { - return pressChange3Hr; - } - - /** - * Set the three hour pressure change. - * - *
-	 *   0 = press same or higher than 3 hrs ago
-	 *   1 = increasing then steady
-	 *   2 = increasing
-	 *   3 = decreasing or steady,then increasing
-	 *   4 = steady
-	 *   5 = press same or lower than 3 hrs ago
-	 *   6 = decreasing then steady
-	 *   7 = decreasing
-	 *   8 = steady or increasing,then decreasing
-	 * 
- * - * @param pressure - * The three hour pressure change in Pascals. - */ - public void setPressChange3Hr(Double pressure) { - this.pressChange3Hr = pressure; - } - - /** - * Get the three hour pressure change characteristic. - * - * @return The three hour pressure change characteristic. - */ - public Integer getPressChangeChar() { - return pressChangeChar; - } - - /** - * Set the three hour pressure change characteristic. - * - * @param pressChangeChar - * The three hour pressure change characteristic. - */ - public void setPressChangeChar(Integer pressChangeChar) { - this.pressChangeChar = pressChangeChar; - } - - /** - * @return the wx_past_1 - */ - public Integer getWx_past_1() { - return wx_past_1; - } - - /** - * @param wx_past_1 - * the wx_past_1 to set - */ - public void setWx_past_1(Integer wx_past_1) { - this.wx_past_1 = wx_past_1; - } - - /** - * @return the wx_past_2 - */ - public Integer getWx_past_2() { - return wx_past_2; - } - - /** - * @param wx_past_2 - * the wx_past_2 to set - */ - public void setWx_past_2(Integer wx_past_2) { - this.wx_past_2 = wx_past_2; - } - - /** - * @return the wx_present - */ - public Integer getWx_present() { - return wx_present; - } - - /** - * @param wx_present - * the wx_present to set - */ - public void setWx_present(Integer wx_present) { - this.wx_present = wx_present; - } - - /** - * @return the presWeather - */ - public String getPresWeather() { - return presWeather; - } - - /** - * @param presWeather - * the presWeather to set - */ - public void setPresWeather(String presWeather) { - this.presWeather = presWeather; - } - - /** - * @return the wx_report_type - */ - public Integer getWx_report_type() { - return wx_report_type; - } - - /** - * @param wx_report_type - * the wx_report_type to set - */ - public void setWx_report_type(Integer wx_report_type) { - this.wx_report_type = wx_report_type; - } - - /** - * @return the horzVisibility - */ - public Integer getHorzVisibility() { - return horzVisibility; - } - - /** - * @param horzVisibility - * the horzVisibility to set - */ - public void setHorzVisibility(Integer horzVisibility) { - this.horzVisibility = horzVisibility; - } - - /** - * @return the vertVisibility - */ - public Integer getVertVisibility() { - return vertVisibility; - } - - /** - * @param vertVisibility - * the vertVisibility to set - */ - public void setVertVisibility(Integer vertVisibility) { - this.vertVisibility = vertVisibility; - } - - /** - * @return the totalCloudCover - */ - public Integer getTotalCloudCover() { - return totalCloudCover; - } - - /** - * @param totalCloudCover - * the totalCloudCover to set - */ - public void setTotalCloudCover(Integer totalCloudCover) { - this.totalCloudCover = totalCloudCover; - } - - /** - * @return the cloudBaseHeight - */ - public Integer getCloudBaseHeight() { - return cloudBaseHeight; - } - - /** - * @param cloudBaseHeight - * the cloudBaseHeight to set - */ - public void setCloudBaseHeight(Integer cloudBaseHeight) { - this.cloudBaseHeight = cloudBaseHeight; - } - - /** - * @return the lowCloudType - */ - public Integer getLowCloudType() { - return lowCloudType; - } - - /** - * @param lowCloudType - * the lowCloudType to set - */ - public void setLowCloudType(Integer lowCloudType) { - this.lowCloudType = lowCloudType; - } - - /** - * @return the midCloudType - */ - public Integer getMidCloudType() { - return midCloudType; - } - - /** - * @param midCloudType - * the midCloudType to set - */ - public void setMidCloudType(Integer midCloudType) { - this.midCloudType = midCloudType; - } - - /** - * @return the highCloudType - */ - public Integer getHighCloudType() { - return highCloudType; - } - - /** - * @param highCloudType - * the highCloudType to set - */ - public void setHighCloudType(Integer highCloudType) { - this.highCloudType = highCloudType; - } - - /** - * @return the platformDirection - */ - public Integer getPlatformDirection() { - return platformDirection; - } - - /** - * @param platformDirection - * the platformDirection to set - */ - public void setPlatformDirection(Integer direction) { - platformDirection = direction; - } - - /** - * @return the platformMovement - */ - public Double getPlatformMovement() { - return platformMovement; - } - - /** - * @param platformMovement - * the platformMovement to set - */ - public void setPlatformMovement(Double movement) { - platformMovement = movement; - } - - /** - * @return the shipIceData - */ - public String getShipIceData() { - return shipIceData; - } - - /** - * @param shipIceData - * the shipIceData to set - */ - public void setShipIceData(String iceData) { - shipIceData = iceData; - } - - /** - * Set the wind wave height. - * - * @param windWaveHeight - * The windWaveHeight in meters. - */ - public void setWindWaveHeight(Double waveHeight) { - windWaveHeight = waveHeight; - } - - /** - * Get the wind wave height. - * - * @return The windWaveHeight in meters. - */ - public Double getWindWaveHeight() { - return windWaveHeight; - } - - /** - * Set the wind wave period. - * - * @param windWavePeriod - * The windWavePeriod in seconds. - */ - public void setWindWavePeriod(Integer wavePeriod) { - windWavePeriod = wavePeriod; - } - - /** - * Get the wind wave period. - * - * @return The windWavePeriod in seconds. - */ - public Integer getWindWavePeriod() { - return windWavePeriod; - } - - /** - * @return the waveSteepness - */ - public Double getWaveSteepness() { - return waveSteepness; - } - - /** - * @param waveSteepness - * the waveSteepness to set - */ - public void setWaveSteepness(Double waveSteepness) { - this.waveSteepness = waveSteepness; - } - - /** - * @return the waveHeight - */ - public Double getWaveHeight() { - return waveHeight; - } - - /** - * @param waveHeight - * the waveHeight to set - */ - public void setWaveHeight(Double waveHeight) { - this.waveHeight = waveHeight; - } - - /** - * @return the wavePeriod - */ - public Integer getWavePeriod() { - return wavePeriod; - } - - /** - * @param wavePeriod - * the wavePeriod to set - */ - public void setWavePeriod(Integer wavePeriod) { - this.wavePeriod = wavePeriod; - } - - /** - * @return the highResWaveHeight - */ - public Double getHighResWaveHeight() { - return highResWaveHeight; - } - - /** - * @param highResWaveHeight - * the highResWaveHeight to set - */ - public void setHighResWaveHeight(Double waveHeight) { - highResWaveHeight = waveHeight; - } - - /** - * @return the primarySwellWaveDir - */ - public Double getPrimarySwellWaveDir() { - return primarySwellWaveDir; - } - - /** - * @param primarySwellWaveDir - * the primarySwellWaveDir to set - */ - public void setPrimarySwellWaveDir(Double waveDir) { - primarySwellWaveDir = waveDir; - } - - /** - * @return the primarySwellWavePeriod - */ - public Integer getPrimarySwellWavePeriod() { - return primarySwellWavePeriod; - } - - /** - * @param primarySwellWavePeriod - * the primarySwellWavePeriod to set - */ - public void setPrimarySwellWavePeriod(Integer primarySwellWavePeriod) { - this.primarySwellWavePeriod = primarySwellWavePeriod; - } - - /** - * @return the primarySwellWaveHeight - */ - public Double getPrimarySwellWaveHeight() { - return primarySwellWaveHeight; - } - - /** - * @param primarySwellWaveHeight - * the primarySwellWaveHeight to set - */ - public void setPrimarySwellWaveHeight(Double waveHeight) { - primarySwellWaveHeight = waveHeight; - } - - /** - * @return the secondarySwellWaveDir - */ - public Double getSecondarySwellWaveDir() { - return secondarySwellWaveDir; - } - - /** - * @param secondarySwellWaveDir - * the secondarySwellWaveDir to set - */ - public void setSecondarySwellWaveDir(Double waveDir) { - secondarySwellWaveDir = waveDir; - } - - /** - * @return the secondarySwellWavePeriod - */ - public Integer getSecondarySwellWavePeriod() { - return secondarySwellWavePeriod; - } - - /** - * @param secondarySwellWavePeriod - * the secondarySwellWavePeriod to set - */ - public void setSecondarySwellWavePeriod(Integer wavePeriod) { - secondarySwellWavePeriod = wavePeriod; - } - - /** - * @return the secondarySwellWaveHeight - */ - public Double getSecondarySwellWaveHeight() { - return secondarySwellWaveHeight; - } - - /** - * @param secondarySwellWaveHeight - * the secondarySwellWaveHeight to set - */ - public void setSecondarySwellWaveHeight(Double height) { - secondarySwellWaveHeight = height; - } - - /** - * @return the ancClouds - */ - public List getAncClouds() { - return ancClouds; - } - - /** - * @param ancClouds - * the ancClouds to set - */ - public void setAncClouds(List ancClouds) { - this.ancClouds = ancClouds; - } - - /** - * - * @param cloud - */ - public void addCloud(AncCloud cloud) { - if (ancClouds == null) { - ancClouds = new ArrayList(); - } - ancClouds.add(cloud); - } - - /** - * @return the ancWaves - */ - public List getAncWaves() { - return ancWaves; - } - - /** - * @param ancWaves - * the ancWaves to set - */ - public void setAncWaves(List ancWaves) { - this.ancWaves = ancWaves; - } - - /** - * - * @param wave - */ - public void addWave(AncWave wave) { - if (ancWaves == null) { - ancWaves = new ArrayList(); - } - ancWaves.add(wave); - } - - /** - * @return the ancTemp - */ - public List getAncTemp() { - return ancTemp; - } - - /** - * @param ancTemp - * the ancTemp to set - */ - public void setAncTemp(List ancTemp) { - this.ancTemp = ancTemp; - } - - /** - * - * @param temp - */ - public void addTemp(AncTemp temp) { - if (ancTemp == null) { - ancTemp = new ArrayList(); - } - ancTemp.add(temp); - } - - /** - * @return the ancPrecip - */ - public List getAncPrecip() { - return ancPrecip; - } - - /** - * @param ancPrecip - * the ancPrecip to set - */ - public void setAncPrecip(List ancPrecip) { - this.ancPrecip = ancPrecip; - } - - /** - * - * @param precip - */ - public void addPrecip(AncPrecip precip) { - if (ancPrecip == null) { - ancPrecip = new ArrayList(); - } - ancPrecip.add(precip); - } - - /** - * @return the ancWinds - */ - public List getAncWinds() { - return ancWinds; - } - - /** - * @param ancWinds - * the ancWinds to set - */ - public void setAncWinds(List ancWinds) { - this.ancWinds = ancWinds; - } - - /** - * - * @param wind - */ - public void addWind(AncWind wind) { - if (ancWinds == null) { - ancWinds = new ArrayList(); - } - ancWinds.add(wind); - } - - /** - * @return the ancPressure - */ - public List getAncPressure() { - return ancPressure; - } - - /** - * @param ancPressure - * the ancPressure to set - */ - public void setAncPressure(List ancPressure) { - this.ancPressure = ancPressure; - } - - /** - * - * @param pressure - */ - public void addPressure(AncPressure pressure) { - if (ancPressure == null) { - ancPressure = new ArrayList(); - } - ancPressure.add(pressure); - } - - /** - * @return the ancPressure - */ - public List getInterWinds() { - return interWinds; - } - - /** - * @param ancPressure - * the ancPressure to set - */ - public void setInterWinds(List winds) { - interWinds = winds; - } - - /** - * - * @param pressure - */ - public void addInterWind(InterWinds wind) { - if (interWinds == null) { - interWinds = new ArrayList(); - } - interWinds.add(wind); - } - - /** - * Set the data uri for this observation. - * - * @param dataURI - */ - @Override - public void setDataURI(String dataURI) { - super.setDataURI(dataURI); - identifier = dataURI; - } - - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } - - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } - - public SurfaceObsLocation getLocation() { - return location; - } - - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } - - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } - - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } - - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } - - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } - - /** - * Get whether the location for this observation is defined. - * - * @return Is this location defined. - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } - - @Override - public String getString(String paramName) { - return null; - } - - @Override - public String[] getStrings(String paramName) { - return null; - } - - /** - * Get the value and units of a named parameter within this observation. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return An Amount with value and units. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Amount getValue(String paramName) { - Amount a = null; - - String pName = PARM_MAP.get(paramName); - - if (SFC_TEMP.equals(pName) && (temp != null)) { - a = new Amount(temp, TEMPERATURE_UNIT); - } else if (SFC_DWPT.equals(pName) && (dwpt != null)) { - a = new Amount(dwpt, TEMPERATURE_UNIT); - } else if (SFC_WNDSPD.equals(pName) && (windSpeed != null)) { - a = new Amount(windSpeed, WIND_SPEED_UNIT); - } else if (SFC_WNDDIR.equals(pName) && (windDirection != null)) { - a = new Amount(windDirection, WIND_DIR_UNIT); - } else if (SFC_WNDGST.equals(pName) && (windGust != null)) { - a = new Amount(windGust, WIND_SPEED_UNIT); - } else if (PRES_STATION.equals(pName) && (pressureStation != null)) { - a = new Amount(pressureStation, PRESSURE_UNIT); - } else if (PRES_SLP.equals(pName) && (pressureSealevel != null)) { - a = new Amount(pressureSealevel, PRESSURE_UNIT); - } else if (PRES_ALTSG.equals(pName) && (pressureAltimeter != null)) { - a = new Amount(pressureAltimeter, PRESSURE_UNIT); - } else if (STA_LAT.equals(pName)) { - a = new Amount(this.getLatitude(), LOCATION_UNIT); - } else if (STA_LON.equals(pName)) { - a = new Amount(this.getLongitude(), LOCATION_UNIT); - } else if ("WT".equals(pName) && this.seaTemp != null) { - a = new Amount(this.seaTemp, TEMPERATURE_UNIT); - } else if ("TCC".equals(pName) && this.totalCloudCover != null) { - a = new Amount(this.totalCloudCover, CLOUD_COVER); - } else if ("COVpct".equals(pName) && this.totalCloudCover != null) { - a = new Amount(this.totalCloudCover * 10, CLOUD_COVER); - } else if ("WP".equals(pName)) { - a = new Amount(wavePeriod, WAVE_UNIT); - } else if ("WH".equals(pName)) { - a = new Amount(waveHeight, WAVE_UNIT); - } else if ("SWP".equals(pName)) { - a = new Amount(primarySwellWavePeriod, WAVE_UNIT); - } else if ("SWH".equals(pName)) { - a = new Amount(primarySwellWaveHeight, WAVE_UNIT); - } else if ("PCHNG".equals(pName) && pressChange3Hr != MISSING) { - a = new Amount(pressChange3Hr, PRESSURE_UNIT); - } else if ("VIS".equals(pName) && this.horzVisibility != null) { - a = new Amount(this.horzVisibility / 1000, VISIBILITY_UNIT); - } else if ("PKWND".equals(paramName) && peakWindSpeed != MISSING) { - a = new Amount(peakWindSpeed, WIND_SPEED_UNIT); - } else if ("SWS".equals(paramName) || "SWGS".equals(paramName)) { - a = new Amount(1, WIND_SPEED_UNIT); - } else if ("SWD".equals(paramName) && primarySwellWaveDir != MISSING) { - a = new Amount(primarySwellWaveDir, WIND_DIR_UNIT); - } - - return a; - } - - @Override - public Collection getValues(String paramName) { - return null; - } - - @Override - public PointDataView getPointDataView() { - return pointDataView; - } - - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + ISpatialEnabled, IDecoderGettable, IPointData { + + private static final long serialVersionUID = 1L; + + private static final int MISSING = -9999; + + public static final Unit TEMPERATURE_UNIT = SI.KELVIN; + + public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; + + public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; + + public static final Unit PRESSURE_UNIT = SI.PASCAL; + + public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; + + public static final Unit WAVE_UNIT = SI.METER; + + public static final Unit VISIBILITY_UNIT = NonSI.MILE; + + public static final Unit CLOUD_COVER = NonSI.OCTET; + + private static final HashMap PARM_MAP = new HashMap(); + static { + PARM_MAP.put("T", SFC_TEMP); + PARM_MAP.put("DpT", SFC_DWPT); + PARM_MAP.put("WS", SFC_WNDSPD); + PARM_MAP.put("WD", SFC_WNDDIR); + PARM_MAP.put("WGS", SFC_WNDGST); + PARM_MAP.put("Px", PRES_STATION); + PARM_MAP.put("PMSL", PRES_SLP); + PARM_MAP.put("ASET", PRES_ALTSG); + PARM_MAP.put("NLAT", STA_LAT); + PARM_MAP.put("NLON", STA_LON); + PARM_MAP.put("WT", "WT"); + PARM_MAP.put("TCC", "TCC"); + PARM_MAP.put("WP", "WP"); + PARM_MAP.put("WH", "WH"); + PARM_MAP.put("SWP", "SWP"); + PARM_MAP.put("SWH", "SWH"); + PARM_MAP.put("SWS", "SWS"); + PARM_MAP.put("SWD", "SWD"); + PARM_MAP.put("SWGS", "SWGS"); + PARM_MAP.put("PCHNG", "PCHNG"); + PARM_MAP.put("PKWND", "PKWND"); + PARM_MAP.put("VIS", "VIS"); + PARM_MAP.put("COVpct", "COVpct"); + } + + // + @DataURI(position = 1) + @Column + @XmlAttribute + @DynamicSerializeElement + @Index(name = "reporttype_index") + private Integer reportType; + + // Correction indicator from wmo header + @DataURI(position = 2) + @Column + @XmlElement + @DynamicSerializeElement + private String corIndicator; + + @Embedded + @DataURI(position = 3, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; + + // Time of the observation. + @Column + @XmlAttribute + @DynamicSerializeElement + private Calendar timeObs; + + // Time of the observation to the nearest hour. + @Column + @XmlAttribute + @DynamicSerializeElement + private Calendar refHour; + + @Transient + @XmlElement + @DynamicSerializeElement + private String obsText = ""; + + // Text of the WMO header + @Transient + @XmlElement + @DynamicSerializeElement + private String wmoHeader = ""; + + // Observation air temperature in degrees Kelvin. + @Transient + @XmlElement + @DynamicSerializeElement + private Double temp = -9999.0; + + // Observation dewpoint temperature in degrees Kelvin. + @Transient + @XmlElement + @DynamicSerializeElement + private Double dwpt = -9999.0; + + // Relative Humidity in percent. Decimal(5,2) + @Transient + @XmlElement + @DynamicSerializeElement + private Double humidity = -9999.0; + + // Observation sea surface temperature in degrees Kelvin. + @Transient + @XmlElement + @DynamicSerializeElement + private Double seaTemp = -9999.0; + + // Observation wetbulb temperature in degrees Kelvin. + @Transient + @XmlElement + @DynamicSerializeElement + private Double wetBulb = -9999.0; + + // Observation wind direction in angular degrees. Integer + @Transient + @XmlElement + @DynamicSerializeElement + private Integer windDirection = -9999; + + // Observation wind speed in meters per second. + @Transient + @XmlElement + @DynamicSerializeElement + private Double windSpeed = -9999.0; + + // Observation wind speed gust in meters per second. + @Transient + @XmlElement + @DynamicSerializeElement + private Double windGust = -9999.0; + + // Direction of the peak wind observation in angular degrees + @Transient + @XmlElement + @DynamicSerializeElement + private Integer peakWindDir = -9999; + + // Speed of the peak wind observation in meters per second. + @Transient + @XmlElement + @DynamicSerializeElement + private Double peakWindSpeed = -9999.0; + + // Time of the peak wind observation. + @Transient + @XmlElement + @DynamicSerializeElement + private Long peakWindTime = -1L; + + // The equivilent 10 meter wind speed in meters per second. + @Transient + @XmlElement + @DynamicSerializeElement + private Double wind10mSpeed = -9999.0; + + // The equivilent 20 meter wind speed in meters per second. + @Transient + @XmlElement + @DynamicSerializeElement + private Double wind20mSpeed = -9999.0; + + // Altimeter setting in Pascals. + @Transient + @XmlElement + @DynamicSerializeElement + private Integer pressureAltimeter = -9999; + + // Sea level pressure in Pascals. + @Transient + @XmlElement + @DynamicSerializeElement + private Integer pressureSealevel = -9999; + + // Station pressure in Pascals. + @Transient + @XmlElement + @DynamicSerializeElement + private Integer pressureStation = -9999; + + // Three hour pressure change in pascals. + @Transient + @XmlElement + @DynamicSerializeElement + private Double pressChange3Hr = -9999.0; + + // Three hour pressure change characteristic. + @Transient + @XmlElement + @DynamicSerializeElement + private Integer pressChangeChar = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer wx_past_1 = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer wx_past_2 = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer wx_present = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private String presWeather = null; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer wx_report_type = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer horzVisibility = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer vertVisibility = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer totalCloudCover = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer cloudBaseHeight = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer lowCloudType = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer midCloudType = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer highCloudType = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer platformDirection = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Double platformMovement = -9999.0; + + @Transient + @XmlElement + @DynamicSerializeElement + private String shipIceData = ""; + + @Transient + @XmlElement + @DynamicSerializeElement + private Double windWaveHeight = -9999.0; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer windWavePeriod = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Double waveSteepness = -9999.0; + + @Transient + @XmlElement + @DynamicSerializeElement + private Double waveHeight = -9999.0; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer wavePeriod = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Double highResWaveHeight = -9999.0; + + @Transient + @XmlElement + @DynamicSerializeElement + private Double primarySwellWaveDir = -9999.0; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer primarySwellWavePeriod = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Double primarySwellWaveHeight = -9999.0; + + @Transient + @XmlElement + @DynamicSerializeElement + private Double secondarySwellWaveDir = -9999.0; + + @Transient + @XmlElement + @DynamicSerializeElement + private Integer secondarySwellWavePeriod = -9999; + + @Transient + @XmlElement + @DynamicSerializeElement + private Double secondarySwellWaveHeight = -9999.0; + + @Transient + @XmlElement + @DynamicSerializeElement + private List ancClouds; + + @Transient + @XmlElement + @DynamicSerializeElement + private List ancWaves; + + @Transient + @XmlElement + @DynamicSerializeElement + private List ancTemp; + + @Transient + @XmlElement + @DynamicSerializeElement + private List ancPrecip; + + @Transient + @XmlElement + @DynamicSerializeElement + private List ancWinds; + + @Transient + @XmlElement + @DynamicSerializeElement + private List ancPressure; + + @Transient + @XmlElement + @DynamicSerializeElement + private List interWinds; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + /** + * Empty default constructor + */ + public ObsCommon() { + } + + /** + * Construct an instance of this class using the supplied datauri. + * + * @param dataUri + */ + public ObsCommon(String dataUri) { + super(dataUri); + } + + /** + * @return the reportType + */ + public Integer getReportType() { + return reportType; + } + + /** + * @param reportType + * the reportType to set + */ + public void setReportType(Integer reportType) { + this.reportType = reportType; + } + + /** + * @return the corIndicator + */ + public String getCorIndicator() { + return corIndicator; + } + + /** + * @param corIndicator + * the corIndicator to set + */ + public void setCorIndicator(String corIndicator) { + this.corIndicator = corIndicator; + } + + /** + * @return the timeObs + */ + public Calendar getTimeObs() { + return timeObs; + } + + /** + * @param timeObs + * the timeObs to set + */ + public void setTimeObs(Calendar timeObs) { + this.timeObs = timeObs; + } + + /** + * @return the refHour + */ + public Calendar getRefHour() { + return refHour; + } + + /** + * @param refHour + * the refHour to set + */ + public void setRefHour(Calendar refHour) { + this.refHour = refHour; + } + + /** + * @return the obsText + */ + public String getObsText() { + return obsText; + } + + /** + * @param obsText + * the obsText to set + */ + public void setObsText(String obsText) { + this.obsText = obsText; + } + + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } + + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } + + /** + * @return the temp + */ + public Double getTemp() { + return temp; + } + + /** + * @param temp + * the temp to set + */ + public void setTemp(Double temp) { + this.temp = temp; + } + + /** + * @return the dwpt + */ + public Double getDwpt() { + return dwpt; + } + + /** + * @param dwpt + * the dwpt to set + */ + public void setDwpt(Double dwpt) { + this.dwpt = dwpt; + } + + /** + * @return the humidity + */ + public Double getHumidity() { + return humidity; + } + + /** + * @param humidity + * the humidity to set + */ + public void setHumidity(Double humidity) { + this.humidity = humidity; + } + + /** + * @return the seaTemp + */ + public Double getSeaTemp() { + return seaTemp; + } + + /** + * @param seaTemp + * the seaTemp to set + */ + public void setSeaTemp(Double seaTemp) { + this.seaTemp = seaTemp; + } + + /** + * @return the wetBulb + */ + public Double getWetBulb() { + return wetBulb; + } + + /** + * @param wetBulb + * the wetBulb to set + */ + public void setWetBulb(Double wetBulb) { + this.wetBulb = wetBulb; + } + + /** + * @return the windDirection + */ + public Integer getWindDirection() { + return windDirection; + } + + /** + * @param windDirection + * the windDirection to set + */ + public void setWindDirection(Integer windDirection) { + this.windDirection = windDirection; + } + + /** + * @return the windSpeed + */ + public Double getWindSpeed() { + return windSpeed; + } + + /** + * @param windSpeed + * the windSpeed to set + */ + public void setWindSpeed(Double windSpeed) { + this.windSpeed = windSpeed; + } + + /** + * + * @return the windGust + */ + public Double getWindGust() { + return windGust; + } + + /** + * + * @param windGust + * the windGust to set + */ + public void setWindGust(Double windGust) { + this.windGust = windGust; + } + + /** + * Get the direction of the peak wind observation. + * + * @return The direction of the peak wind observation in angular degrees + */ + public Integer getPeakWindDir() { + return peakWindDir; + } + + /** + * Set the direction of the peak wind observation. + * + * @param peakWindDir + * The direction of the peak wind observation in angular degrees + */ + public void setPeakWindDir(Integer peakWindDir) { + this.peakWindDir = peakWindDir; + } + + /** + * Get the speed of the peak wind observation. + * + * @return The speed of the peak wind observation in meters per second. + */ + public Double getPeakWindSpeed() { + return peakWindSpeed; + } + + /** + * Set the speed of the peak wind observation. + * + * @param peakWindSpeed + * The speed of the peak wind observation in meters per second. + */ + public void setPeakWindSpeed(Double peakWindSpeed) { + this.peakWindSpeed = peakWindSpeed; + } + + /** + * Set the time of the peak wind observation. + * + * @return The time of the peak wind observation (msecs from 1-1-1970). + */ + public Long getPeakWindTime() { + return peakWindTime; + } + + /** + * Get the time of the peak wind observation. + * + * @param peakWindTime + * The time of the peak wind observation (msecs from 1-1-1970). + */ + public void setPeakWindTime(Long peakWindTime) { + this.peakWindTime = peakWindTime; + } + + /** + * Get the equivilent 10 meter wind speed. + * + * @return The equivilent 10 meter wind speed in meters per second. + */ + public Double getWind10mSpeed() { + return wind10mSpeed; + } + + /** + * Set the equivilent 10 meter wind speed. + * + * @param windSpeed + * The equivilent 20 meter wind speed in meters per second. + */ + public void setWind10mSpeed(Double windSpeed) { + this.wind10mSpeed = windSpeed; + } + + /** + * Get the equivilent 20 meter wind speed. + * + * @return The equivilent 20 meter wind speed in meters per second. + */ + public Double getWind20mSpeed() { + return wind20mSpeed; + } + + /** + * Set the equivilent 20 meter wind speed. + * + * @param windSpeed + * The equivilent 20 meter wind speed in meters per second. + */ + public void setWind20mSpeed(Double windSpeed) { + this.wind20mSpeed = windSpeed; + } + + /** + * Get the altimeter setting. + * + * @return The altimeter setting in Pascals. + */ + public Integer getPressureAltimeter() { + return pressureAltimeter; + } + + /** + * Set the altimeter setting. + * + * @param pressure + * The altimeter setting in Pascals. + */ + public void setPressureAltimeter(Integer pressure) { + pressureAltimeter = pressure; + } + + /** + * Get the sea level pressure. + * + * @return The sea level pressure in Pascals. + */ + public Integer getPressureSealevel() { + return pressureSealevel; + } + + /** + * Set the sea level pressure. + * + * @param pressure + * The sea level pressure in Pascals. + */ + public void setPressureSealevel(Integer pressure) { + pressureSealevel = pressure; + } + + /** + * Get the station pressure. + * + * @return The station pressure in Pascals. + */ + public Integer getPressureStation() { + return pressureStation; + } + + /** + * Set the station pressure. + * + * @param pressure + * The station pressure in Pascals. + */ + public void setPressureStation(Integer pressure) { + this.pressureStation = pressure; + } + + /** + * Get the three hour pressure change. + * + * @return The three hour pressure change in Pascals. + */ + public Double getPressChange3Hr() { + return pressChange3Hr; + } + + /** + * Set the three hour pressure change. + * + *
+     *   0 = press same or higher than 3 hrs ago
+     *   1 = increasing then steady
+     *   2 = increasing
+     *   3 = decreasing or steady,then increasing
+     *   4 = steady
+     *   5 = press same or lower than 3 hrs ago
+     *   6 = decreasing then steady
+     *   7 = decreasing
+     *   8 = steady or increasing,then decreasing
+     * 
+ * + * @param pressure + * The three hour pressure change in Pascals. + */ + public void setPressChange3Hr(Double pressure) { + this.pressChange3Hr = pressure; + } + + /** + * Get the three hour pressure change characteristic. + * + * @return The three hour pressure change characteristic. + */ + public Integer getPressChangeChar() { + return pressChangeChar; + } + + /** + * Set the three hour pressure change characteristic. + * + * @param pressChangeChar + * The three hour pressure change characteristic. + */ + public void setPressChangeChar(Integer pressChangeChar) { + this.pressChangeChar = pressChangeChar; + } + + /** + * @return the wx_past_1 + */ + public Integer getWx_past_1() { + return wx_past_1; + } + + /** + * @param wx_past_1 + * the wx_past_1 to set + */ + public void setWx_past_1(Integer wx_past_1) { + this.wx_past_1 = wx_past_1; + } + + /** + * @return the wx_past_2 + */ + public Integer getWx_past_2() { + return wx_past_2; + } + + /** + * @param wx_past_2 + * the wx_past_2 to set + */ + public void setWx_past_2(Integer wx_past_2) { + this.wx_past_2 = wx_past_2; + } + + /** + * @return the wx_present + */ + public Integer getWx_present() { + return wx_present; + } + + /** + * @param wx_present + * the wx_present to set + */ + public void setWx_present(Integer wx_present) { + this.wx_present = wx_present; + } + + /** + * @return the presWeather + */ + public String getPresWeather() { + return presWeather; + } + + /** + * @param presWeather + * the presWeather to set + */ + public void setPresWeather(String presWeather) { + this.presWeather = presWeather; + } + + /** + * @return the wx_report_type + */ + public Integer getWx_report_type() { + return wx_report_type; + } + + /** + * @param wx_report_type + * the wx_report_type to set + */ + public void setWx_report_type(Integer wx_report_type) { + this.wx_report_type = wx_report_type; + } + + /** + * @return the horzVisibility + */ + public Integer getHorzVisibility() { + return horzVisibility; + } + + /** + * @param horzVisibility + * the horzVisibility to set + */ + public void setHorzVisibility(Integer horzVisibility) { + this.horzVisibility = horzVisibility; + } + + /** + * @return the vertVisibility + */ + public Integer getVertVisibility() { + return vertVisibility; + } + + /** + * @param vertVisibility + * the vertVisibility to set + */ + public void setVertVisibility(Integer vertVisibility) { + this.vertVisibility = vertVisibility; + } + + /** + * @return the totalCloudCover + */ + public Integer getTotalCloudCover() { + return totalCloudCover; + } + + /** + * @param totalCloudCover + * the totalCloudCover to set + */ + public void setTotalCloudCover(Integer totalCloudCover) { + this.totalCloudCover = totalCloudCover; + } + + /** + * @return the cloudBaseHeight + */ + public Integer getCloudBaseHeight() { + return cloudBaseHeight; + } + + /** + * @param cloudBaseHeight + * the cloudBaseHeight to set + */ + public void setCloudBaseHeight(Integer cloudBaseHeight) { + this.cloudBaseHeight = cloudBaseHeight; + } + + /** + * @return the lowCloudType + */ + public Integer getLowCloudType() { + return lowCloudType; + } + + /** + * @param lowCloudType + * the lowCloudType to set + */ + public void setLowCloudType(Integer lowCloudType) { + this.lowCloudType = lowCloudType; + } + + /** + * @return the midCloudType + */ + public Integer getMidCloudType() { + return midCloudType; + } + + /** + * @param midCloudType + * the midCloudType to set + */ + public void setMidCloudType(Integer midCloudType) { + this.midCloudType = midCloudType; + } + + /** + * @return the highCloudType + */ + public Integer getHighCloudType() { + return highCloudType; + } + + /** + * @param highCloudType + * the highCloudType to set + */ + public void setHighCloudType(Integer highCloudType) { + this.highCloudType = highCloudType; + } + + /** + * @return the platformDirection + */ + public Integer getPlatformDirection() { + return platformDirection; + } + + /** + * @param platformDirection + * the platformDirection to set + */ + public void setPlatformDirection(Integer direction) { + platformDirection = direction; + } + + /** + * @return the platformMovement + */ + public Double getPlatformMovement() { + return platformMovement; + } + + /** + * @param platformMovement + * the platformMovement to set + */ + public void setPlatformMovement(Double movement) { + platformMovement = movement; + } + + /** + * @return the shipIceData + */ + public String getShipIceData() { + return shipIceData; + } + + /** + * @param shipIceData + * the shipIceData to set + */ + public void setShipIceData(String iceData) { + shipIceData = iceData; + } + + /** + * Set the wind wave height. + * + * @param windWaveHeight + * The windWaveHeight in meters. + */ + public void setWindWaveHeight(Double waveHeight) { + windWaveHeight = waveHeight; + } + + /** + * Get the wind wave height. + * + * @return The windWaveHeight in meters. + */ + public Double getWindWaveHeight() { + return windWaveHeight; + } + + /** + * Set the wind wave period. + * + * @param windWavePeriod + * The windWavePeriod in seconds. + */ + public void setWindWavePeriod(Integer wavePeriod) { + windWavePeriod = wavePeriod; + } + + /** + * Get the wind wave period. + * + * @return The windWavePeriod in seconds. + */ + public Integer getWindWavePeriod() { + return windWavePeriod; + } + + /** + * @return the waveSteepness + */ + public Double getWaveSteepness() { + return waveSteepness; + } + + /** + * @param waveSteepness + * the waveSteepness to set + */ + public void setWaveSteepness(Double waveSteepness) { + this.waveSteepness = waveSteepness; + } + + /** + * @return the waveHeight + */ + public Double getWaveHeight() { + return waveHeight; + } + + /** + * @param waveHeight + * the waveHeight to set + */ + public void setWaveHeight(Double waveHeight) { + this.waveHeight = waveHeight; + } + + /** + * @return the wavePeriod + */ + public Integer getWavePeriod() { + return wavePeriod; + } + + /** + * @param wavePeriod + * the wavePeriod to set + */ + public void setWavePeriod(Integer wavePeriod) { + this.wavePeriod = wavePeriod; + } + + /** + * @return the highResWaveHeight + */ + public Double getHighResWaveHeight() { + return highResWaveHeight; + } + + /** + * @param highResWaveHeight + * the highResWaveHeight to set + */ + public void setHighResWaveHeight(Double waveHeight) { + highResWaveHeight = waveHeight; + } + + /** + * @return the primarySwellWaveDir + */ + public Double getPrimarySwellWaveDir() { + return primarySwellWaveDir; + } + + /** + * @param primarySwellWaveDir + * the primarySwellWaveDir to set + */ + public void setPrimarySwellWaveDir(Double waveDir) { + primarySwellWaveDir = waveDir; + } + + /** + * @return the primarySwellWavePeriod + */ + public Integer getPrimarySwellWavePeriod() { + return primarySwellWavePeriod; + } + + /** + * @param primarySwellWavePeriod + * the primarySwellWavePeriod to set + */ + public void setPrimarySwellWavePeriod(Integer primarySwellWavePeriod) { + this.primarySwellWavePeriod = primarySwellWavePeriod; + } + + /** + * @return the primarySwellWaveHeight + */ + public Double getPrimarySwellWaveHeight() { + return primarySwellWaveHeight; + } + + /** + * @param primarySwellWaveHeight + * the primarySwellWaveHeight to set + */ + public void setPrimarySwellWaveHeight(Double waveHeight) { + primarySwellWaveHeight = waveHeight; + } + + /** + * @return the secondarySwellWaveDir + */ + public Double getSecondarySwellWaveDir() { + return secondarySwellWaveDir; + } + + /** + * @param secondarySwellWaveDir + * the secondarySwellWaveDir to set + */ + public void setSecondarySwellWaveDir(Double waveDir) { + secondarySwellWaveDir = waveDir; + } + + /** + * @return the secondarySwellWavePeriod + */ + public Integer getSecondarySwellWavePeriod() { + return secondarySwellWavePeriod; + } + + /** + * @param secondarySwellWavePeriod + * the secondarySwellWavePeriod to set + */ + public void setSecondarySwellWavePeriod(Integer wavePeriod) { + secondarySwellWavePeriod = wavePeriod; + } + + /** + * @return the secondarySwellWaveHeight + */ + public Double getSecondarySwellWaveHeight() { + return secondarySwellWaveHeight; + } + + /** + * @param secondarySwellWaveHeight + * the secondarySwellWaveHeight to set + */ + public void setSecondarySwellWaveHeight(Double height) { + secondarySwellWaveHeight = height; + } + + /** + * @return the ancClouds + */ + public List getAncClouds() { + return ancClouds; + } + + /** + * @param ancClouds + * the ancClouds to set + */ + public void setAncClouds(List ancClouds) { + this.ancClouds = ancClouds; + } + + /** + * + * @param cloud + */ + public void addCloud(AncCloud cloud) { + if (ancClouds == null) { + ancClouds = new ArrayList(); + } + ancClouds.add(cloud); + } + + /** + * @return the ancWaves + */ + public List getAncWaves() { + return ancWaves; + } + + /** + * @param ancWaves + * the ancWaves to set + */ + public void setAncWaves(List ancWaves) { + this.ancWaves = ancWaves; + } + + /** + * + * @param wave + */ + public void addWave(AncWave wave) { + if (ancWaves == null) { + ancWaves = new ArrayList(); + } + ancWaves.add(wave); + } + + /** + * @return the ancTemp + */ + public List getAncTemp() { + return ancTemp; + } + + /** + * @param ancTemp + * the ancTemp to set + */ + public void setAncTemp(List ancTemp) { + this.ancTemp = ancTemp; + } + + /** + * + * @param temp + */ + public void addTemp(AncTemp temp) { + if (ancTemp == null) { + ancTemp = new ArrayList(); + } + ancTemp.add(temp); + } + + /** + * @return the ancPrecip + */ + public List getAncPrecip() { + return ancPrecip; + } + + /** + * @param ancPrecip + * the ancPrecip to set + */ + public void setAncPrecip(List ancPrecip) { + this.ancPrecip = ancPrecip; + } + + /** + * + * @param precip + */ + public void addPrecip(AncPrecip precip) { + if (ancPrecip == null) { + ancPrecip = new ArrayList(); + } + ancPrecip.add(precip); + } + + /** + * @return the ancWinds + */ + public List getAncWinds() { + return ancWinds; + } + + /** + * @param ancWinds + * the ancWinds to set + */ + public void setAncWinds(List ancWinds) { + this.ancWinds = ancWinds; + } + + /** + * + * @param wind + */ + public void addWind(AncWind wind) { + if (ancWinds == null) { + ancWinds = new ArrayList(); + } + ancWinds.add(wind); + } + + /** + * @return the ancPressure + */ + public List getAncPressure() { + return ancPressure; + } + + /** + * @param ancPressure + * the ancPressure to set + */ + public void setAncPressure(List ancPressure) { + this.ancPressure = ancPressure; + } + + /** + * + * @param pressure + */ + public void addPressure(AncPressure pressure) { + if (ancPressure == null) { + ancPressure = new ArrayList(); + } + ancPressure.add(pressure); + } + + /** + * @return the ancPressure + */ + public List getInterWinds() { + return interWinds; + } + + /** + * @param ancPressure + * the ancPressure to set + */ + public void setInterWinds(List winds) { + interWinds = winds; + } + + /** + * + * @param pressure + */ + public void addInterWind(InterWinds wind) { + if (interWinds == null) { + interWinds = new ArrayList(); + } + interWinds.add(wind); + } + + /** + * Set the data uri for this observation. + * + * @param dataURI + */ + @Override + public void setDataURI(String dataURI) { + super.setDataURI(dataURI); + identifier = dataURI; + } + + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } + + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } + + public SurfaceObsLocation getLocation() { + return location; + } + + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } + + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } + + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } + + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } + + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } + + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } + + /** + * Get whether the location for this observation is defined. + * + * @return Is this location defined. + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } + + @Override + public String getString(String paramName) { + return null; + } + + @Override + public String[] getStrings(String paramName) { + return null; + } + + /** + * Get the value and units of a named parameter within this observation. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return An Amount with value and units. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Amount getValue(String paramName) { + Amount a = null; + + String pName = PARM_MAP.get(paramName); + + if (SFC_TEMP.equals(pName) && (temp != null)) { + a = new Amount(temp, TEMPERATURE_UNIT); + } else if (SFC_DWPT.equals(pName) && (dwpt != null)) { + a = new Amount(dwpt, TEMPERATURE_UNIT); + } else if (SFC_WNDSPD.equals(pName) && (windSpeed != null)) { + a = new Amount(windSpeed, WIND_SPEED_UNIT); + } else if (SFC_WNDDIR.equals(pName) && (windDirection != null)) { + a = new Amount(windDirection, WIND_DIR_UNIT); + } else if (SFC_WNDGST.equals(pName) && (windGust != null)) { + a = new Amount(windGust, WIND_SPEED_UNIT); + } else if (PRES_STATION.equals(pName) && (pressureStation != null)) { + a = new Amount(pressureStation, PRESSURE_UNIT); + } else if (PRES_SLP.equals(pName) && (pressureSealevel != null)) { + a = new Amount(pressureSealevel, PRESSURE_UNIT); + } else if (PRES_ALTSG.equals(pName) && (pressureAltimeter != null)) { + a = new Amount(pressureAltimeter, PRESSURE_UNIT); + } else if (STA_LAT.equals(pName)) { + a = new Amount(this.getLatitude(), LOCATION_UNIT); + } else if (STA_LON.equals(pName)) { + a = new Amount(this.getLongitude(), LOCATION_UNIT); + } else if ("WT".equals(pName) && (this.seaTemp != null)) { + a = new Amount(this.seaTemp, TEMPERATURE_UNIT); + } else if ("TCC".equals(pName) && (this.totalCloudCover != null)) { + a = new Amount(this.totalCloudCover, CLOUD_COVER); + } else if ("COVpct".equals(pName) && (this.totalCloudCover != null)) { + a = new Amount(this.totalCloudCover * 10, CLOUD_COVER); + } else if ("WP".equals(pName)) { + a = new Amount(wavePeriod, WAVE_UNIT); + } else if ("WH".equals(pName)) { + a = new Amount(waveHeight, WAVE_UNIT); + } else if ("SWP".equals(pName)) { + a = new Amount(primarySwellWavePeriod, WAVE_UNIT); + } else if ("SWH".equals(pName)) { + a = new Amount(primarySwellWaveHeight, WAVE_UNIT); + } else if ("PCHNG".equals(pName) && (pressChange3Hr != MISSING)) { + a = new Amount(pressChange3Hr, PRESSURE_UNIT); + } else if ("VIS".equals(pName) && (this.horzVisibility != null)) { + a = new Amount(this.horzVisibility / 1000, VISIBILITY_UNIT); + } else if ("PKWND".equals(paramName) && (peakWindSpeed != MISSING)) { + a = new Amount(peakWindSpeed, WIND_SPEED_UNIT); + } else if ("SWS".equals(paramName) || "SWGS".equals(paramName)) { + a = new Amount(1, WIND_SPEED_UNIT); + } else if ("SWD".equals(paramName) && (primarySwellWaveDir != MISSING)) { + a = new Amount(primarySwellWaveDir, WIND_DIR_UNIT); + } + + return a; + } + + @Override + public Collection getValues(String paramName) { + return null; + } + + @Override + public PointDataView getPointDataView() { + return pointDataView; + } + + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "sfcobs"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.svrwx/src/com/raytheon/uf/common/dataplugin/svrwx/SvrWxRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.svrwx/src/com/raytheon/uf/common/dataplugin/svrwx/SvrWxRecord.java index f88ea2a2d4..db716a3398 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.svrwx/src/com/raytheon/uf/common/dataplugin/svrwx/SvrWxRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.svrwx/src/com/raytheon/uf/common/dataplugin/svrwx/SvrWxRecord.java @@ -57,11 +57,13 @@ import com.vividsolutions.jts.geom.Geometry; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 4, 2010 jsanchez Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Jan 04, 2010 jsanchez Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -75,229 +77,231 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "svrwx", - indexes = { - @Index(name = "svrwx_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "svrwx", indexes = { @Index(name = "svrwx_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class SvrWxRecord extends PersistablePluginDataObject implements - ISpatialEnabled, IPointData { + ISpatialEnabled, IPointData { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - // Text of the WMO header - @Transient - @XmlElement - @DynamicSerializeElement - private String wmoHeader = ""; + // Text of the WMO header + @Transient + @XmlElement + @DynamicSerializeElement + private String wmoHeader = ""; - @Embedded - @DataURI(position = 2, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; + @Embedded + @DataURI(position = 2, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; - @Transient - @XmlElement - @DynamicSerializeElement - protected String eventKey; + @Transient + @XmlElement + @DynamicSerializeElement + protected String eventKey; - @XmlElement - @DynamicSerializeElement - @Column - @DataURI(position = 1) - protected String reportType; + @XmlElement + @DynamicSerializeElement + @Column + @DataURI(position = 1) + protected String reportType; - @Transient - @XmlElement - @DynamicSerializeElement - protected String details; + @Transient + @XmlElement + @DynamicSerializeElement + protected String details; - @Transient - @XmlElement - @DynamicSerializeElement - protected String greenTime; + @Transient + @XmlElement + @DynamicSerializeElement + protected String greenTime; - /** - * Empty default constructor - */ - public SvrWxRecord() { - } + /** + * Empty default constructor + */ + public SvrWxRecord() { + } - /** - * Construct an instance of this class using the supplied datauri. - * - * @param dataUri - */ - public SvrWxRecord(String dataUri) { - super(dataUri); - } + /** + * Construct an instance of this class using the supplied datauri. + * + * @param dataUri + */ + public SvrWxRecord(String dataUri) { + super(dataUri); + } - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * Set the data uri for this observation. - * - * @param dataURI - */ - @Override - public void setDataURI(String dataURI) { - super.setDataURI(dataURI); - identifier = dataURI; - } + /** + * Set the data uri for this observation. + * + * @param dataURI + */ + @Override + public void setDataURI(String dataURI) { + super.setDataURI(dataURI); + identifier = dataURI; + } - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } - public SurfaceObsLocation getLocation() { - return location; - } + public SurfaceObsLocation getLocation() { + return location; + } - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - public String getEventKey() { - return eventKey; - } + public String getEventKey() { + return eventKey; + } - public void setEventKey(String eventKey) { - this.eventKey = eventKey; - } + public void setEventKey(String eventKey) { + this.eventKey = eventKey; + } - public String getGreenTime() { - return greenTime; - } + public String getGreenTime() { + return greenTime; + } - public void setGreenTime(String greenTime) { - this.greenTime = greenTime; - } + public void setGreenTime(String greenTime) { + this.greenTime = greenTime; + } - public String getDetails() { - return details; - } + public String getDetails() { + return details; + } - public void setDetails(String details) { - this.details = details; - } + public void setDetails(String details) { + this.details = details; + } - public String getReportType() { - return reportType; - } + public String getReportType() { + return reportType; + } - public void setReportType(String reportType) { - this.reportType = reportType; - } + public void setReportType(String reportType) { + this.reportType = reportType; + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } - /** - * Get whether the location for this observation is defined. - * - * @return Is this location defined. - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } + /** + * Get whether the location for this observation is defined. + * + * @return Is this location defined. + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Calendar c = getDataTime().getRefTimeAsCalendar(); + if (c != null) { + sb.append(String.format("SvrWx:%1$tY%1$tm%1$td%1$tH%1$tM", + getDataTime().getRefTimeAsCalendar())); + } else { + sb.append("SvrWx:YYYYMMDDHHmm"); + } + sb.append(String.format("%6.2f %7.2f:", getLatitude(), getLongitude())); + return sb.toString(); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - Calendar c = getDataTime().getRefTimeAsCalendar(); - if (c != null) { - sb.append(String.format("SvrWx:%1$tY%1$tm%1$td%1$tH%1$tM", - getDataTime().getRefTimeAsCalendar())); - } else { - sb.append("SvrWx:YYYYMMDDHHmm"); - } - sb.append(String.format("%6.2f %7.2f:", getLatitude(), getLongitude())); - return sb.toString(); - } @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "svrwx"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.tcg/src/com/raytheon/uf/common/dataplugin/tcg/TropicalCycloneGuidance.java b/edexOsgi/com.raytheon.uf.common.dataplugin.tcg/src/com/raytheon/uf/common/dataplugin/tcg/TropicalCycloneGuidance.java index 09eccfafa4..2e63810550 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.tcg/src/com/raytheon/uf/common/dataplugin/tcg/TropicalCycloneGuidance.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.tcg/src/com/raytheon/uf/common/dataplugin/tcg/TropicalCycloneGuidance.java @@ -57,11 +57,13 @@ import com.vividsolutions.jts.geom.Geometry; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Oct 28, 2009 jsanchez Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Oct 28, 2009 jsanchez Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -75,230 +77,232 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "tcg", - indexes = { - @Index(name = "tcg_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "tcg", indexes = { @Index(name = "tcg_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class TropicalCycloneGuidance extends PersistablePluginDataObject - implements ISpatialEnabled, IPointData { + implements ISpatialEnabled, IPointData { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - // Text of the WMO header - @Transient - @XmlElement - @DynamicSerializeElement - private String wmoHeader = ""; + // Text of the WMO header + @Transient + @XmlElement + @DynamicSerializeElement + private String wmoHeader = ""; - @XmlElement - @DynamicSerializeElement - @Transient - protected String stormName; + @XmlElement + @DynamicSerializeElement + @Transient + protected String stormName; - @XmlElement - @DynamicSerializeElement - @DataURI(position = 1) - @Column - protected String productType = ""; + @XmlElement + @DynamicSerializeElement + @DataURI(position = 1) + @Column + protected String productType = ""; - @XmlElement - @DynamicSerializeElement - @DataURI(position = 2) - @Column - protected String modelName = "NONE"; + @XmlElement + @DynamicSerializeElement + @DataURI(position = 2) + @Column + protected String modelName = "NONE"; - @Embedded - @DataURI(position = 3, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; + @Embedded + @DataURI(position = 3, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; - @Transient - @XmlElement - @DynamicSerializeElement - protected TCGStormType type = TCGStormType.UNKNOWN; + @Transient + @XmlElement + @DynamicSerializeElement + protected TCGStormType type = TCGStormType.UNKNOWN; - /** - * Empty default constructor - */ - public TropicalCycloneGuidance() { - } + /** + * Empty default constructor + */ + public TropicalCycloneGuidance() { + } - /** - * Construct an instance of this class using the supplied datauri. - * - * @param dataUri - */ - public TropicalCycloneGuidance(String dataUri) { - super(dataUri); - } + /** + * Construct an instance of this class using the supplied datauri. + * + * @param dataUri + */ + public TropicalCycloneGuidance(String dataUri) { + super(dataUri); + } - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - public String getModelName() { - return modelName; - } + public String getModelName() { + return modelName; + } - public void setModelName(String modelName) { - this.modelName = modelName; - } + public void setModelName(String modelName) { + this.modelName = modelName; + } - /** - * Set the data uri for this observation. - * - * @param dataURI - */ - @Override - public void setDataURI(String dataURI) { - super.setDataURI(dataURI); - identifier = dataURI; - } + /** + * Set the data uri for this observation. + * + * @param dataURI + */ + @Override + public void setDataURI(String dataURI) { + super.setDataURI(dataURI); + identifier = dataURI; + } - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } - public SurfaceObsLocation getLocation() { - return location; - } + public SurfaceObsLocation getLocation() { + return location; + } - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - public String getStormName() { - return stormName; - } + public String getStormName() { + return stormName; + } - public void setStormName(String stormName) { - this.stormName = stormName; - } + public void setStormName(String stormName) { + this.stormName = stormName; + } - public TCGStormType getType() { - return type; - } + public TCGStormType getType() { + return type; + } - public void setType(TCGStormType type) { - this.type = type; - } + public void setType(TCGStormType type) { + this.type = type; + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } - /** - * Get whether the location for this observation is defined. - * - * @return Is this location defined. - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } + /** + * Get whether the location for this observation is defined. + * + * @return Is this location defined. + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - public String getProductType() { - return productType; - } + public String getProductType() { + return productType; + } - public void setProductType(String productType) { - this.productType = productType; - } + public void setProductType(String productType) { + this.productType = productType; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Calendar c = getDataTime().getRefTimeAsCalendar(); + if (c != null) { + sb.append(String.format("TCG:%1$tY%1$tm%1$td%1$tH%1$tM", + getDataTime().getRefTimeAsCalendar())); + } else { + sb.append("TCG:YYYYMMDDHHmm"); + } + sb.append(String.format("%6.2f %7.2f:", getLatitude(), getLongitude())); + return sb.toString(); + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - Calendar c = getDataTime().getRefTimeAsCalendar(); - if (c != null) { - sb.append(String.format("TCG:%1$tY%1$tm%1$td%1$tH%1$tM", - getDataTime().getRefTimeAsCalendar())); - } else { - sb.append("TCG:YYYYMMDDHHmm"); - } - sb.append(String.format("%6.2f %7.2f:", getLatitude(), getLongitude())); - return sb.toString(); - } @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "tcg"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.tcs/src/com/raytheon/uf/common/dataplugin/tcs/TropicalCycloneSummary.java b/edexOsgi/com.raytheon.uf.common.dataplugin.tcs/src/com/raytheon/uf/common/dataplugin/tcs/TropicalCycloneSummary.java index d891f550e6..89ae09e699 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.tcs/src/com/raytheon/uf/common/dataplugin/tcs/TropicalCycloneSummary.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.tcs/src/com/raytheon/uf/common/dataplugin/tcs/TropicalCycloneSummary.java @@ -58,11 +58,13 @@ import com.vividsolutions.jts.geom.Geometry; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Nov 12, 2009 jsanchez Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Nov 12, 2009 jsanchez Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -76,272 +78,274 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "tcs", - indexes = { - @Index(name = "tcs_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "tcs", indexes = { @Index(name = "tcs_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class TropicalCycloneSummary extends PersistablePluginDataObject - implements ISpatialEnabled, IPointData { + implements ISpatialEnabled, IPointData { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - // Text of the WMO header - @Transient - @XmlElement - @DynamicSerializeElement - private String wmoHeader = ""; + // Text of the WMO header + @Transient + @XmlElement + @DynamicSerializeElement + private String wmoHeader = ""; - @XmlElement - @DynamicSerializeElement - @Column - @DataURI(position = 1) - protected String productType = ""; + @XmlElement + @DynamicSerializeElement + @Column + @DataURI(position = 1) + protected String productType = ""; - @Embedded - @DataURI(position = 2, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; + @Embedded + @DataURI(position = 2, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; - @XmlElement - @DynamicSerializeElement - @Transient - protected String name; + @XmlElement + @DynamicSerializeElement + @Transient + protected String name; - @XmlElement - @DynamicSerializeElement - @Transient - private boolean tropical; + @XmlElement + @DynamicSerializeElement + @Transient + private boolean tropical; - @XmlElement - @DynamicSerializeElement - @Transient - private String displayTime; + @XmlElement + @DynamicSerializeElement + @Transient + private String displayTime; - @XmlElement - @DynamicSerializeElement - @Transient - private int pressure; + @XmlElement + @DynamicSerializeElement + @Transient + private int pressure; - @XmlElement - @DynamicSerializeElement - @Transient - protected int windSpeed; + @XmlElement + @DynamicSerializeElement + @Transient + protected int windSpeed; - @XmlElement - @DynamicSerializeElement - @Transient - protected ArrayList radiusList; + @XmlElement + @DynamicSerializeElement + @Transient + protected ArrayList radiusList; - // @XmlElement - // @DynamicSerializeElement - // @Transient - // protected List windRadii; + // @XmlElement + // @DynamicSerializeElement + // @Transient + // protected List windRadii; - /** - * Empty default constructor - */ - public TropicalCycloneSummary() { - tropical = true; - windSpeed = 0; - displayTime = ""; - } + /** + * Empty default constructor + */ + public TropicalCycloneSummary() { + tropical = true; + windSpeed = 0; + displayTime = ""; + } - public TropicalCycloneSummary(String dataUri) { - super(dataUri); - tropical = true; - windSpeed = 0; - displayTime = ""; - } + public TropicalCycloneSummary(String dataUri) { + super(dataUri); + tropical = true; + windSpeed = 0; + displayTime = ""; + } - public TropicalCycloneSummary(String name, int pressure, double longitude, - double latitude, String displayTime, int wind, boolean tropical) { - this.name = name; - this.pressure = pressure; - location = new SurfaceObsLocation(name); - location.setLatitude(latitude); - location.setLongitude(longitude); - this.displayTime = displayTime; - this.windSpeed = wind; - this.tropical = tropical; - } + public TropicalCycloneSummary(String name, int pressure, double longitude, + double latitude, String displayTime, int wind, boolean tropical) { + this.name = name; + this.pressure = pressure; + location = new SurfaceObsLocation(name); + location.setLatitude(latitude); + location.setLongitude(longitude); + this.displayTime = displayTime; + this.windSpeed = wind; + this.tropical = tropical; + } - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * Set the data uri for this observation. - * - * @param dataURI - */ - @Override - public void setDataURI(String dataURI) { - super.setDataURI(dataURI); - identifier = dataURI; - } + /** + * Set the data uri for this observation. + * + * @param dataURI + */ + @Override + public void setDataURI(String dataURI) { + super.setDataURI(dataURI); + identifier = dataURI; + } - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } - @Override - public PointDataView getPointDataView() { - return pointDataView; - } + @Override + public PointDataView getPointDataView() { + return pointDataView; + } - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - public String getProductType() { - return productType; - } + public String getProductType() { + return productType; + } - public void setProductType(String productType) { - this.productType = productType; - } + public void setProductType(String productType) { + this.productType = productType; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public int getPressure() { - return pressure; - } + public int getPressure() { + return pressure; + } - public void setPressure(int pressure) { - this.pressure = pressure; - } + public void setPressure(int pressure) { + this.pressure = pressure; + } - public SurfaceObsLocation getLocation() { - return location; - } + public SurfaceObsLocation getLocation() { + return location; + } - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - public boolean isTropical() { - return tropical; - } + public boolean isTropical() { + return tropical; + } - public void setTropical(boolean tropical) { - this.tropical = tropical; - } + public void setTropical(boolean tropical) { + this.tropical = tropical; + } - public String getDisplayTime() { - return displayTime; - } + public String getDisplayTime() { + return displayTime; + } - public void setDisplayTime(String displayTime) { - this.displayTime = displayTime; - } + public void setDisplayTime(String displayTime) { + this.displayTime = displayTime; + } - public int getWindSpeed() { - return windSpeed; - } + public int getWindSpeed() { + return windSpeed; + } - public void setWindSpeed(int windSpeed) { - this.windSpeed = windSpeed; - } + public void setWindSpeed(int windSpeed) { + this.windSpeed = windSpeed; + } - public ArrayList getRadiusList() { - return radiusList; - } + public ArrayList getRadiusList() { + return radiusList; + } - public void setRadiusList(ArrayList radiusList) { - this.radiusList = radiusList; - } + public void setRadiusList(ArrayList radiusList) { + this.radiusList = radiusList; + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - Calendar c = getDataTime().getRefTimeAsCalendar(); - if (c != null) { - sb.append(String.format("TCS:%1$tY%1$tm%1$td%1$tH%1$tM", - getDataTime().getRefTimeAsCalendar())); - } else { - sb.append("TCS:YYYYMMDDHHmm"); - } - sb.append(String.format("%6.2f %7.2f:", getLatitude(), getLongitude())); - return sb.toString(); - } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Calendar c = getDataTime().getRefTimeAsCalendar(); + if (c != null) { + sb.append(String.format("TCS:%1$tY%1$tm%1$td%1$tH%1$tM", + getDataTime().getRefTimeAsCalendar())); + } else { + sb.append("TCS:YYYYMMDDHHmm"); + } + sb.append(String.format("%6.2f %7.2f:", getLatitude(), getLongitude())); + return sb.toString(); + } + + public String print() { + String s = ""; + s += "Display Time = " + displayTime + "\n"; + s += location.getLatitude() + ", " + location.getLongitude() + "\n"; + s += "Wind Speed = " + windSpeed + "\n"; + if (radiusList != null) { + for (Radius r : radiusList) { + s += r + "\n"; + } + } + return s; + } - public String print() { - String s = ""; - s += "Display Time = " + displayTime + "\n"; - s += location.getLatitude() + ", " + location.getLongitude() + "\n"; - s += "Wind Speed = " + windSpeed + "\n"; - if (radiusList != null) { - for (Radius r : radiusList) { - s += r + "\n"; - } - } - return s; - } @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "tcs"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.vaa/src/com/raytheon/uf/common/dataplugin/vaa/VAARecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.vaa/src/com/raytheon/uf/common/dataplugin/vaa/VAARecord.java index 0bacb09b39..b3d62641c8 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.vaa/src/com/raytheon/uf/common/dataplugin/vaa/VAARecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.vaa/src/com/raytheon/uf/common/dataplugin/vaa/VAARecord.java @@ -22,9 +22,9 @@ package com.raytheon.uf.common.dataplugin.vaa; import java.util.HashSet; import java.util.Set; -import javax.persistence.CascadeType; import javax.persistence.Access; import javax.persistence.AccessType; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; @@ -58,11 +58,13 @@ import com.vividsolutions.jts.geom.Geometry; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Nov 4, 2009 jkorman Initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Nov 04, 2009 jkorman Initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from - + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract + * * PluginDataObject. * * @@ -71,7 +73,6 @@ import com.vividsolutions.jts.geom.Geometry; * @version 1.0 */ - @Entity @SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "vaaseq") @Table(name = "vaa", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) @@ -79,20 +80,15 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "vaa", - indexes = { - @Index(name = "vaa_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "vaa", indexes = { @Index(name = "vaa_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public class VAARecord extends PluginDataObject implements - ISpatialEnabled { - +public class VAARecord extends PluginDataObject implements ISpatialEnabled { + private static final long serialVersionUID = 1L; - + @Embedded @DataURI(position = 1, embedded = true) @XmlElement @@ -106,7 +102,7 @@ public class VAARecord extends PluginDataObject implements @DataURI(position = 2) @XmlElement @DynamicSerializeElement - private String recordType; + private String recordType; /** * @@ -115,8 +111,8 @@ public class VAARecord extends PluginDataObject implements @DataURI(position = 3) @XmlElement @DynamicSerializeElement - private String advisoryNumber; - + private String advisoryNumber; + // Correction indicator from wmo header @DataURI(position = 4) @Column(length = 8) @@ -135,7 +131,7 @@ public class VAARecord extends PluginDataObject implements @Column(length = 2048) @XmlElement @DynamicSerializeElement - private String message; + private String message; /** * @@ -143,7 +139,7 @@ public class VAARecord extends PluginDataObject implements @Column(length = 512) @XmlElement @DynamicSerializeElement - private String anal00Hr; + private String anal00Hr; /** * @@ -151,7 +147,7 @@ public class VAARecord extends PluginDataObject implements @Column(length = 512) @XmlElement @DynamicSerializeElement - private String fcst06Hr; + private String fcst06Hr; /** * @@ -159,7 +155,7 @@ public class VAARecord extends PluginDataObject implements @Column(length = 512) @XmlElement @DynamicSerializeElement - private String fcst12Hr; + private String fcst12Hr; /** * @@ -167,8 +163,8 @@ public class VAARecord extends PluginDataObject implements @Column(length = 512) @XmlElement @DynamicSerializeElement - private String fcst18Hr; - + private String fcst18Hr; + // Text of the WMO header @Column(length = 64) @XmlElement @@ -180,21 +176,21 @@ public class VAARecord extends PluginDataObject implements @OneToMany(cascade = CascadeType.ALL, mappedBy = "parentId", fetch = FetchType.EAGER) private Set subParts = new HashSet(); - /** * Empty default constructor */ public VAARecord() { } - + /** * Construct an instance of this class using the supplied datauri. + * * @param dataUri */ public VAARecord(String dataUri) { super(dataUri); } - + /** * @return the corIndicator */ @@ -203,12 +199,13 @@ public class VAARecord extends PluginDataObject implements } /** - * @param corIndicator the corIndicator to set + * @param corIndicator + * the corIndicator to set */ public void setCorIndicator(String corIndicator) { this.corIndicator = corIndicator; } - + /** * @return the centerId */ @@ -217,7 +214,8 @@ public class VAARecord extends PluginDataObject implements } /** - * @param centerId the centerId to set + * @param centerId + * the centerId to set */ public void setCenterId(String centerId) { this.centerId = centerId; @@ -231,7 +229,8 @@ public class VAARecord extends PluginDataObject implements } /** - * @param wmoHeader the wmoHeader to set + * @param wmoHeader + * the wmoHeader to set */ public void setWmoHeader(String wmoHeader) { this.wmoHeader = wmoHeader; @@ -241,7 +240,7 @@ public class VAARecord extends PluginDataObject implements public IDecoderGettable getDecoderGettable() { return null; } - + @Override public SurfaceObsLocation getSpatialObject() { return location; @@ -254,7 +253,7 @@ public class VAARecord extends PluginDataObject implements public void setLocation(SurfaceObsLocation location) { this.location = location; } - + /** * Get this observation's geometry. * @@ -308,9 +307,7 @@ public class VAARecord extends PluginDataObject implements public Boolean getLocationDefined() { return location.getLocationDefined(); } - - - + /** * @return the recordType */ @@ -319,7 +316,8 @@ public class VAARecord extends PluginDataObject implements } /** - * @param recordType the recordType to set + * @param recordType + * the recordType to set */ public void setRecordType(String recordType) { this.recordType = recordType; @@ -333,7 +331,8 @@ public class VAARecord extends PluginDataObject implements } /** - * @param advisoryNumber the advisoryNumber to set + * @param advisoryNumber + * the advisoryNumber to set */ public void setAdvisoryNumber(String advisoryNumber) { this.advisoryNumber = advisoryNumber; @@ -347,7 +346,8 @@ public class VAARecord extends PluginDataObject implements } /** - * @param message the message to set + * @param message + * the message to set */ public void setMessage(String message) { this.message = message; @@ -361,7 +361,8 @@ public class VAARecord extends PluginDataObject implements } /** - * @param anal00Hr the anal00Hr to set + * @param anal00Hr + * the anal00Hr to set */ public void setAnal00Hr(String anal00Hr) { this.anal00Hr = anal00Hr; @@ -375,7 +376,8 @@ public class VAARecord extends PluginDataObject implements } /** - * @param fcst06Hr the fcst06Hr to set + * @param fcst06Hr + * the fcst06Hr to set */ public void setFcst06Hr(String fcst06Hr) { this.fcst06Hr = fcst06Hr; @@ -389,7 +391,8 @@ public class VAARecord extends PluginDataObject implements } /** - * @param fcst12Hr the fcst12Hr to set + * @param fcst12Hr + * the fcst12Hr to set */ public void setFcst12Hr(String fcst12Hr) { this.fcst12Hr = fcst12Hr; @@ -403,21 +406,21 @@ public class VAARecord extends PluginDataObject implements } /** - * @param fcst18Hr the fcst18Hr to set + * @param fcst18Hr + * the fcst18Hr to set */ public void setFcst18Hr(String fcst18Hr) { this.fcst18Hr = fcst18Hr; } public void addSubPart(VAASubPart part) { - if(subParts == null) { + if (subParts == null) { subParts = new HashSet(); } part.setParentId(this); subParts.add(part); } - - + /** * @return the subParts */ @@ -426,15 +429,16 @@ public class VAARecord extends PluginDataObject implements } /** - * @param subParts the subParts to set + * @param subParts + * the subParts to set */ public void setSubParts(Set subParts) { - for(VAASubPart p : subParts) { + for (VAASubPart p : subParts) { p.setParentId(this); } this.subParts = subParts; } - + /** * */ @@ -448,36 +452,35 @@ public class VAARecord extends PluginDataObject implements sb.append(","); sb.append(getLongitude()); sb.append("]"); - - + return sb.toString(); } - -// "\r\r\nVA ADVISORY" + -// "\r\r\nDTG: 20091104/1708Z" + -// "\r\r\nVAAC: WASHINGTON" + -// "\r\r\nVOLCANO: SOUFRIERE HILLS 1600-05" + -// "\r\r\nPSN: N1642 W06210" + -// "\r\r\nAREA: W_INDIES" + -// "\r\r\nSUMMIT ELEV: 3002 FT (915 M)" + -// "\r\r\nADVISORY NR: 2009/146" + -// "\r\r\nINFO SOURCE: GOES-12. GFS WINDS." + -// "\r\r\nERUPTION DETAILS: CONTINUOUS EMISSIONS" + -// "\r\r\nOBS VA DTG: 04/1645Z" + -// "\r\r\nOBS VA CLD: SFC/FL100 42NM WID LINE BTN N1638" + -// "\r\r\nW06611 - N1643 W06214. MOV W 7KT" + -// "\r\r\nFCST VA CLD +6HR: 04/2300Z SFC/FL100 40NM WID" + -// "\r\r\nLINE BTN N1640 W06614 - N1644 W06214." + -// "\r\r\nFCST VA CLD +12HR: 05/0500Z SFC/FL100 40NM WID" + -// "\r\r\nLINE BTN N1638 W06614 - N1643 W06214. SFC/FL100" + -// "\r\r\n40NM WID LINE BTN N1641 W06616 - N1643 W06214." + -// "\r\r\nFCST VA CLD +18HR: 05/1100Z" + -// "\r\r\nRMK: A SPREADING 42 NMI WIDE ASH PLUME MOVING AT" + -// "\r\r\nA MEASURED 7 KTS EXTENDS AT LEAST 211 NMI TO THE" + -// "\r\r\nWEST OF THE VOLCANO, OR TO ABOUT 66W. NO" + -// "\r\r\nSIGNIFICANT CHANGE IN DIRECTION OR SPEED IS" + -// "\r\r\nANTICIPATED DURING THE NEXT 12 HOURS. ...BALDWIN" + -// "\r\r\nNXT ADVISORY: WILL BE ISSUED BY 20091104/2315Z" + + + // "\r\r\nVA ADVISORY" + + // "\r\r\nDTG: 20091104/1708Z" + + // "\r\r\nVAAC: WASHINGTON" + + // "\r\r\nVOLCANO: SOUFRIERE HILLS 1600-05" + + // "\r\r\nPSN: N1642 W06210" + + // "\r\r\nAREA: W_INDIES" + + // "\r\r\nSUMMIT ELEV: 3002 FT (915 M)" + + // "\r\r\nADVISORY NR: 2009/146" + + // "\r\r\nINFO SOURCE: GOES-12. GFS WINDS." + + // "\r\r\nERUPTION DETAILS: CONTINUOUS EMISSIONS" + + // "\r\r\nOBS VA DTG: 04/1645Z" + + // "\r\r\nOBS VA CLD: SFC/FL100 42NM WID LINE BTN N1638" + + // "\r\r\nW06611 - N1643 W06214. MOV W 7KT" + + // "\r\r\nFCST VA CLD +6HR: 04/2300Z SFC/FL100 40NM WID" + + // "\r\r\nLINE BTN N1640 W06614 - N1644 W06214." + + // "\r\r\nFCST VA CLD +12HR: 05/0500Z SFC/FL100 40NM WID" + + // "\r\r\nLINE BTN N1638 W06614 - N1643 W06214. SFC/FL100" + + // "\r\r\n40NM WID LINE BTN N1641 W06616 - N1643 W06214." + + // "\r\r\nFCST VA CLD +18HR: 05/1100Z" + + // "\r\r\nRMK: A SPREADING 42 NMI WIDE ASH PLUME MOVING AT" + + // "\r\r\nA MEASURED 7 KTS EXTENDS AT LEAST 211 NMI TO THE" + + // "\r\r\nWEST OF THE VOLCANO, OR TO ABOUT 66W. NO" + + // "\r\r\nSIGNIFICANT CHANGE IN DIRECTION OR SPEED IS" + + // "\r\r\nANTICIPATED DURING THE NEXT 12 HOURS. ...BALDWIN" + + // "\r\r\nNXT ADVISORY: WILL BE ISSUED BY 20091104/2315Z" + @Override @Column @@ -485,4 +488,9 @@ public class VAARecord extends PluginDataObject implements public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "vaa"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.vil/src/com/raytheon/uf/common/dataplugin/vil/VILRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.vil/src/com/raytheon/uf/common/dataplugin/vil/VILRecord.java index 1fcf2e33ea..e190a15221 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.vil/src/com/raytheon/uf/common/dataplugin/vil/VILRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.vil/src/com/raytheon/uf/common/dataplugin/vil/VILRecord.java @@ -63,12 +63,14 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 1/14/09 2027 D. Hladky Initial release - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 04/08/13 #1293 bkowal Removed references to hdffileid. + * Jan 14, 2009 2027 D. Hladky Initial release + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -82,17 +84,13 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "vil", - indexes = { - @Index(name = "vil_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "vil", indexes = { @Index(name = "vil_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public class VILRecord extends PersistablePluginDataObject - implements ISpatialEnabled { +public class VILRecord extends PersistablePluginDataObject implements + ISpatialEnabled { private static final long serialVersionUID = 767763365671L; @@ -416,9 +414,9 @@ public class VILRecord extends PersistablePluginDataObject try { IDataRecord[] dataRec = dataStore.retrieve(getDataURI()); - for (int i = 0; i < dataRec.length; i++) { - if (dataRec[i] instanceof FloatDataRecord) { - setDataArray(((FloatDataRecord) dataRec[i]).getFloatData()); + for (IDataRecord element : dataRec) { + if (element instanceof FloatDataRecord) { + setDataArray(((FloatDataRecord) element).getFloatData()); } } } catch (Exception se) { @@ -493,4 +491,9 @@ public class VILRecord extends PersistablePluginDataObject public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "vil"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/AbstractWarningRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/AbstractWarningRecord.java index 2ecce321a9..3fcde57f96 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/AbstractWarningRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/AbstractWarningRecord.java @@ -52,7 +52,9 @@ import com.vividsolutions.jts.geom.Geometry; * 03/12/2007 1003 bwoodle initial creation * 04/12/2013 1857 bgonzale Added SequenceGenerator annotation. * 05/02/2013 1949 rjpeter Moved ugcZones to be a column inside table. - * 08/08/2013 2243 jsanchez Removed super method in copy constructor. + * Aug 08, 2013 2243 jsanchez Removed super method in copy + * constructor. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author bwoodle @@ -246,7 +248,6 @@ public abstract class AbstractWarningRecord extends PluginDataObject { this.setMotspd(old.getMotspd()); this.setPil(old.getPil()); this.setPhensig(old.getPhensig()); - this.setPluginName(old.getPluginName()); this.setRawmessage(old.getRawmessage()); this.setSeg(old.getSeg()); this.setTraceId(old.getTraceId()); diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/PracticeWarningRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/PracticeWarningRecord.java index c4ede7e9b4..347210ad33 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/PracticeWarningRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/PracticeWarningRecord.java @@ -41,13 +41,15 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 10/04/2011 10049 bgonzale initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime + * Oct 04, 2011 10049 bgonzale initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 02, 2013 1949 rjpeter Removed ugcZones. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author bgonzale @@ -104,4 +106,9 @@ public class PracticeWarningRecord extends AbstractWarningRecord { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "practicewarning"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/WarningRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/WarningRecord.java index aa8859a38e..fa5549c219 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/WarningRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/WarningRecord.java @@ -44,12 +44,14 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 03/12/2007 1003 bwoodle initial creation - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime + * Mar 12, 2007 1003 bwoodle initial creation + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 02, 2013 1949 rjpeter Removed ugcZones. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author bwoodle @@ -166,4 +168,9 @@ public class WarningRecord extends AbstractWarningRecord { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "warning"; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/PluginDataObject.java b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/PluginDataObject.java index 52f74e4406..b1a22cadd5 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/PluginDataObject.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/PluginDataObject.java @@ -102,6 +102,7 @@ import com.raytheon.uf.common.time.DataTime; * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * */ @@ -123,12 +124,6 @@ public abstract class PluginDataObject extends PersistableDataObject implements @Id protected int id; - /** The name of the plugin this object is associated with */ - @Transient - @XmlAttribute - @DynamicSerializeElement - protected String pluginName; - /** The data time for this record */ @Embedded @XmlElement @@ -190,7 +185,7 @@ public abstract class PluginDataObject extends PersistableDataObject implements } public String getDataURI() { - if (dataURI == null && pluginName != null) { + if (dataURI == null) { try { this.dataURI = DataURIUtil.createDataURI(this); } catch (PluginException e) { @@ -230,13 +225,7 @@ public abstract class PluginDataObject extends PersistableDataObject implements this.messageData = messageData; } - public String getPluginName() { - return pluginName; - } - - public void setPluginName(String pluginName) { - this.pluginName = pluginName; - } + public abstract String getPluginName(); public void setDataTime(DataTime dataTime) { this.dataTime = dataTime; @@ -325,11 +314,13 @@ public abstract class PluginDataObject extends PersistableDataObject implements return false; } + String pluginName = getPluginName(); + String rhsPluginName = rhs.getPluginName(); if (pluginName == null) { - if (rhs.pluginName != null) { + if (rhsPluginName != null) { return false; } - } else if (!pluginName.equals(rhs.pluginName)) { + } else if (!pluginName.equals(rhsPluginName)) { return false; } @@ -340,14 +331,16 @@ public abstract class PluginDataObject extends PersistableDataObject implements public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + result = (prime * result) + ((dataTime == null) ? 0 : dataTime.hashCode()); - result = prime * result - + ((getDataURI() == null) ? 0 : dataURI.hashCode()); - result = prime * result + id; - result = prime * result + String dataUri = getDataURI(); + result = (prime * result) + + ((dataUri == null) ? 0 : dataURI.hashCode()); + result = (prime * result) + id; + result = (prime * result) + ((insertTime == null) ? 0 : insertTime.hashCode()); - result = prime * result + String pluginName = getPluginName(); + result = (prime * result) + ((pluginName == null) ? 0 : pluginName.hashCode()); return result; } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/annotations/DataURIUtil.java b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/annotations/DataURIUtil.java index 1c96cbf508..7bd40cbdcf 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/annotations/DataURIUtil.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/annotations/DataURIUtil.java @@ -54,6 +54,7 @@ import com.raytheon.uf.common.util.ConvertUtil; * from PluginDataObject * May 15, 2013 1869 bsteffen Move uri map creation from RecordFactory. * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract and removed setPluginName. * * * @@ -66,6 +67,9 @@ public class DataURIUtil { private static final String FIELD_SEPARATOR = "."; + private static final Pattern FIELD_SEPARATOR_PATTERN = Pattern.compile("[" + + FIELD_SEPARATOR + "]"); + private static final Pattern SEPARATOR_PATTERN = Pattern .compile(DataURI.SEPARATOR); @@ -165,7 +169,7 @@ public class DataURIUtil { throws PluginException { List tokens = tokenizeURI(dataURI); Map dataMap = new HashMap( - (int) (tokens.size() / 0.75f + 1), 0.75f); + (int) ((tokens.size() / 0.75f) + 1), 0.75f); String pluginName = tokens.get(0); tokens = tokens.subList(1, tokens.size()); dataMap.put(PLUGIN_NAME_KEY, pluginName); @@ -246,7 +250,6 @@ public class DataURIUtil { */ public static void populatePluginDataObject(PluginDataObject pdo, Map dataMap) throws PluginException { - pdo.setPluginName(dataMap.get(PLUGIN_NAME_KEY).toString()); populateObject(pdo, dataMap); } @@ -275,7 +278,7 @@ public class DataURIUtil { throws PluginException { DataURIFieldAccess[] accessArray = getAccess(object.getClass()); Map dataMap = new HashMap( - (int) (accessArray.length / 0.75f + 2), 0.75f); + (int) ((accessArray.length / 0.75f) + 2), 0.75f); if (object instanceof PluginDataObject) { dataMap.put(PLUGIN_NAME_KEY, ((PluginDataObject) object).getPluginName()); @@ -300,14 +303,19 @@ public class DataURIUtil { accessMap.put(access.getFieldName(), access); } for (String dataKey : dataMap.keySet()) { - Object data = dataMap.get(dataKey); - DataURIFieldAccess access = accessMap.get(dataKey); - if (access == null) { - access = new DataURIFieldAccess(Arrays.asList(dataKey.split("[" - + FIELD_SEPARATOR + "]")), - object != null ? object.getClass() : null); + if (!PLUGIN_NAME_KEY.equals(dataKey)) { + Object data = dataMap.get(dataKey); + DataURIFieldAccess access = accessMap.get(dataKey); + if (access == null) { + + access = new DataURIFieldAccess( + Arrays.asList(FIELD_SEPARATOR_PATTERN + .split(dataKey)), + object != null ? object.getClass() : null); + } + + access.setFieldValue(object, data); } - access.setFieldValue(object, data); } } @@ -316,7 +324,6 @@ public class DataURIUtil { */ private static void populatePluginDataObject(PluginDataObject pdo, List uriTokens) throws PluginException { - pdo.setPluginName(uriTokens.get(0)); uriTokens = uriTokens.subList(1, uriTokens.size()); DataURIFieldAccess[] access = getAccess(pdo.getClass()); for (int i = 0; i < access.length; i += 1) { @@ -471,7 +478,7 @@ public class DataURIUtil { throws PluginException { Object source = pdo; try { - for (int i = 0; i < fieldNames.length - 1; i += 1) { + for (int i = 0; i < (fieldNames.length - 1); i += 1) { Object obj = PropertyUtils.getProperty(source, fieldNames[i]); if (obj == null) { diff --git a/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/msgs/GetServersResponse.java b/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/msgs/GetServersResponse.java index e78f3542cd..6b5d6db970 100644 --- a/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/msgs/GetServersResponse.java +++ b/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/msgs/GetServersResponse.java @@ -37,6 +37,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Aug 6, 2009 mschenke Initial creation * Sep 12, 2012 1167 djohnson Add datadelivery servers. * Jan 14, 2013 1469 bkowal Removed the hdf5 data directory + * Aug 27, 2013 2995 bkowal Removed jms server; added jms connection string * * * @@ -50,7 +51,7 @@ public class GetServersResponse implements ISerializableObject { private String httpServer; @DynamicSerializeElement - private String jmsServer; + private String jmsConnectionString; @DynamicSerializeElement private String pypiesServer; @@ -66,12 +67,12 @@ public class GetServersResponse implements ISerializableObject { this.httpServer = httpServer; } - public String getJmsServer() { - return jmsServer; + public String getJmsConnectionString() { + return jmsConnectionString; } - public void setJmsServer(String jmsServer) { - this.jmsServer = jmsServer; + public void setJmsConnectionString(String jmsConnectionString) { + this.jmsConnectionString = jmsConnectionString; } public String getPypiesServer() { diff --git a/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/header/WMOHeaderFinder.java b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/header/WMOHeaderFinder.java index 4e29123be7..2828dd0563 100644 --- a/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/header/WMOHeaderFinder.java +++ b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/header/WMOHeaderFinder.java @@ -37,8 +37,8 @@ import java.util.regex.Pattern; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jul 27, 2012 mschenke Initial creation - * + * Jul 27, 2012 mschenke Initial creation + * Sep 09, 2013 2327 rjpeter Updated to allow pattern to be used again. Added capture for DTG * * * @author mschenke @@ -46,10 +46,9 @@ import java.util.regex.Pattern; */ public class WMOHeaderFinder { - - private static Pattern WMOPATTERN = Pattern - .compile("([A-Z]{3}[A-Z0-9](\\d{0,2}|[A-Z]{0,2}) [A-Z0-9 ]{4} " - + "\\d{6}[^\\r\\n]*)[\\r\\n]+"); + private static final Pattern WMOPATTERN = Pattern + .compile("([A-Z]{3}[A-Z0-9](?:\\d{0,2}|[A-Z]{0,2}) [A-Z0-9 ]{4} " + + "(\\d{6})[^\\r\\n]*)[\\r\\n]*"); /** * Finds and returns the WMO header on the {@link File} @@ -99,4 +98,21 @@ public class WMOHeaderFinder { in.close(); } } + + /** + * Returns the Date Time Group associated with a WMO Header + * + * @param header + * @return + */ + public static String findDtg(String header) { + String dtg = null; + Matcher matcher = WMOPATTERN.matcher(header); + + if (matcher.matches()) { + dtg = matcher.group(2); + } + + return dtg; + } } diff --git a/edexOsgi/com.raytheon.uf.edex.archive/.classpath b/edexOsgi/com.raytheon.uf.edex.archive/.classpath index a6f75277ac..4158707b64 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/.classpath +++ b/edexOsgi/com.raytheon.uf.edex.archive/.classpath @@ -1,8 +1,8 @@ - - - - - + + + + + diff --git a/edexOsgi/com.raytheon.uf.edex.archive/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.archive/META-INF/MANIFEST.MF index d6df454102..dd531b7090 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.edex.archive/META-INF/MANIFEST.MF @@ -6,4 +6,12 @@ Bundle-Version: 1.0.0.qualifier Bundle-Vendor: RAYTHEON Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Export-Package: com.raytheon.uf.edex.archive.purge -Import-Package: com.raytheon.uf.common.archive.config +Import-Package: com.raytheon.uf.common.archive.config, + com.raytheon.uf.common.archive.request +Require-Bundle: com.raytheon.uf.common.auth;bundle-version="1.12.1174", + com.raytheon.uf.edex.auth;bundle-version="1.12.1174", + com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174", + com.raytheon.uf.common.status;bundle-version="1.12.1174", + com.raytheon.uf.common.serialization;bundle-version="1.12.1174", + com.raytheon.uf.common.util;bundle-version="1.12.1174", + com.raytheon.uf.common.localization;bundle-version="1.12.1174" diff --git a/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archiveadmim-request.xml b/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archiveadmim-request.xml new file mode 100644 index 0000000000..7b1cc0cfa5 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archiveadmim-request.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties b/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties new file mode 100644 index 0000000000..9b9705e607 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties @@ -0,0 +1,6 @@ +# runs database and hdf5 archive for archive server to pull data from +archive.cron=0+40+*+*+*+? +# purge archives +archive.purge.cron=0+5+*+*+*+? +# enable archive purge +archive.purge.enable=false diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java index af69b267eb..3802050faa 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java @@ -19,7 +19,6 @@ **/ package com.raytheon.uf.edex.archive.purge; -import java.io.File; import java.util.Collection; import com.raytheon.uf.common.archive.config.ArchiveConfig; @@ -39,6 +38,9 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * ------------ ---------- ----------- -------------------------- * May 6, 2013 1965 bgonzale Initial creation * Added info logging for purge counts. + * Aug 28, 2013 2299 rferrel manager.purgeExpiredFromArchive now returns + * number of files purged. + * Sep 03, 2013 2224 rferrel Add check to enable/disable purger. * * * @@ -48,28 +50,34 @@ import com.raytheon.uf.common.status.UFStatus.Priority; public class ArchivePurger { private final static IUFStatusHandler statusHandler = UFStatus - .getHandler(ArchiveConfigManager.class); + .getHandler(ArchivePurger.class); + + private final static String ENABLE_PROPERTY = "archive.purge.enable"; /** * Purge expired elements from the archives. */ public static void purge() { - ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); - Collection archives = manager.getArchives(); - for (ArchiveConfig archive : archives) { - Collection deletedFiles = manager - .purgeExpiredFromArchive(archive); - if (statusHandler.isPriorityEnabled(Priority.INFO)) { - StringBuilder sb = new StringBuilder(archive.getName()); - sb.append("::Archive Purged "); - sb.append(deletedFiles.size()); - sb.append(" file"); - if (deletedFiles.size() != 1) { - sb.append("s"); + String enableString = System.getProperty(ENABLE_PROPERTY, "false"); + if (Boolean.parseBoolean(enableString)) { + statusHandler.info("::Archive Purged started."); + ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); + Collection archives = manager.getArchives(); + for (ArchiveConfig archive : archives) { + int purgeCount = manager.purgeExpiredFromArchive(archive); + if (statusHandler.isPriorityEnabled(Priority.INFO)) { + StringBuilder sb = new StringBuilder(archive.getName()); + sb.append("::Archive Purged "); + sb.append(purgeCount); + sb.append(" file"); + if (purgeCount != 1) { + sb.append("s"); + } + sb.append("."); + statusHandler.info(sb.toString()); } - sb.append("."); - statusHandler.info(sb.toString()); } + statusHandler.info("::Archive Purged finished."); } } } diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/useradmin/ArchiveAdminPrivilegedRequestHandler.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/useradmin/ArchiveAdminPrivilegedRequestHandler.java new file mode 100644 index 0000000000..7d68c406ff --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/useradmin/ArchiveAdminPrivilegedRequestHandler.java @@ -0,0 +1,98 @@ +/** + * 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.archive.useradmin; + +import com.raytheon.uf.common.archive.request.ArchiveAdminAuthRequest; +import com.raytheon.uf.common.auth.exception.AuthorizationException; +import com.raytheon.uf.common.auth.user.IUser; +import com.raytheon.uf.edex.auth.AuthManager; +import com.raytheon.uf.edex.auth.AuthManagerFactory; +import com.raytheon.uf.edex.auth.req.AbstractPrivilegedRequestHandler; +import com.raytheon.uf.edex.auth.resp.AuthorizationResponse; +import com.raytheon.uf.edex.auth.roles.IRoleStorage; + +/** + * Handler for Archive Admin Privileged Requests. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Oct 02, 2013  2326      rferrel     Initial creation.
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public class ArchiveAdminPrivilegedRequestHandler extends + AbstractPrivilegedRequestHandler { + + /** + * Application name. This must match the application tag in the user role + * file. + */ + private static final String APPLICATION = "Data Archiving"; + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest + * (com.raytheon.uf.common.serialization.comm.IServerRequest) + */ + @Override + public ArchiveAdminAuthRequest handleRequest(ArchiveAdminAuthRequest request) + throws Exception { + // If it reaches this point in the code, then the user is authorized, so + // just return the request object with authorized set to true + request.setAuthorized(true); + return request; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.edex.auth.req.AbstractPrivilegedRequestHandler#authorized + * (com.raytheon.uf.common.auth.user.IUser, + * com.raytheon.uf.common.auth.req.AbstractPrivilegedRequest) + */ + @Override + public AuthorizationResponse authorized(IUser user, + ArchiveAdminAuthRequest request) throws AuthorizationException { + + AuthManager manager = AuthManagerFactory.getInstance().getManager(); + IRoleStorage roleStorage = manager.getRoleStorage(); + + boolean authorized = roleStorage.isAuthorized((request).getRoleId(), + user.uniqueId().toString(), APPLICATION); + + if (authorized) { + return new AuthorizationResponse(authorized); + } else { + return new AuthorizationResponse( + (request).getNotAuthorizedMessage()); + } + } +} diff --git a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml index 7ec34bdc8a..6376546ab5 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml +++ b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml @@ -24,43 +24,62 @@ * Date Ticket# Engineer Description * ============ ========== =========== ========================== * Jun 20, 2013 1966 rferrel Initial creation + * Aug 05, 2013 2224 rferrel Changes to add dataSet tags. + * Oct 01, 2013 2147 rfrrel Date time stamp no longer requires an hour field. * * @author rferrel * @version 1.0 --> + (mcidas|viirs)/.*/.*/.*/.* + .*-(\d{4})-(\d{2})-(\d{2})-(\d{2}).* + 2,3,4,5 + {1} + - Sounding + Profiles 168 - (acarssounding|bufrua|goessounding|poessounding|profiler|raobs) - {1} - 2,3,4,5 - [^/]*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* - - - ModelSounding - 168 - (modelsounding)/(.*) - (bufrmos)(.*) - {1} - {2} - 3,4,5,6 - .*(\d{4})-(\d{2})-(\d{2})[-_](\d{2}).* + + (acarssounding|bufrua|goessounding|poessounding|profiler) + {1} + 2,3,4,5 + .*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* + + radar 168 - radar/(.*)/(.*) - {1} - 3,4,5,6 - .*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* + + radar/(.*)/(.*) + {1} + 3,4,5,6 + .*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* + diff --git a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml index 88308bd6ed..5b7eb5cd63 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml +++ b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml @@ -24,43 +24,62 @@ * Date Ticket# Engineer Description * ============ ========== =========== ========================== * Jun 20, 2013 1966 rferrel Initial creation + * Aug 05, 2013 2224 rferrel Changes to add dataSet tags. + * Oct 01, 2013 2147 rfrrel Date time stamp no longer requires an hour field. * * @author rferrel * @version 1.0 --> + + + This permission allows the user to access Archive Retention. + + + + + + This permission allows the user to access Archive Case Creation. + + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.base.feature/feature.xml b/edexOsgi/com.raytheon.uf.edex.base.feature/feature.xml index 86abdf2f3c..547e059577 100644 --- a/edexOsgi/com.raytheon.uf.edex.base.feature/feature.xml +++ b/edexOsgi/com.raytheon.uf.edex.base.feature/feature.xml @@ -183,4 +183,10 @@ install-size="0" version="0.0.0"/> + + diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterLockUtils.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterLockUtils.java index 94fd35a7e5..55b6439c83 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterLockUtils.java +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterLockUtils.java @@ -48,6 +48,8 @@ import com.raytheon.uf.edex.database.dao.DaoConfig; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 28, 2010 #5050 rjpeter Initial creation from SmartInitTransaction. + * Aug 26, 2013 #2272 bkowal Add a function to see if a cluster suffix has + * been specified via the environment. * * * @@ -55,6 +57,16 @@ import com.raytheon.uf.edex.database.dao.DaoConfig; * @version 1.0 */ public class ClusterLockUtils { + /* + * An optional context suffix can be included in an EDEX properties file. + * This suffix will be appended to the details of each cluster task. + */ + public static final String CLUSTER_SUFFIX; + + static { + CLUSTER_SUFFIX = System.getProperty("cluster.suffix") != null ? "-" + + System.getProperty("cluster.suffix") : ""; + } public enum LockState { SUCCESSFUL, ALREADY_RUNNING, FAILED, OLD; diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/handlers/DbQueryHandler.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/handlers/DbQueryHandler.java index e41bc25a6e..ec8d93c7f7 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/handlers/DbQueryHandler.java +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/handlers/DbQueryHandler.java @@ -24,7 +24,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataquery.db.QueryParam; import com.raytheon.uf.common.dataquery.db.QueryParam.QueryOperand; import com.raytheon.uf.common.dataquery.db.ReturnedField; @@ -49,8 +48,9 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 21, 2010 mschenke Initial creation + * Jan 21, 2010 mschenke Initial creation * Mar 19, 2013 1807 rferrel OrderBy now performed. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -179,10 +179,7 @@ public class DbQueryHandler implements IRequestHandler { if (row == null) { continue; } - if (fields == null || fields.size() == 0) { - if (row instanceof PluginDataObject) { - ((PluginDataObject) row).setPluginName(pluginName); - } + if ((fields == null) || (fields.size() == 0)) { objectMap.put(null, row); } else if (fields.size() == 1) { objectMap.put(fields.get(0).field, row); diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java index 38d7bf69e1..6c7d2e2858 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java @@ -112,6 +112,7 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery; * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Oct 07, 2013 2392 rjpeter Updated to pass null productKeys as actual null instead of string null. * * @@ -360,8 +361,8 @@ public abstract class PluginDao extends CoreDao { Boolean hasDataURIColumn = pluginDataURIColumn.get(pdoClazz); if (!Boolean.FALSE.equals(hasDataURIColumn)) { try { - getSessionFactory().getClassMetadata(pdoClazz) - .getPropertyType("dataURI"); + getSessionFactory().getClassMetadata(pdoClazz).getPropertyType( + "dataURI"); criteria.add(Restrictions.eq("dataURI", pdo.getDataURI())); return; } catch (QueryException e) { @@ -633,7 +634,6 @@ public abstract class PluginDao extends CoreDao { throws PluginException { PluginDataObject[] queryResults = getMetadata(query); for (PluginDataObject obj : queryResults) { - obj.setPluginName(pluginName); obj.setMessageData(getHDF5Data(obj, tile)); } return queryResults; @@ -846,7 +846,7 @@ public abstract class PluginDao extends CoreDao { long dateTimeAsLong = timeToCompare.getTime(); if (rule.isDeltaTimeMultiple()) { - if (dateTimeAsLong % delta == 0) { + if ((dateTimeAsLong % delta) == 0) { // If the versions to keep is zero we keep it if // it does not exceed the period specified, if // any @@ -1610,7 +1610,8 @@ public abstract class PluginDao extends CoreDao { } private Date roundDateToHour(Date dateToRound) { - return new Date(dateToRound.getTime() - dateToRound.getTime() % 3600000); + return new Date(dateToRound.getTime() + - (dateToRound.getTime() % 3600000)); } /** @@ -1754,7 +1755,7 @@ public abstract class PluginDao extends CoreDao { // remove .h5 int index = path.lastIndexOf('.'); - if ((index > 0) && (path.length() - index < 5)) { + if ((index > 0) && ((path.length() - index) < 5)) { // ensure its end of string in case extension is // dropped/changed path = path.substring(0, index); @@ -1818,7 +1819,7 @@ public abstract class PluginDao extends CoreDao { } protected void updateRate(float rate) { - cumulativeRate = (rate + cumulativeRate * total) / (total + 1); + cumulativeRate = (rate + (cumulativeRate * total)) / (total + 1); duplicateCheck = cumulativeRate < DUPLICATE_CHECK_THRESHOLD; if (total < DUPLICATE_MEMORY) { diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.feature/feature.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.feature/feature.xml index 6aa5e8f2f2..1d0fbaeb17 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.feature/feature.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.feature/feature.xml @@ -121,4 +121,11 @@ version="0.0.0" unpack="false"/> + + diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.harvester/res/spring/harvester-datadelivery.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.harvester/res/spring/harvester-datadelivery.xml index 15d153514a..d231a27f79 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.harvester/res/spring/harvester-datadelivery.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.harvester/res/spring/harvester-datadelivery.xml @@ -2,8 +2,13 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> + + + + - + diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/util/ResponseProcessingUtilities.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/util/ResponseProcessingUtilities.java index 22c66bd081..e145ca8280 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/util/ResponseProcessingUtilities.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/util/ResponseProcessingUtilities.java @@ -46,9 +46,12 @@ import com.raytheon.uf.common.time.DataTime; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jan 07, 2011 dhladky Initial creation - * Aug 20, 2012 0743 djohnson Fix cache lookup to use the model name and not hashcode. - * Nov 19, 2012 1166 djohnson Clean up JAXB representation of registry objects. - * Jan 30, 2013 1543 djohnson Log exception stacktrace. + * Aug 20, 2012 0743 djohnson Fix cache lookup to use the model name + * and not hashcode. + * Nov 19, 2012 1166 djohnson Clean up JAXB representation of registry + * objects. + * Jan 30, 2013 1543 djohnson Log exception stacktrace. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -62,8 +65,7 @@ public class ResponseProcessingUtilities { .getHandler(ResponseProcessingUtilities.class); public static GridRecord getGridRecord(String name, Parameter parm, - Level level, String ensembleId, - GridCoverage gridCoverage) { + Level level, String ensembleId, GridCoverage gridCoverage) { com.raytheon.uf.common.parameter.Parameter parameter = new com.raytheon.uf.common.parameter.Parameter(); parameter.setAbbreviation(parm.getName()); @@ -71,7 +73,6 @@ public class ResponseProcessingUtilities { parameter.setUnitString(parm.getUnits()); GridRecord record = new GridRecord(); - record.setPluginName("grid"); record.setLocation(gridCoverage); record.setLevel(level); record.setParameter(parameter); @@ -160,8 +161,8 @@ public class ResponseProcessingUtilities { for (int index = startLevel; index <= endLevel; index++) { double levelOneValue = plevels.getLevelAt(index); - String masterLevelName = LevelType - .getLevelTypeIdName(plevels.getLevelType()); + String masterLevelName = LevelType.getLevelTypeIdName(plevels + .getLevelType()); MasterLevel masterLevel = LevelFactory.getInstance() .getMasterLevel(masterLevelName); Level level = LevelFactory.getInstance().getLevel( diff --git a/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/core/filterimpl/PluginDataObjectFilter.java b/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/core/filterimpl/PluginDataObjectFilter.java index efd6eb6d43..10ad340aad 100644 --- a/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/core/filterimpl/PluginDataObjectFilter.java +++ b/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/core/filterimpl/PluginDataObjectFilter.java @@ -21,16 +21,13 @@ package com.raytheon.uf.edex.decodertools.core.filterimpl; import static com.raytheon.uf.common.localization.LocalizationContext.LocalizationType.EDEX_STATIC; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; @@ -44,8 +41,8 @@ import com.raytheon.uf.common.geospatial.ISpatialEnabled; import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext; -import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; @@ -59,6 +56,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jul 16, 2009 jkorman Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -73,10 +71,10 @@ public class PluginDataObjectFilter extends AbstractObsFilter { private static final String ERROR_1_FMT = "Could not create {%s} context for file \"%s\""; private static final String ERROR_2_FMT = "File %s does not exist"; - + public static final String FILTERS_DIR = "plugin-filters"; - - private Log logger = LogFactory.getLog(getClass()); + + private final Log logger = LogFactory.getLog(getClass()); private String filterConfigFile = null; @@ -87,11 +85,12 @@ public class PluginDataObjectFilter extends AbstractObsFilter { filterConfigFile = configFile; try { File filterDir = null; - + IPathManager manager = PathManagerFactory.getPathManager(); - if(manager != null) { - LocalizationContext context = manager.getContext(EDEX_STATIC, LocalizationLevel.valueOf(localContext)); - if(context != null) { + if (manager != null) { + LocalizationContext context = manager.getContext(EDEX_STATIC, + LocalizationLevel.valueOf(localContext)); + if (context != null) { filterDir = manager.getFile(context, FILTERS_DIR); if (filterDir.exists()) { File srcFile = new File(filterDir, filterConfigFile); @@ -111,22 +110,24 @@ public class PluginDataObjectFilter extends AbstractObsFilter { } catch (IOException e) { logger.error("Unable to read filter config", e); } catch (JAXBException e) { - logger.error("Unable to unmarshall filter config", e); + logger.error("Unable to unmarshall filter config", + e); } } else { - logger.error(String.format(ERROR_2_FMT,filterDir.getPath())); + logger.error(String.format(ERROR_2_FMT, + filterDir.getPath())); createDummyFilter(); } } else { - logger.error(String.format(ERROR_1_FMT, localContext,configFile)); + logger.error(String.format(ERROR_1_FMT, localContext, + configFile)); createDummyFilter(); } } else { // Could not create PathManager } } catch (Exception e) { - logger.error( - "Error creating filter.", e); + logger.error("Error creating filter.", e); createDummyFilter(); } logger.info("Filter name = " + getFilterName()); @@ -144,24 +145,27 @@ public class PluginDataObjectFilter extends AbstractObsFilter { int reportCount = 0; if (reports != null) { - for (int i = 0; i < reports.length; i++) { PluginDataObject r = null; boolean keep = true; for (AbstractFilterElement element : filterElements) { r = element.filter(reports[i]); - - // Only allow keep to be set to true. Once true it stays that way. - if(AbstractObsFilter.INCLUDE_TYPE.equals(element.getFilterType())) { + + // Only allow keep to be set to true. Once true it stays + // that way. + if (AbstractObsFilter.INCLUDE_TYPE.equals(element + .getFilterType())) { // Did the filter pass? - if(r == null) { - // If we fail an element, exit now. + if (r == null) { + // If we fail an element, exit now. keep = false; break; } - } else if(AbstractObsFilter.EXCLUDE_TYPE.equals(element.getFilterType())) { - if(r != null) { - // There was a match, so we want to remove this item. + } else if (AbstractObsFilter.EXCLUDE_TYPE.equals(element + .getFilterType())) { + if (r != null) { + // There was a match, so we want to remove this + // item. keep = false; // And there's no reason for further checks. break; @@ -220,30 +224,37 @@ public class PluginDataObjectFilter extends AbstractObsFilter { return fis; } - private static class TestObject extends PluginDataObject implements ISpatialEnabled { + private static class TestObject extends PluginDataObject implements + ISpatialEnabled { private static final long serialVersionUID = 1L; SurfaceObsLocation location; - + @Override public IDecoderGettable getDecoderGettable() { return null; } - + @Override public ISpatialObject getSpatialObject() { return location; } - + + @Override public String toString() { return location.getStationId() + " Passed"; } + + @Override + public String getPluginName() { + return "test"; + } } - - public static final void main(String [] args) { - - RadiusFilterElement element = new RadiusFilterElement(0,0,60); + + public static final void main(String[] args) { + + RadiusFilterElement element = new RadiusFilterElement(0, 0, 60); element.setFilterType("INCLUDE"); TestObject p = new TestObject(); @@ -257,26 +268,26 @@ public class PluginDataObjectFilter extends AbstractObsFilter { p.location.assignLocation(.7, .7); p = (TestObject) element.filter(p); System.out.println((p == null) ? "failed" : p); - + // Southeast corner of OAX WFO - element = new RadiusFilterElement(40,-94.90,100); + element = new RadiusFilterElement(40, -94.90, 100); element.setFilterType("INCLUDE"); p = new TestObject(); p.location = new SurfaceObsLocation("2.1"); - p.location.assignLocation(38.78, -97.65); // KSLN 38 47N 097 39W + p.location.assignLocation(38.78, -97.65); // KSLN 38 47N 097 39W p = (TestObject) element.filter(p); System.out.println((p == null) ? p : "failed"); p = new TestObject(); p.location = new SurfaceObsLocation("2.2"); - p.location.assignLocation(39.13, -96.68); // KMHK 39 08N 096 41W + p.location.assignLocation(39.13, -96.68); // KMHK 39 08N 096 41W p = (TestObject) element.filter(p); System.out.println((p != null) ? p : "failed"); - + // Test set 3 PluginDataObjectFilter filter = new PluginDataObjectFilter(); - element = new RadiusFilterElement(40,-94.90,100); + element = new RadiusFilterElement(40, -94.90, 100); element.setFilterType("INCLUDE"); filter.addFilterElement(element); @@ -288,55 +299,55 @@ public class PluginDataObjectFilter extends AbstractObsFilter { e.setLowerRightLon(-94.90); e.setFilterType("INCLUDE"); filter.addFilterElement(e); - - PluginDataObject [] pp = new PluginDataObject [3]; + + PluginDataObject[] pp = new PluginDataObject[3]; p = new TestObject(); p.location = new SurfaceObsLocation("KSLN"); - p.location.assignLocation(38.78, -97.65); // KSLN 38 47N 097 39W + p.location.assignLocation(38.78, -97.65); // KSLN 38 47N 097 39W pp[0] = p; p = new TestObject(); p.location = new SurfaceObsLocation("KMHK"); - p.location.assignLocation(39.13, -96.68); // KMHK 39 08N 096 41W + p.location.assignLocation(39.13, -96.68); // KMHK 39 08N 096 41W pp[1] = p; p = new TestObject(); p.location = new SurfaceObsLocation("KSTJ"); p.location.assignLocation(41, -96.00); pp[2] = p; - + pp = filter.filter(pp); - + System.out.println("----------------------------------"); System.out.println("- Success = KSTJ"); System.out.println("----------"); - for(PluginDataObject o : pp) { + for (PluginDataObject o : pp) { System.out.println(o); } - + // Test set 4 - pp = new PluginDataObject [4]; + pp = new PluginDataObject[4]; p = new TestObject(); p.location = new SurfaceObsLocation("KORD"); - p.location.assignLocation(38.78, -97.65); // KSLN 38 47N 097 39W + p.location.assignLocation(38.78, -97.65); // KSLN 38 47N 097 39W pp[0] = p; - + p = new TestObject(); p.location = new SurfaceObsLocation("KSLN"); - p.location.assignLocation(38.78, -97.65); // KSLN 38 47N 097 39W + p.location.assignLocation(38.78, -97.65); // KSLN 38 47N 097 39W pp[1] = p; p = new TestObject(); p.location = new SurfaceObsLocation("KMHK"); - p.location.assignLocation(39.13, -96.68); // KMHK 39 08N 096 41W + p.location.assignLocation(39.13, -96.68); // KMHK 39 08N 096 41W pp[2] = p; p = new TestObject(); p.location = new SurfaceObsLocation("KSTJ"); p.location.assignLocation(41, -96.00); pp[3] = p; - + filter = new PluginDataObjectFilter(); StationIdFilterElement s = new StationIdFilterElement(); @@ -345,10 +356,10 @@ public class PluginDataObjectFilter extends AbstractObsFilter { s.setFilterType(INCLUDE_TYPE); filter.addFilterElement(s); -// s = new StationIdFilterElement(); -// s.addPattern("KM[HIJ]K"); -// s.setFilterType(EXCLUDE_TYPE); -// filter.addFilterElement(s); + // s = new StationIdFilterElement(); + // s.addPattern("KM[HIJ]K"); + // s.setFilterType(EXCLUDE_TYPE); + // filter.addFilterElement(s); e = new RectFilterElement(); e.setUpperLeftLat(42.90); @@ -359,36 +370,14 @@ public class PluginDataObjectFilter extends AbstractObsFilter { e.setFilterType("INCLUDE"); filter.addFilterElement(e); - - - - pp = filter.filter(pp); - + System.out.println("----------------------------------"); System.out.println("- Success = KSLN, KSTJ"); System.out.println("----------"); - for(PluginDataObject o : pp) { + for (PluginDataObject o : pp) { System.out.println(o); } System.out.println("----------------------------------"); - - -// try { -// JAXBContext ctx = JAXBContext.newInstance(PluginDataObjectFilter.class,StationIdFilterElement.class); -// -// Marshaller msh = ctx.createMarshaller(); -// -// msh.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); -// -// ByteArrayOutputStream istrm = new ByteArrayOutputStream(); -// msh.marshal(filter, istrm); -// -// String ss = istrm.toString(); -// -// System.out.println(ss); -// } catch(Exception ee) { -// ee.printStackTrace(); -// } } } diff --git a/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/core/filterimpl/WMOHeaderFilterElement.java b/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/core/filterimpl/WMOHeaderFilterElement.java index b88f813c0e..cd337e1be3 100644 --- a/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/core/filterimpl/WMOHeaderFilterElement.java +++ b/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/core/filterimpl/WMOHeaderFilterElement.java @@ -30,11 +30,7 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; -import com.raytheon.uf.common.dataplugin.IDecoderGettable; import com.raytheon.uf.common.dataplugin.PluginDataObject; -import com.raytheon.uf.common.geospatial.ISpatialEnabled; -import com.raytheon.uf.common.geospatial.ISpatialObject; -import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; @@ -42,23 +38,25 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; * TODO Add Description * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Oct 25, 2011 11312      jkorman     Initial creation
- *
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
+ * 
  * 
- * + * * @author jkorman - * @version 1.0 + * @version 1.0 */ @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public class WMOHeaderFilterElement extends AbstractFilterElement implements ISerializableObject { - - private static final Class [] GETTER_CLASS = new Class [0]; +public class WMOHeaderFilterElement extends AbstractFilterElement implements + ISerializableObject { + + private static final Class[] GETTER_CLASS = new Class[0]; private static final String WMO_HEADER = "getWmoHeader"; @@ -69,7 +67,7 @@ public class WMOHeaderFilterElement extends AbstractFilterElement implements ISe public WMOHeaderFilterElement() { super(); } - + /** * @return the patterns */ @@ -78,7 +76,8 @@ public class WMOHeaderFilterElement extends AbstractFilterElement implements ISe } /** - * @param patterns the patterns to set + * @param patterns + * the patterns to set */ public void setPatterns(List patterns) { this.patterns = patterns; @@ -89,7 +88,7 @@ public class WMOHeaderFilterElement extends AbstractFilterElement implements ISe * @param pattern */ public void addPattern(Pattern pattern) { - if(patterns == null) { + if (patterns == null) { patterns = new ArrayList(); } patterns.add(pattern); @@ -100,26 +99,27 @@ public class WMOHeaderFilterElement extends AbstractFilterElement implements ISe * @param pattern */ public void addPattern(String pattern) { - if(pattern != null) { + if (pattern != null) { addPattern(Pattern.compile(pattern)); } } /** * This execute + * * @see com.raytheon.uf.edex.decodertools.core.IObsFilterElement#filter(com.raytheon.uf.common.dataplugin.PluginDataObject) */ @Override public PluginDataObject filter(PluginDataObject report) { boolean pass = false; - if(report != null) { + if (report != null) { String wmoHeader = getWMOHeader(report); - - if(wmoHeader != null) { - for(Pattern p : patterns) { - if(p != null) { + + if (wmoHeader != null) { + for (Pattern p : patterns) { + if (p != null) { Matcher m = p.matcher(wmoHeader); - if(m.matches()) { + if (m.matches()) { pass = true; break; } @@ -127,105 +127,48 @@ public class WMOHeaderFilterElement extends AbstractFilterElement implements ISe } } } - return (pass ? report : null) ; + return (pass ? report : null); } /** - * Get the WMO header from this report object. If an error occurs or the - * WMO header is not defined, a null String reference is returned. + * Get the WMO header from this report object. If an error occurs or the WMO + * header is not defined, a null String reference is returned. + * * @param report * @return */ private String getWMOHeader(PluginDataObject report) { - + String header = null; - if(report != null) { + if (report != null) { Method getter = null; try { getter = report.getClass().getMethod(WMO_HEADER, GETTER_CLASS); } catch (Exception e) { // Nothing } - if(getter != null) { + if (getter != null) { try { header = (String) getter.invoke(report); - } catch(Exception e) { + } catch (Exception e) { // Nothing } } } return header; } - + /** * */ @Override public String toString() { StringBuilder sb = new StringBuilder("WMOHeaderFilterElement:{"); - for(Pattern p : patterns) { + for (Pattern p : patterns) { sb.append(p.pattern()); sb.append(","); } sb.append("}"); return sb.toString(); } - - private static class TestObject extends PluginDataObject implements ISpatialEnabled { - private static final long serialVersionUID = 1L; - - String wmoHeader = null; - - SurfaceObsLocation location; - - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } - - @Override - public ISpatialObject getSpatialObject() { - return location; - } - - public String getWmoHeader() { - return wmoHeader; - } - - public void setWmoHeader(String header) { - wmoHeader = header; - } - - public String toString() { - return wmoHeader + " Passed"; - } - - } - - public static final void main(String [] args) { - - PluginDataObjectFilter filter = new PluginDataObjectFilter(); - WMOHeaderFilterElement element = new WMOHeaderFilterElement(); - element.setFilterElementName(""); - element.setFilterType(AbstractObsFilter.EXCLUDE_TYPE); - element.addPattern(Pattern.compile("SAUS70.*")); - filter.addFilterElement(element); - - TestObject t = new TestObject(); - System.out.println("---- Test 1 -----"); - PluginDataObject [] pp = new TestObject[] { t, }; - t.setWmoHeader("SAUS43 KWBC 251300"); - pp = filter.filter(pp); - for(PluginDataObject p : pp) { - System.out.println(p); - } - - System.out.println("---- Test 2 -----"); - t.setWmoHeader("SAUS70 KWBC 251410 RRA"); - pp = new TestObject[] { t, }; - pp = filter.filter(pp); - for(PluginDataObject p : pp) { - System.out.println(p); - } - } } diff --git a/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/time/TimeTools.java b/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/time/TimeTools.java index 02dd25686c..765257d16c 100644 --- a/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/time/TimeTools.java +++ b/edexOsgi/com.raytheon.uf.edex.decodertools/src/com/raytheon/uf/edex/decodertools/time/TimeTools.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.edex.decodertools.time; +import java.io.File; import java.text.ParseException; import java.util.Calendar; import java.util.TimeZone; @@ -49,6 +50,7 @@ import com.raytheon.uf.edex.decodertools.core.DecoderTools; * 20070925 391 jkorman Added copyToNearestHour method. * 20071019 391 jkorman Added getSystemCalendar and TimeService. * 20130219 1636 rferrel File timestamp can now be YYMMDD or YYMMDDHH. + * 20130912 2249 rferrel Added getWarningTimestamp method. * * * @author jkorman @@ -64,7 +66,24 @@ public class TimeTools { * name: .YYYYMMDD or .YYYYMMDDHH */ private static final Pattern FILE_TIMESTAMP = Pattern - .compile("(.*\\.)(\\d{8}|\\d{10}$)"); + .compile("(.*\\.)(\\d{8}|\\d{10})$"); + + /** + * Time stamp for a file name created by the Text Editor Dialog. This + * assumes the 10 digit following .wan is the warning's issue time in epoch + * seconds. + */ + private static final String TEXT_EDITOR_WARNING = ".*\\.wan(\\d{10})$"; + + /** + * Environment variable with the root directory. + */ + private static final String DATA_ARCHIVE_ROOT = "data.archive.root"; + + /** + * Pattern for getting time stamp from Text Editor Dialog created files. + */ + private static Pattern FILE_WARNING_TIMESTAMP = null; public static final Pattern WMO_TIMESTAMP = Pattern .compile("([0-3][0-9])(\\d{2})(\\d{2})[Zz]?"); @@ -106,7 +125,7 @@ public class TimeTools { } - /** Allows the check on archive to be overriden for testing. */ + /** Allows the check on archive to be overridden for testing. */ static ICheckAllowArchive checkAllowArchive = new CheckOSEnv(); /** @@ -238,6 +257,35 @@ public class TimeTools { return timestamp; } + /** + * Get the time stamp of a warning file name based on the name generated by + * the TextEditorDialog. + * + * @param fileName + * @return timestamp warning's issue time in epoch seconds when fileName is + * a Text Editor Dialog file otherwise null + */ + public static final String getWarningTimestamp(String fileName) { + if (FILE_WARNING_TIMESTAMP == null) { + // Create pattern to test if fileName is in a director relative to + // DATA_ARCHIVE_ROOT and ends with the expected extension. + StringBuilder pattern = new StringBuilder("^"); + pattern.append(System.getProperty(DATA_ARCHIVE_ROOT)); + if (!pattern.substring(pattern.length() - 1).equals(File.separator)) { + pattern.append(File.separator); + } + pattern.append(TEXT_EDITOR_WARNING); + FILE_WARNING_TIMESTAMP = Pattern.compile(pattern.toString()); + } + + String timestamp = null; + Matcher matcher = FILE_WARNING_TIMESTAMP.matcher(fileName); + if (matcher.find()) { + timestamp = matcher.group(1); + } + return timestamp; + } + /** * Converts a ddhhmm time group to a Calendar. Adjusts the calendar as * follows: Any time group with a day (dd) in the future is set back one diff --git a/edexOsgi/com.raytheon.uf.edex.distribution/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.distribution/META-INF/MANIFEST.MF index 21c2288bf1..49b50e4215 100644 --- a/edexOsgi/com.raytheon.uf.edex.distribution/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.edex.distribution/META-INF/MANIFEST.MF @@ -10,3 +10,4 @@ Require-Bundle: com.raytheon.uf.common.serialization, com.raytheon.uf.common.status;bundle-version="1.12.1112" Import-Package: org.apache.camel, org.apache.commons.logging +Export-Package: com.raytheon.uf.edex.distribution diff --git a/edexOsgi/com.raytheon.uf.edex.distribution/res/spring/distribution-spring.xml b/edexOsgi/com.raytheon.uf.edex.distribution/res/spring/distribution-spring.xml index 9572d27ad3..018a905229 100644 --- a/edexOsgi/com.raytheon.uf.edex.distribution/res/spring/distribution-spring.xml +++ b/edexOsgi/com.raytheon.uf.edex.distribution/res/spring/distribution-spring.xml @@ -3,6 +3,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> + @@ -63,9 +64,7 @@ - - - + java.lang.Throwable diff --git a/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionPatterns.java b/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionPatterns.java new file mode 100644 index 0000000000..69eaf6bd4e --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionPatterns.java @@ -0,0 +1,215 @@ +/** + * 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.distribution; + +import java.io.File; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import com.raytheon.uf.common.localization.IPathManager; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.localization.LocalizationFile; +import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.serialization.SerializationUtil; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; + +/** + * Container for the various Distribution patterns used by plugins. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Sep 6, 2013  2327      rjpeter     Initial creation
+ * 
+ * 
+ * + * @author rjpeter + * @version 1.0 + */ +public class DistributionPatterns { + private static final IUFStatusHandler statusHandler = UFStatus + .getHandler(DistributionPatterns.class); + + private static final DistributionPatterns instance = new DistributionPatterns(); + + /** + * Used to track file modified time to determine if a pattern set needs to + * be reloaded. + */ + private final ConcurrentMap modifiedTimes = new ConcurrentHashMap(); + + /** + * Patterns for the various plugins. + */ + private final ConcurrentMap patterns = new ConcurrentHashMap(); + + /** + * Returns the singleton instance. + * + * @return + */ + public static DistributionPatterns getInstance() { + return instance; + } + + private DistributionPatterns() { + refresh(); + } + + /** + * Loads patterns from a distribution file for the specified plugin. + * + * @param file + * The file containing the ingest patterns + * @throws DistributionException + * If the modelFile cannot be deserialized + */ + private RequestPatterns loadPatterns(File file) + throws DistributionException { + RequestPatterns patternSet = null; + try { + patternSet = SerializationUtil.jaxbUnmarshalFromXmlFile( + RequestPatterns.class, file.getPath()); + } catch (Exception e) { + throw new DistributionException("File " + file.getAbsolutePath() + + " could not be unmarshalled.", e); + } + patternSet.compilePatterns(); + return patternSet; + } + + /** + * Lists the files in the distribution directory + * + * @return An array of the files in the distribution directory + */ + private Collection getDistributionFiles() { + IPathManager pathMgr = PathManagerFactory.getPathManager(); + + LocalizationFile[] files = pathMgr.listFiles( + pathMgr.getLocalSearchHierarchy(LocalizationType.EDEX_STATIC), + "distribution", new String[] { ".xml" }, true, true); + Map distFiles = new HashMap(); + for (LocalizationFile file : files) { + if (distFiles.containsKey(file.getName()) == false) { + distFiles.put(file.getName(), file.getFile()); + } + } + + return distFiles.values(); + } + + /** + * Refreshes the distribution patterns if a plugin's distribution pattern + * file has been modified. This method is executed via a quartz timer every + * five seconds + */ + public void refresh() { + for (File file : getDistributionFiles()) { + String fileName = file.getName(); + Long modTime = modifiedTimes.get(fileName); + if ((modTime == null) + || (modTime.longValue() != file.lastModified())) { + // getDistributionFiles only returns files ending in .xml + int index = fileName.lastIndexOf("."); + String plugin = null; + if (index > 0) { + plugin = fileName.substring(0, index); + } else { + plugin = fileName; + } + + try { + if (patterns.containsKey(plugin)) { + statusHandler + .info("Change to distribution file detected. " + + fileName + + " has been modified. Reloading distribution patterns"); + } + patterns.put(plugin, loadPatterns(file)); + modifiedTimes.put(fileName, file.lastModified()); + } catch (DistributionException e) { + statusHandler.error( + "Error reloading distribution patterns from file: " + + fileName, e); + } + } + } + } + + /** + * Returns a list of plugins that are interested in the given header. + * + * @param header + * @return + */ + public List getMatchingPlugins(String header) { + List plugins = new LinkedList(); + + for (Map.Entry entry : patterns.entrySet()) { + if (entry.getValue().isDesiredHeader(header)) { + plugins.add(entry.getKey()); + } + } + + return plugins; + } + + /** + * Returns a list of plugins that are interested in the given header. + * + * @param header + * @param pluginsToCheck + * @return + */ + public List getMatchingPlugins(String header, + Collection pluginsToCheck) { + List plugins = new LinkedList(); + + for (String plugin : pluginsToCheck) { + RequestPatterns pattern = patterns.get(plugin); + if ((pattern != null) && pattern.isDesiredHeader(header)) { + plugins.add(plugin); + } + } + + return plugins; + } + + /** + * Returns true if there are patterns registered for the given plugin, false + * otherwise. + * + * @param pluginName + * @return + */ + public boolean hasPatternsForPlugin(String pluginName) { + return patterns.containsKey(pluginName); + } +} diff --git a/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionSrv.java b/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionSrv.java index d613a2c985..fae3f25a7e 100644 --- a/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionSrv.java +++ b/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionSrv.java @@ -20,11 +20,8 @@ package com.raytheon.uf.edex.distribution; import java.io.File; -import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -34,16 +31,6 @@ import org.apache.camel.RecipientList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.raytheon.uf.common.localization.IPathManager; -import com.raytheon.uf.common.localization.LocalizationContext; -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; -import com.raytheon.uf.common.localization.LocalizationFile; -import com.raytheon.uf.common.localization.PathManagerFactory; -import com.raytheon.uf.common.serialization.SerializationUtil; -import com.raytheon.uf.common.status.IUFStatusHandler; -import com.raytheon.uf.common.status.UFStatus; -import com.raytheon.uf.common.status.UFStatus.Priority; - /** * The purpose of this bean is to load a series of XML files from localization * for each plugin registering itself with this bean and route messages based on @@ -55,108 +42,27 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Oct 16, 2009 brockwoo Initial creation + * Oct 16, 2009 brockwoo Initial creation * 6/8/2010 4647 bphillip Added automatic pattern refreshing * 09/01/2010 4293 cjeanbap Logging of unknown Weather Products. - * Feb 27, 2013 1638 mschenke Cleaned up localization code to fix null pointer + * Feb 27, 2013 1638 mschenke Cleaned up localization code to fix null pointer * when no distribution files present * Mar 19, 2013 1794 djohnson PatternWrapper is immutable, add toString() to it for debugging. * Aug 19, 2013 2257 bkowal edexBridge to qpid 0.18 upgrade - * + * Sep 06, 2013 2327 rjpeter Updated to use DistributionPatterns. * * * @author brockwoo * @version 1.0 */ - public class DistributionSrv { - - private static final IUFStatusHandler statusHandler = UFStatus - .getHandler(DistributionSrv.class); - private static final String HEADER_QPID_SUBJECT = "qpid.subject"; - private static class PatternWrapper { - private final String plugin; + protected Log logger = LogFactory.getLog("Ingest"); - private final RequestPatterns patterns; + protected Log routeFailedLogger = LogFactory.getLog("RouteFailedLog"); - private final String route; - - private final String displayString; - - private PatternWrapper(String plugin, String route, - RequestPatterns patterns) { - this.plugin = plugin; - this.route = route; - this.patterns = patterns; - this.displayString = createDisplayString(); - } - - private String createDisplayString() { - StringBuilder sb = new StringBuilder(); - sb.append("plugin=").append(plugin).append(", "); - sb.append("route=").append(route).append(", "); - sb.append("patterns=").append(patterns); - return sb.toString(); - } - - @Override - public String toString() { - return displayString; - } - } - - protected transient Log logger = LogFactory.getLog("Ingest"); - - protected transient Log routeFailedLogger = LogFactory - .getLog("RouteFailedLog"); - - private final List pluginPatterns = new ArrayList( - 100); - - private final ConcurrentMap patternMap = new ConcurrentHashMap(); - - private final ConcurrentMap modifiedTimes = new ConcurrentHashMap(); - - public DistributionSrv() { - for (File file : getDistributionFiles()) { - modifiedTimes.put(file.getName(), file.lastModified()); - } - } - - /** - * Refreshes the distribution patterns if a plugin's distribution pattern - * file has been modified. This method is executed via a quartz timer every - * five seconds - */ - public synchronized void refresh() { - for (File file : getDistributionFiles()) { - if (!file.getName().endsWith("~") - && modifiedTimes.containsKey(file.getName()) - && (modifiedTimes.get(file.getName()) < file.lastModified())) { - String plugin = file.getName().replace(".xml", ""); - PatternWrapper wrapper = patternMap.get(plugin); - if (wrapper != null) { - try { - statusHandler - .handle(Priority.EVENTA, - "Change to distribution file detected. " - + file.getName() - + " has been modified. Reloading distribution patterns"); - wrapper = new PatternWrapper(wrapper.plugin, - wrapper.route, loadPatterns(file, plugin)); - patternMap.put(plugin, wrapper); - modifiedTimes.put(file.getName(), file.lastModified()); - } catch (DistributionException e) { - statusHandler.handle(Priority.PROBLEM, - "Error reloading distribution patterns from file: " - + file.getName(), e); - } - } - } - } - } + private final ConcurrentMap pluginRoutes = new ConcurrentHashMap(); /** * Allows a plugin to register itself with this bean. Note: if the plugin @@ -167,49 +73,18 @@ public class DistributionSrv { * @param destination * a destination to send this message to * @return an instance of this bean - * @throws EdexException + * @throws DistributionException */ public DistributionSrv register(String pluginName, String destination) throws DistributionException { - IPathManager pathMgr = PathManagerFactory.getPathManager(); - LocalizationContext commonStaticBase = pathMgr.getContext( - LocalizationContext.LocalizationType.EDEX_STATIC, - LocalizationContext.LocalizationLevel.BASE); - - LocalizationContext siteStaticBase = pathMgr.getContext( - LocalizationContext.LocalizationType.EDEX_STATIC, - LocalizationContext.LocalizationLevel.SITE); - - String path = ""; - String sitePath = ""; - try { - path = pathMgr.getFile(commonStaticBase, - "distribution" + File.separator + pluginName + ".xml") - .getCanonicalPath(); - sitePath = pathMgr.getFile(siteStaticBase, - "distribution" + File.separator + pluginName + ".xml") - .getCanonicalPath(); - } catch (IOException e) { + if (!DistributionPatterns.getInstance() + .hasPatternsForPlugin(pluginName)) { throw new DistributionException( "Plugin " + pluginName + " does not have an accompanying patterns file in localization."); } - - File modelFile = new File(path); - File siteModelFile = new File(sitePath); - RequestPatterns patterns = null; - if (siteModelFile.exists()) { - patterns = loadPatterns(siteModelFile, pluginName); - } else if (modelFile.exists()) { - patterns = loadPatterns(modelFile, pluginName); - } else { - patterns = new RequestPatterns(); - } - PatternWrapper wrapper = new PatternWrapper(pluginName, destination, - patterns); - patternMap.put(wrapper.plugin, wrapper); - pluginPatterns.add(wrapper); + pluginRoutes.put(pluginName, destination); return this; } @@ -223,8 +98,6 @@ public class DistributionSrv { */ @RecipientList public List route(Exchange exchange) { - StringBuilder pluginNames = new StringBuilder(); - List dest = new ArrayList(); Message in = exchange.getIn(); // determine if the header is in the qpid subject field? String header = (String) in.getHeader(HEADER_QPID_SUBJECT); @@ -254,14 +127,22 @@ public class DistributionSrv { // No header entry so will try and use the filename instead header = (String) exchange.getIn().getBody(); } - for (PatternWrapper wrapper : pluginPatterns) { - if (wrapper.patterns.isDesiredHeader(header)) { + + List plugins = DistributionPatterns.getInstance() + .getMatchingPlugins(header, pluginRoutes.keySet()); + List routes = new ArrayList(plugins.size()); + StringBuilder pluginNames = new StringBuilder(plugins.size() * 8); + for (String plugin : plugins) { + String route = pluginRoutes.get(plugin); + if (route != null) { if (pluginNames.length() != 0) { pluginNames.append(","); } - pluginNames.append(wrapper.plugin); - dest.add(wrapper.route); + pluginNames.append(plugin); + routes.add(route); unroutedFlag = false; + } else if (logger.isDebugEnabled()) { + logger.debug("No route registered for plugin: " + plugin); } } @@ -270,53 +151,8 @@ public class DistributionSrv { // using warn instead of error; app can continue routeFailedLogger.warn(header); } + in.setHeader("pluginName", pluginNames.toString()); - return dest; - } - - /** - * Loads patterns from a distribution file for the specified plugin - * - * @param modelFile - * The file containing the ingest patterns - * @param pluginName - * The plugin name associated with the ingest patterns - * @throws DistributionException - * If the modelFile cannot be deserialized - */ - private RequestPatterns loadPatterns(File modelFile, String pluginName) - throws DistributionException { - RequestPatterns patternSet = null; - try { - patternSet = SerializationUtil.jaxbUnmarshalFromXmlFile( - RequestPatterns.class, modelFile.getPath()); - } catch (Exception e) { - throw new DistributionException("File " - + modelFile.getAbsolutePath() - + " could not be unmarshalled.", e); - } - patternSet.compilePatterns(); - return patternSet; - } - - /** - * Lists the files in the distribution directory - * - * @return An array of the files in the distribution directory - */ - private File[] getDistributionFiles() { - IPathManager pathMgr = PathManagerFactory.getPathManager(); - - LocalizationFile[] files = pathMgr.listFiles( - pathMgr.getLocalSearchHierarchy(LocalizationType.EDEX_STATIC), - "distribution", null, true, true); - Map distFiles = new HashMap(); - for (LocalizationFile file : files) { - if (distFiles.containsKey(file.getName()) == false) { - distFiles.put(file.getName(), file.getFile()); - } - } - - return distFiles.values().toArray(new File[0]); + return routes; } } diff --git a/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/RequestPatterns.java b/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/RequestPatterns.java index 139602ca98..e18765ffba 100644 --- a/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/RequestPatterns.java +++ b/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/RequestPatterns.java @@ -51,7 +51,7 @@ import com.raytheon.uf.common.serialization.ISerializableObject; * May 16, 2011 7317 cjeanbap Added try-catch statement * for PatternSyntaxException. * Mar 19, 2013 1794 djohnson Add toString() for debugging. - * + * Sep 10, 2013 2327 rjpeter Sized ArrayList declarations. * * * @author brockwoo @@ -60,22 +60,22 @@ import com.raytheon.uf.common.serialization.ISerializableObject; @XmlRootElement(name = "requestPatterns") @XmlAccessorType(XmlAccessType.NONE) -public class RequestPatterns implements ISerializableObject{ - +public class RequestPatterns implements ISerializableObject { + /** * List of patterns requested by a plugin. */ - @XmlElements( { @XmlElement(name = "regex", type = String.class) }) - private List patterns = new ArrayList(); - - private final List compiledPatterns = new ArrayList(); - - protected transient Log patternFailedLogger = LogFactory.getLog("PatternFailedLog"); - + @XmlElements({ @XmlElement(name = "regex", type = String.class) }) + private List patterns = new ArrayList(0); + + private List compiledPatterns = new ArrayList(0); + + protected Log patternFailedLogger = LogFactory.getLog("PatternFailedLog"); + /** * Creates a new instance of the container. */ - public RequestPatterns(){ + public RequestPatterns() { } /** @@ -90,27 +90,30 @@ public class RequestPatterns implements ISerializableObject{ /** * Sets the list of regex strings for this container. * - * @param patterns an arraylist of regex strings + * @param patterns + * an arraylist of regex strings */ public void setPatterns(List patterns) { this.patterns = patterns; } - + /** * Inserts a single string into the list. * - * @param pattern The regex string to insert + * @param pattern + * The regex string to insert */ public void setPattern(String pattern) { this.patterns.add(pattern); } - + /** * Will compile the strings into Pattern objects. * */ - public void compilePatterns(){ - for(String pattern : patterns) { + public void compilePatterns() { + compiledPatterns = new ArrayList(patterns.size()); + for (String pattern : patterns) { try { compiledPatterns.add(Pattern.compile(pattern)); } catch (PatternSyntaxException e) { @@ -121,19 +124,19 @@ public class RequestPatterns implements ISerializableObject{ } } } - + /** - * Takes a string and compares against the patterns in this - * container. The first one that matches breaks the search and - * returns true. + * Takes a string and compares against the patterns in this container. The + * first one that matches breaks the search and returns true. * - * @param header The string to search for + * @param header + * The string to search for * @return a boolean indicating success */ public boolean isDesiredHeader(String header) { boolean isFound = false; - for(Pattern headerPattern : compiledPatterns) { - if(headerPattern.matcher(header).find()) { + for (Pattern headerPattern : compiledPatterns) { + if (headerPattern.matcher(header).find()) { isFound = true; break; } diff --git a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/cluster/quartz/ClusteredQuartzEndpoint.java b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/cluster/quartz/ClusteredQuartzEndpoint.java index 2d852ff443..fd6a04329c 100644 --- a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/cluster/quartz/ClusteredQuartzEndpoint.java +++ b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/cluster/quartz/ClusteredQuartzEndpoint.java @@ -40,6 +40,7 @@ import com.raytheon.uf.edex.database.cluster.ClusterTask; * ------------ ---------- ----------- -------------------------- * Feb 19, 2010 njensen Initial creation * Aug 21, 2013 DR 16521 D. Friedman Ensure endpoint URI is used for cluster entry + * Aug 26, 2013 DR 2272 bkowal Append an optional suffix to the cluster task details * * * @@ -62,7 +63,7 @@ public class ClusteredQuartzEndpoint extends QuartzEndpoint { @Override public void onJobExecute(final JobExecutionContext jobExecutionContext) throws JobExecutionException { - String jName = getEndpointUri(); + String jName = getEndpointUri() + ClusterLockUtils.CLUSTER_SUFFIX; long period = Math.abs(jobExecutionContext.getFireTime().getTime() - jobExecutionContext.getNextFireTime().getTime()) / 2; ClusterTask ct = ClusterLockUtils.lock(TASK, jName, period, false); diff --git a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/context/ClusteredContextManager.java b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/context/ClusteredContextManager.java index dfdfce69b7..910a3d06a4 100644 --- a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/context/ClusteredContextManager.java +++ b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/context/ClusteredContextManager.java @@ -50,6 +50,7 @@ import com.raytheon.uf.edex.database.cluster.ClusterTask; * Nov 10, 2010 5050 rjpeter Initial creation * Jul 16, 2012 DR 15073 D. Friedman Stop consumers instead of whole context * May 14, 2013 1989 njensen Camel 2.11 compatibility + * Aug 26, 2013 DR 2272 bkowal Append an optional suffix to the cluster task details * * * @author rjpeter @@ -112,8 +113,9 @@ public class ClusteredContextManager { } public void checkClusteredContexts() { + String suffix = ClusterLockUtils.CLUSTER_SUFFIX; for (CamelContext camelContext : clusteredContextList) { - String contextName = camelContext.getName(); + String contextName = camelContext.getName() + suffix; ClusterTask lock = ClusterLockUtils.lock(taskName, contextName, myName, timeOutMillis, false); boolean activateRoute = false; diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataStoreArchiver.java b/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataStoreArchiver.java index d386da9309..ba7ea799da 100644 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataStoreArchiver.java +++ b/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataStoreArchiver.java @@ -43,6 +43,7 @@ import com.raytheon.uf.edex.maintenance.archive.config.DataArchiveConfig; * ------------ ---------- ----------- -------------------------- * Dec 8, 2011 njensen Initial creation * Jan 14, 2013 1469 bkowal Removed the hdf5 data directory. + * Jul 23, 2013 2216 rferrel Removed the time stamp filter in hdf5 copy. * * * @@ -68,12 +69,8 @@ public class DataStoreArchiver { String outputDir = archiveDir; // + dirs of hdf5 file try { - // data must be older than 30 minutes, and no older than hours - // to keep hours need to lookup plugin and see if compression - // matches, or embed in configuration the compression level on - // archive, but would still need to lookup plugin - ds.copy(outputDir, compression, "lastArchived", 1800000, - conf.getHoursToKeep() * 60000 + 1800000); + // Do not perform time stamp check. + ds.copy(outputDir, compression, null, 0, 0); } catch (StorageException e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage()); } diff --git a/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/DPADecoder-spring.xml b/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/DPADecoder-spring.xml index e5e7eff311..7db114019d 100644 --- a/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/DPADecoder-spring.xml +++ b/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/DPADecoder-spring.xml @@ -18,6 +18,11 @@
+ + + + diff --git a/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/hpeDHRDecoder-spring.xml b/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/hpeDHRDecoder-spring.xml index edd49c3b2d..40cdd388fc 100644 --- a/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/hpeDHRDecoder-spring.xml +++ b/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/hpeDHRDecoder-spring.xml @@ -11,13 +11,18 @@
- + - + + + + + diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.acars/src/com/raytheon/uf/edex/plugin/acars/dao/ACARSDao.java b/edexOsgi/com.raytheon.uf.edex.plugin.acars/src/com/raytheon/uf/edex/plugin/acars/dao/ACARSDao.java index 3e81fd1a43..76e680fc13 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.acars/src/com/raytheon/uf/edex/plugin/acars/dao/ACARSDao.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.acars/src/com/raytheon/uf/edex/plugin/acars/dao/ACARSDao.java @@ -41,9 +41,10 @@ import com.raytheon.uf.edex.database.DataAccessLayerException; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 21, 2009 1939 jkorman Initial creation + * Jan 21, 2009 1939 jkorman Initial creation * Oct 10, 2012 1261 djohnson Add some generics wildcarding. * Nov 02, 2012 1302 djohnson Add Javadoc. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -201,7 +202,6 @@ public class ACARSDao extends DefaultPluginDao { retData = new ArrayList(); for (Object o : result) { ACARSRecord r = (ACARSRecord) o; - r.setPluginName(pluginName); retData.add(r); } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.acars/src/com/raytheon/uf/edex/plugin/acars/decoder/ACARSDataAdapter.java b/edexOsgi/com.raytheon.uf.edex.plugin.acars/src/com/raytheon/uf/edex/plugin/acars/decoder/ACARSDataAdapter.java index 07def435a6..ba9180c769 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.acars/src/com/raytheon/uf/edex/plugin/acars/decoder/ACARSDataAdapter.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.acars/src/com/raytheon/uf/edex/plugin/acars/decoder/ACARSDataAdapter.java @@ -52,7 +52,8 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 22, 2009 1939 jkorman Initial creation + * Jan 22, 2009 1939 jkorman Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -72,13 +73,13 @@ public class ACARSDataAdapter { private static final int SECOND_OFFSET = 5; - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); // Map detailed flight phase [0-08-009] to flight phase [0-08-004] private static final int[] DETAIL_PHASE_MAP = { 3, 4, 2, 3, 4, 5, 6, 5, 5, 5, 5, 6, 6, 6, 6, 7, }; - private String pluginName; + private final String pluginName; private String traceId = null; @@ -115,7 +116,6 @@ public class ACARSDataAdapter { ACARSRecord record = getDataRecord(parser.next()); if (record != null) { record.setWmoHeader(parser.getWmoHeader().getWmoHeader()); - record.setPluginName(pluginName); try { record.constructDataURI(); @@ -333,14 +333,13 @@ public class ACARSDataAdapter { } } } - if(rpt != null) { - if(rpt.getFlightLevel() == null) { - logger.error(traceId - + " -No aircraft flight level was found"); + if (rpt != null) { + if (rpt.getFlightLevel() == null) { + logger.error(traceId + " -No aircraft flight level was found"); rpt = null; } } - + return rpt; } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.acarssounding/src/com/raytheon/uf/edex/plugin/acarssounding/tools/SoundingBuilder.java b/edexOsgi/com.raytheon.uf.edex.plugin.acarssounding/src/com/raytheon/uf/edex/plugin/acarssounding/tools/SoundingBuilder.java index 29aa287239..525372b6d6 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.acarssounding/src/com/raytheon/uf/edex/plugin/acarssounding/tools/SoundingBuilder.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.acarssounding/src/com/raytheon/uf/edex/plugin/acarssounding/tools/SoundingBuilder.java @@ -55,6 +55,7 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 16, 2009 jkorman Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -64,11 +65,7 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; public class SoundingBuilder { - private Log logger = LogFactory.getLog(getClass()); - - private String pluginName = ACARSSoundingTools.ACARS_SNDG_PLUGIN_NAME; - - private String acarsPluginName = ACARSSoundingTools.ACARS_PLUGIN_NAME; + private final Log logger = LogFactory.getLog(getClass()); File dataDir = null; @@ -237,7 +234,6 @@ public class SoundingBuilder { loc.setElevation(airport.getElevation().intValue()); sounding.setLocation(loc); sounding.setTailNumber(data.getTailNumber()); - sounding.setPluginName(pluginName); try { sounding.constructDataURI(); @@ -288,8 +284,9 @@ public class SoundingBuilder { // If we find an obs with the same time as one in // the sounding, get rid of it. if (layer.getTimeObs().equals(r.getTimeObs())) { - if(logger.isDebugEnabled()) { - logger.debug("Deleting duplicate layer" + r.getDataURI()); + if (logger.isDebugEnabled()) { + logger.debug("Deleting duplicate layer" + + r.getDataURI()); } obs.remove(cRec); incNext = false; @@ -298,8 +295,10 @@ public class SoundingBuilder { // Is the obs time between the current // layers? If so we want to find out if // it needs to be included. - if(ACARSSoundingTools.checkBetween(lastLayer,r,layer)) { - logger.info("Found candidate layer" + r.getDataURI()); + if (ACARSSoundingTools.checkBetween( + lastLayer, r, layer)) { + logger.info("Found candidate layer" + + r.getDataURI()); obs.remove(cRec); incNext = false; } else { @@ -319,7 +318,6 @@ public class SoundingBuilder { } } - /** * Returns a sorted not-null list of layers that are contained in a set of * layers. @@ -395,12 +393,10 @@ public class SoundingBuilder { currTime.add(lastRec); for (int i = 1; i < obsData.size(); i++) { ACARSRecord r = obsData.get(i); - if(r != null) { - r.setPluginName(acarsPluginName); - + if (r != null) { // Do the observations have the same time? - if (ACARSSoundingTools.ACARS_TIME_COMPARATOR - .compare(lastRec, r) != 0) { + if (ACARSSoundingTools.ACARS_TIME_COMPARATOR.compare( + lastRec, r) != 0) { // Different times, so create a new list currTime = new ArrayList(); times.add(currTime); @@ -516,10 +512,4 @@ public class SoundingBuilder { } return retValue; } - - - public static final void main(String[] args) { - - } - } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrascat/src/com/raytheon/uf/edex/plugin/bufrascat/decoder/AScatDataAdapter.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrascat/src/com/raytheon/uf/edex/plugin/bufrascat/decoder/AScatDataAdapter.java index 292a81bb32..c400b70369 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrascat/src/com/raytheon/uf/edex/plugin/bufrascat/decoder/AScatDataAdapter.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrascat/src/com/raytheon/uf/edex/plugin/bufrascat/decoder/AScatDataAdapter.java @@ -48,6 +48,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * Mar 03, 2008 969 jkorman Initial implementation. * May 17, 2013 1869 bsteffen Remove DataURI column from sat plot * types. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -118,7 +119,6 @@ public class AScatDataAdapter extends BUFRPointDataAdapter { obsData = getHeaderData(dataList); if (obsData != null) { // pickup the data. - obsData.setPluginName(getPluginName()); obsData.setWmoHeader(wmoHeader.getWmoHeader()); PointDataContainer container = getContainer(obsData); if (container != null) { diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrhdw/src/com/raytheon/uf/edex/plugin/bufrhdw/decoder/HDWDataAdapter.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrhdw/src/com/raytheon/uf/edex/plugin/bufrhdw/decoder/HDWDataAdapter.java index efb4b7fa05..9d5263b4dc 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrhdw/src/com/raytheon/uf/edex/plugin/bufrhdw/decoder/HDWDataAdapter.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrhdw/src/com/raytheon/uf/edex/plugin/bufrhdw/decoder/HDWDataAdapter.java @@ -49,6 +49,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * Mar 03, 2008 969 jkorman Initial implementation. * May 17, 2013 1869 bsteffen Remove DataURI column from sat plot * types. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -105,7 +106,6 @@ public class HDWDataAdapter extends BUFRPointDataAdapter { if ((obsData = getHeaderData(dataList)) != null) { // Need to set plugin name before getting container! obsData.setWmoHeader(wmoHeader.getWmoHeader()); - obsData.setPluginName(getPluginName()); obsData = getPointData(obsData, dataList); } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrmthdw/src/com/raytheon/uf/edex/plugin/bufrmthdw/decoder/MTHDWDataAdapter.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrmthdw/src/com/raytheon/uf/edex/plugin/bufrmthdw/decoder/MTHDWDataAdapter.java index d8cc115695..eff6e8765e 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrmthdw/src/com/raytheon/uf/edex/plugin/bufrmthdw/decoder/MTHDWDataAdapter.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrmthdw/src/com/raytheon/uf/edex/plugin/bufrmthdw/decoder/MTHDWDataAdapter.java @@ -50,6 +50,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * Jul 26, 2010 jkorman Initial creation * May 17, 2013 1869 bsteffen Remove DataURI column from sat plot * types. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -107,7 +108,6 @@ public class MTHDWDataAdapter extends BUFRPointDataAdapter { if ((obsData = getHeaderData(dataList)) != null) { // Need to set plugin name before getting container! obsData.setWmoHeader(wmoHeader.getWmoHeader()); - obsData.setPluginName(getPluginName()); obsData = getPointData(obsData, dataList); } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrncwf/src/com/raytheon/uf/edex/plugin/bufrncwf/decoder/BUFRncwfDataAdapter.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrncwf/src/com/raytheon/uf/edex/plugin/bufrncwf/decoder/BUFRncwfDataAdapter.java index eebfcdbbc6..c31dd22356 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrncwf/src/com/raytheon/uf/edex/plugin/bufrncwf/decoder/BUFRncwfDataAdapter.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrncwf/src/com/raytheon/uf/edex/plugin/bufrncwf/decoder/BUFRncwfDataAdapter.java @@ -55,6 +55,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Aug 17, 2009 jkorman Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -64,281 +65,295 @@ import com.vividsolutions.jts.geom.Coordinate; public class BUFRncwfDataAdapter extends BUFRPointDataAdapter { - // Position within sub-list - private static final int YEAR_POS = 0; - private static final int MONTH_POS = 1; - private static final int DAY_POS = 2; - private static final int HOUR_POS = 3; - private static final int MINUTE_POS = 4; - private static final int SECOND_POS = 5; + // Position within sub-list + private static final int YEAR_POS = 0; - private static final int FEATURES_POS = 6; + private static final int MONTH_POS = 1; - private static final int FEATURE_TIMSIG_POS = 0; - private static final int FEATURE_TIMEPD_POS = 1; - private static final int FEATURE_ATTSIG_POS = 2; - private static final int FEATURE_DIMSIG_POS = 3; - private static final int FEATURE_LAT_POS = 4; - private static final int FEATURE_LON_POS = 5; - private static final int BOUNDARY_ATTSIG_POS = 6; - private static final int BOUNDARY_DIMSIG_POS = 7; - private static final int BOUNDARY_SUBLIST_POS = 8; + private static final int DAY_POS = 2; - private static final int VERTEX_LAT_POS = 0; - private static final int VERTEX_LON_POS = 1; + private static final int HOUR_POS = 3; - private static final int STORM_TOP_POS = 7; - private static final int STORM_DIR_POS = 8; - private static final int STORM_SPD_POS = 9; + private static final int MINUTE_POS = 4; - private static final int INVALID = -9999; + private static final int SECOND_POS = 5; - /** - * - * @param pdd - * @param dao - * @param pluginName - */ - public BUFRncwfDataAdapter(PointDataDescription pdd, - PointDataPluginDao dao, String pluginName) { - super(pdd, dao, pluginName); - } + private static final int FEATURES_POS = 6; - /** - * Not used. - * - * @see com.raytheon.uf.edex.bufrtools.BUFRPointDataAdapter#createData(java.util.Iterator, - * com.raytheon.uf.edex.wmo.message.WMOHeader) - */ - @Override - public BUFRncwf createData(Iterator iterator, - WMOHeader wmoHeader) { - return null; - } + private static final int FEATURE_TIMSIG_POS = 0; - /** - * - * - * - * - * @see com.raytheon.uf.edex.bufrtools.BUFRPointDataAdapter#createDataList(java.util.Iterator, - * com.raytheon.uf.edex.wmo.message.WMOHeader) - */ - @Override - public List createDataList(Iterator iterator, - WMOHeader wmoHeader) { + private static final int FEATURE_TIMEPD_POS = 1; - List reports = new ArrayList(); + private static final int FEATURE_ATTSIG_POS = 2; - BUFRDataDocument dataDoc = iterator.next(); - if (dataDoc != null) { - // Get the primary data list. - List dataList = dataDoc.getList(); - for (IBUFRDataPacket p : dataList) { - if (p != null) { - List sList = getPacketSubList(p); - for (IBUFRDataPacket pp : sList) { - BUFRncwf ncwfReport = getReport(pp); + private static final int FEATURE_DIMSIG_POS = 3; - if (ncwfReport != null) { - ncwfReport.setPluginName(getPluginName()); + private static final int FEATURE_LAT_POS = 4; - PointDataContainer container = getContainer(ncwfReport); - if (container != null) { - PointDataView view = container.append(); + private static final int FEATURE_LON_POS = 5; - long vt = ncwfReport.getDataTime() - .getValidTime().getTimeInMillis(); - view.setLong("validTime", vt); + private static final int BOUNDARY_ATTSIG_POS = 6; - view.setFloat("storm_top", ncwfReport - .getStormTop().floatValue()); - view.setFloat("storm_dir", ncwfReport - .getStormDir().floatValue()); - view.setFloat("storm_speed", ncwfReport - .getStormSpeed().floatValue()); + private static final int BOUNDARY_DIMSIG_POS = 7; - NCWFFeature detect = ncwfReport.getDetection(); - view.setFloat("or_centroid_lat", - (float) detect.getCentroidLatitude()); - view.setFloat("or_centroid_lon", - (float) detect.getCentroidLongitude()); - int pos = 0; - for (Coordinate dc : detect - .getFeatureBoundary()) { - float lat = (float) DecoderTools - .getCoordinateLatitude(dc); - float lon = (float) DecoderTools - .getCoordinateLongitude(dc); - view.setFloat("oalat", lat, pos); - view.setFloat("oalon", lon, pos++); - } - view.setInt("or_num_of_vertices", pos); - NCWFFeature forecast = ncwfReport.getForecast(); - view.setFloat("centroid_lat", - (float) forecast.getCentroidLatitude()); - view.setFloat("centroid_lon", - (float) forecast.getCentroidLongitude()); - pos = 0; - for (Coordinate dc : forecast - .getFeatureBoundary()) { - float lat = (float) DecoderTools - .getCoordinateLatitude(dc); - float lon = (float) DecoderTools - .getCoordinateLongitude(dc); - view.setFloat("alat", lat, pos); - view.setFloat("alon", lon, pos++); - } - view.setInt("num_of_vertices", pos); + private static final int BOUNDARY_SUBLIST_POS = 8; - ncwfReport.setPointDataView(view); - reports.add(ncwfReport); - } - } - } - } - } - } - return reports; - } + private static final int VERTEX_LAT_POS = 0; - @SuppressWarnings("unchecked") - private BUFRncwf getReport(IBUFRDataPacket packet) { - BUFRncwf ncwfReport = null; - if (packet != null) { - List sList = (List) packet - .getValue(); + private static final int VERTEX_LON_POS = 1; - Calendar c = getTimeInfo(sList); - if (c != null) { - ncwfReport = new BUFRncwf(); + private static final int STORM_TOP_POS = 7; - ncwfReport.setDataTime(new DataTime(TimeTools.copy(c))); - List features = getPacketSubList(sList - .get(FEATURES_POS)); + private static final int STORM_DIR_POS = 8; - ncwfReport - .setDetection(getFeatureData(getPacketSubList(features - .get(0)))); - ncwfReport.setForecast(getFeatureData(getPacketSubList(features - .get(1)))); + private static final int STORM_SPD_POS = 9; - double height = getDouble(sList.get(STORM_TOP_POS), INVALID); - if (height >= 0) { - height = Math.floor((height * 3.280839) / 100); - } - ncwfReport.setStormTop(height); - ncwfReport.setStormDir(getDouble(sList.get(STORM_DIR_POS), - INVALID)); - ncwfReport.setStormSpeed(getDouble(sList.get(STORM_SPD_POS), - INVALID)); - if (ncwfReport.getDetection() != null) { - Coordinate centroid = ncwfReport.getDetection() - .getCentroidLocation(); - SurfaceObsLocation loc = new SurfaceObsLocation(); - loc.assignLocation( - DecoderTools.getCoordinateLatitude(centroid), - DecoderTools.getCoordinateLongitude(centroid)); - ncwfReport.setLocation(loc); - } - } - } - return ncwfReport; - } + private static final int INVALID = -9999; - private NCWFFeature getFeatureData(List featureList) { - NCWFFeature feature = null; - if ((featureList != null) && (featureList.size() > 0)) { - // 0 0 08 021 : CODE TABLE Comments: Time significance - // 1 0 04 026 : Second Comments: Time period or displacement - // 2 0 08 005 : Comments: Meteorological attribute significance - // 3 0 08 007 : Comments: Dimensional significance - // 4 0 05 001 : Comments: Latitude (high accuracy) - // 5 0 06 001 : Comments: Longitude (high accuracy) - // 6 0 08 005 : Comments: Meteorological attribute significance - // 7 0 08 007 : Comments: Dimensional significance - // 8 1 01 000 : Comments: Boundary-Sublist + /** + * + * @param pdd + * @param dao + * @param pluginName + */ + public BUFRncwfDataAdapter(PointDataDescription pdd, + PointDataPluginDao dao, String pluginName) { + super(pdd, dao, pluginName); + } - double lat = getDouble(featureList.get(FEATURE_LAT_POS), INVALID); - double lon = getDouble(featureList.get(FEATURE_LON_POS), INVALID); - if ((lat != INVALID) && (lon != INVALID)) { - feature = new NCWFFeature(lat, lon); + /** + * Not used. + * + * @see com.raytheon.uf.edex.bufrtools.BUFRPointDataAdapter#createData(java.util.Iterator, + * com.raytheon.uf.edex.wmo.message.WMOHeader) + */ + @Override + public BUFRncwf createData(Iterator iterator, + WMOHeader wmoHeader) { + return null; + } - IBUFRDataPacket p1 = featureList.get(BOUNDARY_SUBLIST_POS); - feature.setFeatureBoundary(getVertices(getPacketSubList(p1))); - } - } - return feature; - } + /** + * + * + * + * + * @see com.raytheon.uf.edex.bufrtools.BUFRPointDataAdapter#createDataList(java.util.Iterator, + * com.raytheon.uf.edex.wmo.message.WMOHeader) + */ + @Override + public List createDataList(Iterator iterator, + WMOHeader wmoHeader) { - /** - * - * @param vertexList - * @return - */ - private List getVertices(List vertexList) { - List vertices = new ArrayList(); - if (vertexList != null) { - for (IBUFRDataPacket p : vertexList) { - List vertex = getPacketSubList(p); - double lat = getDouble(vertex.get(VERTEX_LAT_POS), INVALID); - double lon = getDouble(vertex.get(VERTEX_LON_POS), INVALID); - if ((lat != INVALID) && (lon != INVALID)) { - vertices.add(DecoderTools.createCoordinate(lat, lon)); - } - } - } - return vertices; - } + List reports = new ArrayList(); - /** - * - * @param dataList - * @return - */ - private Calendar getTimeInfo(List dataList) { + BUFRDataDocument dataDoc = iterator.next(); + if (dataDoc != null) { + // Get the primary data list. + List dataList = dataDoc.getList(); + for (IBUFRDataPacket p : dataList) { + if (p != null) { + List sList = getPacketSubList(p); + for (IBUFRDataPacket pp : sList) { + BUFRncwf ncwfReport = getReport(pp); - int year = getInt(dataList.get(YEAR_POS), IDecoderConstants.VAL_MISSING); - int month = getInt(dataList.get(MONTH_POS), - IDecoderConstants.VAL_MISSING); - int day = getInt(dataList.get(DAY_POS), IDecoderConstants.VAL_MISSING); - int hour = getInt(dataList.get(HOUR_POS), IDecoderConstants.VAL_MISSING); - int minute = getInt(dataList.get(MINUTE_POS), - IDecoderConstants.VAL_MISSING); - int second = getInt(dataList.get(SECOND_POS), - IDecoderConstants.VAL_MISSING); + if (ncwfReport != null) { + PointDataContainer container = getContainer(ncwfReport); + if (container != null) { + PointDataView view = container.append(); - Calendar baseTime = null; + long vt = ncwfReport.getDataTime() + .getValidTime().getTimeInMillis(); + view.setLong("validTime", vt); - // Ensure that we have all of the time info and create the - // date-time and datatime info. - if ((year > 0) && (month > 0) && (day > 0) && (hour >= 0) - && (minute >= 0) && (second >= 0)) { - baseTime = TimeTools.getBaseCalendar(year, month, day); - baseTime.set(Calendar.HOUR_OF_DAY, hour); - baseTime.set(Calendar.MINUTE, minute); - baseTime.set(Calendar.SECOND, second); - baseTime.set(Calendar.MILLISECOND, 0); - } - return baseTime; - } + view.setFloat("storm_top", ncwfReport + .getStormTop().floatValue()); + view.setFloat("storm_dir", ncwfReport + .getStormDir().floatValue()); + view.setFloat("storm_speed", ncwfReport + .getStormSpeed().floatValue()); - /** - * - * @param packet - * @return - */ - @SuppressWarnings("unchecked") - private static List getPacketSubList(IBUFRDataPacket packet) { - List list = null; - if (packet instanceof BUFRSublistPacket) { - if (RepSubList.getPacketType().equals(packet.getUnits())) { - list = (List) packet.getValue(); - } else if (SubSetList.getPacketType().equals(packet.getUnits())) { - list = (List) packet.getValue(); - } - } - return list; - } + NCWFFeature detect = ncwfReport.getDetection(); + view.setFloat("or_centroid_lat", + (float) detect.getCentroidLatitude()); + view.setFloat("or_centroid_lon", + (float) detect.getCentroidLongitude()); + int pos = 0; + for (Coordinate dc : detect + .getFeatureBoundary()) { + float lat = (float) DecoderTools + .getCoordinateLatitude(dc); + float lon = (float) DecoderTools + .getCoordinateLongitude(dc); + view.setFloat("oalat", lat, pos); + view.setFloat("oalon", lon, pos++); + } + view.setInt("or_num_of_vertices", pos); + NCWFFeature forecast = ncwfReport.getForecast(); + view.setFloat("centroid_lat", + (float) forecast.getCentroidLatitude()); + view.setFloat("centroid_lon", + (float) forecast.getCentroidLongitude()); + pos = 0; + for (Coordinate dc : forecast + .getFeatureBoundary()) { + float lat = (float) DecoderTools + .getCoordinateLatitude(dc); + float lon = (float) DecoderTools + .getCoordinateLongitude(dc); + view.setFloat("alat", lat, pos); + view.setFloat("alon", lon, pos++); + } + view.setInt("num_of_vertices", pos); + + ncwfReport.setPointDataView(view); + reports.add(ncwfReport); + } + } + } + } + } + } + return reports; + } + + @SuppressWarnings("unchecked") + private BUFRncwf getReport(IBUFRDataPacket packet) { + BUFRncwf ncwfReport = null; + if (packet != null) { + List sList = (List) packet + .getValue(); + + Calendar c = getTimeInfo(sList); + if (c != null) { + ncwfReport = new BUFRncwf(); + + ncwfReport.setDataTime(new DataTime(TimeTools.copy(c))); + List features = getPacketSubList(sList + .get(FEATURES_POS)); + + ncwfReport + .setDetection(getFeatureData(getPacketSubList(features + .get(0)))); + ncwfReport.setForecast(getFeatureData(getPacketSubList(features + .get(1)))); + + double height = getDouble(sList.get(STORM_TOP_POS), INVALID); + if (height >= 0) { + height = Math.floor((height * 3.280839) / 100); + } + ncwfReport.setStormTop(height); + ncwfReport.setStormDir(getDouble(sList.get(STORM_DIR_POS), + INVALID)); + ncwfReport.setStormSpeed(getDouble(sList.get(STORM_SPD_POS), + INVALID)); + if (ncwfReport.getDetection() != null) { + Coordinate centroid = ncwfReport.getDetection() + .getCentroidLocation(); + SurfaceObsLocation loc = new SurfaceObsLocation(); + loc.assignLocation( + DecoderTools.getCoordinateLatitude(centroid), + DecoderTools.getCoordinateLongitude(centroid)); + ncwfReport.setLocation(loc); + } + } + } + return ncwfReport; + } + + private NCWFFeature getFeatureData(List featureList) { + NCWFFeature feature = null; + if ((featureList != null) && (featureList.size() > 0)) { + // 0 0 08 021 : CODE TABLE Comments: Time significance + // 1 0 04 026 : Second Comments: Time period or displacement + // 2 0 08 005 : Comments: Meteorological attribute significance + // 3 0 08 007 : Comments: Dimensional significance + // 4 0 05 001 : Comments: Latitude (high accuracy) + // 5 0 06 001 : Comments: Longitude (high accuracy) + // 6 0 08 005 : Comments: Meteorological attribute significance + // 7 0 08 007 : Comments: Dimensional significance + // 8 1 01 000 : Comments: Boundary-Sublist + + double lat = getDouble(featureList.get(FEATURE_LAT_POS), INVALID); + double lon = getDouble(featureList.get(FEATURE_LON_POS), INVALID); + if ((lat != INVALID) && (lon != INVALID)) { + feature = new NCWFFeature(lat, lon); + + IBUFRDataPacket p1 = featureList.get(BOUNDARY_SUBLIST_POS); + feature.setFeatureBoundary(getVertices(getPacketSubList(p1))); + } + } + return feature; + } + + /** + * + * @param vertexList + * @return + */ + private List getVertices(List vertexList) { + List vertices = new ArrayList(); + if (vertexList != null) { + for (IBUFRDataPacket p : vertexList) { + List vertex = getPacketSubList(p); + double lat = getDouble(vertex.get(VERTEX_LAT_POS), INVALID); + double lon = getDouble(vertex.get(VERTEX_LON_POS), INVALID); + if ((lat != INVALID) && (lon != INVALID)) { + vertices.add(DecoderTools.createCoordinate(lat, lon)); + } + } + } + return vertices; + } + + /** + * + * @param dataList + * @return + */ + private Calendar getTimeInfo(List dataList) { + + int year = getInt(dataList.get(YEAR_POS), IDecoderConstants.VAL_MISSING); + int month = getInt(dataList.get(MONTH_POS), + IDecoderConstants.VAL_MISSING); + int day = getInt(dataList.get(DAY_POS), IDecoderConstants.VAL_MISSING); + int hour = getInt(dataList.get(HOUR_POS), IDecoderConstants.VAL_MISSING); + int minute = getInt(dataList.get(MINUTE_POS), + IDecoderConstants.VAL_MISSING); + int second = getInt(dataList.get(SECOND_POS), + IDecoderConstants.VAL_MISSING); + + Calendar baseTime = null; + + // Ensure that we have all of the time info and create the + // date-time and datatime info. + if ((year > 0) && (month > 0) && (day > 0) && (hour >= 0) + && (minute >= 0) && (second >= 0)) { + baseTime = TimeTools.getBaseCalendar(year, month, day); + baseTime.set(Calendar.HOUR_OF_DAY, hour); + baseTime.set(Calendar.MINUTE, minute); + baseTime.set(Calendar.SECOND, second); + baseTime.set(Calendar.MILLISECOND, 0); + } + return baseTime; + } + + /** + * + * @param packet + * @return + */ + @SuppressWarnings("unchecked") + private static List getPacketSubList(IBUFRDataPacket packet) { + List list = null; + if (packet instanceof BUFRSublistPacket) { + if (RepSubList.getPacketType().equals(packet.getUnits())) { + list = (List) packet.getValue(); + } else if (SubSetList.getPacketType().equals(packet.getUnits())) { + list = (List) packet.getValue(); + } + } + return list; + } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrquikscat/src/com/raytheon/uf/edex/plugin/bufrquikscat/decoder/QUIKScatDataAdapter.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrquikscat/src/com/raytheon/uf/edex/plugin/bufrquikscat/decoder/QUIKScatDataAdapter.java index e7604a748a..ca115d97f4 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrquikscat/src/com/raytheon/uf/edex/plugin/bufrquikscat/decoder/QUIKScatDataAdapter.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrquikscat/src/com/raytheon/uf/edex/plugin/bufrquikscat/decoder/QUIKScatDataAdapter.java @@ -45,7 +45,8 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080303 969 jkorman Initial implementation. + * Mar 03, 2008 969 jkorman Initial implementation. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -55,21 +56,29 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; public class QUIKScatDataAdapter extends BUFRPointDataAdapter { // Note inverted logic private static final int RAIN_FLAG_NOT_USABLE = 0x00001000; - private static final int RAIN_FLAG = 0x00002000; - - private static final int RAIN_DATA_MASK = RAIN_FLAG_NOT_USABLE | RAIN_FLAG; - - private static final int RAIN_NOT_PRESENT = 0x00000000; - private static final int RAIN_PRESENT = RAIN_FLAG; - - private static final int YEAR_POS = 2; - private static final int MONTH_POS = 3; - private static final int DAY_POS = 4; - private static final int HOUR_POS = 5; + + private static final int RAIN_FLAG = 0x00002000; + + private static final int RAIN_DATA_MASK = RAIN_FLAG_NOT_USABLE | RAIN_FLAG; + + private static final int RAIN_NOT_PRESENT = 0x00000000; + + private static final int RAIN_PRESENT = RAIN_FLAG; + + private static final int YEAR_POS = 2; + + private static final int MONTH_POS = 3; + + private static final int DAY_POS = 4; + + private static final int HOUR_POS = 5; + private static final int MINUTE_POS = 6; + private static final int SECOND_POS = 7; private static final int SAT_ID_POS = 0; + private static final int ORBIT_N_POS = 1; /** @@ -78,8 +87,9 @@ public class QUIKScatDataAdapter extends BUFRPointDataAdapter { * @param dao * @param pluginName */ - public QUIKScatDataAdapter(PointDataDescription pdd, PointDataPluginDao dao, String pluginName) { - super(pdd,dao,pluginName); + public QUIKScatDataAdapter(PointDataDescription pdd, + PointDataPluginDao dao, String pluginName) { + super(pdd, dao, pluginName); } /** @@ -93,53 +103,56 @@ public class QUIKScatDataAdapter extends BUFRPointDataAdapter { * @return A ProfilerObs instance, or null in the event of an error. */ @Override - public QUIKScatObs createData( - Iterator iterator, WMOHeader wmoHeader) { + public QUIKScatObs createData(Iterator iterator, + WMOHeader wmoHeader) { QUIKScatObs obsData = null; BUFRDataDocument dataDoc = iterator.next(); - + if (dataDoc != null) { // Get the primary data list. List dataList = dataDoc.getList(); - + obsData = getHeaderData(dataList); - if(obsData != null) { + if (obsData != null) { // pickup the data. - obsData.setPluginName(getPluginName()); obsData.setWmoHeader(wmoHeader.getWmoHeader()); PointDataContainer container = getContainer(obsData); - if(container != null) { - + if (container != null) { + logger.debug("Creating obs data "); - PointDataView view = container.append(); + PointDataView view = container.append(); // view.setInt("satelliteID", obsData.getSatId()); view.setInt("orbitNumber", obsData.getOrbitNumber()); - view.setLong("validTime",obsData.getTimeObs().getTimeInMillis()); - - double lat = getDouble(dataList.get(8), IDecoderConstants.VAL_MISSING); - double lon = getDouble(dataList.get(9), IDecoderConstants.VAL_MISSING); - + view.setLong("validTime", obsData.getTimeObs() + .getTimeInMillis()); + + double lat = getDouble(dataList.get(8), + IDecoderConstants.VAL_MISSING); + double lon = getDouble(dataList.get(9), + IDecoderConstants.VAL_MISSING); + SurfaceObsLocation location = new SurfaceObsLocation(); - location.assignLocation(lat,lon); + location.assignLocation(lat, lon); obsData.setLocation(location); - view.setFloat("latitude",(float) lat); - view.setFloat("longitude",(float) lon); - - int rainFlag = getInt(dataList.get(10),IDecoderConstants.VAL_MISSING); - switch((rainFlag & RAIN_DATA_MASK)) { - case RAIN_NOT_PRESENT : { + view.setFloat("latitude", (float) lat); + view.setFloat("longitude", (float) lon); + + int rainFlag = getInt(dataList.get(10), + IDecoderConstants.VAL_MISSING); + switch ((rainFlag & RAIN_DATA_MASK)) { + case RAIN_NOT_PRESENT: { rainFlag = 0; break; } - case RAIN_PRESENT : { + case RAIN_PRESENT: { rainFlag = 1; break; } - default : { // + default: { // rainFlag = -9999; break; } @@ -147,22 +160,23 @@ public class QUIKScatDataAdapter extends BUFRPointDataAdapter { view.setInt("rainIndex", rainFlag); setViewData("probRain", view, dataList.get(11)); // Wind data - float val = (float) getDouble(dataList.get(12), PDV_FILL_DBL); - if(val < 0) { + float val = (float) getDouble(dataList.get(12), + PDV_FILL_DBL); + if (val < 0) { val = (float) PDV_FILL_DBL; } view.setFloat("windSpd", val); val = (float) getDouble(dataList.get(13), PDV_FILL_DBL); - if(val < 0) { + if (val < 0) { val = (float) PDV_FILL_DBL; } view.setFloat("windDir", val); - + obsData.setPointDataView(view); } } } - + return obsData; } @@ -176,7 +190,7 @@ public class QUIKScatDataAdapter extends BUFRPointDataAdapter { return obsList; } - + /** * * @param dataList @@ -184,21 +198,24 @@ public class QUIKScatDataAdapter extends BUFRPointDataAdapter { */ private QUIKScatObs getHeaderData(List dataList) { QUIKScatObs obsData = null; - + Calendar obsTime = getTimeInfo(dataList); - if(obsTime != null) { + if (obsTime != null) { obsData = new QUIKScatObs(); obsData.setTimeObs(obsTime); obsData.setDataTime(new DataTime(TimeTools.copy(obsTime))); - int satId = getInt(dataList.get(SAT_ID_POS), IDecoderConstants.VAL_MISSING); - int orbNo = getInt(dataList.get(ORBIT_N_POS), IDecoderConstants.VAL_MISSING); - - logger.debug("getHeaderData(" + satId + "," + orbNo + ")" + obsData.getDataTime()); - - if(satId != IDecoderConstants.VAL_MISSING) { + int satId = getInt(dataList.get(SAT_ID_POS), + IDecoderConstants.VAL_MISSING); + int orbNo = getInt(dataList.get(ORBIT_N_POS), + IDecoderConstants.VAL_MISSING); + + logger.debug("getHeaderData(" + satId + "," + orbNo + ")" + + obsData.getDataTime()); + + if (satId != IDecoderConstants.VAL_MISSING) { obsData.setSatId(satId); - if(orbNo != IDecoderConstants.VAL_MISSING) { + if (orbNo != IDecoderConstants.VAL_MISSING) { obsData.setOrbitNumber(orbNo); } else { obsData = null; @@ -209,26 +226,30 @@ public class QUIKScatDataAdapter extends BUFRPointDataAdapter { } return obsData; } - + /** * * @param dataList * @return */ private Calendar getTimeInfo(List dataList) { - - int year = getInt(dataList.get(YEAR_POS),IDecoderConstants.VAL_MISSING); - int month = getInt(dataList.get(MONTH_POS),IDecoderConstants.VAL_MISSING); - int day = getInt(dataList.get(DAY_POS),IDecoderConstants.VAL_MISSING); - int hour = getInt(dataList.get(HOUR_POS),IDecoderConstants.VAL_MISSING); - int minute = getInt(dataList.get(MINUTE_POS),IDecoderConstants.VAL_MISSING); - int second = getInt(dataList.get(SECOND_POS),IDecoderConstants.VAL_MISSING); - + + int year = getInt(dataList.get(YEAR_POS), IDecoderConstants.VAL_MISSING); + int month = getInt(dataList.get(MONTH_POS), + IDecoderConstants.VAL_MISSING); + int day = getInt(dataList.get(DAY_POS), IDecoderConstants.VAL_MISSING); + int hour = getInt(dataList.get(HOUR_POS), IDecoderConstants.VAL_MISSING); + int minute = getInt(dataList.get(MINUTE_POS), + IDecoderConstants.VAL_MISSING); + int second = getInt(dataList.get(SECOND_POS), + IDecoderConstants.VAL_MISSING); + Calendar baseTime = null; - + // Ensure that we have all of the time info and create the // date-time and datatime info. - if ((year > 0) && (month > 0) && (day > 0) && (hour >= 0)&& (minute >= 0)&& (second >= 0)) { + if ((year > 0) && (month > 0) && (day > 0) && (hour >= 0) + && (minute >= 0) && (second >= 0)) { baseTime = TimeTools.getBaseCalendar(year, month, day); baseTime.set(Calendar.HOUR_OF_DAY, hour); baseTime.set(Calendar.MINUTE, minute); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrsigwx/src/com/raytheon/uf/edex/plugin/bufrsigwx/SigWxDecoder.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrsigwx/src/com/raytheon/uf/edex/plugin/bufrsigwx/SigWxDecoder.java index 067a7f2ecd..4910740310 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrsigwx/src/com/raytheon/uf/edex/plugin/bufrsigwx/SigWxDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrsigwx/src/com/raytheon/uf/edex/plugin/bufrsigwx/SigWxDecoder.java @@ -42,7 +42,8 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 21, 2009 1939 jkorman Initial creation + * Jan 21, 2009 1939 jkorman Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -52,7 +53,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; public class SigWxDecoder extends AbstractBUFRDecoder { - private PointDataDescription pdd = null; + private final PointDataDescription pdd = null; private SigWxDataDao dao; @@ -69,21 +70,23 @@ public class SigWxDecoder extends AbstractBUFRDecoder { * */ @Override - public List decodeData(List document, String traceId, WMOHeader wmoHeader) { + public List decodeData(List document, + String traceId, WMOHeader wmoHeader) { - List decodedData = null; - if(document != null) { + List decodedData = null; + if (document != null) { decodedData = new ArrayList(); - SigWxDataAdapter adapter = SigWxDataAdapter.getAdapter(pdd, dao, traceId, wmoHeader); + SigWxDataAdapter adapter = SigWxDataAdapter.getAdapter(pdd, dao, + traceId, wmoHeader); logger.debug(traceId + " - Document size = " + document.size()); Iterator iterator = document.iterator(); while (iterator.hasNext()) { logger.debug(traceId + " - Entering createDataList"); - List sigwx = adapter.createDataList(iterator, wmoHeader); + List sigwx = adapter.createDataList(iterator, + wmoHeader); if (sigwx != null) { - for(SigWxData d : sigwx) { - d.setPluginName(getPluginName()); + for (SigWxData d : sigwx) { d.setTraceId(traceId); try { d.constructDataURI(); @@ -100,23 +103,23 @@ public class SigWxDecoder extends AbstractBUFRDecoder { } return decodedData; } - + /** * * @param recreate */ @Override protected void createDAO(boolean recreate) { - if(recreate) { + if (recreate) { dao = null; } try { dao = new SigWxDataDao(pluginName); } catch (Exception e) { - logger.error("SigWxDataDao creation failed",e); + logger.error("SigWxDataDao creation failed", e); logger.error("Plugin set to failSafe mode"); setFailSafe(true); } } - + } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrsigwx/src/com/raytheon/uf/edex/plugin/bufrsigwx/decoder/SigWxDataAdapter.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrsigwx/src/com/raytheon/uf/edex/plugin/bufrsigwx/decoder/SigWxDataAdapter.java index 1eff18adc7..ed45dd0fe7 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrsigwx/src/com/raytheon/uf/edex/plugin/bufrsigwx/decoder/SigWxDataAdapter.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrsigwx/src/com/raytheon/uf/edex/plugin/bufrsigwx/decoder/SigWxDataAdapter.java @@ -19,7 +19,6 @@ **/ package com.raytheon.uf.edex.plugin.bufrsigwx.decoder; - import static com.raytheon.uf.edex.decodertools.bufr.packets.DataPacketTypes.RepSubList; import static com.raytheon.uf.edex.decodertools.bufr.packets.DataPacketTypes.SubSetList; @@ -52,8 +51,9 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20080303 969 jkorman Initial implementation. - * 20090706 2538 jsanchez Added latitude,longitude to point data. + * Mar 03, 2008 969 jkorman Initial implementation. + * Jul 06, 2009 2538 jsanchez Added latitude,longitude to point data. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -64,30 +64,37 @@ public abstract class SigWxDataAdapter extends BUFRPointDataAdapter { private static Log logger = LogFactory.getLog(SigWxDataAdapter.class); - private static final int YEAR_POS = 0; - private static final int MONTH_POS = 1; - private static final int DAY_POS = 2; - private static final int HOUR_POS = 3; + private static final int YEAR_POS = 0; + + private static final int MONTH_POS = 1; + + private static final int DAY_POS = 2; + + private static final int HOUR_POS = 3; + private static final int MINUTE_POS = 4; private static final int TIME_SIG_FCST = 4; - + private static final int BASE_HGT_POS = 13; + private static final int TOP_HGT_POS = 14; - + private static final int MID_LYR_BASE = 3050; + private static final int HI_LYR_TOP = 19200; - + static final int MISSING = PointDataDescription.FILL_VALUE_INT; - + /** * * @param pdd * @param dao * @param pluginName */ - public SigWxDataAdapter(PointDataDescription pdd, PointDataPluginDao dao, String pluginName) { - super(pdd,dao,pluginName); + public SigWxDataAdapter(PointDataDescription pdd, + PointDataPluginDao dao, String pluginName) { + super(pdd, dao, pluginName); } /** @@ -101,8 +108,8 @@ public abstract class SigWxDataAdapter extends BUFRPointDataAdapter { * @return A ProfilerObs instance, or null in the event of an error. */ @Override - public SigWxData createData( - Iterator iterator, WMOHeader wmoHeader) { + public SigWxData createData(Iterator iterator, + WMOHeader wmoHeader) { return null; } @@ -111,8 +118,9 @@ public abstract class SigWxDataAdapter extends BUFRPointDataAdapter { * @param iterator * @param wmoHeader */ - public List createDataList( - Iterator iterator, WMOHeader wmoHeader) { + @Override + public List createDataList(Iterator iterator, + WMOHeader wmoHeader) { List tropList = null; @@ -125,9 +133,8 @@ public abstract class SigWxDataAdapter extends BUFRPointDataAdapter { // Extract the header data. sigWx = getHeaderData(dataList); - + if (sigWx != null) { - sigWx.setPluginName(getPluginName()); sigWx.setWmoHeader(wmoHeader.getWmoHeader()); sigWx.setWxType(getType()); // Go collect the data specific to the data being decoded. @@ -136,7 +143,7 @@ public abstract class SigWxDataAdapter extends BUFRPointDataAdapter { } return tropList; } - + /** * * @param dataList @@ -149,7 +156,7 @@ public abstract class SigWxDataAdapter extends BUFRPointDataAdapter { if (TIME_SIG_FCST == timeSig) { Calendar baseTime = getTimeInfo(dataList, 2); Calendar fcstTime = getTimeInfo(dataList, 8); - if ((fcstTime != null)&&(baseTime != null)) { + if ((fcstTime != null) && (baseTime != null)) { sigWx = new SigWxData(); int fcstSeconds = (int) (fcstTime.getTimeInMillis() - baseTime @@ -179,25 +186,26 @@ public abstract class SigWxDataAdapter extends BUFRPointDataAdapter { } return sigWx; } - + /** * * @param dataList * @return */ private Calendar getTimeInfo(List dataList, int basePos) { - - int year = getInt(dataList.get(basePos + YEAR_POS),MISSING); - int month = getInt(dataList.get(basePos + MONTH_POS),MISSING); - int day = getInt(dataList.get(basePos + DAY_POS),MISSING); - int hour = getInt(dataList.get(basePos + HOUR_POS),MISSING); - int minute = getInt(dataList.get(basePos + MINUTE_POS),MISSING); - + + int year = getInt(dataList.get(basePos + YEAR_POS), MISSING); + int month = getInt(dataList.get(basePos + MONTH_POS), MISSING); + int day = getInt(dataList.get(basePos + DAY_POS), MISSING); + int hour = getInt(dataList.get(basePos + HOUR_POS), MISSING); + int minute = getInt(dataList.get(basePos + MINUTE_POS), MISSING); + Calendar baseTime = null; - + // Ensure that we have all of the time info and create the // date-time and datatime info. - if ((year > 0) && (month > 0) && (day > 0) && (hour >= 0)&& (minute >= 0)) { + if ((year > 0) && (month > 0) && (day > 0) && (hour >= 0) + && (minute >= 0)) { baseTime = TimeTools.getBaseCalendar(year, month, day); baseTime.set(Calendar.HOUR_OF_DAY, hour); baseTime.set(Calendar.MINUTE, minute); @@ -206,21 +214,21 @@ public abstract class SigWxDataAdapter extends BUFRPointDataAdapter { } return baseTime; } - + /** * * @param sigWx * @param index */ - abstract List getSigWxData(SigWxData sigWx, List dataList); - + abstract List getSigWxData(SigWxData sigWx, + List dataList); + /** * * @return */ abstract SigWxType getType(); - abstract void setType(SigWxType type); /** @@ -231,7 +239,7 @@ public abstract class SigWxDataAdapter extends BUFRPointDataAdapter { @SuppressWarnings("unchecked") static List getPacketSubList(IBUFRDataPacket packet) { List list = null; - if(packet instanceof BUFRSublistPacket) { + if (packet instanceof BUFRSublistPacket) { if (RepSubList.getPacketType().equals(packet.getUnits())) { list = (List) packet.getValue(); } else if (SubSetList.getPacketType().equals(packet.getUnits())) { @@ -302,23 +310,26 @@ public abstract class SigWxDataAdapter extends BUFRPointDataAdapter { adapter.setType(SigWxType.VTS); } else { adapter = new SigWxNullData(pdd, dao, pluginName); - logger.error("No decoder adapter for file " + wmoHeader.getWmoHeader()); + logger.error("No decoder adapter for file " + + wmoHeader.getWmoHeader()); } return adapter; } private static PointDataDescription loadPDD(String pddFileName) { - + PointDataDescription pdd = null; try { - pdd = PointDataDescription.fromStream(SigWxDataAdapter.class.getResourceAsStream(pddFileName)); + pdd = PointDataDescription.fromStream(SigWxDataAdapter.class + .getResourceAsStream(pddFileName)); logger.info(pddFileName + "PointDataDescription loaded"); - - } catch(Exception e) { - logger.error("PointDataDescription failed loading " + pddFileName,e); + + } catch (Exception e) { + logger.error("PointDataDescription failed loading " + pddFileName, + e); } - + return pdd; } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.bufrssmi/src/com/raytheon/uf/edex/plugin/bufrssmi/decoder/SSMIDataAdapter.java b/edexOsgi/com.raytheon.uf.edex.plugin.bufrssmi/src/com/raytheon/uf/edex/plugin/bufrssmi/decoder/SSMIDataAdapter.java index 3ed5ec1706..39a7fb75c8 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.bufrssmi/src/com/raytheon/uf/edex/plugin/bufrssmi/decoder/SSMIDataAdapter.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.bufrssmi/src/com/raytheon/uf/edex/plugin/bufrssmi/decoder/SSMIDataAdapter.java @@ -53,6 +53,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * Jul 06, 2009 2538 jsanchez Added latitude,longitude to point data. * May 17, 2013 1869 bsteffen Remove DataURI column from sat plot * types. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -114,7 +115,6 @@ public class SSMIDataAdapter extends BUFRPointDataAdapter { if (obsData != null) { // Need to set plugin name before getting container! - obsData.setPluginName(getPluginName()); PointDataContainer container = getContainer(obsData); if (container != null) { PointDataView view = container.append(); @@ -138,6 +138,7 @@ public class SSMIDataAdapter extends BUFRPointDataAdapter { /** * */ + @Override @SuppressWarnings("unchecked") public List createDataList( Iterator iterator, WMOHeader wmoHeader) { @@ -182,7 +183,6 @@ public class SSMIDataAdapter extends BUFRPointDataAdapter { // Make a copy for each data point. SSMIScanData pointData = obsData.copyObs(); // Need to set plugin name before getting container! - pointData.setPluginName(getPluginName()); pointData = getPointData(pointData, p, it.next()); if (pointData != null) { obsList.add(pointData); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.cwa/src/com/raytheon/uf/edex/plugin/cwa/decoder/CWAParser.java b/edexOsgi/com.raytheon.uf.edex.plugin.cwa/src/com/raytheon/uf/edex/plugin/cwa/decoder/CWAParser.java index 3d56c3ad2c..e0c25617ec 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.cwa/src/com/raytheon/uf/edex/plugin/cwa/decoder/CWAParser.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.cwa/src/com/raytheon/uf/edex/plugin/cwa/decoder/CWAParser.java @@ -60,10 +60,10 @@ import com.vividsolutions.jts.geom.Coordinate; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Feb 01, 2010 jsanchez Initial creation - * Apr 18, 2012 #473 dgilling Modify parser to set - * DataTime based on ingest - * file name. + * Feb 01, 2010 jsanchez Initial creation + * Apr 18, 2012 473 dgilling Modify parser to set DataTime based on + * ingest file name. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -72,7 +72,7 @@ import com.vividsolutions.jts.geom.Coordinate; */ public class CWAParser { /** The logger */ - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); private final PointDataDescription pointDataDescription; @@ -80,11 +80,11 @@ public class CWAParser { private final CWARecordDao cwaDao; - private Map containerMap; + private final Map containerMap; private final GeodeticCalculator gc = new GeodeticCalculator(); - private String pluginName; + private final String pluginName; private String eventId; @@ -98,7 +98,7 @@ public class CWAParser { private CWADimension dimension; - private List coordinates = new ArrayList(); + private final List coordinates = new ArrayList(); boolean isVicinity; @@ -108,7 +108,7 @@ public class CWAParser { int currentReport = -1; - private HashMap URI_MAP = new HashMap(); + private final HashMap URI_MAP = new HashMap(); private static HashMap dirToDeg = new HashMap(); @@ -258,7 +258,8 @@ public class CWAParser { String s = iRpt.getReportLine(); switch (iRpt.getLineType()) { case ISSUANCE: - if (eventId != null && dimension != CWADimension.CANCELED) { + if ((eventId != null) + && (dimension != CWADimension.CANCELED)) { reports.add(getRecord()); } clearData(); @@ -286,7 +287,8 @@ public class CWAParser { } break; case END: - if (eventId != null && dimension != CWADimension.CANCELED) { + if ((eventId != null) + && (dimension != CWADimension.CANCELED)) { reports.add(getRecord()); } clearData(); @@ -322,7 +324,7 @@ public class CWAParser { private void parseIssuanceInfo(String issuanceInfo) { String[] parts = issuanceInfo.split(" "); - if (parts != null && parts[0] != null) { + if ((parts != null) && (parts[0] != null)) { eventId = parts[0]; } @@ -412,7 +414,7 @@ public class CWAParser { } dimension = CWADimension.AREA; distance = 0; - } else if (tok.length() == 0 || tok.equals("")) { + } else if ((tok.length() == 0) || tok.equals("")) { getMoreCoords = true; } else { logger.error("Bad location. '" + tok @@ -444,7 +446,7 @@ public class CWAParser { } } - if (!found && size == 0 && (isVicinity || coordinates.size() > 0)) { + if (!found && (size == 0) && (isVicinity || (coordinates.size() > 0))) { size = 2000; // 2 km = 2000 m } } @@ -474,7 +476,6 @@ public class CWAParser { record.setEventId(eventId); record.setDimension(dimension); record.setMessageData(text); - record.setPluginName(pluginName); // TimeRange tr = new TimeRange( // startTime.getRefTimeAsCalendar(), // endTime.getRefTimeAsCalendar()); @@ -485,7 +486,7 @@ public class CWAParser { Coordinate[] coord = null; if (coordinates.size() == 1) { coord = Utility.makeArea(coordinates.get(0), size); - } else if (coordinates.size() == 2 && size > 0) { + } else if ((coordinates.size() == 2) && (size > 0)) { coord = Utility.makeArea( coordinates.toArray(new Coordinate[coordinates.size()]), size); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.cwat/src/com/raytheon/uf/edex/plugin/cwat/CWATGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.cwat/src/com/raytheon/uf/edex/plugin/cwat/CWATGenerator.java index 6705caa142..07b24b5946 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.cwat/src/com/raytheon/uf/edex/plugin/cwat/CWATGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.cwat/src/com/raytheon/uf/edex/plugin/cwat/CWATGenerator.java @@ -49,7 +49,8 @@ import com.raytheon.uf.edex.plugin.cwat.common.CWATConfig; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 02/25/13 1660 D. Hladky Fixed configuration bug in scan. + * Feb 25, 2013 1660 D. Hladky Fixed configuration bug in scan. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -68,7 +69,7 @@ public class CWATGenerator extends CompositeProductGenerator implements /** Set of icaos to filter for */ private Set icaos = null; - + /** run configuration manager **/ public SCANRunSiteConfigurationManager srcm = null; @@ -98,7 +99,7 @@ public class CWATGenerator extends CompositeProductGenerator implements if (!configValid) { statusHandler.handle(Priority.WARN, - "Configuration for CWAT(scan) is invalid!!!"); + "Configuration for CWAT(scan) is invalid!!!"); return; } @@ -133,7 +134,7 @@ public class CWATGenerator extends CompositeProductGenerator implements cwa_config = new CWATConfig(genMessage, this); } catch (Exception e) { statusHandler.handle(Priority.ERROR, - "CWAT Configuration parameters for run not met...",e); + "CWAT Configuration parameters for run not met...", e); return; } @@ -156,8 +157,6 @@ public class CWATGenerator extends CompositeProductGenerator implements + cwa_config.getVil().getNumBins()); } - cwaRec.setPluginName(cwa_config.getGenerator() - .getCompositeProductType()); cwaRec.setIcao(cwa_config.getIcao()); cwaRec.setDataTime(new DataTime(cwa_config.getCZ().getDataTime() .getRefTime())); @@ -193,7 +192,7 @@ public class CWATGenerator extends CompositeProductGenerator implements resetFilters(); } } - + /** * run config manager * diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java index 2cc6408d3d..e27d61d78c 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java @@ -32,7 +32,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.regex.Pattern; -import com.raytheon.uf.common.dataplugin.message.DataURINotificationMessage; import com.raytheon.edex.plugin.radar.dao.RadarStationDao; import com.raytheon.edex.urifilter.URIFilter; import com.raytheon.edex.urifilter.URIGenerateMessage; @@ -48,6 +47,7 @@ import com.raytheon.uf.common.dataplugin.ffmp.FFMPTemplates.MODE; import com.raytheon.uf.common.dataplugin.ffmp.FFMPUtils; import com.raytheon.uf.common.dataplugin.ffmp.SourceBinList; import com.raytheon.uf.common.dataplugin.ffmp.dao.FFMPDao; +import com.raytheon.uf.common.dataplugin.message.DataURINotificationMessage; import com.raytheon.uf.common.dataplugin.radar.RadarStation; import com.raytheon.uf.common.dataplugin.radar.util.RadarsInUseUtil; import com.raytheon.uf.common.datastorage.DataStoreFactory; @@ -114,17 +114,28 @@ import com.raytheon.uf.edex.plugin.ffmp.common.FFTIRatioDiff; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 06/21/2009 2521 dhladky Initial Creation. - * 02/03/2011 6500 cjeanbap Fixed NullPointerException. - * 07/31/2011 578 dhladky FFTI modifications - * 01/27/13 1478 D. Hladky Added creation of full cache records to help read write stress on NAS - * 02/01/13 1569 D. Hladky Added constants, switched to using aggregate records written through pypies - * 02/20/13 1635 D. Hladky Added some finally methods to increase dead lock safety. Reduced wait times for threads. - * 02/25/13 1660 D. Hladky Redesigned data flow for FFTI in order to have only one mosaic piece in memory at a time. - * 03/13/13 1478 D. Hladky non-FFTI mosaic containers weren't getting ejected. Made it so that they are ejected after processing as well. - * 03/22/13 1803 D. Hladky Fixed broken performance logging for ffmp. - * 07/03/13 2131 D. Hladky InitialLoad array was forcing total FDC re-query with every update. - * Jul 15, 2013 2184 dhladky Remove all HUC's for storage except ALL + * Jun 21, 2009 2521 dhladky Initial Creation. + * Feb 03, 2011 6500 cjeanbap Fixed NullPointerException. + * Jul 31, 2011 578 dhladky FFTI modifications + * Jan 27, 2013 1478 D. Hladky Added creation of full cache records to + * help read write stress on NAS + * Feb 01, 2013 1569 D. Hladky Added constants, switched to using + * aggregate records written through pypies + * Feb 20, 2013 1635 D. Hladky Added some finally methods to increase + * dead lock safety. Reduced wait times for + * threads. + * Feb 25, 2013 1660 D. Hladky Redesigned data flow for FFTI in order to + * have only one mosaic piece in memory at a + * time. + * Mar 13, 2013 1478 D. Hladky non-FFTI mosaic containers weren't + * getting ejected. Made it so that they + * are ejected after processing as well. + * Mar 22, 2013 1803 D. Hladky Fixed broken performance logging for + * ffmp. + * Jul 03, 2013 2131 D. Hladky InitialLoad array was forcing total FDC + * re-query with every update. + * Jul 15, 2013 2184 dhladky Remove all HUC's for storage except ALL + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author dhladky @@ -408,9 +419,9 @@ public class FFMPGenerator extends CompositeProductGenerator implements if (messages instanceof DataURINotificationMessage) { URIFilter[] filters = getFilters(); if (filters != null) { - for (int i = 0; i < filters.length; i++) { - if (filters[i] != null) { - FFMPURIFilter filter = (FFMPURIFilter) filters[i]; + for (URIFilter filter2 : filters) { + if (filter2 != null) { + FFMPURIFilter filter = (FFMPURIFilter) filter2; if (loaded) { @@ -682,7 +693,6 @@ public class FFMPGenerator extends CompositeProductGenerator implements ffmpRec.setSourceName(ffmpProduct.getSourceName()); ffmpRec.setDataKey(dataKey); ffmpRec.setSiteKey(siteKey); - ffmpRec.setPluginName(getCompositeProductType()); ffmpRec.setWfo(config.getCWA()); FFMPProcessor ffmp = new FFMPProcessor(config, generator, ffmpRec, template); @@ -890,7 +900,7 @@ public class FFMPGenerator extends CompositeProductGenerator implements if (source.isRfc()) { int i = 0; for (String dataKey : ingest.getDataKey()) { - if (i < ingest.getDataKey().size() - 1) { + if (i < (ingest.getDataKey().size() - 1)) { buf.append(dataKey + ","); } else { buf.append(dataKey); @@ -1234,7 +1244,6 @@ public class FFMPGenerator extends CompositeProductGenerator implements - (TimeUtil.MILLIS_PER_HOUR * SOURCE_CACHE_TIME)); } - // pull from disk if there fdc = getFFMPDataContainer(sourceSiteDataKey, backDate); @@ -1265,7 +1274,7 @@ public class FFMPGenerator extends CompositeProductGenerator implements Date newDate = fdc.getNewest(); Date oldDate = fdc.getOldest(); - if (newDate != null && oldDate != null) { + if ((newDate != null) && (oldDate != null)) { if ((ffmpRec.getDataTime().getRefTime().getTime() - newDate .getTime()) >= (source .getExpirationMinutes(ffmpRec.getSiteKey()) * TimeUtil.MILLIS_PER_MINUTE)) { @@ -1377,14 +1386,14 @@ public class FFMPGenerator extends CompositeProductGenerator implements } // condition for first time read in - if (fdc == null && record != null) { + if ((fdc == null) && (record != null)) { // creates a place holder for this source fdc = new FFMPDataContainer(sourceSiteDataKey, record); populated = true; } // condition for update to fdc while in use - if (record != null && !populated) { + if ((record != null) && !populated) { fdc.setAggregateData(record); } @@ -1444,10 +1453,11 @@ public class FFMPGenerator extends CompositeProductGenerator implements */ private class WriteAggregateRecord implements Runnable { - private FFMPDataContainer fdc; + private final FFMPDataContainer fdc; - private String sourceSiteDataKey; + private final String sourceSiteDataKey; + @Override public void run() { try { write(); @@ -1750,7 +1760,7 @@ public class FFMPGenerator extends CompositeProductGenerator implements } // This will only happen at initial load, update, and duration changes. - if (accumulator.isReset() || accumulator.getDuration() != duration) { + if (accumulator.isReset() || (accumulator.getDuration() != duration)) { accumulator.setDuration(duration); accumulator.setUnit(unit); @@ -1852,7 +1862,7 @@ public class FFMPGenerator extends CompositeProductGenerator implements if (isFFTI(siteDataKey)) { values = (FFTIRatioDiff) getFFTIData(siteDataKey); - if (values.getGuids() == null || values.getQpes() == null) { + if ((values.getGuids() == null) || (values.getQpes() == null)) { values.setReset(true); } } else { @@ -1860,7 +1870,7 @@ public class FFMPGenerator extends CompositeProductGenerator implements } // This will only happen at initial load, update, and duration changes. - if (values.isReset() || values.getDuration() != duration) { + if (values.isReset() || (values.getDuration() != duration)) { values.setDuration(duration); values.setUnit(unit); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.fog/src/com/raytheon/uf/edex/plugin/fog/FogGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.fog/src/com/raytheon/uf/edex/plugin/fog/FogGenerator.java index bcfc14d19e..726258ecaa 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.fog/src/com/raytheon/uf/edex/plugin/fog/FogGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.fog/src/com/raytheon/uf/edex/plugin/fog/FogGenerator.java @@ -71,7 +71,6 @@ public class FogGenerator extends CompositeProductGenerator { FogRecord fogRec = new FogRecord(); this.setPluginDao(new FogDao(productType)); - fogRec.setPluginName(this.getCompositeProductType()); fogRec.setDataTime(this.getProductTime()); fogRec.setRefHour(TimeTools.roundToNearestHour(fogRec.getDataTime() .getValidTime())); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/common/FSSObsConfig.java b/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/common/FSSObsConfig.java index 04c05710cf..01f3a3ee1b 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/common/FSSObsConfig.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/common/FSSObsConfig.java @@ -41,7 +41,8 @@ import com.raytheon.uf.edex.plugin.fssobs.FSSObsUtils; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Nov 19, 2010 skorolev Initial creation + * Nov 19, 2010 skorolev Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -108,8 +109,8 @@ public class FSSObsConfig { tableRow.setRelativeHumidity(RH); } float[] snowData = FSSObsUtils.getSnowData(tableRow); - if (tableRow.getTemperature() != FSSObsUtils.MISSING - && tableRow.getDewpoint() != FSSObsUtils.MISSING) { + if ((tableRow.getTemperature() != FSSObsUtils.MISSING) + && (tableRow.getDewpoint() != FSSObsUtils.MISSING)) { // TODO to check if this is correct. calcdpd() in Meteolib tableRow.setDewpointDepr(tableRow.getTemperature() - tableRow.getDewpoint()); @@ -122,7 +123,6 @@ public class FSSObsConfig { tableRow.setWindChill(snowData[3]); tableRow.setFrostbiteTime(snowData[4]); - tableRow.setPluginName("fssobs"); tableRow.setCwa(cwa); tableRow.setMonitorUse(monitorUse); tableRow.setPlatformId(tableRow.getLocation().getStationId()); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ldadmesonet/src/com/raytheon/uf/edex/plugin/ldadmesonet/MesonetDecoder.java b/edexOsgi/com.raytheon.uf.edex.plugin.ldadmesonet/src/com/raytheon/uf/edex/plugin/ldadmesonet/MesonetDecoder.java index 1cdf0f192e..c6929e8080 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ldadmesonet/src/com/raytheon/uf/edex/plugin/ldadmesonet/MesonetDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ldadmesonet/src/com/raytheon/uf/edex/plugin/ldadmesonet/MesonetDecoder.java @@ -68,6 +68,7 @@ import com.raytheon.uf.common.time.DataTime; * ----------- ---------- ----------- -------------------------- * Sep 04, 2009 vkorolev Initial creation * May 15, 2013 1869 bsteffen Remove DataURI column from ldadmesonet. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author vkorolev @@ -84,7 +85,7 @@ public class MesonetDecoder extends AbstractDecoder implements private String traceId = null; private String currentFile = null; - + public SimpleDateFormat sdf = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); public File confile; @@ -190,7 +191,6 @@ public class MesonetDecoder extends AbstractDecoder implements MesonetLdadRecord record = new MesonetLdadRecord(); SurfaceObsLocation location = new SurfaceObsLocation(); record.setDataProvider(dd.provider); - record.setPluginName(PLUGIN_NAME); record.setStationType(dd.type); record.setReportTime(dd.reportTime); record.setReportType(dd.storageType); @@ -241,9 +241,9 @@ public class MesonetDecoder extends AbstractDecoder implements } } // for // DataTime = Observation time - + Calendar ot = record.getObservationTime(); - if(ot != null) { + if (ot != null) { DataTime dt = new DataTime(ot); record.setDataTime(dt); record.setLocation(location); @@ -306,21 +306,22 @@ public class MesonetDecoder extends AbstractDecoder implements cal.setTimeZone(TimeZone.getTimeZone("GMT")); cal.setTime(ot); val = cal; - } catch(Exception e) { + } catch (Exception e) { abort = true; - logger.error("Could not parse date field [" + name + ":" + value + "] for file " + currentFile); + logger.error("Could not parse date field [" + name + ":" + + value + "] for file " + currentFile); } // only numbers } else { - + // Get rid of some troublesome data // TODO: find out what should be done with these values abort = "B".equals(value); abort |= "R".equals(value); abort |= "V".equals(value); abort |= "NAN0".equals(value); - - if(!abort) { + + if (!abort) { Double tval = null; try { tval = Double.parseDouble(value); @@ -333,20 +334,21 @@ public class MesonetDecoder extends AbstractDecoder implements } if (configFile.containsKey(vunit)) { Unit inUnit = null; - + Unit outUnit = null; - + try { - inUnit = (Unit) UnitFormat - .getUCUMInstance().parseObject( - configFile.getProperty(vunit)); - outUnit = (Unit) UnitFormat - .getUCUMInstance().parseObject( - configFile.getProperty(name)); + inUnit = (Unit) UnitFormat.getUCUMInstance() + .parseObject(configFile.getProperty(vunit)); + outUnit = (Unit) UnitFormat.getUCUMInstance() + .parseObject(configFile.getProperty(name)); tval = inUnit.getConverterTo(outUnit).convert( (tval).doubleValue()); } catch (ConversionException ce) { - logger.error("Property[" + fld.getName() + "]Input unit " + inUnit.getStandardUnit() + " not compatable with Output unit " + outUnit.getStandardUnit()); + logger.error("Property[" + fld.getName() + + "]Input unit " + inUnit.getStandardUnit() + + " not compatable with Output unit " + + outUnit.getStandardUnit()); return; } } @@ -361,7 +363,7 @@ public class MesonetDecoder extends AbstractDecoder implements } } } - if(!abort) { + if (!abort) { Class types = clazz; Method method = obj.getClass().getMethod(mname, types); method.invoke(obj, val); @@ -432,8 +434,7 @@ public class MesonetDecoder extends AbstractDecoder implements Class cls = record.getClass(); Field fieldlist[] = cls.getDeclaredFields(); - for (int i = 0; i < fieldlist.length; i++) { - Field fld = fieldlist[i]; + for (Field fld : fieldlist) { System.out.println("name = " + fld.getName()); System.out.println("decl class = " + fld.getDeclaringClass().getSimpleName()); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java b/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java index b2129081ed..275044021b 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java @@ -52,7 +52,8 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 21, 2009 1939 jkorman Initial creation + * Jan 21, 2009 1939 jkorman Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -137,18 +138,18 @@ public class LSRParser { } // private Pattern rptStartPtrn = Pattern.compile(TIME_PTRN); - private Pattern latlanPtrn = Pattern.compile(LATLON_PTRN); + private final Pattern latlanPtrn = Pattern.compile(LATLON_PTRN); /** The logger */ - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); private final PointDataDescription pointDataDescription; private final LocalStormReportDao lsrDao; - private Map containerMap; + private final Map containerMap; - private String pluginName; + private final String pluginName; private WMOHeader wmoHeader; @@ -166,7 +167,7 @@ public class LSRParser { int currentReport = -1; - private HashMap URI_MAP = new HashMap(); + private final HashMap URI_MAP = new HashMap(); private List reports; @@ -361,7 +362,6 @@ public class LSRParser { .getWmoHeader()); rpt.setOfficeid(officeid); rpt.setTraceId(traceId); - rpt.setPluginName(pluginName); reports.add(rpt); } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.manualIngest/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.plugin.manualIngest/META-INF/MANIFEST.MF index e179fbdc57..f7db2eec67 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.manualIngest/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.edex.plugin.manualIngest/META-INF/MANIFEST.MF @@ -8,5 +8,8 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Require-Bundle: org.apache.camel;bundle-version="1.0.0", org.springframework;bundle-version="2.5.6", com.raytheon.edex.common;bundle-version="1.11.17", - com.raytheon.uf.common.status + com.raytheon.uf.common.status, + com.raytheon.uf.edex.decodertools, + com.raytheon.uf.edex.distribution, + org.apache.commons.io Import-Package: com.raytheon.uf.edex.site.ingest diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.manualIngest/src/com/raytheon/uf/edex/plugin/manualIngest/MessageGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.manualIngest/src/com/raytheon/uf/edex/plugin/manualIngest/MessageGenerator.java index 99a1e6523e..3d4f4e3353 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.manualIngest/src/com/raytheon/uf/edex/plugin/manualIngest/MessageGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.manualIngest/src/com/raytheon/uf/edex/plugin/manualIngest/MessageGenerator.java @@ -21,18 +21,27 @@ package com.raytheon.uf.edex.plugin.manualIngest; import java.io.File; import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TimeZone; import org.apache.camel.Exchange; import org.apache.camel.Processor; -import org.springframework.util.FileCopyUtils; +import org.apache.commons.io.FileUtils; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.util.header.WMOHeaderFinder; import com.raytheon.uf.edex.core.EDEXUtil; -import com.raytheon.uf.edex.core.EdexException; import com.raytheon.uf.edex.core.props.PropertiesFactory; +import com.raytheon.uf.edex.decodertools.time.TimeTools; +import com.raytheon.uf.edex.distribution.DistributionPatterns; /** * A bean based on FileToString that will take a message generated from a file @@ -45,8 +54,8 @@ import com.raytheon.uf.edex.core.props.PropertiesFactory; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Oct 28, 2009 brockwoo Initial creation - * + * Oct 28, 2009 brockwoo Initial creation + * Sep 03, 2013 2327 rjpeter Added directory routing by plugin and date of product. * * * @author brockwoo @@ -65,6 +74,29 @@ public class MessageGenerator implements Processor { private String ingestRoute = null; + private final ThreadLocal sdfs = new ThreadLocal() { + + /* + * (non-Javadoc) + * + * @see java.lang.ThreadLocal#initialValue() + */ + @Override + protected SimpleDateFormat initialValue() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd" + + File.separatorChar + "HH"); + sdf.setTimeZone(TimeZone.getTimeZone("GMT")); + return sdf; + } + + }; + + /** + * Set of plugins that are not the primary decoder of the data. These are + * secondary or additional information such as text, dhr, dpa, etc. + */ + private final Set secondaryPlugins = new HashSet(); + public static MessageGenerator getInstance() { return instance; } @@ -77,6 +109,19 @@ public class MessageGenerator implements Processor { this.ingestRoute = ingestRoute; } + /** + * Register a secondary plugin, i.e. not the primary decoder of the data. + * These are plugins that provide data in a different format oradditional + * information such as text, dhr, dpa, etc. + * + * @param plugin + * @return + */ + public MessageGenerator registerSecondaryPlugin(String plugin) { + secondaryPlugins.add(plugin); + return this; + } + /* * (non-Javadoc) * @@ -86,14 +131,12 @@ public class MessageGenerator implements Processor { public void process(Exchange arg0) throws Exception { File file = (File) arg0.getIn().getBody(); if (file != null) { - String fileName = file.getName(); String messageHeader = WMOHeaderFinder.find(file); if (messageHeader == null) { - messageHeader = fileName; + messageHeader = file.getName(); } else { messageHeader = messageHeader.trim(); } - arg0.getIn().setBody(file.toString()); arg0.getIn().setHeader("header", messageHeader); arg0.getIn().setHeader("enqueueTime", System.currentTimeMillis()); @@ -103,21 +146,87 @@ public class MessageGenerator implements Processor { } } - public File copyFileToArchive(File inFile) { - String path = DIR + File.separator; + /** + * Copies the specified file to the archive directory. + * + * @param inFile + * @return + * @throws IOException + */ + public File copyFileToArchive(File inFile) throws IOException { + StringBuilder path = new StringBuilder(inFile.getPath().length()); + path.append(DIR).append(File.separatorChar); + + // find header and determine file date + Date fileTime = null; + String header = WMOHeaderFinder.find(inFile); + if (header == null) { + header = inFile.getName(); + } else { + header = header.trim(); + try { + String dtg = WMOHeaderFinder.findDtg(header); + Calendar headerTime = TimeTools.findCurrentTime(dtg, + inFile.getName()); + if (headerTime != null) { + fileTime = headerTime.getTime(); + } + } catch (Exception e) { + statusHandler.error("Exception occurred parsing WMO Header", e); + } + } + + // determine the plugin + List plugins = DistributionPatterns.getInstance() + .getMatchingPlugins(header); + int numPlugins = plugins.size(); + if (numPlugins == 1) { + path.append(plugins.get(0)).append(File.separatorChar); + } else if (numPlugins > 1) { + if (plugins.size() <= secondaryPlugins.size()) { + // check for a non secondary plugin, + String plugin = null; + for (String pluginToCheck : plugins) { + if (!secondaryPlugins.contains(pluginToCheck)) { + plugin = pluginToCheck; + break; + } + } + + if (plugin == null) { + // didn't find a non secondary plugin, just grab first + // plugin + plugin = plugins.get(0); + } + + path.append(plugin).append(File.separatorChar); + } else { + // remove secondary and grab first one + plugins.removeAll(secondaryPlugins); + path.append(plugins.get(0)).append(File.separatorChar); + } + } else { + path.append("unknown").append(File.separatorChar); + } + + // append YYYYMMDD/HH + if (fileTime == null) { + // default to current time + fileTime = SimulatedTime.getSystemTime().getTime(); + } + path.append(sdfs.get().format(fileTime)).append(File.separatorChar); // Determine the sub-directory String inputPath = inFile.getParent(); // Split on the manual directory to get the sub-directory String[] parts = inputPath.split("manual"); - File dir = null; if (parts.length > 1) { - dir = new File(path + parts[1]); - } else { - dir = new File(path); + path.append(parts[1]); } + File dir = new File(path.toString()); + if (!dir.exists()) { dir.mkdirs(); } @@ -125,7 +234,7 @@ public class MessageGenerator implements Processor { File newFile = new File(dir, inFile.getName()); try { - FileCopyUtils.copy(inFile, newFile); + FileUtils.copyFile(inFile, newFile); statusHandler.handle(Priority.INFO, "DataManual: " + inFile.getAbsolutePath()); } catch (IOException e) { @@ -137,7 +246,14 @@ public class MessageGenerator implements Processor { return newFile; } - public File moveFileToArchive(File inFile) { + /** + * Moves the specified file to the archive directory. + * + * @param inFile + * @return + * @throws IOException + */ + public File moveFileToArchive(File inFile) throws IOException { File newFile = copyFileToArchive(inFile); if (newFile != null) { inFile.delete(); @@ -145,10 +261,25 @@ public class MessageGenerator implements Processor { return newFile; } + /** + * Copies a file to the archive directory and sends the path to the manual + * ingest route. + * + * @param inFile + * @return + */ public boolean sendFileToIngest(String inFile) { return sendFileToIngest(inFile, ingestRoute); } + /** + * Copies a file to the archive directory and sends the path to the + * specified route. + * + * @param inFile + * @param route + * @return + */ public boolean sendFileToIngest(String inFile, String route) { boolean rval = true; @@ -156,7 +287,7 @@ public class MessageGenerator implements Processor { File archiveFile = copyFileToArchive(new File(inFile)); EDEXUtil.getMessageProducer().sendAsync(route, archiveFile.getAbsolutePath()); - } catch (EdexException e) { + } catch (Exception e) { rval = false; statusHandler.handle(Priority.ERROR, "Failed to insert file [" + inFile + "] into ingest stream", e); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.mesowest/src/com/raytheon/uf/edex/plugin/mesowest/MESOWestDecoder.java b/edexOsgi/com.raytheon.uf.edex.plugin.mesowest/src/com/raytheon/uf/edex/plugin/mesowest/MESOWestDecoder.java index be6bcf1e5c..3b90cfe1bc 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.mesowest/src/com/raytheon/uf/edex/plugin/mesowest/MESOWestDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.mesowest/src/com/raytheon/uf/edex/plugin/mesowest/MESOWestDecoder.java @@ -37,27 +37,28 @@ import com.raytheon.uf.edex.plugin.mesowest.decoder.MESOWestParser; * TODO Add Description * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * Mar 3, 2009            jkorman     Initial creation
- *
+ * Mar 03, 2009            jkorman     Initial creation
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
+ * 
  * 
- * + * * @author jkorman - * @version 1.0 + * @version 1.0 */ public class MESOWestDecoder { - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); private String pluginName = "mesowest"; - private Map parserMap = new HashMap(); - + private final Map parserMap = new HashMap(); + /** * * @param name @@ -77,27 +78,28 @@ public class MESOWestDecoder { PluginDataObject[] decodedData = null; String traceId = null; - + logger.debug("MESOWestDecoder.decode()"); - - if(input != null) { - traceId = (String) input.getProperty(MESOWestConstants.TRACEID); + + if (input != null) { + traceId = input.getProperty(MESOWestConstants.TRACEID); MESOWestRecord record = null; - + String type = input.getProperty(MESOWestConstants.K_DATATYPE); - if(MESOWestConstants.T_PARMHEADER.equals(type)) { - parserMap.put(input.getProperty("uuid"),new MESOWestParser(input.getReport())); + if (MESOWestConstants.T_PARMHEADER.equals(type)) { + parserMap.put(input.getProperty("uuid"), new MESOWestParser( + input.getReport())); logger.debug("Created parser "); } else if (MESOWestConstants.T_LASTITEM.equals(type)) { parserMap.remove(input.getProperty("uuid")); logger.debug("Destroyed parser "); } else { - MESOWestParser parser = parserMap.get(input.getProperty("uuid")); - if(parser != null) { - if(input.getReport().length() > 10) { - if((record = parser.decode(input.getReport())) != null) { - record.setPluginName(pluginName); + MESOWestParser parser = parserMap + .get(input.getProperty("uuid")); + if (parser != null) { + if (input.getReport().length() > 10) { + if ((record = parser.decode(input.getReport())) != null) { record.setTraceId(traceId); record.setObsText(input.getReport() + "\n"); } @@ -106,15 +108,16 @@ public class MESOWestDecoder { logger.error("Unexpected data in data stream"); } } - + try { if (record != null) { logger.info("Decoded obs " + record.getStationId()); - + try { record.constructDataURI(); } catch (PluginException e) { - throw new DecoderException("Unable to construct dataURI", e); + throw new DecoderException( + "Unable to construct dataURI", e); } decodedData = new PluginDataObject[] { record }; @@ -124,7 +127,7 @@ public class MESOWestDecoder { } catch (Exception e) { logger.error("Error in MESOWestDecoder", e); } finally { - if(decodedData == null) { + if (decodedData == null) { decodedData = new PluginDataObject[0]; } } @@ -134,7 +137,7 @@ public class MESOWestDecoder { return decodedData; } - + /** * @return the pluginName */ diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.mesowest/src/com/raytheon/uf/edex/plugin/mesowest/common/MESOWestRecord.java b/edexOsgi/com.raytheon.uf.edex.plugin.mesowest/src/com/raytheon/uf/edex/plugin/mesowest/common/MESOWestRecord.java index 2eb7f65b23..04a4dfc50b 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.mesowest/src/com/raytheon/uf/edex/plugin/mesowest/common/MESOWestRecord.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.mesowest/src/com/raytheon/uf/edex/plugin/mesowest/common/MESOWestRecord.java @@ -63,10 +63,11 @@ import com.vividsolutions.jts.geom.Geometry; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Mar 3, 2009 jkorman Initial creation - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Mar 03, 2009 jkorman Initial creation + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -79,15 +80,15 @@ import com.vividsolutions.jts.geom.Geometry; @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public class MESOWestRecord extends PluginDataObject implements ISpatialEnabled, -IDecoderGettable { - +public class MESOWestRecord extends PluginDataObject implements + ISpatialEnabled, IDecoderGettable { + private static final long serialVersionUID = 1L; public static final String OBS_TEXT = "text"; - + public static final Unit LENGTH_UNIT = SI.METER; - + public static final Unit TEMPERATURE_UNIT = SI.KELVIN; public static final Unit WIND_SPEED_UNIT = SI.METERS_PER_SECOND; @@ -109,10 +110,10 @@ IDecoderGettable { PARM_MAP.put("PMSL", PRES_SLP); PARM_MAP.put("NLAT", STA_LAT); PARM_MAP.put("NLON", STA_LON); - PARM_MAP.put("STA","STA"); - PARM_MAP.put("stationid","STA"); - PARM_MAP.put("message",OBS_TEXT); - PARM_MAP.put(OBS_TEXT,OBS_TEXT); + PARM_MAP.put("STA", "STA"); + PARM_MAP.put("stationid", "STA"); + PARM_MAP.put("message", OBS_TEXT); + PARM_MAP.put(OBS_TEXT, OBS_TEXT); } @DataURI(position = 1) @@ -131,7 +132,7 @@ IDecoderGettable { @XmlElement @DynamicSerializeElement private SurfaceObsLocation location; - + // Observation air temperature in degrees Kelvin. @Column @DynamicSerializeElement @@ -155,7 +156,7 @@ IDecoderGettable { @DynamicSerializeElement @XmlElement private Double minT24; - + // Relative Humidity in percent. @Column @DynamicSerializeElement @@ -197,7 +198,7 @@ IDecoderGettable { @DynamicSerializeElement @XmlElement private Double altimeter; - + // Observation precip in mm. @Column @DynamicSerializeElement @@ -209,7 +210,7 @@ IDecoderGettable { @DynamicSerializeElement @XmlElement private Double precip_01M; - + // 5 minute precip in inches. @Column @DynamicSerializeElement @@ -257,13 +258,13 @@ IDecoderGettable { @DynamicSerializeElement @XmlElement private Double precip_24H; - + // Raw observation text @Column @DynamicSerializeElement @XmlElement private String obsText; - + /** * */ @@ -280,8 +281,7 @@ IDecoderGettable { public MESOWestRecord(String uri) { super(uri); } - - + /** * Get this observation's geometry. * @@ -290,7 +290,7 @@ IDecoderGettable { public Geometry getGeometry() { return location.getGeometry(); } - + /** * Get the geometry latitude. * @@ -308,7 +308,7 @@ IDecoderGettable { public double getLongitude() { return location.getLongitude(); } - + /** * Get the station identifier for this observation. * @@ -326,7 +326,7 @@ IDecoderGettable { public Integer getElevation() { return location.getElevation(); } - + /** * @return the location */ @@ -335,7 +335,8 @@ IDecoderGettable { } /** - * @param location the location to set + * @param location + * the location to set */ public void setLocation(SurfaceObsLocation location) { this.location = location; @@ -343,7 +344,7 @@ IDecoderGettable { /** * - * @return + * @return */ public String getNetworkType() { return networkType; @@ -351,7 +352,7 @@ IDecoderGettable { /** * - * @return + * @return */ public void setNetworkType(String type) { networkType = type; @@ -373,7 +374,7 @@ IDecoderGettable { } // ****************************************** - + /** * @return the temp */ @@ -382,7 +383,8 @@ IDecoderGettable { } /** - * @param temp the temp to set + * @param temp + * the temp to set */ public void setTemp(Double temp) { this.temp = temp; @@ -396,12 +398,13 @@ IDecoderGettable { } /** - * @param dwpt the dwpt to set + * @param dwpt + * the dwpt to set */ public void setDwpt(Double dwpt) { this.dwpt = dwpt; } - + /** * @return the maxT24 */ @@ -410,7 +413,8 @@ IDecoderGettable { } /** - * @param maxT24 the maxT24 to set + * @param maxT24 + * the maxT24 to set */ public void setMaxT24(Double maxT24) { this.maxT24 = maxT24; @@ -424,7 +428,8 @@ IDecoderGettable { } /** - * @param minT24 the minT24 to set + * @param minT24 + * the minT24 to set */ public void setMinT24(Double minT24) { this.minT24 = minT24; @@ -438,7 +443,8 @@ IDecoderGettable { } /** - * @param humidity the humidity to set + * @param humidity + * the humidity to set */ public void setHumidity(Double humidity) { this.humidity = humidity; @@ -452,7 +458,8 @@ IDecoderGettable { } /** - * @param windDirection the windDirection to set + * @param windDirection + * the windDirection to set */ public void setWindDirection(Double windDirection) { this.windDirection = windDirection; @@ -466,7 +473,8 @@ IDecoderGettable { } /** - * @param windSpeed the windSpeed to set + * @param windSpeed + * the windSpeed to set */ public void setWindSpeed(Double windSpeed) { this.windSpeed = windSpeed; @@ -480,12 +488,13 @@ IDecoderGettable { } /** - * @param windGust the windGust to set + * @param windGust + * the windGust to set */ public void setWindGust(Double windGust) { this.windGust = windGust; } - + /** * @return the pressure */ @@ -494,12 +503,13 @@ IDecoderGettable { } /** - * @param pressure the pressure to set + * @param pressure + * the pressure to set */ public void setPressure(Double pressure) { this.pressure = pressure; } - + /** * @return the seaLevelPressure */ @@ -508,7 +518,8 @@ IDecoderGettable { } /** - * @param seaLevelPressure the seaLevelPressure to set + * @param seaLevelPressure + * the seaLevelPressure to set */ public void setSeaLevelPressure(Double seaLevelPressure) { this.seaLevelPressure = seaLevelPressure; @@ -522,12 +533,12 @@ IDecoderGettable { } /** - * @param altimeter the altimeter to set + * @param altimeter + * the altimeter to set */ public void setAltimeter(Double altimeter) { this.altimeter = altimeter; } - /** * @return the precip @@ -537,7 +548,8 @@ IDecoderGettable { } /** - * @param precip the precip to set + * @param precip + * the precip to set */ public void setPrecip(Double precip) { this.precip = precip; @@ -551,7 +563,8 @@ IDecoderGettable { } /** - * @param precip_01M the precip_01M to set + * @param precip_01M + * the precip_01M to set */ public void setPrecip_01M(Double precip_01M) { this.precip_01M = precip_01M; @@ -565,7 +578,8 @@ IDecoderGettable { } /** - * @param precip_05M the precip_05M to set + * @param precip_05M + * the precip_05M to set */ public void setPrecip_05M(Double precip_05M) { this.precip_05M = precip_05M; @@ -579,7 +593,8 @@ IDecoderGettable { } /** - * @param precip_10M the precip_10M to set + * @param precip_10M + * the precip_10M to set */ public void setPrecip_10M(Double precip_10M) { this.precip_10M = precip_10M; @@ -593,7 +608,8 @@ IDecoderGettable { } /** - * @param precip_15M the precip_15M to set + * @param precip_15M + * the precip_15M to set */ public void setPrecip_15M(Double precip_15M) { this.precip_15M = precip_15M; @@ -607,7 +623,8 @@ IDecoderGettable { } /** - * @param precip_30M the precip_30M to set + * @param precip_30M + * the precip_30M to set */ public void setPrecip_30M(Double precip_30M) { this.precip_30M = precip_30M; @@ -621,7 +638,8 @@ IDecoderGettable { } /** - * @param precip_01H the precip_01H to set + * @param precip_01H + * the precip_01H to set */ public void setPrecip_01H(Double precip_01H) { this.precip_01H = precip_01H; @@ -635,7 +653,8 @@ IDecoderGettable { } /** - * @param precip_03H the precip_03H to set + * @param precip_03H + * the precip_03H to set */ public void setPrecip_03H(Double precip_03H) { this.precip_03H = precip_03H; @@ -649,7 +668,8 @@ IDecoderGettable { } /** - * @param precip_06H the precip_06H to set + * @param precip_06H + * the precip_06H to set */ public void setPrecip_06H(Double precip_06H) { this.precip_06H = precip_06H; @@ -663,7 +683,8 @@ IDecoderGettable { } /** - * @param precip_24H the precip_24H to set + * @param precip_24H + * the precip_24H to set */ public void setPrecip_24H(Double precip_24H) { this.precip_24H = precip_24H; @@ -677,12 +698,13 @@ IDecoderGettable { } /** - * @param obsText the obsText to set + * @param obsText + * the obsText to set */ public void setObsText(String obsText) { this.obsText = obsText; } - + // ****************************************** /** @@ -691,7 +713,7 @@ IDecoderGettable { public void setSpatialObject(SurfaceObsLocation loc) { location = loc; } - + /** * */ @@ -699,10 +721,10 @@ IDecoderGettable { public SurfaceObsLocation getSpatialObject() { return location; } - + /** - * This class implements IDecoderGettable so return this - * instance. + * This class implements IDecoderGettable so return this instance. + * * @return The reference to this instance. */ @Override @@ -722,7 +744,7 @@ IDecoderGettable { } else if (OBS_TEXT.equals(pName)) { retValue = getStationId(); } - + return retValue; } @@ -730,7 +752,7 @@ IDecoderGettable { public String[] getStrings(String paramName) { return null; } - + @Override public Amount getValue(String paramName) { Amount a = null; @@ -755,10 +777,10 @@ IDecoderGettable { } else if (PRES_SLP.equals(pName)) { a = new Amount(seaLevelPressure, PRESSURE_UNIT); } - + return a; } - + /** * */ @@ -766,11 +788,16 @@ IDecoderGettable { public Collection getValues(String paramName) { return null; } - + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "mesowest"; + } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.npp.sounding/src/com/raytheon/uf/edex/plugin/npp/sounding/NPPSoundingDecoder.java b/edexOsgi/com.raytheon.uf.edex.plugin.npp.sounding/src/com/raytheon/uf/edex/plugin/npp/sounding/NPPSoundingDecoder.java index 8ca9ec0a69..d6007ea832 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.npp.sounding/src/com/raytheon/uf/edex/plugin/npp/sounding/NPPSoundingDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.npp.sounding/src/com/raytheon/uf/edex/plugin/npp/sounding/NPPSoundingDecoder.java @@ -57,7 +57,8 @@ import com.raytheon.uf.edex.plugin.npp.AbstractNPPDecoder; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 4, 2013 mschenke Initial creation + * Jan 04, 2013 mschenke Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -67,14 +68,14 @@ import com.raytheon.uf.edex.plugin.npp.AbstractNPPDecoder; public class NPPSoundingDecoder extends AbstractNPPDecoder { - private IUFStatusHandler statusHandler = UFStatus + private final IUFStatusHandler statusHandler = UFStatus .getHandler(NPPSoundingDecoder.class); private static final String LATITUDE_DATASET_ID = "Latitude@"; private static final String LONGITUDE_DATASET_ID = "Longitude@"; - private String pluginName; + private final String pluginName; private NPPSoundingDao pluginDao; @@ -128,7 +129,7 @@ public class NPPSoundingDecoder extends AbstractNPPDecoder { longitude = var; } } - if (latitude == null || longitude == null) { + if ((latitude == null) || (longitude == null)) { throw new DecoderException("Unable to find lat/lon information"); } @@ -142,7 +143,6 @@ public class NPPSoundingDecoder extends AbstractNPPDecoder { // Create PDO for lat/lon entry NPPSoundingRecord record = (NPPSoundingRecord) pluginDao .newObject(); - record.setPluginName(pluginName); record.setDataTime(dataTime); record.setLatitude((double) latArray.getFloat(i)); record.setLongitude((double) lonArray.getFloat(i)); @@ -182,7 +182,7 @@ public class NPPSoundingDecoder extends AbstractNPPDecoder { } else if (sourceNumDims == 1) { read1D(records, var, name); } - } else if (sourceNumDims == 1 && destNumDims == 2) { + } else if ((sourceNumDims == 1) && (destNumDims == 2)) { read1Dto2D(records, var, name); } } @@ -209,8 +209,8 @@ public class NPPSoundingDecoder extends AbstractNPPDecoder { String parameter) throws IOException { int numLevels = var.getDimension(0).getLength(); Array data = var.read(); - for (int i = 0; i < records.length; i++) { - PointDataView pdv = records[i].getPointDataView(); + for (NPPSoundingRecord record : records) { + PointDataView pdv = record.getPointDataView(); for (int j = 0; j < numLevels; j++) { float value = data.getFloat(j); pdv.setFloat(parameter, value, j); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/common_static/base/roles/userRoles.xml b/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/common_static/base/roles/userRoles.xml index 91752e1a0c..7d6bc4cda1 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/common_static/base/roles/userRoles.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/common_static/base/roles/userRoles.xml @@ -92,6 +92,8 @@ + + com.raytheon.localization.site/common_static/purge @@ -125,6 +127,8 @@ com.raytheon.localization.site/common_static/roles com.raytheon.localization.site/common_static/datadelivery com.raytheon.localization.site/common_static/archiver/purger + com.raytheon.localization.site/common_static/archiver/purger/retention + com.raytheon.localization.site/common_static/archiver/purger/case diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.preciprate/src/com/raytheon/uf/edex/plugin/preciprate/PrecipRateGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.preciprate/src/com/raytheon/uf/edex/plugin/preciprate/PrecipRateGenerator.java index 2457c47d68..9f26511832 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.preciprate/src/com/raytheon/uf/edex/plugin/preciprate/PrecipRateGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.preciprate/src/com/raytheon/uf/edex/plugin/preciprate/PrecipRateGenerator.java @@ -49,8 +49,9 @@ import com.raytheon.uf.edex.plugin.preciprate.common.PrecipRateConfig; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 01/25/10 3796 D. Hladky Initial release - * 02/25/13 1660 D. Hladky Fixed SCAN configuration bug. + * Jan 25, 2010 3796 D. Hladky Initial release + * Feb 25, 2013 1660 D. Hladky Fixed SCAN configuration bug. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -59,15 +60,15 @@ import com.raytheon.uf.edex.plugin.preciprate.common.PrecipRateConfig; */ public class PrecipRateGenerator extends CompositeProductGenerator implements -MonitorConfigListener{ - + MonitorConfigListener { + private static final IUFStatusHandler statusHandler = UFStatus .getHandler(PrecipRateGenerator.class); private static final String genName = "PrecipRate"; private static final String productType = "preciprate"; - + /** run configuration manager **/ public SCANRunSiteConfigurationManager srcm = null; @@ -99,7 +100,7 @@ MonitorConfigListener{ if (!configValid) { statusHandler.handle(Priority.WARN, - "Configuration for PrecipRate(scan) is invalid!!!"); + "Configuration for PrecipRate(scan) is invalid!!!"); return; } @@ -137,7 +138,6 @@ MonitorConfigListener{ PrecipRateRecord precipRateRec = new PrecipRateRecord(); this.setPluginDao(new PrecipRateDao(productType)); - precipRateRec.setPluginName(this.getCompositeProductType()); precipRateRec.setDataTime(this.getProductTime()); precipRateRec.setIcao(preciprate_config.getIcao()); precipRateRec.setGateResolution(preciprate_config.getDHR() @@ -166,8 +166,7 @@ MonitorConfigListener{ precipRateRec.setAcoefficent(pr.getDhrMap().get( DHRValues.ZRMULTCOEFF)); - precipRateRec.setBias(pr.getDhrMap().get( - DHRValues.BIAS)); + precipRateRec.setBias(pr.getDhrMap().get(DHRValues.BIAS)); precipRateRec.setHailcap(pr.getDhrMap().get( DHRValues.MAXPRECIPRATEALLOW)); precipRateRec.setCoefficent(pr.getDhrMap().get( @@ -193,12 +192,13 @@ MonitorConfigListener{ @Override public void configChanged(MonitorConfigEvent fce) { if (fce.getSource() instanceof SCANRunSiteConfigurationManager) { - statusHandler.handle(Priority.INFO, - "Re-configuring PrecipRate URI filters...Run Site Config change"); + statusHandler + .handle(Priority.INFO, + "Re-configuring PrecipRate URI filters...Run Site Config change"); resetFilters(); } } - + /** * run config manager * diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.qc/src/com/raytheon/uf/edex/plugin/qc/QCScanner.java b/edexOsgi/com.raytheon.uf.edex.plugin.qc/src/com/raytheon/uf/edex/plugin/qc/QCScanner.java index b8c39b423c..5c77463dda 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.qc/src/com/raytheon/uf/edex/plugin/qc/QCScanner.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.qc/src/com/raytheon/uf/edex/plugin/qc/QCScanner.java @@ -45,8 +45,8 @@ import com.raytheon.uf.edex.database.plugin.PluginFactory; import com.raytheon.uf.edex.plugin.qc.dao.QCDao; /** - * Scans NetCDF files generated by A1 legacy applications and generates - * QCRecord instances that refer to their records. + * Scans NetCDF files generated by A1 legacy applications and generates QCRecord + * instances that refer to their records. * *
  * 
@@ -58,6 +58,7 @@ import com.raytheon.uf.edex.plugin.qc.dao.QCDao;
  * Mar 07, 2013 15842      D. Friedman Use Java NetCDF library instead of
  *                                     pupynere
  * May 16, 2013 1869       bsteffen    Remove DataURI column from qc.
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
  * 
  * 
* @@ -66,7 +67,7 @@ import com.raytheon.uf.edex.plugin.qc.dao.QCDao; */ public class QCScanner { private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(QCScanner.class); + .getHandler(QCScanner.class); private Integer maxRecordsInChunk; @@ -123,8 +124,10 @@ public class QCScanner { private static final int ID_LENGTH = 24; private class QCDirectoryScanner { - private String qcType; - private File directory; + private final String qcType; + + private final File directory; + private QCDao qcDao; public QCDirectoryScanner(String qcType, File directory) { @@ -140,8 +143,9 @@ public class QCScanner { try { scanFile(fn); } catch (Exception e) { - statusHandler.error(String.format("error reading %s/%s: %s", - directory, fn, e.getMessage()), e); + statusHandler.error(String.format( + "error reading %s/%s: %s", directory, fn, + e.getMessage()), e); } } } @@ -151,60 +155,68 @@ public class QCScanner { NetcdfFile nc = NetcdfFile.open(new File(directory, fn).toString()); try { int index = qcDao.getMaxRecordIndex(qcType, fn); - if (index < 0) + if (index < 0) { index = 0; - else + } else { index += 1; + } int nRecords = nc.getUnlimitedDimension().getLength(); - if (index >= nRecords) + if (index >= nRecords) { return; + } String[] idVariablesNames = nc - .findGlobalAttribute("idVariables") - .getStringValue().split(","); + .findGlobalAttribute("idVariables").getStringValue() + .split(","); String[] timeVariableNames = nc - .findGlobalAttribute("timeVariables") - .getStringValue().split(","); + .findGlobalAttribute("timeVariables").getStringValue() + .split(","); Variable[] idVariables = new Variable[idVariablesNames.length]; - for (int i = 0; i < idVariables.length; ++i) + for (int i = 0; i < idVariables.length; ++i) { idVariables[i] = nc.findVariable(idVariablesNames[i]); + } Variable vObsTime = nc.findVariable(timeVariableNames[0]); - double vObsTimeFillValue = vObsTime.findAttribute("_FillValue").getNumericValue().doubleValue(); + double vObsTimeFillValue = vObsTime.findAttribute("_FillValue") + .getNumericValue().doubleValue(); Double vObsTimeMissingValue = null; Attribute a = vObsTime.findAttribute("missing_value"); - if (a != null) + if (a != null) { vObsTimeMissingValue = a.getNumericValue().doubleValue(); + } Variable vLat = nc.findVariable("latitude"); Variable vLon = nc.findVariable("longitude"); Variable vElev = nc.findVariable("elevation"); while (index < nRecords) { - PluginDataObject[] records = new PluginDataObject[Math.min(maxRecordsInChunk, nRecords - index)]; + PluginDataObject[] records = new PluginDataObject[Math.min( + maxRecordsInChunk, nRecords - index)]; int[] ofs = new int[] { index }; int[] len = new int[] { records.length }; Section sec = new Section(); - sec.appendRange(index, index + records.length - 1); + sec.appendRange(index, (index + records.length) - 1); sec.appendRange(); Array dObsTime = vObsTime.read(ofs, len); Array dLat = vLat.read(ofs, len); Array dLon = vLon.read(ofs, len); Array dElev = vElev.read(ofs, len); ArrayChar[] dIDs = new ArrayChar[idVariables.length]; - for (int i = 0; i < dIDs.length; ++i) + for (int i = 0; i < dIDs.length; ++i) { dIDs[i] = (ArrayChar) idVariables[i].read(sec); + } int ri = 0; int oi = 0; while (ri < records.length) { QCRecord r = new QCRecord(); - r.setPluginName("qc"); double obsTime = dObsTime.getDouble(ri); - if (obsTime != vObsTimeFillValue && - (vObsTimeMissingValue == null || - vObsTimeMissingValue != obsTime)) { - r.setDataTime(new DataTime(new Date((long)(obsTime * 1000)))); + if ((obsTime != vObsTimeFillValue) + && ((vObsTimeMissingValue == null) || (vObsTimeMissingValue != obsTime))) { + r.setDataTime(new DataTime(new Date( + (long) (obsTime * 1000)))); SurfaceObsLocation loc = new SurfaceObsLocation(); - loc.assignLocation(dLat.getDouble(ri), dLon.getDouble(ri)); + loc.assignLocation(dLat.getDouble(ri), + dLon.getDouble(ri)); loc.setElevation(dElev.getInt(ri)); - StringBuilder stationId = new StringBuilder(ID_LENGTH); + StringBuilder stationId = new StringBuilder( + ID_LENGTH); for (ArrayChar idArray : dIDs) { stationId.append(idArray.getString(ri)); } @@ -218,8 +230,9 @@ public class QCScanner { ++index; ++ri; } - if (oi < records.length) + if (oi < records.length) { records = Arrays.copyOf(records, oi); + } target.acceptRecords(records); } } finally { diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.qpf/src/com/raytheon/uf/edex/plugin/qpf/QPFGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.qpf/src/com/raytheon/uf/edex/plugin/qpf/QPFGenerator.java index 750eecde04..918988688f 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.qpf/src/com/raytheon/uf/edex/plugin/qpf/QPFGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.qpf/src/com/raytheon/uf/edex/plugin/qpf/QPFGenerator.java @@ -49,10 +49,11 @@ import com.raytheon.uf.edex.plugin.qpf.common.QPFConfig; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 02/07/2009 1981 dhladky Initial Creation. - * 04/27/2012 #562 dgilling Accept getter and setter - * renames in QPFRecord. - * 02/25/13 1660 D. Hladky Fixed configuration bug in scan. + * Feb 07, 2009 1981 dhladky Initial Creation. + * Apr 27, 2012 562 dgilling Accept getter and setter renames in + * QPFRecord. + * Feb 25, 2013 1660 D. Hladky Fixed configuration bug in scan. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -164,7 +165,6 @@ public class QPFGenerator extends CompositeProductGenerator implements .getNumBins()); } - qpfRec.setPluginName(this.getCompositeProductType()); qpfRec.setIcao(qpf_config.getIcao()); qpfRec.setDataTime(this.getProductTime()); qpfRec.setSpatialInfo(qpf_config.getSpatialInfo()); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.satellite.mcidas/src/com/raytheon/uf/edex/plugin/satellite/mcidas/McidasSatelliteDecoder.java b/edexOsgi/com.raytheon.uf.edex.plugin.satellite.mcidas/src/com/raytheon/uf/edex/plugin/satellite/mcidas/McidasSatelliteDecoder.java index 45d31869c2..c55436c775 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.satellite.mcidas/src/com/raytheon/uf/edex/plugin/satellite/mcidas/McidasSatelliteDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.satellite.mcidas/src/com/raytheon/uf/edex/plugin/satellite/mcidas/McidasSatelliteDecoder.java @@ -98,7 +98,8 @@ public class McidasSatelliteDecoder { /** * - * @param data The file byte array data to be decoded. + * @param data + * The file byte array data to be decoded. * @return The decoded data record(s). * @return * @throws Exception @@ -160,13 +161,13 @@ public class McidasSatelliteDecoder { /* int creationHhmmss = */buf.getInt(); int bandMap1to32 = buf.getInt(); int bandMap33to64 = buf.getInt(); - buf.position(buf.position() + 4 * 4); // sensor specific - buf.position(buf.position() + 4 * 8); // memo + buf.position(buf.position() + (4 * 4)); // sensor specific + buf.position(buf.position() + (4 * 8)); // memo int areaNumber = buf.getInt(); int dataBlockOffset = buf.getInt(); int navBlockOffset = buf.getInt(); /* int validityCode = */buf.getInt(); - buf.position(buf.position() + 8 * 4); // PDL + buf.position(buf.position() + (8 * 4)); // PDL buf.getInt(); // GOES AA band 8 /* int imageYyyddd = */buf.getInt(); /* int imageHhmmssOrMillis = */buf.getInt(); @@ -176,7 +177,7 @@ public class McidasSatelliteDecoder { /* int prefixBandListLength = */buf.getInt(); buf.getInt(); // source type buf.getInt(); // cal type - buf.position(buf.position() + 3 * 4); // reserved + buf.position(buf.position() + (3 * 4)); // reserved /* int originalSourceType = */buf.getInt(); // actually a 4cc? /* int units = */buf.getInt(); // also 4cc? /* int scaling = */buf.getInt(); @@ -218,7 +219,8 @@ public class McidasSatelliteDecoder { rec.setCoverage(coverage); // TODO: Line pad if not a multiple of four bytes - if (linePrefixLength == 0 && nBytesPerElement == 1 && nBands == 1) { + if ((linePrefixLength == 0) && (nBytesPerElement == 1) + && (nBands == 1)) { byte[] imageBytes = new byte[nLines * nElementsPerLine]; buf.position(dataBlockOffset); buf.get(imageBytes); @@ -227,7 +229,7 @@ public class McidasSatelliteDecoder { } else if (nBytesPerElement == 1) { byte[] imageBytes = new byte[nLines * nElementsPerLine]; - int si = dataBlockOffset + ri * nBytesPerElement; + int si = dataBlockOffset + (ri * nBytesPerElement); int di = 0; int eincr = nBands * nBytesPerElement; for (int y = 0; y < nLines; ++y) { @@ -243,7 +245,6 @@ public class McidasSatelliteDecoder { rec.setTraceId(traceId); rec.setPersistenceTime(TimeTools.getSystemCalendar().getTime()); - rec.setPluginName("satellite"); rec.constructDataURI(); // Set the data into the IDataRecord @@ -303,22 +304,22 @@ public class McidasSatelliteDecoder { double dy = spacingAtStdLatInMeters * yImgRes; double phi0r = clat * DTR; - double rxp = ((double) (elementOfEquator - ulX) / xImgRes + 1.); - double ryp = (ny - (double) (lineOfEquator - ulY) / yImgRes); + double rxp = (((double) (elementOfEquator - ulX) / xImgRes) + 1.); + double ryp = (ny - ((double) (lineOfEquator - ulY) / yImgRes)); double dxp = 1. - rxp; double dyp = 1. - ryp; double rm = dx * dyp; double rcos = radiusInMeters * Math.cos(phi0r); double arg = Math.exp(rm / rcos); - la1 = (float) ((2. * Math.atan(arg) - HALFPI) * RTD); - lo1 = (float) prnlon((clon + ((dx * dxp) / rcos) * RTD)); + la1 = (float) (((2. * Math.atan(arg)) - HALFPI) * RTD); + lo1 = (float) prnlon((clon + (((dx * dxp) / rcos) * RTD))); dxp = nx - rxp; dyp = ny - ryp; rm = dx * dyp; arg = Math.exp(rm / rcos); - la2 = (float) ((2. * Math.atan(arg) - HALFPI) * RTD); - lo2 = (float) prnlon((clon + ((dx * dxp) / rcos) * RTD)); + la2 = (float) (((2. * Math.atan(arg)) - HALFPI) * RTD); + lo2 = (float) prnlon((clon + (((dx * dxp) / rcos) * RTD))); lo2 = (float) prnlon(lo2); result = SatSpatialFactory.getInstance().getMapCoverage( @@ -332,11 +333,11 @@ public class McidasSatelliteDecoder { } private static double prnlon(double lon) { - double dlon = lon - (int) (lon / 360.f) * 360.f; + double dlon = lon - ((int) (lon / 360.f) * 360.f); if (lon < -180.) { dlon = lon + 360.f; } else if (lon > 180.) { - dlon = (double) (lon - 360.); + dlon = lon - 360.; } return dlon; } @@ -345,12 +346,12 @@ public class McidasSatelliteDecoder { Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); cal.setTimeInMillis(0); - cal.set(Calendar.YEAR, +1900 + yyyddd / 1000); + cal.set(Calendar.YEAR, +1900 + (yyyddd / 1000)); cal.set(Calendar.DAY_OF_YEAR, yyyddd % 1000); int hh = hhmmss / 10000; cal.set(Calendar.HOUR_OF_DAY, hh); - cal.set(Calendar.MINUTE, (hhmmss - hh * 10000) / 100); + cal.set(Calendar.MINUTE, (hhmmss - (hh * 10000)) / 100); cal.set(Calendar.SECOND, hhmmss % 100); return cal; @@ -358,9 +359,9 @@ public class McidasSatelliteDecoder { private static double unpackDdmmss(int ddmmss) { int dd = ddmmss / 10000; - int mm = (ddmmss - dd * 10000) / 100; + int mm = (ddmmss - (dd * 10000)) / 100; int ss = ddmmss % 100; - return dd + mm / 60.0 + ss / 3600.0; + return dd + (mm / 60.0) + (ss / 3600.0); } private static double flipLon(double lon, boolean flip) { diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.scan/src/com/raytheon/uf/edex/plugin/scan/ScanGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.scan/src/com/raytheon/uf/edex/plugin/scan/ScanGenerator.java index 406bef6cc3..2ac2dfd8a9 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.scan/src/com/raytheon/uf/edex/plugin/scan/ScanGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.scan/src/com/raytheon/uf/edex/plugin/scan/ScanGenerator.java @@ -56,7 +56,8 @@ import com.raytheon.uf.edex.dat.utils.ScanDataCache; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 02/25/13 1660 D. Hladky Fixed SCAN configuration bug. + * Feb 25, 2013 1660 D. Hladky Fixed SCAN configuration bug. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -102,13 +103,14 @@ public class ScanGenerator extends CompositeProductGenerator implements try { getRunConfig().readConfigXml(); } catch (SerializationException e) { - statusHandler.handle(Priority.ERROR, "Couldn't read scan configuration!!!", e); + statusHandler.handle(Priority.ERROR, + "Couldn't read scan configuration!!!", e); } boolean configValid = getRunConfig().isPopulated(); if (!configValid) { statusHandler.handle(Priority.WARN, - "Configuration for SCAN is invalid!!!"); + "Configuration for SCAN is invalid!!!"); return; } @@ -203,7 +205,6 @@ public class ScanGenerator extends CompositeProductGenerator implements ScanRecord scanRec = new ScanRecord(); scanRec.setType(type); scanRec.setTilt(sfilter.getTilt(table)); - scanRec.setPluginName(this.getCompositeProductType()); scanRec.setIcao(sfilter.getIcao()); scanRec.setLastElevationAngle(tables.get(table) .getLastElevationAngle()); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.svrwx/src/com/raytheon/uf/edex/plugin/svrwx/decoder/SvrWxParser.java b/edexOsgi/com.raytheon.uf.edex.plugin.svrwx/src/com/raytheon/uf/edex/plugin/svrwx/decoder/SvrWxParser.java index f0091efed4..ed760110c2 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.svrwx/src/com/raytheon/uf/edex/plugin/svrwx/decoder/SvrWxParser.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.svrwx/src/com/raytheon/uf/edex/plugin/svrwx/decoder/SvrWxParser.java @@ -51,7 +51,8 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 04, 2010 jsanchez Initial creation + * Jan 04, 2010 jsanchez Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -61,23 +62,23 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; public class SvrWxParser { /** The logger */ - private Log logger = LogFactory.getLog(getClass()); + private final Log logger = LogFactory.getLog(getClass()); private final PointDataDescription pointDataDescription; private final SvrWxRecordDao svrWxDao; - private Map containerMap; + private final Map containerMap; private WMOHeader wmoHeader; - private String pluginName; + private final String pluginName; private String traceId; int currentReport = -1; - private HashMap URI_MAP = new HashMap(); + private final HashMap URI_MAP = new HashMap(); private List reports; @@ -260,13 +261,12 @@ public class SvrWxParser { parseTimeRangeLine(rpt.getReportLine()); break; case REPORT_TYPE: - if (reportType != null && eventKey != null) { + if ((reportType != null) && (eventKey != null)) { SurfaceObsLocation location = new SurfaceObsLocation( stationId); location.setLongitude(longitude.doubleValue()); location.setLatitude(latitude.doubleValue()); svrWxRecord = new SvrWxRecord(); - svrWxRecord.setPluginName(pluginName); svrWxRecord.setReportType(reportType); svrWxRecord.setGreenTime(greenTime); svrWxRecord.setLocation(location); @@ -278,13 +278,12 @@ public class SvrWxParser { clearData(); break; case EVENT_LN: - if (reportType != null && eventKey != null) { + if ((reportType != null) && (eventKey != null)) { SurfaceObsLocation location = new SurfaceObsLocation( stationId); location.setLongitude(longitude.doubleValue()); location.setLatitude(latitude.doubleValue()); svrWxRecord = new SvrWxRecord(); - svrWxRecord.setPluginName(pluginName); svrWxRecord.setReportType(reportType); svrWxRecord.setGreenTime(greenTime); svrWxRecord.setLocation(location); @@ -301,19 +300,18 @@ public class SvrWxParser { break; case EXTRA: String s = rpt.getReportLine().trim(); - if (s.length() != 0 && remarks != null) { + if ((s.length() != 0) && (remarks != null)) { remarks += " " + s; } break; case END: - if (reportType != null && eventKey != null) { + if ((reportType != null) && (eventKey != null)) { SurfaceObsLocation location = new SurfaceObsLocation( stationId); location.setLongitude(longitude.doubleValue()); location.setLatitude(latitude.doubleValue()); svrWxRecord = new SvrWxRecord(); svrWxRecord.setReportType(reportType); - svrWxRecord.setPluginName(pluginName); svrWxRecord.setGreenTime(greenTime); svrWxRecord.setLocation(location); svrWxRecord.setDataTime(refTime); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/HURData.java b/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/HURData.java index 83d4ce4b2d..3606a81a11 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/HURData.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/HURData.java @@ -39,173 +39,190 @@ import com.vividsolutions.jts.geom.Coordinate; * TODO Add Description * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * Oct 26, 2009            jsanchez     Initial creation
- *
+ * Oct 26, 2009            jsanchez    Initial creation
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
+ * 
  * 
- * + * * @author jsanchez - * @version 1.0 + * @version 1.0 */ -public class HURData extends TCGDataAdapter{ - - private List forecastTimes = new ArrayList(); - - private HashMap> coordinates = new HashMap>(); - - public HURData(PointDataDescription pdd, TropicalCycloneGuidanceDao dao, String pluginName) { - super(pdd,dao,pluginName); +public class HURData extends TCGDataAdapter { + + private final List forecastTimes = new ArrayList(); + + private final HashMap> coordinates = new HashMap>(); + + public HURData(PointDataDescription pdd, TropicalCycloneGuidanceDao dao, + String pluginName) { + super(pdd, dao, pluginName); } - - public List findReports(byte [] message) { - + + @Override + public List findReports(byte[] message) { + List reports = new ArrayList(); List parts = InternalReport.identifyMessage(message); - - if(parts != null) { + + if (parts != null) { clearData(); - for(InternalReport iRpt : parts) { + for (InternalReport iRpt : parts) { InternalType t = iRpt.getLineType(); String s = iRpt.getReportLine(); - if (InternalType.PRODUCT.equals(t)) { + if (InternalType.PRODUCT.equals(t)) { productType = s; } else if (InternalType.DATA_INFO.equals(t)) { parseDataInfo(s); } else if (InternalType.DATETIME_INFO.equals(t)) { parseDateTimeInfo(s); - } else if(InternalType.MODEL_INFO.equals(t)) { + } else if (InternalType.MODEL_INFO.equals(t)) { parseModelInfo(s); - } else if(InternalType.END.equals(t)) { - for(String model : coordinates.keySet()) { + } else if (InternalType.END.equals(t)) { + for (String model : coordinates.keySet()) { List list = coordinates.get(model); - if(list.size() == forecastTimes.size()) { + if (list.size() == forecastTimes.size()) { for (int i = 0; i < list.size(); i++) { TropicalCycloneGuidance rpt = new TropicalCycloneGuidance(); - SurfaceObsLocation location = new SurfaceObsLocation(stationId); + SurfaceObsLocation location = new SurfaceObsLocation( + stationId); location.setLongitude(list.get(i).x); location.setLatitude(list.get(i).y); - + rpt.setWmoHeader(wmoHeader.getWmoHeader()); rpt.setTraceId(traceId); - rpt.setPluginName(pluginName); rpt.setStormName(stormName); rpt.setType(stormType); rpt.setProductType(productType); - rpt.setModelName(model); + rpt.setModelName(model); rpt.setLocation(location); - rpt.setInsertTime(Calendar.getInstance(TimeZone.getTimeZone("GMT"))); + rpt.setInsertTime(Calendar.getInstance(TimeZone + .getTimeZone("GMT"))); DataTime dt; - if(i != 0){ + if (i != 0) { int fcstTime = new Double( - (forecastTimes.get(i).getValidTime().getTimeInMillis() - - refTime.getValidTime().getTimeInMillis())/1000L).intValue(); - dt = new DataTime(refTime.getRefTimeAsCalendar(),fcstTime); + (forecastTimes.get(i) + .getValidTime() + .getTimeInMillis() - refTime + .getValidTime() + .getTimeInMillis()) / 1000L) + .intValue(); + dt = new DataTime( + refTime.getRefTimeAsCalendar(), + fcstTime); } else { - dt = new DataTime(refTime.getRefTimeAsCalendar()); + dt = new DataTime( + refTime.getRefTimeAsCalendar()); } rpt.setDataTime(dt); reports.add(rpt); } - } + } } clearData(); - } + } } } return reports; } - + private void parseModelInfo(String modelInfo) { Pattern modelPtrn = Pattern.compile(InternalReport.MODEL_PTRN); Pattern latlonPtrn = Pattern.compile(InternalReport.LATLON_PTRN); Matcher m = modelPtrn.matcher(modelInfo); - if(m.find()) { + if (m.find()) { String model = m.group(); List coordinate = coordinates.get(model); if (coordinate == null) { coordinate = new ArrayList(); } m = latlonPtrn.matcher(modelInfo); - while(m.find()){ + while (m.find()) { String latlon[] = m.group().split(" "); int n = latlon.length - 1; - - double lon = Double.valueOf(latlon[n].trim().substring(0, latlon[n].length() - 1)); - double lat = Double.valueOf(latlon[0].trim().substring(0, latlon[0].length() - 1)); - lon = latlon[n].charAt(latlon[n].length() - 1) == 'E'? lon : lon * -1; - lat = latlon[0].charAt(latlon[0].length() - 1) == 'N'? lat : lat * -1; - - Coordinate c = new Coordinate(lon,lat); + double lon = Double.valueOf(latlon[n].trim().substring(0, + latlon[n].length() - 1)); + double lat = Double.valueOf(latlon[0].trim().substring(0, + latlon[0].length() - 1)); + + lon = latlon[n].charAt(latlon[n].length() - 1) == 'E' ? lon + : lon * -1; + lat = latlon[0].charAt(latlon[0].length() - 1) == 'N' ? lat + : lat * -1; + + Coordinate c = new Coordinate(lon, lat); coordinate.add(c); } coordinates.put(model, coordinate); - + } } - + private void parseDateTimeInfo(String dateTimeInfo) { - Pattern dateTimePtrn = Pattern.compile(InternalReport.DATETIME); + Pattern dateTimePtrn = Pattern.compile(InternalReport.DATETIME); Matcher m = dateTimePtrn.matcher(dateTimeInfo); while (m.find()) { - //YYMMDD HHMM - String yy = m.group().substring(0,2); - if(Integer.valueOf(yy) < 70) { + // YYMMDD HHMM + String yy = m.group().substring(0, 2); + if (Integer.valueOf(yy) < 70) { yy = "20" + yy; } else { yy = "19" + yy; } int year = Integer.valueOf(yy); - int month = Integer.valueOf(m.group().substring(2,4)); - int day = Integer.valueOf(m.group().substring(4,6)); - int hour = Integer.valueOf(m.group().substring(8,10)); + int month = Integer.valueOf(m.group().substring(2, 4)); + int day = Integer.valueOf(m.group().substring(4, 6)); + int hour = Integer.valueOf(m.group().substring(8, 10)); int minute = Integer.valueOf(m.group().substring(10)); - forecastTimes.add(getDataTime(year, month, day, hour, minute, "GMT")); + forecastTimes + .add(getDataTime(year, month, day, hour, minute, "GMT")); } } - + private void parseDataInfo(String dataInfo) { Pattern stationIdPtrn = Pattern.compile(InternalReport.STATIONID_PTRN); Pattern refTimePtrn = Pattern.compile(InternalReport.REFTIME_PTRN); Matcher m = stationIdPtrn.matcher(dataInfo); - - if(m.find()) { - stationId = m.group().substring(1,m.group().length()-1); + + if (m.find()) { + stationId = m.group().substring(1, m.group().length() - 1); } - + m = refTimePtrn.matcher(dataInfo); - if(m.find()){ - //Reference Time - //YYYYMMDD HHMM + if (m.find()) { + // Reference Time + // YYYYMMDD HHMM int year = Integer.valueOf(m.group().substring(0, 4)); int month = Integer.valueOf(m.group().substring(4, 6)); int day = Integer.valueOf(m.group().substring(6, 8)); - int hour = Integer.valueOf(m.group().substring(9,11)); + int hour = Integer.valueOf(m.group().substring(9, 11)); int minute = Integer.valueOf(m.group().substring(11)); - refTime = getDataTime(year, month, day, hour, minute,"UTC"); + refTime = getDataTime(year, month, day, hour, minute, "UTC"); } else { refTime = new DataTime(); } - + int index = setStormType(dataInfo); - + if (index != -1) { - stormName = dataInfo.substring(index,dataInfo.indexOf("(")).trim(); + stormName = dataInfo.substring(index, dataInfo.indexOf("(")).trim(); } } - - private void refreshMaps(){ + + private void refreshMaps() { coordinates.put("BAMS", null); coordinates.put("BAMD", null); coordinates.put("BAMD", null); coordinates.put("LBAR", null); } - - public void clearData(){ + + @Override + public void clearData() { refreshMaps(); forecastTimes.clear(); stationId = null; @@ -213,5 +230,5 @@ public class HURData extends TCGDataAdapter{ stormName = null; refTime = null; } - + } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/QLMData.java b/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/QLMData.java index 0edd86c120..24ef9d6065 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/QLMData.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/QLMData.java @@ -40,11 +40,11 @@ import com.raytheon.uf.common.time.DataTime; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Oct 26, 2009 jsanchez Initial creation - * Jun 28, 2012 #826 dgilling Use wmoHeader headerDate to - * set refTime so times are set - * correctly when processing archive - * data. + * Oct 26, 2009 jsanchez Initial creation + * Jun 28, 2012 826 dgilling Use wmoHeader headerDate to set refTime + * so times are set correctly when + * processing archive data. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -67,7 +67,7 @@ public class QLMData extends TCGDataAdapter { } } - private List list = new ArrayList(); + private final List list = new ArrayList(); private static final int MAX_FORECASTS = 22; @@ -94,7 +94,7 @@ public class QLMData extends TCGDataAdapter { } else if (InternalType.FORECAST_POSITION_INFO.equals(t)) { parseForecastPositionInfo(s); } else if (InternalType.STORM_DISSIPATED.equals(t) - || list.size() == MAX_FORECASTS) { + || (list.size() == MAX_FORECASTS)) { boolean firstValue = true; for (ForecastPosition fp : list) { TropicalCycloneGuidance rpt = new TropicalCycloneGuidance(); @@ -105,7 +105,6 @@ public class QLMData extends TCGDataAdapter { rpt.setWmoHeader(wmoHeader.getWmoHeader()); rpt.setTraceId(traceId); - rpt.setPluginName(pluginName); rpt.setStormName(stormName); rpt.setType(stormType); rpt.setProductType(productType); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/TCEData.java b/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/TCEData.java index 4005da42e3..180c7a1e8c 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/TCEData.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.tcg/src/com/raytheon/uf/edex/plugin/tcg/decoder/TCEData.java @@ -37,76 +37,82 @@ import com.raytheon.uf.common.time.DataTime; * TODO Add Description * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * Nov 12, 2009            jsanchez     Initial creation
- *
+ * Nov 12, 2009            jsanchez    Initial creation
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
+ * 
  * 
- * + * * @author jsanchez - * @version 1.0 + * @version 1.0 */ -public class TCEData extends TCGDataAdapter{ - +public class TCEData extends TCGDataAdapter { + private float latitude = -9999; - + private float longitude = -9999; - + private int month; - + private int year; - + private int day; - + private int hour; - + private int minute; - - public TCEData(PointDataDescription pdd, TropicalCycloneGuidanceDao dao, String pluginName) { - super(pdd,dao,pluginName); + + public TCEData(PointDataDescription pdd, TropicalCycloneGuidanceDao dao, + String pluginName) { + super(pdd, dao, pluginName); } - - public List findReports(byte [] message) { + + @Override + public List findReports(byte[] message) { List reports = new ArrayList(); List parts = InternalReport.identifyMessage(message); - if(parts != null) { + if (parts != null) { clearData(); - for(InternalReport iRpt : parts) { + for (InternalReport iRpt : parts) { InternalType t = iRpt.getLineType(); String s = iRpt.getReportLine(); if (InternalType.PRODUCT.equals(t)) { productType = s; - } else if(InternalType.STORM_TYPE_INFO.equals(t)){ + } else if (InternalType.STORM_TYPE_INFO.equals(t)) { parseStormTypeInfo(s); - } else if(InternalType.STATIONID.equals(t)){ + } else if (InternalType.STATIONID.equals(t)) { parseStationIdInfo(s); - } else if(InternalType.INIT_TIME_INFO.equals(t)){ + } else if (InternalType.INIT_TIME_INFO.equals(t)) { parseInitTimeInfo(s); - } else if(InternalType.TCE_REFHOUR.equals(t)){ + } else if (InternalType.TCE_REFHOUR.equals(t)) { parseRefhour(s); - } else if(InternalType.LATITUDE.equals(t)){ + } else if (InternalType.LATITUDE.equals(t)) { parseLatitude(s); - } else if(InternalType.LONGITUDE.equals(t)){ + } else if (InternalType.LONGITUDE.equals(t)) { parseLongitude(s); - } else if(InternalType.END.equals(t)){ - if(latitude != -9999 && longitude != -9999){ + } else if (InternalType.END.equals(t)) { + if ((latitude != -9999) && (longitude != -9999)) { TropicalCycloneGuidance rpt = new TropicalCycloneGuidance(); - SurfaceObsLocation location = new SurfaceObsLocation(stationId); - location.setLongitude((double)longitude); - location.setLatitude((double)latitude); + SurfaceObsLocation location = new SurfaceObsLocation( + stationId); + location.setLongitude((double) longitude); + location.setLatitude((double) latitude); rpt.setWmoHeader(wmoHeader.getWmoHeader()); rpt.setTraceId(traceId); - rpt.setPluginName(pluginName); rpt.setStormName(stormName); rpt.setType(stormType); - rpt.setProductType(productType); + rpt.setProductType(productType); rpt.setLocation(location); - rpt.setInsertTime(Calendar.getInstance(TimeZone.getTimeZone("GMT"))); - refTime = getDataTime(year, month, day, hour, minute, "GMT"); - DataTime dt = new DataTime(refTime.getRefTimeAsCalendar()); + rpt.setInsertTime(Calendar.getInstance(TimeZone + .getTimeZone("GMT"))); + refTime = getDataTime(year, month, day, hour, minute, + "GMT"); + DataTime dt = new DataTime( + refTime.getRefTimeAsCalendar()); rpt.setDataTime(dt); reports.add(rpt); } @@ -116,65 +122,66 @@ public class TCEData extends TCGDataAdapter{ } return reports; } - - private void parseStormTypeInfo(String stormTypeInfo){ + + private void parseStormTypeInfo(String stormTypeInfo) { int index = setStormType(stormTypeInfo); if (index != -1) { String temp[] = stormTypeInfo.substring(index).trim().split(" "); stormName = temp[0]; } } - - private void parseStationIdInfo(String stationIdInfo){ + + private void parseStationIdInfo(String stationIdInfo) { Pattern p = Pattern.compile("(\\w{2,2}\\d{6,6})"); Matcher m = p.matcher(stationIdInfo); - if(m.find()){ + if (m.find()) { stationId = m.group(); } } - - private void parseInitTimeInfo(String initTimeInfo){ + + private void parseInitTimeInfo(String initTimeInfo) { String parts[] = getParts(initTimeInfo, 7); month = MONTH_MAP.get(parts[4]); day = Integer.parseInt(parts[5]); year = Integer.parseInt(parts[6]); } - - private void parseRefhour(String refhourInfo){ + + private void parseRefhour(String refhourInfo) { Pattern p = Pattern.compile("(\\d{4,4})"); Matcher m = p.matcher(refhourInfo); - if(m.find()){ - hour = Integer.parseInt(m.group().substring(0,2)); + if (m.find()) { + hour = Integer.parseInt(m.group().substring(0, 2)); minute = Integer.parseInt(m.group().substring(2)); } } - - private void parseLatitude(String latitudeInfo){ + + private void parseLatitude(String latitudeInfo) { Pattern p = Pattern.compile(InternalReport.LAT_PTRN); Matcher m = p.matcher(latitudeInfo); - if(m.find()){ + if (m.find()) { latitude = Float.parseFloat(m.group().substring(8).trim()); - if (latitudeInfo.contains("SOUTH")){ + if (latitudeInfo.contains("SOUTH")) { latitude *= -1; } } - + } - - private void parseLongitude(String longitudeInfo){ + + private void parseLongitude(String longitudeInfo) { Pattern p = Pattern.compile(InternalReport.LON_PTRN); Matcher m = p.matcher(longitudeInfo); - if(m.find()){ + if (m.find()) { longitude = Float.parseFloat(m.group().substring(10).trim()); - if(longitudeInfo.contains("WEST")){ + if (longitudeInfo.contains("WEST")) { longitude *= -1; - } else if (longitudeInfo.contains("SOUTH") && latitude > 0){ + } else if (longitudeInfo.contains("SOUTH") && (latitude > 0)) { latitude *= -1; } } } - - public void clearData(){ + + @Override + public void clearData() { latitude = -9999; longitude = -9999; stationId = null; diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.tcs/src/com/raytheon/uf/edex/plugin/tcs/decoder/TCMData.java b/edexOsgi/com.raytheon.uf.edex.plugin.tcs/src/com/raytheon/uf/edex/plugin/tcs/decoder/TCMData.java index 3d2da99d16..826f3ef328 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.tcs/src/com/raytheon/uf/edex/plugin/tcs/decoder/TCMData.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.tcs/src/com/raytheon/uf/edex/plugin/tcs/decoder/TCMData.java @@ -48,9 +48,10 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Oct 20, 2010 jsanchez Initial creation - * Apr 19, 2012 #457 dgilling Use TimeTools.findDataTime() - * to calculate times. + * Oct 20, 2010 jsanchez Initial creation + * Apr 19, 2012 457 dgilling Use TimeTools.findDataTime() to + * calculate times. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -144,7 +145,7 @@ public class TCMData extends TCSDataAdapter { } } - if (name == null || name.length() == 0) { + if ((name == null) || (name.length() == 0)) { m = stormNamePtrn.matcher(line); if (m.find()) { name = m.group(2); @@ -175,11 +176,11 @@ public class TCMData extends TCSDataAdapter { break; } // Searching for the press - if (pressure == 0 && line.contains(" PRESSURE ")) { + if ((pressure == 0) && line.contains(" PRESSURE ")) { m = pressurePtrn.matcher(line); if (m.find()) { pressure = Integer.parseInt(m.group(2)); - if (pressure < 800 || pressure > 1050) { + if ((pressure < 800) || (pressure > 1050)) { pressure = 0; } continue; @@ -192,7 +193,7 @@ public class TCMData extends TCSDataAdapter { m = windPtrn.matcher(line.replace("-", "")); if (m.find()) { int wind = Integer.parseInt(m.group(2)); - storm.setWindSpeed(wind > 0 && wind < 250 ? wind : 0); + storm.setWindSpeed((wind > 0) && (wind < 250) ? wind : 0); continue; } } @@ -208,9 +209,9 @@ public class TCMData extends TCSDataAdapter { String mask = line; // Searching for the wind radius if (Util.isWindRadius(type, mask, radius)) { - if (radius.getKFUnit() != 'x' && radius.getKT_FT() != -1 - && radius.getNE() != -1 && radius.getSE() != -1 - && radius.getSW() != -1 && radius.getNW() != -1) { + if ((radius.getKFUnit() != 'x') && (radius.getKT_FT() != -1) + && (radius.getNE() != -1) && (radius.getSE() != -1) + && (radius.getSW() != -1) && (radius.getNW() != -1)) { boolean exist = false; ArrayList radiusList = storm.getRadiusList(); @@ -234,12 +235,11 @@ public class TCMData extends TCSDataAdapter { } if (isLocation && !storm.getDisplayTime().equals("") - && storm.getWindSpeed() != 0) { + && (storm.getWindSpeed() != 0)) { storm.setTropical(!isExtraTropical); storm.setName(name); storm.setPressure(pressure); storm.setProductType(type.toString()); - storm.setPluginName(pluginName); stormList.add(storm); // Reset values @@ -272,7 +272,7 @@ public class TCMData extends TCSDataAdapter { break; } } - if (k < stormList.size() || storm.getDisplayTime().equals(time)) { + if ((k < stormList.size()) || storm.getDisplayTime().equals(time)) { continue; } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.vaa/src/com/raytheon/uf/edex/plugin/vaa/decoder/VAAParser.java b/edexOsgi/com.raytheon.uf.edex.plugin.vaa/src/com/raytheon/uf/edex/plugin/vaa/decoder/VAAParser.java index eebebc431f..43b20a9e02 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.vaa/src/com/raytheon/uf/edex/plugin/vaa/decoder/VAAParser.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.vaa/src/com/raytheon/uf/edex/plugin/vaa/decoder/VAAParser.java @@ -43,7 +43,8 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Nov 05, 2009 3267 jkorman Initial creation + * Nov 05, 2009 3267 jkorman Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -69,13 +70,13 @@ public class VAAParser implements Iterable { public String shapeType; } - private String pluginName; + private final String pluginName; - private WMOHeader wmoHeader; + private final WMOHeader wmoHeader; - private String traceId; + private final String traceId; - private List records = new ArrayList(); + private final List records = new ArrayList(); private List reports; @@ -115,7 +116,6 @@ public class VAAParser implements Iterable { VAARecord vaa = new VAARecord(); vaa.setTraceId(traceId); - vaa.setPluginName(pluginName); vaa.setWmoHeader(wmoHeader.getWmoHeader()); String cor = wmoHeader.getBBBIndicator(); if (cor != null) { diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.vil/src/com/raytheon/uf/edex/plugin/vil/VILGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.vil/src/com/raytheon/uf/edex/plugin/vil/VILGenerator.java index 43ba2ad369..9e3632848c 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.vil/src/com/raytheon/uf/edex/plugin/vil/VILGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.vil/src/com/raytheon/uf/edex/plugin/vil/VILGenerator.java @@ -49,8 +49,9 @@ import com.raytheon.uf.edex.plugin.vil.common.VILConfig; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 02/07/2009 2037 dhladky Initial Creation. - * 02/25/13 1660 D. Hladky Fixed SCAN configuration bug. + * Feb 07, 2009 2037 dhladky Initial Creation. + * Feb 25, 2013 1660 D. Hladky Fixed SCAN configuration bug. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -69,7 +70,7 @@ public class VILGenerator extends CompositeProductGenerator implements /** Set of icaos to filter for */ private Set icaos = null; - + /** run configuration manager **/ public SCANRunSiteConfigurationManager srcm = null; @@ -119,7 +120,7 @@ public class VILGenerator extends CompositeProductGenerator implements if (!configValid) { statusHandler.handle(Priority.WARN, - "Configuration for vil(scan) is invalid!!!"); + "Configuration for vil(scan) is invalid!!!"); return; } @@ -157,7 +158,6 @@ public class VILGenerator extends CompositeProductGenerator implements vilRec.setDy(ScanUtils.SCAN_GRID_DIM_RESOLUTION / 2); } - vilRec.setPluginName(this.getCompositeProductType()); vilRec.setIcao(vil_config.getIcao()); vilRec.setDataTime(this.getProductTime()); vilRec.setSpatialInfo(vil_config.getSpatialInfo()); @@ -190,7 +190,7 @@ public class VILGenerator extends CompositeProductGenerator implements resetFilters(); } } - + /** * run config manager * diff --git a/edexOsgi/com.raytheon.uf.edex.python.decoder/src/com/raytheon/uf/edex/python/decoder/PythonDecoder.java b/edexOsgi/com.raytheon.uf.edex.python.decoder/src/com/raytheon/uf/edex/python/decoder/PythonDecoder.java index 73921b93f0..753979938d 100644 --- a/edexOsgi/com.raytheon.uf.edex.python.decoder/src/com/raytheon/uf/edex/python/decoder/PythonDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.python.decoder/src/com/raytheon/uf/edex/python/decoder/PythonDecoder.java @@ -49,6 +49,7 @@ import com.vividsolutions.jts.io.WKTReader; * ------------ ---------- ----------- -------------------------- * Sep 22, 2008 njensen Initial creation * Nov 24, 2008 chammack Camel Refactor + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author njensen @@ -79,12 +80,13 @@ public class PythonDecoder extends AbstractDecoder { public PluginDataObject[] decode(File file) throws Exception { - List decodedObjects = new ArrayList(0); + List decodedObjects = new ArrayList( + 0); PythonScript py = null; long id = Thread.currentThread().getId(); try { - if (!cache || cachedInterpreters.get(id) == null) { + if (!cache || (cachedInterpreters.get(id) == null)) { py = PythonDecoderFactory.makePythonDecoder(pluginFQN, moduleName); } else { @@ -130,7 +132,7 @@ public class PythonDecoder extends AbstractDecoder { public List asPluginDataObjects(List result) throws Exception { List decodedObjects = null; - if (result == null || result.isEmpty()) { + if ((result == null) || result.isEmpty()) { decodedObjects = new ArrayList(0); } else { if (result.get(0) instanceof Map) { @@ -142,11 +144,9 @@ public class PythonDecoder extends AbstractDecoder { ArrayList> resultList = (ArrayList>) result; PluginDataObject record = (PluginDataObject) recordClass .newInstance(); - record.setPluginName(pluginName); BeanMap bm = BeanMap.create(record); for (HashMap map : resultList) { record = (PluginDataObject) recordClass.newInstance(); - record.setPluginName(pluginName); bm.setBean(record); try { for (String key : map.keySet()) { @@ -167,17 +167,17 @@ public class PythonDecoder extends AbstractDecoder { private Object transformValue(String key, Object val, BeanMap bm) { Class type = bm.getPropertyType(key); if (type != null) { - if (type.equals(Calendar.class) && val instanceof Long) { + if (type.equals(Calendar.class) && (val instanceof Long)) { Calendar cal = Calendar.getInstance(TimeZone .getTimeZone("Zulu")); cal.setTimeInMillis((Long) val); val = cal; - } else if (type.equals(DataTime.class) && val instanceof Long) { + } else if (type.equals(DataTime.class) && (val instanceof Long)) { Calendar cal = Calendar.getInstance(TimeZone .getTimeZone("Zulu")); cal.setTimeInMillis((Long) val); val = new DataTime(cal); - } else if (type.equals(Geometry.class) && val instanceof String) { + } else if (type.equals(Geometry.class) && (val instanceof String)) { val = buildGeometry((String) val); } } @@ -206,10 +206,10 @@ public class PythonDecoder extends AbstractDecoder { for (String coord : coords) { counter++; if ((counter % 2) == 0) { - buf.append(Double.parseDouble(coord) / -100 + " " + buf.append((Double.parseDouble(coord) / -100) + " " + tempbuf.toString() + ", "); if (counter == 2) { - firstpt.append(Double.parseDouble(coord) / -100 + " " + firstpt.append((Double.parseDouble(coord) / -100) + " " + tempbuf.toString() + ", "); } tempbuf.delete(0, tempbuf.length()); diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.airmet/src/gov/noaa/nws/ncep/common/dataplugin/airmet/AirmetRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.airmet/src/gov/noaa/nws/ncep/common/dataplugin/airmet/AirmetRecord.java index 6f067b1de7..87501866f8 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.airmet/src/gov/noaa/nws/ncep/common/dataplugin/airmet/AirmetRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.airmet/src/gov/noaa/nws/ncep/common/dataplugin/airmet/AirmetRecord.java @@ -60,110 +60,103 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "airmet", - indexes = { - @Index(name = "airmet_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "airmet", indexes = { @Index(name = "airmet_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize +public class AirmetRecord extends PluginDataObject { - -public class AirmetRecord extends PluginDataObject{ - - /** + /** * */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - // reportType is AIRMET. - @Column(length=32) - @DataURI(position=4) - @DynamicSerializeElement - private String reportType; - - // reportName will be SIERRA, TANGO, or ZULU - @Column(length=32) - @DataURI(position=1) - @DynamicSerializeElement - private String reportName; - - // WMO header - @Column(length=32) - @DataURI(position=2) - @DynamicSerializeElement - private String wmoHeader; - - // The issue office where the report from - @Column(length=32) - @DynamicSerializeElement - private String issueOffice; - - // Update number as: 1, 2, 3, ... - @Column - @DataURI(position=3) - @DynamicSerializeElement - private Integer updateNumber; - - // Issue time of the report - @Column - @DynamicSerializeElement - private Calendar issueTime; - - // The designator - @Column(length=8) - @DynamicSerializeElement - private String designatorBBB; - - // CorrectionFlag is a flag: 0 for normal, 1 for COR or CC, 2 for AMD, and 3 for TEST - /* - * CorrectionFlag is a flag: - * 0 for normal, 1 for COR or CC, 2 for AMD, 3 for TEST, and 4 for NIL report - */ - @Column + // reportType is AIRMET. + @Column(length = 32) + @DataURI(position = 4) @DynamicSerializeElement - private Integer correctionFlag; - - // The entire report - @Column(length=15000) - @DynamicSerializeElement - private String bullMessage; + private String reportType; + // reportName will be SIERRA, TANGO, or ZULU + @Column(length = 32) + @DataURI(position = 1) + @DynamicSerializeElement + private String reportName; - /** - * Airmet report - */ - @DynamicSerializeElement - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinColumn(name = "parentID", nullable = false) + // WMO header + @Column(length = 32) + @DataURI(position = 2) + @DynamicSerializeElement + private String wmoHeader; + + // The issue office where the report from + @Column(length = 32) + @DynamicSerializeElement + private String issueOffice; + + // Update number as: 1, 2, 3, ... + @Column + @DataURI(position = 3) + @DynamicSerializeElement + private Integer updateNumber; + + // Issue time of the report + @Column + @DynamicSerializeElement + private Calendar issueTime; + + // The designator + @Column(length = 8) + @DynamicSerializeElement + private String designatorBBB; + + // CorrectionFlag is a flag: 0 for normal, 1 for COR or CC, 2 for AMD, and 3 + // for TEST + /* + * CorrectionFlag is a flag: 0 for normal, 1 for COR or CC, 2 for AMD, 3 for + * TEST, and 4 for NIL report + */ + @Column + @DynamicSerializeElement + private Integer correctionFlag; + + // The entire report + @Column(length = 15000) + @DynamicSerializeElement + private String bullMessage; + + /** + * Airmet report + */ + @DynamicSerializeElement + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "parentID", nullable = false) @Index(name = "airmetReport_parentid_idex") - private Set airmetReport = new HashSet(); + private Set airmetReport = new HashSet(); - - /** + /** * Default Convstructor */ public AirmetRecord() { - this.issueOffice=""; - this.wmoHeader=""; - this.bullMessage=""; - this.designatorBBB=""; - this.updateNumber=0; - this.reportType=""; - this.reportName=null; - this.correctionFlag=0; + this.issueOffice = ""; + this.wmoHeader = ""; + this.bullMessage = ""; + this.designatorBBB = ""; + this.updateNumber = 0; + this.reportType = ""; + this.reportName = null; + this.correctionFlag = 0; } /** * Convstructs an airmet record from a dataURI * - * @param uri The dataURI + * @param uri + * The dataURI */ public AirmetRecord(String uri) { super(uri); } - @Override public IDecoderGettable getDecoderGettable() { // TODO Auto-generated method stub @@ -171,172 +164,180 @@ public class AirmetRecord extends PluginDataObject{ } /** - * @return the issueOffice - */ - public String getIssueOffice(){ - return issueOffice; - } + * @return the issueOffice + */ + public String getIssueOffice() { + return issueOffice; + } - /** - * @param issueOffice to set - */ - public void setIssueOffice(String issueOffice){ - this.issueOffice=issueOffice; - } - - /** - * @return the wmoHeader - */ - public String getWmoHeader(){ - return wmoHeader; - } + /** + * @param issueOffice + * to set + */ + public void setIssueOffice(String issueOffice) { + this.issueOffice = issueOffice; + } - /** - * @param wnoHeader to set - */ - public void setWmoHeader(String wmoHeader){ - this.wmoHeader=wmoHeader; - } - - /** - * @return the issueTime - */ - public Calendar getIssueTime(){ - return issueTime; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param issueTime to set - */ - public void setIssueTime(Calendar issueTime){ - this.issueTime=issueTime; - } - - /** - * @return the reportType - */ - public String getReportType() { - return reportType; - } + /** + * @param wnoHeader + * to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * @param reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } + /** + * @return the issueTime + */ + public Calendar getIssueTime() { + return issueTime; + } - /** - * @return the designatorBBB - */ - public String getDesignatorBBB() { - return designatorBBB; - } + /** + * @param issueTime + * to set + */ + public void setIssueTime(Calendar issueTime) { + this.issueTime = issueTime; + } - /** - * @param designatorBBB to set - */ - public void setDesignatorBBB(String designatorBBB) { - this.designatorBBB = designatorBBB; - } + /** + * @return the reportType + */ + public String getReportType() { + return reportType; + } - /** - * @return the correctionFlag - */ - public Integer getCorrectionFlag() { - return correctionFlag; - } + /** + * @param reportType + * to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } - /** - * @param correctionFlag to set - */ - public void setCorrectionFlag(Integer correctionFlag) { - this.correctionFlag = correctionFlag; - } + /** + * @return the designatorBBB + */ + public String getDesignatorBBB() { + return designatorBBB; + } - /** - * @return the updateNumber - */ - public Integer getUpdateNumber() { - return updateNumber; - } + /** + * @param designatorBBB + * to set + */ + public void setDesignatorBBB(String designatorBBB) { + this.designatorBBB = designatorBBB; + } - /** - * @param updateNumber to set - */ - public void setUpdateNumber(Integer updateNumber) { - this.updateNumber = updateNumber; - } + /** + * @return the correctionFlag + */ + public Integer getCorrectionFlag() { + return correctionFlag; + } - /** - * @return the bullMessage - */ - public String getBullMessage() { - return bullMessage; - } + /** + * @param correctionFlag + * to set + */ + public void setCorrectionFlag(Integer correctionFlag) { + this.correctionFlag = correctionFlag; + } - /** - * @param bullMessage to set - */ - public void setBullMessage(String bullMessage) { - this.bullMessage = bullMessage; - } - - /** - * @return the reportName - */ - public String getReportName() { - return reportName; - } + /** + * @return the updateNumber + */ + public Integer getUpdateNumber() { + return updateNumber; + } - /** - * @param reportName to set - */ - public void setReportName(String reportName) { - this.reportName = reportName; - } - - /** - * @return the set of AIRMET report - */ - public Set getAirmetReport() { - return airmetReport; - } + /** + * @param updateNumber + * to set + */ + public void setUpdateNumber(Integer updateNumber) { + this.updateNumber = updateNumber; + } - /** - * @param airmet the report to set - */ - public void setAirmetReport(Set curReport) { - this.airmetReport = curReport; - } + /** + * @return the bullMessage + */ + public String getBullMessage() { + return bullMessage; + } - /** - * @param add AirmetReport to set - */ - public void addAirmetReport(AirmetReport curReport){ - airmetReport.add(curReport); - //curReport.setParentID(this); - } - - /** - * Override existing set method to modify any - * classes that use the dataURI as a foreign key - */ - @Override - public void setIdentifier(Object dataURI) - { + /** + * @param bullMessage + * to set + */ + public void setBullMessage(String bullMessage) { + this.bullMessage = bullMessage; + } - this.identifier = dataURI; - /* - if(this.getAirmetReport() != null && this.getAirmetReport().size() > 0) - { - for (Iterator iter = this.getAirmetReport().iterator(); iter.hasNext();) { - AirmetReport cs = iter.next(); - cs.setParentID(this); - } - }*/ - - } + /** + * @return the reportName + */ + public String getReportName() { + return reportName; + } + + /** + * @param reportName + * to set + */ + public void setReportName(String reportName) { + this.reportName = reportName; + } + + /** + * @return the set of AIRMET report + */ + public Set getAirmetReport() { + return airmetReport; + } + + /** + * @param airmet + * the report to set + */ + public void setAirmetReport(Set curReport) { + this.airmetReport = curReport; + } + + /** + * @param add + * AirmetReport to set + */ + public void addAirmetReport(AirmetReport curReport) { + airmetReport.add(curReport); + // curReport.setParentID(this); + } + + /** + * Override existing set method to modify any classes that use the dataURI + * as a foreign key + */ + @Override + public void setIdentifier(Object dataURI) { + + this.identifier = dataURI; + /* + * if(this.getAirmetReport() != null && this.getAirmetReport().size() > + * 0) { for (Iterator iter = + * this.getAirmetReport().iterator(); iter.hasNext();) { AirmetReport cs + * = iter.next(); cs.setParentID(this); } } + */ + + } @Override @Column @@ -344,4 +345,9 @@ public class AirmetRecord extends PluginDataObject{ public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "airmet"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.atcf/src/gov/noaa/nws/ncep/common/dataplugin/atcf/AtcfRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.atcf/src/gov/noaa/nws/ncep/common/dataplugin/atcf/AtcfRecord.java index 7707ba49d9..b646d7d64d 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.atcf/src/gov/noaa/nws/ncep/common/dataplugin/atcf/AtcfRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.atcf/src/gov/noaa/nws/ncep/common/dataplugin/atcf/AtcfRecord.java @@ -1,23 +1,3 @@ -/* - * - * AtcfRecord - * - * This class performs the mapping to the database tables for the Automated - * Tropical Cyclone Forecast (ATCF) Decoder Plug-In - * - * SOFTWARE HISTORY - * Date Ticket# Engineer Description - * ------------ ----------- -------------- ----------------------------------- - * 06/23/10 283 F. J. Yen Initial creation - * * - * This code has been developed by the SIB for use in the AWIPS2 system. - * - * - * @author F. J. Yen, SIB - * @version 1 - - */ - package gov.noaa.nws.ncep.common.dataplugin.atcf; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; @@ -55,13 +35,14 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 06/23/10 208 F. J. Yen Initial Coding. - * 03/10/12 606 G. Hull added reportType to URI - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Jun 23, 2010 208 F. J. Yen Initial Coding. + * Mar 10, 2012 606 G. Hull added reportType to URI + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. - * + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author F. J. Yen, SIB @@ -74,683 +55,681 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "atcf", - indexes = { - @Index(name = "atcf_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "atcf", indexes = { @Index(name = "atcf_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class AtcfRecord extends PluginDataObject { - private static final long serialVersionUID = 1L; - private static final float RMISSD = IDecoderConstantsN.FLOAT_MISSING; - private static final Integer IMISSD = IDecoderConstantsN.INTEGER_MISSING; - - /** Report type */ - @DataURI(position = 8) - @Column(length = 32) - @XmlElement - @DynamicSerializeElement - private String reportType; - - /** - * Basin, e.g. WP, IO, SH, CP, EP, AL, SL - */ - @DataURI(position = 1) - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String basin; - - /** - * Annual cyclone number; 1 through 99 - */ - @DataURI(position = 2) - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private int cycloneNum; - - /** - * Warning Date-Time - */ - @DataURI(position = 3) - @Column - @DynamicSerializeElement - @XmlElement - private Calendar warnTime; - - /** - * Objective technique sorting number/Minutes for best track: 00-99 - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private int techniqueNum; - - /** - * Objective Technique or CARQ or WRNG, BEST for best Track - */ - @DataURI(position = 4) - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String technique; - - /** - * TAU -- forecast Period: -24 through 120 hours, 0 for best-track, negative - * forecastHours used for CARQ and WRNG records. - */ - @DataURI(position = 5) - @Column - @DynamicSerializeElement - @XmlElement - private int fcstHour; - - /** - * Latitude (degrees) for the DTG: -900 through 900 - */ - @DynamicSerializeElement - @XmlElement - private float clat; - - /** - * Longitude (degrees) for the DTG: -1800 through 1800 - */ - @DynamicSerializeElement - @XmlElement - private float clon; - - /** - * Maximum sustained wind speed in knots: 0 through 300 - */ - @DynamicSerializeElement - @XmlElement - private float windMax; - - /** - * Minimum sea level pressure, 1 through 1100MB - */ - @DynamicSerializeElement - @XmlElement - private float mslp; - - /** - * Level of tropical cyclone development; such as DB, TD, TS, TY, ... - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String intensity; - - /** - * Wind intensity (kts) for the radii defined i this record: 34, 50, 64 - */ - @DataURI(position = 6) - @DynamicSerializeElement - @XmlElement - private float radWind; - - /** - * Radius Code for wind intensity: AAA = full circle; QQQ = quadrant (NNQ, - * NEQ, EEQ, SEQ, SSQ, SWQ, WWQ, NWQ) - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String radWindQuad; - - /** - * If full circle, radius of specified wind intensity. If semicircle or - * quadrant, radius of specified wind intensity of circle portion specified - * in radius code. 0 - 1200 nm. - */ - @DynamicSerializeElement - @XmlElement - private float quad1WindRad; - - /** - * If full circle, this field not used. If semicircle, radius (nm) of - * specified wind intensity for semicircle not specified in radius code. If - * quadrant, radius (nm) of specified wind intensity for 2nd quadrant - * (counting clockwise from quadrant specified in radius code). 0 - 1200 nm. - */ - @DynamicSerializeElement - @XmlElement - private float quad2WindRad; - - /** - * If full circle or semicircle this field not used. If quadrant, radius - * (nm) of specified wind intensity for 3rd quadrant (counting clockwise - * from quadrant specified in radius code). 0 - 1200 nm. - */ - @DynamicSerializeElement - @XmlElement - private float quad3WindRad; - - /** - * If full circle or semicircle this field not used. If quadrant, radius - * (nm) of specified wind intensity for 4th quadrant (counting clockwise - * from quadrant specified in radius code). 0 - 1200 nm. - */ - @DynamicSerializeElement - @XmlElement - private float quad4WindRad; - - /** - * Pressure in millibars of the last closed isobar. 900 - 1050 mb - */ - @DynamicSerializeElement - @XmlElement - private float closedP; - - /** - * Radius of the last closed isobar in nm. 0 - 9999 nm - */ - @DynamicSerializeElement - @XmlElement - private float radClosedP; - - /** - * Radius of max winds. 0 - 999 nm - */ - @DynamicSerializeElement - @XmlElement - private float maxWindRad; - - /** - * Gusts. 0 - 995 kts. - */ - @DynamicSerializeElement - @XmlElement - private float gust; - - /** - * Eye diameter. 0 - 999nm - */ - @DynamicSerializeElement - @XmlElement - private float eyeSize; - - /** - * Subregion code: A, B, C, E, L, P, Q, S, W - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String subRegion; - - /** - * Max seas: 0 through 999 ft. - */ - @DynamicSerializeElement - @XmlElement - private float maxSeas; - - /** - * Forecaster's initials, used for forecastHour 0 WRNG, up to 3 chars - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String forecaster; - - /** - * Storm direction in compass coordinates, 0 - 359 degrees - */ - @DynamicSerializeElement - @XmlElement - private float stormDrct; - - /** - * Storm speed. 0 - 999 kts - */ - @DynamicSerializeElement - @XmlElement - private float stormSped; - - /** - * Literal storm name, NONAME, or INVEST - */ - @DataURI(position = 7) - @Column(length = 32) - @DynamicSerializeElement - @XmlElement - private String stormName; - - /** - * System depth, D=deep, M=medium, S=shallow, X=unknown - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String stormDepth; - - /** - * Wave height for radii defined in seas1 - seas4. 0 - 99 ft. - */ - @DynamicSerializeElement - @XmlElement - private float radWave; - - /** - * Radius code for seas wave height - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String radWaveQuad; - - /** - * First quadrant seas radius as defined by radWaveQuad, 0 - 999 nm - */ - @DynamicSerializeElement - @XmlElement - private float quad1WaveRad; - - /** - * Second quadrant seas radius as defined by radWaveQuad, 0 - 999 nm - */ - @DynamicSerializeElement - @XmlElement - private float quad2WaveRad; - - /** - * Third quadrant seas radius as defined by radWaveQuad, 0 - 999 nm - */ - @DynamicSerializeElement - @XmlElement - private float quad3WaveRad; - - /** - * Fourth quadrant seas radius as defined by radWaveQuad, 0 - 999 nm - */ - @DynamicSerializeElement - @XmlElement - private float quad4WaveRad; - - /* - * 20 character description of format to follow in userData - */ - @Column(length = 20) - @DynamicSerializeElement - @XmlElement - private String userDefined; - - /* - * User data section as indicated by userDefined parameter - */ - @Column(length = 30) - @DynamicSerializeElement - @XmlElement - private String userData; - - /** - * Default Constructor - */ - public AtcfRecord() { - this.reportType="ATCF"; - this.basin = " "; - this.cycloneNum = IMISSD; - this.warnTime = null; - this.techniqueNum = IMISSD; - this.technique = " "; - this.fcstHour = IMISSD; - this.clat = RMISSD; - this.clon = RMISSD; - this.windMax = RMISSD; - this.mslp = RMISSD; - this.intensity = " "; - this.radWind = RMISSD; - this.radWindQuad = " "; - this.quad1WindRad = RMISSD; - this.quad2WindRad = RMISSD; - this.quad3WindRad = RMISSD; - this.quad4WindRad = RMISSD; - this.closedP = RMISSD; - this.radClosedP = RMISSD; - this.maxWindRad = RMISSD; - this.gust = RMISSD; - this.eyeSize = RMISSD; - this.subRegion = " "; - this.maxSeas = RMISSD; - this.forecaster = " "; - this.stormDrct = RMISSD; - this.stormSped = RMISSD; - this.stormName = " "; - this.stormDepth = " "; - this.radWave = RMISSD; - this.radWaveQuad = " "; - this.quad1WaveRad = RMISSD; - this.quad2WaveRad = RMISSD; - this.quad3WaveRad = RMISSD; - this.quad4WaveRad = RMISSD; - this.userDefined = " "; - this.userData = " "; - } - - /** - * Constructs a atcf record from a dataURI - * - * @param uri - * The dataURI - */ - public AtcfRecord(String uri) { - super(uri); - } - - @Override - public IDecoderGettable getDecoderGettable() { - // TODO Auto-generated method stub - return null; - } - - public String getReportType() { - return reportType; - } - - public void setReportType(String reportType) { - this.reportType = reportType; - } - - public String getBasin() { - return basin; - } - - public void setBasin(String basin) { - this.basin = basin; - } - - public int getCycloneNum() { - return cycloneNum; - } - - public void setCycloneNum(int cycloneNum) { - this.cycloneNum = cycloneNum; - } - - public Calendar getWarnTime() { - return warnTime; - } - - public void setWarnTime(Calendar warnTime) { - this.warnTime = warnTime; - } - - public int getTechniqueNum() { - return techniqueNum; - } - - public void setTechniqueNum(int techniqueNum) { - this.techniqueNum = techniqueNum; - } - - public String getTechnique() { - return technique; - } - - public void setTechnique(String technique) { - this.technique = technique; - } - - public int getFcstHour() { - return fcstHour; - } - - public void setFcstHour(int fcstHour) { - this.fcstHour = fcstHour; - } - - public float getClat() { - return clat; - } - - public void setClat(float clat) { - this.clat = clat; - } - - public float getClon() { - return clon; - } - - public void setClon(float clon) { - this.clon = clon; - } - - public float getWindMax() { - return windMax; - } - - public void setWindMax(float windMax) { - this.windMax = windMax; - } - - public float getMslp() { - return mslp; - } - - public void setMslp(float mslp) { - this.mslp = mslp; - } - - public String getIntensity() { - return intensity; - } + private static final long serialVersionUID = 1L; + + private static final float RMISSD = IDecoderConstantsN.FLOAT_MISSING; + + private static final Integer IMISSD = IDecoderConstantsN.INTEGER_MISSING; + + /** Report type */ + @DataURI(position = 8) + @Column(length = 32) + @XmlElement + @DynamicSerializeElement + private String reportType; + + /** + * Basin, e.g. WP, IO, SH, CP, EP, AL, SL + */ + @DataURI(position = 1) + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String basin; + + /** + * Annual cyclone number; 1 through 99 + */ + @DataURI(position = 2) + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private int cycloneNum; + + /** + * Warning Date-Time + */ + @DataURI(position = 3) + @Column + @DynamicSerializeElement + @XmlElement + private Calendar warnTime; + + /** + * Objective technique sorting number/Minutes for best track: 00-99 + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private int techniqueNum; + + /** + * Objective Technique or CARQ or WRNG, BEST for best Track + */ + @DataURI(position = 4) + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String technique; + + /** + * TAU -- forecast Period: -24 through 120 hours, 0 for best-track, negative + * forecastHours used for CARQ and WRNG records. + */ + @DataURI(position = 5) + @Column + @DynamicSerializeElement + @XmlElement + private int fcstHour; + + /** + * Latitude (degrees) for the DTG: -900 through 900 + */ + @DynamicSerializeElement + @XmlElement + private float clat; + + /** + * Longitude (degrees) for the DTG: -1800 through 1800 + */ + @DynamicSerializeElement + @XmlElement + private float clon; + + /** + * Maximum sustained wind speed in knots: 0 through 300 + */ + @DynamicSerializeElement + @XmlElement + private float windMax; + + /** + * Minimum sea level pressure, 1 through 1100MB + */ + @DynamicSerializeElement + @XmlElement + private float mslp; + + /** + * Level of tropical cyclone development; such as DB, TD, TS, TY, ... + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String intensity; + + /** + * Wind intensity (kts) for the radii defined i this record: 34, 50, 64 + */ + @DataURI(position = 6) + @DynamicSerializeElement + @XmlElement + private float radWind; + + /** + * Radius Code for wind intensity: AAA = full circle; QQQ = quadrant (NNQ, + * NEQ, EEQ, SEQ, SSQ, SWQ, WWQ, NWQ) + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String radWindQuad; + + /** + * If full circle, radius of specified wind intensity. If semicircle or + * quadrant, radius of specified wind intensity of circle portion specified + * in radius code. 0 - 1200 nm. + */ + @DynamicSerializeElement + @XmlElement + private float quad1WindRad; + + /** + * If full circle, this field not used. If semicircle, radius (nm) of + * specified wind intensity for semicircle not specified in radius code. If + * quadrant, radius (nm) of specified wind intensity for 2nd quadrant + * (counting clockwise from quadrant specified in radius code). 0 - 1200 nm. + */ + @DynamicSerializeElement + @XmlElement + private float quad2WindRad; + + /** + * If full circle or semicircle this field not used. If quadrant, radius + * (nm) of specified wind intensity for 3rd quadrant (counting clockwise + * from quadrant specified in radius code). 0 - 1200 nm. + */ + @DynamicSerializeElement + @XmlElement + private float quad3WindRad; + + /** + * If full circle or semicircle this field not used. If quadrant, radius + * (nm) of specified wind intensity for 4th quadrant (counting clockwise + * from quadrant specified in radius code). 0 - 1200 nm. + */ + @DynamicSerializeElement + @XmlElement + private float quad4WindRad; + + /** + * Pressure in millibars of the last closed isobar. 900 - 1050 mb + */ + @DynamicSerializeElement + @XmlElement + private float closedP; + + /** + * Radius of the last closed isobar in nm. 0 - 9999 nm + */ + @DynamicSerializeElement + @XmlElement + private float radClosedP; + + /** + * Radius of max winds. 0 - 999 nm + */ + @DynamicSerializeElement + @XmlElement + private float maxWindRad; + + /** + * Gusts. 0 - 995 kts. + */ + @DynamicSerializeElement + @XmlElement + private float gust; + + /** + * Eye diameter. 0 - 999nm + */ + @DynamicSerializeElement + @XmlElement + private float eyeSize; + + /** + * Subregion code: A, B, C, E, L, P, Q, S, W + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String subRegion; + + /** + * Max seas: 0 through 999 ft. + */ + @DynamicSerializeElement + @XmlElement + private float maxSeas; + + /** + * Forecaster's initials, used for forecastHour 0 WRNG, up to 3 chars + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String forecaster; + + /** + * Storm direction in compass coordinates, 0 - 359 degrees + */ + @DynamicSerializeElement + @XmlElement + private float stormDrct; + + /** + * Storm speed. 0 - 999 kts + */ + @DynamicSerializeElement + @XmlElement + private float stormSped; + + /** + * Literal storm name, NONAME, or INVEST + */ + @DataURI(position = 7) + @Column(length = 32) + @DynamicSerializeElement + @XmlElement + private String stormName; + + /** + * System depth, D=deep, M=medium, S=shallow, X=unknown + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String stormDepth; + + /** + * Wave height for radii defined in seas1 - seas4. 0 - 99 ft. + */ + @DynamicSerializeElement + @XmlElement + private float radWave; + + /** + * Radius code for seas wave height + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String radWaveQuad; + + /** + * First quadrant seas radius as defined by radWaveQuad, 0 - 999 nm + */ + @DynamicSerializeElement + @XmlElement + private float quad1WaveRad; + + /** + * Second quadrant seas radius as defined by radWaveQuad, 0 - 999 nm + */ + @DynamicSerializeElement + @XmlElement + private float quad2WaveRad; + + /** + * Third quadrant seas radius as defined by radWaveQuad, 0 - 999 nm + */ + @DynamicSerializeElement + @XmlElement + private float quad3WaveRad; + + /** + * Fourth quadrant seas radius as defined by radWaveQuad, 0 - 999 nm + */ + @DynamicSerializeElement + @XmlElement + private float quad4WaveRad; + + /* + * 20 character description of format to follow in userData + */ + @Column(length = 20) + @DynamicSerializeElement + @XmlElement + private String userDefined; + + /* + * User data section as indicated by userDefined parameter + */ + @Column(length = 30) + @DynamicSerializeElement + @XmlElement + private String userData; + + /** + * Default Constructor + */ + public AtcfRecord() { + this.reportType = "ATCF"; + this.basin = " "; + this.cycloneNum = IMISSD; + this.warnTime = null; + this.techniqueNum = IMISSD; + this.technique = " "; + this.fcstHour = IMISSD; + this.clat = RMISSD; + this.clon = RMISSD; + this.windMax = RMISSD; + this.mslp = RMISSD; + this.intensity = " "; + this.radWind = RMISSD; + this.radWindQuad = " "; + this.quad1WindRad = RMISSD; + this.quad2WindRad = RMISSD; + this.quad3WindRad = RMISSD; + this.quad4WindRad = RMISSD; + this.closedP = RMISSD; + this.radClosedP = RMISSD; + this.maxWindRad = RMISSD; + this.gust = RMISSD; + this.eyeSize = RMISSD; + this.subRegion = " "; + this.maxSeas = RMISSD; + this.forecaster = " "; + this.stormDrct = RMISSD; + this.stormSped = RMISSD; + this.stormName = " "; + this.stormDepth = " "; + this.radWave = RMISSD; + this.radWaveQuad = " "; + this.quad1WaveRad = RMISSD; + this.quad2WaveRad = RMISSD; + this.quad3WaveRad = RMISSD; + this.quad4WaveRad = RMISSD; + this.userDefined = " "; + this.userData = " "; + } + + /** + * Constructs a atcf record from a dataURI + * + * @param uri + * The dataURI + */ + public AtcfRecord(String uri) { + super(uri); + } + + @Override + public IDecoderGettable getDecoderGettable() { + // TODO Auto-generated method stub + return null; + } + + public String getReportType() { + return reportType; + } + + public void setReportType(String reportType) { + this.reportType = reportType; + } + + public String getBasin() { + return basin; + } + + public void setBasin(String basin) { + this.basin = basin; + } + + public int getCycloneNum() { + return cycloneNum; + } + + public void setCycloneNum(int cycloneNum) { + this.cycloneNum = cycloneNum; + } + + public Calendar getWarnTime() { + return warnTime; + } + + public void setWarnTime(Calendar warnTime) { + this.warnTime = warnTime; + } + + public int getTechniqueNum() { + return techniqueNum; + } + + public void setTechniqueNum(int techniqueNum) { + this.techniqueNum = techniqueNum; + } + + public String getTechnique() { + return technique; + } + + public void setTechnique(String technique) { + this.technique = technique; + } + + public int getFcstHour() { + return fcstHour; + } + + public void setFcstHour(int fcstHour) { + this.fcstHour = fcstHour; + } + + public float getClat() { + return clat; + } + + public void setClat(float clat) { + this.clat = clat; + } + + public float getClon() { + return clon; + } + + public void setClon(float clon) { + this.clon = clon; + } + + public float getWindMax() { + return windMax; + } + + public void setWindMax(float windMax) { + this.windMax = windMax; + } + + public float getMslp() { + return mslp; + } + + public void setMslp(float mslp) { + this.mslp = mslp; + } + + public String getIntensity() { + return intensity; + } - public void setIntensity(String intensity) { - this.intensity = intensity; - } + public void setIntensity(String intensity) { + this.intensity = intensity; + } - public float getRadWind() { - return radWind; - } + public float getRadWind() { + return radWind; + } - public void setRadWind(float radWind) { - this.radWind = radWind; - } + public void setRadWind(float radWind) { + this.radWind = radWind; + } - public String getRadWindQuad() { - return radWindQuad; - } + public String getRadWindQuad() { + return radWindQuad; + } - public void setRadWindQuad(String radWindQuad) { - this.radWindQuad = radWindQuad; - } + public void setRadWindQuad(String radWindQuad) { + this.radWindQuad = radWindQuad; + } - public float getQuad1WindRad() { - return quad1WindRad; - } + public float getQuad1WindRad() { + return quad1WindRad; + } - public void setQuad1WindRad(float quad1WindRad) { - this.quad1WindRad = quad1WindRad; - } + public void setQuad1WindRad(float quad1WindRad) { + this.quad1WindRad = quad1WindRad; + } - public float getQuad2WindRad() { - return quad2WindRad; - } + public float getQuad2WindRad() { + return quad2WindRad; + } - public void setQuad2WindRad(float quad2WindRad) { - this.quad2WindRad = quad2WindRad; - } + public void setQuad2WindRad(float quad2WindRad) { + this.quad2WindRad = quad2WindRad; + } - public float getQuad3WindRad() { - return quad3WindRad; - } + public float getQuad3WindRad() { + return quad3WindRad; + } - public void setQuad3WindRad(float quad3WindRad) { - this.quad3WindRad = quad3WindRad; - } + public void setQuad3WindRad(float quad3WindRad) { + this.quad3WindRad = quad3WindRad; + } - public float getQuad4WindRad() { - return quad4WindRad; - } + public float getQuad4WindRad() { + return quad4WindRad; + } - public void setQuad4WindRad(float quad4WindRad) { - this.quad4WindRad = quad4WindRad; - } + public void setQuad4WindRad(float quad4WindRad) { + this.quad4WindRad = quad4WindRad; + } - public float getClosedP() { - return closedP; - } + public float getClosedP() { + return closedP; + } - public void setClosedP(float closedP) { - this.closedP = closedP; - } + public void setClosedP(float closedP) { + this.closedP = closedP; + } - public float getRadClosedP() { - return radClosedP; - } + public float getRadClosedP() { + return radClosedP; + } - public void setRadClosedP(float radClosedP) { - this.radClosedP = radClosedP; - } + public void setRadClosedP(float radClosedP) { + this.radClosedP = radClosedP; + } - public float getMaxWindRad() { - return maxWindRad; - } + public float getMaxWindRad() { + return maxWindRad; + } - public void setMaxWindRad(float maxWindRad) { - this.maxWindRad = maxWindRad; - } + public void setMaxWindRad(float maxWindRad) { + this.maxWindRad = maxWindRad; + } - public float getGust() { - return gust; - } + public float getGust() { + return gust; + } - public void setGust(float gust) { - this.gust = gust; - } + public void setGust(float gust) { + this.gust = gust; + } - public float getEyeSize() { - return eyeSize; - } + public float getEyeSize() { + return eyeSize; + } - public void setEyeSize(float eyeSize) { - this.eyeSize = eyeSize; - } + public void setEyeSize(float eyeSize) { + this.eyeSize = eyeSize; + } - public String getSubRegion() { - return subRegion; - } + public String getSubRegion() { + return subRegion; + } - public void setSubRegion(String subRegion) { - this.subRegion = subRegion; - } + public void setSubRegion(String subRegion) { + this.subRegion = subRegion; + } - public float getMaxSeas() { - return maxSeas; - } + public float getMaxSeas() { + return maxSeas; + } - public void setMaxSeas(float maxSeas) { - this.maxSeas = maxSeas; - } + public void setMaxSeas(float maxSeas) { + this.maxSeas = maxSeas; + } - public String getForecaster() { - return forecaster; - } + public String getForecaster() { + return forecaster; + } - public void setForecaster(String forecaster) { - this.forecaster = forecaster; - } + public void setForecaster(String forecaster) { + this.forecaster = forecaster; + } - public float getStormDrct() { - return stormDrct; - } + public float getStormDrct() { + return stormDrct; + } - public void setStormDrct(float stormDrct) { - this.stormDrct = stormDrct; - } + public void setStormDrct(float stormDrct) { + this.stormDrct = stormDrct; + } - public float getStormSped() { - return stormSped; - } + public float getStormSped() { + return stormSped; + } - public void setStormSped(float stormSped) { - this.stormSped = stormSped; - } + public void setStormSped(float stormSped) { + this.stormSped = stormSped; + } - public String getStormName() { - return stormName; - } + public String getStormName() { + return stormName; + } - public void setStormName(String stormName) { - this.stormName = stormName; - } + public void setStormName(String stormName) { + this.stormName = stormName; + } - public String getStormDepth() { - return stormDepth; - } + public String getStormDepth() { + return stormDepth; + } - public void setStormDepth(String stormDepth) { - this.stormDepth = stormDepth; - } + public void setStormDepth(String stormDepth) { + this.stormDepth = stormDepth; + } - public float getRadWave() { - return radWave; - } + public float getRadWave() { + return radWave; + } - public void setRadWave(float radWave) { - this.radWave = radWave; - } + public void setRadWave(float radWave) { + this.radWave = radWave; + } - public String getRadWaveQuad() { - return radWaveQuad; - } + public String getRadWaveQuad() { + return radWaveQuad; + } - public void setRadWaveQuad(String radWaveQuad) { - this.radWaveQuad = radWaveQuad; - } + public void setRadWaveQuad(String radWaveQuad) { + this.radWaveQuad = radWaveQuad; + } - public float getQuad1WaveRad() { - return quad1WaveRad; - } + public float getQuad1WaveRad() { + return quad1WaveRad; + } - public void setQuad1WaveRad(float quad1WaveRad) { - this.quad1WaveRad = quad1WaveRad; - } + public void setQuad1WaveRad(float quad1WaveRad) { + this.quad1WaveRad = quad1WaveRad; + } - public float getQuad2WaveRad() { - return quad2WaveRad; - } + public float getQuad2WaveRad() { + return quad2WaveRad; + } - public void setQuad2WaveRad(float quad2WaveRad) { - this.quad2WaveRad = quad2WaveRad; - } + public void setQuad2WaveRad(float quad2WaveRad) { + this.quad2WaveRad = quad2WaveRad; + } - public float getQuad3WaveRad() { - return quad3WaveRad; - } + public float getQuad3WaveRad() { + return quad3WaveRad; + } - public void setQuad3WaveRad(float quad3WaveRad) { - this.quad3WaveRad = quad3WaveRad; - } + public void setQuad3WaveRad(float quad3WaveRad) { + this.quad3WaveRad = quad3WaveRad; + } - public float getQuad4WaveRad() { - return quad4WaveRad; - } + public float getQuad4WaveRad() { + return quad4WaveRad; + } - public void setQuad4WaveRad(float quad4WaveRad) { - this.quad4WaveRad = quad4WaveRad; - } + public void setQuad4WaveRad(float quad4WaveRad) { + this.quad4WaveRad = quad4WaveRad; + } - public String getUserDefined() { - return userDefined; - } + public String getUserDefined() { + return userDefined; + } - public void setUserDefined(String userDefined) { - this.userDefined = userDefined; - } + public void setUserDefined(String userDefined) { + this.userDefined = userDefined; + } - public String getUserData() { - return userData; - } + public String getUserData() { + return userData; + } - public void setUserData(String userData) { - this.userData = userData; - } + public void setUserData(String userData) { + this.userData = userData; + } @Override @Column @@ -758,4 +737,9 @@ public class AtcfRecord extends PluginDataObject { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "atcf"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.aww/src/gov/noaa/nws/ncep/common/dataplugin/aww/AwwRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.aww/src/gov/noaa/nws/ncep/common/dataplugin/aww/AwwRecord.java index 5d99f7939a..61e7aecdb9 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.aww/src/gov/noaa/nws/ncep/common/dataplugin/aww/AwwRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.aww/src/gov/noaa/nws/ncep/common/dataplugin/aww/AwwRecord.java @@ -66,52 +66,26 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "aww", - indexes = { - @Index(name = "aww_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "aww", indexes = { @Index(name = "aww_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize +public class AwwRecord extends PluginDataObject { -public class AwwRecord extends PluginDataObject{ - - private static final long serialVersionUID = 1L; - - /* - * There are many report types as follows: - * 1. SEVERE THUNDERSTORM WARNING - * 2. SEVERE THUNDERSTORM WATCH - * 3. TORNADO WARNING - * 4. TORNADO WATCH - * 5. SEVERE THUNDERSTORM OUTLINE UPDATE - * 6. TORNADO WATCH OUTLINE UPDATE - * 7. FLASH FLOOD WARNING - * 8. FLASH FLOOD WATCH - * 9. FLOOD WARNING - * 10. FLOOD WATCH - * 11. FLOOD STATEMENT - * 12. WINTER STORM WARNING - * 13. WINTER STORM WATCH - * 14. WATCH COUNTY NOTIFICATION - * 15. SEVERE WEATHER STATEMENT - * 16. WIND ADVISORY - * 17. FOG ADVISORY - * 18. HEAT ADVISORY - * 19. FROST ADVISORY - * 20. SMOKE ADVISORY - * 21. WEATHER ADVISORY - * 22. WINTER WEATHER ADVISORY - * 23. SIGNIGICANT WEATHER ADVISORY - * 24. SPECIAL WEATHER STATEMENT - * 25. RED FLAG WARNING - * 26. TORNADO REPORT - * 27. HIGH WIND WARNING - * 28. FREEZE WARNING - * 29. ADVERTENCIA DE INUNDACIONES - * 30. HYDROLOGIC STATEMENT - * 31. URGENT WEATHER MESSAGE - */ + private static final long serialVersionUID = 1L; + + /* + * There are many report types as follows: 1. SEVERE THUNDERSTORM WARNING 2. + * SEVERE THUNDERSTORM WATCH 3. TORNADO WARNING 4. TORNADO WATCH 5. SEVERE + * THUNDERSTORM OUTLINE UPDATE 6. TORNADO WATCH OUTLINE UPDATE 7. FLASH + * FLOOD WARNING 8. FLASH FLOOD WATCH 9. FLOOD WARNING 10. FLOOD WATCH 11. + * FLOOD STATEMENT 12. WINTER STORM WARNING 13. WINTER STORM WATCH 14. WATCH + * COUNTY NOTIFICATION 15. SEVERE WEATHER STATEMENT 16. WIND ADVISORY 17. + * FOG ADVISORY 18. HEAT ADVISORY 19. FROST ADVISORY 20. SMOKE ADVISORY 21. + * WEATHER ADVISORY 22. WINTER WEATHER ADVISORY 23. SIGNIGICANT WEATHER + * ADVISORY 24. SPECIAL WEATHER STATEMENT 25. RED FLAG WARNING 26. TORNADO + * REPORT 27. HIGH WIND WARNING 28. FREEZE WARNING 29. ADVERTENCIA DE + * INUNDACIONES 30. HYDROLOGIC STATEMENT 31. URGENT WEATHER MESSAGE + */ public static enum AwwReportType { SEVERE_THUNDERSTORM_WARNING, SEVERE_THUNDERSTORM_WATCH, @@ -175,89 +149,87 @@ public class AwwRecord extends PluginDataObject{ } } - @Column(length=40) - @DataURI(position=1) - @DynamicSerializeElement - private String reportType; - - // The issue office where the report from - @Column(length=32) - @DataURI(position=2) - @DynamicSerializeElement - private String issueOffice; - - // The collection of watch numbers in the report - @Column(length=160) - @DataURI(position=5) - @DynamicSerializeElement - private String watchNumber; - - // WMO header - @Column(length=32) - @DynamicSerializeElement - private String wmoHeader; - - // Issue time of the report - @Column - @DataURI(position=3) - @DynamicSerializeElement - private Calendar issueTime; - - // The designator - @Column(length=8) - @DataURI(position=4) - @DynamicSerializeElement - private String designatorBBB; - - // The designator - @Column(length=72) - @DataURI(position=6) - @DynamicSerializeElement - private String mndTime; - - // Attention WFO - @Column(length=72) - @DynamicSerializeElement - private String attentionWFO; - - // The entire report - @Column(length=40000) - @DynamicSerializeElement - private String bullMessage; - + @Column(length = 40) + @DataURI(position = 1) + @DynamicSerializeElement + private String reportType; - // AWW UGC Table - @DynamicSerializeElement - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinColumn(name = "parentID", nullable = false) + // The issue office where the report from + @Column(length = 32) + @DataURI(position = 2) + @DynamicSerializeElement + private String issueOffice; + + // The collection of watch numbers in the report + @Column(length = 160) + @DataURI(position = 5) + @DynamicSerializeElement + private String watchNumber; + + // WMO header + @Column(length = 32) + @DynamicSerializeElement + private String wmoHeader; + + // Issue time of the report + @Column + @DataURI(position = 3) + @DynamicSerializeElement + private Calendar issueTime; + + // The designator + @Column(length = 8) + @DataURI(position = 4) + @DynamicSerializeElement + private String designatorBBB; + + // The designator + @Column(length = 72) + @DataURI(position = 6) + @DynamicSerializeElement + private String mndTime; + + // Attention WFO + @Column(length = 72) + @DynamicSerializeElement + private String attentionWFO; + + // The entire report + @Column(length = 40000) + @DynamicSerializeElement + private String bullMessage; + + // AWW UGC Table + @DynamicSerializeElement + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "parentID", nullable = false) @Index(name = "awwUGC_parentid_idex") - private Set awwUGC = new HashSet(); + private Set awwUGC = new HashSet(); - - /** + /** * Default Convstructor */ public AwwRecord() { - this.issueOffice=null; - this.watchNumber="0000"; - this.issueTime=null; - this.attentionWFO=null; - this.wmoHeader=null; - this.designatorBBB=null; - this.bullMessage=null; - this.mndTime=null; + this.issueOffice = null; + this.watchNumber = "0000"; + this.issueTime = null; + this.attentionWFO = null; + this.wmoHeader = null; + this.designatorBBB = null; + this.bullMessage = null; + this.mndTime = null; } /** * Convstructs a consigmet record from a dataURI * - * @param uri The dataURI + * @param uri + * The dataURI */ public AwwRecord(String uri) { super(uri); } - - + @Override public IDecoderGettable getDecoderGettable() { // TODO Auto-generated method stub @@ -265,165 +237,173 @@ public class AwwRecord extends PluginDataObject{ } /** - * @return the reportType - */ + * @return the reportType + */ public String getReportType() { - return reportType; - } + return reportType; + } /** - * @return the reportType - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } + * @return the reportType + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } - /** - * @return the wmoHeader - */ - public String getWmoHeader(){ - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wnoHeader to set - */ - public void setWmoHeader(String wmoHeader){ - this.wmoHeader=wmoHeader; - } - - /** - * @return the issueTime - */ - public Calendar getIssueTime(){ - return issueTime; - } + /** + * @param wnoHeader + * to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * @param issueTime to set - */ - public void setIssueTime(Calendar issueTime){ - this.issueTime=issueTime; - } + /** + * @return the issueTime + */ + public Calendar getIssueTime() { + return issueTime; + } - /** - * @return the set of UGC - */ - public Set getAwwUGC() { - return awwUGC; - } + /** + * @param issueTime + * to set + */ + public void setIssueTime(Calendar issueTime) { + this.issueTime = issueTime; + } - /** - * @param awwUgc the ugc to set - */ - public void setAwwUGC(Set awwUgc) { - this.awwUGC = awwUgc; - } + /** + * @return the set of UGC + */ + public Set getAwwUGC() { + return awwUGC; + } - /** - * @param add AWW UGC to set - */ - public void addAwwUGC(AwwUgc pugc){ - awwUGC.add(pugc); - //pugc.setParentID(this); - } + /** + * @param awwUgc + * the ugc to set + */ + public void setAwwUGC(Set awwUgc) { + this.awwUGC = awwUgc; + } - /** - * Override existing set method to modify any - * classes that use the dataURI as a foreign key - */ - public void setIdentifier(Object dataURI) - { + /** + * @param add + * AWW UGC to set + */ + public void addAwwUGC(AwwUgc pugc) { + awwUGC.add(pugc); + // pugc.setParentID(this); + } - this.identifier = dataURI; - - - - } + /** + * Override existing set method to modify any classes that use the dataURI + * as a foreign key + */ + @Override + public void setIdentifier(Object dataURI) { - /** - * @return the designator - */ - public String getDesignatorBBB() { - return designatorBBB; - } + this.identifier = dataURI; - /** - * @param designatorBBB to set - */ - public void setDesignatorBBB(String designatorBBB) { - this.designatorBBB = designatorBBB; - } + } - /** - * @return the attentionWFO - */ - public String getAttentionWFO() { - return attentionWFO; - } + /** + * @return the designator + */ + public String getDesignatorBBB() { + return designatorBBB; + } - /** - * @param attentionWFO to set - */ - public void setAttentionWFO(String attentionWFO) { - this.attentionWFO = attentionWFO; - } + /** + * @param designatorBBB + * to set + */ + public void setDesignatorBBB(String designatorBBB) { + this.designatorBBB = designatorBBB; + } - /** - * @return the watchNumber - */ - public String getWatchNumber() { - return watchNumber; - } + /** + * @return the attentionWFO + */ + public String getAttentionWFO() { + return attentionWFO; + } - /** - * @param watchNumber to set - */ - public void setWatchNumber(String watchNumber) { - this.watchNumber = watchNumber; - } + /** + * @param attentionWFO + * to set + */ + public void setAttentionWFO(String attentionWFO) { + this.attentionWFO = attentionWFO; + } - /** - * @return the bullMessage - */ - public String getBullMessage() { - return bullMessage; - } + /** + * @return the watchNumber + */ + public String getWatchNumber() { + return watchNumber; + } - /** - * @param bullMessage to set - */ - public void setBullMessage(String bullMessage) { - this.bullMessage = bullMessage; - } + /** + * @param watchNumber + * to set + */ + public void setWatchNumber(String watchNumber) { + this.watchNumber = watchNumber; + } - /** - * @return the issueOffice - */ - public String getIssueOffice() { - return issueOffice; - } + /** + * @return the bullMessage + */ + public String getBullMessage() { + return bullMessage; + } - /** - * @param issueOffice to set - */ - public void setIssueOffice(String issueOffice) { - this.issueOffice = issueOffice; - } + /** + * @param bullMessage + * to set + */ + public void setBullMessage(String bullMessage) { + this.bullMessage = bullMessage; + } - /** - * @return the mndTime - */ - public String getMndTime() { - return mndTime; - } + /** + * @return the issueOffice + */ + public String getIssueOffice() { + return issueOffice; + } - /** - * @param mndTime to set - */ - public void setMndTime(String mndTime) { - this.mndTime = mndTime; - } + /** + * @param issueOffice + * to set + */ + public void setIssueOffice(String issueOffice) { + this.issueOffice = issueOffice; + } + + /** + * @return the mndTime + */ + public String getMndTime() { + return mndTime; + } + + /** + * @param mndTime + * to set + */ + public void setMndTime(String mndTime) { + this.mndTime = mndTime; + } @Override @Column @@ -431,4 +411,9 @@ public class AwwRecord extends PluginDataObject{ public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "aww"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.convsigmet/src/gov/noaa/nws/ncep/common/dataplugin/convsigmet/ConvSigmetRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.convsigmet/src/gov/noaa/nws/ncep/common/dataplugin/convsigmet/ConvSigmetRecord.java index c5b4beda65..6799bf4f97 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.convsigmet/src/gov/noaa/nws/ncep/common/dataplugin/convsigmet/ConvSigmetRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.convsigmet/src/gov/noaa/nws/ncep/common/dataplugin/convsigmet/ConvSigmetRecord.java @@ -56,97 +56,91 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "convsigmet", - indexes = { - @Index(name = "convsigmet_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "convsigmet", indexes = { @Index(name = "convsigmet_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize -public class ConvSigmetRecord extends PluginDataObject{ +public class ConvSigmetRecord extends PluginDataObject { - /** + /** * */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - // reportType is "convective sigmet". - @Column(length=32) - @DataURI(position=1) - @DynamicSerializeElement - private String reportType; - - // WMO header - @Column(length=32) - @DataURI(position=2) - @DynamicSerializeElement - private String wmoHeader; - - // forecastRegion as: SIGW, SIGC, or SIGE - @Column(length=8) - @DataURI(position=3) - @DynamicSerializeElement - private String forecastRegion; - - // The issue office where the report from - @Column(length=32) - @DynamicSerializeElement - private String issueOffice; - - // Issue time of the report - @Column - @DynamicSerializeElement - private Calendar issueTime; - - // The designator - @Column(length=8) - @DynamicSerializeElement - private String designatorBBB; - - // CorrectionFlag is a flag indicating a cancellation (0 or 1) - @Column + // reportType is "convective sigmet". + @Column(length = 32) + @DataURI(position = 1) @DynamicSerializeElement - private Integer correctionFlag; - - // The entire report - @Column(length=15000) - @DynamicSerializeElement - private String bullMessage; + private String reportType; + // WMO header + @Column(length = 32) + @DataURI(position = 2) + @DynamicSerializeElement + private String wmoHeader; - /** - * Convsigmet section - */ - @DynamicSerializeElement - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinColumn(name = "parentID", nullable = false) + // forecastRegion as: SIGW, SIGC, or SIGE + @Column(length = 8) + @DataURI(position = 3) + @DynamicSerializeElement + private String forecastRegion; + + // The issue office where the report from + @Column(length = 32) + @DynamicSerializeElement + private String issueOffice; + + // Issue time of the report + @Column + @DynamicSerializeElement + private Calendar issueTime; + + // The designator + @Column(length = 8) + @DynamicSerializeElement + private String designatorBBB; + + // CorrectionFlag is a flag indicating a cancellation (0 or 1) + @Column + @DynamicSerializeElement + private Integer correctionFlag; + + // The entire report + @Column(length = 15000) + @DynamicSerializeElement + private String bullMessage; + + /** + * Convsigmet section + */ + @DynamicSerializeElement + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "parentID", nullable = false) @Index(name = "convSigmetSection_parentid_idex") - private Set convSigmetSection = new HashSet(); + private Set convSigmetSection = new HashSet(); - - /** + /** * Default Convstructor */ public ConvSigmetRecord() { - this.issueOffice=""; - this.wmoHeader=""; - this.bullMessage=""; - this.designatorBBB=""; - this.forecastRegion=""; - this.reportType=""; - this.correctionFlag=IDecoderConstantsN.INTEGER_MISSING; + this.issueOffice = ""; + this.wmoHeader = ""; + this.bullMessage = ""; + this.designatorBBB = ""; + this.forecastRegion = ""; + this.reportType = ""; + this.correctionFlag = IDecoderConstantsN.INTEGER_MISSING; } /** * Convstructs a consigmet record from a dataURI * - * @param uri The dataURI + * @param uri + * The dataURI */ public ConvSigmetRecord(String uri) { super(uri); } - @Override public IDecoderGettable getDecoderGettable() { // TODO Auto-generated method stub @@ -154,151 +148,159 @@ public class ConvSigmetRecord extends PluginDataObject{ } /** - * @return the issueOffice - */ - public String getIssueOffice(){ - return issueOffice; - } + * @return the issueOffice + */ + public String getIssueOffice() { + return issueOffice; + } - /** - * @param issueOffice to set - */ - public void setIssueOffice(String issueOffice){ - this.issueOffice=issueOffice; - } - - /** - * @return the wmoHeader - */ - public String getWmoHeader(){ - return wmoHeader; - } + /** + * @param issueOffice + * to set + */ + public void setIssueOffice(String issueOffice) { + this.issueOffice = issueOffice; + } - /** - * @param wnoHeader to set - */ - public void setWmoHeader(String wmoHeader){ - this.wmoHeader=wmoHeader; - } - - /** - * @return the issueTime - */ - public Calendar getIssueTime(){ - return issueTime; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param issueTime to set - */ - public void setIssueTime(Calendar issueTime){ - this.issueTime=issueTime; - } - - /** - * @return the reportType - */ - public String getReportType() { - return reportType; - } + /** + * @param wnoHeader + * to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * @param reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } + /** + * @return the issueTime + */ + public Calendar getIssueTime() { + return issueTime; + } - /** - * @return the designatorBBB - */ - public String getDesignatorBBB() { - return designatorBBB; - } + /** + * @param issueTime + * to set + */ + public void setIssueTime(Calendar issueTime) { + this.issueTime = issueTime; + } - /** - * @param designatorBBB to set - */ - public void setDesignatorBBB(String designatorBBB) { - this.designatorBBB = designatorBBB; - } + /** + * @return the reportType + */ + public String getReportType() { + return reportType; + } - /** - * @return the correctionFlag - */ - public Integer getCorrectionFlag() { - return correctionFlag; - } + /** + * @param reportType + * to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } - /** - * @param correctionFlag to set - */ - public void setCorrectionFlag(Integer correctionFlag) { - this.correctionFlag = correctionFlag; - } + /** + * @return the designatorBBB + */ + public String getDesignatorBBB() { + return designatorBBB; + } - /** - * @return the forecastRegion - */ - public String getForecastRegion() { - return forecastRegion; - } + /** + * @param designatorBBB + * to set + */ + public void setDesignatorBBB(String designatorBBB) { + this.designatorBBB = designatorBBB; + } - /** - * @param forecastRegion to set - */ - public void setForecastRegion(String forecastRegion) { - this.forecastRegion = forecastRegion; - } - - /** - * @return the bullMessage - */ - public String getBullMessage() { - return bullMessage; - } + /** + * @return the correctionFlag + */ + public Integer getCorrectionFlag() { + return correctionFlag; + } - /** - * @param bullMessage to set - */ - public void setBullMessage(String bullMessage) { - this.bullMessage = bullMessage; - } - - - /** - * @return the set of convective Sigmet section - */ - public Set getConvSigmetSection() { - return convSigmetSection; - } + /** + * @param correctionFlag + * to set + */ + public void setCorrectionFlag(Integer correctionFlag) { + this.correctionFlag = correctionFlag; + } - /** - * @param convsigmet the section to set - */ - public void setConvSigmetSection(Set convSection) { - this.convSigmetSection = convSection; - } + /** + * @return the forecastRegion + */ + public String getForecastRegion() { + return forecastRegion; + } - /** - * @param add convective Sigmet Section to set - */ - public void addConvSigmetSection(ConvSigmetSection psection){ - convSigmetSection.add(psection); - - } - - /** - * Override existing set method to modify any - * classes that use the dataURI as a foreign key - */ - @Override - public void setIdentifier(Object dataURI) - { + /** + * @param forecastRegion + * to set + */ + public void setForecastRegion(String forecastRegion) { + this.forecastRegion = forecastRegion; + } - this.identifier = dataURI; - - } + /** + * @return the bullMessage + */ + public String getBullMessage() { + return bullMessage; + } + + /** + * @param bullMessage + * to set + */ + public void setBullMessage(String bullMessage) { + this.bullMessage = bullMessage; + } + + /** + * @return the set of convective Sigmet section + */ + public Set getConvSigmetSection() { + return convSigmetSection; + } + + /** + * @param convsigmet + * the section to set + */ + public void setConvSigmetSection(Set convSection) { + this.convSigmetSection = convSection; + } + + /** + * @param add + * convective Sigmet Section to set + */ + public void addConvSigmetSection(ConvSigmetSection psection) { + convSigmetSection.add(psection); + + } + + /** + * Override existing set method to modify any classes that use the dataURI + * as a foreign key + */ + @Override + public void setIdentifier(Object dataURI) { + + this.identifier = dataURI; + + } @Override @Column @@ -306,4 +308,9 @@ public class ConvSigmetRecord extends PluginDataObject{ public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "convsigmet"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ffg/src/gov/noaa/nws/ncep/common/dataplugin/ffg/FfgRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ffg/src/gov/noaa/nws/ncep/common/dataplugin/ffg/FfgRecord.java index f956a86c9e..bf9c24bf61 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ffg/src/gov/noaa/nws/ncep/common/dataplugin/ffg/FfgRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ffg/src/gov/noaa/nws/ncep/common/dataplugin/ffg/FfgRecord.java @@ -7,18 +7,21 @@ *
  * SOFTWARE HISTORY
  *
- * Date         Ticket#         Engineer    Description
- * ------------ ----------      ----------- --------------------------
- * 08/2008      14				T. Lee     	Initial coding
- * 12/2008		14				T. Lee		Initialized variable
- * 03/2009		14				T. Lee		Migration to TO10
- * 07/2009		14				T. Lee		Migration to TO11
- * 09/2011      				Chin Chen   changed to improve purge performance and
- * 										    removed xml serialization as well
- * Apr 4, 2013        1846 bkowal      Added an index on refTime and forecastTime
- * Apr 12, 2013 1857            bgonzale    Added SequenceGenerator annotation.
- * May 07, 2013 1869            bsteffen    Remove dataURI column from
- *                                          PluginDataObject.
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * 08/2008      14         T. Lee      Initial coding
+ * 12/2008      14         T. Lee      Initialized variable
+ * 03/2009      14         T. Lee      Migration to TO10
+ * 07/2009      14         T. Lee      Migration to TO11
+ * 09/2011                 Chin Chen   changed to improve purge performance
+ *                                     and  removed xml serialization as
+ *                                     well
+ * Apr 04, 2013 1846       bkowal      Added an index on refTime and
+ *                                     forecastTime
+ * Apr 12, 2013 1857       bgonzale    Added SequenceGenerator annotation.
+ * May 07, 2013 1869       bsteffen    Remove dataURI column from
+ *                                     PluginDataObject.
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
  *
  * 
* @@ -59,240 +62,246 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ffg", - indexes = { - @Index(name = "ffg_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ffg", indexes = { @Index(name = "ffg_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class FfgRecord extends PluginDataObject { private static final long serialVersionUID = 1L; - + /** Report type */ - @Column(length=32) - @DynamicSerializeElement - @DataURI(position=2) + @Column(length = 32) + @DynamicSerializeElement + @DataURI(position = 2) private String reportType; /** FFG AWIPS identifier */ - @Column(length=32) - @DataURI(position=1) + @Column(length = 32) + @DataURI(position = 1) @DynamicSerializeElement private String awipsID; - + /** Bulletin insurance time */ - @Column + @Column @DynamicSerializeElement private Calendar issueTime; /** Station ID */ - @Column(length=32) + @Column(length = 32) @DynamicSerializeElement private String issueOffice; /** Designator BBB */ - @Column(length=8) + @Column(length = 8) @DynamicSerializeElement private String designatorBBB; /** Bulletin messages */ - @Column(length=10000) + @Column(length = 10000) @DynamicSerializeElement private String bullMessage; - + /** Mass News Disseminator (MND) */ - @Column(length=72) + @Column(length = 72) @DynamicSerializeElement private String mndTime; /** WMO header */ - @Column(length=32) + @Column(length = 32) @DynamicSerializeElement private String wmoHeader; - + /** FFG precipitation */ - @DynamicSerializeElement + @DynamicSerializeElement @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinColumn(name = "parentID", nullable = false) + @JoinColumn(name = "parentID", nullable = false) @Index(name = "ffgP_parentid_idex") - private Set ffgP = new HashSet(); - + private Set ffgP = new HashSet(); + /** * Default Constructor */ public FfgRecord() { - awipsID = ""; - issueTime = null; - issueOffice = ""; - wmoHeader = ""; - mndTime = ""; - bullMessage = ""; + awipsID = ""; + issueTime = null; + issueOffice = ""; + wmoHeader = ""; + mndTime = ""; + bullMessage = ""; } /** * Constructs a FFG record from a dataURI * - * @param uri: The dataURI + * @param uri + * : The dataURI */ public FfgRecord(String uri) { - super(uri); + super(uri); } - + @Override public IDecoderGettable getDecoderGettable() { - // TODO Auto-generated method stub - return null; + // TODO Auto-generated method stub + return null; } - - /** - * Return the reportType + + /** + * Return the reportType */ public String getReportType() { return reportType; } /** - * @param reportType the report type to set + * @param reportType + * the report type to set */ public void setReportType(String reportType) { this.reportType = reportType; } - + /** * @return the awipsID */ public String getAwipsID() { - return awipsID; + return awipsID; } /** - * @param awipsID the AWIPS identifier to set + * @param awipsID + * the AWIPS identifier to set */ public void setAwipsID(String awipsID) { - this.awipsID = awipsID; + this.awipsID = awipsID; } /** * @return the issueTime */ public Calendar getIssueTime() { - return issueTime; + return issueTime; } /** - * @param issueTime the issueTime to set + * @param issueTime + * the issueTime to set */ public void setIssueTime(Calendar issueTime) { - this.issueTime = issueTime; + this.issueTime = issueTime; } /** * @return the issueOffice */ public String getIssueOffice() { - return issueOffice; + return issueOffice; } /** - * @param issueOffice the issueOffice to set + * @param issueOffice + * the issueOffice to set */ public void setIssueOffice(String issueOffice) { - this.issueOffice = issueOffice; + this.issueOffice = issueOffice; } /** * @return the wmoHeader */ public String getWmoHeader() { - return wmoHeader; + return wmoHeader; } /** - * @param wmoHeader the wmoHeader to set + * @param wmoHeader + * the wmoHeader to set */ public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; + this.wmoHeader = wmoHeader; } /** * @return designatorBBB */ public String getDesignatorBBB() { - return designatorBBB; + return designatorBBB; } /** - * @param designatorBBB the designatorBBB to set + * @param designatorBBB + * the designatorBBB to set */ public void setDesignatorBBB(String designatorBBB) { - this.designatorBBB = designatorBBB; + this.designatorBBB = designatorBBB; } - + /** * @return the bullMessage */ public String getBullMessage() { - return bullMessage; - } - + return bullMessage; + } + /** - * @param bullMessage the bullMessage to set + * @param bullMessage + * the bullMessage to set */ public void setBullMessage(String bullMessage) { - this.bullMessage = bullMessage; + this.bullMessage = bullMessage; } - + /** * @return the MndTime */ public String getMndTime() { - return mndTime; + return mndTime; } /** - * @param mndTime the mndTime to set + * @param mndTime + * the mndTime to set */ public void setMndTime(String mndTime) { - this.mndTime = mndTime; + this.mndTime = mndTime; } - + /** * @return the set of precipitation (ffgP) */ public Set getFfgP() { - return ffgP; + return ffgP; } /** - * @param ffgP the set of precipitation to set + * @param ffgP + * the set of precipitation to set */ - public void setFfgP(Set ffgP ) { - this.ffgP = ffgP; + public void setFfgP(Set ffgP) { + this.ffgP = ffgP; } /** * Add FfgPrecip to set */ - public void addPrecip(FfgPrecip precip){ - ffgP.add(precip); - //precip.setParentID (this); - } + public void addPrecip(FfgPrecip precip) { + ffgP.add(precip); + // precip.setParentID (this); + } /** - * Override existing set method to modify any - * classes that use the dataURI as a foreign key + * Override existing set method to modify any classes that use the dataURI + * as a foreign key */ @Override public void setIdentifier(Object dataURI) { - - this.identifier = dataURI; - /*if (this.getFfgP() != null && this.getFfgP().size() > 0) { - for (Iterator iter = this.getFfgP().iterator(); iter.hasNext();) { - FfgPrecip fp = iter.next(); - //fp.setParentID(this); - } - }*/ + + this.identifier = dataURI; + /* + * if (this.getFfgP() != null && this.getFfgP().size() > 0) { for + * (Iterator iter = this.getFfgP().iterator(); + * iter.hasNext();) { FfgPrecip fp = iter.next(); + * //fp.setParentID(this); } } + */ } @Override @@ -301,4 +310,9 @@ public class FfgRecord extends PluginDataObject { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ffg"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.geomag/src/gov/noaa/nws/ncep/common/dataplugin/geomag/GeoMagRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.geomag/src/gov/noaa/nws/ncep/common/dataplugin/geomag/GeoMagRecord.java index e46fdaeb7a..f8b55fb5ea 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.geomag/src/gov/noaa/nws/ncep/common/dataplugin/geomag/GeoMagRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.geomag/src/gov/noaa/nws/ncep/common/dataplugin/geomag/GeoMagRecord.java @@ -28,9 +28,12 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ---------------- -------------------------- - * 03/27/2013 975 sgurung Initial creation. - * 05/26/2013 bhebbard Added SequenceGenerator annotation. - * 06/26/2013 989 qzhou Added lots of fields. + * Mar 27, 2013 975 sgurung Initial creation. + * May 26, 2013 bhebbard Added SequenceGenerator + * annotation. + * Jun 26, 2013 989 qzhou Added lots of fields. + * Jul 22, 2013 1977 rjpeter Added getDataURI and annotations. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author sgurung @@ -757,4 +760,9 @@ public class GeoMagRecord extends PersistablePluginDataObject { public IHDFFilePathProvider getHDFPathProvider() { return GeoMagPathProvider.getInstance(); } + + @Override + public String getPluginName() { + return "geomag"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.gpd/src/gov/noaa/nws/ncep/common/dataplugin/gpd/GenericPointDataRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.gpd/src/gov/noaa/nws/ncep/common/dataplugin/gpd/GenericPointDataRecord.java index 04fa3abd8f..9c8b4bd96e 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.gpd/src/gov/noaa/nws/ncep/common/dataplugin/gpd/GenericPointDataRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.gpd/src/gov/noaa/nws/ncep/common/dataplugin/gpd/GenericPointDataRecord.java @@ -49,264 +49,259 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.time.DataTime; @Entity -//@Table(name = "gpd", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) +// @Table(name = "gpd", uniqueConstraints = { @UniqueConstraint(columnNames = { +// "dataURI" }) }) @SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "gpdseq") @Table(name = "gpd") @DynamicSerialize @XmlAccessorType(XmlAccessType.NONE) @XmlRootElement -public class GenericPointDataRecord extends PersistablePluginDataObject implements -/*ISpatialEnabled,*/ IDecoderGettable, IPointData, IPersistable { +public class GenericPointDataRecord extends PersistablePluginDataObject + implements + /* ISpatialEnabled, */IDecoderGettable, IPointData, IPersistable { - private static final long serialVersionUID = 1L; - @ManyToOne - @PrimaryKeyJoinColumn - //@DataURI(position = 1, embedded = true) - @DynamicSerializeElement - @XmlElement - private GenericPointDataProductInfo productInfo; + private static final long serialVersionUID = 1L; - @ManyToOne + @ManyToOne + @PrimaryKeyJoinColumn + // @DataURI(position = 1, embedded = true) + @DynamicSerializeElement + @XmlElement + private GenericPointDataProductInfo productInfo; + + @ManyToOne @PrimaryKeyJoinColumn @DynamicSerializeElement @XmlElement - private ObStation location; - - @Column - @DynamicSerializeElement - @XmlAttribute - private float slat; + private ObStation location; - @Column - @DynamicSerializeElement - @XmlAttribute - private float slon; + @Column + @DynamicSerializeElement + @XmlAttribute + private float slat; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - /* TBM - chin...delete these later..not used? - @Column - @DynamicSerializeElement - @XmlAttribute - private int numLevel; - */ - - @Column - @DynamicSerializeElement - @XmlAttribute - //@DataURI(position = 2) - //product release version for product correction used only. - private int productVersion=0; - - - //list of master level values - @Transient - @XmlElement - private List levelValueLst = new ArrayList(); - - //one level of parameters value map. Key (String) = parameter name, value (double) = parameter value - //@Transient - //private HashMap Map_ParmToValue = new HashMap(); - - //Map of all levels of parameters value maps. Key (integer) = level value in levelValueLst, value = - // one level of parameter values = a Map_ParmToValue map). - //@Transient - //private HashMap> Map_LevelToParmValueMap = new HashMap >(); - - public GenericPointDataRecord() { - super(); - //System.out.println("GenericPointDataRecord() entered"); - - } + @Column + @DynamicSerializeElement + @XmlAttribute + private float slon; - public GenericPointDataRecord(String uri) { - super(uri); - //System.out.println("GenericPointDataRecord(String uri) entered"); - } + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - public GenericPointDataRecord(String uri, GenericPointDataProductInfo productInfo, - ObStation location, - float slat, float slon, PointDataView pointDataView) { - super(uri); - this.productInfo = productInfo; - this.location = location; - this.slat = slat; - this.slon = slon; - this.pointDataView = pointDataView; - this.pluginName ="gpd"; - //System.out.println("GenericPointDataRecord(3) entered"); - } - public GenericPointDataRecord(GenericPointDataProductInfo productInfo, - ObStation location, - float slat, float slon, PointDataView pointDataView, DataTime dataTime, - int productVersion) { - this.productInfo = productInfo; - this.location = location; - this.slat = slat; - this.slon = slon; - this.pointDataView = pointDataView; - this.dataTime = dataTime; - this.productVersion = productVersion; - this.pluginName ="gpd"; - //System.out.println("GenericPointDataRecord(4) entered"); - } - - /* TBM - chin...delete it later..not used? - public void constructTransientListAndMap(GenericPointDataStationProduct stnPd){ - setNumLevel(stnPd.getNumLevel()); - for(int i=0; i levelValueLst = new ArrayList(); - public void setProductInfo(GenericPointDataProductInfo productInfo) { - this.productInfo = productInfo; - } + // one level of parameters value map. Key (String) = parameter name, value + // (double) = parameter value + // @Transient + // private HashMap Map_ParmToValue = new HashMap(); - public float getSlat() { - return slat; - } + // Map of all levels of parameters value maps. Key (integer) = level value + // in levelValueLst, value = + // one level of parameter values = a Map_ParmToValue map). + // @Transient + // private HashMap> Map_LevelToParmValueMap = + // new HashMap >(); - public void setSlat(float slat) { - this.slat = slat; - } + public GenericPointDataRecord() { + super(); + // System.out.println("GenericPointDataRecord() entered"); - public float getSlon() { - return slon; - } + } - public void setSlon(float slon) { - this.slon = slon; - } + public GenericPointDataRecord(String uri) { + super(uri); + // System.out.println("GenericPointDataRecord(String uri) entered"); + } - @Override - public IDecoderGettable getDecoderGettable() { - // TODO Auto-generated method stub - return null; - } + public GenericPointDataRecord(String uri, + GenericPointDataProductInfo productInfo, ObStation location, + float slat, float slon, PointDataView pointDataView) { + super(uri); + this.productInfo = productInfo; + this.location = location; + this.slat = slat; + this.slon = slon; + this.pointDataView = pointDataView; + // System.out.println("GenericPointDataRecord(3) entered"); + } - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } + public GenericPointDataRecord(GenericPointDataProductInfo productInfo, + ObStation location, float slat, float slon, + PointDataView pointDataView, DataTime dataTime, int productVersion) { + this.productInfo = productInfo; + this.location = location; + this.slat = slat; + this.slon = slon; + this.pointDataView = pointDataView; + this.dataTime = dataTime; + this.productVersion = productVersion; + // System.out.println("GenericPointDataRecord(4) entered"); + } - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + /* + * TBM - chin...delete it later..not used? public void + * constructTransientListAndMap(GenericPointDataStationProduct stnPd){ + * setNumLevel(stnPd.getNumLevel()); for(int i=0; i getValues(String paramName) { - // TODO Auto-generated method stub - return null; - } + public void setProductInfo(GenericPointDataProductInfo productInfo) { + this.productInfo = productInfo; + } - @Override - public String getString(String paramName) { - // TODO Auto-generated method stub - return null; - } + public float getSlat() { + return slat; + } - @Override - public String[] getStrings(String paramName) { - // TODO Auto-generated method stub - return null; - } + public void setSlat(float slat) { + this.slat = slat; + } - - /*TBM - chin...delete these later..not used? - @Override - public void constructDataURI() throws PluginException { - // TODO Auto-generated method stub - super.constructDataURI(); - // ObStation class does not define dataUri component. Therefore, - // add stationId/longitude/latitude here to end of dataUri - if(this.location!=null){ - if(this.location.getStationId()!=null){ - this.dataURI = this.dataURI+DataURI.SEPARATOR+this.location.getStationId(); - } - else { - this.dataURI = this.dataURI+DataURI.SEPARATOR+"null"; - } - if(this.location.getStationGeom()!=null){ - this.dataURI = this.dataURI+DataURI.SEPARATOR+ - this.location.getStationGeom().getX()+ DataURI.SEPARATOR+ - this.location.getStationGeom().getY(); - } - else { - this.dataURI = this.dataURI+DataURI.SEPARATOR+"null"+DataURI.SEPARATOR+"null"; - } - } - }*/ + public float getSlon() { + return slon; + } - public ObStation getLocation() { - return location; - } + public void setSlon(float slon) { + this.slon = slon; + } - public void setLocation(ObStation location) { - this.location = location; - } + @Override + public IDecoderGettable getDecoderGettable() { + // TODO Auto-generated method stub + return null; + } - /* TBM - chin...delete these later..not used? - public int getNumLevel() { - return numLevel; - } + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } - public void setNumLevel(int numLevel) { - this.numLevel = numLevel; - } */ + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - public List getLevelValueLst() { - return levelValueLst; - } + @Override + public Amount getValue(String paramName) { + // TODO Auto-generated method stub + return null; + } - public void setLevelValueLst(List levelValueLst) { - this.levelValueLst = levelValueLst; - } + @Override + public Collection getValues(String paramName) { + // TODO Auto-generated method stub + return null; + } - /* TBM - chin...delete these later..not used? - public HashMap getMap_ParmToValue() { - return Map_ParmToValue; - } + @Override + public String getString(String paramName) { + // TODO Auto-generated method stub + return null; + } - public void setMap_ParmToValue(HashMap map_ParmToValue) { - Map_ParmToValue = map_ParmToValue; - } + @Override + public String[] getStrings(String paramName) { + // TODO Auto-generated method stub + return null; + } - public HashMap> getMap_LevelToParmValueMap() { - return Map_LevelToParmValueMap; - } + /* + * TBM - chin...delete these later..not used? + * + * @Override public void constructDataURI() throws PluginException { // TODO + * Auto-generated method stub super.constructDataURI(); // ObStation class + * does not define dataUri component. Therefore, // add + * stationId/longitude/latitude here to end of dataUri + * if(this.location!=null){ if(this.location.getStationId()!=null){ + * this.dataURI = + * this.dataURI+DataURI.SEPARATOR+this.location.getStationId(); } else { + * this.dataURI = this.dataURI+DataURI.SEPARATOR+"null"; } + * if(this.location.getStationGeom()!=null){ this.dataURI = + * this.dataURI+DataURI.SEPARATOR+ this.location.getStationGeom().getX()+ + * DataURI.SEPARATOR+ this.location.getStationGeom().getY(); } else { + * this.dataURI = + * this.dataURI+DataURI.SEPARATOR+"null"+DataURI.SEPARATOR+"null"; } } } + */ - public void setMap_LevelToParmValueMap( - HashMap> map_LevelToParmValueMap) { - Map_LevelToParmValueMap = map_LevelToParmValueMap; - }*/ + public ObStation getLocation() { + return location; + } - public int getProductVersion() { - return productVersion; - } + public void setLocation(ObStation location) { + this.location = location; + } - public void setProductVersion(int productVersion) { - this.productVersion = productVersion; - } + /* + * TBM - chin...delete these later..not used? public int getNumLevel() { + * return numLevel; } + * + * public void setNumLevel(int numLevel) { this.numLevel = numLevel; } + */ + public List getLevelValueLst() { + return levelValueLst; + } + + public void setLevelValueLst(List levelValueLst) { + this.levelValueLst = levelValueLst; + } + + /* + * TBM - chin...delete these later..not used? public HashMap + * getMap_ParmToValue() { return Map_ParmToValue; } + * + * public void setMap_ParmToValue(HashMap map_ParmToValue) { + * Map_ParmToValue = map_ParmToValue; } + * + * public HashMap> + * getMap_LevelToParmValueMap() { return Map_LevelToParmValueMap; } + * + * public void setMap_LevelToParmValueMap( HashMap> map_LevelToParmValueMap) { Map_LevelToParmValueMap = + * map_LevelToParmValueMap; } + */ + + public int getProductVersion() { + return productVersion; + } + + public void setProductVersion(int productVersion) { + this.productVersion = productVersion; + } + + @Override + public String getPluginName() { + return "gpd"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.idft/src/gov/noaa/nws/ncep/common/dataplugin/idft/IdftRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.idft/src/gov/noaa/nws/ncep/common/dataplugin/idft/IdftRecord.java index 6a98caea32..bf9462fd61 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.idft/src/gov/noaa/nws/ncep/common/dataplugin/idft/IdftRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.idft/src/gov/noaa/nws/ncep/common/dataplugin/idft/IdftRecord.java @@ -1,30 +1,3 @@ -/** - * - * IdftRecord.java - * - * This java class performs the mapping to the database tables for the Ice Drift - * (IDFT) Decoder Plug-In. - * - *
- * 
- * SOFTWARE HISTORY
- * Date			Ticket#		Engineer		Description
- * ------------	----------- --------------	-----------------------------------
- * 05/21/09		   100		F. J. Yen		Initial creation
- * 12/08/09		   100		F. J. Yen		Modified for to11d6 from to11d3
- * 05/27/10		   100		F. J. Yen		Refactored from to11dr3 for tolldr11
- * Apr 4, 2013        1846 bkowal      Added an index on refTime and forecastTime
- * Apr 12, 2013    1857     bgonzale        Added SequenceGenerator annotation.
- * 03/07/13        982      Archana         Updated getPointNum() to return an Integer
- * 
- * *
- * This code has been developed by the SIB for use in the AWIPS2 system.
- * 
- * - * @author F. J. Yen, SIB - * @version 1 - */ - package gov.noaa.nws.ncep.common.dataplugin.idft; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; @@ -52,19 +25,29 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; /** + * This java class performs the mapping to the database tables for the Ice Drift + * (IDFT) Decoder Plug-In. * - * + * This code has been developed by the SIB for use in the AWIPS2 system. + * *
  * 
  * SOFTWARE HISTORY
  * 
  * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * 07/22/2013   1977       rjpeter     Added getDataURI and annotations.
- * 
+ * ------------ --------- ----------- --------------------------
+ * May 21, 2009 100       F. J. Yen   Initial creation
+ * Dec 08, 2009 100       F. J. Yen   Modified for to11d6 from to11d3
+ * May 27, 2010 100       F. J. Yen   Refactored from to11dr3 for tolldr11
+ * Apr 04, 2013 1846      bkowal      Added an index on refTime and forecastTime
+ * Apr 12, 2013 1857      bgonzale    Added SequenceGenerator annotation.
+ * Mar 07, 2013 982       Archana     Updated getPointNum() to return an Integer
+ * Jul 22, 2013 1977      rjpeter     Added getDataURI and annotations.
+ * Aug 30, 2013 2298      rjpeter     Make getPluginName abstract
  * 
+ * * - * @author rjpeter + * @author F. J. Yen, SIB * @version 1.0 */ @Entity @@ -222,4 +205,9 @@ public class IdftRecord extends PluginDataObject { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "idft"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.intlsigmet/src/gov/noaa/nws/ncep/common/dataplugin/intlsigmet/IntlSigmetRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.intlsigmet/src/gov/noaa/nws/ncep/common/dataplugin/intlsigmet/IntlSigmetRecord.java index 4c622b792b..60b09f4e49 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.intlsigmet/src/gov/noaa/nws/ncep/common/dataplugin/intlsigmet/IntlSigmetRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.intlsigmet/src/gov/noaa/nws/ncep/common/dataplugin/intlsigmet/IntlSigmetRecord.java @@ -58,183 +58,174 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "intlsigmet", - indexes = { - @Index(name = "intlsigmet_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "intlsigmet", indexes = { @Index(name = "intlsigmet_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize +public class IntlSigmetRecord extends PluginDataObject { - -public class IntlSigmetRecord extends PluginDataObject{ - - /** + /** * */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - // reportType is "international sigmet". - @Column(length=32) - @DataURI(position=1) - @DynamicSerializeElement - private String reportType; - - // hazardType is weather phenomena. - @Column(length=48) - @DataURI(position=2) - @DynamicSerializeElement - private String hazardType; - - // WMO header - @Column(length=32) - @DynamicSerializeElement - private String wmoHeader; - - // The issue office where the report from - @Column(length=32) - @DynamicSerializeElement - private String issueOffice; - - // Issue time of the report - @Column - @DynamicSerializeElement - private Calendar issueTime; - - // Start time of the report - @Column - @DynamicSerializeElement - private Calendar startTime; - - // End time of the report - @Column - @DynamicSerializeElement - private Calendar endTime; - - // The message ID - @Column(length=16) - @DataURI(position=3) - @DynamicSerializeElement - private String messageID; - - // The sequence number - @Column(length=8) - @DataURI(position=4) - @DynamicSerializeElement - private String sequenceNumber; - - // The air traffic services unit - @Column(length=16) - @DynamicSerializeElement - private String atsu; - - // The location indicator of the meteorological watch office originator - @Column(length=16) - @DynamicSerializeElement - private String omwo; - - // Flight level 1 - @Column - @DynamicSerializeElement - private Integer flightlevel1; - - // Flight level 2 - @Column - @DynamicSerializeElement - private Integer flightlevel2; - - // Distance - @Column - @DynamicSerializeElement - private Integer distance; - - // Direction - @Column(length=16) - @DynamicSerializeElement - private String direction; - - // Speed - @Column - @DynamicSerializeElement - private Integer speed; - - /* - * the name of the storm, where applicable, or location of the - * volcano, where applicable, or the word, OTHER, for reports - * not from CONUS, Hawaii, Guam, Japan, UK, Tahiti, and Cuba - - */ - @Column(length=48) - @DynamicSerializeElement - private String nameLocation; - - /* - * remarks such as: correction, remarks, ...etc. - */ - @Column(length=32) + // reportType is "international sigmet". + @Column(length = 32) + @DataURI(position = 1) @DynamicSerializeElement - private String remarks; - - // The changes in intensity; using as "INTSF", "WKN", or "NC". - @Column(length=16) - @DynamicSerializeElement - private String intensity; - - // The polygon indicator as "WI", "WTN", "EITHER SIDE", or "E OF". - @Column(length=16) - @DynamicSerializeElement - private String polygonExtent; - - // The entire report - @Column(length=5000) - @DynamicSerializeElement - private String bullMessage; + private String reportType; + // hazardType is weather phenomena. + @Column(length = 48) + @DataURI(position = 2) + @DynamicSerializeElement + private String hazardType; - /** - * Intlsigmet location - */ - @DynamicSerializeElement - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinColumn(name = "parentID", nullable = false) + // WMO header + @Column(length = 32) + @DynamicSerializeElement + private String wmoHeader; + + // The issue office where the report from + @Column(length = 32) + @DynamicSerializeElement + private String issueOffice; + + // Issue time of the report + @Column + @DynamicSerializeElement + private Calendar issueTime; + + // Start time of the report + @Column + @DynamicSerializeElement + private Calendar startTime; + + // End time of the report + @Column + @DynamicSerializeElement + private Calendar endTime; + + // The message ID + @Column(length = 16) + @DataURI(position = 3) + @DynamicSerializeElement + private String messageID; + + // The sequence number + @Column(length = 8) + @DataURI(position = 4) + @DynamicSerializeElement + private String sequenceNumber; + + // The air traffic services unit + @Column(length = 16) + @DynamicSerializeElement + private String atsu; + + // The location indicator of the meteorological watch office originator + @Column(length = 16) + @DynamicSerializeElement + private String omwo; + + // Flight level 1 + @Column + @DynamicSerializeElement + private Integer flightlevel1; + + // Flight level 2 + @Column + @DynamicSerializeElement + private Integer flightlevel2; + + // Distance + @Column + @DynamicSerializeElement + private Integer distance; + + // Direction + @Column(length = 16) + @DynamicSerializeElement + private String direction; + + // Speed + @Column + @DynamicSerializeElement + private Integer speed; + + /* + * the name of the storm, where applicable, or location of the volcano, + * where applicable, or the word, OTHER, for reports not from CONUS, Hawaii, + * Guam, Japan, UK, Tahiti, and Cuba + */ + @Column(length = 48) + @DynamicSerializeElement + private String nameLocation; + + /* + * remarks such as: correction, remarks, ...etc. + */ + @Column(length = 32) + @DynamicSerializeElement + private String remarks; + + // The changes in intensity; using as "INTSF", "WKN", or "NC". + @Column(length = 16) + @DynamicSerializeElement + private String intensity; + + // The polygon indicator as "WI", "WTN", "EITHER SIDE", or "E OF". + @Column(length = 16) + @DynamicSerializeElement + private String polygonExtent; + + // The entire report + @Column(length = 5000) + @DynamicSerializeElement + private String bullMessage; + + /** + * Intlsigmet location + */ + @DynamicSerializeElement + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "parentID", nullable = false) @Index(name = "intlSigmetLocation_parentid_idex") - private Set intlSigmetLocation = new HashSet(); + private Set intlSigmetLocation = new HashSet(); - - /** + /** * Default Convstructor */ public IntlSigmetRecord() { - this.issueOffice=null; - this.wmoHeader=null; - this.bullMessage=null; - this.hazardType=null; - this.messageID=null; - this.reportType="INTLSIGMET"; - this.sequenceNumber=null; - this.atsu=null; - this.omwo=null; - this.nameLocation=null; - this.intensity=null; - this.remarks=null; - this.flightlevel1=IDecoderConstantsN.INTEGER_MISSING; - this.flightlevel2=IDecoderConstantsN.INTEGER_MISSING; - this.direction=null; - this.distance=IDecoderConstantsN.INTEGER_MISSING; - this.speed=IDecoderConstantsN.INTEGER_MISSING; - this.polygonExtent=null; + this.issueOffice = null; + this.wmoHeader = null; + this.bullMessage = null; + this.hazardType = null; + this.messageID = null; + this.reportType = "INTLSIGMET"; + this.sequenceNumber = null; + this.atsu = null; + this.omwo = null; + this.nameLocation = null; + this.intensity = null; + this.remarks = null; + this.flightlevel1 = IDecoderConstantsN.INTEGER_MISSING; + this.flightlevel2 = IDecoderConstantsN.INTEGER_MISSING; + this.direction = null; + this.distance = IDecoderConstantsN.INTEGER_MISSING; + this.speed = IDecoderConstantsN.INTEGER_MISSING; + this.polygonExtent = null; } /** * Convstructs a consigmet record from a dataURI * - * @param uri The dataURI + * @param uri + * The dataURI */ public IntlSigmetRecord(String uri) { super(uri); } - @Override public IDecoderGettable getDecoderGettable() { // TODO Auto-generated method stub @@ -242,338 +233,356 @@ public class IntlSigmetRecord extends PluginDataObject{ } /** - * @return the issueOffice - */ - public String getIssueOffice(){ - return issueOffice; - } + * @return the issueOffice + */ + public String getIssueOffice() { + return issueOffice; + } - /** - * @param issueOffice to set - */ - public void setIssueOffice(String issueOffice){ - this.issueOffice=issueOffice; - } - - /** - * @return the wmoHeader - */ - public String getWmoHeader(){ - return wmoHeader; - } + /** + * @param issueOffice + * to set + */ + public void setIssueOffice(String issueOffice) { + this.issueOffice = issueOffice; + } - /** - * @param wnoHeader to set - */ - public void setWmoHeader(String wmoHeader){ - this.wmoHeader=wmoHeader; - } - - /** - * @return the issueTime - */ - public Calendar getIssueTime(){ - return issueTime; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param issueTime to set - */ - public void setIssueTime(Calendar issueTime){ - this.issueTime=issueTime; - } - - /** - * @return the reportType - */ - public String getReportType() { - return reportType; - } + /** + * @param wnoHeader + * to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * @param reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } + /** + * @return the issueTime + */ + public Calendar getIssueTime() { + return issueTime; + } - /** - * @return the bullMessage - */ - public String getBullMessage() { - return bullMessage; - } + /** + * @param issueTime + * to set + */ + public void setIssueTime(Calendar issueTime) { + this.issueTime = issueTime; + } - /** - * @param bullMessage to set - */ - public void setBullMessage(String bullMessage) { - this.bullMessage = bullMessage; - } + /** + * @return the reportType + */ + public String getReportType() { + return reportType; + } - /** - * @return the set of hazard - */ - public String getHazardType() { - return hazardType; - } + /** + * @param reportType + * to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } - /** - * @param hazardType to set - */ - public void setHazardType(String hazardType) { - this.hazardType = hazardType; - } + /** + * @return the bullMessage + */ + public String getBullMessage() { + return bullMessage; + } - /** - * @return the startTime - */ - public Calendar getStartTime() { - return startTime; - } + /** + * @param bullMessage + * to set + */ + public void setBullMessage(String bullMessage) { + this.bullMessage = bullMessage; + } - /** - * @param startTime to set - */ - public void setStartTime(Calendar startTime) { - this.startTime = startTime; - } + /** + * @return the set of hazard + */ + public String getHazardType() { + return hazardType; + } - /** - * @return the endTime - */ - public Calendar getEndTime() { - return endTime; - } + /** + * @param hazardType + * to set + */ + public void setHazardType(String hazardType) { + this.hazardType = hazardType; + } - /** - * @param endTime to set - */ - public void setEndTime(Calendar endTime) { - this.endTime = endTime; - } + /** + * @return the startTime + */ + public Calendar getStartTime() { + return startTime; + } - public String getMessageID() { - return messageID; - } + /** + * @param startTime + * to set + */ + public void setStartTime(Calendar startTime) { + this.startTime = startTime; + } - /** - * @param messageID to set - */ - public void setMessageID(String messageID) { - this.messageID = messageID; - } + /** + * @return the endTime + */ + public Calendar getEndTime() { + return endTime; + } - /** - * @return the sequenceNumber - */ - public String getSequenceNumber() { - return sequenceNumber; - } + /** + * @param endTime + * to set + */ + public void setEndTime(Calendar endTime) { + this.endTime = endTime; + } - /** - * @param sequenceNumber to set - */ - public void setSequenceNumber(String sequenceNumber) { - this.sequenceNumber = sequenceNumber; - } + public String getMessageID() { + return messageID; + } - /** - * @return the atsu - */ - public String getAtsu() { - return atsu; - } + /** + * @param messageID + * to set + */ + public void setMessageID(String messageID) { + this.messageID = messageID; + } - /** - * @param atsu to set - */ - public void setAtsu(String atsu) { - this.atsu = atsu; - } + /** + * @return the sequenceNumber + */ + public String getSequenceNumber() { + return sequenceNumber; + } - /** - * @return the omwo - */ - public String getOmwo() { - return omwo; - } + /** + * @param sequenceNumber + * to set + */ + public void setSequenceNumber(String sequenceNumber) { + this.sequenceNumber = sequenceNumber; + } - /** - * @param omwo to set - */ - public void setOmwo(String omwo) { - this.omwo = omwo; - } + /** + * @return the atsu + */ + public String getAtsu() { + return atsu; + } - /** - * @return the flightLevel1 - */ - public Integer getFlightlevel1() { - return flightlevel1; - } + /** + * @param atsu + * to set + */ + public void setAtsu(String atsu) { + this.atsu = atsu; + } - /** - * @param flightLevel1 to set - */ - public void setFlightlevel1(Integer flightlevel1) { - this.flightlevel1 = flightlevel1; - } + /** + * @return the omwo + */ + public String getOmwo() { + return omwo; + } - /** - * @return flightLevel2 - */ - public Integer getFlightlevel2() { - return flightlevel2; - } + /** + * @param omwo + * to set + */ + public void setOmwo(String omwo) { + this.omwo = omwo; + } - /** - * @param flightLevel2 to set - */ - public void setFlightlevel2(Integer flightlevel2) { - this.flightlevel2 = flightlevel2; - } - - /** - * @return distacne - */ - public Integer getDistance() { - return distance; - } + /** + * @return the flightLevel1 + */ + public Integer getFlightlevel1() { + return flightlevel1; + } - /** - * @param distance to set - */ - public void setDistance(Integer distance) { - this.distance = distance; - } + /** + * @param flightLevel1 + * to set + */ + public void setFlightlevel1(Integer flightlevel1) { + this.flightlevel1 = flightlevel1; + } - /** - * @return direction - */ - public String getDirection() { - return direction; - } + /** + * @return flightLevel2 + */ + public Integer getFlightlevel2() { + return flightlevel2; + } - /** - * @param direction to set - */ - public void setDirection(String direction) { - this.direction = direction; - } + /** + * @param flightLevel2 + * to set + */ + public void setFlightlevel2(Integer flightlevel2) { + this.flightlevel2 = flightlevel2; + } - /** - * @return the speed - */ - public Integer getSpeed() { - return speed; - } + /** + * @return distacne + */ + public Integer getDistance() { + return distance; + } - /** - * @param speed to set - */ - public void setSpeed(Integer speed) { - this.speed = speed; - } + /** + * @param distance + * to set + */ + public void setDistance(Integer distance) { + this.distance = distance; + } - /** - * @return the nameLocation - */ - public String getNameLocation() { - return nameLocation; - } + /** + * @return direction + */ + public String getDirection() { + return direction; + } - /** - * @param nameLocation to set - */ - public void setNameLocation(String nameLocation) { - this.nameLocation = nameLocation; - } + /** + * @param direction + * to set + */ + public void setDirection(String direction) { + this.direction = direction; + } - /** - * @return the remarks - */ - public String getRemarks() { - return remarks; - } + /** + * @return the speed + */ + public Integer getSpeed() { + return speed; + } - /** - * @param remarks to set - */ - public void setRemarks(String remarks) { - this.remarks = remarks; - } + /** + * @param speed + * to set + */ + public void setSpeed(Integer speed) { + this.speed = speed; + } - /** - * @return the intensity - */ - public String getIntensity() { - return intensity; - } - - /** - * @param intensity to set - */ - public void setIntensity(String intensity) { - this.intensity = intensity; - } - - /** - * @return the polygonExtent - */ - public String getPolygonExtent() { - return polygonExtent; - } - - /** - * @param polygonExtent to set - */ - public void setPolygonExtent(String polygonExtent) { - this.polygonExtent = polygonExtent; - } + /** + * @return the nameLocation + */ + public String getNameLocation() { + return nameLocation; + } - /** - * @return the intlSigmetLocation - */ - public Set getIntlSigmetLocation() { - return intlSigmetLocation; - } + /** + * @param nameLocation + * to set + */ + public void setNameLocation(String nameLocation) { + this.nameLocation = nameLocation; + } - /** - * @param intlSigmetLocation to set - */ - public void setIntlSigmetLocation(Set intlSigmetLocation) { - this.intlSigmetLocation = intlSigmetLocation; - } + /** + * @return the remarks + */ + public String getRemarks() { + return remarks; + } - /** - * @return the serialVersionUID - */ - public static long getSerialVersionUID() { - return serialVersionUID; - } - - /** - * @param add international sigmet Location to set - */ - public void addIntlSigmetLocation(IntlSigmetLocation psection){ - intlSigmetLocation.add(psection); - - } - - /** - * Override existing set method to modify any - * classes that use the dataURI as a foreign key - */ - @Override - public void setIdentifier(Object dataURI) - { + /** + * @param remarks + * to set + */ + public void setRemarks(String remarks) { + this.remarks = remarks; + } - this.identifier = dataURI; - - - - } + /** + * @return the intensity + */ + public String getIntensity() { + return intensity; + } + + /** + * @param intensity + * to set + */ + public void setIntensity(String intensity) { + this.intensity = intensity; + } + + /** + * @return the polygonExtent + */ + public String getPolygonExtent() { + return polygonExtent; + } + + /** + * @param polygonExtent + * to set + */ + public void setPolygonExtent(String polygonExtent) { + this.polygonExtent = polygonExtent; + } + + /** + * @return the intlSigmetLocation + */ + public Set getIntlSigmetLocation() { + return intlSigmetLocation; + } + + /** + * @param intlSigmetLocation + * to set + */ + public void setIntlSigmetLocation(Set intlSigmetLocation) { + this.intlSigmetLocation = intlSigmetLocation; + } + + /** + * @return the serialVersionUID + */ + public static long getSerialVersionUID() { + return serialVersionUID; + } + + /** + * @param add + * international sigmet Location to set + */ + public void addIntlSigmetLocation(IntlSigmetLocation psection) { + intlSigmetLocation.add(psection); + + } + + /** + * Override existing set method to modify any classes that use the dataURI + * as a foreign key + */ + @Override + public void setIdentifier(Object dataURI) { + this.identifier = dataURI; + } @Override @Column @@ -581,4 +590,9 @@ public class IntlSigmetRecord extends PluginDataObject{ public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "intlsigmet"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasRecord.java index d5f3316c16..8395e52c8d 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.mcidas/src/gov/noaa/nws/ncep/common/dataplugin/mcidas/McidasRecord.java @@ -8,16 +8,18 @@ * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 08/2009 144 T. Lee Created - * 11/2009 144 T. Lee Implemented area name and - * added file name - * 12/2009 144 T. Lee Added calType, satelliteId - * and imageTypeNumber - * 05/2010 144 L. Lin Migration to TO11DR11. - * 09/2012 B. Hebbard Merge out RTS changes from OB12.9.1 - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime + * 11/2009 144 T. Lee Implemented area name and added file + * name + * 12/2009 144 T. Lee Added calType, satelliteId and + * imageTypeNumber + * 05/2010 144 L. Lin Migration to TO11DR11. + * 09/2012 B. Hebbard Merge out RTS changes from OB12.9.1 + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -65,12 +67,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "mcidas", - indexes = { - @Index(name = "mcidas_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "mcidas", indexes = { @Index(name = "mcidas_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @@ -223,7 +221,6 @@ public class McidasRecord extends PersistablePluginDataObject implements super(uri); } - /** * Set the time to be used for the persistence time for this object. * @@ -379,4 +376,9 @@ public class McidasRecord extends PersistablePluginDataObject implements public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "mcidas"; + } } \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncairep/src/gov/noaa/nws/ncep/common/dataplugin/ncairep/NcAirepPointDataTransform.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncairep/src/gov/noaa/nws/ncep/common/dataplugin/ncairep/NcAirepPointDataTransform.java index 41841d241f..1fcac9a8d6 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncairep/src/gov/noaa/nws/ncep/common/dataplugin/ncairep/NcAirepPointDataTransform.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncairep/src/gov/noaa/nws/ncep/common/dataplugin/ncairep/NcAirepPointDataTransform.java @@ -20,6 +20,8 @@ package gov.noaa.nws.ncep.common.dataplugin.ncairep; * further licensing information. **/ +import gov.noaa.nws.ncep.common.dataplugin.ncairep.dao.NcAirepDao; + import java.io.File; import java.util.ArrayList; import java.util.Date; @@ -27,7 +29,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import gov.noaa.nws.ncep.common.dataplugin.ncairep.dao.NcAirepDao; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.pointdata.PointDataContainer; import com.raytheon.uf.common.pointdata.PointDataDescription; @@ -36,17 +37,21 @@ import com.raytheon.uf.common.pointdata.spatial.AircraftObsLocation; import com.raytheon.uf.common.time.DataTime; /** - * Provides a transform from NcAirepRecords to PointDataContainer and vice versa. + * Provides a transform from NcAirepRecords to PointDataContainer and vice + * versa. * *
  * 
  * SOFTWARE HISTORY
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * 04/27/2011				F. J. Yen	Initial creation from MetarPointDataTransform
- * 06/28/2011				F. J. Yen	Updated for OB11.5
- * 09/19/2011    286       Q.Zhou      Modified populateRecord to add 8 new fields for TB, IC and SK.
- * 10/18/2011    286       Q.Zhou      Fixed datarui in db
+ * Apr 27, 2011            F. J. Yen   Initial creation from
+ *                                     MetarPointDataTransform
+ * Jun 28, 2011            F. J. Yen   Updated for OB11.5
+ * Sep 19, 2011 286        Q.Zhou      Modified populateRecord to add 8 new
+ *                                     fields for TB, IC and SK.
+ * Oct 18, 2011 286        Q.Zhou      Fixed datarui in db
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
  * 
* * @author f j yen @@ -68,9 +73,9 @@ public class NcAirepPointDataTransform { private static final String FLIGHT_HAZARD = "flightHazard"; private static final String FLIGHT_WEATHER = "flightWeather"; - + private static final String FLIGHT_CONDITIONS = "flightConditions"; - + // FLIGHT_HAZARD, FLIGHT_WEATHER, FLIGHT_CONDITIONS // ------------------ private static final String WMO_HEADER = "wmoHeader"; @@ -80,7 +85,7 @@ public class NcAirepPointDataTransform { private static final String REPORT_TYPE = "reportType"; private static final String TIME_OBS = "timeObs"; - + private static final String OBS_ID = "obsId"; // WMO_HEADER, STATION_ID, REPORT_TYPE, TIME_OBS, OBS_ID @@ -88,9 +93,9 @@ public class NcAirepPointDataTransform { private static final String LONGITUDE = "longitude"; private static final String LATITUDE = "latitude"; - + private static final String FLIGHT_LEVEL = "flightLevel"; - + // LONGITUDE, LATITUDE, FLIGHT_LEVEL // ------------------ private static final String CORRECTION_CODE = "correctionCode"; @@ -98,14 +103,23 @@ public class NcAirepPointDataTransform { private static final String DATAURI = "dataURI"; private static final String TURB_INTEN = "turbInten"; + private static final String TURB_TYPE = "turbType"; + private static final String TURB_FREQ = "turbFreq"; + private static final String ICE_INTEN = "iceInten"; + private static final String ICE_TYPE = "iceType"; + private static final String SKY_COVER = "skyCover"; + private static final String SKY_BASE_HEIGHT = "skyBaseHeight"; + private static final String SKY_TOP_HEIGHT = "skyTopHeight"; + private static final String SUSPECT_TIME_FLAG = "suspectTimeFlag"; + // CORRECTION_CODE, DATAURI, // ------------------ @@ -113,12 +127,12 @@ public class NcAirepPointDataTransform { * It is important to keep this up to date or risk breaking backwards * compatibility */ - private static final String[] ALL_PARAMS = { DATAURI, TIME_OBS, OBS_ID, REPORT_TYPE, - STATION_ID, WMO_HEADER, FLIGHT_HAZARD, FLIGHT_WEATHER, + private static final String[] ALL_PARAMS = { DATAURI, TIME_OBS, OBS_ID, + REPORT_TYPE, STATION_ID, WMO_HEADER, FLIGHT_HAZARD, FLIGHT_WEATHER, FLIGHT_CONDITIONS, LONGITUDE, LATITUDE, FLIGHT_LEVEL, - CORRECTION_CODE, TEMPERATURE, WIND_SPEED, WIND_DIR, - TURB_INTEN, TURB_TYPE, TURB_FREQ, ICE_INTEN, ICE_TYPE, SKY_COVER, - SKY_BASE_HEIGHT, SKY_TOP_HEIGHT, SUSPECT_TIME_FLAG}; + CORRECTION_CODE, TEMPERATURE, WIND_SPEED, WIND_DIR, TURB_INTEN, + TURB_TYPE, TURB_FREQ, ICE_INTEN, ICE_TYPE, SKY_COVER, + SKY_BASE_HEIGHT, SKY_TOP_HEIGHT, SUSPECT_TIME_FLAG }; public static final String ALL_PARAMS_LIST; static { @@ -150,60 +164,62 @@ public class NcAirepPointDataTransform { } public PluginDataObject[] toPointData(PluginDataObject[] pdo) { - - long t0 =System.currentTimeMillis(); - System.out.println("===============>toPointData"); // in NcAirepPointDataTransform t0=" + t0); + + long t0 = System.currentTimeMillis(); + System.out.println("===============>toPointData"); // in + // NcAirepPointDataTransform + // t0=" + t0); /* 999 */ - + if (pdo.length > 0) { Map pointMap = new HashMap(); - + for (PluginDataObject p : pdo) { - - if (!(p instanceof NcAirepRecord)) + + if (!(p instanceof NcAirepRecord)) { continue; - + } + File f = this.dao.getFullFilePath(p); - + PointDataContainer pdc = pointMap.get(f); if (pdc == null) { pdc = PointDataContainer.build(this.description); pointMap.put(f, pdc); - + } - - NcAirepRecord nar = (NcAirepRecord) p; - PointDataView pdv = buildView(pdc, nar); + + NcAirepRecord nar = (NcAirepRecord) p; + PointDataView pdv = buildView(pdc, nar); nar.setPointDataView(pdv); - + } } - - long t1 =System.currentTimeMillis(); - + + long t1 = System.currentTimeMillis(); + return pdo; } private PointDataView buildView(PointDataContainer container, NcAirepRecord record) { PointDataView pdv = container.append(); -// pdv.setString(STATION_ID, record.getStationId()); if (record.getCorIndicator() != null) { - pdv.setString(CORRECTION_CODE, record.getCorIndicator()); - }else{ - pdv.setString(CORRECTION_CODE," "); + pdv.setString(CORRECTION_CODE, record.getCorIndicator()); + } else { + pdv.setString(CORRECTION_CODE, " "); } - -// pdv.setFloat(LATITUDE, (float) record.getLatitude()); -// pdv.setFloat(LONGITUDE, (float) record.getLongitude()); + + // pdv.setFloat(LATITUDE, (float) record.getLatitude()); + // pdv.setFloat(LONGITUDE, (float) record.getLongitude()); pdv.setFloat(FLIGHT_LEVEL, record.getFlightLevel()); pdv.setLong(TIME_OBS, record.getDataTime().getRefTime().getTime()); -// pdv.setString(DATAURI, record.getDataURI()); -// pdv.setString(REPORT_TYPE, record.getReportType()); - pdv.setFloat(TEMPERATURE,(float) record.getTemp()); - pdv.setFloat(WIND_DIR, (float) record.getWindDirection()); - pdv.setFloat(WIND_SPEED, (float) record.getWindSpeed()); - + // pdv.setString(DATAURI, record.getDataURI()); + // pdv.setString(REPORT_TYPE, record.getReportType()); + pdv.setFloat(TEMPERATURE, record.getTemp()); + pdv.setFloat(WIND_DIR, record.getWindDirection()); + pdv.setFloat(WIND_SPEED, record.getWindSpeed()); + pdv.setString(TURB_INTEN, record.getTurbInten()); pdv.setString(TURB_TYPE, record.getTurbType()); pdv.setString(TURB_FREQ, record.getTurbFreq()); @@ -213,7 +229,7 @@ public class NcAirepPointDataTransform { pdv.setInt(SKY_BASE_HEIGHT, record.getSkyBaseHeight()); pdv.setInt(SKY_TOP_HEIGHT, record.getSkyTopHeight()); pdv.setString(SUSPECT_TIME_FLAG, record.getSuspectTimeFlag()); - + return pdv; } @@ -237,7 +253,6 @@ public class NcAirepPointDataTransform { nar.setTemp(pdv.getNumber(TEMPERATURE).floatValue()); - nar.setPluginName("ncairep"); nar.setFlightHazard(pdv.getInt(FLIGHT_HAZARD)); nar.setFlightWeather(pdv.getInt(FLIGHT_WEATHER)); nar.setFlightConditions(pdv.getInt(FLIGHT_CONDITIONS)); @@ -245,8 +260,8 @@ public class NcAirepPointDataTransform { // AIREP Wind data nar.setWindDirection(pdv.getNumber(WIND_DIR).floatValue()); nar.setWindSpeed(pdv.getNumber(WIND_SPEED).floatValue()); - //nar.setSuspectTimeFlag(pdv.getString(SUSPECT_TIME_FLAG)); - + // nar.setSuspectTimeFlag(pdv.getString(SUSPECT_TIME_FLAG)); + return nar; } @@ -260,4 +275,3 @@ public class NcAirepPointDataTransform { return records.toArray(new NcAirepRecord[records.size()]); } } - diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncairep/src/gov/noaa/nws/ncep/common/dataplugin/ncairep/NcAirepRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncairep/src/gov/noaa/nws/ncep/common/dataplugin/ncairep/NcAirepRecord.java index 3410c76c85..c35159c23b 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncairep/src/gov/noaa/nws/ncep/common/dataplugin/ncairep/NcAirepRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncairep/src/gov/noaa/nws/ncep/common/dataplugin/ncairep/NcAirepRecord.java @@ -60,19 +60,23 @@ import com.vividsolutions.jts.geom.Geometry; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20110421 F. J. Yen Initial creation from Raytheon's pirep. - * Change temp, windSpeed from Double to Float. - * Change windDirection from Integer to Float - * 08/30/2011 286 qzhou Use IDecoderConstantsN.INTEGER_MISSING instead -9999 in visibility. - * 08/31/2011 286 qzhou Moved this from ~edex.plugin.airep - * 9/20/2011 286 qzhou Change reportType to String - * 04/05/2012 420 dgilling Prevent NullPointerExceptions in + * Apr 21, 2011 F. J. Yen Initial creation from Raytheon's pirep. + * Change temp, windSpeed from Double to + * Float. Change windDirection from Integer + * to Float + * Aug 30, 2011 286 qzhou Use IDecoderConstantsN.INTEGER_MISSING + * instead -9999 in visibility. + * Aug 31, 2011 286 qzhou Moved this from ~edex.plugin.airep + * Sep 20, 2011 286 qzhou Change reportType to String + * Apr 05, 2012 420 dgilling Prevent NullPointerExceptions in * buildMessageData(). - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 04/08/13 1293 bkowal Removed references to hdffileid. - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -87,812 +91,804 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ncairep", - indexes = { - @Index(name = "ncairep_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ncairep", indexes = { @Index(name = "ncairep_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class NcAirepRecord extends PluginDataObject implements ISpatialEnabled, - IDecoderGettable, IPointData, IPersistable { + IDecoderGettable, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - // public static final String PLUGIN_NAME = "ncairep"; - // - // public static final String STATION_ID = "stationId"; + public static final Unit TEMPERATURE_UNIT = SI.CELSIUS; - public static final Unit TEMPERATURE_UNIT = SI.CELSIUS; + public static final Unit WIND_SPEED_UNIT = NonSI.KNOT; - public static final Unit WIND_SPEED_UNIT = NonSI.KNOT; + public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; - public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit ALTITUDE_UNIT = NonSI.FOOT; - public static final Unit ALTITUDE_UNIT = NonSI.FOOT; + public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; - public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; + private static UnitConverter ftToHft = NonSI.FOOT.getConverterTo(SI + .HECTO(NonSI.FOOT)); - private static UnitConverter ftToHft = NonSI.FOOT.getConverterTo(SI - .HECTO(NonSI.FOOT)); + private static final HashMap PARM_MAP = new HashMap(); - private static final HashMap PARM_MAP = new HashMap(); + // private static final HashMap WX_MAP = new + // HashMap(); - // private static final HashMap WX_MAP = new - // HashMap(); + static { + PARM_MAP.put("T", SFC_TEMP); + PARM_MAP.put("WS", SFC_WNDSPD); + PARM_MAP.put("WD", SFC_WNDDIR); + PARM_MAP.put("NLAT", STA_LAT); + PARM_MAP.put("NLON", STA_LON); + PARM_MAP.put("FLT_LVL", UA_FLTLVL); - static { - PARM_MAP.put("T", SFC_TEMP); - PARM_MAP.put("WS", SFC_WNDSPD); - PARM_MAP.put("WD", SFC_WNDDIR); - PARM_MAP.put("NLAT", STA_LAT); - PARM_MAP.put("NLON", STA_LON); - PARM_MAP.put("FLT_LVL", UA_FLTLVL); + // WX_MAP.put(0, "CLR"); + // WX_MAP.put(1, "SCT"); + // WX_MAP.put(2, "BKN"); + // WX_MAP.put(3, "CONT"); + // WX_MAP.put(4, "LIGHTNING"); + // WX_MAP.put(5, "DZRA"); + // WX_MAP.put(6, "CONT RA"); + // WX_MAP.put(7, "CONT SN"); + // WX_MAP.put(8, "SH"); + // WX_MAP.put(9, "TSRA"); + } - // WX_MAP.put(0, "CLR"); - // WX_MAP.put(1, "SCT"); - // WX_MAP.put(2, "BKN"); - // WX_MAP.put(3, "CONT"); - // WX_MAP.put(4, "LIGHTNING"); - // WX_MAP.put(5, "DZRA"); - // WX_MAP.put(6, "CONT RA"); - // WX_MAP.put(7, "CONT SN"); - // WX_MAP.put(8, "SH"); - // WX_MAP.put(9, "TSRA"); - } + @Transient + @DynamicSerializeElement + @XmlAttribute + private Integer obsId; - @Transient - @DynamicSerializeElement - @XmlAttribute - private Integer obsId; + // Time of the observation. + @Transient + @DynamicSerializeElement + @XmlAttribute + private Calendar timeObs; - // Time of the observation. - @Transient - @DynamicSerializeElement - @XmlAttribute - private Calendar timeObs; + // Time of the observation to the nearest hour. + @Column + @DynamicSerializeElement + @XmlAttribute + private Calendar refHour; - // Time of the observation to the nearest hour. - @Column - @DynamicSerializeElement - @XmlAttribute - private Calendar refHour; + // + @DataURI(position = 1) + @Column(length = 8) + @DynamicSerializeElement + @XmlAttribute + private String reportType; - // - @DataURI(position = 1) - @Column(length = 8) - @DynamicSerializeElement - @XmlAttribute - private String reportType; + // Text of the WMO header + @Transient + @DynamicSerializeElement + @XmlElement + private String wmoHeader; - // Text of the WMO header - @Transient - @DynamicSerializeElement - @XmlElement - private String wmoHeader; + // Correction indicator from wmo header + @DataURI(position = 2) + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String corIndicator; - // Correction indicator from wmo header - @DataURI(position = 2) - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String corIndicator; + // Observation air temperature in degrees Celsius. + // Decimal(5,2) + @Transient + @DynamicSerializeElement + @XmlElement + private Float temp; - // Observation air temperature in degrees Celsius. - // Decimal(5,2) - @Transient - @DynamicSerializeElement - @XmlElement - private Float temp; + // Observation wind direction in angular degrees. Integer + @Transient + @DynamicSerializeElement + @XmlElement + private Float windDirection; - // Observation wind direction in angular degrees. Integer - @Transient - @DynamicSerializeElement - @XmlElement - private Float windDirection; + // Observation wind speed in knots. + // Decimal(5,2) + @Transient + // @Column + @DynamicSerializeElement + @XmlElement + private Float windSpeed; - // Observation wind speed in knots. - // Decimal(5,2) - @Transient - // @Column - @DynamicSerializeElement - @XmlElement - private Float windSpeed; + @Transient + @DynamicSerializeElement + @XmlElement + private Integer flightHazard; - @Transient - @DynamicSerializeElement - @XmlElement - private Integer flightHazard; + @Transient + @DynamicSerializeElement + @XmlElement + private Integer flightWeather; - @Transient - @DynamicSerializeElement - @XmlElement - private Integer flightWeather; + @Transient + @DynamicSerializeElement + @XmlElement + private Integer flightConditions; - @Transient - @DynamicSerializeElement - @XmlElement - private Integer flightConditions; + // @Transient + // @DynamicSerializeElement + // @XmlElement + // private Float latitude; + // + // @Transient + // @DynamicSerializeElement + // @XmlElement + // private Float longitude; + // + // @Transient + // @DynamicSerializeElement + // @XmlElement + // private String stationId; - // @Transient - // @DynamicSerializeElement - // @XmlElement - // private Float latitude; - // - // @Transient - // @DynamicSerializeElement - // @XmlElement - // private Float longitude; - // - // @Transient - // @DynamicSerializeElement - // @XmlElement - // private String stationId; + // @Transient + // @DynamicSerializeElement + // @XmlElement + // private String dataURI; - // @Transient - // @DynamicSerializeElement - // @XmlElement - // private String dataURI; + @Transient + @DynamicSerializeElement + // @XmlElement + @XmlAttribute + private String turbInten; - @Transient - @DynamicSerializeElement - // @XmlElement - @XmlAttribute - private String turbInten; + @Transient + @DynamicSerializeElement + @XmlElement + private String iceInten; - @Transient - @DynamicSerializeElement - @XmlElement - private String iceInten; + @Transient + @DynamicSerializeElement + @XmlElement + private String skyCover; - @Transient - @DynamicSerializeElement - @XmlElement - private String skyCover; + @Transient + @DynamicSerializeElement + @XmlElement + private String turbType; - @Transient - @DynamicSerializeElement - @XmlElement - private String turbType; + @Transient + @DynamicSerializeElement + @XmlElement + private String iceType; - @Transient - @DynamicSerializeElement - @XmlElement - private String iceType; + @Transient + @DynamicSerializeElement + @XmlElement + private String turbFreq; - @Transient - @DynamicSerializeElement - @XmlElement - private String turbFreq; + @Transient + @DynamicSerializeElement + @XmlElement + private int skyBaseHeight; - @Transient - @DynamicSerializeElement - @XmlElement - private int skyBaseHeight; + @Transient + @DynamicSerializeElement + @XmlElement + private int skyTopHeight; - @Transient - @DynamicSerializeElement - @XmlElement - private int skyTopHeight; + @Transient + @DynamicSerializeElement + @XmlElement + private String suspectTimeFlag; - @Transient - @DynamicSerializeElement - @XmlElement - private String suspectTimeFlag; + @Embedded + @DataURI(position = 3, embedded = true) + @XmlElement + @DynamicSerializeElement + private AircraftObsLocation location; - @Embedded - @DataURI(position = 3, embedded = true) - @XmlElement - @DynamicSerializeElement - private AircraftObsLocation location; + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - /** + /** * */ - public NcAirepRecord() { - } - - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public NcAirepRecord(String uri) { - super(uri); - } - - public Integer getObsId() { - return obsId; - } - - public void setObsId(Integer obsId) { - this.obsId = obsId; - } - - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } - - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } - - /** - * Get the report correction indicator. - * - * @return The corIndicator - */ - public String getCorIndicator() { - return corIndicator; - } - - /** - * Set the report correction indicator. - * - * @param corIndicator - * The corIndicator. - */ - public void setCorIndicator(String corIndicator) { - this.corIndicator = corIndicator; - } - - /** - * Get the report data for this observation. - * - * @return The Report data. - */ - public String getReportData() { - String s = null; - if (messageData != null && messageData instanceof String) { - s = (String) messageData; - } else { - s = buildMessageData(); - } - return s; - } - - /** - * Set the report data for this observation. - * - * @param reportData - * The Report data. - */ - public void setReportData(String reportData) { - messageData = reportData; - } - - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } - - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } - - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } - - /** - * Boolean for whether location is defined in the spatial tables. - * - * @return true or false (Is location defined in the spatial tables?) - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } - - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } - - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getFlightLevel() { - return location.getFlightLevel(); - } - - /** - * @return the reportType - */ - public String getReportType() { - return reportType; - } - - /** - * @param reportType - * the reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } - - /** - * @return the timeObs - */ - public Calendar getTimeObs() { - if (this.dataTime == null) { - return null; - } - return this.dataTime.getRefTimeAsCalendar(); - } - - /** - * @param timeObs - * the timeObs to set - */ - public void setTimeObs(Calendar timeObs) { - this.timeObs = timeObs; - } - - /** - * @return the refHour - */ - public Calendar getRefHour() { - return refHour; - } - - /** - * @param refHour - * the refHour to set - */ - public void setRefHour(Calendar refHour) { - this.refHour = refHour; - } - - /** - * @return the temp - */ - public float getTemp() { - return temp; - } - - /** - * @param temp - * the temp to set - */ - public void setTemp(float temp) { - this.temp = temp; - } - - /** - * @return the windDirection - */ - public float getWindDirection() { - return windDirection; - } - - /** - * @param windDirection - * the windDirection to set - */ - public void setWindDirection(float windDirection) { - this.windDirection = windDirection; - } - - /** - * @return the windspeed - */ - public float getWindSpeed() { - return windSpeed; - } - - /** - * @param windspeed - * the windspeed to set - */ - public void setWindSpeed(float windSpeed) { - this.windSpeed = windSpeed; - } - - /** - * @return the flightHazard - */ - public Integer getFlightHazard() { - return flightHazard; - } - - /** - * @param flightHazard - * the wx_past_1 to set - */ - public void setFlightHazard(Integer flightHazard) { - this.flightHazard = flightHazard; - } - - /** - * @return the flightWeather - */ - public Integer getFlightWeather() { - return flightWeather; - } - - /** - * @param flightWeather - * the getFlightWeather to set - */ - public void setFlightWeather(Integer flightWeather) { - this.flightWeather = flightWeather; - } - - /** - * @return the flightConditions - */ - public Integer getFlightConditions() { - return flightConditions; - } - - /** - * @param flightConditions - * the flightConditions to set - */ - public void setFlightConditions(Integer flightConditions) { - this.flightConditions = flightConditions; - } - - /** - * @return the wmoHeader - */ - public String getTurbInten() { - return turbInten; - } - - public void setTurbInten(String turbInten) { - this.turbInten = turbInten; - } - - public String getIceInten() { - return iceInten; - } - - public void setIceInten(String iceInten) { - this.iceInten = iceInten; - } - - public String getSkyCover() { - return skyCover; - } - - public void setSkyCover(String skyCover) { - this.skyCover = skyCover; - } - - public String getTurbType() { - return turbType; - } - - public void setTurbType(String turbType) { - this.turbType = turbType; - } - - public String getIceType() { - return iceType; - } - - public void setIceType(String iceType) { - this.iceType = iceType; - } - - public String getTurbFreq() { - return turbFreq; - } - - public void setTurbFreq(String turbFreq) { - this.turbFreq = turbFreq; - } - - public int getSkyBaseHeight() { - return skyBaseHeight; - } - - public void setSkyBaseHeight(int skyBaseHeight) { - this.skyBaseHeight = skyBaseHeight; - } - - public int getSkyTopHeight() { - return skyTopHeight; - } - - public void setSkyTopHeight(int skyTopHeight) { - this.skyTopHeight = skyTopHeight; - } - - public String getSuspectTimeFlag() { - return suspectTimeFlag; - } - - public void setSuspectTimeFlag(String suspectTimeFlag) { - this.suspectTimeFlag = suspectTimeFlag; - } - - @Override - public void setDataURI(String dataURI) { - identifier = dataURI; - } - - /** - * Get the IDecoderGettable reference for this record. - * - * @return The IDecoderGettable reference for this record. - */ - @Override - public IDecoderGettable getDecoderGettable() { - return this; - } - - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public String getString(String paramName) { - if ("STA".matches(paramName)) { - return this.getStationId(); - } - return null; - } - - /** - * Get the value and units of a named parameter within this observation. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return An Amount with value and units. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Amount getValue(String paramName) { - Amount a = null; - - String pName = PARM_MAP.get(paramName); - - if (SFC_TEMP.equals(pName) && (temp != null)) { - a = new Amount(temp, TEMPERATURE_UNIT); - } else if (SFC_WNDSPD.equals(pName) && (windSpeed != null)) { - a = new Amount(windSpeed, WIND_SPEED_UNIT); - } else if (SFC_WNDDIR.equals(pName) && (windDirection != null)) { - a = new Amount(windDirection, WIND_DIR_UNIT); - } else if (STA_LAT.equals(pName)) { - a = new Amount(this.getLatitude(), LOCATION_UNIT); - } else if (STA_LON.equals(pName)) { - a = new Amount(this.getLongitude(), LOCATION_UNIT); - } else if (UA_FLTLVL.equals(pName) && getFlightLevel() != null) { - a = new Amount(this.getFlightLevel().intValue(), ALTITUDE_UNIT); - - } - return a; - } - - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Collection getValues(String paramName) { - return null; - } - - @Override - public String[] getStrings(String paramName) { - if ("FLT_HZD".matches(paramName) && flightHazard != null) { - String[] flightHazards = { flightHazard.toString() }; - return flightHazards; - } - return null; - } - - @Override - public AircraftObsLocation getSpatialObject() { - return location; - } - - public AircraftObsLocation getLocation() { - return location; - } - - public void setLocation(AircraftObsLocation location) { - this.location = location; - } - - @Override - public String getMessageData() { - return getReportData(); - } - - private String buildMessageData() { - boolean validLocation = (location != null); - - StringBuilder messageData = new StringBuilder("ARP "); - if (validLocation && getStationId() != null) { - messageData.append(getStationId()); - } - messageData.append(' '); - - if ((validLocation) && (!Double.isNaN(getLatitude())) - && (!Double.isNaN(getLongitude()))) { - messageData.append(formatLatLon(getLatitude(), true)); - messageData.append(' '); - messageData.append(formatLatLon(getLongitude(), false)); - messageData.append(' '); - } - - if (timeObs != null) { - DateFormat df = new SimpleDateFormat("HHmm"); - messageData.append(df.format(timeObs.getTime())); - } - messageData.append(" F"); - - if (validLocation && getFlightLevel() != null) { - int flightLevel = (int) ftToHft.convert(getFlightLevel()); - messageData.append(flightLevel); - } - messageData.append(' '); - - if (temp != null) { - if (temp > 0) { - messageData.append('P'); - } else { - messageData.append('M'); - } - messageData.append(Math.abs(temp.intValue())); - } - messageData.append(' '); - - if ((windDirection != null) && (windSpeed != null)) { - messageData.append(windDirection.intValue()); - messageData.append('/'); - messageData.append(windSpeed.intValue()); - messageData.append("KT"); - } - messageData.append("TB"); - - return messageData.toString(); - } - - private String formatLatLon(double value, boolean isLatitude) { - char dir; - if (isLatitude) { - if (value > 0) { - dir = 'N'; - } else { - dir = 'S'; - } - } else { - if (value > 0) { - dir = 'E'; - } else { - dir = 'W'; - } - } - - DecimalFormat df = new DecimalFormat("###.000"); - df.setRoundingMode(RoundingMode.DOWN); - - return df.format(Math.abs(value)) + dir; - } - - /** - * Returns the hashCode for this object. This implementation returns the - * hashCode of the generated dataURI. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); - return result; - } - - /** - * Checks if this record is equal to another by checking the generated - * dataURI. - * - * @param obj - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - NcAirepRecord other = (NcAirepRecord) obj; - if (getDataURI() == null) { - if (other.getDataURI() != null) { - return false; - } - } else if (!getDataURI().equals(other.getDataURI())) { - return false; - } - return true; - } - - @Override - public Date getPersistenceTime() { - return this.dataTime.getRefTime(); - } - - @Override - public void setPersistenceTime(Date persistTime) { - } - - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() - */ - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } - - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon - * .uf.common.pointdata.PointDataView) - */ - @Override - public void setPointDataView(PointDataView pdv) { - this.pointDataView = pdv; - } + public NcAirepRecord() { + } + + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public NcAirepRecord(String uri) { + super(uri); + } + + public Integer getObsId() { + return obsId; + } + + public void setObsId(Integer obsId) { + this.obsId = obsId; + } + + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } + + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } + + /** + * Get the report correction indicator. + * + * @return The corIndicator + */ + public String getCorIndicator() { + return corIndicator; + } + + /** + * Set the report correction indicator. + * + * @param corIndicator + * The corIndicator. + */ + public void setCorIndicator(String corIndicator) { + this.corIndicator = corIndicator; + } + + /** + * Get the report data for this observation. + * + * @return The Report data. + */ + public String getReportData() { + String s = null; + if ((messageData != null) && (messageData instanceof String)) { + s = (String) messageData; + } else { + s = buildMessageData(); + } + return s; + } + + /** + * Set the report data for this observation. + * + * @param reportData + * The Report data. + */ + public void setReportData(String reportData) { + messageData = reportData; + } + + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } + + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } + + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } + + /** + * Boolean for whether location is defined in the spatial tables. + * + * @return true or false (Is location defined in the spatial tables?) + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } + + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } + + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getFlightLevel() { + return location.getFlightLevel(); + } + + /** + * @return the reportType + */ + public String getReportType() { + return reportType; + } + + /** + * @param reportType + * the reportType to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } + + /** + * @return the timeObs + */ + public Calendar getTimeObs() { + if (this.dataTime == null) { + return null; + } + return this.dataTime.getRefTimeAsCalendar(); + } + + /** + * @param timeObs + * the timeObs to set + */ + public void setTimeObs(Calendar timeObs) { + this.timeObs = timeObs; + } + + /** + * @return the refHour + */ + public Calendar getRefHour() { + return refHour; + } + + /** + * @param refHour + * the refHour to set + */ + public void setRefHour(Calendar refHour) { + this.refHour = refHour; + } + + /** + * @return the temp + */ + public float getTemp() { + return temp; + } + + /** + * @param temp + * the temp to set + */ + public void setTemp(float temp) { + this.temp = temp; + } + + /** + * @return the windDirection + */ + public float getWindDirection() { + return windDirection; + } + + /** + * @param windDirection + * the windDirection to set + */ + public void setWindDirection(float windDirection) { + this.windDirection = windDirection; + } + + /** + * @return the windspeed + */ + public float getWindSpeed() { + return windSpeed; + } + + /** + * @param windspeed + * the windspeed to set + */ + public void setWindSpeed(float windSpeed) { + this.windSpeed = windSpeed; + } + + /** + * @return the flightHazard + */ + public Integer getFlightHazard() { + return flightHazard; + } + + /** + * @param flightHazard + * the wx_past_1 to set + */ + public void setFlightHazard(Integer flightHazard) { + this.flightHazard = flightHazard; + } + + /** + * @return the flightWeather + */ + public Integer getFlightWeather() { + return flightWeather; + } + + /** + * @param flightWeather + * the getFlightWeather to set + */ + public void setFlightWeather(Integer flightWeather) { + this.flightWeather = flightWeather; + } + + /** + * @return the flightConditions + */ + public Integer getFlightConditions() { + return flightConditions; + } + + /** + * @param flightConditions + * the flightConditions to set + */ + public void setFlightConditions(Integer flightConditions) { + this.flightConditions = flightConditions; + } + + /** + * @return the wmoHeader + */ + public String getTurbInten() { + return turbInten; + } + + public void setTurbInten(String turbInten) { + this.turbInten = turbInten; + } + + public String getIceInten() { + return iceInten; + } + + public void setIceInten(String iceInten) { + this.iceInten = iceInten; + } + + public String getSkyCover() { + return skyCover; + } + + public void setSkyCover(String skyCover) { + this.skyCover = skyCover; + } + + public String getTurbType() { + return turbType; + } + + public void setTurbType(String turbType) { + this.turbType = turbType; + } + + public String getIceType() { + return iceType; + } + + public void setIceType(String iceType) { + this.iceType = iceType; + } + + public String getTurbFreq() { + return turbFreq; + } + + public void setTurbFreq(String turbFreq) { + this.turbFreq = turbFreq; + } + + public int getSkyBaseHeight() { + return skyBaseHeight; + } + + public void setSkyBaseHeight(int skyBaseHeight) { + this.skyBaseHeight = skyBaseHeight; + } + + public int getSkyTopHeight() { + return skyTopHeight; + } + + public void setSkyTopHeight(int skyTopHeight) { + this.skyTopHeight = skyTopHeight; + } + + public String getSuspectTimeFlag() { + return suspectTimeFlag; + } + + public void setSuspectTimeFlag(String suspectTimeFlag) { + this.suspectTimeFlag = suspectTimeFlag; + } + + @Override + public void setDataURI(String dataURI) { + identifier = dataURI; + } + + /** + * Get the IDecoderGettable reference for this record. + * + * @return The IDecoderGettable reference for this record. + */ + @Override + public IDecoderGettable getDecoderGettable() { + return this; + } + + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public String getString(String paramName) { + if ("STA".matches(paramName)) { + return this.getStationId(); + } + return null; + } + + /** + * Get the value and units of a named parameter within this observation. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return An Amount with value and units. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Amount getValue(String paramName) { + Amount a = null; + + String pName = PARM_MAP.get(paramName); + + if (SFC_TEMP.equals(pName) && (temp != null)) { + a = new Amount(temp, TEMPERATURE_UNIT); + } else if (SFC_WNDSPD.equals(pName) && (windSpeed != null)) { + a = new Amount(windSpeed, WIND_SPEED_UNIT); + } else if (SFC_WNDDIR.equals(pName) && (windDirection != null)) { + a = new Amount(windDirection, WIND_DIR_UNIT); + } else if (STA_LAT.equals(pName)) { + a = new Amount(this.getLatitude(), LOCATION_UNIT); + } else if (STA_LON.equals(pName)) { + a = new Amount(this.getLongitude(), LOCATION_UNIT); + } else if (UA_FLTLVL.equals(pName) && (getFlightLevel() != null)) { + a = new Amount(this.getFlightLevel().intValue(), ALTITUDE_UNIT); + + } + return a; + } + + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Collection getValues(String paramName) { + return null; + } + + @Override + public String[] getStrings(String paramName) { + if ("FLT_HZD".matches(paramName) && (flightHazard != null)) { + String[] flightHazards = { flightHazard.toString() }; + return flightHazards; + } + return null; + } + + @Override + public AircraftObsLocation getSpatialObject() { + return location; + } + + public AircraftObsLocation getLocation() { + return location; + } + + public void setLocation(AircraftObsLocation location) { + this.location = location; + } + + @Override + public String getMessageData() { + return getReportData(); + } + + private String buildMessageData() { + boolean validLocation = (location != null); + + StringBuilder messageData = new StringBuilder("ARP "); + if (validLocation && (getStationId() != null)) { + messageData.append(getStationId()); + } + messageData.append(' '); + + if ((validLocation) && (!Double.isNaN(getLatitude())) + && (!Double.isNaN(getLongitude()))) { + messageData.append(formatLatLon(getLatitude(), true)); + messageData.append(' '); + messageData.append(formatLatLon(getLongitude(), false)); + messageData.append(' '); + } + + if (timeObs != null) { + DateFormat df = new SimpleDateFormat("HHmm"); + messageData.append(df.format(timeObs.getTime())); + } + messageData.append(" F"); + + if (validLocation && (getFlightLevel() != null)) { + int flightLevel = (int) ftToHft.convert(getFlightLevel()); + messageData.append(flightLevel); + } + messageData.append(' '); + + if (temp != null) { + if (temp > 0) { + messageData.append('P'); + } else { + messageData.append('M'); + } + messageData.append(Math.abs(temp.intValue())); + } + messageData.append(' '); + + if ((windDirection != null) && (windSpeed != null)) { + messageData.append(windDirection.intValue()); + messageData.append('/'); + messageData.append(windSpeed.intValue()); + messageData.append("KT"); + } + messageData.append("TB"); + + return messageData.toString(); + } + + private String formatLatLon(double value, boolean isLatitude) { + char dir; + if (isLatitude) { + if (value > 0) { + dir = 'N'; + } else { + dir = 'S'; + } + } else { + if (value > 0) { + dir = 'E'; + } else { + dir = 'W'; + } + } + + DecimalFormat df = new DecimalFormat("###.000"); + df.setRoundingMode(RoundingMode.DOWN); + + return df.format(Math.abs(value)) + dir; + } + + /** + * Returns the hashCode for this object. This implementation returns the + * hashCode of the generated dataURI. + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); + return result; + } + + /** + * Checks if this record is equal to another by checking the generated + * dataURI. + * + * @param obj + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + NcAirepRecord other = (NcAirepRecord) obj; + if (getDataURI() == null) { + if (other.getDataURI() != null) { + return false; + } + } else if (!getDataURI().equals(other.getDataURI())) { + return false; + } + return true; + } + + @Override + public Date getPersistenceTime() { + return this.dataTime.getRefTime(); + } + + @Override + public void setPersistenceTime(Date persistTime) { + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() + */ + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon + * .uf.common.pointdata.PointDataView) + */ + @Override + public void setPointDataView(PointDataView pdv) { + this.pointDataView = pdv; + } @Override @Column @@ -900,4 +896,9 @@ public class NcAirepRecord extends PluginDataObject implements ISpatialEnabled, public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ncairep"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncccfp/src/gov/noaa/nws/ncep/common/dataplugin/ncccfp/NcccfpRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncccfp/src/gov/noaa/nws/ncep/common/dataplugin/ncccfp/NcccfpRecord.java index 8c01720dbd..b1d0dc5817 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncccfp/src/gov/noaa/nws/ncep/common/dataplugin/ncccfp/NcccfpRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncccfp/src/gov/noaa/nws/ncep/common/dataplugin/ncccfp/NcccfpRecord.java @@ -1,4 +1,3 @@ - package gov.noaa.nws.ncep.common.dataplugin.ncccfp; import java.util.Calendar; @@ -31,15 +30,16 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * *
  * SOFTWARE HISTORY
- * Date         Ticket#     Engineer    Description
- * --------- ----------  ----------- --------------------------
- * 10/05/2009   155         F. J. Yen   From Raytheon's CCFP; mod for NC_CCFP
- * 26/05/2010	155			F. J. Yen	Refactored to dataplugin for migration to to11dr11
- * Apr 4, 2013        1846 bkowal      Added an index on refTime and forecastTime
- * Apr 12, 2013 1857        bgonzale    Added SequenceGenerator annotation.
- * May 07, 2013 1869     bsteffen    Remove dataURI column from
+ * Date         Ticket#  Engineer    Description
+ * ------------ -------- ----------- --------------------------
+ * Oct 05, 2009 155      F. J. Yen   From Raytheon's CCFP; mod for NC_CCFP
+ * May 26, 2010 155      F. J. Yen   Refactored to dataplugin for
+ *                                   migration to to11dr11
+ * Apr 04, 2013 1846      bkowal     Added an index on refTime and forecastTime
+ * Apr 12, 2013 1857      bgonzale   Added SequenceGenerator annotation.
+ * May 07, 2013 1869      bsteffen   Remove dataURI column from
  *                                   PluginDataObject.
- * 
+ * Aug 30, 2013 2298      rjpeter    Make getPluginName abstract
  * 
* * @author F. J. Yen @@ -52,12 +52,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ncccfp", - indexes = { - @Index(name = "ncccfp_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ncccfp", indexes = { @Index(name = "ncccfp_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -76,7 +72,7 @@ public class NcccfpRecord extends PluginDataObject implements ISpatialEnabled { @XmlAttribute @DynamicSerializeElement private Calendar validtime; - + @Column(length = 8) @XmlAttribute @DynamicSerializeElement @@ -117,26 +113,26 @@ public class NcccfpRecord extends PluginDataObject implements ISpatialEnabled { @XmlAttribute @DynamicSerializeElement private Integer numPts; - + @Column @DynamicSerializeElement @XmlElement private Boolean canadaflag; /* - * locationUri contains up to the first seven coordinates. This is for making the dataURI - * unique. (It was suggested that it was highly unlikely that 7 coordinates would not - * be unique enough. The number of coordinates was reduced due to the limited length of - * the string dataURI) + * locationUri contains up to the first seven coordinates. This is for + * making the dataURI unique. (It was suggested that it was highly unlikely + * that 7 coordinates would not be unique enough. The number of coordinates + * was reduced due to the limited length of the string dataURI) */ @DataURI(position = 4) - @Column(length=150) + @Column(length = 150) @XmlElement @DynamicSerializeElement private String locationUri; - + private NcccfpLocation location; - + /** * Default Constructor */ @@ -299,8 +295,8 @@ public class NcccfpRecord extends PluginDataObject implements ISpatialEnabled { */ public void setDirection(Integer direction) { this.direction = direction; - } - + } + /** * @return the number of points */ @@ -315,6 +311,7 @@ public class NcccfpRecord extends PluginDataObject implements ISpatialEnabled { public void setNumPts(Integer numPts) { this.numPts = numPts; } + @Override public NcccfpLocation getSpatialObject() { return location; @@ -332,9 +329,9 @@ public class NcccfpRecord extends PluginDataObject implements ISpatialEnabled { return location; } - public void setLocation (NcccfpLocation location) { + public void setLocation(NcccfpLocation location) { this.location = location; - } + } @Override @Column @@ -343,4 +340,8 @@ public class NcccfpRecord extends PluginDataObject implements ISpatialEnabled { return super.getDataURI(); } + @Override + public String getPluginName() { + return "ncccfp"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncgrib/src/gov/noaa/nws/ncep/common/dataplugin/ncgrib/NcgribRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncgrib/src/gov/noaa/nws/ncep/common/dataplugin/ncgrib/NcgribRecord.java index c570367cfe..963efe9174 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncgrib/src/gov/noaa/nws/ncep/common/dataplugin/ncgrib/NcgribRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncgrib/src/gov/noaa/nws/ncep/common/dataplugin/ncgrib/NcgribRecord.java @@ -64,14 +64,17 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 4/7/09 1994 bphillip Initial Creation - * 10/13/10 276 llin Modified for NC GRIB. - * 03/07/12 606 ghull Added eventName to URI for NcInventory updating. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 04/08/13 1293 bkowal Removed references to hdffileid. + * Apr 07, 2009 1994 bphillip Initial Creation + * Oct 13, 2010 276 llin Modified for NC GRIB. + * Mar 07, 2012 606 ghull Added eventName to URI for NcInventory + * updating. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -85,12 +88,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ncgrib", - indexes = { - @Index(name = "ncgrib_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ncgrib", indexes = { @Index(name = "ncgrib_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -105,36 +104,36 @@ public class NcgribRecord extends PersistablePluginDataObject implements @DynamicSerializeElement private int masterTableVersion; - /** + /** * Version number of GRIB local tables used to augment Master Tables (See * Table 1.1) 0 - local tables not used, only table entries and templates - * the current master table are valid. (Currently 1) + * the current master table are valid. (Currently 1) */ @Column @XmlAttribute @DynamicSerializeElement private int localTableVersion; - /** Significance of reference time (See Table 1.2) - * 0 for analysis, 1 for forecast, 2 for verifying time, - * and 3 for observation time + /** + * Significance of reference time (See Table 1.2) 0 for analysis, 1 for + * forecast, 2 for verifying time, and 3 for observation time */ @Column @XmlAttribute @DynamicSerializeElement private int refTimeSignificance; - /** Processed data type in this GRIB message (See Table 1.4) - * 0 for analysis, 1 for forecast, 2 for both, .... - * or PDT in table 4.3 - * This refers to PDT# in GEMPAK output + /** + * Processed data type in this GRIB message (See Table 1.4) 0 for analysis, + * 1 for forecast, 2 for both, .... or PDT in table 4.3 This refers to PDT# + * in GEMPAK output */ @Column @XmlAttribute @DynamicSerializeElement private int processedDataType; - - /** Denotes if local section is present (currently false)*/ + + /** Denotes if local section is present (currently false) */ @Column @XmlAttribute @DynamicSerializeElement @@ -179,7 +178,7 @@ public class NcgribRecord extends PersistablePluginDataObject implements @DynamicSerializeElement private float[] hybridCoordList; - /** The model information in ncgrib_models child table*/ + /** The model information in ncgrib_models child table */ @ManyToOne(cascade = { CascadeType.REFRESH }, fetch = FetchType.EAGER) @PrimaryKeyJoinColumn @Fetch(FetchMode.SELECT) @@ -190,13 +189,12 @@ public class NcgribRecord extends PersistablePluginDataObject implements private boolean isVector = false; - /** The short model name (i.e.NAM80) This should be interpreted from - * the generating process number and grid id : 96 for gfs, - * 114 for NAEFS, 84 for meso NAM 12KM, 86 for RUC, 81 for GFS analysis, - * 82 for analysis GDAS, etc... - * information form ON388 - table A - * Generating Process or Model from originating center 7 - * which is NCEP + /** + * The short model name (i.e.NAM80) This should be interpreted from the + * generating process number and grid id : 96 for gfs, 114 for NAEFS, 84 for + * meso NAM 12KM, 86 for RUC, 81 for GFS analysis, 82 for analysis GDAS, + * etc... information form ON388 - table A Generating Process or Model from + * originating center 7 which is NCEP */ @Column @XmlAttribute @@ -210,33 +208,35 @@ public class NcgribRecord extends PersistablePluginDataObject implements @DataURI(position = 3) private int gridVersion = 0; - /** The name of ingested file + /** + * The name of ingested file */ @Column @XmlAttribute @DynamicSerializeElement @DataURI(position = 4) private String fileName; - - /** The name of event such as Hurricane or - * Volcano + + /** + * The name of event such as Hurricane or Volcano */ @Column @XmlAttribute @DynamicSerializeElement @DataURI(position = 8) private String eventName; - - /** Type of Generating Process + + /** + * Type of Generating Process */ @Column @XmlAttribute @DynamicSerializeElement @DataURI(position = 7) private int processType; - - /** Resolution and componet flags - * (See Table 3.3) + + /** + * Resolution and componet flags (See Table 3.3) */ @Column @XmlAttribute @@ -244,10 +244,9 @@ public class NcgribRecord extends PersistablePluginDataObject implements private Integer resCompFlags; /** - * Indicate the discipline of the processed - * data contained within a GRIB message - - * 0 for Meteorological products in table 0.0 - * This refers to DIS# in GEMPAK output + * Indicate the discipline of the processed data contained within a GRIB + * message - 0 for Meteorological products in table 0.0 This refers to DIS# + * in GEMPAK output */ @Column @XmlAttribute @@ -255,8 +254,8 @@ public class NcgribRecord extends PersistablePluginDataObject implements private int discipline; /** - * Parameter category by product discipline - * 0 for temperature in table 4.1 by discipline 0 + * Parameter category by product discipline 0 for temperature in table 4.1 + * by discipline 0 */ @Column @XmlAttribute @@ -264,29 +263,27 @@ public class NcgribRecord extends PersistablePluginDataObject implements private int category; /** - * Parameter number by product discipline and parameter category - * 9 for temperature anomaly in table 4.2-0-0 for discipline 0 - * and category 0 - * This refers to ID# in GEMPAK output + * Parameter number by product discipline and parameter category 9 for + * temperature anomaly in table 4.2-0-0 for discipline 0 and category 0 This + * refers to ID# in GEMPAK output */ @Column @XmlAttribute @DynamicSerializeElement private int parameterId; - - /** pdt - Product definition template number. + + /** + * pdt - Product definition template number. */ @Column @XmlAttribute @DynamicSerializeElement private int pdt; - + /** - * Fixed surface types or vertical coordinate ID 1 - * 2 for cloud base level and 100 for isobaric surface - * in table 4.5 or VCRDGRID1.TBL for NCEP - * This refers to VCD# in GEMPAK output - * The location in pds[9] + * Fixed surface types or vertical coordinate ID 1 2 for cloud base level + * and 100 for isobaric surface in table 4.5 or VCRDGRID1.TBL for NCEP This + * refers to VCD# in GEMPAK output The location in pds[9] */ @Column @XmlAttribute @@ -294,11 +291,9 @@ public class NcgribRecord extends PersistablePluginDataObject implements private int vcrdId1; /** - * Fixed surface types or vertical coordinate ID 2 - * 2 for cloud base level and 100 for isobaric surface - * in table 4.5 or VCRDGRID1.TBL for NCEP - * This refers to VCD# in GEMPAK output - * The location in pds[12] + * Fixed surface types or vertical coordinate ID 2 2 for cloud base level + * and 100 for isobaric surface in table 4.5 or VCRDGRID1.TBL for NCEP This + * refers to VCD# in GEMPAK output The location in pds[12] */ @Column @XmlAttribute @@ -306,19 +301,19 @@ public class NcgribRecord extends PersistablePluginDataObject implements private int vcrdId2; /** - * Scaled value of first fixed surface in GRIB2- TEMPLATE 4.1 - * This refers to LEVEL1 in GEMPAK output + * Scaled value of first fixed surface in GRIB2- TEMPLATE 4.1 This refers to + * LEVEL1 in GEMPAK output */ @Column @XmlAttribute @DynamicSerializeElement private int glevel1; - + private float decodedLevel1; /** - * Scaled value of second fixed surface in GRIB2- TEMPLATE 4.1 - * This refers to LEVEL2 in GEMPAK output + * Scaled value of second fixed surface in GRIB2- TEMPLATE 4.1 This refers + * to LEVEL2 in GEMPAK output */ @Column @XmlAttribute @@ -335,7 +330,7 @@ public class NcgribRecord extends PersistablePluginDataObject implements @DynamicSerializeElement @DataURI(position = 6) private String vcord; - + /** * The gempak abbreviation grid name */ @@ -344,7 +339,7 @@ public class NcgribRecord extends PersistablePluginDataObject implements @DynamicSerializeElement @DataURI(position = 5) private String parm; - + /** * The gempak scale for decoding the grid field */ @@ -352,7 +347,7 @@ public class NcgribRecord extends PersistablePluginDataObject implements @XmlAttribute @DynamicSerializeElement private String scale; - + /** * The forecast interval */ @@ -360,7 +355,7 @@ public class NcgribRecord extends PersistablePluginDataObject implements @XmlAttribute @DynamicSerializeElement private int interval; - + /** * Creates an empty NcgribRecord */ @@ -392,7 +387,6 @@ public class NcgribRecord extends PersistablePluginDataObject implements this.insertTime = (Calendar) recordToCopy.insertTime.clone(); } this.messageData = recordToCopy.messageData; - this.pluginName = recordToCopy.pluginName; this.gridVersion = recordToCopy.gridVersion; if (recordToCopy.hybridCoordList != null) { this.hybridCoordList = Arrays.copyOf(recordToCopy.hybridCoordList, @@ -449,10 +443,10 @@ public class NcgribRecord extends PersistablePluginDataObject implements } /** - public void setSpatialObject(NcgridCoverage location) { - modelInfo.setLocation(location); - }*/ - + * public void setSpatialObject(NcgridCoverage location) { + * modelInfo.setLocation(location); } + */ + /** * Gets the model information * @@ -656,7 +650,7 @@ public class NcgribRecord extends PersistablePluginDataObject implements this.gridVersion = gridVersion; } - public Integer getResCompFlags() { + public Integer getResCompFlags() { return resCompFlags; } @@ -665,160 +659,162 @@ public class NcgribRecord extends PersistablePluginDataObject implements } public String getModelName() { - return modelName; - } + return modelName; + } - public void setModelName(String modelName) { - this.modelName = modelName; - } + public void setModelName(String modelName) { + this.modelName = modelName; + } - public int getDiscipline() { - return discipline; - } + public int getDiscipline() { + return discipline; + } - public void setDiscipline(int discipline) { - this.discipline = discipline; - } + public void setDiscipline(int discipline) { + this.discipline = discipline; + } - public int getCategory() { - return category; - } + public int getCategory() { + return category; + } - public void setCategory(int category) { - this.category = category; - } + public void setCategory(int category) { + this.category = category; + } - public int getParameterId() { - return parameterId; - } + public int getParameterId() { + return parameterId; + } - public void setParameterId(int parameterId) { - this.parameterId = parameterId; - } + public void setParameterId(int parameterId) { + this.parameterId = parameterId; + } - public int getPdt() { - return pdt; - } + public int getPdt() { + return pdt; + } - public void setPdt(int pdt) { - this.pdt = pdt; - } + public void setPdt(int pdt) { + this.pdt = pdt; + } - public String getFileName() { - return fileName; - } + public String getFileName() { + return fileName; + } - public void setFileName(String fileName) { - this.fileName = fileName; - } - - public String getEventName() { - return eventName; - } + public void setFileName(String fileName) { + this.fileName = fileName; + } - public void setEventName(String eventName) { - this.eventName = eventName; - } + public String getEventName() { + return eventName; + } - public int getProcessType() { - return processType; - } + public void setEventName(String eventName) { + this.eventName = eventName; + } - public void setProcessType(int processType) { - this.processType = processType; - } - - public int getVcrdId1() { - return vcrdId1; - } + public int getProcessType() { + return processType; + } - public void setVcrdId1(int vcrdId1) { - this.vcrdId1 = vcrdId1; - } + public void setProcessType(int processType) { + this.processType = processType; + } - public int getVcrdId2() { - return vcrdId2; - } + public int getVcrdId1() { + return vcrdId1; + } - public void setVcrdId2(int vcrdId2) { - this.vcrdId2 = vcrdId2; - } + public void setVcrdId1(int vcrdId1) { + this.vcrdId1 = vcrdId1; + } - public int getGlevel1() { - return glevel1; - } + public int getVcrdId2() { + return vcrdId2; + } - public void setGlevel1(int glevel1) { - this.glevel1 = glevel1; - } + public void setVcrdId2(int vcrdId2) { + this.vcrdId2 = vcrdId2; + } - public int getGlevel2() { - return glevel2; - } + public int getGlevel1() { + return glevel1; + } - public void setGlevel2(int glevel2) { - this.glevel2 = glevel2; - } + public void setGlevel1(int glevel1) { + this.glevel1 = glevel1; + } - public String getVcord() { - return vcord; - } + public int getGlevel2() { + return glevel2; + } - public void setVcord(String vcord) { - this.vcord = vcord; - } + public void setGlevel2(int glevel2) { + this.glevel2 = glevel2; + } - public String getParm() { - return parm; - } + public String getVcord() { + return vcord; + } - public void setParm(String parm) { - this.parm = parm; - } + public void setVcord(String vcord) { + this.vcord = vcord; + } - public String getScale() { - return scale; - } + public String getParm() { + return parm; + } - public void setScale(String scale) { - this.scale = scale; - } + public void setParm(String parm) { + this.parm = parm; + } - public int getInterval() { - return interval; - } + public String getScale() { + return scale; + } - public void setInterval(int interval) { - this.interval = interval; - } + public void setScale(String scale) { + this.scale = scale; + } - /** - * @return the decodedLevel1 - */ - public float getDecodedLevel1() { - return decodedLevel1; - } + public int getInterval() { + return interval; + } - /** - * @param decodedLevel1 the decodedLevel1 to set - */ - public void setDecodedLevel1(float decodedLevel1) { - this.decodedLevel1 = decodedLevel1; - } + public void setInterval(int interval) { + this.interval = interval; + } - /** - * @return the decodedLevel2 - */ - public float getDecodedLevel2() { - return decodedLevel2; - } + /** + * @return the decodedLevel1 + */ + public float getDecodedLevel1() { + return decodedLevel1; + } - /** - * @param decodedLevel2 the decodedLevel2 to set - */ - public void setDecodedLevel2(float decodedLevel2) { - this.decodedLevel2 = decodedLevel2; - } + /** + * @param decodedLevel1 + * the decodedLevel1 to set + */ + public void setDecodedLevel1(float decodedLevel1) { + this.decodedLevel1 = decodedLevel1; + } + + /** + * @return the decodedLevel2 + */ + public float getDecodedLevel2() { + return decodedLevel2; + } + + /** + * @param decodedLevel2 + * the decodedLevel2 to set + */ + public void setDecodedLevel2(float decodedLevel2) { + this.decodedLevel2 = decodedLevel2; + } @Override @Column @@ -827,4 +823,8 @@ public class NcgribRecord extends PersistablePluginDataObject implements return super.getDataURI(); } + @Override + public String getPluginName() { + return "ncgrib"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncpafm/src/gov/noaa/nws/ncep/common/dataplugin/ncpafm/NcPafmRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncpafm/src/gov/noaa/nws/ncep/common/dataplugin/ncpafm/NcPafmRecord.java index 5bcb47b33f..1063ca2c1b 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncpafm/src/gov/noaa/nws/ncep/common/dataplugin/ncpafm/NcPafmRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncpafm/src/gov/noaa/nws/ncep/common/dataplugin/ncpafm/NcPafmRecord.java @@ -1,24 +1,3 @@ -/* - * - * NcPafmRecord - * - * This class performs the mapping to the database tables for the Point/Area - * Forecast Matrices (PAFM) Decoder Plug-In - * - * SOFTWARE HISTORY - * Date Ticket# Engineer Description - * ------------ ----------- -------------- ----------------------------------- - * 08/05/2009 126 F. J. Yen Initial creation - * 01/06/2010 126 F. J. Yen Migrated and refactored from to11dr3 to to11dr11 - * * - * This code has been developed by the SIB for use in the AWIPS2 system. - * - * - * @author F. J. Yen, SIB - * @version 1 - - */ - package gov.noaa.nws.ncep.common.dataplugin.ncpafm; import java.util.Calendar; @@ -61,25 +40,33 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description + * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 30 Sep 2011 126 B. Hebbard Initial version in refactored NcPafm decoder. - * This new (fine-grain) PDO contains data associated - * with one location / forecast hour pair only, for - * efficiency of retrieval. It also implements - * IPointData -- that is, presents a PointDataView - * object suitable for HDF5 persistence. - * 10 Oct 2011 126 G. Hull replace stnid,lat&lon with the SurfaceObsLocation. - * 03 Feb 2012 606 G. Hull added reportType to the URI for inventory updating - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 08 Apr 2013 1293 bkowal Removed references to hdffileid. + * Aug 05, 2009 126 F. J. Yen Initial creation + * Jan 06, 2010 126 F. J. Yen Migrated and refactored from to11dr3 to + * to11dr11 + * 30 Sep 2011 126 B. Hebbard Initial version in refactored NcPafm + * decoder. This new (fine-grain) PDO + * contains data associated with one + * location / forecast hour pair only, for + * efficiency of retrieval. It also + * implements IPointData -- that is, + * presents a PointDataView object suitable + * for HDF5 persistence. + * 10 Oct 2011 126 G. Hull replace stnid,lat&lon with the + * SurfaceObsLocation. + * 03 Feb 2012 606 G. Hull added reportType to the URI for inventory + * updating + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * 08 Apr 2013 1293 bkowal Removed references to hdffileid. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. - * + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * - * @author B. Hebbard, SIB + * @author F. J. Yen, SIB * @version 1.0 */ @Entity @@ -89,326 +76,323 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ncpafm", - indexes = { - @Index(name = "ncpafm_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ncpafm", indexes = { @Index(name = "ncpafm_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class NcPafmRecord extends PersistablePluginDataObject implements // TODO: Make absolutely sure these are NO LONGER required... ISpatialEnabled, // IDecoderGettable, - IPointData, IPersistable { + IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - /** Report type */ - @Column(length = 32) - @DataURI(position=6) - @XmlElement - @DynamicSerializeElement - private String reportType; + /** Report type */ + @Column(length = 32) + @DataURI(position = 6) + @XmlElement + @DynamicSerializeElement + private String reportType; - // WMO header - @DataURI(position = 4) - @Column(length = 32) - @XmlElement - @DynamicSerializeElement - private String wmoHeader; + // WMO header + @DataURI(position = 4) + @Column(length = 32) + @XmlElement + @DynamicSerializeElement + private String wmoHeader; - // The issue office where the report from - @Column(length = 32) - @DataURI(position = 1) - @XmlElement - @DynamicSerializeElement - private String issueOffice; + // The issue office where the report from + @Column(length = 32) + @DataURI(position = 1) + @XmlElement + @DynamicSerializeElement + private String issueOffice; - @Column - @DataURI(position = 2) - @DynamicSerializeElement - @XmlElement - private Calendar issueTime; + @Column + @DataURI(position = 2) + @DynamicSerializeElement + @XmlElement + private Calendar issueTime; - // The stationId here is the FIPS code and not the issuing office - @Embedded - @DataURI(position = 3, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; + // The stationId here is the FIPS code and not the issuing office + @Embedded + @DataURI(position = 3, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String designatorBBB; + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String designatorBBB; - // The mndTime - @Column(length = 72) - @XmlElement - @DynamicSerializeElement - private String mndTime; + // The mndTime + @Column(length = 72) + @XmlElement + @DynamicSerializeElement + private String mndTime; - /** Matrix type */ - @DataURI(position = 5) - @Column(length = 32) - @XmlElement - @DynamicSerializeElement - private String matrixType; + /** Matrix type */ + @DataURI(position = 5) + @Column(length = 32) + @XmlElement + @DynamicSerializeElement + private String matrixType; - // The universal geographic code - @Column(length = 640) - @XmlElement - @DynamicSerializeElement - private String ugc; + // The universal geographic code + @Column(length = 640) + @XmlElement + @DynamicSerializeElement + private String ugc; - // The product purge time - @XmlElement - @DynamicSerializeElement - private Calendar prodPurgeTime; + // The product purge time + @XmlElement + @DynamicSerializeElement + private Calendar prodPurgeTime; - // Text information for this segment - // @Column(length=12000) - // @XmlElement - // @DynamicSerializeElement - private String segment; + // Text information for this segment + // @Column(length=12000) + // @XmlElement + // @DynamicSerializeElement + private String segment; - // // The county FIPS : this is the stationId in the SurfaceObsLocation - // @Column(length=16) - // @XmlElement - // @DynamicSerializeElement - // private String fips; + // // The county FIPS : this is the stationId in the SurfaceObsLocation + // @Column(length=16) + // @XmlElement + // @DynamicSerializeElement + // private String fips; - // The group of parameter values associated with the above combination. - @Transient - private NcPafmParameters pafmParms; + // The group of parameter values associated with the above combination. + @Transient + private NcPafmParameters pafmParms; - // The PointDataView representation of data associated with this PDO - // to be persisted as HDF5 - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + // The PointDataView representation of data associated with this PDO + // to be persisted as HDF5 + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - /** - * Default Constructor - */ - public NcPafmRecord() { - this.location = null; - this.issueOffice = null; - this.reportType = "PAFM"; - this.matrixType = " "; - this.issueTime = null; - this.wmoHeader = null; - this.designatorBBB = " "; - this.mndTime = null; - } + /** + * Default Constructor + */ + public NcPafmRecord() { + this.location = null; + this.issueOffice = null; + this.reportType = "PAFM"; + this.matrixType = " "; + this.issueTime = null; + this.wmoHeader = null; + this.designatorBBB = " "; + this.mndTime = null; + } - /** - * Constructs a pafm record from a dataURI - * - * @param uri - * The dataURI - */ - public NcPafmRecord(String uri) { - super(uri); - } + /** + * Constructs a pafm record from a dataURI + * + * @param uri + * The dataURI + */ + public NcPafmRecord(String uri) { + super(uri); + } - @Override - public IDecoderGettable getDecoderGettable() { - // TODO Auto-generated method stub - return null; - } + @Override + public IDecoderGettable getDecoderGettable() { + // TODO Auto-generated method stub + return null; + } - public String getReportType() { - return reportType; - } + public String getReportType() { + return reportType; + } - public void setReportType(String reportType) { - this.reportType = reportType; - } + public void setReportType(String reportType) { + this.reportType = reportType; + } - public String getMatrixType() { - return matrixType; - } + public String getMatrixType() { + return matrixType; + } - public void setMatrixType(String matrixType) { - this.matrixType = matrixType; - } + public void setMatrixType(String matrixType) { + this.matrixType = matrixType; + } - public String getWmoHeader() { - return wmoHeader; - } + public String getWmoHeader() { + return wmoHeader; + } - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - public String getIssueOffice() { - return issueOffice; - } + public String getIssueOffice() { + return issueOffice; + } - public void setIssueOffice(String issueOffice) { - this.issueOffice = issueOffice; - } + public void setIssueOffice(String issueOffice) { + this.issueOffice = issueOffice; + } - public Calendar getIssueTime() { - return issueTime; - } + public Calendar getIssueTime() { + return issueTime; + } - public void setIssueTime(Calendar issueTime) { - this.issueTime = issueTime; - } + public void setIssueTime(Calendar issueTime) { + this.issueTime = issueTime; + } - public String getDesignatorBBB() { - return designatorBBB; - } + public String getDesignatorBBB() { + return designatorBBB; + } - public void setDesignatorBBB(String designatorBBB) { - this.designatorBBB = designatorBBB; - } + public void setDesignatorBBB(String designatorBBB) { + this.designatorBBB = designatorBBB; + } - public String getMndTime() { - return mndTime; - } + public String getMndTime() { + return mndTime; + } - public void setMndTime(String mndTime) { - this.mndTime = mndTime; - } + public void setMndTime(String mndTime) { + this.mndTime = mndTime; + } - /** - * @return the ugc - */ - public String getUgc() { - return ugc; - } + /** + * @return the ugc + */ + public String getUgc() { + return ugc; + } - /** - * @param ugc - * to set - */ - public void setUgc(String ugc) { - this.ugc = ugc; - } + /** + * @param ugc + * to set + */ + public void setUgc(String ugc) { + this.ugc = ugc; + } - /** - * @return the prodPurgeTime - */ - public Calendar getProdPurgeTime() { - return prodPurgeTime; - } + /** + * @return the prodPurgeTime + */ + public Calendar getProdPurgeTime() { + return prodPurgeTime; + } - /** - * @param prodPurgeTime - * to set - */ - public void setProdPurgeTime(Calendar prodPurgeTime) { - this.prodPurgeTime = prodPurgeTime; - } + /** + * @param prodPurgeTime + * to set + */ + public void setProdPurgeTime(Calendar prodPurgeTime) { + this.prodPurgeTime = prodPurgeTime; + } - /** - * @return the segment - */ - public String getSegment() { - return segment; - } + /** + * @return the segment + */ + public String getSegment() { + return segment; + } - /** - * @param segment - * to set - */ - public void setSegment(String segment) { - this.segment = segment; - } + /** + * @param segment + * to set + */ + public void setSegment(String segment) { + this.segment = segment; + } - // public String getFips() { - // return fips; - // } + // public String getFips() { + // return fips; + // } - public String getStationId() { - return location.getStationId(); - } + public String getStationId() { + return location.getStationId(); + } - // if this needs to be an ISpatialObject - // @Override - // public SurfaceObsLocation getSpatialObject() { - // return location; - // } + // if this needs to be an ISpatialObject + // @Override + // public SurfaceObsLocation getSpatialObject() { + // return location; + // } - public SurfaceObsLocation getLocation() { - return location; - } + public SurfaceObsLocation getLocation() { + return location; + } - public void setLocation(SurfaceObsLocation obsLoc) { - this.location = obsLoc; - } + public void setLocation(SurfaceObsLocation obsLoc) { + this.location = obsLoc; + } - public double getLatitude() { - return location.getLatitude(); - } + public double getLatitude() { + return location.getLatitude(); + } - public double getLongitude() { - return location.getLongitude(); - } + public double getLongitude() { + return location.getLongitude(); + } - public Integer getElevation() { - return location.getElevation(); - } + public Integer getElevation() { + return location.getElevation(); + } - // public void setFips(String fips) { - // this.fips = fips; - // } + // public void setFips(String fips) { + // this.fips = fips; + // } - /** - * @return the set of Parameters - */ - public NcPafmParameters getPafmParms() { - return pafmParms; - } + /** + * @return the set of Parameters + */ + public NcPafmParameters getPafmParms() { + return pafmParms; + } - /** - * @param pafmParameters - * -the set of Parmameters to set - */ - public void setPafmParms(NcPafmParameters pafmParams) { - this.pafmParms = pafmParams; - } + /** + * @param pafmParameters + * -the set of Parmameters to set + */ + public void setPafmParms(NcPafmParameters pafmParams) { + this.pafmParms = pafmParams; + } - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() - */ - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() + */ + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon - * .uf.common.pointdata.PointDataView) - */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon + * .uf.common.pointdata.PointDataView) + */ + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } - @Override - public Date getPersistenceTime() { - // return this.dataTime.getRefTime(); - return null; - } + @Override + public Date getPersistenceTime() { + // return this.dataTime.getRefTime(); + return null; + } - /** - * Override existing set method to modify any classes that use the dataURI - * as a foreign key - */ - public void setIdentifier(Object dataURI) { - this.identifier = dataURI; - } + /** + * Override existing set method to modify any classes that use the dataURI + * as a foreign key + */ + @Override + public void setIdentifier(Object dataURI) { + this.identifier = dataURI; + } @Override @Column @@ -417,4 +401,8 @@ public class NcPafmRecord extends PersistablePluginDataObject implements return super.getDataURI(); } + @Override + public String getPluginName() { + return "ncpafm"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncpirep/src/gov/noaa/nws/ncep/common/dataplugin/ncpirep/NcPirepRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncpirep/src/gov/noaa/nws/ncep/common/dataplugin/ncpirep/NcPirepRecord.java index 26d211133e..606409d6b6 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncpirep/src/gov/noaa/nws/ncep/common/dataplugin/ncpirep/NcPirepRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncpirep/src/gov/noaa/nws/ncep/common/dataplugin/ncpirep/NcPirepRecord.java @@ -60,17 +60,22 @@ import com.vividsolutions.jts.geom.Geometry; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 20110421 F. J. Yen Initial creation from Raytheon's pirep. - * Change temp, windSpeed from Double to Float. - * Change windDirection from Integer to Float - * 08/30/2011 286 qzhou Use IDecoderConstantsN.INTEGER_MISSING instead -9999 in visibility. - * 08/31/2011 286 qzhou Created project and moved this from ~edex.plugin.pirep - * 09/19/2011 286 Q.Zhou Changed reportType to string, - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 04/08/2013 1293 bkowal Removed references to hdffileid. - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Apr 21, 2011 F. J. Yen Initial creation from Raytheon's pirep. + * Change temp, windSpeed from Double to + * Float. Change windDirection from Integer + * to Float + * Aug 30, 2011 286 qzhou Use IDecoderConstantsN.INTEGER_MISSING + * instead -9999 in visibility. + * Aug 31, 2011 286 qzhou Created project and moved this from + * ~edex.plugin.pirep + * Sep 19, 2011 286 Q.Zhou Changed reportType to string, + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -84,764 +89,764 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ncpirep", - indexes = { - @Index(name = "ncpirep_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ncpirep", indexes = { @Index(name = "ncpirep_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class NcPirepRecord extends PluginDataObject implements ISpatialEnabled, - IDecoderGettable, IPointData, IPersistable { + IDecoderGettable, IPointData, IPersistable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public static final Unit TEMPERATURE_UNIT = SI.CELSIUS; + public static final Unit TEMPERATURE_UNIT = SI.CELSIUS; - public static final Unit ALTITUDE_UNIT = NonSI.FOOT; + public static final Unit ALTITUDE_UNIT = NonSI.FOOT; - public static final Unit WIND_SPEED_UNIT = NonSI.KNOT; + public static final Unit WIND_SPEED_UNIT = NonSI.KNOT; - public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit WIND_DIR_UNIT = NonSI.DEGREE_ANGLE; - public static final Unit PRESSURE_UNIT = SI.PASCAL; + public static final Unit PRESSURE_UNIT = SI.PASCAL; - public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; + public static final Unit LOCATION_UNIT = NonSI.DEGREE_ANGLE; - private static final HashMap PARM_MAP = new HashMap(); - private static final HashMap ICING_MAP = new HashMap(); - private static final HashMap TURB_MAP = new HashMap(); - static { - PARM_MAP.put("T", SFC_TEMP); - PARM_MAP.put("WS", SFC_WNDSPD); - PARM_MAP.put("WD", SFC_WNDDIR); - PARM_MAP.put("NLAT", STA_LAT); - PARM_MAP.put("NLON", STA_LON); - PARM_MAP.put("FLT_LVL", UA_FLTLVL); - PARM_MAP.put("ICT", UA_ICETYPE); - PARM_MAP.put("ICI", UA_ICEINTENSE); - PARM_MAP.put("TBF", UA_TURBFREQ); - PARM_MAP.put("TBI", UA_TURBINTENSE); - PARM_MAP.put("TOP_HGT", UA_TOPHGT); - PARM_MAP.put("BOT_HGT", UA_BOTHGT); + private static final HashMap PARM_MAP = new HashMap(); - ICING_MAP.put("", new Integer(0)); - ICING_MAP.put("NEG", new Integer(1)); - ICING_MAP.put("TRACE", new Integer(2)); - ICING_MAP.put("TRACELGT", new Integer(3)); - ICING_MAP.put("LGT", new Integer(4)); - ICING_MAP.put("LGTMOD", new Integer(5)); - ICING_MAP.put("MOD", new Integer(6)); - ICING_MAP.put("MODSEV", new Integer(7)); - ICING_MAP.put("SEV", new Integer(8)); + private static final HashMap ICING_MAP = new HashMap(); - TURB_MAP.put("", new Integer(0)); - TURB_MAP.put("NEG", new Integer(1)); - TURB_MAP.put("SMOOTHLGT", new Integer(2)); - TURB_MAP.put("LGT", new Integer(3)); - TURB_MAP.put("LGTMOD", new Integer(4)); - TURB_MAP.put("MOD", new Integer(5)); - TURB_MAP.put("MODSEV", new Integer(6)); - TURB_MAP.put("SEV", new Integer(7)); - TURB_MAP.put("EXTRM", new Integer(8)); - } + private static final HashMap TURB_MAP = new HashMap(); + static { + PARM_MAP.put("T", SFC_TEMP); + PARM_MAP.put("WS", SFC_WNDSPD); + PARM_MAP.put("WD", SFC_WNDDIR); + PARM_MAP.put("NLAT", STA_LAT); + PARM_MAP.put("NLON", STA_LON); + PARM_MAP.put("FLT_LVL", UA_FLTLVL); + PARM_MAP.put("ICT", UA_ICETYPE); + PARM_MAP.put("ICI", UA_ICEINTENSE); + PARM_MAP.put("TBF", UA_TURBFREQ); + PARM_MAP.put("TBI", UA_TURBINTENSE); + PARM_MAP.put("TOP_HGT", UA_TOPHGT); + PARM_MAP.put("BOT_HGT", UA_BOTHGT); - @Transient - private NcPirepLayerData maxPirepLayerData = null; + ICING_MAP.put("", new Integer(0)); + ICING_MAP.put("NEG", new Integer(1)); + ICING_MAP.put("TRACE", new Integer(2)); + ICING_MAP.put("TRACELGT", new Integer(3)); + ICING_MAP.put("LGT", new Integer(4)); + ICING_MAP.put("LGTMOD", new Integer(5)); + ICING_MAP.put("MOD", new Integer(6)); + ICING_MAP.put("MODSEV", new Integer(7)); + ICING_MAP.put("SEV", new Integer(8)); - @Transient - private boolean display = true; + TURB_MAP.put("", new Integer(0)); + TURB_MAP.put("NEG", new Integer(1)); + TURB_MAP.put("SMOOTHLGT", new Integer(2)); + TURB_MAP.put("LGT", new Integer(3)); + TURB_MAP.put("LGTMOD", new Integer(4)); + TURB_MAP.put("MOD", new Integer(5)); + TURB_MAP.put("MODSEV", new Integer(6)); + TURB_MAP.put("SEV", new Integer(7)); + TURB_MAP.put("EXTRM", new Integer(8)); + } - @Transient - @XmlAttribute - @DynamicSerializeElement - private Integer obsId; + @Transient + private NcPirepLayerData maxPirepLayerData = null; - // Time of the observation. - @Transient - @XmlAttribute - @DynamicSerializeElement - private Calendar timeObs; + @Transient + private boolean display = true; - // Time of the observation to the nearest hour. - @Column - @XmlElement - @DynamicSerializeElement - private Calendar refHour; + @Transient + @XmlAttribute + @DynamicSerializeElement + private Integer obsId; - // - @Column(length = 8) - @DataURI(position = 1) - @XmlAttribute - @DynamicSerializeElement - private String reportType; + // Time of the observation. + @Transient + @XmlAttribute + @DynamicSerializeElement + private Calendar timeObs; - // Text of the WMO header - @Transient - @XmlElement - @DynamicSerializeElement - private String wmoHeader; + // Time of the observation to the nearest hour. + @Column + @XmlElement + @DynamicSerializeElement + private Calendar refHour; - @Transient - @DynamicSerializeElement - @XmlElement - private String suspectTimeFlag; + // + @Column(length = 8) + @DataURI(position = 1) + @XmlAttribute + @DynamicSerializeElement + private String reportType; - // Correction indicator from wmo header - @Column(length = 8) - @DataURI(position = 2) - @XmlElement - @DynamicSerializeElement - private String corIndicator; + // Text of the WMO header + @Transient + @XmlElement + @DynamicSerializeElement + private String wmoHeader; - @Transient - @XmlElement - @DynamicSerializeElement - private String aircraftType; + @Transient + @DynamicSerializeElement + @XmlElement + private String suspectTimeFlag; - // Observation air temperature in degrees Celsius, if not converted. - // Observation air temperature in degrees Kelvin. - // Decimal(5,2) - @Transient - @XmlElement - @DynamicSerializeElement - // private Double temp; - private Float temp; + // Correction indicator from wmo header + @Column(length = 8) + @DataURI(position = 2) + @XmlElement + @DynamicSerializeElement + private String corIndicator; - // Observation wind direction in angular degrees. Integer - @Transient - @XmlElement - @DynamicSerializeElement - // private Integer windDirection; - private Float windDirection; + @Transient + @XmlElement + @DynamicSerializeElement + private String aircraftType; - // Observation wind speed in knots, if not converted. - // Observation wind speed in meters per second. - // Decimal(5,2) - @Transient - @XmlElement - @DynamicSerializeElement - // private Double windSpeed; - private Float windSpeed; + // Observation air temperature in degrees Celsius, if not converted. + // Observation air temperature in degrees Kelvin. + // Decimal(5,2) + @Transient + @XmlElement + @DynamicSerializeElement + // private Double temp; + private Float temp; - @Transient - @XmlElement - @DynamicSerializeElement - // private Integer horzVisibility; - private Integer horzVisibility = IDecoderConstantsN.INTEGER_MISSING; // -9999 + // Observation wind direction in angular degrees. Integer + @Transient + @XmlElement + @DynamicSerializeElement + // private Integer windDirection; + private Float windDirection; - @Transient - @XmlElement - @DynamicSerializeElement - private String obsText; + // Observation wind speed in knots, if not converted. + // Observation wind speed in meters per second. + // Decimal(5,2) + @Transient + @XmlElement + @DynamicSerializeElement + // private Double windSpeed; + private Float windSpeed; - // @Column(length = 16) - @Transient - @XmlElement - @DynamicSerializeElement - private String weatherGroup; + @Transient + @XmlElement + @DynamicSerializeElement + // private Integer horzVisibility; + private Integer horzVisibility = IDecoderConstantsN.INTEGER_MISSING; // -9999 - @DynamicSerializeElement - @XmlElement - // @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = - // FetchType.EAGER) - // private Set ancPirepData; - @Transient - private Set ancPirepData = new HashSet(); + @Transient + @XmlElement + @DynamicSerializeElement + private String obsText; - @Embedded - @DataURI(position = 3, embedded = true) - @XmlElement - @DynamicSerializeElement - private AircraftObsLocation location; + // @Column(length = 16) + @Transient + @XmlElement + @DynamicSerializeElement + private String weatherGroup; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + @DynamicSerializeElement + @XmlElement + // @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = + // FetchType.EAGER) + // private Set ancPirepData; + @Transient + private Set ancPirepData = new HashSet(); - /** + @Embedded + @DataURI(position = 3, embedded = true) + @XmlElement + @DynamicSerializeElement + private AircraftObsLocation location; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + /** * */ - public NcPirepRecord() { - } + public NcPirepRecord() { + } - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public NcPirepRecord(String uri) { - super(uri); - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public NcPirepRecord(String uri) { + super(uri); + } - public Integer getObsId() { - return obsId; - } + public Integer getObsId() { + return obsId; + } - public void setObsId(Integer obsId) { - this.obsId = obsId; - } + public void setObsId(Integer obsId) { + this.obsId = obsId; + } - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } - /** - * Get the report correction indicator. - * - * @return The corIndicator - */ - public String getCorIndicator() { - return corIndicator; - } + /** + * Get the report correction indicator. + * + * @return The corIndicator + */ + public String getCorIndicator() { + return corIndicator; + } - /** - * Set the report correction indicator. - * - * @param corIndicator - * The corIndicator. - */ - public void setCorIndicator(String corIndicator) { - this.corIndicator = corIndicator; - } + /** + * Set the report correction indicator. + * + * @param corIndicator + * The corIndicator. + */ + public void setCorIndicator(String corIndicator) { + this.corIndicator = corIndicator; + } - /** - * Get the report data for this observation. - * - * @return The Report data. - */ - public String getReportData() { - String s = null; - if (messageData instanceof String) { - s = (String) messageData; - } - return s; - } + /** + * Get the report data for this observation. + * + * @return The Report data. + */ + public String getReportData() { + String s = null; + if (messageData instanceof String) { + s = (String) messageData; + } + return s; + } - /** - * Set the report data for this observation. - * - * @param reportData - * The Report data. - */ - public void setReportData(String reportData) { - messageData = reportData; - } + /** + * Set the report data for this observation. + * + * @param reportData + * The Report data. + */ + public void setReportData(String reportData) { + messageData = reportData; + } - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } - /** - * Is the location defined in the spatial tables. - * - * @return Is the location defined in the spatial tables. - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } + /** + * Is the location defined in the spatial tables. + * + * @return Is the location defined in the spatial tables. + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } - /** - * // * Get the elevation, in meters, of the observing platform or location. - * Get the elevation, in feet, of the observing platform or location. - * - * // * @return The observation elevation, in meters. - * - * @return The observation elevation, in feet. - */ - public Integer getFlightLevel() { - return location.getFlightLevel(); - } + /** + * Get the elevation, in feet, of the observing platform or location. + * + * @return The observation elevation, in feet. + */ + public Integer getFlightLevel() { + return location.getFlightLevel(); + } - /** - * @return the reportType - */ - public String getReportType() { - return reportType; - } + /** + * @return the reportType + */ + public String getReportType() { + return reportType; + } - /** - * @param reportType - * the reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } + /** + * @param reportType + * the reportType to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } - /** - * @return the timeObs - */ - public Calendar getTimeObs() { - if (this.dataTime == null) - return null; - return this.dataTime.getRefTimeAsCalendar(); - } + /** + * @return the timeObs + */ + public Calendar getTimeObs() { + if (this.dataTime == null) { + return null; + } + return this.dataTime.getRefTimeAsCalendar(); + } - /** - * @param timeObs - * the timeObs to set - */ - public void setTimeObs(Calendar timeObs) { - this.timeObs = timeObs; - } + /** + * @param timeObs + * the timeObs to set + */ + public void setTimeObs(Calendar timeObs) { + this.timeObs = timeObs; + } - /** - * @return the refHour - */ - public Calendar getRefHour() { - return refHour; - } + /** + * @return the refHour + */ + public Calendar getRefHour() { + return refHour; + } - /** - * @param refHour - * the refHour to set - */ - public void setRefHour(Calendar refHour) { - this.refHour = refHour; - } + /** + * @param refHour + * the refHour to set + */ + public void setRefHour(Calendar refHour) { + this.refHour = refHour; + } - public String getSuspectTimeFlag() { - return suspectTimeFlag; - } + public String getSuspectTimeFlag() { + return suspectTimeFlag; + } - public void setSuspectTimeFlag(String suspectTimeFlag) { - this.suspectTimeFlag = suspectTimeFlag; - } + public void setSuspectTimeFlag(String suspectTimeFlag) { + this.suspectTimeFlag = suspectTimeFlag; + } - /** - * @param aircraftType - * the aircraftType to set - */ - public void setAircraftType(String aircraftType) { - this.aircraftType = aircraftType; - } + /** + * @param aircraftType + * the aircraftType to set + */ + public void setAircraftType(String aircraftType) { + this.aircraftType = aircraftType; + } - /** - * @return the aircraftType - */ - public String getAircraftType() { - return aircraftType; - } + /** + * @return the aircraftType + */ + public String getAircraftType() { + return aircraftType; + } - /** - * @return the temp - */ - // public Double getTemp() { - public float getTemp() { - return temp; - } + /** + * @return the temp + */ + // public Double getTemp() { + public float getTemp() { + return temp; + } - /** - * @param temp - * the temp to set - */ - // public void setTemp(Double temp) { - public void setTemp(float temp) { - this.temp = temp; - } + /** + * @param temp + * the temp to set + */ + // public void setTemp(Double temp) { + public void setTemp(float temp) { + this.temp = temp; + } - /** - * @return the windDirection - */ - // public Integer getWindDirection() { - public float getWindDirection() { - return windDirection; - } + /** + * @return the windDirection + */ + // public Integer getWindDirection() { + public float getWindDirection() { + return windDirection; + } - /** - * @param windDirection - * the windDirection to set - */ - // public void setWindDirection(Integer windDirection) { - public void setWindDirection(float windDirection) { - this.windDirection = windDirection; - } + /** + * @param windDirection + * the windDirection to set + */ + // public void setWindDirection(Integer windDirection) { + public void setWindDirection(float windDirection) { + this.windDirection = windDirection; + } - /** - * @return the windspeed - */ - // public Double getWindSpeed() { - public float getWindSpeed() { - return windSpeed; - } + /** + * @return the windspeed + */ + // public Double getWindSpeed() { + public float getWindSpeed() { + return windSpeed; + } - /** - * @param windspeed - * the windspeed to set - */ - // public void setWindSpeed(Double windSpeed) { - public void setWindSpeed(float windSpeed) { - this.windSpeed = windSpeed; - } + /** + * @param windspeed + * the windspeed to set + */ + // public void setWindSpeed(Double windSpeed) { + public void setWindSpeed(float windSpeed) { + this.windSpeed = windSpeed; + } - /** - * @return the horzVisibility - */ - public Integer getHorzVisibility() { - return horzVisibility; - } + /** + * @return the horzVisibility + */ + public Integer getHorzVisibility() { + return horzVisibility; + } - /** - * @param horzVisibility - * the horzVisibility to set - */ - public void setHorzVisibility(Integer horzVisibility) { - this.horzVisibility = horzVisibility; - } + /** + * @param horzVisibility + * the horzVisibility to set + */ + public void setHorzVisibility(Integer horzVisibility) { + this.horzVisibility = horzVisibility; + } - /** - * @return the obsText - */ - public String getObsText() { - return obsText; - } + /** + * @return the obsText + */ + public String getObsText() { + return obsText; + } - /** - * @param obsText - * the obsText to set - */ - public void setObsText(String obsText) { - this.obsText = obsText; - } + /** + * @param obsText + * the obsText to set + */ + public void setObsText(String obsText) { + this.obsText = obsText; + } - /** - * @return the weatherGroup - */ - public String getWeatherGroup() { - return weatherGroup; - } + /** + * @return the weatherGroup + */ + public String getWeatherGroup() { + return weatherGroup; + } - /** - * @param weatherGroup - * the weatherGroup to set - */ - public void setWeatherGroup(String weatherGroup) { - this.weatherGroup = weatherGroup; - } + /** + * @param weatherGroup + * the weatherGroup to set + */ + public void setWeatherGroup(String weatherGroup) { + this.weatherGroup = weatherGroup; + } - /** - * @return the ancPirepData - */ - public Set getAncPirepData() { - return ancPirepData; - } + /** + * @return the ancPirepData + */ + public Set getAncPirepData() { + return ancPirepData; + } - /** - * @param ancPirepData - * the ancPirepData to set - */ - public void setAncPirepData(Set ancPirepData) { - this.ancPirepData = ancPirepData; - } + /** + * @param ancPirepData + * the ancPirepData to set + */ + public void setAncPirepData(Set ancPirepData) { + this.ancPirepData = ancPirepData; + } - /** - * - * @param cloud - */ - public void addLayer(NcPirepLayerData layer) { - layer.setParent(this); - if (ancPirepData == null) { - ancPirepData = new HashSet(); - } - ancPirepData.add(layer); - } + /** + * + * @param cloud + */ + public void addLayer(NcPirepLayerData layer) { + layer.setParent(this); + if (ancPirepData == null) { + ancPirepData = new HashSet(); + } + ancPirepData.add(layer); + } - @Override - public void setDataURI(String dataURI) { - identifier = dataURI; - } + @Override + public void setDataURI(String dataURI) { + identifier = dataURI; + } - /** - * Get the IDecoderGettable reference for this record. - * - * @return The IDecoderGettable reference for this record. - */ - @Override - public IDecoderGettable getDecoderGettable() { - return this; - } + /** + * Get the IDecoderGettable reference for this record. + * + * @return The IDecoderGettable reference for this record. + */ + @Override + public IDecoderGettable getDecoderGettable() { + return this; + } - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public String getString(String paramName) { - String retData = null; - if ("STA".matches(paramName)) { - retData = getStationId(); - } else if ("TEXT".equals(paramName)) { - retData = obsText; - } - return retData; - } + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public String getString(String paramName) { + String retData = null; + if ("STA".matches(paramName)) { + retData = getStationId(); + } else if ("TEXT".equals(paramName)) { + retData = obsText; + } + return retData; + } - /** - * Get the value and units of a named parameter within this observation. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return An Amount with value and units. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Amount getValue(String paramName) { - Amount a = null; + /** + * Get the value and units of a named parameter within this observation. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return An Amount with value and units. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Amount getValue(String paramName) { + Amount a = null; - String pName = PARM_MAP.get(paramName); - if (display) { - if (SFC_TEMP.equals(pName) && (temp != null)) { - a = new Amount(temp, TEMPERATURE_UNIT); - } else if (SFC_WNDSPD.equals(pName) && (windSpeed != null)) { - a = new Amount(windSpeed, WIND_SPEED_UNIT); - } else if (SFC_WNDDIR.equals(pName) && (windDirection != null)) { - a = new Amount(windDirection, WIND_DIR_UNIT); - } else if (STA_LAT.equals(pName)) { - a = new Amount(this.getLatitude(), LOCATION_UNIT); - } else if (STA_LON.equals(pName)) { - a = new Amount(this.getLongitude(), LOCATION_UNIT); - } else if (UA_FLTLVL.equals(pName) && getFlightLevel() != null) { - a = new Amount(this.getFlightLevel().intValue(), ALTITUDE_UNIT); - // if used, need to modify raytheon code - // } else if (UA_TOPHGT.equals(pName) && maxPirepLayerData != - // null - // && maxPirepLayerData.getTopLayerHeight() != null) { - // a = new - // Amount(maxPirepLayerData.getTopLayerHeight().intValue(), - // ALTITUDE_UNIT); - // } else if (UA_BOTHGT.equals(pName) && maxPirepLayerData != - // null - // && maxPirepLayerData.getBaseLayerHeight() != null) { - // a = new - // Amount(maxPirepLayerData.getBaseLayerHeight().intValue(), - // ALTITUDE_UNIT); - } - } - return a; - } + String pName = PARM_MAP.get(paramName); + if (display) { + if (SFC_TEMP.equals(pName) && (temp != null)) { + a = new Amount(temp, TEMPERATURE_UNIT); + } else if (SFC_WNDSPD.equals(pName) && (windSpeed != null)) { + a = new Amount(windSpeed, WIND_SPEED_UNIT); + } else if (SFC_WNDDIR.equals(pName) && (windDirection != null)) { + a = new Amount(windDirection, WIND_DIR_UNIT); + } else if (STA_LAT.equals(pName)) { + a = new Amount(this.getLatitude(), LOCATION_UNIT); + } else if (STA_LON.equals(pName)) { + a = new Amount(this.getLongitude(), LOCATION_UNIT); + } else if (UA_FLTLVL.equals(pName) && (getFlightLevel() != null)) { + a = new Amount(this.getFlightLevel().intValue(), ALTITUDE_UNIT); + // if used, need to modify raytheon code + // } else if (UA_TOPHGT.equals(pName) && maxPirepLayerData != + // null + // && maxPirepLayerData.getTopLayerHeight() != null) { + // a = new + // Amount(maxPirepLayerData.getTopLayerHeight().intValue(), + // ALTITUDE_UNIT); + // } else if (UA_BOTHGT.equals(pName) && maxPirepLayerData != + // null + // && maxPirepLayerData.getBaseLayerHeight() != null) { + // a = new + // Amount(maxPirepLayerData.getBaseLayerHeight().intValue(), + // ALTITUDE_UNIT); + } + } + return a; + } - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Collection getValues(String paramName) { - return null; - } + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Collection getValues(String paramName) { + return null; + } - @Override - public String[] getStrings(String paramName) { - if ("ICI".matches(paramName)) { - int rank = -1; - String iceIntensity = null; - for (NcPirepLayerData layer : this.ancPirepData) { - String intensity = ""; - if (layer.getLayerType().equals( - NcPirepLayerData.LAYER_TYP_ICING)) { - if (layer.getIceInten() != null) { - intensity = layer.getIceInten(); - } - // if (layer.getSecondValue() != null) { - // intensity += layer.getSecondValue(); - // } + @Override + public String[] getStrings(String paramName) { + if ("ICI".matches(paramName)) { + int rank = -1; + String iceIntensity = null; + for (NcPirepLayerData layer : this.ancPirepData) { + String intensity = ""; + if (layer.getLayerType().equals( + NcPirepLayerData.LAYER_TYP_ICING)) { + if (layer.getIceInten() != null) { + intensity = layer.getIceInten(); + } + // if (layer.getSecondValue() != null) { + // intensity += layer.getSecondValue(); + // } - if (ICING_MAP.get(intensity).intValue() > rank) { - rank = ICING_MAP.get(intensity).intValue(); - iceIntensity = intensity; - maxPirepLayerData = layer; - } - } - } - if (iceIntensity != null) { - String[] maxIntensity = { iceIntensity }; - return maxIntensity; - } else { - display = false; - } - } else if ("ICT".matches(paramName) && maxPirepLayerData != null) { - String[] maxType = { maxPirepLayerData.getIceType() }; - return maxType; - } else if ("TBI".matches(paramName)) { - int rank = -1; - String turbIntensity = null; - for (NcPirepLayerData layer : this.ancPirepData) { - String intensity = ""; - if (layer.getLayerType().equals( - NcPirepLayerData.LAYER_TYP_TURBC)) { - if (layer.getTurbInten() != null) { - intensity = layer.getTurbInten(); - } - // if (layer.getSecondValue() != null) { - // intensity += layer.getSecondValue(); - // } + if (ICING_MAP.get(intensity).intValue() > rank) { + rank = ICING_MAP.get(intensity).intValue(); + iceIntensity = intensity; + maxPirepLayerData = layer; + } + } + } + if (iceIntensity != null) { + String[] maxIntensity = { iceIntensity }; + return maxIntensity; + } else { + display = false; + } + } else if ("ICT".matches(paramName) && (maxPirepLayerData != null)) { + String[] maxType = { maxPirepLayerData.getIceType() }; + return maxType; + } else if ("TBI".matches(paramName)) { + int rank = -1; + String turbIntensity = null; + for (NcPirepLayerData layer : this.ancPirepData) { + String intensity = ""; + if (layer.getLayerType().equals( + NcPirepLayerData.LAYER_TYP_TURBC)) { + if (layer.getTurbInten() != null) { + intensity = layer.getTurbInten(); + } + // if (layer.getSecondValue() != null) { + // intensity += layer.getSecondValue(); + // } - if (TURB_MAP.get(intensity).intValue() > rank) { - rank = TURB_MAP.get(intensity).intValue(); - turbIntensity = intensity; - maxPirepLayerData = layer; - } - } - } - if (turbIntensity != null) { - String[] maxIntensity = { turbIntensity }; - return maxIntensity; - } else { - display = false; - } - } else if ("TBT".matches(paramName) && maxPirepLayerData != null) { - String[] maxType = { maxPirepLayerData.getTurbType() }; - return maxType; - } else if ("TBF".matches(paramName) && maxPirepLayerData != null) { - // Turbulence Frequency Types do not get stored. - } - return null; - } + if (TURB_MAP.get(intensity).intValue() > rank) { + rank = TURB_MAP.get(intensity).intValue(); + turbIntensity = intensity; + maxPirepLayerData = layer; + } + } + } + if (turbIntensity != null) { + String[] maxIntensity = { turbIntensity }; + return maxIntensity; + } else { + display = false; + } + } else if ("TBT".matches(paramName) && (maxPirepLayerData != null)) { + String[] maxType = { maxPirepLayerData.getTurbType() }; + return maxType; + } else if ("TBF".matches(paramName) && (maxPirepLayerData != null)) { + // Turbulence Frequency Types do not get stored. + } + return null; + } - @Override - public AircraftObsLocation getSpatialObject() { - return location; - } + @Override + public AircraftObsLocation getSpatialObject() { + return location; + } - public AircraftObsLocation getLocation() { - return location; - } + public AircraftObsLocation getLocation() { + return location; + } - public void setLocation(AircraftObsLocation location) { - this.location = location; - } + public void setLocation(AircraftObsLocation location) { + this.location = location; + } - @Override - public String getMessageData() { - return getObsText(); - } + @Override + public String getMessageData() { + return getObsText(); + } - /** - * Returns the hashCode for this object. This implementation returns the - * hashCode of the generated dataURI. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); - return result; - } + /** + * Returns the hashCode for this object. This implementation returns the + * hashCode of the generated dataURI. + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); + return result; + } - /** - * Checks if this record is equal to another by checking the generated - * dataURI. - * - * @param obj - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NcPirepRecord other = (NcPirepRecord) obj; - if (getDataURI() == null) { - if (other.getDataURI() != null) { - return false; - } - } else if (!getDataURI().equals(other.getDataURI())) - return false; - return true; - } + /** + * Checks if this record is equal to another by checking the generated + * dataURI. + * + * @param obj + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + NcPirepRecord other = (NcPirepRecord) obj; + if (getDataURI() == null) { + if (other.getDataURI() != null) { + return false; + } + } else if (!getDataURI().equals(other.getDataURI())) { + return false; + } + return true; + } - @Override - public Date getPersistenceTime() { - return this.dataTime.getRefTime(); - } + @Override + public Date getPersistenceTime() { + return this.dataTime.getRefTime(); + } - @Override - public void setPersistenceTime(Date persistTime) { - } + @Override + public void setPersistenceTime(Date persistTime) { + } - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() - */ - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() + */ + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon - * .uf.common.pointdata.PointDataView) - */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon + * .uf.common.pointdata.PointDataView) + */ + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } @Override @Column @@ -849,4 +854,9 @@ public class NcPirepRecord extends PluginDataObject implements ISpatialEnabled, public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ncpirep"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscat/src/gov/noaa/nws/ncep/common/dataplugin/ncscat/NcscatRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscat/src/gov/noaa/nws/ncep/common/dataplugin/ncscat/NcscatRecord.java index 3521a2192d..031199a14b 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscat/src/gov/noaa/nws/ncep/common/dataplugin/ncscat/NcscatRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscat/src/gov/noaa/nws/ncep/common/dataplugin/ncscat/NcscatRecord.java @@ -50,12 +50,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ncscat", - indexes = { - @Index(name = "ncscat_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ncscat", indexes = { @Index(name = "ncscat_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @@ -168,4 +164,9 @@ public class NcscatRecord extends PersistablePluginDataObject { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ncsat"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscd/src/gov/noaa/nws/ncep/common/dataplugin/ncscd/NcScdRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscd/src/gov/noaa/nws/ncep/common/dataplugin/ncscd/NcScdRecord.java index 826c596eb1..8b7473c804 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscd/src/gov/noaa/nws/ncep/common/dataplugin/ncscd/NcScdRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscd/src/gov/noaa/nws/ncep/common/dataplugin/ncscd/NcScdRecord.java @@ -1,34 +1,3 @@ -/** - * - * NcScdRecord - * - * This java class performs the mapping to the database tables for SCD. - * - *
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    	Engineer    Description
- * -------		-------	 	--------	-----------
- * 12/2008		41			T. Lee		Created
- * 04/2009		41			T. Lee		Migrated to TO10
- * 07/2009		41			T. Lee		Migrated to TO11
- * 11/2009		41			T. Lee		Migrated to TO11D6
- * 06/2011		41			F. J. Yen	Convert SCD to HDF5 (OB11.5).  Changed type
- * 										of suspectTimeFlag from Boolean to String
- * 										since undefined in PointDataDescription.
- * 09/2011      457         S. Gurung   Renamed H5 to Nc and h5 to nc
- * Apr 4, 2013        1846 bkowal      Added an index on refTime and forecastTime
- * 04/2013      1293        bkowal      Removed references to hdffileid.
- * Apr 12, 2013 1857        bgonzale    Added SequenceGenerator annotation.
- * May 07, 2013 1869        bsteffen	Remove dataURI column from PluginDataObject.
- *
- * 
- * - * @author T.Lee - * @version 1.0 - * - */ - package gov.noaa.nws.ncep.common.dataplugin.ncscd; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; @@ -70,6 +39,36 @@ import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +/** + * + * NcScdRecord + * + * This java class performs the mapping to the database tables for SCD. + * + *
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#  Engineer  Description
+ * ------------ -------- --------- ----------------------------------
+ * 12/2008      41       T. Lee    Created
+ * 04/2009      41       T. Lee    Migrated to TO10
+ * 07/2009      41       T. Lee    Migrated to TO11
+ * 11/2009      41       T. Lee    Migrated to TO11D6
+ * 06/2011      41       F. J. Yen Convert SCD to HDF5 (OB11.5).  Changed type
+ *                                 of suspectTimeFlag from Boolean to String
+ *                                 since undefined in PointDataDescription.
+ * 09/2011      457      S. Gurung Renamed H5 to Nc and h5 to nc
+ * Apr 04, 2013 1846     bkowal    Added an index on refTime and forecastTime
+ * Apr 04, 2013 1293     bkowal    Removed references to hdffileid.
+ * Apr 12, 2013 1857     bgonzale  Added SequenceGenerator annotation.
+ * May 07, 2013 1869     bsteffen  Remove dataURI column from PluginDataObject.
+ * Aug 30, 2013 2298     rjpeter   Make getPluginName abstract
+ * 
+ * + * @author T.Lee + * @version 1.0 + * + */ @Entity @SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "ncscdseq") @Table(name = "ncscd", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) @@ -77,483 +76,479 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ncscd", - indexes = { - @Index(name = "ncscd_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ncscd", indexes = { @Index(name = "ncscd_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class NcScdRecord extends PluginDataObject implements ISpatialEnabled, - IDecoderGettable, IPointData, IPersistable { - - private static final long serialVersionUID = 1L; - - public static final Unit TDXC_UNIT = SI.CELSIUS; - - public static final Unit PRECIP_UNIT = NonSI.INCH; - - /** Report type */ - @XmlElement - @DynamicSerializeElement - @Column - @DataURI(position = 1) - private String reportType; - - @Embedded - @DataURI(position = 2, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; - - /** Bulletin correction */ - @Column(length = 8) - @DataURI(position = 3) - @XmlElement - @DynamicSerializeElement - private String corIndicator; - - /** Bulletin observation time */ - @Transient - @XmlAttribute - @DynamicSerializeElement - private Calendar obsTime; - - /** Bulletin issuance time */ - @Column - @DataURI(position = 4) - @XmlElement - @DynamicSerializeElement - private Calendar issueTime; - - /** Maximum 24h temperature in Celsius */ - @Transient - @XmlElement - @DynamicSerializeElement - private float TDXC; - - /** Minimum 24h temperature in Celsius */ - @Transient - @XmlElement - @DynamicSerializeElement - private float TDNC; - - /** Six hour accumulated precipitation in inches */ - @Transient - @XmlElement - @DynamicSerializeElement - private float P06I; - - /** Twenty-four hour accumulated precipitation in inches */ - @Transient - @XmlElement - @DynamicSerializeElement - private float P24I; - - /** Character weather phenomenon */ - @Transient - @XmlElement - @DynamicSerializeElement - private String WTHR; - - /** Snow depth */ - @Transient - @XmlElement - @DynamicSerializeElement - private float SNOW; - - /** New snow depth on the ground */ - @Transient - @XmlElement - @DynamicSerializeElement - private float SNEW; - - /** Total snow depth in a Calendar day */ - @Transient - @XmlElement - @DynamicSerializeElement - private float S24I; - - /** Water equivalent of snow */ - @Transient - @XmlElement - @DynamicSerializeElement - private float WEQS; - - /** Duration of sunshine */ - @Transient - @XmlElement - @DynamicSerializeElement - private int MSUN; - - /** Low-level cloud genera from WMO Code 0513 */ - @Transient - @XmlElement - @DynamicSerializeElement - private int CTYL; - - /** Mid-level cloud genera from WMO Code 0513 */ - @Transient - @XmlElement - @DynamicSerializeElement - private int CTYM; - - /** High-level cloud genera from WMO Code 0513 */ - @Transient - @XmlElement - @DynamicSerializeElement - private int CTYH; - - /** Fraction of celestial dome covered by cloud from WMO Code 2700 */ - @Transient - @XmlElement - @DynamicSerializeElement - private int CFRT; - - /** - * Fraction of celestial dome covered by low or mid cloud from WMO Code 2700 - */ - @Transient - @XmlElement - @DynamicSerializeElement - private int CFRL; - - /** Cloud base height from WMO Code 1600 */ - @Transient - @XmlElement - @DynamicSerializeElement - private int CBAS; - - /** Suspect time flag */ - @Transient - @XmlElement - @DynamicSerializeElement - private String suspectTimeFlag; - - /** Raw report */ - @Transient - @XmlElement - @DynamicSerializeElement - private String report; - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - /** - * Default constructor - * - */ - public NcScdRecord() { - this.location = null; - this.issueTime = null; - this.corIndicator = "REG"; - this.obsTime = null; - this.TDXC = IDecoderConstantsN.FLOAT_MISSING; - this.TDNC = IDecoderConstantsN.FLOAT_MISSING; - this.P06I = IDecoderConstantsN.FLOAT_MISSING; - this.P24I = IDecoderConstantsN.FLOAT_MISSING; - this.WTHR = ""; - this.SNOW = IDecoderConstantsN.FLOAT_MISSING; - this.SNEW = IDecoderConstantsN.FLOAT_MISSING; - this.S24I = IDecoderConstantsN.FLOAT_MISSING; - this.WEQS = IDecoderConstantsN.FLOAT_MISSING; - this.MSUN = IDecoderConstantsN.INTEGER_MISSING; - this.CTYL = IDecoderConstantsN.INTEGER_MISSING; - this.CTYM = IDecoderConstantsN.INTEGER_MISSING; - this.CTYH = IDecoderConstantsN.INTEGER_MISSING; - this.CFRT = IDecoderConstantsN.INTEGER_MISSING; - this.CFRL = IDecoderConstantsN.INTEGER_MISSING; - this.CBAS = IDecoderConstantsN.INTEGER_MISSING; - this.suspectTimeFlag = "false"; - this.report = ""; - } - - /** - * Constructs a SCD record from a dataURI - * - * @param uri - * The dataURI - */ - public NcScdRecord(String uri) { - super(uri); - } - - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } - - public String getReportType() { - return reportType; - } - - public void setReportType(String reportType) { - this.reportType = reportType; - } - - public String getStationId() { - return location.getStationId(); - } - - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } - - public SurfaceObsLocation getLocation() { - return location; - } - - public void setLocation(SurfaceObsLocation obsLoc) { - this.location = obsLoc; - } - - public double getLatitude() { - return location.getLatitude(); - } - - public double getLongitude() { - return location.getLongitude(); - } - - public Integer getElevation() { - return location.getElevation(); - } - - public Calendar getIssueTime() { - return issueTime; - } - - public void setIssueTime(Calendar issueTime) { - this.issueTime = issueTime; - } - - public String getCorIndicator() { - return corIndicator; - } - - public void setCorIndicator(String corIndicator) { - this.corIndicator = corIndicator; - } - - public Calendar getObsTime() { - return obsTime; - } - - public void setObsTime(Calendar obsTime) { - this.obsTime = obsTime; - } - - public float getTDXC() { - return TDXC; - } - - public void setTDXC(float TDXC) { - this.TDXC = TDXC; - } - - public float getTDNC() { - return TDNC; - } - - public void setTDNC(float TDNC) { - this.TDNC = TDNC; - } - - public float getP06I() { - return P06I; - } - - public void setP06I(float P06I) { - this.P06I = P06I; - } - - public float getP24I() { - return P24I; - } - - public void setP24I(float P24I) { - this.P24I = P24I; - } + IDecoderGettable, IPointData, IPersistable { + + private static final long serialVersionUID = 1L; + + public static final Unit TDXC_UNIT = SI.CELSIUS; + + public static final Unit PRECIP_UNIT = NonSI.INCH; + + /** Report type */ + @XmlElement + @DynamicSerializeElement + @Column + @DataURI(position = 1) + private String reportType; + + @Embedded + @DataURI(position = 2, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; + + /** Bulletin correction */ + @Column(length = 8) + @DataURI(position = 3) + @XmlElement + @DynamicSerializeElement + private String corIndicator; + + /** Bulletin observation time */ + @Transient + @XmlAttribute + @DynamicSerializeElement + private Calendar obsTime; + + /** Bulletin issuance time */ + @Column + @DataURI(position = 4) + @XmlElement + @DynamicSerializeElement + private Calendar issueTime; + + /** Maximum 24h temperature in Celsius */ + @Transient + @XmlElement + @DynamicSerializeElement + private float TDXC; + + /** Minimum 24h temperature in Celsius */ + @Transient + @XmlElement + @DynamicSerializeElement + private float TDNC; + + /** Six hour accumulated precipitation in inches */ + @Transient + @XmlElement + @DynamicSerializeElement + private float P06I; + + /** Twenty-four hour accumulated precipitation in inches */ + @Transient + @XmlElement + @DynamicSerializeElement + private float P24I; + + /** Character weather phenomenon */ + @Transient + @XmlElement + @DynamicSerializeElement + private String WTHR; + + /** Snow depth */ + @Transient + @XmlElement + @DynamicSerializeElement + private float SNOW; + + /** New snow depth on the ground */ + @Transient + @XmlElement + @DynamicSerializeElement + private float SNEW; + + /** Total snow depth in a Calendar day */ + @Transient + @XmlElement + @DynamicSerializeElement + private float S24I; + + /** Water equivalent of snow */ + @Transient + @XmlElement + @DynamicSerializeElement + private float WEQS; + + /** Duration of sunshine */ + @Transient + @XmlElement + @DynamicSerializeElement + private int MSUN; + + /** Low-level cloud genera from WMO Code 0513 */ + @Transient + @XmlElement + @DynamicSerializeElement + private int CTYL; + + /** Mid-level cloud genera from WMO Code 0513 */ + @Transient + @XmlElement + @DynamicSerializeElement + private int CTYM; + + /** High-level cloud genera from WMO Code 0513 */ + @Transient + @XmlElement + @DynamicSerializeElement + private int CTYH; + + /** Fraction of celestial dome covered by cloud from WMO Code 2700 */ + @Transient + @XmlElement + @DynamicSerializeElement + private int CFRT; + + /** + * Fraction of celestial dome covered by low or mid cloud from WMO Code 2700 + */ + @Transient + @XmlElement + @DynamicSerializeElement + private int CFRL; + + /** Cloud base height from WMO Code 1600 */ + @Transient + @XmlElement + @DynamicSerializeElement + private int CBAS; + + /** Suspect time flag */ + @Transient + @XmlElement + @DynamicSerializeElement + private String suspectTimeFlag; + + /** Raw report */ + @Transient + @XmlElement + @DynamicSerializeElement + private String report; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + /** + * Default constructor + * + */ + public NcScdRecord() { + this.location = null; + this.issueTime = null; + this.corIndicator = "REG"; + this.obsTime = null; + this.TDXC = IDecoderConstantsN.FLOAT_MISSING; + this.TDNC = IDecoderConstantsN.FLOAT_MISSING; + this.P06I = IDecoderConstantsN.FLOAT_MISSING; + this.P24I = IDecoderConstantsN.FLOAT_MISSING; + this.WTHR = ""; + this.SNOW = IDecoderConstantsN.FLOAT_MISSING; + this.SNEW = IDecoderConstantsN.FLOAT_MISSING; + this.S24I = IDecoderConstantsN.FLOAT_MISSING; + this.WEQS = IDecoderConstantsN.FLOAT_MISSING; + this.MSUN = IDecoderConstantsN.INTEGER_MISSING; + this.CTYL = IDecoderConstantsN.INTEGER_MISSING; + this.CTYM = IDecoderConstantsN.INTEGER_MISSING; + this.CTYH = IDecoderConstantsN.INTEGER_MISSING; + this.CFRT = IDecoderConstantsN.INTEGER_MISSING; + this.CFRL = IDecoderConstantsN.INTEGER_MISSING; + this.CBAS = IDecoderConstantsN.INTEGER_MISSING; + this.suspectTimeFlag = "false"; + this.report = ""; + } + + /** + * Constructs a SCD record from a dataURI + * + * @param uri + * The dataURI + */ + public NcScdRecord(String uri) { + super(uri); + } + + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } + + public String getReportType() { + return reportType; + } + + public void setReportType(String reportType) { + this.reportType = reportType; + } + + public String getStationId() { + return location.getStationId(); + } + + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } + + public SurfaceObsLocation getLocation() { + return location; + } + + public void setLocation(SurfaceObsLocation obsLoc) { + this.location = obsLoc; + } + + public double getLatitude() { + return location.getLatitude(); + } + + public double getLongitude() { + return location.getLongitude(); + } + + public Integer getElevation() { + return location.getElevation(); + } + + public Calendar getIssueTime() { + return issueTime; + } + + public void setIssueTime(Calendar issueTime) { + this.issueTime = issueTime; + } + + public String getCorIndicator() { + return corIndicator; + } + + public void setCorIndicator(String corIndicator) { + this.corIndicator = corIndicator; + } + + public Calendar getObsTime() { + return obsTime; + } + + public void setObsTime(Calendar obsTime) { + this.obsTime = obsTime; + } + + public float getTDXC() { + return TDXC; + } + + public void setTDXC(float TDXC) { + this.TDXC = TDXC; + } + + public float getTDNC() { + return TDNC; + } + + public void setTDNC(float TDNC) { + this.TDNC = TDNC; + } + + public float getP06I() { + return P06I; + } + + public void setP06I(float P06I) { + this.P06I = P06I; + } + + public float getP24I() { + return P24I; + } + + public void setP24I(float P24I) { + this.P24I = P24I; + } - public String getWTHR() { - return WTHR; - } + public String getWTHR() { + return WTHR; + } - public void setWTHR(String WTHR) { - this.WTHR = WTHR; - } + public void setWTHR(String WTHR) { + this.WTHR = WTHR; + } - public float getSNOW() { - return SNOW; - } + public float getSNOW() { + return SNOW; + } - public void setSNOW(float SNOW) { - this.SNOW = SNOW; - } - - public float getSNEW() { - return SNEW; - } - - public void setSNEW(float SNEW) { - this.SNEW = SNEW; - } - - public float getS24I() { - return S24I; - } - - public void setS24I(float S24I) { - this.S24I = S24I; - } - - public float getWEQS() { - return WEQS; - } - - public void setWEQS(float WEQS) { - this.WEQS = WEQS; - } - - public int getMSUN() { - return MSUN; - } - - public void setMSUN(int MSUN) { - this.MSUN = MSUN; - } - - public int getCTYL() { - return CTYL; - } - - public void setCTYL(int CTYL) { - this.CTYL = CTYL; - } - - public int getCTYM() { - return CTYM; - } - - public void setCTYM(int CTYM) { - this.CTYM = CTYM; - } - - public int getCTYH() { - return CTYH; - } - - public void setCTYH(int CTYH) { - this.CTYH = CTYH; - } - - public int getCFRT() { - return CFRT; - } - - public void setCFRT(int CFRT) { - this.CFRT = CFRT; - } - - public int getCFRL() { - return CFRL; - } - - public void setCFRL(int CFRL) { - this.CFRL = CFRL; - } - - public int getCBAS() { - return CBAS; - } - - public void setCBAS(int CBAS) { - this.CBAS = CBAS; - } - - public String getReport() { - return report; - } - - public void setReport(String report) { - this.report = report; - } - - public String getSuspectTimeFlag() { - return suspectTimeFlag; - } - - public void setSuspectTimeFlag(String suspectTimeFlag) { - this.suspectTimeFlag = suspectTimeFlag; - } - - /** - * Get the value and units of a named parameter within this observation. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return An Amount with value and units. If the parameter is unknown, a - * null reference is returned. - */ - - @Override - public Date getPersistenceTime() { - return this.dataTime.getRefTime(); - } - - @Override - public void setPersistenceTime(Date persistTime) { - } - - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() - */ - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } - - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon - * .uf.common.pointdata.PointDataView) - */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } - - @Override - public Amount getValue(String paramName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Collection getValues(String paramName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getString(String paramName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String[] getStrings(String paramName) { - // TODO Auto-generated method stub - return null; - } + public void setSNOW(float SNOW) { + this.SNOW = SNOW; + } + + public float getSNEW() { + return SNEW; + } + + public void setSNEW(float SNEW) { + this.SNEW = SNEW; + } + + public float getS24I() { + return S24I; + } + + public void setS24I(float S24I) { + this.S24I = S24I; + } + + public float getWEQS() { + return WEQS; + } + + public void setWEQS(float WEQS) { + this.WEQS = WEQS; + } + + public int getMSUN() { + return MSUN; + } + + public void setMSUN(int MSUN) { + this.MSUN = MSUN; + } + + public int getCTYL() { + return CTYL; + } + + public void setCTYL(int CTYL) { + this.CTYL = CTYL; + } + + public int getCTYM() { + return CTYM; + } + + public void setCTYM(int CTYM) { + this.CTYM = CTYM; + } + + public int getCTYH() { + return CTYH; + } + + public void setCTYH(int CTYH) { + this.CTYH = CTYH; + } + + public int getCFRT() { + return CFRT; + } + + public void setCFRT(int CFRT) { + this.CFRT = CFRT; + } + + public int getCFRL() { + return CFRL; + } + + public void setCFRL(int CFRL) { + this.CFRL = CFRL; + } + + public int getCBAS() { + return CBAS; + } + + public void setCBAS(int CBAS) { + this.CBAS = CBAS; + } + + public String getReport() { + return report; + } + + public void setReport(String report) { + this.report = report; + } + + public String getSuspectTimeFlag() { + return suspectTimeFlag; + } + + public void setSuspectTimeFlag(String suspectTimeFlag) { + this.suspectTimeFlag = suspectTimeFlag; + } + + /** + * Get the value and units of a named parameter within this observation. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return An Amount with value and units. If the parameter is unknown, a + * null reference is returned. + */ + + @Override + public Date getPersistenceTime() { + return this.dataTime.getRefTime(); + } + + @Override + public void setPersistenceTime(Date persistTime) { + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() + */ + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon + * .uf.common.pointdata.PointDataView) + */ + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + + @Override + public Amount getValue(String paramName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getValues(String paramName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getString(String paramName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String[] getStrings(String paramName) { + // TODO Auto-generated method stub + return null; + } @Override @Column @@ -561,4 +556,9 @@ public class NcScdRecord extends PluginDataObject implements ISpatialEnabled, public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ncscd"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscd/src/gov/noaa/nws/ncep/common/dataplugin/ncscd/dao/NcScdPointDataTransform.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscd/src/gov/noaa/nws/ncep/common/dataplugin/ncscd/dao/NcScdPointDataTransform.java index 534cf3c6f8..b47f03347b 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscd/src/gov/noaa/nws/ncep/common/dataplugin/ncscd/dao/NcScdPointDataTransform.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncscd/src/gov/noaa/nws/ncep/common/dataplugin/ncscd/dao/NcScdPointDataTransform.java @@ -4,6 +4,8 @@ **/ package gov.noaa.nws.ncep.common.dataplugin.ncscd.dao; +import gov.noaa.nws.ncep.common.dataplugin.ncscd.NcScdRecord; + import java.io.File; import java.util.ArrayList; import java.util.Date; @@ -11,9 +13,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import gov.noaa.nws.ncep.common.dataplugin.ncscd.NcScdRecord; -import gov.noaa.nws.ncep.common.dataplugin.ncscd.dao.NcScdDao; - import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.pointdata.PointDataContainer; import com.raytheon.uf.common.pointdata.PointDataDescription; @@ -30,9 +29,10 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 06/29/2011 F. J. Yen Initial creation - * 09/08/2011 294 G. Hull Use SurfaceObsLocation to set lat/lon - * 09/13/2011 457 S. Gurung Renamed H5 to Nc and h5 to nc + * Jun 29, 2011 F. J. Yen Initial creation + * Sep 08, 2011 294 G. Hull Use SurfaceObsLocation to set lat/lon + * Sep 13, 2011 457 S. Gurung Renamed H5 to Nc and h5 to nc + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -55,70 +55,69 @@ public class NcScdPointDataTransform { private static final String LATITUDE = "latitude"; private static final String ELEVATION = "elevation"; - + private static final String ISSUE_TIME = "issueTime"; - + private static final String OBS_TIME = "obsTime"; // STATION_ID, REPORT_TYPE, ISSUE_TIME, OBS_TIME // ------------------ - + private static final String CORRECTION_CODE = "correctionCode"; private static final String DATAURI = "dataURI"; - + private static final String REPORT = "report"; // CORRECTION_CODE, DATAURI, REPORT // ------------------ - + private static final String TDXC = "TDXC"; private static final String TDNC = "TDNC"; - + private static final String P06I = "P06I"; - + private static final String P24I = "P24I"; private static final String WTHR = "WTHR"; - + private static final String SNOW = "SNOW"; - + private static final String SNEW = "SNEW"; - + private static final String S24I = "S24I"; private static final String WEQS = "WEQS"; - + private static final String MSUN = "MSUN"; - + private static final String CTYL = "CTYL"; private static final String CTYM = "CTYM"; - + private static final String CTYH = "CTYH"; - + private static final String CFRT = "CFRT"; private static final String CFRL = "CFRL"; - - private static final String CBAS = "CBAS"; - - private static final String SUSPECT_TIME_FLAG = "suspectTimeFlag"; - - // TDXC, TDNC, P06I, P24I, WTHR, SNOW, SNEW, S24I, WEQS, MSUN, - // CTYL, CTYM, CTYH, CFRT, CFRL, CBAS, SUSPECT_TIME_FLAG - // ------------------ + private static final String CBAS = "CBAS"; + + private static final String SUSPECT_TIME_FLAG = "suspectTimeFlag"; + + // TDXC, TDNC, P06I, P24I, WTHR, SNOW, SNEW, S24I, WEQS, MSUN, + // CTYL, CTYM, CTYH, CFRT, CFRL, CBAS, SUSPECT_TIME_FLAG + // ------------------ /** * It is important to keep this up to date or risk breaking backwards * compatibility */ - private static final String[] ALL_PARAMS = { STATION_ID, REPORT_TYPE, - ISSUE_TIME, OBS_TIME, CORRECTION_CODE, REPORT, DATAURI, TDXC, - TDNC, P06I, P24I, WTHR, SNOW, SNEW, S24I, WEQS, MSUN, CTYL, - CTYM, CTYH, CFRT, CFRL, CBAS, SUSPECT_TIME_FLAG,}; + private static final String[] ALL_PARAMS = { STATION_ID, REPORT_TYPE, + ISSUE_TIME, OBS_TIME, CORRECTION_CODE, REPORT, DATAURI, TDXC, TDNC, + P06I, P24I, WTHR, SNOW, SNEW, S24I, WEQS, MSUN, CTYL, CTYM, CTYH, + CFRT, CFRL, CBAS, SUSPECT_TIME_FLAG, }; public static final String ALL_PARAMS_LIST; static { @@ -154,8 +153,9 @@ public class NcScdPointDataTransform { if (pdo.length > 0) { Map pointMap = new HashMap(); for (PluginDataObject p : pdo) { - if (!(p instanceof NcScdRecord)) + if (!(p instanceof NcScdRecord)) { continue; + } File f = this.dao.getFullFilePath(p); PointDataContainer pdc = pointMap.get(f); if (pdc == null) { @@ -206,21 +206,19 @@ public class NcScdPointDataTransform { nar.setDataURI(pdv.getString(DATAURI)); nar.setReport(pdv.getString(REPORT)); nar.setReportType(pdv.getString(REPORT_TYPE)); - + SurfaceObsLocation loc = new SurfaceObsLocation( pdv.getString(STATION_NAME)); Double lat = pdv.getNumber(LATITUDE).doubleValue(); Double lon = pdv.getNumber(LONGITUDE).doubleValue(); loc.assignLocation(lat, lon); loc.setElevation(pdv.getNumber(ELEVATION).intValue()); - + long tmptime = pdv.getNumber(ISSUE_TIME).longValue(); nar.setIssueTime(TimeTools.newCalendar(tmptime)); tmptime = pdv.getNumber(OBS_TIME).longValue(); nar.setObsTime(TimeTools.newCalendar(tmptime)); - nar.setPluginName("ncscd"); - nar.setTDXC(pdv.getNumber(TDXC).floatValue()); nar.setTDNC(pdv.getNumber(TDNC).floatValue()); nar.setP06I(pdv.getNumber(P06I).floatValue()); @@ -230,11 +228,11 @@ public class NcScdPointDataTransform { nar.setSNEW(pdv.getNumber(SNEW).floatValue()); nar.setS24I(pdv.getNumber(S24I).floatValue()); nar.setWEQS(pdv.getNumber(WEQS).floatValue()); - + nar.setMSUN(pdv.getInt(MSUN)); nar.setCTYL(pdv.getInt(CTYL)); nar.setCTYM(pdv.getInt(CTYM)); - nar.setCTYH(pdv.getInt(CTYH)); + nar.setCTYH(pdv.getInt(CTYH)); nar.setCFRT(pdv.getInt(CFRT)); nar.setCFRL(pdv.getInt(CFRL)); nar.setCBAS(pdv.getInt(CBAS)); diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.nctaf/src/gov/noaa/nws/ncep/common/dataplugin/nctaf/NcTafRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.nctaf/src/gov/noaa/nws/ncep/common/dataplugin/nctaf/NcTafRecord.java index 50f2d9eabb..b26e3018a8 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.nctaf/src/gov/noaa/nws/ncep/common/dataplugin/nctaf/NcTafRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.nctaf/src/gov/noaa/nws/ncep/common/dataplugin/nctaf/NcTafRecord.java @@ -59,20 +59,25 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 09/20/2011 458 sgurung Main pdo class - * 09/23/2011 458 sgurung Converted to HDF5 - * 09/29/2011 sgurung Added reportType - * 10/19/2011 sgurung Set dataTime with correct valid period - * 10/26/2011 sgurung Added probable parameters (for TEMPO/PROB groups). - * Split change groups into hourly records. - * 11/03/2011 sgurung Added probable weather and method to calculate ceiling. - * 11/04/2011 sgurung Sort sky_cover before calculating ceiling. - * Change startRefTime to nearest hour to get hourly refTimes - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * 04/08/2013 1293 bkowal Removed references to hdffileid. + * Sep 20, 2011 458 sgurung Main pdo class + * Sep 23, 2011 458 sgurung Converted to HDF5 + * Sep 29, 2011 sgurung Added reportType + * Oct 19, 2011 sgurung Set dataTime with correct valid period + * Oct 26, 2011 sgurung Added probable parameters (for + * TEMPO/PROB groups). Split change groups + * into hourly records. + * Nov 03, 2011 sgurung Added probable weather and method to + * calculate ceiling. + * Nov 04, 2011 sgurung Sort sky_cover before calculating + * ceiling. Change startRefTime to nearest + * hour to get hourly refTimes + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 08, 2013 1293 bkowal Removed references to hdffileid. * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -86,1531 +91,1552 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "nctaf", - indexes = { - @Index(name = "nctaf_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "nctaf", indexes = { @Index(name = "nctaf_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize @XmlAccessorType(XmlAccessType.NONE) @XmlRootElement public class NcTafRecord extends PluginDataObject implements ISpatialEnabled, - IDecoderGettable, IPointData, IPersistable { - - private static final long serialVersionUID = 1L; - - @DynamicSerializeElement - @XmlElement - @Column - private String wmoHeader; - - @DynamicSerializeElement - @XmlElement - // @Column(length = 1024) - @Transient - private String tafText; - - // The observation report type. - @DataURI(position = 1) - @Column - @XmlElement - @DynamicSerializeElement - private String reportType; - - @Embedded - @DataURI(position = 2, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; - - // Station Identifier for the data - @DynamicSerializeElement - @XmlElement - @Transient - // @Index(name = "nctaf_stationIndex") - private String stationId; - - @DynamicSerializeElement - @XmlElement - @Column - @DataURI(position = 3) - private String corIndicator; - - @DynamicSerializeElement - @XmlElement - @Column - @DataURI(position = 4) - private String amdIndicator; - - /** Issue date */ - @DynamicSerializeElement - @XmlElement - @Column - // @DataURI(position = 4) - private Date issue_time; - - /** Issue date string */ - @DynamicSerializeElement - @XmlElement - @Column - @DataURI(position = 5) - private String issue_timeString; - - /** Bulletin issuance time */ - @DynamicSerializeElement - @XmlElement - @Transient - private Date bulletin_time; - - /** Any remarks contained in the TAF record */ - @DynamicSerializeElement - @XmlElement - @Transient - private String remarks; - - /** A String containing the change group */ - @DynamicSerializeElement - @XmlElement - // @Column - @Transient - private String changeGroup; - - /** The period for which the TAF is valid */ - @DynamicSerializeElement - @XmlElement - @Embedded - @Transient - private NcTafPeriod tafChangePeriod; - - /** - * The forecast valid starting date - */ - @DynamicSerializeElement - @XmlElement - @Transient - private Calendar startDate; - - // This time is only used for BECMG groups. It marks the end time of the - // BECMG transition period. - @DynamicSerializeElement - @XmlElement - @Transient - private Calendar transitionEndDate; - - /** - * The forecast valid ending date - */ - @DynamicSerializeElement - @XmlElement - @Transient - private Calendar endDate; - - /** - * The sequence id is used to physically order a collection of ChangeGroups. - * This is required because the start times may be ambiguous i.e. A BECMG - * and TEMPO change group could share the same start time. - */ - @DynamicSerializeElement - @XmlElement - @Column - @DataURI(position = 6) - private Integer sequenceId; - - /** - * The change group indicator i.e. BECMG, FM, TEMPO, etc - */ - @DynamicSerializeElement - @XmlElement - @Column - @DataURI(position = 7) - private String change_indicator; - - /** - * The probability percentage for PROB and PROB TEMPO change groups. - */ - @DynamicSerializeElement - @XmlElement - @Transient - private Integer probability; - - /** Wind direction in degrees */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float wind_dir_degrees; - - /** Wind speed in knots */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float wind_speed_kt; - - /** Wind gust in knots */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float wind_gust_kt; - - /** Wind shear height above ground level */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float wind_shear_hgt_ft_agl; - - /** Wind shear direction in degrees */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float wind_shear_dir_degrees; - - /** Wind shear speed in knots */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float wind_shear_speed_kt; - - /** Visibility (horizontal) in miles */ - @DynamicSerializeElement - @XmlElement - @Column - private Float visibility_mi; - - /** Altimeter reading in inches of mercury */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float altim_in_hg; - - /** Vertical visibility */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float vert_vis_ft; - - /** Maximum temperature */ - @DynamicSerializeElement - @XmlElement - @Transient - private Integer max_temp_c; - - /** Minimum temperature */ - @DynamicSerializeElement - @XmlElement - @Transient - private Integer min_temp_c; - - /** Wind direction in degrees (TEMPO/PROB) */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float probable_wind_dir_degrees; - - /** Wind speed in knots (TEMPO/PROB) */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float probable_wind_speed_kt; - - /** Wind gust in knots (TEMPO/PROB) */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float probable_wind_gust_kt; - - /** Wind shear height above ground level (TEMPO/PROB) */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float probable_wind_shear_hgt_ft_agl; - - /** Wind shear direction in degrees (TEMPO/PROB) */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float probable_wind_shear_dir_degrees; - - /** Wind shear speed in knots (TEMPO/PROB) */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float probable_wind_shear_speed_kt; - - /** Visibility (horizontal) in miles (TEMPO/PROB) */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float probable_visibility_mi; - - /** Vertical visibility (TEMPO/PROB) */ - @DynamicSerializeElement - @XmlElement - @Transient - private Float probable_vert_vis_ft; - - /** - * The valid period for the TAF record. - */ - @DynamicSerializeElement - @XmlElement - private NcTafPeriod tafValidPeriod; - - /** - * Weather and obscurations - */ - @DynamicSerializeElement - @XmlElement - @Transient - private Set weather; - - /** - * (TEMPO/PROB) Weather and obscurations - */ - @DynamicSerializeElement - @XmlElement - @Transient - private Set probable_weather; - - /** Sky coverage */ - @DynamicSerializeElement - @XmlElement - @Transient - private Set sky_cover; - - /** (TEMPO/PROB) Sky coverage */ - @DynamicSerializeElement - @XmlElement - @Transient - private Set probable_sky_cover; - - /** The turbulence layers */ - @DynamicSerializeElement - @XmlElement - @Transient - private Set turbulence_layers; - - /** The icing layers */ - @DynamicSerializeElement - @XmlElement - @Transient - private Set icing_layers; - - /** The temperature forecasts */ - @DynamicSerializeElement - @XmlElement - @Transient - private Set temp_forecasts; - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - // private Integer hdfFileId; - - public NcTafRecord() { - wmoHeader = " "; - tafText = " "; - reportType = "TAF"; - stationId = " "; - bulletin_time = null; - corIndicator = " "; - amdIndicator = " "; - issue_timeString = " "; - remarks = " "; - changeGroup = " "; - altim_in_hg = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - change_indicator = " "; - max_temp_c = IDecoderConstantsN.NEGATIVE_INTEGER_MISSING; - min_temp_c = IDecoderConstantsN.NEGATIVE_INTEGER_MISSING; - probability = IDecoderConstantsN.NEGATIVE_INTEGER_MISSING; - remarks = " "; - sequenceId = IDecoderConstantsN.NEGATIVE_INTEGER_MISSING; - vert_vis_ft = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - visibility_mi = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - wind_dir_degrees = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - wind_gust_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - wind_speed_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - wind_shear_hgt_ft_agl = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - wind_shear_dir_degrees = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - wind_shear_speed_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - startDate = null; - endDate = null; - transitionEndDate = null; - location = null; - probable_vert_vis_ft = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - probable_visibility_mi = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - probable_wind_dir_degrees = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - probable_wind_gust_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - probable_wind_speed_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - probable_wind_shear_hgt_ft_agl = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - probable_wind_shear_dir_degrees = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - probable_wind_shear_speed_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - } - - /** - * Constructs a taf record from a dataURI - * - * @param uri - * The dataURI - * @param tableDef - * The table definition associated with this class - */ - public NcTafRecord(String uri) { - super(uri); - } - - /** - * Get the WMO header for the enclosing WMO message. - * - * @return The wmoHeader. - */ - public String getWmoHeader() { - return wmoHeader; - } - - /** - * Set the WMO header for the enclosing WMO message. - * - * @param wmoHeader - * The WMOHeader to set. - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } - - /** - * Get the text of this terminal forecast. - * - * @return The terminal forecast text. - */ - public String getTafText() { - return tafText; - } - - /** - * Set the text of this terminal forecast. - * - * @param tafText - * The terminal forecast text. - */ - public void setTafText(String tafText) { - this.tafText = tafText; - } - - /** - * Get the observation report type. - * - * @return the reportType - */ - public String getReportType() { - return reportType; - } - - /** - * Set the observation report type. - * - * @param reportType - * the reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } - - /** - * - * @return - */ - public String getStationId() { - return stationId; - } - - /** - * - * @param stationID - */ - public void setStationId(String stationID) { - stationId = stationID; - } - - /** - * - * @return the corIndicator - */ - public String getCorIndicator() { - return corIndicator; - } - - /** - * - * @param corIndicator - * the corIndicator to set - */ - public void setCorIndicator(String corIndicator) { - this.corIndicator = corIndicator; - } - - /** - * - * @return the amdIndicator - */ - public String getAmdIndicator() { - return amdIndicator; - } - - /** - * - * @param amdIndicator - * the amdIndicator to set - */ - public void setAmdIndicator(String amdIndicator) { - this.amdIndicator = amdIndicator; - } - - /** - * - * @return the bulletin_time - */ - public Date getBulletin_time() { - return bulletin_time; - } - - /** - * - * @param bulletin_time - * the bulletin_time to set - */ - public void setBulletin_time(Date bulletin_time) { - this.bulletin_time = bulletin_time; - } - - /** - * @return the issue_time - */ - public Date getIssue_time() { - return issue_time; - } - - /** - * @param issue_time - * the issue_time to set - */ - public void setIssue_time(Date issue_time) { - this.issue_time = issue_time; - } - - /** - * @return the issue_timeString - */ - public String getIssue_timeString() { - return issue_timeString; - } - - /** - * @param issue_timeString - * the issue_time to set - */ - public void setIssue_timeString(String issue_timeString) { - this.issue_timeString = issue_timeString; - } - - @Override - public void setIdentifier(Object dataURI) { - - this.identifier = dataURI; - - } - - /** - * Get the IDecoderGettable reference for this record. - * - * @return The IDecoderGettable reference for this record. Null for this - * class. - */ - @Override - public IDecoderGettable getDecoderGettable() { - return null; - } - - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } - - public SurfaceObsLocation getLocation() { - return location; - } - - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - public double getLatitude() { - return location.getLatitude(); - } - - public double getLongitude() { - return location.getLongitude(); - } - - public Integer getElevation() { - return location.getElevation(); - } - - /** - * Returns the hashCode for this object. This implementation returns the - * hashCode of the generated dataURI. - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); - return result; - } - - /** - * Checks if this record is equal to another by checking the generated - * dataURI. - * - * @param obj - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NcTafRecord other = (NcTafRecord) obj; - if (getDataURI() == null) { - if (other.getDataURI() != null) { - return false; - } - } else if (!getDataURI().equals(other.getDataURI())) - return false; - return true; - } - - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() - */ - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } - - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon - * .uf.common.pointdata.PointDataView) - */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } - - /** - * Get the time to use for persisting this data. - * - * @return The persistence time for this data. - */ - @Override - public Date getPersistenceTime() { - if (getInsertTime() == null) - return null; - else - return getInsertTime().getTime(); - } - - /** - * Set the time to be used for the persistence time for this object. - * - * @param persistTime - * The persistence time to be used. - */ - @Override - public void setPersistenceTime(Date persistTime) { - Calendar insertTime = Calendar.getInstance(); - insertTime.setTime(persistTime); - setInsertTime(insertTime); - } - - @Override - public Amount getValue(String paramName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Collection getValues(String paramName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getString(String paramName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String[] getStrings(String paramName) { - // TODO Auto-generated method stub - return null; - } - - /** - * - * @return The string containing the change group text - */ - public String getChangeGroup() { - return this.changeGroup; - } - - public void setChangeGroup(String changeGroup) { - this.changeGroup = changeGroup; - } - - public NcTafPeriod getTafChangePeriod() { - return tafChangePeriod; - } - - public void setTafChangePeriod(NcTafPeriod tafChangePeriod) { - this.tafChangePeriod = tafChangePeriod; - } - - public Float getWind_dir_degrees() { - return wind_dir_degrees; - } - - public void setWind_dir_degrees(Float wind_dir_degrees) { - this.wind_dir_degrees = wind_dir_degrees; - } - - public Float getWind_speed_kt() { - return wind_speed_kt; - } - - public void setWind_speed_kt(Float wind_speed_kt) { - this.wind_speed_kt = wind_speed_kt; - } - - public Float getWind_gust_kt() { - return wind_gust_kt; - } - - public void setWind_gust_kt(Float wind_gust_kt) { - this.wind_gust_kt = wind_gust_kt; - } - - public Float getWind_shear_hgt_ft_agl() { - return wind_shear_hgt_ft_agl; - } - - public void setWind_shear_hgt_ft_agl(Float wind_shear_hgt_ft_agl) { - this.wind_shear_hgt_ft_agl = wind_shear_hgt_ft_agl; - } - - public Float getWind_shear_dir_degrees() { - return wind_shear_dir_degrees; - } - - public void setWind_shear_dir_degrees(Float wind_shear_dir_degrees) { - this.wind_shear_dir_degrees = wind_shear_dir_degrees; - } - - public Float getWind_shear_speed_kt() { - return wind_shear_speed_kt; - } - - public void setWind_shear_speed_kt(Float wind_shear_speed_kt) { - this.wind_shear_speed_kt = wind_shear_speed_kt; - } - - public Float getVisibility_mi() { - return visibility_mi; - } - - public void setVisibility_mi(Float visibility_mi) { - this.visibility_mi = visibility_mi; - } - - public float getAltim_in_hg() { - return altim_in_hg; - } - - public void setAltim_in_hg(float altim_in_hg) { - this.altim_in_hg = altim_in_hg; - } - - public float getVert_vis_ft() { - return probable_vert_vis_ft; - } - - public void setVert_vis_ft(float vert_vis_ft) { - this.probable_vert_vis_ft = vert_vis_ft; - } - - public float getProbable_wind_dir_degrees() { - return probable_wind_dir_degrees; - } - - public void setProbable_wind_dir_degrees(float wind_dir_degrees) { - this.probable_wind_dir_degrees = wind_dir_degrees; - } - - public float getProbable_wind_speed_kt() { - return probable_wind_speed_kt; - } - - public void setProbable_wind_speed_kt(float wind_speed_kt) { - this.probable_wind_speed_kt = wind_speed_kt; - } - - public float getProbable_wind_gust_kt() { - return probable_wind_gust_kt; - } - - public void setProbable_wind_gust_kt(float wind_gust_kt) { - this.probable_wind_gust_kt = wind_gust_kt; - } - - public float getProbable_wind_shear_hgt_ft_agl() { - return probable_wind_shear_hgt_ft_agl; - } - - public void setProbable_wind_shear_hgt_ft_agl(float wind_shear_hgt_ft_agl) { - this.probable_wind_shear_hgt_ft_agl = wind_shear_hgt_ft_agl; - } - - public float getProbable_wind_shear_dir_degrees() { - return probable_wind_shear_dir_degrees; - } - - public void setProbable_wind_shear_dir_degrees(float wind_shear_dir_degrees) { - this.probable_wind_shear_dir_degrees = wind_shear_dir_degrees; - } - - public float getProbable_wind_shear_speed_kt() { - return probable_wind_shear_speed_kt; - } - - public void setProbable_wind_shear_speed_kt(float wind_shear_speed_kt) { - this.probable_wind_shear_speed_kt = wind_shear_speed_kt; - } - - public float getProbable_visibility_mi() { - return probable_visibility_mi; - } - - public void setProbable_visibility_mi(float visibility_mi) { - this.probable_visibility_mi = visibility_mi; - } - - public float getProbable_vert_vis_ft() { - return probable_vert_vis_ft; - } - - public void setProbable_vert_vis_ft(float vert_vis_ft) { - this.probable_vert_vis_ft = vert_vis_ft; - } - - public Integer getMax_temp_c() { - return max_temp_c; - } - - public void setMax_temp_c(Integer max_temp_c) { - this.max_temp_c = max_temp_c; - } - - public Integer getMin_temp_c() { - return min_temp_c; - } - - public void setMin_temp_c(Integer min_temp_c) { - this.min_temp_c = min_temp_c; - } - - public Integer getProbability() { - return probability; - } - - public void setProbability(Integer probability) { - this.probability = probability; - } - - /** - * @return the sequenceId - */ - public Integer getSequenceId() { - return sequenceId; - } - - /** - * @param sequenceId - * the sequenceId to set - */ - public void setSequenceId(Integer sequenceId) { - this.sequenceId = sequenceId; - } - - /** - * @return the remarks - */ - public String getRemarks() { - return remarks; - } - - /** - * @param remarks - * the remarks to set - */ - public void setRemarks(String remarks) { - this.remarks = remarks; - } - - public String getChange_indicator() { - return change_indicator; - } - - public void setChange_indicator(String change_indicator) { - this.change_indicator = change_indicator; - } - - public NcTafPeriod getTafValidPeriod() { - return tafValidPeriod; - } - - public void setTafValidPeriod(NcTafPeriod tafValidPeriod) { - this.tafValidPeriod = tafValidPeriod; - } - - public Set getTurbulence_layers() { - return turbulence_layers; - } - - public void setTurbulence_layers(Set turbulence_layers) { - this.turbulence_layers = turbulence_layers; - } - - /** - * @param add - * taf turbulence layer to set - */ - public void addTurbulence_layer(NcTafTurbulenceLayer turb) { - turbulence_layers.add(turb); - } - - public Set getIcing_layers() { - return icing_layers; - } - - public void setIcing_layers(Set icing_layers) { - this.icing_layers = icing_layers; - } - - /** - * @param add - * taf icing layer to set - */ - public void addIcing_layer(NcTafIcingLayer icng) { - icing_layers.add(icng); - } - - public Set getTemp_forecasts() { - return temp_forecasts; - } - - public void setTemp_forecasts(Set temp_forecasts) { - this.temp_forecasts = temp_forecasts; - } - - /** - * @param add - * taf temp forecast to set - */ - public void addTemp_forecast(NcTafTemperatureForecast tempFcst) { - temp_forecasts.add(tempFcst); - } - - public Set getWeather() { - return weather; - } - - public void setWeather(Set weather) { - this.weather = weather; - } - - /** - * @param add - * taf weather condition to set - */ - public void addWeather(NcTafWeatherCondition wthrCond) { - weather.add(wthrCond); - } - - public Set getProbable_weather() { - return probable_weather; - } - - public void setProbable_weather(Set weather) { - this.probable_weather = weather; - } - - /** - * @param add - * probable taf weather condition to set - */ - public void addProbable_weather(NcTafWeatherCondition wthrCond) { - probable_weather.add(wthrCond); - } - - public Set getSky_cover() { - return sky_cover; - } - - public void setSky_cover(Set sky_cover) { - this.sky_cover = sky_cover; - } - - /** - * @param add - * taf sky cover to set - */ - public void addSky_cover(NcTafSkyCover skyCvr) { - sky_cover.add(skyCvr); - } - - /** - * @param add - * probable taf sky cover to set - */ - public void addProbable_sky_cover(NcTafSkyCover skyCvr) { - probable_sky_cover.add(skyCvr); - } - - public Set getProbable_sky_cover() { - return probable_sky_cover; - } - - public void setProbable_sky_cover(Set sky_cover) { - this.probable_sky_cover = sky_cover; - } - - /** - * @return the theStartDate - */ - public Calendar getStartDate() { - return startDate; - } - - /** - * @param theStartDate - * the theStartDate to set - */ - public void setStartDate(Calendar start) { - startDate = start; - } - - /** - * @return the transitionEndDate - */ - public Calendar getTransitionEndDate() { - return transitionEndDate; - } - - /** - * @param transitionEndDate - * the transitionEndDate to set - */ - public void setTransitionEndDate(Calendar transitionEndDate) { - this.transitionEndDate = transitionEndDate; - } - - /** - * @return the theEndDate - */ - public Calendar getEndDate() { - return endDate; - } - - /** - * @param theEndDate - * the theEndDate to set - */ - public void setEndDate(Calendar end) { - endDate = end; - } - - public static String formatDate(Calendar dateTime) { - return String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS", dateTime); - } - - /** - * This method determines the ceiling value of a TAF. - */ - public static float getCeiling(Set skyCov, float vertVis) { - - // If a vertical visibility has been reported, the sky is obscured - // and the vertical visibility becomes the ceiling. - if (vertVis >= 0 && vertVis < 1e20f) { - return vertVis; - } else { - // Otherwise, determine the ceiling value. - return findTafCeilingFromLayers(sortSkyCover(skyCov)); - } - } - - public static Set sortSkyCover(Set skySet) { - if (skySet != null) { - SortedSet skSet = new TreeSet(); - for (NcTafSkyCover sc : skySet) { - skSet.add(sc); - } - return skSet; - } else { - return new HashSet(); - } - } - - /** - * This method calculates a floating point number representing the ceiling. - * By definition, the ceiling is the lowest overcast or broken cloud layer, - * so the method looks for the lowest layer that matches a BKN or OVC - * condition, and returns that layer. - * - * @param skyCov - * -- the set of sky coverage data - * @return -- the ceiling - */ - public static float findTafCeilingFromLayers(Set skyCov) { - float ceiling = 1e20f; - // Find a ceiling in a TAF report. - try { - for (NcTafSkyCover sc : skyCov) { - if (sc.getType().equals("CLR") || sc.getType().equals("SKC")) { - ceiling = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; - break; - } else if ((sc.getType().equals("BKN")) - || (sc.getType().equals("OVC"))) { - if (sc.getHeight() != null) { - ceiling = sc.getHeight(); - break; - } - } - - } - } catch (RuntimeException e) { - // ignore cloud cover that is null - } - return ceiling >= 1e20f ? IDecoderConstantsN.NEGATIVE_FLOAT_MISSING - : ceiling; - } - - /** - * Constructs an array of NcTafRecord PDOs given one or more bulletin - * records. (The bulletin records each contain data from a whole bulletin, - * while each NcTafRecord is more fine-grained -- representing the values - * for a single NcTafChangeGroup of the entire bulletin [NcTafBulletin]). We - * do this "reshuffle" because the - * NcTafBulletin/NcTafChangeGroup/NcTafSkyCover (same for - * NcTafTemperatureForecase, NcTafTurbulenceLayer, NcTafSkyCover, - * NcTafWeatherCondition) hierarchy efficiently represents the original - * structure as parsed from the text, but we want the persistent PDO - * (NcTafRecord) to be optimized for efficient access. - * - * @param bulletin - * the bulletin record to split - * @return NcTafRecord[] the array of NcTafRecord PDOs - */ - public static NcTafRecord[] split(NcTafBulletinRecord bulletin) { - List records = new ArrayList(); - if (bulletin.getChangeGroups() != null) { - Iterator chgGrps = bulletin.getChangeGroups() - .iterator(); - if (chgGrps != null) { - while (chgGrps.hasNext()) { - - NcTafRecord tfr = new NcTafRecord(); - - NcTafChangeGroup chgGrp = chgGrps.next(); - - tfr.setPersistenceTime(new Date()); - - NcTafPeriod validPeriod = chgGrp.getTafChangePeriod(); - Calendar cStart = TimeTools - .copy(validPeriod.getStartDate()); - - TimeRange range = new TimeRange(cStart, - validPeriod.getEndDate()); - DataTime tafPeriod = new DataTime(cStart, range); - - tfr.setDataTime(tafPeriod); - - if (bulletin.getTafValidPeriod() != null) - tfr.setTafValidPeriod(bulletin.getTafValidPeriod()); - - if (chgGrp.getTafChangePeriod() != null) - tfr.setTafChangePeriod(chgGrp.getTafChangePeriod()); - - if (chgGrp.getTafChangePeriod().getEndDate() != null) - tfr.setEndDate(chgGrp.getTafChangePeriod().getEndDate()); - - if (chgGrp.getTafChangePeriod().getStartDate() != null) - tfr.setStartDate(chgGrp.getTafChangePeriod() - .getStartDate()); - - if (chgGrp.getTafChangePeriod().getTransitionEndDate() != null) - tfr.setTransitionEndDate(chgGrp.getTafChangePeriod() - .getTransitionEndDate()); - - if (bulletin.getWmoHeader() != null) - tfr.setWmoHeader(bulletin.getWmoHeader()); - - if (bulletin.getTafText() != null) - tfr.setTafText(bulletin.getTafText()); - - if (bulletin.getReportType() != null) - tfr.setReportType(bulletin.getReportType()); - - if (bulletin.getStationId() != null) - tfr.setStationId(bulletin.getStationId()); - - if (bulletin.getCorIndicator() != null) { - tfr.setCorIndicator(bulletin.getCorIndicator()); - } else { - tfr.setCorIndicator(""); - } - - if (bulletin.getAmdIndicator() != null) { - tfr.setAmdIndicator(bulletin.getAmdIndicator()); - } else { - tfr.setAmdIndicator(""); - } - - if (bulletin.getIssue_time() != null) - tfr.setIssue_time(bulletin.getIssue_time()); - - if (bulletin.getIssue_timeString() != null) - tfr.setIssue_timeString(bulletin.getIssue_timeString()); - - if (bulletin.getBulletin_time() != null) - tfr.setBulletin_time(bulletin.getBulletin_time()); - - if (bulletin.getLocation() != null) - tfr.setLocation(bulletin.getLocation()); - - if (chgGrp.getChange_indicator() != null) - tfr.setChange_indicator(chgGrp.getChange_indicator()); - - if (chgGrp.getChangeGroup() != null) - tfr.setChangeGroup(chgGrp.getChangeGroup()); - - if (chgGrp.getProbability() != null) - tfr.setProbability(chgGrp.getProbability()); - - if (chgGrp.getMax_temp_c() != null) - tfr.setMax_temp_c(chgGrp.getMax_temp_c()); - - if (chgGrp.getMin_temp_c() != null) - tfr.setMin_temp_c(chgGrp.getMin_temp_c()); - - if (chgGrp.getAltim_in_hg() != null - && (chgGrp.getAltim_in_hg().trim().length() > 0)) { - tfr.setAltim_in_hg(Float.parseFloat(chgGrp - .getAltim_in_hg())); - } else { - tfr.setAltim_in_hg(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getRemarks() != null) - tfr.setRemarks(chgGrp.getRemarks()); - - if (chgGrp.getSequenceId() != null) - tfr.setSequenceId(chgGrp.getSequenceId()); - - VisibilityParser parser = new VisibilityParser(); - if (chgGrp.getVisibility_mi() != null - && parser.decode(chgGrp.getVisibility_mi() + "SM")) { - float val = (float) parser.getPrevail_vsbySM(); - tfr.setVisibility_mi(val); - } else { - tfr.setVisibility_mi(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getVert_vis_ft() != null - && (chgGrp.getVert_vis_ft().trim().length() > 0)) { - tfr.setVert_vis_ft(Float.parseFloat(chgGrp - .getVert_vis_ft())); - } else { - tfr.setVert_vis_ft(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getWind_dir_degrees() != null - && !chgGrp.getWind_dir_degrees().equalsIgnoreCase( - "VRB")) { - tfr.setWind_dir_degrees(Float.parseFloat(chgGrp - .getWind_dir_degrees())); - } else { - tfr.setWind_dir_degrees(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getWind_gust_kt() != null) { - tfr.setWind_gust_kt(new Float(chgGrp.getWind_gust_kt())); - } else { - tfr.setWind_gust_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getWind_speed_kt() != null) { - tfr.setWind_speed_kt(new Float(chgGrp - .getWind_speed_kt())); - } else { - tfr.setWind_speed_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getWind_shear_dir_degrees() != null) { - tfr.setWind_shear_dir_degrees(new Float(chgGrp - .getWind_shear_dir_degrees())); - } else { - tfr.setWind_shear_dir_degrees(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getWind_shear_speed_kt() != null) { - tfr.setWind_shear_speed_kt(new Float(chgGrp - .getWind_shear_speed_kt())); - } else { - tfr.setWind_shear_speed_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getWind_shear_hgt_ft_agl() != null) { - tfr.setWind_shear_hgt_ft_agl(new Float(chgGrp - .getWind_shear_hgt_ft_agl())); - } else { - tfr.setWind_shear_hgt_ft_agl(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getProbable_visibility_mi() != null - && parser.decode(chgGrp.getProbable_visibility_mi() - + "SM")) { - float val = (float) parser.getPrevail_vsbySM(); - tfr.setProbable_visibility_mi(val); - } else { - tfr.setProbable_visibility_mi(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getProbable_vert_vis_ft() != null - && (chgGrp.getProbable_vert_vis_ft().trim() - .length() > 0)) { - tfr.setProbable_vert_vis_ft(Float.parseFloat(chgGrp - .getProbable_vert_vis_ft())); - } else { - tfr.setProbable_vert_vis_ft(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getProbable_wind_dir_degrees() != null - && !chgGrp.getProbable_wind_dir_degrees() - .equalsIgnoreCase("VRB")) { - tfr.setProbable_wind_dir_degrees(Float - .parseFloat(chgGrp - .getProbable_wind_dir_degrees())); - } else { - tfr.setProbable_wind_dir_degrees(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getProbable_wind_gust_kt() != null) { - tfr.setProbable_wind_gust_kt(new Float(chgGrp - .getProbable_wind_gust_kt())); - } else { - tfr.setProbable_wind_gust_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getProbable_wind_speed_kt() != null) { - tfr.setProbable_wind_speed_kt(new Float(chgGrp - .getProbable_wind_speed_kt())); - } else { - tfr.setProbable_wind_speed_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getProbable_wind_shear_dir_degrees() != null) { - tfr.setProbable_wind_speed_kt(new Float(chgGrp - .getProbable_wind_shear_dir_degrees())); - } else { - tfr.setWind_shear_dir_degrees(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getProbable_wind_shear_speed_kt() != null) { - tfr.setWind_shear_speed_kt(new Float(chgGrp - .getProbable_wind_shear_speed_kt())); - } else { - tfr.setWind_shear_speed_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getProbable_wind_shear_hgt_ft_agl() != null) { - tfr.setProbable_wind_shear_hgt_ft_agl(new Float(chgGrp - .getProbable_wind_shear_hgt_ft_agl())); - } else { - tfr.setProbable_wind_shear_hgt_ft_agl(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); - } - - if (chgGrp.getIcing_layers() != null) { - tfr.setIcing_layers(chgGrp.getIcing_layers()); - } - - if (chgGrp.getSky_cover() != null) { - tfr.setSky_cover(chgGrp.getSky_cover()); - } - - if (chgGrp.getProbable_sky_cover() != null) { - tfr.setProbable_sky_cover(chgGrp - .getProbable_sky_cover()); - } - - if (chgGrp.getTemp_forecasts() != null) { - tfr.setTemp_forecasts(chgGrp.getTemp_forecasts()); - } - - if (chgGrp.getTurbulence_layers() != null) { - tfr.setTurbulence_layers(chgGrp.getTurbulence_layers()); - } - - if (chgGrp.getWeather() != null) { - tfr.setWeather(chgGrp.getWeather()); - } - - records.add(tfr); - } - - } - } - - List hourlyRecords = splitToHourlyRecords(records); - - return hourlyRecords.toArray(new NcTafRecord[0]); - } - - public static List splitToHourlyRecords( - List records) { - List newRecords = new ArrayList(); - int recordsSize = (records != null) ? records.size() : 0; - - if (recordsSize > 0) { - - for (int i = 0; i < recordsSize; i++) { - - NcTafRecord record = records.get(i); - - Calendar startRefTime = record.getStartDate(); - Calendar endRefTime = record.getEndDate(); - - // add 1 minute so that 12:30 becomes 12:31 and hence is rounded - // to 13:00 and not 12:00 - startRefTime.add(Calendar.MINUTE, 1); - Date nearestHour = DateUtils.round(startRefTime.getTime(), - Calendar.HOUR); - startRefTime.setTime(nearestHour); - - nearestHour = DateUtils.round(endRefTime.getTime(), - Calendar.HOUR); - endRefTime.setTime(nearestHour); - - long milliseconds1 = startRefTime.getTimeInMillis(); - long milliseconds2 = endRefTime.getTimeInMillis(); - long diff = milliseconds2 - milliseconds1; - long diffHours = diff / (60 * 60 * 1000); - - for (int hour = 0; hour < diffHours; hour++) { - - NcTafRecord tfr = new NcTafRecord(); - - tfr.setPersistenceTime(new Date()); - tfr.setDataTime(new DataTime(startRefTime)); - tfr.setTafValidPeriod(record.getTafValidPeriod()); - tfr.setTafChangePeriod(record.getTafChangePeriod()); - tfr.setEndDate(record.getTafChangePeriod().getEndDate()); - tfr.setStartDate(record.getTafChangePeriod().getStartDate()); - tfr.setTransitionEndDate(record.getTafChangePeriod() - .getTransitionEndDate()); - tfr.setWmoHeader(record.getWmoHeader()); - if (record.getTafText() != null - && record.getTafText().length() > 1024) { - tfr.setTafText(record.getTafText().substring(0, 1024)); - } else { - tfr.setTafText(record.getTafText()); - } - tfr.setTafText(record.getTafText()); - tfr.setReportType(record.getReportType()); - tfr.setStationId(record.getStationId()); - tfr.setCorIndicator(record.getCorIndicator()); - tfr.setAmdIndicator(record.getAmdIndicator()); - tfr.setIssue_time(record.getIssue_time()); - tfr.setIssue_timeString(record.getIssue_timeString()); - tfr.setBulletin_time(record.getBulletin_time()); - tfr.setLocation(record.getLocation()); - tfr.setChange_indicator(record.getChange_indicator()); - if (record.getChangeGroup() != null - && record.getChangeGroup().length() > 128) { - tfr.setChangeGroup(record.getChangeGroup().substring(0, - 128)); - } else { - tfr.setChangeGroup(record.getChangeGroup()); - } - tfr.setChangeGroup(record.getChangeGroup()); - tfr.setProbability(record.getProbability()); - tfr.setMax_temp_c(record.getMax_temp_c()); - tfr.setMin_temp_c(record.getMin_temp_c()); - tfr.setAltim_in_hg(record.getAltim_in_hg()); - tfr.setRemarks(record.getRemarks()); - tfr.setSequenceId(record.getSequenceId()); - tfr.setVisibility_mi(record.getVisibility_mi()); - tfr.setVert_vis_ft(record.getVert_vis_ft()); - tfr.setWind_dir_degrees(record.getWind_dir_degrees()); - tfr.setWind_gust_kt(record.getWind_gust_kt()); - tfr.setWind_speed_kt(record.getWind_speed_kt()); - tfr.setWind_shear_dir_degrees(record - .getWind_shear_dir_degrees()); - tfr.setWind_shear_speed_kt(record.getWind_shear_speed_kt()); - tfr.setWind_shear_hgt_ft_agl(record - .getWind_shear_hgt_ft_agl()); - tfr.setProbable_visibility_mi(record - .getProbable_visibility_mi()); - tfr.setProbable_vert_vis_ft(record - .getProbable_vert_vis_ft()); - tfr.setProbable_wind_dir_degrees(record - .getProbable_wind_dir_degrees()); - tfr.setProbable_wind_gust_kt(record - .getProbable_wind_gust_kt()); - tfr.setProbable_wind_speed_kt(record - .getProbable_wind_speed_kt()); - tfr.setWind_shear_dir_degrees(record - .getProbable_wind_shear_dir_degrees()); - tfr.setWind_shear_speed_kt(record - .getProbable_wind_shear_speed_kt()); - tfr.setProbable_wind_shear_hgt_ft_agl(record - .getProbable_wind_shear_hgt_ft_agl()); - tfr.setIcing_layers(record.getIcing_layers()); - tfr.setSky_cover(record.getSky_cover()); - tfr.setProbable_sky_cover(record.getProbable_sky_cover()); - tfr.setTemp_forecasts(record.getTemp_forecasts()); - tfr.setTurbulence_layers(record.getTurbulence_layers()); - tfr.setWeather(record.getWeather()); - tfr.setProbable_weather(record.getWeather()); - newRecords.add(tfr); - startRefTime.add(Calendar.HOUR_OF_DAY, 1); - } - } - } - - return newRecords; - } + IDecoderGettable, IPointData, IPersistable { + + private static final long serialVersionUID = 1L; + + @DynamicSerializeElement + @XmlElement + @Column + private String wmoHeader; + + @DynamicSerializeElement + @XmlElement + // @Column(length = 1024) + @Transient + private String tafText; + + // The observation report type. + @DataURI(position = 1) + @Column + @XmlElement + @DynamicSerializeElement + private String reportType; + + @Embedded + @DataURI(position = 2, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; + + // Station Identifier for the data + @DynamicSerializeElement + @XmlElement + @Transient + // @Index(name = "nctaf_stationIndex") + private String stationId; + + @DynamicSerializeElement + @XmlElement + @Column + @DataURI(position = 3) + private String corIndicator; + + @DynamicSerializeElement + @XmlElement + @Column + @DataURI(position = 4) + private String amdIndicator; + + /** Issue date */ + @DynamicSerializeElement + @XmlElement + @Column + // @DataURI(position = 4) + private Date issue_time; + + /** Issue date string */ + @DynamicSerializeElement + @XmlElement + @Column + @DataURI(position = 5) + private String issue_timeString; + + /** Bulletin issuance time */ + @DynamicSerializeElement + @XmlElement + @Transient + private Date bulletin_time; + + /** Any remarks contained in the TAF record */ + @DynamicSerializeElement + @XmlElement + @Transient + private String remarks; + + /** A String containing the change group */ + @DynamicSerializeElement + @XmlElement + // @Column + @Transient + private String changeGroup; + + /** The period for which the TAF is valid */ + @DynamicSerializeElement + @XmlElement + @Embedded + @Transient + private NcTafPeriod tafChangePeriod; + + /** + * The forecast valid starting date + */ + @DynamicSerializeElement + @XmlElement + @Transient + private Calendar startDate; + + // This time is only used for BECMG groups. It marks the end time of the + // BECMG transition period. + @DynamicSerializeElement + @XmlElement + @Transient + private Calendar transitionEndDate; + + /** + * The forecast valid ending date + */ + @DynamicSerializeElement + @XmlElement + @Transient + private Calendar endDate; + + /** + * The sequence id is used to physically order a collection of ChangeGroups. + * This is required because the start times may be ambiguous i.e. A BECMG + * and TEMPO change group could share the same start time. + */ + @DynamicSerializeElement + @XmlElement + @Column + @DataURI(position = 6) + private Integer sequenceId; + + /** + * The change group indicator i.e. BECMG, FM, TEMPO, etc + */ + @DynamicSerializeElement + @XmlElement + @Column + @DataURI(position = 7) + private String change_indicator; + + /** + * The probability percentage for PROB and PROB TEMPO change groups. + */ + @DynamicSerializeElement + @XmlElement + @Transient + private Integer probability; + + /** Wind direction in degrees */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float wind_dir_degrees; + + /** Wind speed in knots */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float wind_speed_kt; + + /** Wind gust in knots */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float wind_gust_kt; + + /** Wind shear height above ground level */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float wind_shear_hgt_ft_agl; + + /** Wind shear direction in degrees */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float wind_shear_dir_degrees; + + /** Wind shear speed in knots */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float wind_shear_speed_kt; + + /** Visibility (horizontal) in miles */ + @DynamicSerializeElement + @XmlElement + @Column + private Float visibility_mi; + + /** Altimeter reading in inches of mercury */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float altim_in_hg; + + /** Vertical visibility */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float vert_vis_ft; + + /** Maximum temperature */ + @DynamicSerializeElement + @XmlElement + @Transient + private Integer max_temp_c; + + /** Minimum temperature */ + @DynamicSerializeElement + @XmlElement + @Transient + private Integer min_temp_c; + + /** Wind direction in degrees (TEMPO/PROB) */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float probable_wind_dir_degrees; + + /** Wind speed in knots (TEMPO/PROB) */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float probable_wind_speed_kt; + + /** Wind gust in knots (TEMPO/PROB) */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float probable_wind_gust_kt; + + /** Wind shear height above ground level (TEMPO/PROB) */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float probable_wind_shear_hgt_ft_agl; + + /** Wind shear direction in degrees (TEMPO/PROB) */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float probable_wind_shear_dir_degrees; + + /** Wind shear speed in knots (TEMPO/PROB) */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float probable_wind_shear_speed_kt; + + /** Visibility (horizontal) in miles (TEMPO/PROB) */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float probable_visibility_mi; + + /** Vertical visibility (TEMPO/PROB) */ + @DynamicSerializeElement + @XmlElement + @Transient + private Float probable_vert_vis_ft; + + /** + * The valid period for the TAF record. + */ + @DynamicSerializeElement + @XmlElement + private NcTafPeriod tafValidPeriod; + + /** + * Weather and obscurations + */ + @DynamicSerializeElement + @XmlElement + @Transient + private Set weather; + + /** + * (TEMPO/PROB) Weather and obscurations + */ + @DynamicSerializeElement + @XmlElement + @Transient + private Set probable_weather; + + /** Sky coverage */ + @DynamicSerializeElement + @XmlElement + @Transient + private Set sky_cover; + + /** (TEMPO/PROB) Sky coverage */ + @DynamicSerializeElement + @XmlElement + @Transient + private Set probable_sky_cover; + + /** The turbulence layers */ + @DynamicSerializeElement + @XmlElement + @Transient + private Set turbulence_layers; + + /** The icing layers */ + @DynamicSerializeElement + @XmlElement + @Transient + private Set icing_layers; + + /** The temperature forecasts */ + @DynamicSerializeElement + @XmlElement + @Transient + private Set temp_forecasts; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + // private Integer hdfFileId; + + public NcTafRecord() { + wmoHeader = " "; + tafText = " "; + reportType = "TAF"; + stationId = " "; + bulletin_time = null; + corIndicator = " "; + amdIndicator = " "; + issue_timeString = " "; + remarks = " "; + changeGroup = " "; + altim_in_hg = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + change_indicator = " "; + max_temp_c = IDecoderConstantsN.NEGATIVE_INTEGER_MISSING; + min_temp_c = IDecoderConstantsN.NEGATIVE_INTEGER_MISSING; + probability = IDecoderConstantsN.NEGATIVE_INTEGER_MISSING; + remarks = " "; + sequenceId = IDecoderConstantsN.NEGATIVE_INTEGER_MISSING; + vert_vis_ft = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + visibility_mi = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + wind_dir_degrees = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + wind_gust_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + wind_speed_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + wind_shear_hgt_ft_agl = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + wind_shear_dir_degrees = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + wind_shear_speed_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + startDate = null; + endDate = null; + transitionEndDate = null; + location = null; + probable_vert_vis_ft = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + probable_visibility_mi = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + probable_wind_dir_degrees = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + probable_wind_gust_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + probable_wind_speed_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + probable_wind_shear_hgt_ft_agl = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + probable_wind_shear_dir_degrees = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + probable_wind_shear_speed_kt = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + } + + /** + * Constructs a taf record from a dataURI + * + * @param uri + * The dataURI + * @param tableDef + * The table definition associated with this class + */ + public NcTafRecord(String uri) { + super(uri); + } + + /** + * Get the WMO header for the enclosing WMO message. + * + * @return The wmoHeader. + */ + public String getWmoHeader() { + return wmoHeader; + } + + /** + * Set the WMO header for the enclosing WMO message. + * + * @param wmoHeader + * The WMOHeader to set. + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } + + /** + * Get the text of this terminal forecast. + * + * @return The terminal forecast text. + */ + public String getTafText() { + return tafText; + } + + /** + * Set the text of this terminal forecast. + * + * @param tafText + * The terminal forecast text. + */ + public void setTafText(String tafText) { + this.tafText = tafText; + } + + /** + * Get the observation report type. + * + * @return the reportType + */ + public String getReportType() { + return reportType; + } + + /** + * Set the observation report type. + * + * @param reportType + * the reportType to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } + + /** + * + * @return + */ + public String getStationId() { + return stationId; + } + + /** + * + * @param stationID + */ + public void setStationId(String stationID) { + stationId = stationID; + } + + /** + * + * @return the corIndicator + */ + public String getCorIndicator() { + return corIndicator; + } + + /** + * + * @param corIndicator + * the corIndicator to set + */ + public void setCorIndicator(String corIndicator) { + this.corIndicator = corIndicator; + } + + /** + * + * @return the amdIndicator + */ + public String getAmdIndicator() { + return amdIndicator; + } + + /** + * + * @param amdIndicator + * the amdIndicator to set + */ + public void setAmdIndicator(String amdIndicator) { + this.amdIndicator = amdIndicator; + } + + /** + * + * @return the bulletin_time + */ + public Date getBulletin_time() { + return bulletin_time; + } + + /** + * + * @param bulletin_time + * the bulletin_time to set + */ + public void setBulletin_time(Date bulletin_time) { + this.bulletin_time = bulletin_time; + } + + /** + * @return the issue_time + */ + public Date getIssue_time() { + return issue_time; + } + + /** + * @param issue_time + * the issue_time to set + */ + public void setIssue_time(Date issue_time) { + this.issue_time = issue_time; + } + + /** + * @return the issue_timeString + */ + public String getIssue_timeString() { + return issue_timeString; + } + + /** + * @param issue_timeString + * the issue_time to set + */ + public void setIssue_timeString(String issue_timeString) { + this.issue_timeString = issue_timeString; + } + + @Override + public void setIdentifier(Object dataURI) { + + this.identifier = dataURI; + + } + + /** + * Get the IDecoderGettable reference for this record. + * + * @return The IDecoderGettable reference for this record. Null for this + * class. + */ + @Override + public IDecoderGettable getDecoderGettable() { + return null; + } + + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } + + public SurfaceObsLocation getLocation() { + return location; + } + + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } + + public double getLatitude() { + return location.getLatitude(); + } + + public double getLongitude() { + return location.getLongitude(); + } + + public Integer getElevation() { + return location.getElevation(); + } + + /** + * Returns the hashCode for this object. This implementation returns the + * hashCode of the generated dataURI. + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + + ((getDataURI() == null) ? 0 : getDataURI().hashCode()); + return result; + } + + /** + * Checks if this record is equal to another by checking the generated + * dataURI. + * + * @param obj + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + NcTafRecord other = (NcTafRecord) obj; + if (getDataURI() == null) { + if (other.getDataURI() != null) { + return false; + } + } else if (!getDataURI().equals(other.getDataURI())) { + return false; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() + */ + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon + * .uf.common.pointdata.PointDataView) + */ + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + + /** + * Get the time to use for persisting this data. + * + * @return The persistence time for this data. + */ + @Override + public Date getPersistenceTime() { + if (getInsertTime() == null) { + return null; + } else { + return getInsertTime().getTime(); + } + } + + /** + * Set the time to be used for the persistence time for this object. + * + * @param persistTime + * The persistence time to be used. + */ + @Override + public void setPersistenceTime(Date persistTime) { + Calendar insertTime = Calendar.getInstance(); + insertTime.setTime(persistTime); + setInsertTime(insertTime); + } + + @Override + public Amount getValue(String paramName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getValues(String paramName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getString(String paramName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String[] getStrings(String paramName) { + // TODO Auto-generated method stub + return null; + } + + /** + * + * @return The string containing the change group text + */ + public String getChangeGroup() { + return this.changeGroup; + } + + public void setChangeGroup(String changeGroup) { + this.changeGroup = changeGroup; + } + + public NcTafPeriod getTafChangePeriod() { + return tafChangePeriod; + } + + public void setTafChangePeriod(NcTafPeriod tafChangePeriod) { + this.tafChangePeriod = tafChangePeriod; + } + + public Float getWind_dir_degrees() { + return wind_dir_degrees; + } + + public void setWind_dir_degrees(Float wind_dir_degrees) { + this.wind_dir_degrees = wind_dir_degrees; + } + + public Float getWind_speed_kt() { + return wind_speed_kt; + } + + public void setWind_speed_kt(Float wind_speed_kt) { + this.wind_speed_kt = wind_speed_kt; + } + + public Float getWind_gust_kt() { + return wind_gust_kt; + } + + public void setWind_gust_kt(Float wind_gust_kt) { + this.wind_gust_kt = wind_gust_kt; + } + + public Float getWind_shear_hgt_ft_agl() { + return wind_shear_hgt_ft_agl; + } + + public void setWind_shear_hgt_ft_agl(Float wind_shear_hgt_ft_agl) { + this.wind_shear_hgt_ft_agl = wind_shear_hgt_ft_agl; + } + + public Float getWind_shear_dir_degrees() { + return wind_shear_dir_degrees; + } + + public void setWind_shear_dir_degrees(Float wind_shear_dir_degrees) { + this.wind_shear_dir_degrees = wind_shear_dir_degrees; + } + + public Float getWind_shear_speed_kt() { + return wind_shear_speed_kt; + } + + public void setWind_shear_speed_kt(Float wind_shear_speed_kt) { + this.wind_shear_speed_kt = wind_shear_speed_kt; + } + + public Float getVisibility_mi() { + return visibility_mi; + } + + public void setVisibility_mi(Float visibility_mi) { + this.visibility_mi = visibility_mi; + } + + public float getAltim_in_hg() { + return altim_in_hg; + } + + public void setAltim_in_hg(float altim_in_hg) { + this.altim_in_hg = altim_in_hg; + } + + public float getVert_vis_ft() { + return probable_vert_vis_ft; + } + + public void setVert_vis_ft(float vert_vis_ft) { + this.probable_vert_vis_ft = vert_vis_ft; + } + + public float getProbable_wind_dir_degrees() { + return probable_wind_dir_degrees; + } + + public void setProbable_wind_dir_degrees(float wind_dir_degrees) { + this.probable_wind_dir_degrees = wind_dir_degrees; + } + + public float getProbable_wind_speed_kt() { + return probable_wind_speed_kt; + } + + public void setProbable_wind_speed_kt(float wind_speed_kt) { + this.probable_wind_speed_kt = wind_speed_kt; + } + + public float getProbable_wind_gust_kt() { + return probable_wind_gust_kt; + } + + public void setProbable_wind_gust_kt(float wind_gust_kt) { + this.probable_wind_gust_kt = wind_gust_kt; + } + + public float getProbable_wind_shear_hgt_ft_agl() { + return probable_wind_shear_hgt_ft_agl; + } + + public void setProbable_wind_shear_hgt_ft_agl(float wind_shear_hgt_ft_agl) { + this.probable_wind_shear_hgt_ft_agl = wind_shear_hgt_ft_agl; + } + + public float getProbable_wind_shear_dir_degrees() { + return probable_wind_shear_dir_degrees; + } + + public void setProbable_wind_shear_dir_degrees(float wind_shear_dir_degrees) { + this.probable_wind_shear_dir_degrees = wind_shear_dir_degrees; + } + + public float getProbable_wind_shear_speed_kt() { + return probable_wind_shear_speed_kt; + } + + public void setProbable_wind_shear_speed_kt(float wind_shear_speed_kt) { + this.probable_wind_shear_speed_kt = wind_shear_speed_kt; + } + + public float getProbable_visibility_mi() { + return probable_visibility_mi; + } + + public void setProbable_visibility_mi(float visibility_mi) { + this.probable_visibility_mi = visibility_mi; + } + + public float getProbable_vert_vis_ft() { + return probable_vert_vis_ft; + } + + public void setProbable_vert_vis_ft(float vert_vis_ft) { + this.probable_vert_vis_ft = vert_vis_ft; + } + + public Integer getMax_temp_c() { + return max_temp_c; + } + + public void setMax_temp_c(Integer max_temp_c) { + this.max_temp_c = max_temp_c; + } + + public Integer getMin_temp_c() { + return min_temp_c; + } + + public void setMin_temp_c(Integer min_temp_c) { + this.min_temp_c = min_temp_c; + } + + public Integer getProbability() { + return probability; + } + + public void setProbability(Integer probability) { + this.probability = probability; + } + + /** + * @return the sequenceId + */ + public Integer getSequenceId() { + return sequenceId; + } + + /** + * @param sequenceId + * the sequenceId to set + */ + public void setSequenceId(Integer sequenceId) { + this.sequenceId = sequenceId; + } + + /** + * @return the remarks + */ + public String getRemarks() { + return remarks; + } + + /** + * @param remarks + * the remarks to set + */ + public void setRemarks(String remarks) { + this.remarks = remarks; + } + + public String getChange_indicator() { + return change_indicator; + } + + public void setChange_indicator(String change_indicator) { + this.change_indicator = change_indicator; + } + + public NcTafPeriod getTafValidPeriod() { + return tafValidPeriod; + } + + public void setTafValidPeriod(NcTafPeriod tafValidPeriod) { + this.tafValidPeriod = tafValidPeriod; + } + + public Set getTurbulence_layers() { + return turbulence_layers; + } + + public void setTurbulence_layers(Set turbulence_layers) { + this.turbulence_layers = turbulence_layers; + } + + /** + * @param add + * taf turbulence layer to set + */ + public void addTurbulence_layer(NcTafTurbulenceLayer turb) { + turbulence_layers.add(turb); + } + + public Set getIcing_layers() { + return icing_layers; + } + + public void setIcing_layers(Set icing_layers) { + this.icing_layers = icing_layers; + } + + /** + * @param add + * taf icing layer to set + */ + public void addIcing_layer(NcTafIcingLayer icng) { + icing_layers.add(icng); + } + + public Set getTemp_forecasts() { + return temp_forecasts; + } + + public void setTemp_forecasts(Set temp_forecasts) { + this.temp_forecasts = temp_forecasts; + } + + /** + * @param add + * taf temp forecast to set + */ + public void addTemp_forecast(NcTafTemperatureForecast tempFcst) { + temp_forecasts.add(tempFcst); + } + + public Set getWeather() { + return weather; + } + + public void setWeather(Set weather) { + this.weather = weather; + } + + /** + * @param add + * taf weather condition to set + */ + public void addWeather(NcTafWeatherCondition wthrCond) { + weather.add(wthrCond); + } + + public Set getProbable_weather() { + return probable_weather; + } + + public void setProbable_weather(Set weather) { + this.probable_weather = weather; + } + + /** + * @param add + * probable taf weather condition to set + */ + public void addProbable_weather(NcTafWeatherCondition wthrCond) { + probable_weather.add(wthrCond); + } + + public Set getSky_cover() { + return sky_cover; + } + + public void setSky_cover(Set sky_cover) { + this.sky_cover = sky_cover; + } + + /** + * @param add + * taf sky cover to set + */ + public void addSky_cover(NcTafSkyCover skyCvr) { + sky_cover.add(skyCvr); + } + + /** + * @param add + * probable taf sky cover to set + */ + public void addProbable_sky_cover(NcTafSkyCover skyCvr) { + probable_sky_cover.add(skyCvr); + } + + public Set getProbable_sky_cover() { + return probable_sky_cover; + } + + public void setProbable_sky_cover(Set sky_cover) { + this.probable_sky_cover = sky_cover; + } + + /** + * @return the theStartDate + */ + public Calendar getStartDate() { + return startDate; + } + + /** + * @param theStartDate + * the theStartDate to set + */ + public void setStartDate(Calendar start) { + startDate = start; + } + + /** + * @return the transitionEndDate + */ + public Calendar getTransitionEndDate() { + return transitionEndDate; + } + + /** + * @param transitionEndDate + * the transitionEndDate to set + */ + public void setTransitionEndDate(Calendar transitionEndDate) { + this.transitionEndDate = transitionEndDate; + } + + /** + * @return the theEndDate + */ + public Calendar getEndDate() { + return endDate; + } + + /** + * @param theEndDate + * the theEndDate to set + */ + public void setEndDate(Calendar end) { + endDate = end; + } + + public static String formatDate(Calendar dateTime) { + return String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS", dateTime); + } + + /** + * This method determines the ceiling value of a TAF. + */ + public static float getCeiling(Set skyCov, float vertVis) { + + // If a vertical visibility has been reported, the sky is obscured + // and the vertical visibility becomes the ceiling. + if ((vertVis >= 0) && (vertVis < 1e20f)) { + return vertVis; + } else { + // Otherwise, determine the ceiling value. + return findTafCeilingFromLayers(sortSkyCover(skyCov)); + } + } + + public static Set sortSkyCover(Set skySet) { + if (skySet != null) { + SortedSet skSet = new TreeSet(); + for (NcTafSkyCover sc : skySet) { + skSet.add(sc); + } + return skSet; + } else { + return new HashSet(); + } + } + + /** + * This method calculates a floating point number representing the ceiling. + * By definition, the ceiling is the lowest overcast or broken cloud layer, + * so the method looks for the lowest layer that matches a BKN or OVC + * condition, and returns that layer. + * + * @param skyCov + * -- the set of sky coverage data + * @return -- the ceiling + */ + public static float findTafCeilingFromLayers(Set skyCov) { + float ceiling = 1e20f; + // Find a ceiling in a TAF report. + try { + for (NcTafSkyCover sc : skyCov) { + if (sc.getType().equals("CLR") || sc.getType().equals("SKC")) { + ceiling = IDecoderConstantsN.NEGATIVE_FLOAT_MISSING; + break; + } else if ((sc.getType().equals("BKN")) + || (sc.getType().equals("OVC"))) { + if (sc.getHeight() != null) { + ceiling = sc.getHeight(); + break; + } + } + + } + } catch (RuntimeException e) { + // ignore cloud cover that is null + } + return ceiling >= 1e20f ? IDecoderConstantsN.NEGATIVE_FLOAT_MISSING + : ceiling; + } + + /** + * Constructs an array of NcTafRecord PDOs given one or more bulletin + * records. (The bulletin records each contain data from a whole bulletin, + * while each NcTafRecord is more fine-grained -- representing the values + * for a single NcTafChangeGroup of the entire bulletin [NcTafBulletin]). We + * do this "reshuffle" because the + * NcTafBulletin/NcTafChangeGroup/NcTafSkyCover (same for + * NcTafTemperatureForecase, NcTafTurbulenceLayer, NcTafSkyCover, + * NcTafWeatherCondition) hierarchy efficiently represents the original + * structure as parsed from the text, but we want the persistent PDO + * (NcTafRecord) to be optimized for efficient access. + * + * @param bulletin + * the bulletin record to split + * @return NcTafRecord[] the array of NcTafRecord PDOs + */ + public static NcTafRecord[] split(NcTafBulletinRecord bulletin) { + List records = new ArrayList(); + if (bulletin.getChangeGroups() != null) { + Iterator chgGrps = bulletin.getChangeGroups() + .iterator(); + if (chgGrps != null) { + while (chgGrps.hasNext()) { + + NcTafRecord tfr = new NcTafRecord(); + + NcTafChangeGroup chgGrp = chgGrps.next(); + + tfr.setPersistenceTime(new Date()); + + NcTafPeriod validPeriod = chgGrp.getTafChangePeriod(); + Calendar cStart = TimeTools + .copy(validPeriod.getStartDate()); + + TimeRange range = new TimeRange(cStart, + validPeriod.getEndDate()); + DataTime tafPeriod = new DataTime(cStart, range); + + tfr.setDataTime(tafPeriod); + + if (bulletin.getTafValidPeriod() != null) { + tfr.setTafValidPeriod(bulletin.getTafValidPeriod()); + } + + if (chgGrp.getTafChangePeriod() != null) { + tfr.setTafChangePeriod(chgGrp.getTafChangePeriod()); + } + + if (chgGrp.getTafChangePeriod().getEndDate() != null) { + tfr.setEndDate(chgGrp.getTafChangePeriod().getEndDate()); + } + + if (chgGrp.getTafChangePeriod().getStartDate() != null) { + tfr.setStartDate(chgGrp.getTafChangePeriod() + .getStartDate()); + } + + if (chgGrp.getTafChangePeriod().getTransitionEndDate() != null) { + tfr.setTransitionEndDate(chgGrp.getTafChangePeriod() + .getTransitionEndDate()); + } + + if (bulletin.getWmoHeader() != null) { + tfr.setWmoHeader(bulletin.getWmoHeader()); + } + + if (bulletin.getTafText() != null) { + tfr.setTafText(bulletin.getTafText()); + } + + if (bulletin.getReportType() != null) { + tfr.setReportType(bulletin.getReportType()); + } + + if (bulletin.getStationId() != null) { + tfr.setStationId(bulletin.getStationId()); + } + + if (bulletin.getCorIndicator() != null) { + tfr.setCorIndicator(bulletin.getCorIndicator()); + } else { + tfr.setCorIndicator(""); + } + + if (bulletin.getAmdIndicator() != null) { + tfr.setAmdIndicator(bulletin.getAmdIndicator()); + } else { + tfr.setAmdIndicator(""); + } + + if (bulletin.getIssue_time() != null) { + tfr.setIssue_time(bulletin.getIssue_time()); + } + + if (bulletin.getIssue_timeString() != null) { + tfr.setIssue_timeString(bulletin.getIssue_timeString()); + } + + if (bulletin.getBulletin_time() != null) { + tfr.setBulletin_time(bulletin.getBulletin_time()); + } + + if (bulletin.getLocation() != null) { + tfr.setLocation(bulletin.getLocation()); + } + + if (chgGrp.getChange_indicator() != null) { + tfr.setChange_indicator(chgGrp.getChange_indicator()); + } + + if (chgGrp.getChangeGroup() != null) { + tfr.setChangeGroup(chgGrp.getChangeGroup()); + } + + if (chgGrp.getProbability() != null) { + tfr.setProbability(chgGrp.getProbability()); + } + + if (chgGrp.getMax_temp_c() != null) { + tfr.setMax_temp_c(chgGrp.getMax_temp_c()); + } + + if (chgGrp.getMin_temp_c() != null) { + tfr.setMin_temp_c(chgGrp.getMin_temp_c()); + } + + if ((chgGrp.getAltim_in_hg() != null) + && (chgGrp.getAltim_in_hg().trim().length() > 0)) { + tfr.setAltim_in_hg(Float.parseFloat(chgGrp + .getAltim_in_hg())); + } else { + tfr.setAltim_in_hg(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getRemarks() != null) { + tfr.setRemarks(chgGrp.getRemarks()); + } + + if (chgGrp.getSequenceId() != null) { + tfr.setSequenceId(chgGrp.getSequenceId()); + } + + VisibilityParser parser = new VisibilityParser(); + if ((chgGrp.getVisibility_mi() != null) + && parser.decode(chgGrp.getVisibility_mi() + "SM")) { + float val = (float) parser.getPrevail_vsbySM(); + tfr.setVisibility_mi(val); + } else { + tfr.setVisibility_mi(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if ((chgGrp.getVert_vis_ft() != null) + && (chgGrp.getVert_vis_ft().trim().length() > 0)) { + tfr.setVert_vis_ft(Float.parseFloat(chgGrp + .getVert_vis_ft())); + } else { + tfr.setVert_vis_ft(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if ((chgGrp.getWind_dir_degrees() != null) + && !chgGrp.getWind_dir_degrees().equalsIgnoreCase( + "VRB")) { + tfr.setWind_dir_degrees(Float.parseFloat(chgGrp + .getWind_dir_degrees())); + } else { + tfr.setWind_dir_degrees(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getWind_gust_kt() != null) { + tfr.setWind_gust_kt(new Float(chgGrp.getWind_gust_kt())); + } else { + tfr.setWind_gust_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getWind_speed_kt() != null) { + tfr.setWind_speed_kt(new Float(chgGrp + .getWind_speed_kt())); + } else { + tfr.setWind_speed_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getWind_shear_dir_degrees() != null) { + tfr.setWind_shear_dir_degrees(new Float(chgGrp + .getWind_shear_dir_degrees())); + } else { + tfr.setWind_shear_dir_degrees(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getWind_shear_speed_kt() != null) { + tfr.setWind_shear_speed_kt(new Float(chgGrp + .getWind_shear_speed_kt())); + } else { + tfr.setWind_shear_speed_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getWind_shear_hgt_ft_agl() != null) { + tfr.setWind_shear_hgt_ft_agl(new Float(chgGrp + .getWind_shear_hgt_ft_agl())); + } else { + tfr.setWind_shear_hgt_ft_agl(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if ((chgGrp.getProbable_visibility_mi() != null) + && parser.decode(chgGrp.getProbable_visibility_mi() + + "SM")) { + float val = (float) parser.getPrevail_vsbySM(); + tfr.setProbable_visibility_mi(val); + } else { + tfr.setProbable_visibility_mi(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if ((chgGrp.getProbable_vert_vis_ft() != null) + && (chgGrp.getProbable_vert_vis_ft().trim() + .length() > 0)) { + tfr.setProbable_vert_vis_ft(Float.parseFloat(chgGrp + .getProbable_vert_vis_ft())); + } else { + tfr.setProbable_vert_vis_ft(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if ((chgGrp.getProbable_wind_dir_degrees() != null) + && !chgGrp.getProbable_wind_dir_degrees() + .equalsIgnoreCase("VRB")) { + tfr.setProbable_wind_dir_degrees(Float + .parseFloat(chgGrp + .getProbable_wind_dir_degrees())); + } else { + tfr.setProbable_wind_dir_degrees(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getProbable_wind_gust_kt() != null) { + tfr.setProbable_wind_gust_kt(new Float(chgGrp + .getProbable_wind_gust_kt())); + } else { + tfr.setProbable_wind_gust_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getProbable_wind_speed_kt() != null) { + tfr.setProbable_wind_speed_kt(new Float(chgGrp + .getProbable_wind_speed_kt())); + } else { + tfr.setProbable_wind_speed_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getProbable_wind_shear_dir_degrees() != null) { + tfr.setProbable_wind_speed_kt(new Float(chgGrp + .getProbable_wind_shear_dir_degrees())); + } else { + tfr.setWind_shear_dir_degrees(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getProbable_wind_shear_speed_kt() != null) { + tfr.setWind_shear_speed_kt(new Float(chgGrp + .getProbable_wind_shear_speed_kt())); + } else { + tfr.setWind_shear_speed_kt(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getProbable_wind_shear_hgt_ft_agl() != null) { + tfr.setProbable_wind_shear_hgt_ft_agl(new Float(chgGrp + .getProbable_wind_shear_hgt_ft_agl())); + } else { + tfr.setProbable_wind_shear_hgt_ft_agl(IDecoderConstantsN.NEGATIVE_FLOAT_MISSING); + } + + if (chgGrp.getIcing_layers() != null) { + tfr.setIcing_layers(chgGrp.getIcing_layers()); + } + + if (chgGrp.getSky_cover() != null) { + tfr.setSky_cover(chgGrp.getSky_cover()); + } + + if (chgGrp.getProbable_sky_cover() != null) { + tfr.setProbable_sky_cover(chgGrp + .getProbable_sky_cover()); + } + + if (chgGrp.getTemp_forecasts() != null) { + tfr.setTemp_forecasts(chgGrp.getTemp_forecasts()); + } + + if (chgGrp.getTurbulence_layers() != null) { + tfr.setTurbulence_layers(chgGrp.getTurbulence_layers()); + } + + if (chgGrp.getWeather() != null) { + tfr.setWeather(chgGrp.getWeather()); + } + + records.add(tfr); + } + + } + } + + List hourlyRecords = splitToHourlyRecords(records); + + return hourlyRecords.toArray(new NcTafRecord[0]); + } + + public static List splitToHourlyRecords( + List records) { + List newRecords = new ArrayList(); + int recordsSize = (records != null) ? records.size() : 0; + + if (recordsSize > 0) { + + for (int i = 0; i < recordsSize; i++) { + + NcTafRecord record = records.get(i); + + Calendar startRefTime = record.getStartDate(); + Calendar endRefTime = record.getEndDate(); + + // add 1 minute so that 12:30 becomes 12:31 and hence is rounded + // to 13:00 and not 12:00 + startRefTime.add(Calendar.MINUTE, 1); + Date nearestHour = DateUtils.round(startRefTime.getTime(), + Calendar.HOUR); + startRefTime.setTime(nearestHour); + + nearestHour = DateUtils.round(endRefTime.getTime(), + Calendar.HOUR); + endRefTime.setTime(nearestHour); + + long milliseconds1 = startRefTime.getTimeInMillis(); + long milliseconds2 = endRefTime.getTimeInMillis(); + long diff = milliseconds2 - milliseconds1; + long diffHours = diff / (60 * 60 * 1000); + + for (int hour = 0; hour < diffHours; hour++) { + + NcTafRecord tfr = new NcTafRecord(); + + tfr.setPersistenceTime(new Date()); + tfr.setDataTime(new DataTime(startRefTime)); + tfr.setTafValidPeriod(record.getTafValidPeriod()); + tfr.setTafChangePeriod(record.getTafChangePeriod()); + tfr.setEndDate(record.getTafChangePeriod().getEndDate()); + tfr.setStartDate(record.getTafChangePeriod().getStartDate()); + tfr.setTransitionEndDate(record.getTafChangePeriod() + .getTransitionEndDate()); + tfr.setWmoHeader(record.getWmoHeader()); + if ((record.getTafText() != null) + && (record.getTafText().length() > 1024)) { + tfr.setTafText(record.getTafText().substring(0, 1024)); + } else { + tfr.setTafText(record.getTafText()); + } + tfr.setTafText(record.getTafText()); + tfr.setReportType(record.getReportType()); + tfr.setStationId(record.getStationId()); + tfr.setCorIndicator(record.getCorIndicator()); + tfr.setAmdIndicator(record.getAmdIndicator()); + tfr.setIssue_time(record.getIssue_time()); + tfr.setIssue_timeString(record.getIssue_timeString()); + tfr.setBulletin_time(record.getBulletin_time()); + tfr.setLocation(record.getLocation()); + tfr.setChange_indicator(record.getChange_indicator()); + if ((record.getChangeGroup() != null) + && (record.getChangeGroup().length() > 128)) { + tfr.setChangeGroup(record.getChangeGroup().substring(0, + 128)); + } else { + tfr.setChangeGroup(record.getChangeGroup()); + } + tfr.setChangeGroup(record.getChangeGroup()); + tfr.setProbability(record.getProbability()); + tfr.setMax_temp_c(record.getMax_temp_c()); + tfr.setMin_temp_c(record.getMin_temp_c()); + tfr.setAltim_in_hg(record.getAltim_in_hg()); + tfr.setRemarks(record.getRemarks()); + tfr.setSequenceId(record.getSequenceId()); + tfr.setVisibility_mi(record.getVisibility_mi()); + tfr.setVert_vis_ft(record.getVert_vis_ft()); + tfr.setWind_dir_degrees(record.getWind_dir_degrees()); + tfr.setWind_gust_kt(record.getWind_gust_kt()); + tfr.setWind_speed_kt(record.getWind_speed_kt()); + tfr.setWind_shear_dir_degrees(record + .getWind_shear_dir_degrees()); + tfr.setWind_shear_speed_kt(record.getWind_shear_speed_kt()); + tfr.setWind_shear_hgt_ft_agl(record + .getWind_shear_hgt_ft_agl()); + tfr.setProbable_visibility_mi(record + .getProbable_visibility_mi()); + tfr.setProbable_vert_vis_ft(record + .getProbable_vert_vis_ft()); + tfr.setProbable_wind_dir_degrees(record + .getProbable_wind_dir_degrees()); + tfr.setProbable_wind_gust_kt(record + .getProbable_wind_gust_kt()); + tfr.setProbable_wind_speed_kt(record + .getProbable_wind_speed_kt()); + tfr.setWind_shear_dir_degrees(record + .getProbable_wind_shear_dir_degrees()); + tfr.setWind_shear_speed_kt(record + .getProbable_wind_shear_speed_kt()); + tfr.setProbable_wind_shear_hgt_ft_agl(record + .getProbable_wind_shear_hgt_ft_agl()); + tfr.setIcing_layers(record.getIcing_layers()); + tfr.setSky_cover(record.getSky_cover()); + tfr.setProbable_sky_cover(record.getProbable_sky_cover()); + tfr.setTemp_forecasts(record.getTemp_forecasts()); + tfr.setTurbulence_layers(record.getTurbulence_layers()); + tfr.setWeather(record.getWeather()); + tfr.setProbable_weather(record.getWeather()); + newRecords.add(tfr); + startRefTime.add(Calendar.HOUR_OF_DAY, 1); + } + } + } + + return newRecords; + } @Override @Column @@ -1619,65 +1645,69 @@ public class NcTafRecord extends PluginDataObject implements ISpatialEnabled, return super.getDataURI(); } - /** - * - * @param args - */ - public static final void main(String[] args) { + /** + * + * @param args + */ + public static final void main(String[] args) { - Set skyCovers = new HashSet(); + Set skyCovers = new HashSet(); - NcTafSkyCover cover = new NcTafSkyCover(); - cover.setGenus(""); - cover.setType("OVC"); - cover.setHeight(1800); - skyCovers.add(cover); + NcTafSkyCover cover = new NcTafSkyCover(); + cover.setGenus(""); + cover.setType("OVC"); + cover.setHeight(1800); + skyCovers.add(cover); - cover = new NcTafSkyCover(); - cover.setGenus(""); - cover.setType("BKN"); - cover.setHeight(1000); - skyCovers.add(cover); + cover = new NcTafSkyCover(); + cover.setGenus(""); + cover.setType("BKN"); + cover.setHeight(1000); + skyCovers.add(cover); - cover = new NcTafSkyCover(); - cover.setGenus(""); - cover.setType("SCT"); - cover.setHeight(800); - skyCovers.add(cover); + cover = new NcTafSkyCover(); + cover.setGenus(""); + cover.setType("SCT"); + cover.setHeight(800); + skyCovers.add(cover); - for (NcTafSkyCover s : skyCovers) { - System.out.println(s); - } + for (NcTafSkyCover s : skyCovers) { + System.out.println(s); + } - System.out.println(getCeiling(skyCovers, 8)); + System.out.println(getCeiling(skyCovers, 8)); - System.out.println(getCeiling(skyCovers, -1)); + System.out.println(getCeiling(skyCovers, -1)); - Calendar startRefTime = Calendar.getInstance(); - startRefTime.set(2011, 11, 04, 12, 30); - startRefTime.add(Calendar.MINUTE, 1); - Calendar endRefTime = Calendar.getInstance(); - endRefTime.set(2011, 11, 04, 14, 30); + Calendar startRefTime = Calendar.getInstance(); + startRefTime.set(2011, 11, 04, 12, 30); + startRefTime.add(Calendar.MINUTE, 1); + Calendar endRefTime = Calendar.getInstance(); + endRefTime.set(2011, 11, 04, 14, 30); - Date nearestHour = DateUtils.round(startRefTime.getTime(), - Calendar.HOUR); - startRefTime.setTime(nearestHour); + Date nearestHour = DateUtils.round(startRefTime.getTime(), + Calendar.HOUR); + startRefTime.setTime(nearestHour); - nearestHour = DateUtils.round(endRefTime.getTime(), Calendar.HOUR); - endRefTime.setTime(nearestHour); + nearestHour = DateUtils.round(endRefTime.getTime(), Calendar.HOUR); + endRefTime.setTime(nearestHour); - long milliseconds1 = startRefTime.getTimeInMillis(); - long milliseconds2 = endRefTime.getTimeInMillis(); - long diff = milliseconds2 - milliseconds1; - long diffHours = diff / (60 * 60 * 1000); + long milliseconds1 = startRefTime.getTimeInMillis(); + long milliseconds2 = endRefTime.getTimeInMillis(); + long diff = milliseconds2 - milliseconds1; + long diffHours = diff / (60 * 60 * 1000); - System.out.println(" diffHours = " + diffHours); + System.out.println(" diffHours = " + diffHours); - for (int hour = 0; hour < diffHours; hour++) { - System.out.println(" startRefTime = " - + startRefTime.getTime().toString()); - startRefTime.add(Calendar.HOUR_OF_DAY, 1); - } - } + for (int hour = 0; hour < diffHours; hour++) { + System.out.println(" startRefTime = " + + startRefTime.getTime().toString()); + startRefTime.add(Calendar.HOUR_OF_DAY, 1); + } + } + @Override + public String getPluginName() { + return "nctaf"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncuair/src/gov/noaa/nws/ncep/common/dataplugin/ncuair/NcUairRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncuair/src/gov/noaa/nws/ncep/common/dataplugin/ncuair/NcUairRecord.java index 27ba1eddb6..6a023c45eb 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ncuair/src/gov/noaa/nws/ncep/common/dataplugin/ncuair/NcUairRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ncuair/src/gov/noaa/nws/ncep/common/dataplugin/ncuair/NcUairRecord.java @@ -67,504 +67,501 @@ import com.vividsolutions.jts.geom.Geometry; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ncuair", - indexes = { - @Index(name = "ncuair_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ncuair", indexes = { @Index(name = "ncuair_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class NcUairRecord extends PersistablePluginDataObject implements - ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { - - private static final long serialVersionUID = 1L; - public static final String PLUGIN_NAME = "ncuair"; - - // Time of the UTC - @DataURI(position = 4) - @Column - @DynamicSerializeElement - private int UTC; - - // The observation report type. - @DataURI(position = 1) - @Column - @DynamicSerializeElement - private String reportType; - - // Issue time for the bulletin - @Column - @DynamicSerializeElement - private Calendar issueTime; - - // Observation time for the bulletin - @Column - @DynamicSerializeElement - private Calendar obsTime; - - // Synoptic time for the bulletin - // Time of the observation to the nearest hour. - @Column - @DynamicSerializeElement - private Calendar synopticTime; - - // Type of data such as TTAA/BB/CC/DD or PP... - @DataURI(position = 3) - @Column - @DynamicSerializeElement - private String dataType; - - // Correction indicator from wmo header - @DataURI(position = 5) - @Column - @DynamicSerializeElement - private String corr; - - // Text of the WMO header - @Column - @DynamicSerializeElement - private String wmoHeader; - - // Station number - // @DataURI(position = 2) - @Column - @DynamicSerializeElement - private String stnum; - - @Embedded - @DataURI(position = 2, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; - - // Yes if report is a NIL. - @Column - @DynamicSerializeElement - private Boolean nil; - - // bulletin message - @Transient - @DynamicSerializeElement - private String bullMessage; - - /** - * Uair observation levels - */ - @DynamicSerializeElement - @Transient - private Set obsLevels = new HashSet(); - - /** - * Uair tropopause data - */ - @DynamicSerializeElement - @Transient - private Set tropopause = new HashSet(); - - /** - * Uair maxwind data - */ - @DynamicSerializeElement - @Transient - private Set maxwind = new HashSet(); - - /** - * Uair lifted index data - */ - @DynamicSerializeElement - @Transient - private Set liftedindex = new HashSet(); - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - /** - * Empty constructor. - */ - public NcUairRecord() { - this.nil = false; - this.stnum = ""; - this.wmoHeader = ""; - // this.stid=""; - this.corr = ""; - this.dataType = ""; - } - - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public NcUairRecord(String uri) { - super(uri); - if (location != null) { - String staId = location.getStationId(); - location.setStationId("null".equals(staId) ? null : staId); - } - } - - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } - - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } - - /** - * Get the report correction indicator. - * - * @return The corr - */ - public String getCorr() { - return corr; - } - - /** - * Set the report correction indicator. - * - * @param corr - * The corr. - */ - public void setCorr(String corr) { - this.corr = corr; - } - - /** - * Get the observation report type. - * - * @return the reportType - */ - public String getReportType() { - return reportType; - } - - /** - * Set the observation report type. - * - * @param reportType - * the reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } - - public String getStnum() { - return stnum; - } - - public void setStnum(String stnum) { - this.stnum = stnum; - } - - /* - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } - - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } - - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } - - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } - - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } - - /** - * Get whether the location for this observation is defined. - * - * @return Is this location defined. - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } - - public Calendar getObsTime() { - return obsTime; - } - - public void setObsTime(Calendar obsTime) { - this.obsTime = obsTime; - } - - public Calendar getSynopticTime() { - return synopticTime; - } - - public void setSynopticTime(Calendar synopticTime) { - this.synopticTime = synopticTime; - } - - public String getBullMessage() { - return bullMessage; - } - - public void setBullMessage(String bullMessage) { - this.bullMessage = bullMessage; - } - - public Calendar getIssueTime() { - return issueTime; - } - - public void setIssueTime(Calendar issueTime) { - this.issueTime = issueTime; - } - - public String getDataType() { - return dataType; - } - - public void setDataType(String dataType) { - this.dataType = dataType; - } - - public int getUTC() { - return UTC; - } - - public void setUTC(int utc) { - UTC = utc; - } - - public Boolean getNil() { - return nil; - } - - public void setNil(Boolean nil) { - this.nil = nil; - } - - @Override - public IDecoderGettable getDecoderGettable() { - // TODO Auto-generated method stub - return null; - } - - /** - * @return the set of uair observation levels - */ - public Set getObsLevels() { - return obsLevels; - } - - /** - * @param uair - * observation levels to set - */ - public void setObsLevels(Set uairLevel) { - this.obsLevels = uairLevel; - } - - /** - * @param add - * uair observation levels to set - */ - public void addObsLevels(NcUairObsLevels plevel) { - obsLevels.add(plevel); - // plevel.setParentID(this); - } - - /** - * @return the set of uair observation levels - */ - public Set getTropopause() { - return tropopause; - } - - /** - * @param uair - * observation levels to set - */ - public void setTropopause(Set trop) { - this.tropopause = trop; - } - - /** - * @param add - * uair observation levels to set - */ - public void addTropopause(NcUairTropopause trop) { - tropopause.add(trop); - // trop.setParentID(this); - } - - /** - * @return the set of uair maximum wind - */ - public Set getMaxWind() { - return maxwind; - } - - /** - * @param uair - * maximum wind to set - */ - public void setMaxWind(Set mwind) { - this.maxwind = mwind; - } - - /** - * @param add - * uair maximum wind to set - */ - public void addMaxWind(NcUairMaxWind mwind) { - maxwind.add(mwind); - // mwind.setParentID(this); - } - - /** - * @return the set of uair lifted index - */ - public Set getLiftedIndex() { - return liftedindex; - } - - /** - * @param uair - * lifted index to set - */ - public void setLiftedIndex(Set li) { - this.liftedindex = li; - } - - /** - * @param add - * uair lifted index to set - */ - public void addLiftedIndex(NcUairLiftedIndex li) { - liftedindex.add(li); - // li.setParentID(this); - } - - /** - * Override existing set method to modify any classes that use the dataURI - * as a foreign key - */ - @Override - public void setIdentifier(Object dataURI) { - - this.identifier = dataURI; - - } - - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } - - public SurfaceObsLocation getLocation() { - if (location == null) { - location = new SurfaceObsLocation(); - } - return location; - } - - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() - */ - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } - - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon - * .uf.common.pointdata.PointDataView) - */ - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } - - @Override - public Date getPersistenceTime() { - // return this.dataTime.getRefTime(); - return null; - } - - @Override - public void setPersistenceTime(Date persistTime) { - // TODO Auto-generated method stub - - } - - @Override - public Amount getValue(String paramName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Collection getValues(String paramName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getString(String paramName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String[] getStrings(String paramName) { - // TODO Auto-generated method stub - return null; - } + ISpatialEnabled, IDecoderGettable, IPointData, IPersistable { + + private static final long serialVersionUID = 1L; + + public static final String PLUGIN_NAME = "ncuair"; + + // Time of the UTC + @DataURI(position = 4) + @Column + @DynamicSerializeElement + private int UTC; + + // The observation report type. + @DataURI(position = 1) + @Column + @DynamicSerializeElement + private String reportType; + + // Issue time for the bulletin + @Column + @DynamicSerializeElement + private Calendar issueTime; + + // Observation time for the bulletin + @Column + @DynamicSerializeElement + private Calendar obsTime; + + // Synoptic time for the bulletin + // Time of the observation to the nearest hour. + @Column + @DynamicSerializeElement + private Calendar synopticTime; + + // Type of data such as TTAA/BB/CC/DD or PP... + @DataURI(position = 3) + @Column + @DynamicSerializeElement + private String dataType; + + // Correction indicator from wmo header + @DataURI(position = 5) + @Column + @DynamicSerializeElement + private String corr; + + // Text of the WMO header + @Column + @DynamicSerializeElement + private String wmoHeader; + + // Station number + // @DataURI(position = 2) + @Column + @DynamicSerializeElement + private String stnum; + + @Embedded + @DataURI(position = 2, embedded = true) + @XmlElement + @DynamicSerializeElement + private SurfaceObsLocation location; + + // Yes if report is a NIL. + @Column + @DynamicSerializeElement + private Boolean nil; + + // bulletin message + @Transient + @DynamicSerializeElement + private String bullMessage; + + /** + * Uair observation levels + */ + @DynamicSerializeElement + @Transient + private Set obsLevels = new HashSet(); + + /** + * Uair tropopause data + */ + @DynamicSerializeElement + @Transient + private Set tropopause = new HashSet(); + + /** + * Uair maxwind data + */ + @DynamicSerializeElement + @Transient + private Set maxwind = new HashSet(); + + /** + * Uair lifted index data + */ + @DynamicSerializeElement + @Transient + private Set liftedindex = new HashSet(); + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + /** + * Empty constructor. + */ + public NcUairRecord() { + this.nil = false; + this.stnum = ""; + this.wmoHeader = ""; + // this.stid=""; + this.corr = ""; + this.dataType = ""; + } + + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public NcUairRecord(String uri) { + super(uri); + if (location != null) { + String staId = location.getStationId(); + location.setStationId("null".equals(staId) ? null : staId); + } + } + + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } + + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } + + /** + * Get the report correction indicator. + * + * @return The corr + */ + public String getCorr() { + return corr; + } + + /** + * Set the report correction indicator. + * + * @param corr + * The corr. + */ + public void setCorr(String corr) { + this.corr = corr; + } + + /** + * Get the observation report type. + * + * @return the reportType + */ + public String getReportType() { + return reportType; + } + + /** + * Set the observation report type. + * + * @param reportType + * the reportType to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } + + public String getStnum() { + return stnum; + } + + public void setStnum(String stnum) { + this.stnum = stnum; + } + + /* + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } + + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } + + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } + + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } + + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } + + /** + * Get whether the location for this observation is defined. + * + * @return Is this location defined. + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } + + public Calendar getObsTime() { + return obsTime; + } + + public void setObsTime(Calendar obsTime) { + this.obsTime = obsTime; + } + + public Calendar getSynopticTime() { + return synopticTime; + } + + public void setSynopticTime(Calendar synopticTime) { + this.synopticTime = synopticTime; + } + + public String getBullMessage() { + return bullMessage; + } + + public void setBullMessage(String bullMessage) { + this.bullMessage = bullMessage; + } + + public Calendar getIssueTime() { + return issueTime; + } + + public void setIssueTime(Calendar issueTime) { + this.issueTime = issueTime; + } + + public String getDataType() { + return dataType; + } + + public void setDataType(String dataType) { + this.dataType = dataType; + } + + public int getUTC() { + return UTC; + } + + public void setUTC(int utc) { + UTC = utc; + } + + public Boolean getNil() { + return nil; + } + + public void setNil(Boolean nil) { + this.nil = nil; + } + + @Override + public IDecoderGettable getDecoderGettable() { + // TODO Auto-generated method stub + return null; + } + + /** + * @return the set of uair observation levels + */ + public Set getObsLevels() { + return obsLevels; + } + + /** + * @param uair + * observation levels to set + */ + public void setObsLevels(Set uairLevel) { + this.obsLevels = uairLevel; + } + + /** + * @param add + * uair observation levels to set + */ + public void addObsLevels(NcUairObsLevels plevel) { + obsLevels.add(plevel); + // plevel.setParentID(this); + } + + /** + * @return the set of uair observation levels + */ + public Set getTropopause() { + return tropopause; + } + + /** + * @param uair + * observation levels to set + */ + public void setTropopause(Set trop) { + this.tropopause = trop; + } + + /** + * @param add + * uair observation levels to set + */ + public void addTropopause(NcUairTropopause trop) { + tropopause.add(trop); + // trop.setParentID(this); + } + + /** + * @return the set of uair maximum wind + */ + public Set getMaxWind() { + return maxwind; + } + + /** + * @param uair + * maximum wind to set + */ + public void setMaxWind(Set mwind) { + this.maxwind = mwind; + } + + /** + * @param add + * uair maximum wind to set + */ + public void addMaxWind(NcUairMaxWind mwind) { + maxwind.add(mwind); + // mwind.setParentID(this); + } + + /** + * @return the set of uair lifted index + */ + public Set getLiftedIndex() { + return liftedindex; + } + + /** + * @param uair + * lifted index to set + */ + public void setLiftedIndex(Set li) { + this.liftedindex = li; + } + + /** + * @param add + * uair lifted index to set + */ + public void addLiftedIndex(NcUairLiftedIndex li) { + liftedindex.add(li); + // li.setParentID(this); + } + + /** + * Override existing set method to modify any classes that use the dataURI + * as a foreign key + */ + @Override + public void setIdentifier(Object dataURI) { + + this.identifier = dataURI; + + } + + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } + + public SurfaceObsLocation getLocation() { + if (location == null) { + location = new SurfaceObsLocation(); + } + return location; + } + + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.pointdata.IPointData#getPointDataView() + */ + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.pointdata.IPointData#setPointDataView(com.raytheon + * .uf.common.pointdata.PointDataView) + */ + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + + @Override + public Date getPersistenceTime() { + // return this.dataTime.getRefTime(); + return null; + } + + @Override + public void setPersistenceTime(Date persistTime) { + // TODO Auto-generated method stub + + } + + @Override + public Amount getValue(String paramName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getValues(String paramName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getString(String paramName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String[] getStrings(String paramName) { + // TODO Auto-generated method stub + return null; + } @Override @Column @@ -573,4 +570,8 @@ public class NcUairRecord extends PersistablePluginDataObject implements return super.getDataURI(); } + @Override + public String getPluginName() { + return "ncuair"; + } } \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.nonconvsigmet/src/gov/noaa/nws/ncep/common/dataplugin/nonconvsigmet/NonConvSigmetRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.nonconvsigmet/src/gov/noaa/nws/ncep/common/dataplugin/nonconvsigmet/NonConvSigmetRecord.java index c08cd7a97d..ffd2bd171c 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.nonconvsigmet/src/gov/noaa/nws/ncep/common/dataplugin/nonconvsigmet/NonConvSigmetRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.nonconvsigmet/src/gov/noaa/nws/ncep/common/dataplugin/nonconvsigmet/NonConvSigmetRecord.java @@ -52,512 +52,484 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "nonconvsigmet", - indexes = { - @Index(name = "nonconvsigmet_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "nonconvsigmet", indexes = { @Index(name = "nonconvsigmet_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize +public class NonConvSigmetRecord extends PluginDataObject { - -public class NonConvSigmetRecord extends PluginDataObject{ - - /** + /** * */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - // reportType is "non-convective sigmet". - @Column(length=32) - @DataURI(position=5) - @DynamicSerializeElement - private String reportType; - - // WMO header - @Column(length=32) - @DynamicSerializeElement - private String wmoHeader; - - // forecastRegion as: SL - @Column(length=8) - @DataURI(position=2) - @DynamicSerializeElement - private String forecastRegion; - - // The issue office where the report from - @Column(length=32) - @DataURI(position=1) - @DynamicSerializeElement - private String issueOffice; - - // Issue time of the report - @Column - @DataURI(position=3) - @DynamicSerializeElement - private Calendar issueTime; - - // The designator - @Column(length=8) - @DynamicSerializeElement - private String designatorBBB; - - // CorrectionFlag is a flag with values (1 or 2 or 3) - @Column(length=8) + // reportType is "non-convective sigmet". + @Column(length = 32) + @DataURI(position = 5) @DynamicSerializeElement - private String correctionRemarks; - - // The awipsId from the report - @Column(length=32) - @DataURI(position=4) - @DynamicSerializeElement - private String awipsId; - - // The state list from the report - @Column(length=256) - @DynamicSerializeElement - private String stateList; - - // Start time of the report - @Column - @DynamicSerializeElement - private Calendar startTime; - - // End time of the report - @Column - @DynamicSerializeElement - private Calendar endTime; - - // The type of the hazard from the report - @Column(length=16) - @DynamicSerializeElement - private String hazardType; - - // The intensity of the hazard from the report - @Column(length=64) - @DynamicSerializeElement - private String hazardIntensity; - - // The cause for the hazard from the report - @Column(length=128) - @DynamicSerializeElement - private String hazardCause; - - // The conditions stated about the hazard from the report - @Column(length=128) - @DynamicSerializeElement - private String hazardCondition; - - // The lower flight level from the report - @Column - @DynamicSerializeElement - private int flightLevel1; - - // The upper flight level from the report - @Column - @DynamicSerializeElement - private int flightLevel2; - - // The sigmet Identifier from the report - @Column(length=32) - @DynamicSerializeElement - private String sigmetId; - - // The entire report - @Column(length=3000) - @DynamicSerializeElement - private String bullMessage; + private String reportType; - - /** - * Convsigmet location - */ - @DynamicSerializeElement - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinColumn(name = "parentID", nullable = false) + // WMO header + @Column(length = 32) + @DynamicSerializeElement + private String wmoHeader; + + // forecastRegion as: SL + @Column(length = 8) + @DataURI(position = 2) + @DynamicSerializeElement + private String forecastRegion; + + // The issue office where the report from + @Column(length = 32) + @DataURI(position = 1) + @DynamicSerializeElement + private String issueOffice; + + // Issue time of the report + @Column + @DataURI(position = 3) + @DynamicSerializeElement + private Calendar issueTime; + + // The designator + @Column(length = 8) + @DynamicSerializeElement + private String designatorBBB; + + // CorrectionFlag is a flag with values (1 or 2 or 3) + @Column(length = 8) + @DynamicSerializeElement + private String correctionRemarks; + + // The awipsId from the report + @Column(length = 32) + @DataURI(position = 4) + @DynamicSerializeElement + private String awipsId; + + // The state list from the report + @Column(length = 256) + @DynamicSerializeElement + private String stateList; + + // Start time of the report + @Column + @DynamicSerializeElement + private Calendar startTime; + + // End time of the report + @Column + @DynamicSerializeElement + private Calendar endTime; + + // The type of the hazard from the report + @Column(length = 16) + @DynamicSerializeElement + private String hazardType; + + // The intensity of the hazard from the report + @Column(length = 64) + @DynamicSerializeElement + private String hazardIntensity; + + // The cause for the hazard from the report + @Column(length = 128) + @DynamicSerializeElement + private String hazardCause; + + // The conditions stated about the hazard from the report + @Column(length = 128) + @DynamicSerializeElement + private String hazardCondition; + + // The lower flight level from the report + @Column + @DynamicSerializeElement + private int flightLevel1; + + // The upper flight level from the report + @Column + @DynamicSerializeElement + private int flightLevel2; + + // The sigmet Identifier from the report + @Column(length = 32) + @DynamicSerializeElement + private String sigmetId; + + // The entire report + @Column(length = 3000) + @DynamicSerializeElement + private String bullMessage; + + /** + * Convsigmet location + */ + @DynamicSerializeElement + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "parentID", nullable = false) @Index(name = "nonConvSigmetLocation_parentid_idex") - private Set nonConvSigmetLocation = new HashSet(); + private Set nonConvSigmetLocation = new HashSet(); - - /** + /** * Default Constructor */ public NonConvSigmetRecord() { - this.issueOffice =""; - this.wmoHeader =""; - this.bullMessage =""; - this.designatorBBB =""; - this.forecastRegion =""; - this.reportType =""; - this.correctionRemarks =""; - this.awipsId =""; - this.flightLevel1 =IDecoderConstantsN.INTEGER_MISSING; - this.flightLevel2 =IDecoderConstantsN.INTEGER_MISSING; - this.hazardCause =""; - this.hazardCondition =""; - this.hazardIntensity =""; - this.hazardType ="UNKNOWN"; - this.stateList =""; - this.sigmetId =""; + this.issueOffice = ""; + this.wmoHeader = ""; + this.bullMessage = ""; + this.designatorBBB = ""; + this.forecastRegion = ""; + this.reportType = ""; + this.correctionRemarks = ""; + this.awipsId = ""; + this.flightLevel1 = IDecoderConstantsN.INTEGER_MISSING; + this.flightLevel2 = IDecoderConstantsN.INTEGER_MISSING; + this.hazardCause = ""; + this.hazardCondition = ""; + this.hazardIntensity = ""; + this.hazardType = "UNKNOWN"; + this.stateList = ""; + this.sigmetId = ""; } /** * Convstructs a non-consigmet record from a dataURI * - * @param uri The dataURI + * @param uri + * The dataURI */ public NonConvSigmetRecord(String uri) { super(uri); } - - @Override - public IDecoderGettable getDecoderGettable() { - // TODO Auto-generated method stub - return null; - } - - - /** - * @return the reportType - */ - public String getReportType() { - return reportType; - } - - - /** - * @param reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } - - - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } - - - /** - * @param wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } - - - /** - * @return the forecastRegion - */ - public String getForecastRegion() { - return forecastRegion; - } - - - /** - * @param forecastRegion to set - */ - public void setForecastRegion(String forecastRegion) { - this.forecastRegion = forecastRegion; - } - - - /** - * @return the issueOffice - */ - public String getIssueOffice() { - return issueOffice; - } - - - /** - * @param issueOffice to set - */ - public void setIssueOffice(String issueOffice) { - this.issueOffice = issueOffice; - } - - - /** - * @return the issueTime - */ - public Calendar getIssueTime() { - return issueTime; - } - - - /** - * @param issueTime to set - */ - public void setIssueTime(Calendar issueTime) { - this.issueTime = issueTime; - } - - - /** - * @return the designatorBBB - */ - public String getDesignatorBBB() { - return designatorBBB; - } - - - /** - * @param designatorBBB to set - */ - public void setDesignatorBBB(String designatorBBB) { - this.designatorBBB = designatorBBB; - } - - - /** - * @return the correctionFlag - */ - public String getCorrectionRemarks() { - return correctionRemarks; - } - - - /** - * @param correctionFlag to set - */ - public void setCorrectionRemarks(String correctionRemarks) { - this.correctionRemarks = correctionRemarks; - } - - - /** - * @return the awipsId - */ - public String getAwipsId() { - return awipsId; - } - - - /** - * @param awipsId to set - */ - public void setAwipsId(String awipsId) { - this.awipsId = awipsId; - } - - - /** - * @return the stateList - */ - public String getStateList() { - return stateList; - } - - - /** - * @param stateList to set - */ - public void setStateList(String stateList) { - this.stateList = stateList; - } - - - /** - * @return the startTime - */ - public Calendar getStartTime() { - return startTime; - } - - - /** - * @param startTime to set - */ - public void setStartTime(Calendar startTime) { - this.startTime = startTime; - } - - - /** - * @return the endTime - */ - public Calendar getEndTime() { - return endTime; - } - - - /** - * @param endTime to set - */ - public void setEndTime(Calendar endTime) { - this.endTime = endTime; - } - - - /** - * @return the hazardType - */ - public String getHazardType() { - return hazardType; - } - - - /** - * @param hazardType to set - */ - public void setHazardType(String hazardType) { - this.hazardType = hazardType; - } - - - /** - * @return the hazardIntensity - */ - public String getHazardIntensity() { - return hazardIntensity; - } - - - /** - * @param hazardIntensity to set - */ - public void setHazardIntensity(String hazardIntensity) { - this.hazardIntensity = hazardIntensity; - } + @Override + public IDecoderGettable getDecoderGettable() { + // TODO Auto-generated method stub + return null; + } /** - * @return the hazardCause - */ - public String getHazardCause() { - return hazardCause; - } - - - /** - * @param hazardCause to set - */ - public void setHazardCause(String hazardCause) { - this.hazardCause = hazardCause; - } - + * @return the reportType + */ + public String getReportType() { + return reportType; + } /** - * @return the hazardCondition - */ - public String getHazardCondition() { - return hazardCondition; - } - - - /** - * @param hazardCondition to set - */ - public void setHazardCondition(String hazardCondition) { - this.hazardCondition = hazardCondition; - } - + * @param reportType + * to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } /** - * @return the flightLevel1 - */ - public int getFlightLevel1() { - return flightLevel1; - } - - - /** - * @param flightLevel1 to set - */ - public void setFlightLevel1(int flightLevel1) { - this.flightLevel1 = flightLevel1; - } - + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } /** - * @return the flightLevel2 - */ - public int getFlightLevel2() { - return flightLevel2; - } - - - /** - * @param flightLevel2 to set - */ - public void setFlightLevel2(int flightLevel2) { - this.flightLevel2 = flightLevel2; - } - + * @param wmoHeader + * to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } /** - * @return the sigmetId - */ - public String getSigmetId() { - return sigmetId; - } - - - /** - * @param sigmetId to set - */ - public void setSigmetId(String sigmetId) { - this.sigmetId = sigmetId; - } - + * @return the forecastRegion + */ + public String getForecastRegion() { + return forecastRegion; + } /** - * @return the bullMessage - */ - public String getBullMessage() { - return bullMessage; - } + * @param forecastRegion + * to set + */ + public void setForecastRegion(String forecastRegion) { + this.forecastRegion = forecastRegion; + } + /** + * @return the issueOffice + */ + public String getIssueOffice() { + return issueOffice; + } - /** - * @param bullMessage to set - */ - public void setBullMessage(String bullMessage) { - this.bullMessage = bullMessage; - } + /** + * @param issueOffice + * to set + */ + public void setIssueOffice(String issueOffice) { + this.issueOffice = issueOffice; + } + /** + * @return the issueTime + */ + public Calendar getIssueTime() { + return issueTime; + } - /** - * @return the set of nonconvective sigmet location - */ - public Set getNonConvSigmetLocation() { - return nonConvSigmetLocation; - } + /** + * @param issueTime + * to set + */ + public void setIssueTime(Calendar issueTime) { + this.issueTime = issueTime; + } - /** - * @param nonconvsigmet the location to set - */ - public void setNonConvSigmetLocation(Set nonConvLocation) { - this.nonConvSigmetLocation = nonConvLocation; - } + /** + * @return the designatorBBB + */ + public String getDesignatorBBB() { + return designatorBBB; + } - /** - * @param add conv Sigmet location to set - */ - public void addNonConvSigmetLocation(NonConvSigmetLocation pLocation){ - nonConvSigmetLocation.add(pLocation); - - } - - - /** - * Override existing set method to modify any - * classes that use the dataURI as a foreign key - */ - @Override - public void setIdentifier(Object dataURI) - { + /** + * @param designatorBBB + * to set + */ + public void setDesignatorBBB(String designatorBBB) { + this.designatorBBB = designatorBBB; + } + + /** + * @return the correctionFlag + */ + public String getCorrectionRemarks() { + return correctionRemarks; + } + + /** + * @param correctionFlag + * to set + */ + public void setCorrectionRemarks(String correctionRemarks) { + this.correctionRemarks = correctionRemarks; + } + + /** + * @return the awipsId + */ + public String getAwipsId() { + return awipsId; + } + + /** + * @param awipsId + * to set + */ + public void setAwipsId(String awipsId) { + this.awipsId = awipsId; + } + + /** + * @return the stateList + */ + public String getStateList() { + return stateList; + } + + /** + * @param stateList + * to set + */ + public void setStateList(String stateList) { + this.stateList = stateList; + } + + /** + * @return the startTime + */ + public Calendar getStartTime() { + return startTime; + } + + /** + * @param startTime + * to set + */ + public void setStartTime(Calendar startTime) { + this.startTime = startTime; + } + + /** + * @return the endTime + */ + public Calendar getEndTime() { + return endTime; + } + + /** + * @param endTime + * to set + */ + public void setEndTime(Calendar endTime) { + this.endTime = endTime; + } + + /** + * @return the hazardType + */ + public String getHazardType() { + return hazardType; + } + + /** + * @param hazardType + * to set + */ + public void setHazardType(String hazardType) { + this.hazardType = hazardType; + } + + /** + * @return the hazardIntensity + */ + public String getHazardIntensity() { + return hazardIntensity; + } + + /** + * @param hazardIntensity + * to set + */ + public void setHazardIntensity(String hazardIntensity) { + this.hazardIntensity = hazardIntensity; + } + + /** + * @return the hazardCause + */ + public String getHazardCause() { + return hazardCause; + } + + /** + * @param hazardCause + * to set + */ + public void setHazardCause(String hazardCause) { + this.hazardCause = hazardCause; + } + + /** + * @return the hazardCondition + */ + public String getHazardCondition() { + return hazardCondition; + } + + /** + * @param hazardCondition + * to set + */ + public void setHazardCondition(String hazardCondition) { + this.hazardCondition = hazardCondition; + } + + /** + * @return the flightLevel1 + */ + public int getFlightLevel1() { + return flightLevel1; + } + + /** + * @param flightLevel1 + * to set + */ + public void setFlightLevel1(int flightLevel1) { + this.flightLevel1 = flightLevel1; + } + + /** + * @return the flightLevel2 + */ + public int getFlightLevel2() { + return flightLevel2; + } + + /** + * @param flightLevel2 + * to set + */ + public void setFlightLevel2(int flightLevel2) { + this.flightLevel2 = flightLevel2; + } + + /** + * @return the sigmetId + */ + public String getSigmetId() { + return sigmetId; + } + + /** + * @param sigmetId + * to set + */ + public void setSigmetId(String sigmetId) { + this.sigmetId = sigmetId; + } + + /** + * @return the bullMessage + */ + public String getBullMessage() { + return bullMessage; + } + + /** + * @param bullMessage + * to set + */ + public void setBullMessage(String bullMessage) { + this.bullMessage = bullMessage; + } + + /** + * @return the set of nonconvective sigmet location + */ + public Set getNonConvSigmetLocation() { + return nonConvSigmetLocation; + } + + /** + * @param nonconvsigmet + * the location to set + */ + public void setNonConvSigmetLocation( + Set nonConvLocation) { + this.nonConvSigmetLocation = nonConvLocation; + } + + /** + * @param add + * conv Sigmet location to set + */ + public void addNonConvSigmetLocation(NonConvSigmetLocation pLocation) { + nonConvSigmetLocation.add(pLocation); + + } + + /** + * Override existing set method to modify any classes that use the dataURI + * as a foreign key + */ + @Override + public void setIdentifier(Object dataURI) { + + this.identifier = dataURI; + + } - this.identifier = dataURI; - - - - } - @Override @Column @Access(AccessType.PROPERTY) @@ -565,4 +537,8 @@ public class NonConvSigmetRecord extends PluginDataObject{ return super.getDataURI(); } + @Override + public String getPluginName() { + return "nonconvsigmet"; + } } \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ntrans/src/gov/noaa/nws/ncep/common/dataplugin/ntrans/NtransRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ntrans/src/gov/noaa/nws/ncep/common/dataplugin/ntrans/NtransRecord.java index cc9f7d5f39..179a35f666 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ntrans/src/gov/noaa/nws/ncep/common/dataplugin/ntrans/NtransRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ntrans/src/gov/noaa/nws/ncep/common/dataplugin/ntrans/NtransRecord.java @@ -18,8 +18,6 @@ package gov.noaa.nws.ncep.common.dataplugin.ntrans; -import java.util.Calendar; - import javax.persistence.Access; import javax.persistence.AccessType; import javax.persistence.Column; @@ -52,50 +50,46 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ntrans", - indexes = { - @Index(name = "ntrans_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ntrans", indexes = { @Index(name = "ntrans_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class NtransRecord extends PersistablePluginDataObject { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; @Column - @DataURI(position=1) + @DataURI(position = 1) @XmlElement @DynamicSerializeElement private String modelName; @Column - @DataURI(position=2) + @DataURI(position = 2) @XmlElement @DynamicSerializeElement - private String metafileName ; + private String metafileName; @Column - @DataURI(position=3) + @DataURI(position = 3) @XmlElement @DynamicSerializeElement private String productName; - @Column + @Column @XmlElement @DynamicSerializeElement private String validTimeString; - - @Column - @XmlElement - @DynamicSerializeElement - private String reportType; - - @Transient - private byte[] imageData; + + @Column + @XmlElement + @DynamicSerializeElement + private String reportType; + + @Transient + private byte[] imageData; @Column @XmlElement @@ -121,131 +115,130 @@ public class NtransRecord extends PersistablePluginDataObject { @XmlElement @DynamicSerializeElement private int totalFramesInFile; - - /** - * Default Constructor - */ - public NtransRecord() { - } - /** - * Constructs an NTRANS record from a dataURI - * + /** + * Default Constructor + */ + public NtransRecord() { + } + + /** + * Constructs an NTRANS record from a dataURI + * * @param uri * The dataURI - */ - public NtransRecord(String uri) { - super(uri); - } + */ + public NtransRecord(String uri) { + super(uri); + } - public String getModelName() { - return modelName; - } + public String getModelName() { + return modelName; + } - public void setModelName(String model) { - this.modelName = model; - } + public void setModelName(String model) { + this.modelName = model; + } - public String getMetafileName() { - return metafileName; - } + public String getMetafileName() { + return metafileName; + } - public void setMetafileName(String inputMetaFileName) { - this.metafileName = inputMetaFileName; - } + public void setMetafileName(String inputMetaFileName) { + this.metafileName = inputMetaFileName; + } - public String getValidTimeString() { - return validTimeString; - } + public String getValidTimeString() { + return validTimeString; + } - public void setValidTimeString(String validTimeString) { - this.validTimeString = validTimeString; - } + public void setValidTimeString(String validTimeString) { + this.validTimeString = validTimeString; + } - public String getProductName() { - return productName; - } + public String getProductName() { + return productName; + } - public void setProductName(String productNameString) { - this.productName = productNameString; - } + public void setProductName(String productNameString) { + this.productName = productNameString; + } - public String getReportType() { - return reportType; - } + public String getReportType() { + return reportType; + } - public void setReportType(String reportType) { - this.reportType = reportType; - } + public void setReportType(String reportType) { + this.reportType = reportType; + } - public byte[] getImageData() { - return imageData; - } + public byte[] getImageData() { + return imageData; + } - public void setImageData(byte[] imageData) { - this.imageData = imageData; - } + public void setImageData(byte[] imageData) { + this.imageData = imageData; + } - public int getImageSizeX() { - return imageSizeX; - } + public int getImageSizeX() { + return imageSizeX; + } - public void setImageSizeX(int imageSizeX) { - this.imageSizeX = imageSizeX; - } + public void setImageSizeX(int imageSizeX) { + this.imageSizeX = imageSizeX; + } - public int getImageSizeY() { - return imageSizeY; - } + public int getImageSizeY() { + return imageSizeY; + } - public void setImageSizeY(int imageSizeY) { - this.imageSizeY = imageSizeY; - } + public void setImageSizeY(int imageSizeY) { + this.imageSizeY = imageSizeY; + } - public int getImageByteCount() { - return imageByteCount; - } + public int getImageByteCount() { + return imageByteCount; + } - public void setImageByteCount(int imageByteCount) { - this.imageByteCount = imageByteCount; - } + public void setImageByteCount(int imageByteCount) { + this.imageByteCount = imageByteCount; + } - public int getFrameNumberInFile() { - return frameNumberInFile; - } + public int getFrameNumberInFile() { + return frameNumberInFile; + } - public void setFrameNumberInFile(int frameNumberInFile) { - this.frameNumberInFile = frameNumberInFile; - } + public void setFrameNumberInFile(int frameNumberInFile) { + this.frameNumberInFile = frameNumberInFile; + } - public int getTotalFramesInFile() { - return totalFramesInFile; - } + public int getTotalFramesInFile() { + return totalFramesInFile; + } - public void setTotalFramesInFile(int totalFramesInFile) { - this.totalFramesInFile = totalFramesInFile; - } + public void setTotalFramesInFile(int totalFramesInFile) { + this.totalFramesInFile = totalFramesInFile; + } - - @Override - public IDecoderGettable getDecoderGettable() { - // TODO Auto-generated method stub - return null; - } - - @Override + @Override + public IDecoderGettable getDecoderGettable() { + // TODO Auto-generated method stub + return null; + } + + @Override public IHDFFilePathProvider getHDFPathProvider() { return NtransPathProvider.getInstance(); } - public static long getSerialVersionUID() { - return serialVersionUID; - } + public static long getSerialVersionUID() { + return serialVersionUID; + } - @Override + @Override public void setIdentifier(Object dataURI) { - this.identifier = dataURI; - } + this.identifier = dataURI; + } @Override @Column @@ -253,4 +246,9 @@ public class NtransRecord extends PersistablePluginDataObject { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ntrans"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.pgen/src/gov/noaa/nws/ncep/common/dataplugin/pgen/PgenRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.pgen/src/gov/noaa/nws/ncep/common/dataplugin/pgen/PgenRecord.java index c7f1b9d8c4..be7d03d2dc 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.pgen/src/gov/noaa/nws/ncep/common/dataplugin/pgen/PgenRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.pgen/src/gov/noaa/nws/ncep/common/dataplugin/pgen/PgenRecord.java @@ -30,9 +30,10 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Apr 22, 2013 sgilbert Initial creation - * Jun 26, 2013 bhebbard Added SequenceGenerator annotation - * Jul 22, 2013 1977 rjpeter Added getDataURI and annotations. + * Apr 22, 2013 sgilbert Initial creation + * Jun 26, 2013 bhebbard Added SequenceGenerator annotation + * Jul 22, 2013 1977 rjpeter Added getDataURI and annotations. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author sgilbert @@ -270,4 +271,9 @@ public class PgenRecord extends PersistablePluginDataObject { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "pgen"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.sgwh/src/gov/noaa/nws/ncep/common/dataplugin/sgwh/SgwhRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.sgwh/src/gov/noaa/nws/ncep/common/dataplugin/sgwh/SgwhRecord.java index 59459131cb..90bf018bd1 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.sgwh/src/gov/noaa/nws/ncep/common/dataplugin/sgwh/SgwhRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.sgwh/src/gov/noaa/nws/ncep/common/dataplugin/sgwh/SgwhRecord.java @@ -1,26 +1,3 @@ -/** - * SgwhRecord - * This java class performs the mapping to the database for BUFR Sgwh. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date			Ticket#		Engineer	Description
- * ------------ -----------	----------- --------------------------
- * Aug17 2011	   		    Chin Chen	Initial Coding (Following BufrsgwhRecord to refactor for 
- * 										saving data to HDF5)
- * Apr 4, 2013        1846 bkowal      Added an index on refTime and forecastTime
- * Apr 8, 2013  1293        bkowal      Removed references to hdffileid.
- * Apr 12, 2013 1857        bgonzale    Added SequenceGenerator annotation.
- * May 07, 2013 1869       	bsteffen    Remove dataURI column from
- *                                      PluginDataObject.
- *
- * 
- * - * @author chin chen - * @version 1.0 - */ package gov.noaa.nws.ncep.common.dataplugin.sgwh; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; @@ -50,6 +27,30 @@ import com.raytheon.uf.common.pointdata.PointDataView; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +/** + * SgwhRecord This java class performs the mapping to the database for BUFR + * Sgwh. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------- ----------- --------------------------
+ * Aug17 2011               Chin Chen   Initial Coding (Following BufrsgwhRecord
+ *                                      to refactor for  saving data to HDF5)
+ * Apr 04, 2013 1846        bkowal      Added an index on refTime and
+ *                                      forecastTime
+ * Apr 08, 2013 1293        bkowal      Removed references to hdffileid.
+ * Apr 12, 2013 1857        bgonzale    Added SequenceGenerator annotation.
+ * May 07, 2013 1869        bsteffen    Remove dataURI column from
+ *                                      PluginDataObject.
+ * Aug 30, 2013 2298        rjpeter     Make getPluginName abstract
+ * 
+ * + * @author chin chen + * @version 1.0 + */ @Entity @SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "sgwhseq") @Table(name = "sgwh", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) @@ -57,1674 +58,1613 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "sgwh", - indexes = { - @Index(name = "sgwh_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "sgwh", indexes = { @Index(name = "sgwh_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class SgwhRecord extends PluginDataObject implements IDecoderGettable, - IPointData, IPersistable { - private static final long serialVersionUID = 1L; - - /** Satellite Identification */ - @Column - @DataURI(position = 1) - @DynamicSerializeElement - private Long said; - - /** Software Identification */ - @Column - @DynamicSerializeElement - private Long swid; - - /** Identification of the originating/generating center */ - @Column - @DynamicSerializeElement - private Long ogce; - - /** Satellite sensor indicator, first occurrence */ - @Column - @DynamicSerializeElement - private Long ssin1; - - /** Satellite sensor indicator, second occurrence */ - @Column - @DynamicSerializeElement - private Long ssin2; - - /** Orbit Number */ - @Column - @DataURI(position = 2) - @DynamicSerializeElement - private Long orbn; - - /** Height of station in meters */ - @Column - @DynamicSerializeElement - private Double selv = IDecoderConstantsN.DOUBLE_MISSING; - - /** Height increment in meters */ - @Column - @DynamicSerializeElement - private Double hinc = IDecoderConstantsN.DOUBLE_MISSING; - - /** Observation time */ - @Column - @DataURI(position = 3) - @DynamicSerializeElement - private Calendar obsTime; - - /** Latitude */ - @Column - @DataURI(position = 4) - @DynamicSerializeElement - private Double clath = IDecoderConstantsN.DOUBLE_MISSING; - - /** Longitude */ - @Column - @DataURI(position = 5) - @DynamicSerializeElement - private Double clonh = IDecoderConstantsN.DOUBLE_MISSING; - - /** Remotely sensed surface type */ - @Transient - @DynamicSerializeElement - private Long rsst; - - /** Altimeter echo type */ - @Transient - @DynamicSerializeElement - private Long aetp; - - /** Land/Sea qualifier */ - @Transient - @DynamicSerializeElement - private Long lsql; - - /** Altimeter state flag */ - @Transient - @DynamicSerializeElement - private Long asfl; - - /** Radiometer state flag */ - @Transient - @DynamicSerializeElement - private Long rsfl; - - /** 3D error estimate of the navigator orbit */ - @Transient - @DynamicSerializeElement - private Long eeno; - - /** Associated field significance for sgwh */ - @Transient - @DynamicSerializeElement - private Long afssgwh; - - /** Significant wave height in meters */ - @Transient - @DynamicSerializeElement - private Double sgwh = IDecoderConstantsN.DOUBLE_MISSING; - - /** First order statistics */ - @Transient - @DynamicSerializeElement - private Long fostsgwh; - - /** Significant wave height (standard deviation) in meters */ - @Transient - @DynamicSerializeElement - private Double sgwhstd = IDecoderConstantsN.DOUBLE_MISSING; - - /** Number of valid points per second used to derive previous parameters */ - @Transient - @DynamicSerializeElement - private Long nvpp; - - /** Type of Band for 1st replication */ - @Transient - @DynamicSerializeElement - private Long tobdg1r1; - - /** Type of Band for 2nd replication */ - @Transient - @DynamicSerializeElement - private Long tobdg1r2; - - /** - * Associated field significance for group 1, replication 1, first - * occurrence - */ - @Transient - @DynamicSerializeElement - private Long afsbkstg1r1; - - /** - * Associated field significance for group 1, replication 2, first - * occurrence - */ - @Transient - @DynamicSerializeElement - private Long afsbkstg1r2; - - /** Backscatter in decibels for group 1 rep 1 */ - @Transient - @DynamicSerializeElement - private Double bkstg1r1 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Backscatter in decibels for group 1 rep 2 */ - @Transient - @DynamicSerializeElement - private Double bkstg1r2 = IDecoderConstantsN.DOUBLE_MISSING; - - /** fost for bkst for group 1, replication 1, first fost occurrence */ - @Transient - @DynamicSerializeElement - private Long fostbkstg1r1; - - /** fost for bkst for group 1, replication 2, first fost occurrence */ - @Transient - @DynamicSerializeElement - private Long fostbkstg1r2; - - /** Backscatter Standard Deviation in decibels for group 1 rep 1 */ - @Transient - @DynamicSerializeElement - private Double bkststdg1r1 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Backscatter Standard Deviation in decibels for group 1 rep 2 */ - @Transient - @DynamicSerializeElement - private Double bkststdg1r2 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Square of the off-nadir angle in degrees squared */ - @Transient - @DynamicSerializeElement - private Double sona; - - /** - * Associated Field Significance for Square of the off-nadir angle in - * degrees squared - */ - @Transient - @DynamicSerializeElement - private Long afssona; - - /** Radiometer water vapor content in kg per square meter */ - @Transient - @DynamicSerializeElement - private Double rwvc = IDecoderConstantsN.DOUBLE_MISSING; - - /** Radiometer liquid content in kg per square meter */ - @Transient - @DynamicSerializeElement - private Double rlqc = IDecoderConstantsN.DOUBLE_MISSING; - - /** - * Associated field significance for group 1, replication 1, second - * occurrence - */ - @Transient - @DynamicSerializeElement - private Long afsselvg1r1; - - /** - * Associated field significance for group 1, replication 2, second - * occurrence - */ - @Transient - @DynamicSerializeElement - private Long afsselvg1r2; - - /** Height of station for 1st replication */ - @Transient - @DynamicSerializeElement - private Double selvg1r1 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Height of station for 2nd replication */ - @Transient - @DynamicSerializeElement - private Double selvg1r2 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Height increment in meters for 1st replication */ - @Transient - @DynamicSerializeElement - private Double hincg1r1 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Height increment in meters for snd replication */ - @Transient - @DynamicSerializeElement - private Double hincg1r2 = IDecoderConstantsN.DOUBLE_MISSING; - - /** fost for selv for group 1, replication 1, second fost occurrence */ - @Transient - @DynamicSerializeElement - private Long fostselvg1r1; - - /** fost for selv for group 1, replication 2, second fost occurrence */ - @Transient - @DynamicSerializeElement - private Long fostselvg1r2; - - /** Std of Height of station for 1st replication */ - @Transient - @DynamicSerializeElement - private Double selvstdg1r1 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Std of Height of station for 2nd replication */ - @Transient - @DynamicSerializeElement - private Double selvstdg1r2 = IDecoderConstantsN.DOUBLE_MISSING; - - /** - * Number of valid points per second used to derive previous parameters for - * 1st replication - */ - @Transient - @DynamicSerializeElement - private Long nvppg1r1; - - /** - * Number of valid points per second used to derive previous parameters for - * 2nd replication - */ - @Transient - @DynamicSerializeElement - private Long nvppg1r2; - - /** MEFR Mean Frequency for group 2 for 1st replication */ - @Transient - @DynamicSerializeElement - private Double mefrg2r1 = IDecoderConstantsN.DOUBLE_MISSING; - - /** mefr Mean Frequency for group 2 for 2nd replication */ - @Transient - @DynamicSerializeElement - private Double mefrg2r2 = IDecoderConstantsN.DOUBLE_MISSING; - - /** mefr Mean Frequency for group 2 for 3rd replication */ - @Transient - @DynamicSerializeElement - private Double mefrg2r3 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Associated field significance for tmbr for group 2, replication 1 */ - @Transient - @DynamicSerializeElement - private Long afstmbrg2r1; - - /** Associated field significance for tmbr for group 2, replication 2 */ - @Transient - @DynamicSerializeElement - private Long afstmbrg2r2; - - /** Associated field significance for tmbr for group 2, replication 3 */ - @Transient - @DynamicSerializeElement - private Long afstmbrg2r3; - - /** Brightness temperature tmbrg2r1 in K for group 2, rep 1 */ - @Transient - @DynamicSerializeElement - private Double tmbrg2r1 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Brightness temperature tmbrg2r2 in K for group 2 rep 2 */ - @Transient - @DynamicSerializeElement - private Double tmbrg2r2 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Brightness temperature tmbrg2r3 in K for group 2 rep 3 */ - @Transient - @DynamicSerializeElement - private Double tmbrg2r3 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Satellite-derived wind computation method swcmg3r1 for group 3 rep 1 */ - @Transient - @DynamicSerializeElement - private Long swcmg3r1; - - /** Satellite-derived wind computation method swcmg3r1 for group 3 rep 2 */ - @Transient - @DynamicSerializeElement - private Long swcmg3r2; - - /** Wind speed at 10 m; in meters per second; for group 3 rep 1 */ - @Transient - @DynamicSerializeElement - private Double ws10g3r1 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Wind speed at 10 m; in meters per second; for group 3 rep 2 */ - @Transient - @DynamicSerializeElement - private Double ws10g3r2 = IDecoderConstantsN.DOUBLE_MISSING; - - /** Report type */ - // @Column(length=8) - @Transient - @DynamicSerializeElement - @DataURI(position=6) - private String reportType; - - /** Text of the WMO header */ - @Column(length = 32) - @DynamicSerializeElement - private String wmoHeader; - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - /** - * Empty constructor. - */ - public SgwhRecord() { - } - - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - */ - public SgwhRecord(String uri) { - super(uri); - } - - /** - * Get the observation report type. - * - * @return the reportType - */ - public String getReportType() { - return reportType; - } - - /** - * Set the observation report type. - * - * @param reportType - * the reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } - - /** - * Get the Satellite Identifier. - * - * @return the Satellite ID - */ - public Long getSaid() { - return said; - } - - /** - * Set the Satellite Identifier. - * - * @param said - * the Satellite ID to set - */ - public void setSaid(Long said) { - this.said = said; - } - - /** - * @param swid - * the Software Identification to get - */ - /** - * @return the swid - */ - public Long getSwid() { - return swid; - } - - /** - * @param swid - * the Software Identification to set - */ - public void setSwid(Long swid) { - this.swid = swid; - } - - /** - * @param ogce - * the Identification of originating/generating center to return - */ - /** - * @return the ogce - */ - public Long getOgce() { - return ogce; - } - - /** - * @param ogce - * the Identification of originating/generating center to set - */ - public void setOgce(Long ogce) { - this.ogce = ogce; - } - - /** - * @param ssin1 - * the Satellite Sensor Indicator 1 to return - */ - /** - * @return the ssin1 - */ - public Long getSsin1() { - return ssin1; - } - - /** - * @param ssin - * the Satellite Sensor Indicator 1 to set - */ - public void setSsin1(Long ssin1) { - this.ssin1 = ssin1; - } - - /** - * @param ssin - * the Satellite Sensor Indicator 2 to return - */ - /** - * @return the ssin2 - */ - public Long getSsin2() { - return ssin2; - } - - /** - * @param ssin2 - * the Satellite Sensor Indicator 2 to set - */ - public void setSsin2(Long ssin2) { - this.ssin2 = ssin2; - } - - /** - * @param orbn - * the Orbit number to return - */ - /** - * @return the orbn - */ - public Long getOrbn() { - return orbn; - } - - /** - * @param orbn - * the Orbit number to set - */ - public void setOrbn(Long orbn) { - this.orbn = orbn; - } - - /** - * @param selv - * height of station to return - */ - /** - * @return the selv - */ - public Double getSelv() { - return selv; - } - - /** - * @param selv - * the height of elevation to set - */ - public void setSelv(Double selv) { - this.selv = selv; - } - - /** - * @param hinc - * height increment to return - */ - /** - * @return the hinc - */ - public Double getHinc() { - return hinc; - } - - /** - * @param hinc - * the height increment to set - */ - public void setHinc(Double hinc) { - this.hinc = hinc; - } - - /** - * @return the clath - */ - public Double getClath() { - return clath; - } - - /** - * @param clath - * the clath to set - */ - public void setClath(Double clath) { - this.clath = clath; - } - - /** - * @return the clonh - */ - public Double getClonh() { - return clonh; - } - - /** - * @param clonh - * the clonh to set - */ - public void setClonh(Double clonh) { - this.clonh = clonh; - } - - /** - * @param rsst - * remotely sensed surface type to return - */ - /** - * @return the rsst - */ - public Long getRsst() { - return rsst; - } - - /** - * @param rsst - * the remotely sensed surface type to set - */ - public void setRsst(Long rsst) { - this.rsst = rsst; - } - - /** - * @param aetp - * remotely sensed surface type to return - */ - /** - * @return the aetp - */ - public Long getAetp() { - return aetp; - } - - /** - * @param aetp - * the remotely sensed surface type to set - */ - public void setAetp(Long aetp) { - this.aetp = aetp; - } - - /** - * @param lsql - * land/sea qualifier to return - */ - /** - * @return the lsql - */ - public Long getLsql() { - return lsql; - } - - /** - * @param lsql - * land/sea qualifer to set - */ - public void setLsql(Long lsql) { - this.lsql = lsql; - } - - /** - * @param asfl - * altimeter state flag to return - */ - /** - * @return the asfl - */ - public Long getAsfl() { - return asfl; - } - - /** - * @param asfl - * the altimeter state flag to set - */ - public void setAsfl(Long asfl) { - this.asfl = asfl; - } - - /** - * @param rsfl - * radiometer state flag to return - */ - /** - * @return the rsfl - */ - public Long getRsfl() { - return rsfl; - } - - /** - * @param rsfl - * the radiometer state flag to set - */ - public void setRsfl(Long rsfl) { - this.rsfl = rsfl; - } - - /** - * @param eeno - * three dimensional error estimate of the navigator orbit to - * return - */ - /** - * @return the eeno - */ - public Long getEeno() { - return eeno; - } - - /** - * @param eeno - * three dimensional error estimate of the navigator orbit to set - */ - public void setEeno(Long eeno) { - this.eeno = eeno; - } - - /** - * @param afssgwh - * associated field significance for sgwh to return - */ - /** - * @return the afssgwh - */ - public Long getAfssgwh() { - return afssgwh; - } - - /** - * @param afssgwh - * associated field significance for sgwh to set - */ - public void setAfssgwh(Long afssgwh) { - this.afssgwh = afssgwh; - } - - /** - * @param sgwh - * significant wave height to return - */ - /** - * @return the sgwh - */ - public Double getSgwh() { - return sgwh; - } - - /** - * @param sgwh - * significant wave height to set - */ - public void setSgwh(Double sgwh) { - this.sgwh = sgwh; - } - - /** - * @param sgwh - * significant wave height (standard deviation) to return - */ - /** - * @return the sgwhStd - */ - public Double getSgwhstd() { - return sgwhstd; - } - - /** - * @param sgwh - * significant wave height to set - */ - public void setSgwhstd(Double sgwhstd) { - this.sgwhstd = sgwhstd; - } - - /** - * @param fostsgwh - * first order statistics for sgwh to return - */ - /** - * @return the fostsgwh - */ - public Long getFostsgwh() { - return fostsgwh; - } - - /** - * @param fostsgwh - * first order statistics for sgwh to set - */ - public void setFostsgwh(Long fostsgwh) { - this.fostsgwh = fostsgwh; - } - - /** - * @param nvpp - * number of valid points per sec used to derive previous - * parameters to return - */ - /** - * @return the nvpp - */ - public Long getNvpp() { - return nvpp; - } - - /** - * @param nvpp - * number of valid points per sec used to derive previous - * parameters to set - */ - public void setNvpp(Long nvpp) { - this.nvpp = nvpp; - } - - /** - * @param tobdg1r1 - * type of band for 1st replication to return - */ - /** - * @return the tobdg1r1 - */ - public Long getTobdg1r1() { - return tobdg1r1; - } - - /** - * @param tbnd - * type of band for 1st replication to set - */ - public void setTobdg1r1(Long tobdg1r1) { - this.tobdg1r1 = tobdg1r1; - } - - /** - * @param tobdg1r2 - * type of band for 2nd replication to return - */ - /** - * @return the tobdg1r2 - */ - public Long getTobdg1r2() { - return tobdg1r2; - } - - /** - * @param tobdg1r2 - * type of band for 2nd replication to set - */ - public void setTobdg1r2(Long tobdg1r2) { - this.tobdg1r2 = tobdg1r2; - } - - /** - * @param afsbkstg1r1 - * associated field sig. bkst in group1, 1st replication to - * return - */ - /** - * @return the afsbkstg1r1 - */ - public Long getAfsbkstg1r1() { - return afsbkstg1r1; - } - - /** - * @param afsbkstg1r1 - * associated field sig. for bkst in group 1, 1st replication to - * set - */ - public void setAfsbkstg1r1(Long afsbkstg1r1) { - this.afsbkstg1r1 = afsbkstg1r1; - } - - /** - * @param afsbkstg1r2 - * associated field sig for bkst in group 1, 2nd replication to - * return - */ - /** - * @return the afsbkstg1r2 - */ - public Long getAfsbkstg1r2() { - return afsbkstg1r2; - } - - /** - * @param afsbkstg1r2 - * associated field sig for bkst in group 1, 2nd replication to - * set - */ - public void setAfsbkstg1r2(Long afsbkstg1r2) { - this.afsbkstg1r2 = afsbkstg1r2; - } - - /** - * @param afsselvg1r1 - * associated field sig for selv in group 1, 1st replication to - * return - */ - /** - * @return the afsselvg1r1 - */ - public Long getAfsselvg1r1() { - return afsselvg1r1; - } - - /** - * @param afsselvg1r1 - * associated field sig for selv in group 1, 1st replication to - * set - */ - public void setAfsselvg1r1(Long afsselvg1r1) { - this.afsselvg1r1 = afsselvg1r1; - } - - /** - * @param afsselvg1r2b - * associated field sig for selv in group 1, 2nd replication to - * return - */ - /** - * @return the afsselvg1r2 - */ - public Long getAfsselvg1r2() { - return afsselvg1r2; - } - - /** - * @param afsselvg1r2b - * associated field sig for selv in group 1 for 2nd replication - * to set - */ - public void setAfsselvg1r2(Long afsselvg1r2) { - this.afsselvg1r2 = afsselvg1r2; - } - - /** - * @param fostbkstg1r1 - * fost for bkst for group 1, 1st replication to return - */ - /** - * @return the fostbkstg1r1 - */ - public Long getFostbkstg1r1() { - return fostbkstg1r1; - } - - /** - * @param fostbkstg1r1 - * fost for bkst for group 1, 1st replication to set - */ - public void setFostbkstg1r1(Long fostbkstg1r1) { - this.fostbkstg1r1 = fostbkstg1r1; - } - - /** - * @param fostbkstg1r2 - * fost for bkst for group 1, 2nd replication to return - */ - /** - * @return the fostbkstg1r2 fost for bkst for group 1, 2nd replication to - * set - */ - public Long getFostbkstg1r2() { - return fostbkstg1r2; - } - - /** - * @param afsg1r2 - * associated field sig for 1st occurrence in group 1, 2nd - * replication to set - */ - public void setFostbkstg1r2(Long fostbkstg1r2) { - this.fostbkstg1r2 = fostbkstg1r2; - } - - /** - * @param bkstg1r1 - * backscatter to return - */ - /** - * @return the bkstg1r1 - */ - public Double getBkstg1r1() { - return bkstg1r1; - } - - /** - * @param bkst - * backscatter to set - */ - public void setBkstg1r1(Double bkstg1r1) { - this.bkstg1r1 = bkstg1r1; - } - - /** - * @param bkststdg1r1 - * backscatter standard deviation to return - */ - /** - * @return the bkststdg1r1 - */ - public Double getBkststdg1r1() { - return bkststdg1r1; - } - - /** - * @param bkststdg1r1 - * backscatter standard deviation to set - */ - public void setBkststdg1r1(Double bkststdg1r1) { - this.bkststdg1r1 = bkststdg1r1; - } - - /** - * @param bkstg1r2 - * backscatter to return - */ - /** - * @return the bkstg1r2 - */ - public Double getBkstg1r2() { - return bkstg1r2; - } - - /** - * @param bkstg1r2 - * backscatter to set - */ - public void setBkstg1r2(Double bkstg1r2) { - this.bkstg1r2 = bkstg1r2; - } - - /** - * @param bkststdg1r2 - * backscatter standard deviation to return - */ - /** - * @return the bkststdg1r2 - */ - public Double getBkststdg1r2() { - return bkststdg1r2; - } - - /** - * @param bkststdg1r - * backscatter standard deviation to set - */ - public void setBkststdg1r2(Double bkststdg1r2) { - this.bkststdg1r2 = bkststdg1r2; - } - - /** - * @param fostselvg1r1 - * fost for selv for group 1, 1st replication to return - */ - /** - * @return the fostselvg1r1 - */ - public Long getFostselvg1r1() { - return fostselvg1r1; - } - - /** - * @param fostselvg1r1 - * fost for selv for group 1, 1st replication to set - */ - public void setFostselvg1r1(Long fostselvg1r1) { - this.fostselvg1r1 = fostselvg1r1; - } - - /** - * @param fostselvg1r2 - * fost for selv for group 1, 2nd replication to return - */ - /** - * @return the fostselvg1r2 - */ - public Long getFostselvg1r2() { - return fostselvg1r2; - } - - /** - * @param fostselvg1r2 - * fost for selv for 1st occurrence in group 1, 2nd replication - * to set - */ - public void setFostselvg1r2(Long fostselvg1r2) { - this.fostselvg1r2 = fostselvg1r2; - } - - /** - * @param selvg1r1 - * elevation of satellite in group 1 replication 1 to return - */ - /** - * @return the selvg1r1 - */ - public Double getSelvg1r1() { - return selvg1r1; - } - - /** - * @param selv - * elevation of satellite in group 1 replication 1 to set - */ - public void setSelvg1r1(Double selvg1r1) { - this.selvg1r1 = selvg1r1; - } - - /** - * @param selvg1r2 - * elevation of satellite in group 1 replication 2 to return - */ - /** - * @return the selvg1r2 - */ - public Double getSelvg1r2() { - return selvg1r2; - } - - /** - * @param selvg1r2 - * elevation of satellite in group 1 replication 2 to set - */ - public void setSelvg1r2(Double selvg1r2) { - this.selvg1r2 = selvg1r2; - } - - /** - * @param hincg1r1 - * height increment in group 1 replication 1 to return - */ - /** - * @return the hincg1r1 - */ - public Double getHincg1r1() { - return hincg1r1; - } - - /** - * @param hincg1r1 - * height increment in group 1 replication 1 to set - */ - public void setHincg1r1(Double hincg1r1) { - this.hincg1r1 = hincg1r1; - } - - /** - * @param hincg1r2 - * height increment in group 1 replication 2 to return - */ - /** - * @return the hincg1r2 - */ - public Double getHincg1r2() { - return hincg1r2; - } - - /** - * @param hincg1r1 - * height increment in group 1 replication 2 to set - */ - public void setHincg1r2(Double hincg1r2) { - this.hincg1r2 = hincg1r2; - } - - /** - * @param selvstdg1r1 - * std of elevation of satellite in group 1 replication 1 to - * return - */ - /** - * @return the selvstdg1r1 - */ - public Double getSelvstdg1r1() { - return selvstdg1r1; - } - - /** - * @param selvstdg1r1 - * elevation of satellite in group 1 replication 2 to set - */ - public void setSelvstdg1r1(Double selvstdg1r1) { - this.selvstdg1r1 = selvstdg1r1; - } - - /** - * @param selvstdg1r2 - * std of elevation of satellite in group 1 replication 1 to - * return - */ - /** - * @return the selvstdg1r2 - */ - public Double getSelvstdg1r2() { - return selvstdg1r2; - } - - /** - * @param selvstdg1r2 - * elevation of satellite in group 1 replication 2 to set - */ - public void setSelvstdg1r2(Double selvstdg1r2) { - this.selvstdg1r2 = selvstdg1r2; - } - - /** - * @param nvppg1r1 - * number of valid points per sec used to derive previous - * parameters in group 1 replication 1 to return - */ - /** - * @return the nvppg1r1 - */ - public Long getNvppg1r1() { - return nvppg1r1; - } - - /** - * @param nvppg1r1 - * number of valid points per sec used to derive previous - * parameters in group 1 replication 1 to set - */ - public void setNvppg1r1(Long nvppg1r1) { - this.nvppg1r1 = nvppg1r1; - } - - /** - * @param nvppg1r2 - * number of valid points per sec used to derive previous - * parameters in group 1 replication 2 to return - */ - /** - * @return the nvppg1r1 - */ - public Long getNvppg1r2() { - return nvppg1r2; - } - - /** - * @param nvppg1r2 - * number of valid points per sec used to derive previous - * parameters in group 1 replication 2 to set - */ - public void setNvppg1r2(Long nvppg1r2) { - this.nvppg1r2 = nvppg1r2; - } - - /** - * @param afssona - * Associated Field Significance of Square of the off-nadir angle - * to return - */ - /** - * @return the afssona - */ - public Long getAfssona() { - return afssona; - } - - /** - * @param afssona - * Assocaited Field Significance of sona to set - */ - public void setAfssona(Long afssona) { - this.afssona = afssona; - } - - /** - * @param sona - * Square of the off-nadir angle to return - */ - /** - * @return the sona - */ - public Double getSona() { - return sona; - } - - /** - * @param sona - * Square of the off-nadir angle to set - */ - public void setSona(Double sona) { - this.sona = sona; - } - - /** - * @param mefrg2r1 - * mean frequency in hz for group 2 rep 1 to return - */ - /** - * @return the mefrg2r1 - */ - public Double getMefrg2r1() { - return mefrg2r1; - } - - /** - * @param mefrg2r1 - * mean frequency for group 2 rep 1 to set - */ - public void setMefrg2r1(Double mefrg2r1) { - this.mefrg2r1 = mefrg2r1; - } - - /** - * @param mefrg2r2 - * mean frequency in hz for group 2 rep 2 to return - */ - /** - * @return the mefrg2r2 - */ - public Double getMefrg2r2() { - return mefrg2r2; - } - - /** - * @param mefrg2r2 - * mean frequency for group 2 rep 2 to set - */ - public void setMefrg2r2(Double mefrg2r2) { - this.mefrg2r2 = mefrg2r2; - } - - /** - * @param mefrg2r3 - * mean frequency in hz for group 2 rep 3 to return - */ - /** - * @return the mefrg2r3 - */ - public Double getMefrg2r3() { - return mefrg2r3; - } - - /** - * @param mefrg2r3 - * mean frequency for group 2 rep 3 to set - */ - public void setMefrg2r3(Double mefrg2r3) { - this.mefrg2r3 = mefrg2r3; - } - - /** - * @param afstmbrg2r1 - * associated field sig for tmbr in group 2, 1st replication to - * return - */ - /** - * @return the afstmbrg2r1 - */ - public Long getAfstmbrg2r1() { - return afstmbrg2r1; - } - - /** - * @param afstmbrg2r1 - * associated field sig for tmbr in group 2, 1st replication to - * set - */ - public void setAfstmbrg2r1(Long afstmbrg2r1) { - this.afstmbrg2r1 = afstmbrg2r1; - } - - /** - * @param afstmbrg2r2b - * associated field sig for tmbr in group 2, 2nd replication to - * return - */ - /** - * @return the afstmbrg2r2 - */ - public Long getAfstmbrg2r2() { - return afstmbrg2r2; - } - - /** - * @param afstmbrg2r2b - * associated field sig for tmbr in group 2 for 2nd replication - * to set - */ - public void setAfstmbrg2r2(Long afstmbrg2r2) { - this.afstmbrg2r2 = afstmbrg2r2; - } - - /** - * @param afstmbrg2r3 - * associated field sig for tmbr in group 2, 3rd replication to - * return - */ - /** - * @return the afstmbrg2r3 - */ - public Long getAfstmbrg2r3() { - return afstmbrg2r3; - } - - /** - * @param afstmbrg2r3 - * associated field sig for tmbr in group 2, 3rd replication to - * set - */ - public void setAfstmbrg2r3(Long afstmbrg2r3) { - this.afstmbrg2r3 = afstmbrg2r3; - } - - /** - * @param tmbrg2r1 - * brightness temperature in K for group 2 rep 1 to return - */ - /** - * @return the tmbrg2r1 - */ - public Double getTmbrg2r1() { - return tmbrg2r1; - } - - /** - * @param tmbrg2r1 - * brightness temperaturefor group 2 rep 1 to set - */ - public void setTmbrg2r1(Double tmbrg2r1) { - this.tmbrg2r1 = tmbrg2r1; - } - - /** - * @param tmbrg2r2 - * brightness temperature in K for group 2 rep 2 to return - */ - /** - * @return the tmbrg2r2 - */ - public Double getTmbrg2r2() { - return tmbrg2r2; - } - - /** - * @param tmbrg2r2 - * brightness temperaturefor group 2 rep 2 to set - */ - public void setTmbrg2r2(Double tmbrg2r2) { - this.tmbrg2r2 = tmbrg2r2; - } - - /** - * @param tmbrg2r3 - * brightness temperature in K for group 2 rep 3 to return - */ - /** - * @return the tmbrg2r3 - */ - public Double getTmbrg2r3() { - return tmbrg2r3; - } - - /** - * @param tmbrg2r3 - * mean frequency for group 2 rep 3 to set - */ - public void setTmbrg2r3(Double tmbrg2r3) { - this.tmbrg2r3 = tmbrg2r3; - } - - /** - * @param swcmg3r1 - * satellite-derived wind computation method for group 3 rep 1 to - * return - */ - /** - * @return the swcmg3r1 - */ - public Long getSwcmg3r1() { - return swcmg3r1; - } - - /** - * @param swcmg3r1 - * satellite-derived wind computation method for group 3 rep 1 to - * set - */ - public void setSwcmg3r1(Long swcmg3r1) { - this.swcmg3r1 = swcmg3r1; - } - - /** - * @param swcmg3r2 - * satellite-derived wind computation method for group 3 rep 2 to - * return - */ - /** - * @return the swcmg3r2 - */ - public Long getSwcmg3r2() { - return swcmg3r2; - } - - /** - * @param swcmg3r2 - * satellite-derived wind computation method for group 3 rep 2 to - * set - */ - public void setSwcmg3r2(Long swcmg3r2) { - this.swcmg3r2 = swcmg3r2; - } - - /** - * @param ws10g3r1 - * wind speed at 10 m for group 3 rep 1 to return - */ - /** - * @return the ws10g3r1 - */ - public Double getWs10g3r1() { - return ws10g3r1; - } - - /** - * @param ws10g3r1 - * wind speed at 10 m to set - */ - public void setWs10g3r1(Double ws10g3r1) { - this.ws10g3r1 = ws10g3r1; - } - - /** - * @param ws10g3r1 - * wind speed at 10 m for group 3 rep 2 to return - */ - /** - * @return the ws10g3r2 - */ - public Double getWs10g3r2() { - return ws10g3r2; - } - - /** - * @param ws10g3r1 - * wind speed at 10 m to set - */ - public void setWs10g3r2(Double ws10g3r2) { - this.ws10g3r2 = ws10g3r2; - } - - /** - * @param rwvc - * radiometer liquid content to return - */ - /** - * @return the rwvc - */ - public Double getRwvc() { - return rwvc; - } - - /** - * @param rwvc - * radiometer liquid content to set - */ - public void setRwvc(Double rwvc) { - this.rwvc = rwvc; - } - - /** - * @param rlqc - * radiometer liquid content to return - */ - /** - * @return the rlqc - */ - public Double getRlqc() { - return rlqc; - } - - /** - * @param rlqc - * radiometer liquid content to set - */ - public void setRlqc(Double rlqc) { - this.rlqc = rlqc; - } - - /** - * @return the wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } - - /** - * @param wmoHeader - * the wmoHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } - - /** - * @return the obsTime - */ - public Calendar getObsTime() { - return obsTime; - } - - /** - * @param obsTime - * the obsTime to set - */ - public void setObsTime(Calendar obsTime) { - this.obsTime = obsTime; - } - - /** - * Get the value and units of a named parameter within this observation. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return An Amount with value and units. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Amount getValue(String paramName) { - return null; - } - - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public String getString(String paramName) { - return null; - } - - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Collection getValues(String paramName) { - return null; - } - - /** - * Get the IDecoderGettable reference for this record. - * - * @return The IDecoderGettable reference for this record. - */ - @Override - public IDecoderGettable getDecoderGettable() { - return this; - } - - @Override - public void setDataURI(String dataURI) { - identifier = dataURI; - } - - @Override - public String[] getStrings(String paramName) { - return null; - } - - @Override - public Date getPersistenceTime() { - return this.dataTime.getRefTime(); - - } - - @Override - public void setPersistenceTime(Date persistTime) { - // TODO Auto-generated method stub - - } - - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } - - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - - } + IPointData, IPersistable { + private static final long serialVersionUID = 1L; + + /** Satellite Identification */ + @Column + @DataURI(position = 1) + @DynamicSerializeElement + private Long said; + + /** Software Identification */ + @Column + @DynamicSerializeElement + private Long swid; + + /** Identification of the originating/generating center */ + @Column + @DynamicSerializeElement + private Long ogce; + + /** Satellite sensor indicator, first occurrence */ + @Column + @DynamicSerializeElement + private Long ssin1; + + /** Satellite sensor indicator, second occurrence */ + @Column + @DynamicSerializeElement + private Long ssin2; + + /** Orbit Number */ + @Column + @DataURI(position = 2) + @DynamicSerializeElement + private Long orbn; + + /** Height of station in meters */ + @Column + @DynamicSerializeElement + private Double selv = IDecoderConstantsN.DOUBLE_MISSING; + + /** Height increment in meters */ + @Column + @DynamicSerializeElement + private Double hinc = IDecoderConstantsN.DOUBLE_MISSING; + + /** Observation time */ + @Column + @DataURI(position = 3) + @DynamicSerializeElement + private Calendar obsTime; + + /** Latitude */ + @Column + @DataURI(position = 4) + @DynamicSerializeElement + private Double clath = IDecoderConstantsN.DOUBLE_MISSING; + + /** Longitude */ + @Column + @DataURI(position = 5) + @DynamicSerializeElement + private Double clonh = IDecoderConstantsN.DOUBLE_MISSING; + + /** Remotely sensed surface type */ + @Transient + @DynamicSerializeElement + private Long rsst; + + /** Altimeter echo type */ + @Transient + @DynamicSerializeElement + private Long aetp; + + /** Land/Sea qualifier */ + @Transient + @DynamicSerializeElement + private Long lsql; + + /** Altimeter state flag */ + @Transient + @DynamicSerializeElement + private Long asfl; + + /** Radiometer state flag */ + @Transient + @DynamicSerializeElement + private Long rsfl; + + /** 3D error estimate of the navigator orbit */ + @Transient + @DynamicSerializeElement + private Long eeno; + + /** Associated field significance for sgwh */ + @Transient + @DynamicSerializeElement + private Long afssgwh; + + /** Significant wave height in meters */ + @Transient + @DynamicSerializeElement + private Double sgwh = IDecoderConstantsN.DOUBLE_MISSING; + + /** First order statistics */ + @Transient + @DynamicSerializeElement + private Long fostsgwh; + + /** Significant wave height (standard deviation) in meters */ + @Transient + @DynamicSerializeElement + private Double sgwhstd = IDecoderConstantsN.DOUBLE_MISSING; + + /** Number of valid points per second used to derive previous parameters */ + @Transient + @DynamicSerializeElement + private Long nvpp; + + /** Type of Band for 1st replication */ + @Transient + @DynamicSerializeElement + private Long tobdg1r1; + + /** Type of Band for 2nd replication */ + @Transient + @DynamicSerializeElement + private Long tobdg1r2; + + /** + * Associated field significance for group 1, replication 1, first + * occurrence + */ + @Transient + @DynamicSerializeElement + private Long afsbkstg1r1; + + /** + * Associated field significance for group 1, replication 2, first + * occurrence + */ + @Transient + @DynamicSerializeElement + private Long afsbkstg1r2; + + /** Backscatter in decibels for group 1 rep 1 */ + @Transient + @DynamicSerializeElement + private Double bkstg1r1 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Backscatter in decibels for group 1 rep 2 */ + @Transient + @DynamicSerializeElement + private Double bkstg1r2 = IDecoderConstantsN.DOUBLE_MISSING; + + /** fost for bkst for group 1, replication 1, first fost occurrence */ + @Transient + @DynamicSerializeElement + private Long fostbkstg1r1; + + /** fost for bkst for group 1, replication 2, first fost occurrence */ + @Transient + @DynamicSerializeElement + private Long fostbkstg1r2; + + /** Backscatter Standard Deviation in decibels for group 1 rep 1 */ + @Transient + @DynamicSerializeElement + private Double bkststdg1r1 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Backscatter Standard Deviation in decibels for group 1 rep 2 */ + @Transient + @DynamicSerializeElement + private Double bkststdg1r2 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Square of the off-nadir angle in degrees squared */ + @Transient + @DynamicSerializeElement + private Double sona; + + /** + * Associated Field Significance for Square of the off-nadir angle in + * degrees squared + */ + @Transient + @DynamicSerializeElement + private Long afssona; + + /** Radiometer water vapor content in kg per square meter */ + @Transient + @DynamicSerializeElement + private Double rwvc = IDecoderConstantsN.DOUBLE_MISSING; + + /** Radiometer liquid content in kg per square meter */ + @Transient + @DynamicSerializeElement + private Double rlqc = IDecoderConstantsN.DOUBLE_MISSING; + + /** + * Associated field significance for group 1, replication 1, second + * occurrence + */ + @Transient + @DynamicSerializeElement + private Long afsselvg1r1; + + /** + * Associated field significance for group 1, replication 2, second + * occurrence + */ + @Transient + @DynamicSerializeElement + private Long afsselvg1r2; + + /** Height of station for 1st replication */ + @Transient + @DynamicSerializeElement + private Double selvg1r1 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Height of station for 2nd replication */ + @Transient + @DynamicSerializeElement + private Double selvg1r2 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Height increment in meters for 1st replication */ + @Transient + @DynamicSerializeElement + private Double hincg1r1 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Height increment in meters for snd replication */ + @Transient + @DynamicSerializeElement + private Double hincg1r2 = IDecoderConstantsN.DOUBLE_MISSING; + + /** fost for selv for group 1, replication 1, second fost occurrence */ + @Transient + @DynamicSerializeElement + private Long fostselvg1r1; + + /** fost for selv for group 1, replication 2, second fost occurrence */ + @Transient + @DynamicSerializeElement + private Long fostselvg1r2; + + /** Std of Height of station for 1st replication */ + @Transient + @DynamicSerializeElement + private Double selvstdg1r1 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Std of Height of station for 2nd replication */ + @Transient + @DynamicSerializeElement + private Double selvstdg1r2 = IDecoderConstantsN.DOUBLE_MISSING; + + /** + * Number of valid points per second used to derive previous parameters for + * 1st replication + */ + @Transient + @DynamicSerializeElement + private Long nvppg1r1; + + /** + * Number of valid points per second used to derive previous parameters for + * 2nd replication + */ + @Transient + @DynamicSerializeElement + private Long nvppg1r2; + + /** MEFR Mean Frequency for group 2 for 1st replication */ + @Transient + @DynamicSerializeElement + private Double mefrg2r1 = IDecoderConstantsN.DOUBLE_MISSING; + + /** mefr Mean Frequency for group 2 for 2nd replication */ + @Transient + @DynamicSerializeElement + private Double mefrg2r2 = IDecoderConstantsN.DOUBLE_MISSING; + + /** mefr Mean Frequency for group 2 for 3rd replication */ + @Transient + @DynamicSerializeElement + private Double mefrg2r3 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Associated field significance for tmbr for group 2, replication 1 */ + @Transient + @DynamicSerializeElement + private Long afstmbrg2r1; + + /** Associated field significance for tmbr for group 2, replication 2 */ + @Transient + @DynamicSerializeElement + private Long afstmbrg2r2; + + /** Associated field significance for tmbr for group 2, replication 3 */ + @Transient + @DynamicSerializeElement + private Long afstmbrg2r3; + + /** Brightness temperature tmbrg2r1 in K for group 2, rep 1 */ + @Transient + @DynamicSerializeElement + private Double tmbrg2r1 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Brightness temperature tmbrg2r2 in K for group 2 rep 2 */ + @Transient + @DynamicSerializeElement + private Double tmbrg2r2 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Brightness temperature tmbrg2r3 in K for group 2 rep 3 */ + @Transient + @DynamicSerializeElement + private Double tmbrg2r3 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Satellite-derived wind computation method swcmg3r1 for group 3 rep 1 */ + @Transient + @DynamicSerializeElement + private Long swcmg3r1; + + /** Satellite-derived wind computation method swcmg3r1 for group 3 rep 2 */ + @Transient + @DynamicSerializeElement + private Long swcmg3r2; + + /** Wind speed at 10 m; in meters per second; for group 3 rep 1 */ + @Transient + @DynamicSerializeElement + private Double ws10g3r1 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Wind speed at 10 m; in meters per second; for group 3 rep 2 */ + @Transient + @DynamicSerializeElement + private Double ws10g3r2 = IDecoderConstantsN.DOUBLE_MISSING; + + /** Report type */ + // @Column(length=8) + @Transient + @DynamicSerializeElement + @DataURI(position = 6) + private String reportType; + + /** Text of the WMO header */ + @Column(length = 32) + @DynamicSerializeElement + private String wmoHeader; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + /** + * Empty constructor. + */ + public SgwhRecord() { + } + + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + */ + public SgwhRecord(String uri) { + super(uri); + } + + /** + * Get the observation report type. + * + * @return the reportType + */ + public String getReportType() { + return reportType; + } + + /** + * Set the observation report type. + * + * @param reportType + * the reportType to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } + + /** + * Get the Satellite Identifier. + * + * @return the Satellite ID + */ + public Long getSaid() { + return said; + } + + /** + * Set the Satellite Identifier. + * + * @param said + * the Satellite ID to set + */ + public void setSaid(Long said) { + this.said = said; + } + + /** + * @param swid + * the Software Identification to get + * + * @return the swid + */ + public Long getSwid() { + return swid; + } + + /** + * @param swid + * the Software Identification to set + */ + public void setSwid(Long swid) { + this.swid = swid; + } + + /** + * @param ogce + * the Identification of originating/generating center to return + * + * @return the ogce + */ + public Long getOgce() { + return ogce; + } + + /** + * @param ogce + * the Identification of originating/generating center to set + */ + public void setOgce(Long ogce) { + this.ogce = ogce; + } + + /** + * @param ssin1 + * the Satellite Sensor Indicator 1 to return + * + * @return the ssin1 + */ + public Long getSsin1() { + return ssin1; + } + + /** + * @param ssin + * the Satellite Sensor Indicator 1 to set + */ + public void setSsin1(Long ssin1) { + this.ssin1 = ssin1; + } + + /** + * @param ssin + * the Satellite Sensor Indicator 2 to return + * + * @return the ssin2 + */ + public Long getSsin2() { + return ssin2; + } + + /** + * @param ssin2 + * the Satellite Sensor Indicator 2 to set + */ + public void setSsin2(Long ssin2) { + this.ssin2 = ssin2; + } + + /** + * @param orbn + * the Orbit number to return + * + * @return the orbn + */ + public Long getOrbn() { + return orbn; + } + + /** + * @param orbn + * the Orbit number to set + */ + public void setOrbn(Long orbn) { + this.orbn = orbn; + } + + /** + * @param selv + * height of station to return + * + * @return the selv + */ + public Double getSelv() { + return selv; + } + + /** + * @param selv + * the height of elevation to set + */ + public void setSelv(Double selv) { + this.selv = selv; + } + + /** + * @param hinc + * height increment to return + * + * @return the hinc + */ + public Double getHinc() { + return hinc; + } + + /** + * @param hinc + * the height increment to set + */ + public void setHinc(Double hinc) { + this.hinc = hinc; + } + + /** + * @return the clath + */ + public Double getClath() { + return clath; + } + + /** + * @param clath + * the clath to set + */ + public void setClath(Double clath) { + this.clath = clath; + } + + /** + * @return the clonh + */ + public Double getClonh() { + return clonh; + } + + /** + * @param clonh + * the clonh to set + */ + public void setClonh(Double clonh) { + this.clonh = clonh; + } + + /** + * @param rsst + * remotely sensed surface type to return + * + * @return the rsst + */ + public Long getRsst() { + return rsst; + } + + /** + * @param rsst + * the remotely sensed surface type to set + */ + public void setRsst(Long rsst) { + this.rsst = rsst; + } + + /** + * @param aetp + * remotely sensed surface type to return + * + * @return the aetp + */ + public Long getAetp() { + return aetp; + } + + /** + * @param aetp + * the remotely sensed surface type to set + */ + public void setAetp(Long aetp) { + this.aetp = aetp; + } + + /** + * @param lsql + * land/sea qualifier to return + * + * @return the lsql + */ + public Long getLsql() { + return lsql; + } + + /** + * @param lsql + * land/sea qualifer to set + */ + public void setLsql(Long lsql) { + this.lsql = lsql; + } + + /** + * @param asfl + * altimeter state flag to return + * + * @return the asfl + */ + public Long getAsfl() { + return asfl; + } + + /** + * @param asfl + * the altimeter state flag to set + */ + public void setAsfl(Long asfl) { + this.asfl = asfl; + } + + /** + * @param rsfl + * radiometer state flag to return + * + * @return the rsfl + */ + public Long getRsfl() { + return rsfl; + } + + /** + * @param rsfl + * the radiometer state flag to set + */ + public void setRsfl(Long rsfl) { + this.rsfl = rsfl; + } + + /** + * @param eeno + * three dimensional error estimate of the navigator orbit to + * return + * + * @return the eeno + */ + public Long getEeno() { + return eeno; + } + + /** + * @param eeno + * three dimensional error estimate of the navigator orbit to set + */ + public void setEeno(Long eeno) { + this.eeno = eeno; + } + + /** + * @param afssgwh + * associated field significance for sgwh to return + * + * @return the afssgwh + */ + public Long getAfssgwh() { + return afssgwh; + } + + /** + * @param afssgwh + * associated field significance for sgwh to set + */ + public void setAfssgwh(Long afssgwh) { + this.afssgwh = afssgwh; + } + + /** + * @param sgwh + * significant wave height to return + * + * @return the sgwh + */ + public Double getSgwh() { + return sgwh; + } + + /** + * @param sgwh + * significant wave height to set + */ + public void setSgwh(Double sgwh) { + this.sgwh = sgwh; + } + + /** + * @param sgwh + * significant wave height (standard deviation) to return + * + * @return the sgwhStd + */ + public Double getSgwhstd() { + return sgwhstd; + } + + /** + * @param sgwh + * significant wave height to set + */ + public void setSgwhstd(Double sgwhstd) { + this.sgwhstd = sgwhstd; + } + + /** + * @param fostsgwh + * first order statistics for sgwh to return + * + * @return the fostsgwh + */ + public Long getFostsgwh() { + return fostsgwh; + } + + /** + * @param fostsgwh + * first order statistics for sgwh to set + */ + public void setFostsgwh(Long fostsgwh) { + this.fostsgwh = fostsgwh; + } + + /** + * @param nvpp + * number of valid points per sec used to derive previous + * parameters to return + * + * @return the nvpp + */ + public Long getNvpp() { + return nvpp; + } + + /** + * @param nvpp + * number of valid points per sec used to derive previous + * parameters to set + */ + public void setNvpp(Long nvpp) { + this.nvpp = nvpp; + } + + /** + * @param tobdg1r1 + * type of band for 1st replication to return + * + * @return the tobdg1r1 + */ + public Long getTobdg1r1() { + return tobdg1r1; + } + + /** + * @param tbnd + * type of band for 1st replication to set + */ + public void setTobdg1r1(Long tobdg1r1) { + this.tobdg1r1 = tobdg1r1; + } + + /** + * @param tobdg1r2 + * type of band for 2nd replication to return + * + * @return the tobdg1r2 + */ + public Long getTobdg1r2() { + return tobdg1r2; + } + + /** + * @param tobdg1r2 + * type of band for 2nd replication to set + */ + public void setTobdg1r2(Long tobdg1r2) { + this.tobdg1r2 = tobdg1r2; + } + + /** + * @param afsbkstg1r1 + * associated field sig. bkst in group1, 1st replication to + * return + * + * @return the afsbkstg1r1 + */ + public Long getAfsbkstg1r1() { + return afsbkstg1r1; + } + + /** + * @param afsbkstg1r1 + * associated field sig. for bkst in group 1, 1st replication to + * set + */ + public void setAfsbkstg1r1(Long afsbkstg1r1) { + this.afsbkstg1r1 = afsbkstg1r1; + } + + /** + * @param afsbkstg1r2 + * associated field sig for bkst in group 1, 2nd replication to + * return + * + * @return the afsbkstg1r2 + */ + public Long getAfsbkstg1r2() { + return afsbkstg1r2; + } + + /** + * @param afsbkstg1r2 + * associated field sig for bkst in group 1, 2nd replication to + * set + */ + public void setAfsbkstg1r2(Long afsbkstg1r2) { + this.afsbkstg1r2 = afsbkstg1r2; + } + + /** + * @param afsselvg1r1 + * associated field sig for selv in group 1, 1st replication to + * return + * + * @return the afsselvg1r1 + */ + public Long getAfsselvg1r1() { + return afsselvg1r1; + } + + /** + * @param afsselvg1r1 + * associated field sig for selv in group 1, 1st replication to + * set + */ + public void setAfsselvg1r1(Long afsselvg1r1) { + this.afsselvg1r1 = afsselvg1r1; + } + + /** + * @param afsselvg1r2b + * associated field sig for selv in group 1, 2nd replication to + * return + * + * @return the afsselvg1r2 + */ + public Long getAfsselvg1r2() { + return afsselvg1r2; + } + + /** + * @param afsselvg1r2b + * associated field sig for selv in group 1 for 2nd replication + * to set + */ + public void setAfsselvg1r2(Long afsselvg1r2) { + this.afsselvg1r2 = afsselvg1r2; + } + + /** + * @param fostbkstg1r1 + * fost for bkst for group 1, 1st replication to return + * + * @return the fostbkstg1r1 + */ + public Long getFostbkstg1r1() { + return fostbkstg1r1; + } + + /** + * @param fostbkstg1r1 + * fost for bkst for group 1, 1st replication to set + */ + public void setFostbkstg1r1(Long fostbkstg1r1) { + this.fostbkstg1r1 = fostbkstg1r1; + } + + /** + * @param fostbkstg1r2 + * fost for bkst for group 1, 2nd replication to return + * + * @return the fostbkstg1r2 fost for bkst for group 1, 2nd replication to + * set + */ + public Long getFostbkstg1r2() { + return fostbkstg1r2; + } + + /** + * @param afsg1r2 + * associated field sig for 1st occurrence in group 1, 2nd + * replication to set + */ + public void setFostbkstg1r2(Long fostbkstg1r2) { + this.fostbkstg1r2 = fostbkstg1r2; + } + + /** + * @param bkstg1r1 + * backscatter to return + * + * @return the bkstg1r1 + */ + public Double getBkstg1r1() { + return bkstg1r1; + } + + /** + * @param bkst + * backscatter to set + */ + public void setBkstg1r1(Double bkstg1r1) { + this.bkstg1r1 = bkstg1r1; + } + + /** + * @param bkststdg1r1 + * backscatter standard deviation to return + * + * @return the bkststdg1r1 + */ + public Double getBkststdg1r1() { + return bkststdg1r1; + } + + /** + * @param bkststdg1r1 + * backscatter standard deviation to set + */ + public void setBkststdg1r1(Double bkststdg1r1) { + this.bkststdg1r1 = bkststdg1r1; + } + + /** + * @param bkstg1r2 + * backscatter to return + * + * @return the bkstg1r2 + */ + public Double getBkstg1r2() { + return bkstg1r2; + } + + /** + * @param bkstg1r2 + * backscatter to set + */ + public void setBkstg1r2(Double bkstg1r2) { + this.bkstg1r2 = bkstg1r2; + } + + /** + * @param bkststdg1r2 + * backscatter standard deviation to return + * + * @return the bkststdg1r2 + */ + public Double getBkststdg1r2() { + return bkststdg1r2; + } + + /** + * @param bkststdg1r + * backscatter standard deviation to set + */ + public void setBkststdg1r2(Double bkststdg1r2) { + this.bkststdg1r2 = bkststdg1r2; + } + + /** + * @param fostselvg1r1 + * fost for selv for group 1, 1st replication to return + * + * @return the fostselvg1r1 + */ + public Long getFostselvg1r1() { + return fostselvg1r1; + } + + /** + * @param fostselvg1r1 + * fost for selv for group 1, 1st replication to set + */ + public void setFostselvg1r1(Long fostselvg1r1) { + this.fostselvg1r1 = fostselvg1r1; + } + + /** + * @param fostselvg1r2 + * fost for selv for group 1, 2nd replication to return + * + * @return the fostselvg1r2 + */ + public Long getFostselvg1r2() { + return fostselvg1r2; + } + + /** + * @param fostselvg1r2 + * fost for selv for 1st occurrence in group 1, 2nd replication + * to set + */ + public void setFostselvg1r2(Long fostselvg1r2) { + this.fostselvg1r2 = fostselvg1r2; + } + + /** + * @param selvg1r1 + * elevation of satellite in group 1 replication 1 to return + * + * @return the selvg1r1 + */ + public Double getSelvg1r1() { + return selvg1r1; + } + + /** + * @param selv + * elevation of satellite in group 1 replication 1 to set + */ + public void setSelvg1r1(Double selvg1r1) { + this.selvg1r1 = selvg1r1; + } + + /** + * @param selvg1r2 + * elevation of satellite in group 1 replication 2 to return + * + * @return the selvg1r2 + */ + public Double getSelvg1r2() { + return selvg1r2; + } + + /** + * @param selvg1r2 + * elevation of satellite in group 1 replication 2 to set + */ + public void setSelvg1r2(Double selvg1r2) { + this.selvg1r2 = selvg1r2; + } + + /** + * @param hincg1r1 + * height increment in group 1 replication 1 to return + * + * @return the hincg1r1 + */ + public Double getHincg1r1() { + return hincg1r1; + } + + /** + * @param hincg1r1 + * height increment in group 1 replication 1 to set + */ + public void setHincg1r1(Double hincg1r1) { + this.hincg1r1 = hincg1r1; + } + + /** + * @param hincg1r2 + * height increment in group 1 replication 2 to return + * + * @return the hincg1r2 + */ + public Double getHincg1r2() { + return hincg1r2; + } + + /** + * @param hincg1r1 + * height increment in group 1 replication 2 to set + */ + public void setHincg1r2(Double hincg1r2) { + this.hincg1r2 = hincg1r2; + } + + /** + * @param selvstdg1r1 + * std of elevation of satellite in group 1 replication 1 to + * return + * + * @return the selvstdg1r1 + */ + public Double getSelvstdg1r1() { + return selvstdg1r1; + } + + /** + * @param selvstdg1r1 + * elevation of satellite in group 1 replication 2 to set + */ + public void setSelvstdg1r1(Double selvstdg1r1) { + this.selvstdg1r1 = selvstdg1r1; + } + + /** + * @param selvstdg1r2 + * std of elevation of satellite in group 1 replication 1 to + * return + * + * @return the selvstdg1r2 + */ + public Double getSelvstdg1r2() { + return selvstdg1r2; + } + + /** + * @param selvstdg1r2 + * elevation of satellite in group 1 replication 2 to set + */ + public void setSelvstdg1r2(Double selvstdg1r2) { + this.selvstdg1r2 = selvstdg1r2; + } + + /** + * @param nvppg1r1 + * number of valid points per sec used to derive previous + * parameters in group 1 replication 1 to return + * + * @return the nvppg1r1 + */ + public Long getNvppg1r1() { + return nvppg1r1; + } + + /** + * @param nvppg1r1 + * number of valid points per sec used to derive previous + * parameters in group 1 replication 1 to set + */ + public void setNvppg1r1(Long nvppg1r1) { + this.nvppg1r1 = nvppg1r1; + } + + /** + * @param nvppg1r2 + * number of valid points per sec used to derive previous + * parameters in group 1 replication 2 to return + * + * @return the nvppg1r1 + */ + public Long getNvppg1r2() { + return nvppg1r2; + } + + /** + * @param nvppg1r2 + * number of valid points per sec used to derive previous + * parameters in group 1 replication 2 to set + */ + public void setNvppg1r2(Long nvppg1r2) { + this.nvppg1r2 = nvppg1r2; + } + + /** + * @param afssona + * Associated Field Significance of Square of the off-nadir angle + * to return + * + * @return the afssona + */ + public Long getAfssona() { + return afssona; + } + + /** + * @param afssona + * Assocaited Field Significance of sona to set + */ + public void setAfssona(Long afssona) { + this.afssona = afssona; + } + + /** + * @param sona + * Square of the off-nadir angle to return + * + * @return the sona + */ + public Double getSona() { + return sona; + } + + /** + * @param sona + * Square of the off-nadir angle to set + */ + public void setSona(Double sona) { + this.sona = sona; + } + + /** + * @param mefrg2r1 + * mean frequency in hz for group 2 rep 1 to return + * + * @return the mefrg2r1 + */ + public Double getMefrg2r1() { + return mefrg2r1; + } + + /** + * @param mefrg2r1 + * mean frequency for group 2 rep 1 to set + */ + public void setMefrg2r1(Double mefrg2r1) { + this.mefrg2r1 = mefrg2r1; + } + + /** + * @param mefrg2r2 + * mean frequency in hz for group 2 rep 2 to return + * + * @return the mefrg2r2 + */ + public Double getMefrg2r2() { + return mefrg2r2; + } + + /** + * @param mefrg2r2 + * mean frequency for group 2 rep 2 to set + */ + public void setMefrg2r2(Double mefrg2r2) { + this.mefrg2r2 = mefrg2r2; + } + + /** + * @param mefrg2r3 + * mean frequency in hz for group 2 rep 3 to return + * + * @return the mefrg2r3 + */ + public Double getMefrg2r3() { + return mefrg2r3; + } + + /** + * @param mefrg2r3 + * mean frequency for group 2 rep 3 to set + */ + public void setMefrg2r3(Double mefrg2r3) { + this.mefrg2r3 = mefrg2r3; + } + + /** + * @param afstmbrg2r1 + * associated field sig for tmbr in group 2, 1st replication to + * return + * + * @return the afstmbrg2r1 + */ + public Long getAfstmbrg2r1() { + return afstmbrg2r1; + } + + /** + * @param afstmbrg2r1 + * associated field sig for tmbr in group 2, 1st replication to + * set + */ + public void setAfstmbrg2r1(Long afstmbrg2r1) { + this.afstmbrg2r1 = afstmbrg2r1; + } + + /** + * @param afstmbrg2r2b + * associated field sig for tmbr in group 2, 2nd replication to + * return + * + * @return the afstmbrg2r2 + */ + public Long getAfstmbrg2r2() { + return afstmbrg2r2; + } + + /** + * @param afstmbrg2r2b + * associated field sig for tmbr in group 2 for 2nd replication + * to set + */ + public void setAfstmbrg2r2(Long afstmbrg2r2) { + this.afstmbrg2r2 = afstmbrg2r2; + } + + /** + * @param afstmbrg2r3 + * associated field sig for tmbr in group 2, 3rd replication to + * return + * + * @return the afstmbrg2r3 + */ + public Long getAfstmbrg2r3() { + return afstmbrg2r3; + } + + /** + * @param afstmbrg2r3 + * associated field sig for tmbr in group 2, 3rd replication to + * set + */ + public void setAfstmbrg2r3(Long afstmbrg2r3) { + this.afstmbrg2r3 = afstmbrg2r3; + } + + /** + * @param tmbrg2r1 + * brightness temperature in K for group 2 rep 1 to return + * + * @return the tmbrg2r1 + */ + public Double getTmbrg2r1() { + return tmbrg2r1; + } + + /** + * @param tmbrg2r1 + * brightness temperaturefor group 2 rep 1 to set + */ + public void setTmbrg2r1(Double tmbrg2r1) { + this.tmbrg2r1 = tmbrg2r1; + } + + /** + * @param tmbrg2r2 + * brightness temperature in K for group 2 rep 2 to return + * + * @return the tmbrg2r2 + */ + public Double getTmbrg2r2() { + return tmbrg2r2; + } + + /** + * @param tmbrg2r2 + * brightness temperaturefor group 2 rep 2 to set + */ + public void setTmbrg2r2(Double tmbrg2r2) { + this.tmbrg2r2 = tmbrg2r2; + } + + /** + * @param tmbrg2r3 + * brightness temperature in K for group 2 rep 3 to return + * + * @return the tmbrg2r3 + */ + public Double getTmbrg2r3() { + return tmbrg2r3; + } + + /** + * @param tmbrg2r3 + * mean frequency for group 2 rep 3 to set + */ + public void setTmbrg2r3(Double tmbrg2r3) { + this.tmbrg2r3 = tmbrg2r3; + } + + /** + * @param swcmg3r1 + * satellite-derived wind computation method for group 3 rep 1 to + * return + * + * @return the swcmg3r1 + */ + public Long getSwcmg3r1() { + return swcmg3r1; + } + + /** + * @param swcmg3r1 + * satellite-derived wind computation method for group 3 rep 1 to + * set + */ + public void setSwcmg3r1(Long swcmg3r1) { + this.swcmg3r1 = swcmg3r1; + } + + /** + * @param swcmg3r2 + * satellite-derived wind computation method for group 3 rep 2 to + * return + * + * @return the swcmg3r2 + */ + public Long getSwcmg3r2() { + return swcmg3r2; + } + + /** + * @param swcmg3r2 + * satellite-derived wind computation method for group 3 rep 2 to + * set + */ + public void setSwcmg3r2(Long swcmg3r2) { + this.swcmg3r2 = swcmg3r2; + } + + /** + * @param ws10g3r1 + * wind speed at 10 m for group 3 rep 1 to return + * + * @return the ws10g3r1 + */ + public Double getWs10g3r1() { + return ws10g3r1; + } + + /** + * @param ws10g3r1 + * wind speed at 10 m to set + */ + public void setWs10g3r1(Double ws10g3r1) { + this.ws10g3r1 = ws10g3r1; + } + + /** + * @param ws10g3r1 + * wind speed at 10 m for group 3 rep 2 to return + * + * @return the ws10g3r2 + */ + public Double getWs10g3r2() { + return ws10g3r2; + } + + /** + * @param ws10g3r1 + * wind speed at 10 m to set + */ + public void setWs10g3r2(Double ws10g3r2) { + this.ws10g3r2 = ws10g3r2; + } + + /** + * @param rwvc + * radiometer liquid content to return + * + * @return the rwvc + */ + public Double getRwvc() { + return rwvc; + } + + /** + * @param rwvc + * radiometer liquid content to set + */ + public void setRwvc(Double rwvc) { + this.rwvc = rwvc; + } + + /** + * @param rlqc + * radiometer liquid content to return + * + * @return the rlqc + */ + public Double getRlqc() { + return rlqc; + } + + /** + * @param rlqc + * radiometer liquid content to set + */ + public void setRlqc(Double rlqc) { + this.rlqc = rlqc; + } + + /** + * @return the wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } + + /** + * @param wmoHeader + * the wmoHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } + + /** + * @return the obsTime + */ + public Calendar getObsTime() { + return obsTime; + } + + /** + * @param obsTime + * the obsTime to set + */ + public void setObsTime(Calendar obsTime) { + this.obsTime = obsTime; + } + + /** + * Get the value and units of a named parameter within this observation. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return An Amount with value and units. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Amount getValue(String paramName) { + return null; + } + + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public String getString(String paramName) { + return null; + } + + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Collection getValues(String paramName) { + return null; + } + + /** + * Get the IDecoderGettable reference for this record. + * + * @return The IDecoderGettable reference for this record. + */ + @Override + public IDecoderGettable getDecoderGettable() { + return this; + } + + @Override + public void setDataURI(String dataURI) { + identifier = dataURI; + } + + @Override + public String[] getStrings(String paramName) { + return null; + } + + @Override + public Date getPersistenceTime() { + return this.dataTime.getRefTime(); + + } + + @Override + public void setPersistenceTime(Date persistTime) { + // TODO Auto-generated method stub + + } + + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } + + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + + } @Override @Column @@ -1733,4 +1673,8 @@ public class SgwhRecord extends PluginDataObject implements IDecoderGettable, return super.getDataURI(); } + @Override + public String getPluginName() { + return "sgwh"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.sgwhv/src/gov/noaa/nws/ncep/common/dataplugin/sgwhv/SgwhvRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.sgwhv/src/gov/noaa/nws/ncep/common/dataplugin/sgwhv/SgwhvRecord.java index a85a13e802..9ff61d069f 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.sgwhv/src/gov/noaa/nws/ncep/common/dataplugin/sgwhv/SgwhvRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.sgwhv/src/gov/noaa/nws/ncep/common/dataplugin/sgwhv/SgwhvRecord.java @@ -1,26 +1,3 @@ -/** - * SgwhvRecord - * This java class performs the mapping to the database for BUFR Sgwhv. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date			Ticket#		Engineer	Description
- * ------------ -----------	----------- --------------------------
- * Aug23 2011	   		    Chin Chen	Initial Coding (Following BufrsgwhvRecord to refactor for 
- * 										saving data to HDF5)
- * Apr 4, 2013        1846 bkowal      Added an index on refTime and forecastTime
- * Apr 8, 2013   1293       bkowal      Removed references to hdffileid.
- * Apr 12, 2013 1857        bgonzale    Added SequenceGenerator annotation.
- * May 07, 2013 1869       	bsteffen    Remove dataURI column from
- *                                      PluginDataObject.
- *
- * 
- * - * @author chin chen - * @version 1.0 - */ package gov.noaa.nws.ncep.common.dataplugin.sgwhv; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; @@ -50,6 +27,31 @@ import com.raytheon.uf.common.pointdata.PointDataView; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +/** + * SgwhvRecord + * This java class performs the mapping to the database for BUFR Sgwhv. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------- ----------- --------------------------
+ * Aug23 2011               Chin Chen   Initial Coding (Following
+ *                                      BufrsgwhvRecord to refactor for  saving
+ *                                      data to HDF5)
+ * Apr 04, 2013 1846        bkowal      Added an index on refTime and
+ *                                      forecastTime
+ * Apr 08, 2013 1293        bkowal      Removed references to hdffileid.
+ * Apr 12, 2013 1857        bgonzale    Added SequenceGenerator annotation.
+ * May 07, 2013 1869        bsteffen    Remove dataURI column from
+ *                                      PluginDataObject.
+ * Aug 30, 2013 2298        rjpeter     Make getPluginName abstract
+ * 
+ * + * @author chin chen + * @version 1.0 + */ @Entity @SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "sgwhvseq") @Table(name = "sgwhv", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) @@ -57,486 +59,484 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "sgwhv", - indexes = { - @Index(name = "sgwhv_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "sgwhv", indexes = { @Index(name = "sgwhv_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class SgwhvRecord extends PluginDataObject implements IDecoderGettable, - IPointData, IPersistable { - private static final long serialVersionUID = 1L; - private static final float RMISSD = IDecoderConstantsN.FLOAT_MISSING; - private static final Integer IMISSD = IDecoderConstantsN.INTEGER_MISSING; + IPointData, IPersistable { + private static final long serialVersionUID = 1L; - /** Satellite Identification */ - @Column - /* - * Height of waves are from blended TOPEX/Poseidon, Jason-1, ERS 1, ERS 2m - * GPO and Envisat ocean altimetry satellites, therefore satelliteId should - * be a primary key. Data is from Navoceano. SGWH is from Jason-1 and has - * satelliteID of 260. SGWH2 is from Jason-2 and has satelliteId of 261. - * SGWHE is from Envisat and has satelliteId of 60. - */ - @DataURI(position = 4) - @DynamicSerializeElement - private Long satelliteId; + private static final float RMISSD = IDecoderConstantsN.FLOAT_MISSING; - /** Observation time */ - @Column - @DataURI(position = 1) - @DynamicSerializeElement - private Calendar obsTime; + private static final Integer IMISSD = IDecoderConstantsN.INTEGER_MISSING; - /** Latitude */ - @Column - @DataURI(position = 2) - @DynamicSerializeElement - private Double lat; + /** Satellite Identification */ + @Column + /* + * Height of waves are from blended TOPEX/Poseidon, Jason-1, ERS 1, ERS 2m + * GPO and Envisat ocean altimetry satellites, therefore satelliteId should + * be a primary key. Data is from Navoceano. SGWH is from Jason-1 and has + * satelliteID of 260. SGWH2 is from Jason-2 and has satelliteId of 261. + * SGWHE is from Envisat and has satelliteId of 60. + */ + @DataURI(position = 4) + @DynamicSerializeElement + private Long satelliteId; - /** Longitude */ - @Column - @DataURI(position = 3) - @DynamicSerializeElement - private Double lon; + /** Observation time */ + @Column + @DataURI(position = 1) + @DynamicSerializeElement + private Calendar obsTime; - /** Wind speed at 10 m (m/s) */ - @Transient - @DynamicSerializeElement - private Double wspd10; + /** Latitude */ + @Column + @DataURI(position = 2) + @DynamicSerializeElement + private Double lat; - /** Height of waves (m) */ - @Transient - @DynamicSerializeElement - private Double htwaves; + /** Longitude */ + @Column + @DataURI(position = 3) + @DynamicSerializeElement + private Double lon; - /** Standard Deviation of significant wave height (m) */ - @Transient - @DynamicSerializeElement - private Double sgwhSd; + /** Wind speed at 10 m (m/s) */ + @Transient + @DynamicSerializeElement + private Double wspd10; - /** Altitude (Platform to ellipsoid) (m) */ - @Transient - @DynamicSerializeElement - private Double altitude; + /** Height of waves (m) */ + @Transient + @DynamicSerializeElement + private Double htwaves; - /** Number of valid points per second used to derive previous parameters */ - @Transient - @DynamicSerializeElement - private Long peak; + /** Standard Deviation of significant wave height (m) */ + @Transient + @DynamicSerializeElement + private Double sgwhSd; - /** Altitude correction (ionosphere) */ - @Transient - @DynamicSerializeElement - private Double altCorrI; + /** Altitude (Platform to ellipsoid) (m) */ + @Transient + @DynamicSerializeElement + private Double altitude; - /** Altitude correction (dry troposphere) */ - @Transient - @DynamicSerializeElement - private Double altCorrD; + /** Number of valid points per second used to derive previous parameters */ + @Transient + @DynamicSerializeElement + private Long peak; - /** Altitude correction (wet troposphere) */ - @Transient - @DynamicSerializeElement - private Double altCorrW; + /** Altitude correction (ionosphere) */ + @Transient + @DynamicSerializeElement + private Double altCorrI; - /** Open loop correction (auto gain control) in decibels for group 1 rep 2 */ - @Transient - @DynamicSerializeElement - private Double loopCorr; + /** Altitude correction (dry troposphere) */ + @Transient + @DynamicSerializeElement + private Double altCorrD; - /** Backscatter in decibels */ - @Transient - @DynamicSerializeElement - private Double bkst; + /** Altitude correction (wet troposphere) */ + @Transient + @DynamicSerializeElement + private Double altCorrW; - /** Report type */ - // @Column(length=8) - @Transient - @DynamicSerializeElement - @DataURI(position=5) - private String reportType; + /** Open loop correction (auto gain control) in decibels for group 1 rep 2 */ + @Transient + @DynamicSerializeElement + private Double loopCorr; - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; + /** Backscatter in decibels */ + @Transient + @DynamicSerializeElement + private Double bkst; - /** - * Default constructor. - */ - public SgwhvRecord() { - Double doubleRmissd = Double.parseDouble(String.valueOf(RMISSD)); - Long longImissd = Long.parseLong(String.valueOf(IMISSD)); - this.reportType = "BUFRSGWHV"; - this.satelliteId = longImissd; - this.lat = doubleRmissd; - this.lon = doubleRmissd; - this.altCorrD = doubleRmissd; - this.wspd10 = doubleRmissd; - this.htwaves = doubleRmissd; - this.sgwhSd = doubleRmissd; - this.altitude = doubleRmissd; - this.altCorrI = doubleRmissd; - this.altCorrD = doubleRmissd; - this.altCorrW = doubleRmissd; - this.loopCorr = doubleRmissd; - this.bkst = doubleRmissd; - this.peak = longImissd; - } + /** Report type */ + // @Column(length=8) + @Transient + @DynamicSerializeElement + @DataURI(position = 5) + private String reportType; - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - */ - public SgwhvRecord(String uri) { - super(uri); - } + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; - /** - * Get the observation report type. - * - * @return the reportType - */ - public String getReportType() { - return reportType; - } + /** + * Default constructor. + */ + public SgwhvRecord() { + Double doubleRmissd = Double.parseDouble(String.valueOf(RMISSD)); + Long longImissd = Long.parseLong(String.valueOf(IMISSD)); + this.reportType = "BUFRSGWHV"; + this.satelliteId = longImissd; + this.lat = doubleRmissd; + this.lon = doubleRmissd; + this.altCorrD = doubleRmissd; + this.wspd10 = doubleRmissd; + this.htwaves = doubleRmissd; + this.sgwhSd = doubleRmissd; + this.altitude = doubleRmissd; + this.altCorrI = doubleRmissd; + this.altCorrD = doubleRmissd; + this.altCorrW = doubleRmissd; + this.loopCorr = doubleRmissd; + this.bkst = doubleRmissd; + this.peak = longImissd; + } - /** - * Set the observation report type. - * - * @param reportType - * the reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + */ + public SgwhvRecord(String uri) { + super(uri); + } - /** - * Get the Satellite Identifier. - * - * @return the Satellite ID - */ - public Long getSatelliteId() { - return satelliteId; - } + /** + * Get the observation report type. + * + * @return the reportType + */ + public String getReportType() { + return reportType; + } - /** - * @param satelliteId - * the Satellite Identifier to set - */ - public void setSatelliteId(Long satelliteId) { - this.satelliteId = satelliteId; - } + /** + * Set the observation report type. + * + * @param reportType + * the reportType to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } - /** - * @return the lat - */ - public Double getLat() { - return lat; - } + /** + * Get the Satellite Identifier. + * + * @return the Satellite ID + */ + public Long getSatelliteId() { + return satelliteId; + } - /** - * @param lat - * the latitude (coarse) to set - */ - public void setLat(Double lat) { - this.lat = lat; - } + /** + * @param satelliteId + * the Satellite Identifier to set + */ + public void setSatelliteId(Long satelliteId) { + this.satelliteId = satelliteId; + } - /** - * @return the lon - */ - public Double getLon() { - return lon; - } + /** + * @return the lat + */ + public Double getLat() { + return lat; + } - /** - * @param lon - * the longitude (coarse) to set - */ - public void setLon(Double lon) { - this.lon = lon; - } + /** + * @param lat + * the latitude (coarse) to set + */ + public void setLat(Double lat) { + this.lat = lat; + } - /** - * @param wspd10 - * wind speed at 10 m to return - */ - public Double getWspd10() { - return wspd10; - } + /** + * @return the lon + */ + public Double getLon() { + return lon; + } - /** - * @param wspd10 - * wind speed at 10 m to set - */ - public void setWspd10(Double wspd10) { - this.wspd10 = wspd10; - } + /** + * @param lon + * the longitude (coarse) to set + */ + public void setLon(Double lon) { + this.lon = lon; + } - /** - * @param htwaves - * height of waves to return - */ - public Double getHtwaves() { - return htwaves; - } + /** + * @param wspd10 + * wind speed at 10 m to return + */ + public Double getWspd10() { + return wspd10; + } - /** - * @param htwaves - * height of waves to set - */ - public void setHtwaves(Double htwaves) { - this.htwaves = htwaves; - } + /** + * @param wspd10 + * wind speed at 10 m to set + */ + public void setWspd10(Double wspd10) { + this.wspd10 = wspd10; + } - /** - * @param SgwhSd - * SGWH standard deviation to return - */ - /** - * @return the SgwhSd - */ - public Double getSgwhSd() { - return sgwhSd; - } + /** + * @param htwaves + * height of waves to return + */ + public Double getHtwaves() { + return htwaves; + } - /** - * @param SgwhSd - * SGWH standard deviation to set - */ - public void setSgwhSd(Double sgwhSd) { - this.sgwhSd = sgwhSd; - } + /** + * @param htwaves + * height of waves to set + */ + public void setHtwaves(Double htwaves) { + this.htwaves = htwaves; + } - /** - * @param altitude - * altitude (platform to ellipsoid) m - */ - public Double getAltitude() { - return altitude; - } + /** + * @param SgwhSd + * SGWH standard deviation to return + */ + /** + * @return the SgwhSd + */ + public Double getSgwhSd() { + return sgwhSd; + } - /** - * @param altitude - * altitude to set - */ - public void setAltitude(Double altitude) { - this.altitude = altitude; - } + /** + * @param SgwhSd + * SGWH standard deviation to set + */ + public void setSgwhSd(Double sgwhSd) { + this.sgwhSd = sgwhSd; + } - /** - * @param peak - * peakiness to return - */ - /** - * @return the peak - */ - public Long getPeak() { - return peak; - } + /** + * @param altitude + * altitude (platform to ellipsoid) m + */ + public Double getAltitude() { + return altitude; + } - /** - * @param peak - * peakiness to set - */ - public void setPeak(Long peak) { - this.peak = peak; - } + /** + * @param altitude + * altitude to set + */ + public void setAltitude(Double altitude) { + this.altitude = altitude; + } - /** - * @param altCorrI - * altitude correction (ionosphere) to return - */ - /** - * @return the altCorrI - */ - public Double getAltCorrI() { - return altCorrI; - } + /** + * @param peak + * peakiness to return + */ + /** + * @return the peak + */ + public Long getPeak() { + return peak; + } - /** - * @param altCorrI - * altitude correction (ionosphere) (m) to set - */ - public void setAltCorrI(Double altCorrI) { - this.altCorrI = altCorrI; - } + /** + * @param peak + * peakiness to set + */ + public void setPeak(Long peak) { + this.peak = peak; + } - /** - * @param altCorrD - * altitude correction (dry troposphere) to return - */ - /** - * @return the altCorrD - */ - public Double getAltCorrD() { - return altCorrD; - } + /** + * @param altCorrI + * altitude correction (ionosphere) to return + */ + /** + * @return the altCorrI + */ + public Double getAltCorrI() { + return altCorrI; + } - /** - * @param altCorrD - * altitude correction (dry troposphere) (m) to set - */ - public void setAltCorrD(Double altCorrD) { - this.altCorrD = altCorrD; - } + /** + * @param altCorrI + * altitude correction (ionosphere) (m) to set + */ + public void setAltCorrI(Double altCorrI) { + this.altCorrI = altCorrI; + } - /** - * @param altCorrW - * altitude correction (wet troposphere) to return - */ - /** - * @return the altCorrW - */ - public Double getAltCorrW() { - return altCorrW; - } + /** + * @param altCorrD + * altitude correction (dry troposphere) to return + */ + /** + * @return the altCorrD + */ + public Double getAltCorrD() { + return altCorrD; + } - /** - * @param altCorrI - * altitude correction (wet troposphere) (m) to set - */ - public void setAltCorrW(Double altCorrW) { - this.altCorrW = altCorrW; - } + /** + * @param altCorrD + * altitude correction (dry troposphere) (m) to set + */ + public void setAltCorrD(Double altCorrD) { + this.altCorrD = altCorrD; + } - /** - * @param loopCorr - * open loop correction (auto gain control) (db) to return - */ - /** - * @return the loopCorr - */ - public Double getLoopCorr() { - return loopCorr; - } + /** + * @param altCorrW + * altitude correction (wet troposphere) to return + */ + /** + * @return the altCorrW + */ + public Double getAltCorrW() { + return altCorrW; + } - /** - * @param loopCorr - * open loop correction (auto gain control) (db) to set - */ - public void setLoopCorr(Double loopCorr) { - this.loopCorr = loopCorr; - } + /** + * @param altCorrI + * altitude correction (wet troposphere) (m) to set + */ + public void setAltCorrW(Double altCorrW) { + this.altCorrW = altCorrW; + } - /** - * @param bkst - * backscatter to return - */ - /** - * @return the bkst - */ - public Double getBkst() { - return bkst; - } + /** + * @param loopCorr + * open loop correction (auto gain control) (db) to return + */ + /** + * @return the loopCorr + */ + public Double getLoopCorr() { + return loopCorr; + } - /** - * @param bkst - * backscatter to set - */ - public void setBkst(Double bkst) { - this.bkst = bkst; - } + /** + * @param loopCorr + * open loop correction (auto gain control) (db) to set + */ + public void setLoopCorr(Double loopCorr) { + this.loopCorr = loopCorr; + } - /** - * @return the obsTime - */ - public Calendar getObsTime() { - return obsTime; - } + /** + * @param bkst + * backscatter to return + */ + /** + * @return the bkst + */ + public Double getBkst() { + return bkst; + } - /** - * @param obsTime - * the obsTime to set - */ - public void setObsTime(Calendar obsTime) { - this.obsTime = obsTime; - } + /** + * @param bkst + * backscatter to set + */ + public void setBkst(Double bkst) { + this.bkst = bkst; + } - /** - * Get the value and units of a named parameter within this observation. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return An Amount with value and units. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Amount getValue(String paramName) { - return null; - } + /** + * @return the obsTime + */ + public Calendar getObsTime() { + return obsTime; + } - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public String getString(String paramName) { - return null; - } + /** + * @param obsTime + * the obsTime to set + */ + public void setObsTime(Calendar obsTime) { + this.obsTime = obsTime; + } - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Collection getValues(String paramName) { - return null; - } + /** + * Get the value and units of a named parameter within this observation. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return An Amount with value and units. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Amount getValue(String paramName) { + return null; + } - /** - * Get the IDecoderGettable reference for this record. - * - * @return The IDecoderGettable reference for this record. - */ - @Override - public IDecoderGettable getDecoderGettable() { - return this; - } + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public String getString(String paramName) { + return null; + } - @Override - public void setDataURI(String dataURI) { - identifier = dataURI; - } + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Collection getValues(String paramName) { + return null; + } - @Override - public String[] getStrings(String paramName) { - return null; - } + /** + * Get the IDecoderGettable reference for this record. + * + * @return The IDecoderGettable reference for this record. + */ + @Override + public IDecoderGettable getDecoderGettable() { + return this; + } - @Override - public Date getPersistenceTime() { - return this.dataTime.getRefTime(); - } + @Override + public void setDataURI(String dataURI) { + identifier = dataURI; + } - @Override - public void setPersistenceTime(Date persistTime) { - // TODO Auto-generated method stub + @Override + public String[] getStrings(String paramName) { + return null; + } - } + @Override + public Date getPersistenceTime() { + return this.dataTime.getRefTime(); + } - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } + @Override + public void setPersistenceTime(Date persistTime) { + // TODO Auto-generated method stub - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } + } + + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } + + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } @Override @Column @@ -544,4 +544,9 @@ public class SgwhvRecord extends PluginDataObject implements IDecoderGettable, public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "sgwhv"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.solarimage/src/gov/noaa/nws/ncep/common/dataplugin/solarimage/SolarImageRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.solarimage/src/gov/noaa/nws/ncep/common/dataplugin/solarimage/SolarImageRecord.java index 4f118d329d..95fe8e1e43 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.solarimage/src/gov/noaa/nws/ncep/common/dataplugin/solarimage/SolarImageRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.solarimage/src/gov/noaa/nws/ncep/common/dataplugin/solarimage/SolarImageRecord.java @@ -32,13 +32,17 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ---------------- -------------------------- - * 12/05/2012 865 sgurung, qzhou Initial creation. - * 01/07/2013 865 qzhou Added "Site" for Halpha. - * 01/28/2013 865 qzhou Changed float to double for intTime. - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * Dec 05, 2012 865 sgurung, qzhou Initial creation. + * Jan 07, 2013 865 qzhou Added "Site" for Halpha. + * Jan 28, 2013 865 qzhou Changed float to double for + * intTime. + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator + * annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -53,12 +57,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "solarimage", - indexes = { - @Index(name = "solarimage_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "solarimage", indexes = { @Index(name = "solarimage_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -103,7 +103,7 @@ public class SolarImageRecord extends PersistablePluginDataObject { @DynamicSerializeElement @XmlAttribute private Double intTime; - + /** * Site */ @@ -112,7 +112,7 @@ public class SolarImageRecord extends PersistablePluginDataObject { @DynamicSerializeElement @XmlAttribute private String site; - + /** * hdu containing image data */ @@ -120,16 +120,16 @@ public class SolarImageRecord extends PersistablePluginDataObject { @DynamicSerializeElement @XmlAttribute private int imageHDUNum; - + /** * report type */ @DataURI(position = 6) - @Column + @Column @DynamicSerializeElement @XmlAttribute private String reportType; - + /** * raw data */ @@ -167,7 +167,6 @@ public class SolarImageRecord extends PersistablePluginDataObject { public void setInstrument(String instrument) { this.instrument = instrument; } - /** * @return the satellite @@ -198,7 +197,7 @@ public class SolarImageRecord extends PersistablePluginDataObject { public void setWavelength(String wavelength) { this.wavelength = wavelength; } - + /** * @return the intTime */ @@ -213,7 +212,7 @@ public class SolarImageRecord extends PersistablePluginDataObject { public void setIntTime(Double intTime) { this.intTime = intTime; } - + /** * @return the site */ @@ -228,7 +227,7 @@ public class SolarImageRecord extends PersistablePluginDataObject { public void setSite(String site) { this.site = site; } - + /** * @return the reportType */ @@ -250,20 +249,20 @@ public class SolarImageRecord extends PersistablePluginDataObject { public int getImageHDUNum() { return imageHDUNum; } - + /** * @param imageHDUNum * the hdu containing image data */ public void setImageHDUNum(int hduId) { this.imageHDUNum = hduId; - } - + } + @Override public IDecoderGettable getDecoderGettable() { return null; } - + /** * @return the raw_data */ @@ -280,24 +279,29 @@ public class SolarImageRecord extends PersistablePluginDataObject { } public void retrieveFromDataStore(IDataStore dataStore) { - + try { IDataRecord[] dataRec = dataStore.retrieve(getDataURI()); - for (int i = 0; i < dataRec.length; i++) { - if (dataRec[i].getName().equals(SolarImageRecord.RAW_DATA)) { - raw_data = (((ByteDataRecord) dataRec[i]).getByteData()); - } + for (IDataRecord element : dataRec) { + if (element.getName().equals(SolarImageRecord.RAW_DATA)) { + raw_data = (((ByteDataRecord) element).getByteData()); + } } } catch (Exception se) { se.printStackTrace(); } } - + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "solarimage"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.ssha/src/gov/noaa/nws/ncep/common/dataplugin/ssha/SshaRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.ssha/src/gov/noaa/nws/ncep/common/dataplugin/ssha/SshaRecord.java index 5ca4bcd6ae..c659918d9a 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.ssha/src/gov/noaa/nws/ncep/common/dataplugin/ssha/SshaRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.ssha/src/gov/noaa/nws/ncep/common/dataplugin/ssha/SshaRecord.java @@ -1,26 +1,3 @@ -/** - * - * SshaRecord - * - * This java class performs the mapping to the database for Ssha. - * - *
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    	Engineer    Description
- * ------- 		------- 	--------	-----------
- * Sep 2011	   		        Chin Chen	Initial Coding (Following BufrsshaRecord to refactor for 
- * 										saving data to HDF5)
- * Apr 4, 2013        1846 bkowal      Added an index on refTime and forecastTime
- * Apr 12, 2013    1857     bgonzale    Added SequenceGenerator annotation.
- * May 07, 2013 1869        bsteffen	Remove dataURI column from PluginDataObject.
- *
- * 
- * - * @author Chin Chen - * @version 1.0 - * - */ package gov.noaa.nws.ncep.common.dataplugin.ssha; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; @@ -51,6 +28,30 @@ import com.raytheon.uf.common.pointdata.PointDataView; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +/** + * SshaRecord + * + * This java class performs the mapping to the database for Ssha. + * + *
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ --------    --------    ----------------------------------------------
+ * Sep 2011                 Chin Chen   Initial Coding (Following BufrsshaRecord
+ *                                      to refactor for  saving data to HDF5)
+ * Apr 04, 2013 1846        bkowal      Added an index on refTime and
+ *                                      forecastTime
+ * Apr 12, 2013 1857        bgonzale    Added SequenceGenerator annotation.
+ * May 07, 2013 1869        bsteffen    Remove dataURI column from
+ *                                      PluginDataObject.
+ * Aug 30, 2013 2298        rjpeter     Make getPluginName abstract
+ * 
+ * + * @author Chin Chen + * @version 1.0 + * + */ @Entity @SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "sshaseq") @Table(name = "ssha", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) @@ -58,2511 +59,2509 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "ssha", - indexes = { - @Index(name = "ssha_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "ssha", indexes = { @Index(name = "ssha_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize public class SshaRecord extends PersistablePluginDataObject implements - IDecoderGettable, IPointData, IPersistable { - private static final long serialVersionUID = 1L; - private static final float RMISSD = IDecoderConstantsN.FLOAT_MISSING; - private static final Integer IMISSD = IDecoderConstantsN.INTEGER_MISSING; - - /** Satellite Identification */ - @Column - /* - * Sea surface height anomalies are from blended TOPEX/Poseidon, Jason-1, - * ERS 1, ERS 2m GPO and Envisat ocean altimetry satellites, therefore said - * should be a primary key. - */ - @DataURI(position = 4) - @DynamicSerializeElement - private Long said; - - /** Satellite Instruments */ - @Column - @DynamicSerializeElement - private Long siid; - - /** Station Acquisition */ - @Column(length = 20) - @DynamicSerializeElement - private String staq; - - /** Software Identification and Version Number */ - @Column(length = 12) - @DynamicSerializeElement - private String softv; - - /** Satellite Cycle Number */ - @Column - @DynamicSerializeElement - private Long sacyln; - - /** Orbit Number */ - @Column - @DataURI(position = 5) - @DynamicSerializeElement - private Long orbn; - - /** Numerical Model Identifier */ - @Column(length = 16) - @DynamicSerializeElement - private String numid; - - /** Observation time */ - @Column - @DataURI(position = 1) - @DynamicSerializeElement - private Calendar obsTime; - - /** Latitude */ - @Column - @DataURI(position = 2) - @DynamicSerializeElement - private Double clath; - - /** Longitude */ - @Column - @DataURI(position = 3) - @DynamicSerializeElement - private Double clonh; - - /** Remotely Sensed Surface Type */ - @Transient - @DynamicSerializeElement - private Long rsst; - - /** Altimeter Echo Type */ - @Transient - @DynamicSerializeElement - private Long aetp; - - /** Radiometer Sensed Surface Type */ - @Transient - @DynamicSerializeElement - private Long dsst; - - /** Interpolation Flag */ - @Transient - @DynamicSerializeElement - private Long intf; - - /** Three-dimensional Error Estimate of the Navigator Orbit */ - @Transient - @DynamicSerializeElement - private Long eeno; - - /** Altimeter State Flag */ - @Transient - @DynamicSerializeElement - private Long asfl; - - /** Altimeter Data Quality Flag */ - @Transient - @DynamicSerializeElement - private Long adqf; - - /** Altimeter Correction Quality Flag */ - @Transient - @DynamicSerializeElement - private Long arqf; - - /** Altimeter Rain Flag */ - @Transient - @DynamicSerializeElement - private Long alrf; - - /** Radioimeter State Flag */ - @Transient - @DynamicSerializeElement - private Long rsfl; - - /** Radioimeter Data Quality Flag */ - @Transient - @DynamicSerializeElement - private Long rdqf; - - /** Radioimeter Brightness Temperature Interpretation */ - @Transient - @DynamicSerializeElement - private Long rbif; - - /** Ice Presence Indicator */ - @Transient - @DynamicSerializeElement - private Long ipin; - - /** Auxilliary Altimeter State Flags */ - @Transient - @DynamicSerializeElement - private Long aasf; - - /** Meteorological Map Availability */ - @Transient - @DynamicSerializeElement - private Long mmap; - - /** Interpolation Flag For Mean Diurnal Tide */ - @Transient - @DynamicSerializeElement - private Long ifdt; - - /** Ku Band Ocean Range (m) */ - @Transient - @DynamicSerializeElement - private Double kbor; - - /** RMS of 20 Hz Ku Band Ocean Range (m) */ - @Transient - @DynamicSerializeElement - private Double rkbor; - - /** Number of 20 Hz valid points for Ku Band */ - @Transient - @DynamicSerializeElement - private Long nvpk2; - - /** Ku Band net instrumental Correction (m) */ - @Transient - @DynamicSerializeElement - private Double kbic; - - /** Sea State Bias Correction On Ku Band (m) */ - @Transient - @DynamicSerializeElement - private Double sbck; - - /** Ku Band Significant Wave Height (m) */ - @Transient - @DynamicSerializeElement - private Double kbsw; - - /** RMS 20 Hz Ku Band Significant Wave Height (m) */ - @Transient - @DynamicSerializeElement - private Double rksw; - - /** Number of 20 Hz valid points for Ku Band Significant Wave Height */ - @Transient - @DynamicSerializeElement - private Long nvksw; - - /** - * 20 Hz RMS Ku Band Net Instrumental Correction For Significant Wave Height - * (m) - */ - @Transient - @DynamicSerializeElement - private Double kncs; - - /** Ku Band Corrected Ocean Backscatter coefficient (kb) */ - @Transient - @DynamicSerializeElement - private Double kobc; - - /** STD Ku Band Corrected Ocean Backscatter coefficient (kb) */ - @Transient - @DynamicSerializeElement - private Double skobc; - - /** Number of valid points for Ku Band Backscatter */ - @Transient - @DynamicSerializeElement - private Long nvpkb; - - /** Ku band net instrumental correction for AGC (db) */ - @Transient - @DynamicSerializeElement - private Double knic; - - /** Attenuation Correction 1 On Sigma-0 (db) */ - @Transient - @DynamicSerializeElement - private Double acrs1; - - /** Attenuation Correction 2 On Sigma-0 (db) */ - @Transient - @DynamicSerializeElement - private Double acrs2; - - /** Ku Band Automatic Gain Control (db) */ - @Transient - @DynamicSerializeElement - private Double kagc; - - /** RMS Ku Band Automatic Gain Control (db) */ - @Transient - @DynamicSerializeElement - private Double rkagc; - - /** Number of valid points for Ku Band Automatic Gain Control */ - @Transient - @DynamicSerializeElement - private Long nvkg; - - /** C Band Ocean Range (m) */ - @Transient - @DynamicSerializeElement - private Double cbor; - - /** RMS of C Band Ocean Range (m) */ - @Transient - @DynamicSerializeElement - private Double rcbor; - - /** Number of 20 Hz valid points for C band */ - @Transient - @DynamicSerializeElement - private Long nvpc; - - /** C band net instrumental correction (m) */ - @Transient - @DynamicSerializeElement - private Double cbic; - - /** Sea state bias correction on C band (m) */ - @Transient - @DynamicSerializeElement - private Double sbcc; - - /** C band significant wave height (m) */ - @Transient - @DynamicSerializeElement - private Double cbsw; - - /** RMS 20 Hz C band significant wave height (m) */ - @Transient - @DynamicSerializeElement - private Double rcsw; - - /** Number of 20 Hz valid points for C band significance */ - @Transient - @DynamicSerializeElement - private Long nvcsw; - - /** C band net instrumental correction for significance (m) */ - @Transient - @DynamicSerializeElement - private Double cncs; - - /** C band corrected ocean backscatter coefficient (db) */ - @Transient - @DynamicSerializeElement - private Double ccob; - - /** RMS C band corrected ocean backscatter coefficient (db) */ - @Transient - @DynamicSerializeElement - private Double rccob; - - /** Number of valid points for C band backscatter */ - @Transient - @DynamicSerializeElement - private Long nvpcb; - - /** C band net instrumental correction for AGC (db) */ - @Transient - @DynamicSerializeElement - private Double cnia; - - /** C band automatic gain control (db) */ - @Transient - @DynamicSerializeElement - private Double cagc; - - /** RMS C band automatic gain control (db) */ - @Transient - @DynamicSerializeElement - private Double rcagc; - - /** Number of valid points for C band automatic gain */ - @Transient - @DynamicSerializeElement - private Long nvpca; - - /** Satellite channel center frequency 1 (hz) */ - @Transient - @DynamicSerializeElement - private Double sccf1; - - /** Satellite channel center frequency 2 (hz) */ - @Transient - @DynamicSerializeElement - private Double sccf2; - - /** Satellite channel center frequency 3 (hz) */ - @Transient - @DynamicSerializeElement - private Double sccf3; - - /** Brightness temperature 1 (k) */ - @Transient - @DynamicSerializeElement - private Double tmbrst1; - - /** Brightness temperature 2 (k) */ - @Transient - @DynamicSerializeElement - private Double tmbrst2; - - /** Brightness temperature 3 (k) */ - @Transient - @DynamicSerializeElement - private Double tmbrst3; - - /** Radiometer water vapor content (kg/m**2) */ - @Transient - @DynamicSerializeElement - private Double rwvc; - - /** Radiometer liquid content (kg/m**) */ - @Transient - @DynamicSerializeElement - private Double rlqc; - - /** Height or altitude 1 (m) */ - @Transient - @DynamicSerializeElement - private Double hmsl1; - - /** Height or altitude 2 (m) */ - @Transient - @DynamicSerializeElement - private Double hmsl2; - - /** Wind speed from altimeter (m/s) */ - @Transient - @DynamicSerializeElement - private Double wspa; - - /** Wind speed from radiometer (m/s) */ - @Transient - @DynamicSerializeElement - private Double wspr; - - /** u-component of the model wind vector (m/s) */ - @Transient - @DynamicSerializeElement - private Double umwv; - - /** v-component of the model wind vector (m/s) */ - @Transient - @DynamicSerializeElement - private Double vwmv; - - /** Mean dynamic topography (m) */ - @Transient - @DynamicSerializeElement - private Double mdyt; - - /** Altitude of COG above reference ellipsoid (m) */ - @Transient - @DynamicSerializeElement - private Double alre; - - /** Instantaneous altitude rate (m/s) */ - @Transient - @DynamicSerializeElement - private Double ialr; - - /** Squared off nadir angle of the satellite from platform data (degree**2) */ - @Transient - @DynamicSerializeElement - private Double onap; - - /** Squared off nadir angle of the satellite from waveform data (degree**2) */ - @Transient - @DynamicSerializeElement - private Double sonaw; - - /** Ionospheric correction from model on Ku band (m) */ - @Transient - @DynamicSerializeElement - private Double icmk; - - /** Altimeter ionospheric correction on Ku band (m) */ - @Transient - @DynamicSerializeElement - private Double aick; - - /** Model dry tropospheric correction (m) */ - @Transient - @DynamicSerializeElement - private Double mdtc; - - /** Model wet tropospheric correction (m) */ - @Transient - @DynamicSerializeElement - private Double mwtc; - - /** Radiometer wet tropospheric correction (m) */ - @Transient - @DynamicSerializeElement - private Double rwtc; - - /** Mean sea-surface height (m) */ - @Transient - @DynamicSerializeElement - private Double mssh; - - /** Mean sea surface height from altimeter only (m) */ - @Transient - @DynamicSerializeElement - private Double msha; - - /** Geoid's height (m) */ - @Transient - @DynamicSerializeElement - private Double geodh; - - /** Ocean depth/land elevation (m) */ - @Transient - @DynamicSerializeElement - private Double odle; - - /** Solid earth tide height (m) */ - @Transient - @DynamicSerializeElement - private Double seth; - - /** Total geocentric ocean tide height solution 1 (m) */ - @Transient - @DynamicSerializeElement - private Double tgoth1; - - /** Total geocentric ocean tide height solution 2 (m) */ - @Transient - @DynamicSerializeElement - private Double tgoth2; - - /** Loading tide height geocentric ocean tide solution 1 (m) */ - @Transient - @DynamicSerializeElement - private Double lths1; - - /** Loading tide height geocentric ocean tide solution 2 (m) */ - @Transient - @DynamicSerializeElement - private Double lths2; - - /** Long period tide height (m) */ - @Transient - @DynamicSerializeElement - private Double lpth; - - /** Non-equilibrium long period tide height (m) */ - @Transient - @DynamicSerializeElement - private Double nlth; - - /** Geocentric pole tide height (m) */ - @Transient - @DynamicSerializeElement - private Double gpth; - - /* Inverted barometer correction (m) */ - @Transient - @DynamicSerializeElement - private Double ibco; - - /* High frequency fluctuations of the sea surface topography correction (m) */ - @Transient - @DynamicSerializeElement - private Double hfstc; - - /** Sea Surface Height Anomoly (m) */ - @Transient - @DynamicSerializeElement - private Double ssha; - - /** Report type */ - @Transient - @DynamicSerializeElement - @DataURI(position=6) - private String reportType; - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - /** - * Default constructor. - */ - public SshaRecord() { - Double doubleRmissd = Double.parseDouble(String.valueOf(RMISSD)); - Long longImissd = Long.parseLong(String.valueOf(IMISSD)); - this.reportType = "BUFRSSHA"; - this.said = longImissd; - this.siid = longImissd; - this.staq = " "; - this.softv = " "; - this.sacyln = longImissd; - this.orbn = longImissd; - this.numid = " "; - this.clath = doubleRmissd; - this.clonh = doubleRmissd; - this.rsst = longImissd; - this.aetp = longImissd; - this.dsst = longImissd; - this.intf = longImissd; - this.eeno = longImissd; - this.asfl = longImissd; - this.adqf = longImissd; - this.arqf = longImissd; - this.alrf = longImissd; - this.rsfl = longImissd; - this.rdqf = longImissd; - this.rbif = longImissd; - this.ipin = longImissd; - this.aasf = longImissd; - this.mmap = longImissd; - this.ifdt = longImissd; - this.kbor = doubleRmissd; - this.rkbor = doubleRmissd; - this.nvpk2 = longImissd; - this.kbic = doubleRmissd; - this.sbck = doubleRmissd; - this.kbsw = doubleRmissd; - this.rksw = doubleRmissd; - this.nvksw = longImissd; - this.kncs = doubleRmissd; - this.kobc = doubleRmissd; - this.skobc = doubleRmissd; - this.nvpkb = longImissd; - this.knic = doubleRmissd; - this.acrs1 = doubleRmissd; - this.acrs2 = doubleRmissd; - this.kagc = doubleRmissd; - this.rkagc = doubleRmissd; - this.nvkg = longImissd; - this.cbor = doubleRmissd; - this.rcbor = doubleRmissd; - this.nvpc = longImissd; - this.cbic = doubleRmissd; - this.sbcc = doubleRmissd; - this.cbsw = doubleRmissd; - this.rcsw = doubleRmissd; - this.nvcsw = longImissd; - this.cncs = doubleRmissd; - this.ccob = doubleRmissd; - this.rccob = doubleRmissd; - this.nvpcb = longImissd; - this.cnia = doubleRmissd; - this.cagc = doubleRmissd; - this.rcagc = doubleRmissd; - this.nvpca = longImissd; - this.sccf1 = doubleRmissd; - this.sccf2 = doubleRmissd; - this.sccf3 = doubleRmissd; - this.tmbrst1 = doubleRmissd; - this.tmbrst2 = doubleRmissd; - this.tmbrst3 = doubleRmissd; - this.rwvc = doubleRmissd; - this.rlqc = doubleRmissd; - this.hmsl1 = doubleRmissd; - this.hmsl2 = doubleRmissd; - this.wspa = doubleRmissd; - this.wspr = doubleRmissd; - this.umwv = doubleRmissd; - this.vwmv = doubleRmissd; - this.mdyt = doubleRmissd; - this.alre = doubleRmissd; - this.ialr = doubleRmissd; - this.onap = doubleRmissd; - this.sonaw = doubleRmissd; - this.icmk = doubleRmissd; - this.aick = doubleRmissd; - this.mdtc = doubleRmissd; - this.mwtc = doubleRmissd; - this.rwtc = doubleRmissd; - this.mssh = doubleRmissd; - this.msha = doubleRmissd; - this.geodh = doubleRmissd; - this.odle = doubleRmissd; - this.seth = doubleRmissd; - this.tgoth1 = doubleRmissd; - this.tgoth2 = doubleRmissd; - this.lths1 = doubleRmissd; - this.lths2 = doubleRmissd; - this.lpth = doubleRmissd; - this.nlth = doubleRmissd; - this.gpth = doubleRmissd; - this.ibco = doubleRmissd; - this.hfstc = doubleRmissd; - this.ssha = doubleRmissd; - } - - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - */ - public SshaRecord(String uri) { - super(uri); - } - - /** - * Get the observation report type. - * - * @return the reportType - */ - public String getReportType() { - return reportType; - } - - /** - * Set the observation report type. - * - * @param reportType - * the reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } - - /** - * Get the Satellite Identifier. - * - * @return the Satellite ID - */ - public Long getSaid() { - return said; - } - - /** - * @param said - * the Satellite Identifier to set - */ - public void setSaid(Long said) { - this.said = said; - } - - /** - * Get the Satellite Instruments. - * - * @return the Satellite Instruments - */ - public Long getSiid() { - return siid; - } - - /** - * @param siid - * the Satellite Instruments to set - */ - public void setSiid(Long siid) { - this.siid = siid; - } - - /** - * Get the Station Acquisition. - * - * @return the Station Acquisition - */ - public String getStaq() { - return staq; - } - - /** - * @param staq - * the Station Acquisition to set - */ - public void setStaq(String staq) { - this.staq = staq; - } - - /** - * Get the Software Identification and Version. - * - * @return the Software Id and Version - */ - public String getSoftv() { - return softv; - } - - /** - * @param softv - * the Software Id and Version to set - */ - public void setSoftv(String softv) { - this.softv = softv; - } - - /** - * Get the Satellite Cycle Number. - * - * @return the Satellite Cycle Number - */ - public Long getSacyln() { - return sacyln; - } - - /** - * @param sacyln - * the Satellite Cycle Number to set - */ - public void setSacyln(Long sacyln) { - this.sacyln = sacyln; - } - - /** - * Get the Orbit Number. - * - * @return the Orbit Number - */ - public Long getOrbn() { - return orbn; - } - - /** - * @param orbn - * the Orbit Number to set - */ - public void setOrbn(Long orbn) { - this.orbn = orbn; - } - - /** - * Get the Numerical Model Identifier. - * - * @return the Numerical Model Identifier - */ - public String getNumid() { - return numid; - } - - /** - * @param numid - * the Numerical Model Identifier to set - */ - public void setNumid(String numid) { - this.numid = numid; - } - - /** - * @return the clath - */ - public Double getClath() { - return clath; - } - - /** - * @param clath - * the latitude to set - */ - public void setClath(Double clath) { - this.clath = clath; - } - - /** - * @return the clonh - */ - public Double getClonh() { - return clonh; - } - - /** - * @param clonh - * the longitude to set - */ - public void setClonh(Double clonh) { - this.clonh = clonh; - } - - /** - * Get the Remote Sensed Surface Type. - * - * @return the Remote Sensed Surface Type - */ - public Long getRsst() { - return rsst; - } - - /** - * @param rsst - * the Remote Sensed Surface Type to set - */ - public void setRsst(Long rsst) { - this.rsst = rsst; - } - - /** - * Get the Altimeter Echo Type. - * - * @return the Altimeter Echo Type - */ - public Long getAetp() { - return aetp; - } - - /** - * @param aetp - * the Altimeter Echo Type to set - */ - public void setAetp(Long aetp) { - this.aetp = aetp; - } - - /** - * Get the Radiometer Sensed Surface Type. - * - * @return the Remote Sensed Surface Type - */ - public Long getDsst() { - return dsst; - } - - /** - * @param dsst - * the Radiometer Sensed Surface Type to set - */ - public void setDsst(Long dsst) { - this.dsst = dsst; - } - - /** - * Get the Interpolation Flag. - * - * @return the Interpolation Flag - */ - public Long getIntf() { - return intf; - } - - /** - * @param intf - * the Interpolation Flag to set - */ - public void setIntf(Long intf) { - this.intf = intf; - } - - /** - * Get the Three-dimensional Error Estimate of the Navigator Orbit. - * - * @return the Three-dimensional Error Estimate of the Navigator Orbit - */ - public Long getEeno() { - return eeno; - } - - /** - * @param eeno - * the Three-dimensional Error Estimate of the Navigator Orbit to - * set - */ - public void setEeno(Long eeno) { - this.eeno = eeno; - } - - /** - * Get the Altimeter State Flag. - * - * @return the Altimeter State Flag - */ - public Long getAsfl() { - return asfl; - } - - /** - * @param asfl - * the Altimeter State Flag to set - */ - public void setAsfl(Long asfl) { - this.asfl = asfl; - } - - /** - * Get the Altimeter Data Quality Flag. - * - * @return the Altimeter Data Quality Flag - */ - public Long getAdqf() { - return adqf; - } - - /** - * @param adqf - * the Altimeter Data Quality Flag to set - */ - public void setAdqf(Long adqf) { - this.adqf = adqf; - } - - /** - * Get the Altimeter Correction Quality Flag. - * - * @return the Altimeter Correction Quality Flag - */ - public Long getArqf() { - return arqf; - } - - /** - * @param arqf - * the Altimeter Correction Quality Flag to set - */ - public void setArqf(Long arqf) { - this.arqf = arqf; - } - - /** - * Get the Altimeter Rain Flag. - * - * @return the Altimeter Rain Flag - */ - public Long getAlrf() { - return alrf; - } - - /** - * @param alrf - * the Altimeter Rain Flag to set - */ - public void setAlrf(Long alrf) { - this.alrf = alrf; - } - - /** - * Get the Radiometer State Flag. - * - * @return the Radiometer State Flag - */ - public Long getRsfl() { - return rsfl; - } - - /** - * @param rsfl - * the Radiometer State Flag to set - */ - public void setRsfl(Long rsfl) { - this.rsfl = rsfl; - } - - /** - * Get the Radiometer Data Quality Flag. - * - * @return the Radiometer Data Quality Flag - */ - public Long getRdqf() { - return rdqf; - } - - /** - * @param rdqf - * the Radiometer Data Quality Flag to set - */ - public void setRdqf(Long rdqf) { - this.rdqf = rdqf; - } - - /** - * Get the Radiometer Brightness Temperature Interpretation. - * - * @return the Radiometer Brightness Temperature Interpretation - */ - public Long getRbif() { - return rbif; - } - - /** - * @param rbif - * the Radiometer Brightness Temperature Interpretation to set - */ - public void setRbif(Long rbif) { - this.rbif = rbif; - } - - /** - * Get the Ice Presence Indicator. - * - * @return the Ice Presence Indicator - */ - public Long getIpin() { - return ipin; - } - - /** - * @param ipin - * the Ice Presence Indicator to set - */ - public void setIpin(Long ipin) { - this.ipin = ipin; - } - - /** - * Get the Auxillliary Altimeter State Flags. - * - * @return the Auxillliary Altimeter State Flags - */ - public Long getAasf() { - return aasf; - } - - /** - * @param aasf - * the Auxillliary Altimeter State Flags to set - */ - public void setAasf(Long aasf) { - this.aasf = aasf; - } - - /** - * Get the Meteorological Map Availablity. - * - * @return the Meteorological Map Availablity - */ - public Long getMmap() { - return mmap; - } - - /** - * @param mmap - * the Meteorological Map Availablity to set - */ - public void setMmap(Long mmap) { - this.mmap = mmap; - } - - /** - * Get the Interpolation Flag For Mean Diurnal Tide. - * - * @return the Interpolation Flag For Mean Diurnal Tide - */ - public Long getIfdt() { - return ifdt; - } - - /** - * @param ifdt - * the Interpolation Flag For Mean Diurnal Tide to set - */ - public void setIfdt(Long ifdt) { - this.ifdt = ifdt; - } - - /** - * Get the Ku Band Ocean Range - * - * @param kbor - * Ku Band Ocean Range to return - */ - public Double getKbor() { - return kbor; - } - - /** - * @param kbor - * Ku Band Ocean Range to set - */ - public void setKbor(Double kbor) { - this.kbor = kbor; - } - - /** - * Get the RMS of 20 Hz Ku Band Ocean Range - * - * @param rkbor - * RMS of 20 Hz Ku Band Ocean Range to return - */ - public Double getRkbor() { - return rkbor; - } - - /** - * @param rkbor - * RMS of 20 Hz Ku Band Ocean Range to set - */ - public void setRkbor(Double rkbor) { - this.rkbor = rkbor; - } - - /** - * Get the Number of 20 Hz valid points for Ku Band. - * - * @return the Number of 20 Hz valid points for Ku Band - */ - public Long getNvpk2() { - return nvpk2; - } - - /** - * @param nvpk2 - * the Number of 20 Hz valid points for Ku Band to set - */ - public void setNvpk2(Long nvpk2) { - this.nvpk2 = nvpk2; - } - - /** - * Get the Ku Band Net Instrumental Correction - * - * @param kbic - * Ku Band Net Instrumental Correction to return - */ - public Double getKbic() { - return kbic; - } - - /** - * @param kbic - * Ku Band Net Instrumental Correction to set - */ - public void setKbic(Double kbic) { - this.kbic = kbic; - } - - /** - * Get the Sea State Bias Correction On Ku Band - * - * @param sbck - * Sea State Bias Correction On Ku Band to return - */ - public Double getSbck() { - return sbck; - } - - /** - * @param sbck - * Sea State Bias Correction On Ku Band to set - */ - public void setSbck(Double sbck) { - this.sbck = sbck; - } - - /** - * Get Ku Band Significant Wave Height - * - * @param kbsw - * Ku Band Significant Wave Height to return - */ - public Double getKbsw() { - return kbsw; - } - - /** - * @param kbsw - * Ku Band Significant Wave Height to set - */ - public void setKbsw(Double kbsw) { - this.kbsw = kbsw; - } - - /** - * RMS 20 Hz Ku Band Significant Wave Height - * - * @param rksw - * RMS 20 Hz Ku Band Significant Wave Height - */ - public Double getRksw() { - return rksw; - } - - /** - * @param rksw - * 20 Hz RMS Ku Band Significant Wave Height to set - */ - public void setRksw(Double rksw) { - this.rksw = rksw; - } - - /** - * Get the Number of 20 Hz valid points for Ku Band Significant Wave Height. - * - * @return the Number of 20 Hz valid points for Ku Band Significant Wave - * Height - */ - public Long getNvksw() { - return nvksw; - } - - /** - * @param nvksw - * the Number of 20 Hz valid points for Ku Band Significant Wave - * Height to set - */ - public void setNvksw(Long nvksw) { - this.nvksw = nvksw; - } - - /** - * RMS 20 Hz Ku Band Net Instrumental Correction For Significant Wave Height - * - * @param kncs - * RMS 20 Hz Ku Band Net Instrumental Correction For Significant - * Wave Height - */ - public Double getKncs() { - return kncs; - } - - /** - * @param kncs - * 20 Hz RMS Ku Band Net Instrumental Correction For Significant - * Wave Height to set - */ - public void setKncs(Double kncs) { - this.kncs = kncs; - } - - /** - * Ku Band Corrected Ocean Backscatter coefficient - * - * @param kobc - * Ku Band Corrected Ocean Backscatter coefficient - */ - public Double getKobc() { - return kobc; - } - - /** - * @param kobc - * Ku Band Corrected Ocean Backscatter coefficient to set - */ - public void setKobc(Double kobc) { - this.kobc = kobc; - } - - /** - * STD Ku Band Corrected Ocean Backscatter coefficient - * - * @param kobc - * STD Ku Band Corrected Ocean Backscatter coefficient - */ - public Double getSkobc() { - return skobc; - } - - /** - * @param skobc - * STD Ku Band Corrected Ocean Backscatter coefficient to set - */ - public void setSkobc(Double skobc) { - this.skobc = skobc; - } - - /** - * Get the Number of valid points for Ku Band Backscatter. - * - * @return the Number of valid points for Ku Band Backscatter - */ - public Long getNvpkb() { - return nvpkb; - } - - /** - * @param nvpkb - * the Number of valid points for Ku Band Backscatter to set - */ - public void setNvpkb(Long nvpkb) { - this.nvpkb = nvpkb; - } - - /** - * Ku band net instrumental correction for AGC - * - * @param knic - * Ku band net instrumental correction for AGC - */ - public Double getKnic() { - return knic; - } - - /** - * @param knic - * Ku band net instrumental correction for AGC to set - */ - public void setKnic(Double knic) { - this.knic = knic; - } - - /** - * Attenuation Correction 1 On Sigma-0 - * - * @param acrs1 - * Attenuation 1 Correction On Sigma-0 - */ - public Double getAcrs1() { - return acrs1; - } - - /** - * @param acrs1 - * Attenuation Correction 1 On Sigma-0 - */ - public void setAcrs1(Double acrs1) { - this.acrs1 = acrs1; - } - - /** - * Attenuation Correction 2 On Sigma-0 - * - * @param acrs2 - * Attenuation Correction 2 On Sigma-0 - */ - public Double getAcrs2() { - return acrs2; - } - - /** - * @param acrs2 - * Attenuation Correction 2 On Sigma-0 - */ - public void setAcrs2(Double acrs2) { - this.acrs2 = acrs2; - } - - /** - * Ku Band Automatic Gain Control - * - * @param kagc - * Ku Band Automatic Gain Control - */ - public Double getKagc() { - return kagc; - } - - /** - * @param kagc - * Ku Band Automatic Gain Control - */ - public void setKagc(Double kagc) { - this.kagc = kagc; - } - - /** - * RMS Ku Band Automatic Gain Control - * - * @param rkagc - * RMS Ku Band Automatic Gain Control - */ - public Double getRkagc() { - return rkagc; - } - - /** - * @param rkagc - * RMS Ku Band Automatic Gain Control - */ - public void setRkagc(Double rkagc) { - this.rkagc = rkagc; - } - - /** - * Get the Number of valid points for Ku Band Automatic Gain Control. - * - * @return nvkg the Number of valid points for Ku Band Automatic Gain - * Control - */ - public Long getNvkg() { - return nvkg; - } - - /** - * @param nvkg - * the Number of valid points for Ku Band Automatic Gain Control - * to set - */ - public void setNvkg(Long nvkg) { - this.nvkg = nvkg; - } - - /** - * C Band Ocean Range - * - * @param cbor - * C Band Ocean Range to return - */ - public Double getCbor() { - return cbor; - } - - /** - * @param cbor - * C Band Ocean Range to set - */ - public void setCbor(Double cbor) { - this.cbor = cbor; - } - - /** - * RMS of C Band Ocean Range - * - * @param rcbor - * RMS of C Band Ocean Range to return - */ - public Double getRcbor() { - return rcbor; - } - - /** - * @param rcbor - * RMS of C Band Ocean Range to set - */ - public void setRcbor(Double rcbor) { - this.rcbor = rcbor; - } - - /** - * Get the Number of Number of 20 Hz valid points for C band - * - * @return nvpc the Number of 20 Hz valid points for C band - */ - public Long getNvpc() { - return nvpc; - } - - /** - * @param nvpc - * the Number of 20 Hz valid points for C band to set - */ - public void setNvpc(Long nvpc) { - this.nvpc = nvpc; - } - - /** - * C Band net instrumental correction - * - * @param cbic - * C band net instrumental correction to return - */ - public Double getCbic() { - return cbic; - } - - /** - * @param cbic - * C band net instrumental correction to set - */ - public void setCbic(Double cbic) { - this.cbic = cbic; - } - - /** - * Sea state bias correction on C band - * - * @param sbcc - * Sea state bias correction on C band to return - */ - public Double getSbcc() { - return sbcc; - } - - /** - * @param sbcc - * Sea state bias correction on C band to set - */ - public void setSbcc(Double sbcc) { - this.sbcc = sbcc; - } - - /** - * C band significant wave height - * - * @param cbsw - * C band significant wave height to return - */ - public Double getCbsw() { - return cbsw; - } - - /** - * @param cbsw - * C band significant wave height to set - */ - public void setCbsw(Double cbsw) { - this.cbsw = cbsw; - } - - /** - * RMS 20 Hz C band significant wave height - * - * @param rcsw - * RMS 20 Hz C band significant wave height to return - */ - public Double getRcsw() { - return rcsw; - } - - /** - * @param rcsw - * RMS 20 Hz C band significant wave height to set - */ - public void setRcsw(Double rcsw) { - this.rcsw = rcsw; - } - - /** - * Get the Number of 20 Hz valid points for C band significance - * - * @return nvcsw the Number of 20 Hz valid points for C band significance - */ - public Long getNvcsw() { - return nvcsw; - } - - /** - * @param nvcsw - * the Number of 20 Hz valid points for C band significance to - * set - */ - public void setNvcsw(Long nvcsw) { - this.nvcsw = nvcsw; - } - - /** - * C band net instrumental correction for significance - * - * @param cncs - * C band net instrumental correction for significance to return - */ - public Double getCncs() { - return cncs; - } - - /** - * @param cncs - * C band net instrumental correction for significance to set - */ - public void setCncs(Double cncs) { - this.cncs = cncs; - } - - /** - * C band corrected ocean backscatter coefficient - * - * @param ccob - * C band corrected ocean backscatter coefficient to return - */ - public Double getCcob() { - return ccob; - } - - /** - * @param ccob - * C band corrected ocean backscatter coefficient to set - */ - public void setCcob(Double ccob) { - this.ccob = ccob; - } - - /** - * RMS C band corrected ocean backscatter coefficient - * - * @param rccob - * RMS C band corrected ocean backscatter coefficient to return - */ - public Double getRccob() { - return rccob; - } - - /** - * @param rccob - * RMS C band corrected ocean backscatter coefficient to set - */ - public void setRccob(Double rccob) { - this.rccob = rccob; - } - - /** - * Get the Number of valid points for C band backscatter - * - * @return nvpcb the Number of valid points for C band backscatter - */ - public Long getNvpcb() { - return nvpcb; - } - - /** - * @param nvpcb - * the Number of valid points for C band backscatter to set - */ - public void setNvpcb(Long nvpcb) { - this.nvpcb = nvpcb; - } - - /** - * RMS C band net instrumental correction for AGC - * - * @param cnia - * C band net instrumental correction for AGC to return - */ - public Double getCnia() { - return cnia; - } - - /** - * @param cnia - * C band net instrumental correction for AGC to set - */ - public void setCnia(Double cnia) { - this.cnia = cnia; - } - - /** - * C band automatic gain control - * - * @param cagc - * C band automatic gain control to return - */ - public Double getCagc() { - return cagc; - } - - /** - * @param cagc - * C band automatic gain control to set - */ - public void setCagc(Double cagc) { - this.cagc = cagc; - } - - /** - * RMS C band automatic gain control - * - * @param rcagc - * RMS C band automatic gain control to return - */ - public Double getRcagc() { - return rcagc; - } - - /** - * @param rcagc - * RMS C band automatic gain control to set - */ - public void setRcagc(Double rcagc) { - this.rcagc = rcagc; - } - - /** - * Get the Number of valid points for C band automatic gain - * - * @return nvpca the Number of valid points for C band automatic gain - */ - public Long getNvpca() { - return nvpca; - } - - /** - * @param nvpca - * the Number of valid points for C band automatic gain to set - */ - public void setNvpca(Long nvpca) { - this.nvpca = nvpca; - } - - /** - * Satellite channel center frequency 1 - * - * @param sccf1 - * Satellite channel center frequency 1 - */ - public Double getSccf1() { - return sccf1; - } - - /** - * @param sccf1 - * Satellite channel center frequency 1 - */ - public void setSccf1(Double sccf1) { - this.sccf1 = sccf1; - } - - /** - * Satellite channel center frequency 1 - * - * @param sccf2 - * Satellite channel center frequency 2 - */ - public Double getSccf2() { - return sccf2; - } - - /** - * @param sccf2 - * Satellite channel center frequency 2 - */ - public void setSccf2(Double sccf2) { - this.sccf2 = sccf2; - } - - /** - * Satellite channel center frequency 3 - * - * @param sccf1 - * Satellite channel center frequency 3 - */ - public Double getSccf3() { - return sccf3; - } - - /** - * @param sccf3 - * Satellite channel center frequency 3 - */ - public void setSccf3(Double sccf3) { - this.sccf3 = sccf3; - } - - /** - * Brightness temperature 1 - * - * @param tmbrst1 - * Brightness temperature 1 - */ - public Double getTmbrst1() { - return tmbrst1; - } - - /** - * @param tmbrst1 - * Brightness temperature 1 - */ - public void setTmbrst1(Double tmbrst1) { - this.tmbrst1 = tmbrst1; - } - - /** - * Brightness temperature 2 - * - * @param tmbrst2 - * Brightness temperature 2 - */ - public Double getTmbrst2() { - return tmbrst2; - } - - /** - * @param tmbrst2 - * Brightness temperature 2 - */ - public void setTmbrst2(Double tmbrst2) { - this.tmbrst2 = tmbrst2; - } - - /** - * Brightness temperature 3 - * - * @param tmbrst3 - * Brightness temperature 3 - */ - public Double getTmbrst3() { - return tmbrst3; - } - - /** - * @param tmbrst3 - * Brightness temperature 3 - */ - public void setTmbrst3(Double tmbrst3) { - this.tmbrst3 = tmbrst3; - } - - /** - * Radiometer water vapor content - * - * @param rwvc - * Radiometer water vapor content to return - */ - public Double getRwvc() { - return rwvc; - } - - /** - * @param rwvc - * Radiometer water vapor content to set - */ - public void setRwvc(Double rwvc) { - this.rwvc = rwvc; - } - - /** - * Radiometer liquid content - * - * @param rlqc - * Radiometer liquid content to return - */ - public Double getRlqc() { - return rlqc; - } - - /** - * @param rlqc - * Radiometer liquid content to set - */ - public void setRlqc(Double rlqc) { - this.rlqc = rlqc; - } - - /** - * Height or altitude 1 - * - * @param hmsl - * Height or altitude 1 to return - */ - public Double getHmsl1() { - return hmsl1; - } - - /** - * @param hmsl - * Height or altitude 1 to set - */ - public void setHmsl1(Double hmsl1) { - this.hmsl1 = hmsl1; - } - - /** - * Height or altitude 2 - * - * @param hmsl - * Height or altitude 2 to return - */ - public Double getHmsl2() { - return hmsl2; - } - - /** - * @param hmsl - * Height or altitude 2 to set - */ - public void setHmsl2(Double hmsl2) { - this.hmsl2 = hmsl2; - } - - /** - * Wind speed from altimeter (m/s) - * - * @param wspa - * Wind speed from altimeter to return - */ - public Double getWspa() { - return wspa; - } - - /** - * @param wspa - * Wind speed from altimeter to set - */ - public void setWspa(Double wspa) { - this.wspa = wspa; - } - - /** - * Wind speed from radiometer (m/s) - * - * @param wspr - * Wind speed from radiometer to return - */ - public Double getWspr() { - return wspr; - } - - /** - * @param wspr - * Wind speed from radiometer to set - */ - public void setWspr(Double wspr) { - this.wspr = wspr; - } - - /** - * u-component of the model wind vector (m/s) - * - * @param umwv - * u-component of the model wind vector to return - */ - public Double getUmwv() { - return umwv; - } - - /** - * @param umwv - * u-component of the model wind vector to set - */ - public void setUmwv(Double umwv) { - this.umwv = umwv; - } - - /** - * u-component of the model wind vector (m/s) - * - * @param vwmv - * u-component of the model wind vector to return - */ - public Double getVwmv() { - return vwmv; - } - - /** - * @param vwmv - * u-component of the model wind vector to set - */ - public void setVwmv(Double vwmv) { - this.vwmv = vwmv; - } - - /** - * Mean dynamic topography (m) - * - * @param 1G Mean dynamic topography to return - */ - public Double getMdyt() { - return mdyt; - } - - /** - * @param mdyt - * Mean dynamic topography to set - */ - public void setMdyt(Double mdyt) { - this.mdyt = mdyt; - } - - /** - * Altitude of COG above reference ellipsoid (m) - * - * @param alre - * Altitude of COG above reference ellipsoid - */ - public Double getAlre() { - return alre; - } - - /** - * @param alre - * Altitude of COG above reference ellipsoid to set - */ - public void setAlre(Double alre) { - this.alre = alre; - } - - /** - * Instantaneous altitude rate (m/s) - * - * @param ialr - * Instantaneous altitude rate to return - */ - public Double getIalr() { - return ialr; - } - - /** - * @param ialr - * Instantaneous altitude rate to set - */ - public void setIalr(Double ialr) { - this.ialr = ialr; - } - - /** - * Squared off nadir angle of the satellite from platform data (degree**2) - * - * @param onap - * Squared off nadir angle of the satellite from platform data to - * set - */ - public Double getOnap() { - return onap; - } - - /** - * @param onap - * Squared off nadir angle of the satellite from platform data to - * set - */ - public void setOnap(Double onap) { - this.onap = onap; - } - - /** - * Squared off nadir angle of the satellite from waveform data (degree**2) - * - * @param sonaw - * Squared off nadir angle of the satellite from waveform data to - * return - */ - public Double getSonaw() { - return sonaw; - } - - /** - * @param sonaw - * Squared off nadir angle of the satellite from waveform data to - * set - */ - public void setSonaw(Double sonaw) { - this.sonaw = sonaw; - } - - /** - * Ionospheric correction from model on Ku band (m) - * - * @param icmk - * Ionospheric correction from model on Ku band to return - */ - public Double getIcmk() { - return icmk; - } - - /** - * @param icmk - * Ionospheric correction from model on Ku band to set - */ - public void setIcmk(Double icmk) { - this.icmk = icmk; - } - - /** - * Ionospheric correction from model on Ku band (m) - * - * @param aick - * Ionospheric correction from model on Ku band to return - */ - public Double getAick() { - return aick; - } - - /** - * @param aick - * Ionospheric correction from model on Ku band to set - */ - public void setAick(Double aick) { - this.aick = aick; - } - - /** - * Model dry tropospheric correction (m) - * - * @param mdtc - * Model dry tropospheric correction to return - */ - public Double getMdtc() { - return mdtc; - } - - /** - * @param mdtc - * Model dry tropospheric correction to set - */ - public void setMdtc(Double mdtc) { - this.mdtc = mdtc; - } - - /** - * Model wet tropospheric correction (m) - * - * @param mwtc - * Model wet tropospheric correction to return - */ - public Double getMwtc() { - return mwtc; - } - - /** - * @param mwtc - * Model wet tropospheric correction to set - */ - public void setMwtc(Double mwtc) { - this.mwtc = mwtc; - } - - /** - * Radiometer wet tropospheric correction (m) - * - * @param rwtc - * Radiometer wet tropospheric correction to return - */ - public Double getRwtc() { - return rwtc; - } - - /** - * @param rwtc - * Radiometer wet tropospheric correction to set - */ - public void setRwtc(Double rwtc) { - this.rwtc = rwtc; - } - - /** - * Mean sea-surface height (m) - * - * @param mssh - * Mean sea-surface height to return - */ - public Double getMssh() { - return mssh; - } - - /** - * @param mssh - * Mean sea-surface height to set - */ - public void setMssh(Double mssh) { - this.mssh = mssh; - } - - /** - * Mean sea-surface height from altimeter only (m) - * - * @param msha - * Mean sea-surface height from altimeter only to return - */ - public Double getMsha() { - return msha; - } - - /** - * @param msha - * Mean sea-surface height from altimeter only to set - */ - public void setMsha(Double msha) { - this.msha = msha; - } - - /** - * Geoid's height (m) - * - * @param geodh - * Geoid's height to return - */ - public Double getGeodh() { - return geodh; - } - - /** - * @param odle - * Ocean depth/land elevation (m) - */ - public void setGeodh(Double geodh) { - this.geodh = geodh; - } - - /** - * Ocean depth/land elevation (m) - * - * @param odle - * Ocean depth/land elevation to return - */ - public Double getOdle() { - return odle; - } - - /** - * @param odle - * Ocean depth/land elevation to set - */ - public void setOdle(Double odle) { - this.odle = odle; - } - - /** - * Solid earth tide height (m) - * - * @param seth - * Solid earth tide height to return - */ - public Double getSeth() { - return seth; - } - - /** - * @param seth - * Solid earth tide height to set - */ - public void setSeth(Double seth) { - this.seth = seth; - } - - /** - * Total geocentric ocean tide height solution 1 (m) - * - * @param tgoth1 - * Total geocentric ocean tide height solution 1 to return - */ - public Double getTgoth1() { - return tgoth1; - } - - /** - * @param tgoth1 - * Total geocentric ocean tide height solution 1 to set - */ - public void setTgoth1(Double tgoth1) { - this.tgoth1 = tgoth1; - } - - /** - * Total geocentric ocean tide height solution 2 (m) - * - * @param tgoth2 - * Total geocentric ocean tide height solution 2 to return - */ - public Double getTgoth2() { - return tgoth2; - } - - /** - * @param tgoth2 - * Total geocentric ocean tide height solution 2 to set - */ - public void setTgoth2(Double tgoth2) { - this.tgoth2 = tgoth2; - } - - /** - * Loading tide height geocentric ocean tide solution 1 (m) - * - * @param lths1 - * Loading tide height geocentric ocean tide solution 1 to return - */ - public Double getLths1() { - return lths1; - } - - /** - * @param lths1 - * Loading tide height geocentric ocean tide solution 1 to set - */ - public void setLths1(Double lths1) { - this.lths1 = lths1; - } - - /** - * Loading tide height geocentric ocean tide solution 2 (m) - * - * @param lths2 - * Loading tide height geocentric ocean tide solution 2 to return - */ - public Double getLths2() { - return lths2; - } - - /** - * @param lths2 - * Loading tide height geocentric ocean tide solution 2 to set - */ - public void setLths2(Double lths2) { - this.lths2 = lths2; - } - - /** - * Long period tide height (m) - * - * @param lpth - * Long period tide height to return - */ - public Double getLpth() { - return lpth; - } - - /** - * @param lpth - * Long period tide height to set - */ - public void setLpth(Double lpth) { - this.lpth = lpth; - } - - /** - * Non-equilibrium long period tide height (m) - * - * @param nlth - * Non-equilibrium long period tide height to return - */ - public Double getNlth() { - return nlth; - } - - /** - * @param nlth - * Non-equilibrium long period tide height to set - */ - public void setNlth(Double nlth) { - this.nlth = nlth; - } - - /** - * Geocentric pole tide height (m) - * - * @param gpth - * Geocentric pole tide height to return - */ - public Double getGpth() { - return gpth; - } - - /** - * @param gpth - * Geocentric pole tide height to set - */ - public void setGpth(Double gpth) { - this.gpth = gpth; - } - - /** - * Inverted barometer correction (m) - * - * @param ibco - * Inverted barometer correction to return - */ - public Double getIbco() { - return ibco; - } - - /** - * @param ibco - * Inverted barometer correction to set - */ - public void setIbco(Double ibco) { - this.ibco = ibco; - } - - /** - * High frequency fluctuations of the sea surface topography correction (m) - * - * @param hfstc - * High frequency fluctuations of the sea surface topography - * correction - * - */ - public Double getHfstc() { - return hfstc; - } - - /** - * @param hfstc - * High frequency fluctuations of the sea surface topography - * correction to set - */ - public void setHfstc(Double hfstc) { - this.hfstc = hfstc; - } - - /** - * Sea Surface Height Anomoly - * - * @param ssha - * Sea Surface Height Anomoly to return - */ - public Double getSsha() { - return ssha; - } - - /** - * @param ssha - * Sea Surface Height Anomoly to set - */ - public void setSsha(Double ssha) { - this.ssha = ssha; - } - - /** - * @return the obsTime - */ - public Calendar getObsTime() { - return obsTime; - } - - /** - * @param obsTime - * the obsTime to set - */ - public void setObsTime(Calendar obsTime) { - this.obsTime = obsTime; - } - - /** - * Get the value and units of a named parameter within this observation. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return An Amount with value and units. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Amount getValue(String paramName) { - return null; - } - - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public String getString(String paramName) { - return null; - } - - /** - * Get the value of a parameter that is represented as a String. - * - * @param paramName - * The name of the parameter value to retrieve. - * @return The String value of the parameter. If the parameter is unknown, a - * null reference is returned. - */ - @Override - public Collection getValues(String paramName) { - return null; - } - - /** - * Get the IDecoderGettable reference for this record. - * - * @return The IDecoderGettable reference for this record. - */ - @Override - public IDecoderGettable getDecoderGettable() { - return this; - } - - @Override - public void setDataURI(String dataURI) { - identifier = dataURI; - } - - @Override - public String[] getStrings(String paramName) { - return null; - } - - @Override - public Date getPersistenceTime() { - return this.dataTime.getRefTime(); - - } - - @Override - public void setPersistenceTime(Date persistTime) { - // TODO Auto-generated method stub - - } - - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } - - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - - } + IDecoderGettable, IPointData, IPersistable { + private static final long serialVersionUID = 1L; + + private static final float RMISSD = IDecoderConstantsN.FLOAT_MISSING; + + private static final Integer IMISSD = IDecoderConstantsN.INTEGER_MISSING; + + /** Satellite Identification */ + @Column + /* + * Sea surface height anomalies are from blended TOPEX/Poseidon, Jason-1, + * ERS 1, ERS 2m GPO and Envisat ocean altimetry satellites, therefore said + * should be a primary key. + */ + @DataURI(position = 4) + @DynamicSerializeElement + private Long said; + + /** Satellite Instruments */ + @Column + @DynamicSerializeElement + private Long siid; + + /** Station Acquisition */ + @Column(length = 20) + @DynamicSerializeElement + private String staq; + + /** Software Identification and Version Number */ + @Column(length = 12) + @DynamicSerializeElement + private String softv; + + /** Satellite Cycle Number */ + @Column + @DynamicSerializeElement + private Long sacyln; + + /** Orbit Number */ + @Column + @DataURI(position = 5) + @DynamicSerializeElement + private Long orbn; + + /** Numerical Model Identifier */ + @Column(length = 16) + @DynamicSerializeElement + private String numid; + + /** Observation time */ + @Column + @DataURI(position = 1) + @DynamicSerializeElement + private Calendar obsTime; + + /** Latitude */ + @Column + @DataURI(position = 2) + @DynamicSerializeElement + private Double clath; + + /** Longitude */ + @Column + @DataURI(position = 3) + @DynamicSerializeElement + private Double clonh; + + /** Remotely Sensed Surface Type */ + @Transient + @DynamicSerializeElement + private Long rsst; + + /** Altimeter Echo Type */ + @Transient + @DynamicSerializeElement + private Long aetp; + + /** Radiometer Sensed Surface Type */ + @Transient + @DynamicSerializeElement + private Long dsst; + + /** Interpolation Flag */ + @Transient + @DynamicSerializeElement + private Long intf; + + /** Three-dimensional Error Estimate of the Navigator Orbit */ + @Transient + @DynamicSerializeElement + private Long eeno; + + /** Altimeter State Flag */ + @Transient + @DynamicSerializeElement + private Long asfl; + + /** Altimeter Data Quality Flag */ + @Transient + @DynamicSerializeElement + private Long adqf; + + /** Altimeter Correction Quality Flag */ + @Transient + @DynamicSerializeElement + private Long arqf; + + /** Altimeter Rain Flag */ + @Transient + @DynamicSerializeElement + private Long alrf; + + /** Radioimeter State Flag */ + @Transient + @DynamicSerializeElement + private Long rsfl; + + /** Radioimeter Data Quality Flag */ + @Transient + @DynamicSerializeElement + private Long rdqf; + + /** Radioimeter Brightness Temperature Interpretation */ + @Transient + @DynamicSerializeElement + private Long rbif; + + /** Ice Presence Indicator */ + @Transient + @DynamicSerializeElement + private Long ipin; + + /** Auxilliary Altimeter State Flags */ + @Transient + @DynamicSerializeElement + private Long aasf; + + /** Meteorological Map Availability */ + @Transient + @DynamicSerializeElement + private Long mmap; + + /** Interpolation Flag For Mean Diurnal Tide */ + @Transient + @DynamicSerializeElement + private Long ifdt; + + /** Ku Band Ocean Range (m) */ + @Transient + @DynamicSerializeElement + private Double kbor; + + /** RMS of 20 Hz Ku Band Ocean Range (m) */ + @Transient + @DynamicSerializeElement + private Double rkbor; + + /** Number of 20 Hz valid points for Ku Band */ + @Transient + @DynamicSerializeElement + private Long nvpk2; + + /** Ku Band net instrumental Correction (m) */ + @Transient + @DynamicSerializeElement + private Double kbic; + + /** Sea State Bias Correction On Ku Band (m) */ + @Transient + @DynamicSerializeElement + private Double sbck; + + /** Ku Band Significant Wave Height (m) */ + @Transient + @DynamicSerializeElement + private Double kbsw; + + /** RMS 20 Hz Ku Band Significant Wave Height (m) */ + @Transient + @DynamicSerializeElement + private Double rksw; + + /** Number of 20 Hz valid points for Ku Band Significant Wave Height */ + @Transient + @DynamicSerializeElement + private Long nvksw; + + /** + * 20 Hz RMS Ku Band Net Instrumental Correction For Significant Wave Height + * (m) + */ + @Transient + @DynamicSerializeElement + private Double kncs; + + /** Ku Band Corrected Ocean Backscatter coefficient (kb) */ + @Transient + @DynamicSerializeElement + private Double kobc; + + /** STD Ku Band Corrected Ocean Backscatter coefficient (kb) */ + @Transient + @DynamicSerializeElement + private Double skobc; + + /** Number of valid points for Ku Band Backscatter */ + @Transient + @DynamicSerializeElement + private Long nvpkb; + + /** Ku band net instrumental correction for AGC (db) */ + @Transient + @DynamicSerializeElement + private Double knic; + + /** Attenuation Correction 1 On Sigma-0 (db) */ + @Transient + @DynamicSerializeElement + private Double acrs1; + + /** Attenuation Correction 2 On Sigma-0 (db) */ + @Transient + @DynamicSerializeElement + private Double acrs2; + + /** Ku Band Automatic Gain Control (db) */ + @Transient + @DynamicSerializeElement + private Double kagc; + + /** RMS Ku Band Automatic Gain Control (db) */ + @Transient + @DynamicSerializeElement + private Double rkagc; + + /** Number of valid points for Ku Band Automatic Gain Control */ + @Transient + @DynamicSerializeElement + private Long nvkg; + + /** C Band Ocean Range (m) */ + @Transient + @DynamicSerializeElement + private Double cbor; + + /** RMS of C Band Ocean Range (m) */ + @Transient + @DynamicSerializeElement + private Double rcbor; + + /** Number of 20 Hz valid points for C band */ + @Transient + @DynamicSerializeElement + private Long nvpc; + + /** C band net instrumental correction (m) */ + @Transient + @DynamicSerializeElement + private Double cbic; + + /** Sea state bias correction on C band (m) */ + @Transient + @DynamicSerializeElement + private Double sbcc; + + /** C band significant wave height (m) */ + @Transient + @DynamicSerializeElement + private Double cbsw; + + /** RMS 20 Hz C band significant wave height (m) */ + @Transient + @DynamicSerializeElement + private Double rcsw; + + /** Number of 20 Hz valid points for C band significance */ + @Transient + @DynamicSerializeElement + private Long nvcsw; + + /** C band net instrumental correction for significance (m) */ + @Transient + @DynamicSerializeElement + private Double cncs; + + /** C band corrected ocean backscatter coefficient (db) */ + @Transient + @DynamicSerializeElement + private Double ccob; + + /** RMS C band corrected ocean backscatter coefficient (db) */ + @Transient + @DynamicSerializeElement + private Double rccob; + + /** Number of valid points for C band backscatter */ + @Transient + @DynamicSerializeElement + private Long nvpcb; + + /** C band net instrumental correction for AGC (db) */ + @Transient + @DynamicSerializeElement + private Double cnia; + + /** C band automatic gain control (db) */ + @Transient + @DynamicSerializeElement + private Double cagc; + + /** RMS C band automatic gain control (db) */ + @Transient + @DynamicSerializeElement + private Double rcagc; + + /** Number of valid points for C band automatic gain */ + @Transient + @DynamicSerializeElement + private Long nvpca; + + /** Satellite channel center frequency 1 (hz) */ + @Transient + @DynamicSerializeElement + private Double sccf1; + + /** Satellite channel center frequency 2 (hz) */ + @Transient + @DynamicSerializeElement + private Double sccf2; + + /** Satellite channel center frequency 3 (hz) */ + @Transient + @DynamicSerializeElement + private Double sccf3; + + /** Brightness temperature 1 (k) */ + @Transient + @DynamicSerializeElement + private Double tmbrst1; + + /** Brightness temperature 2 (k) */ + @Transient + @DynamicSerializeElement + private Double tmbrst2; + + /** Brightness temperature 3 (k) */ + @Transient + @DynamicSerializeElement + private Double tmbrst3; + + /** Radiometer water vapor content (kg/m**2) */ + @Transient + @DynamicSerializeElement + private Double rwvc; + + /** Radiometer liquid content (kg/m**) */ + @Transient + @DynamicSerializeElement + private Double rlqc; + + /** Height or altitude 1 (m) */ + @Transient + @DynamicSerializeElement + private Double hmsl1; + + /** Height or altitude 2 (m) */ + @Transient + @DynamicSerializeElement + private Double hmsl2; + + /** Wind speed from altimeter (m/s) */ + @Transient + @DynamicSerializeElement + private Double wspa; + + /** Wind speed from radiometer (m/s) */ + @Transient + @DynamicSerializeElement + private Double wspr; + + /** u-component of the model wind vector (m/s) */ + @Transient + @DynamicSerializeElement + private Double umwv; + + /** v-component of the model wind vector (m/s) */ + @Transient + @DynamicSerializeElement + private Double vwmv; + + /** Mean dynamic topography (m) */ + @Transient + @DynamicSerializeElement + private Double mdyt; + + /** Altitude of COG above reference ellipsoid (m) */ + @Transient + @DynamicSerializeElement + private Double alre; + + /** Instantaneous altitude rate (m/s) */ + @Transient + @DynamicSerializeElement + private Double ialr; + + /** Squared off nadir angle of the satellite from platform data (degree**2) */ + @Transient + @DynamicSerializeElement + private Double onap; + + /** Squared off nadir angle of the satellite from waveform data (degree**2) */ + @Transient + @DynamicSerializeElement + private Double sonaw; + + /** Ionospheric correction from model on Ku band (m) */ + @Transient + @DynamicSerializeElement + private Double icmk; + + /** Altimeter ionospheric correction on Ku band (m) */ + @Transient + @DynamicSerializeElement + private Double aick; + + /** Model dry tropospheric correction (m) */ + @Transient + @DynamicSerializeElement + private Double mdtc; + + /** Model wet tropospheric correction (m) */ + @Transient + @DynamicSerializeElement + private Double mwtc; + + /** Radiometer wet tropospheric correction (m) */ + @Transient + @DynamicSerializeElement + private Double rwtc; + + /** Mean sea-surface height (m) */ + @Transient + @DynamicSerializeElement + private Double mssh; + + /** Mean sea surface height from altimeter only (m) */ + @Transient + @DynamicSerializeElement + private Double msha; + + /** Geoid's height (m) */ + @Transient + @DynamicSerializeElement + private Double geodh; + + /** Ocean depth/land elevation (m) */ + @Transient + @DynamicSerializeElement + private Double odle; + + /** Solid earth tide height (m) */ + @Transient + @DynamicSerializeElement + private Double seth; + + /** Total geocentric ocean tide height solution 1 (m) */ + @Transient + @DynamicSerializeElement + private Double tgoth1; + + /** Total geocentric ocean tide height solution 2 (m) */ + @Transient + @DynamicSerializeElement + private Double tgoth2; + + /** Loading tide height geocentric ocean tide solution 1 (m) */ + @Transient + @DynamicSerializeElement + private Double lths1; + + /** Loading tide height geocentric ocean tide solution 2 (m) */ + @Transient + @DynamicSerializeElement + private Double lths2; + + /** Long period tide height (m) */ + @Transient + @DynamicSerializeElement + private Double lpth; + + /** Non-equilibrium long period tide height (m) */ + @Transient + @DynamicSerializeElement + private Double nlth; + + /** Geocentric pole tide height (m) */ + @Transient + @DynamicSerializeElement + private Double gpth; + + /* Inverted barometer correction (m) */ + @Transient + @DynamicSerializeElement + private Double ibco; + + /* High frequency fluctuations of the sea surface topography correction (m) */ + @Transient + @DynamicSerializeElement + private Double hfstc; + + /** Sea Surface Height Anomoly (m) */ + @Transient + @DynamicSerializeElement + private Double ssha; + + /** Report type */ + @Transient + @DynamicSerializeElement + @DataURI(position = 6) + private String reportType; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + /** + * Default constructor. + */ + public SshaRecord() { + Double doubleRmissd = Double.parseDouble(String.valueOf(RMISSD)); + Long longImissd = Long.parseLong(String.valueOf(IMISSD)); + this.reportType = "BUFRSSHA"; + this.said = longImissd; + this.siid = longImissd; + this.staq = " "; + this.softv = " "; + this.sacyln = longImissd; + this.orbn = longImissd; + this.numid = " "; + this.clath = doubleRmissd; + this.clonh = doubleRmissd; + this.rsst = longImissd; + this.aetp = longImissd; + this.dsst = longImissd; + this.intf = longImissd; + this.eeno = longImissd; + this.asfl = longImissd; + this.adqf = longImissd; + this.arqf = longImissd; + this.alrf = longImissd; + this.rsfl = longImissd; + this.rdqf = longImissd; + this.rbif = longImissd; + this.ipin = longImissd; + this.aasf = longImissd; + this.mmap = longImissd; + this.ifdt = longImissd; + this.kbor = doubleRmissd; + this.rkbor = doubleRmissd; + this.nvpk2 = longImissd; + this.kbic = doubleRmissd; + this.sbck = doubleRmissd; + this.kbsw = doubleRmissd; + this.rksw = doubleRmissd; + this.nvksw = longImissd; + this.kncs = doubleRmissd; + this.kobc = doubleRmissd; + this.skobc = doubleRmissd; + this.nvpkb = longImissd; + this.knic = doubleRmissd; + this.acrs1 = doubleRmissd; + this.acrs2 = doubleRmissd; + this.kagc = doubleRmissd; + this.rkagc = doubleRmissd; + this.nvkg = longImissd; + this.cbor = doubleRmissd; + this.rcbor = doubleRmissd; + this.nvpc = longImissd; + this.cbic = doubleRmissd; + this.sbcc = doubleRmissd; + this.cbsw = doubleRmissd; + this.rcsw = doubleRmissd; + this.nvcsw = longImissd; + this.cncs = doubleRmissd; + this.ccob = doubleRmissd; + this.rccob = doubleRmissd; + this.nvpcb = longImissd; + this.cnia = doubleRmissd; + this.cagc = doubleRmissd; + this.rcagc = doubleRmissd; + this.nvpca = longImissd; + this.sccf1 = doubleRmissd; + this.sccf2 = doubleRmissd; + this.sccf3 = doubleRmissd; + this.tmbrst1 = doubleRmissd; + this.tmbrst2 = doubleRmissd; + this.tmbrst3 = doubleRmissd; + this.rwvc = doubleRmissd; + this.rlqc = doubleRmissd; + this.hmsl1 = doubleRmissd; + this.hmsl2 = doubleRmissd; + this.wspa = doubleRmissd; + this.wspr = doubleRmissd; + this.umwv = doubleRmissd; + this.vwmv = doubleRmissd; + this.mdyt = doubleRmissd; + this.alre = doubleRmissd; + this.ialr = doubleRmissd; + this.onap = doubleRmissd; + this.sonaw = doubleRmissd; + this.icmk = doubleRmissd; + this.aick = doubleRmissd; + this.mdtc = doubleRmissd; + this.mwtc = doubleRmissd; + this.rwtc = doubleRmissd; + this.mssh = doubleRmissd; + this.msha = doubleRmissd; + this.geodh = doubleRmissd; + this.odle = doubleRmissd; + this.seth = doubleRmissd; + this.tgoth1 = doubleRmissd; + this.tgoth2 = doubleRmissd; + this.lths1 = doubleRmissd; + this.lths2 = doubleRmissd; + this.lpth = doubleRmissd; + this.nlth = doubleRmissd; + this.gpth = doubleRmissd; + this.ibco = doubleRmissd; + this.hfstc = doubleRmissd; + this.ssha = doubleRmissd; + } + + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + */ + public SshaRecord(String uri) { + super(uri); + } + + /** + * Get the observation report type. + * + * @return the reportType + */ + public String getReportType() { + return reportType; + } + + /** + * Set the observation report type. + * + * @param reportType + * the reportType to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } + + /** + * Get the Satellite Identifier. + * + * @return the Satellite ID + */ + public Long getSaid() { + return said; + } + + /** + * @param said + * the Satellite Identifier to set + */ + public void setSaid(Long said) { + this.said = said; + } + + /** + * Get the Satellite Instruments. + * + * @return the Satellite Instruments + */ + public Long getSiid() { + return siid; + } + + /** + * @param siid + * the Satellite Instruments to set + */ + public void setSiid(Long siid) { + this.siid = siid; + } + + /** + * Get the Station Acquisition. + * + * @return the Station Acquisition + */ + public String getStaq() { + return staq; + } + + /** + * @param staq + * the Station Acquisition to set + */ + public void setStaq(String staq) { + this.staq = staq; + } + + /** + * Get the Software Identification and Version. + * + * @return the Software Id and Version + */ + public String getSoftv() { + return softv; + } + + /** + * @param softv + * the Software Id and Version to set + */ + public void setSoftv(String softv) { + this.softv = softv; + } + + /** + * Get the Satellite Cycle Number. + * + * @return the Satellite Cycle Number + */ + public Long getSacyln() { + return sacyln; + } + + /** + * @param sacyln + * the Satellite Cycle Number to set + */ + public void setSacyln(Long sacyln) { + this.sacyln = sacyln; + } + + /** + * Get the Orbit Number. + * + * @return the Orbit Number + */ + public Long getOrbn() { + return orbn; + } + + /** + * @param orbn + * the Orbit Number to set + */ + public void setOrbn(Long orbn) { + this.orbn = orbn; + } + + /** + * Get the Numerical Model Identifier. + * + * @return the Numerical Model Identifier + */ + public String getNumid() { + return numid; + } + + /** + * @param numid + * the Numerical Model Identifier to set + */ + public void setNumid(String numid) { + this.numid = numid; + } + + /** + * @return the clath + */ + public Double getClath() { + return clath; + } + + /** + * @param clath + * the latitude to set + */ + public void setClath(Double clath) { + this.clath = clath; + } + + /** + * @return the clonh + */ + public Double getClonh() { + return clonh; + } + + /** + * @param clonh + * the longitude to set + */ + public void setClonh(Double clonh) { + this.clonh = clonh; + } + + /** + * Get the Remote Sensed Surface Type. + * + * @return the Remote Sensed Surface Type + */ + public Long getRsst() { + return rsst; + } + + /** + * @param rsst + * the Remote Sensed Surface Type to set + */ + public void setRsst(Long rsst) { + this.rsst = rsst; + } + + /** + * Get the Altimeter Echo Type. + * + * @return the Altimeter Echo Type + */ + public Long getAetp() { + return aetp; + } + + /** + * @param aetp + * the Altimeter Echo Type to set + */ + public void setAetp(Long aetp) { + this.aetp = aetp; + } + + /** + * Get the Radiometer Sensed Surface Type. + * + * @return the Remote Sensed Surface Type + */ + public Long getDsst() { + return dsst; + } + + /** + * @param dsst + * the Radiometer Sensed Surface Type to set + */ + public void setDsst(Long dsst) { + this.dsst = dsst; + } + + /** + * Get the Interpolation Flag. + * + * @return the Interpolation Flag + */ + public Long getIntf() { + return intf; + } + + /** + * @param intf + * the Interpolation Flag to set + */ + public void setIntf(Long intf) { + this.intf = intf; + } + + /** + * Get the Three-dimensional Error Estimate of the Navigator Orbit. + * + * @return the Three-dimensional Error Estimate of the Navigator Orbit + */ + public Long getEeno() { + return eeno; + } + + /** + * @param eeno + * the Three-dimensional Error Estimate of the Navigator Orbit to + * set + */ + public void setEeno(Long eeno) { + this.eeno = eeno; + } + + /** + * Get the Altimeter State Flag. + * + * @return the Altimeter State Flag + */ + public Long getAsfl() { + return asfl; + } + + /** + * @param asfl + * the Altimeter State Flag to set + */ + public void setAsfl(Long asfl) { + this.asfl = asfl; + } + + /** + * Get the Altimeter Data Quality Flag. + * + * @return the Altimeter Data Quality Flag + */ + public Long getAdqf() { + return adqf; + } + + /** + * @param adqf + * the Altimeter Data Quality Flag to set + */ + public void setAdqf(Long adqf) { + this.adqf = adqf; + } + + /** + * Get the Altimeter Correction Quality Flag. + * + * @return the Altimeter Correction Quality Flag + */ + public Long getArqf() { + return arqf; + } + + /** + * @param arqf + * the Altimeter Correction Quality Flag to set + */ + public void setArqf(Long arqf) { + this.arqf = arqf; + } + + /** + * Get the Altimeter Rain Flag. + * + * @return the Altimeter Rain Flag + */ + public Long getAlrf() { + return alrf; + } + + /** + * @param alrf + * the Altimeter Rain Flag to set + */ + public void setAlrf(Long alrf) { + this.alrf = alrf; + } + + /** + * Get the Radiometer State Flag. + * + * @return the Radiometer State Flag + */ + public Long getRsfl() { + return rsfl; + } + + /** + * @param rsfl + * the Radiometer State Flag to set + */ + public void setRsfl(Long rsfl) { + this.rsfl = rsfl; + } + + /** + * Get the Radiometer Data Quality Flag. + * + * @return the Radiometer Data Quality Flag + */ + public Long getRdqf() { + return rdqf; + } + + /** + * @param rdqf + * the Radiometer Data Quality Flag to set + */ + public void setRdqf(Long rdqf) { + this.rdqf = rdqf; + } + + /** + * Get the Radiometer Brightness Temperature Interpretation. + * + * @return the Radiometer Brightness Temperature Interpretation + */ + public Long getRbif() { + return rbif; + } + + /** + * @param rbif + * the Radiometer Brightness Temperature Interpretation to set + */ + public void setRbif(Long rbif) { + this.rbif = rbif; + } + + /** + * Get the Ice Presence Indicator. + * + * @return the Ice Presence Indicator + */ + public Long getIpin() { + return ipin; + } + + /** + * @param ipin + * the Ice Presence Indicator to set + */ + public void setIpin(Long ipin) { + this.ipin = ipin; + } + + /** + * Get the Auxillliary Altimeter State Flags. + * + * @return the Auxillliary Altimeter State Flags + */ + public Long getAasf() { + return aasf; + } + + /** + * @param aasf + * the Auxillliary Altimeter State Flags to set + */ + public void setAasf(Long aasf) { + this.aasf = aasf; + } + + /** + * Get the Meteorological Map Availablity. + * + * @return the Meteorological Map Availablity + */ + public Long getMmap() { + return mmap; + } + + /** + * @param mmap + * the Meteorological Map Availablity to set + */ + public void setMmap(Long mmap) { + this.mmap = mmap; + } + + /** + * Get the Interpolation Flag For Mean Diurnal Tide. + * + * @return the Interpolation Flag For Mean Diurnal Tide + */ + public Long getIfdt() { + return ifdt; + } + + /** + * @param ifdt + * the Interpolation Flag For Mean Diurnal Tide to set + */ + public void setIfdt(Long ifdt) { + this.ifdt = ifdt; + } + + /** + * Get the Ku Band Ocean Range + * + * @param kbor + * Ku Band Ocean Range to return + */ + public Double getKbor() { + return kbor; + } + + /** + * @param kbor + * Ku Band Ocean Range to set + */ + public void setKbor(Double kbor) { + this.kbor = kbor; + } + + /** + * Get the RMS of 20 Hz Ku Band Ocean Range + * + * @param rkbor + * RMS of 20 Hz Ku Band Ocean Range to return + */ + public Double getRkbor() { + return rkbor; + } + + /** + * @param rkbor + * RMS of 20 Hz Ku Band Ocean Range to set + */ + public void setRkbor(Double rkbor) { + this.rkbor = rkbor; + } + + /** + * Get the Number of 20 Hz valid points for Ku Band. + * + * @return the Number of 20 Hz valid points for Ku Band + */ + public Long getNvpk2() { + return nvpk2; + } + + /** + * @param nvpk2 + * the Number of 20 Hz valid points for Ku Band to set + */ + public void setNvpk2(Long nvpk2) { + this.nvpk2 = nvpk2; + } + + /** + * Get the Ku Band Net Instrumental Correction + * + * @param kbic + * Ku Band Net Instrumental Correction to return + */ + public Double getKbic() { + return kbic; + } + + /** + * @param kbic + * Ku Band Net Instrumental Correction to set + */ + public void setKbic(Double kbic) { + this.kbic = kbic; + } + + /** + * Get the Sea State Bias Correction On Ku Band + * + * @param sbck + * Sea State Bias Correction On Ku Band to return + */ + public Double getSbck() { + return sbck; + } + + /** + * @param sbck + * Sea State Bias Correction On Ku Band to set + */ + public void setSbck(Double sbck) { + this.sbck = sbck; + } + + /** + * Get Ku Band Significant Wave Height + * + * @param kbsw + * Ku Band Significant Wave Height to return + */ + public Double getKbsw() { + return kbsw; + } + + /** + * @param kbsw + * Ku Band Significant Wave Height to set + */ + public void setKbsw(Double kbsw) { + this.kbsw = kbsw; + } + + /** + * RMS 20 Hz Ku Band Significant Wave Height + * + * @param rksw + * RMS 20 Hz Ku Band Significant Wave Height + */ + public Double getRksw() { + return rksw; + } + + /** + * @param rksw + * 20 Hz RMS Ku Band Significant Wave Height to set + */ + public void setRksw(Double rksw) { + this.rksw = rksw; + } + + /** + * Get the Number of 20 Hz valid points for Ku Band Significant Wave Height. + * + * @return the Number of 20 Hz valid points for Ku Band Significant Wave + * Height + */ + public Long getNvksw() { + return nvksw; + } + + /** + * @param nvksw + * the Number of 20 Hz valid points for Ku Band Significant Wave + * Height to set + */ + public void setNvksw(Long nvksw) { + this.nvksw = nvksw; + } + + /** + * RMS 20 Hz Ku Band Net Instrumental Correction For Significant Wave Height + * + * @param kncs + * RMS 20 Hz Ku Band Net Instrumental Correction For Significant + * Wave Height + */ + public Double getKncs() { + return kncs; + } + + /** + * @param kncs + * 20 Hz RMS Ku Band Net Instrumental Correction For Significant + * Wave Height to set + */ + public void setKncs(Double kncs) { + this.kncs = kncs; + } + + /** + * Ku Band Corrected Ocean Backscatter coefficient + * + * @param kobc + * Ku Band Corrected Ocean Backscatter coefficient + */ + public Double getKobc() { + return kobc; + } + + /** + * @param kobc + * Ku Band Corrected Ocean Backscatter coefficient to set + */ + public void setKobc(Double kobc) { + this.kobc = kobc; + } + + /** + * STD Ku Band Corrected Ocean Backscatter coefficient + * + * @param kobc + * STD Ku Band Corrected Ocean Backscatter coefficient + */ + public Double getSkobc() { + return skobc; + } + + /** + * @param skobc + * STD Ku Band Corrected Ocean Backscatter coefficient to set + */ + public void setSkobc(Double skobc) { + this.skobc = skobc; + } + + /** + * Get the Number of valid points for Ku Band Backscatter. + * + * @return the Number of valid points for Ku Band Backscatter + */ + public Long getNvpkb() { + return nvpkb; + } + + /** + * @param nvpkb + * the Number of valid points for Ku Band Backscatter to set + */ + public void setNvpkb(Long nvpkb) { + this.nvpkb = nvpkb; + } + + /** + * Ku band net instrumental correction for AGC + * + * @param knic + * Ku band net instrumental correction for AGC + */ + public Double getKnic() { + return knic; + } + + /** + * @param knic + * Ku band net instrumental correction for AGC to set + */ + public void setKnic(Double knic) { + this.knic = knic; + } + + /** + * Attenuation Correction 1 On Sigma-0 + * + * @param acrs1 + * Attenuation 1 Correction On Sigma-0 + */ + public Double getAcrs1() { + return acrs1; + } + + /** + * @param acrs1 + * Attenuation Correction 1 On Sigma-0 + */ + public void setAcrs1(Double acrs1) { + this.acrs1 = acrs1; + } + + /** + * Attenuation Correction 2 On Sigma-0 + * + * @param acrs2 + * Attenuation Correction 2 On Sigma-0 + */ + public Double getAcrs2() { + return acrs2; + } + + /** + * @param acrs2 + * Attenuation Correction 2 On Sigma-0 + */ + public void setAcrs2(Double acrs2) { + this.acrs2 = acrs2; + } + + /** + * Ku Band Automatic Gain Control + * + * @param kagc + * Ku Band Automatic Gain Control + */ + public Double getKagc() { + return kagc; + } + + /** + * @param kagc + * Ku Band Automatic Gain Control + */ + public void setKagc(Double kagc) { + this.kagc = kagc; + } + + /** + * RMS Ku Band Automatic Gain Control + * + * @param rkagc + * RMS Ku Band Automatic Gain Control + */ + public Double getRkagc() { + return rkagc; + } + + /** + * @param rkagc + * RMS Ku Band Automatic Gain Control + */ + public void setRkagc(Double rkagc) { + this.rkagc = rkagc; + } + + /** + * Get the Number of valid points for Ku Band Automatic Gain Control. + * + * @return nvkg the Number of valid points for Ku Band Automatic Gain + * Control + */ + public Long getNvkg() { + return nvkg; + } + + /** + * @param nvkg + * the Number of valid points for Ku Band Automatic Gain Control + * to set + */ + public void setNvkg(Long nvkg) { + this.nvkg = nvkg; + } + + /** + * C Band Ocean Range + * + * @param cbor + * C Band Ocean Range to return + */ + public Double getCbor() { + return cbor; + } + + /** + * @param cbor + * C Band Ocean Range to set + */ + public void setCbor(Double cbor) { + this.cbor = cbor; + } + + /** + * RMS of C Band Ocean Range + * + * @param rcbor + * RMS of C Band Ocean Range to return + */ + public Double getRcbor() { + return rcbor; + } + + /** + * @param rcbor + * RMS of C Band Ocean Range to set + */ + public void setRcbor(Double rcbor) { + this.rcbor = rcbor; + } + + /** + * Get the Number of Number of 20 Hz valid points for C band + * + * @return nvpc the Number of 20 Hz valid points for C band + */ + public Long getNvpc() { + return nvpc; + } + + /** + * @param nvpc + * the Number of 20 Hz valid points for C band to set + */ + public void setNvpc(Long nvpc) { + this.nvpc = nvpc; + } + + /** + * C Band net instrumental correction + * + * @param cbic + * C band net instrumental correction to return + */ + public Double getCbic() { + return cbic; + } + + /** + * @param cbic + * C band net instrumental correction to set + */ + public void setCbic(Double cbic) { + this.cbic = cbic; + } + + /** + * Sea state bias correction on C band + * + * @param sbcc + * Sea state bias correction on C band to return + */ + public Double getSbcc() { + return sbcc; + } + + /** + * @param sbcc + * Sea state bias correction on C band to set + */ + public void setSbcc(Double sbcc) { + this.sbcc = sbcc; + } + + /** + * C band significant wave height + * + * @param cbsw + * C band significant wave height to return + */ + public Double getCbsw() { + return cbsw; + } + + /** + * @param cbsw + * C band significant wave height to set + */ + public void setCbsw(Double cbsw) { + this.cbsw = cbsw; + } + + /** + * RMS 20 Hz C band significant wave height + * + * @param rcsw + * RMS 20 Hz C band significant wave height to return + */ + public Double getRcsw() { + return rcsw; + } + + /** + * @param rcsw + * RMS 20 Hz C band significant wave height to set + */ + public void setRcsw(Double rcsw) { + this.rcsw = rcsw; + } + + /** + * Get the Number of 20 Hz valid points for C band significance + * + * @return nvcsw the Number of 20 Hz valid points for C band significance + */ + public Long getNvcsw() { + return nvcsw; + } + + /** + * @param nvcsw + * the Number of 20 Hz valid points for C band significance to + * set + */ + public void setNvcsw(Long nvcsw) { + this.nvcsw = nvcsw; + } + + /** + * C band net instrumental correction for significance + * + * @param cncs + * C band net instrumental correction for significance to return + */ + public Double getCncs() { + return cncs; + } + + /** + * @param cncs + * C band net instrumental correction for significance to set + */ + public void setCncs(Double cncs) { + this.cncs = cncs; + } + + /** + * C band corrected ocean backscatter coefficient + * + * @param ccob + * C band corrected ocean backscatter coefficient to return + */ + public Double getCcob() { + return ccob; + } + + /** + * @param ccob + * C band corrected ocean backscatter coefficient to set + */ + public void setCcob(Double ccob) { + this.ccob = ccob; + } + + /** + * RMS C band corrected ocean backscatter coefficient + * + * @param rccob + * RMS C band corrected ocean backscatter coefficient to return + */ + public Double getRccob() { + return rccob; + } + + /** + * @param rccob + * RMS C band corrected ocean backscatter coefficient to set + */ + public void setRccob(Double rccob) { + this.rccob = rccob; + } + + /** + * Get the Number of valid points for C band backscatter + * + * @return nvpcb the Number of valid points for C band backscatter + */ + public Long getNvpcb() { + return nvpcb; + } + + /** + * @param nvpcb + * the Number of valid points for C band backscatter to set + */ + public void setNvpcb(Long nvpcb) { + this.nvpcb = nvpcb; + } + + /** + * RMS C band net instrumental correction for AGC + * + * @param cnia + * C band net instrumental correction for AGC to return + */ + public Double getCnia() { + return cnia; + } + + /** + * @param cnia + * C band net instrumental correction for AGC to set + */ + public void setCnia(Double cnia) { + this.cnia = cnia; + } + + /** + * C band automatic gain control + * + * @param cagc + * C band automatic gain control to return + */ + public Double getCagc() { + return cagc; + } + + /** + * @param cagc + * C band automatic gain control to set + */ + public void setCagc(Double cagc) { + this.cagc = cagc; + } + + /** + * RMS C band automatic gain control + * + * @param rcagc + * RMS C band automatic gain control to return + */ + public Double getRcagc() { + return rcagc; + } + + /** + * @param rcagc + * RMS C band automatic gain control to set + */ + public void setRcagc(Double rcagc) { + this.rcagc = rcagc; + } + + /** + * Get the Number of valid points for C band automatic gain + * + * @return nvpca the Number of valid points for C band automatic gain + */ + public Long getNvpca() { + return nvpca; + } + + /** + * @param nvpca + * the Number of valid points for C band automatic gain to set + */ + public void setNvpca(Long nvpca) { + this.nvpca = nvpca; + } + + /** + * Satellite channel center frequency 1 + * + * @param sccf1 + * Satellite channel center frequency 1 + */ + public Double getSccf1() { + return sccf1; + } + + /** + * @param sccf1 + * Satellite channel center frequency 1 + */ + public void setSccf1(Double sccf1) { + this.sccf1 = sccf1; + } + + /** + * Satellite channel center frequency 1 + * + * @param sccf2 + * Satellite channel center frequency 2 + */ + public Double getSccf2() { + return sccf2; + } + + /** + * @param sccf2 + * Satellite channel center frequency 2 + */ + public void setSccf2(Double sccf2) { + this.sccf2 = sccf2; + } + + /** + * Satellite channel center frequency 3 + * + * @param sccf1 + * Satellite channel center frequency 3 + */ + public Double getSccf3() { + return sccf3; + } + + /** + * @param sccf3 + * Satellite channel center frequency 3 + */ + public void setSccf3(Double sccf3) { + this.sccf3 = sccf3; + } + + /** + * Brightness temperature 1 + * + * @param tmbrst1 + * Brightness temperature 1 + */ + public Double getTmbrst1() { + return tmbrst1; + } + + /** + * @param tmbrst1 + * Brightness temperature 1 + */ + public void setTmbrst1(Double tmbrst1) { + this.tmbrst1 = tmbrst1; + } + + /** + * Brightness temperature 2 + * + * @param tmbrst2 + * Brightness temperature 2 + */ + public Double getTmbrst2() { + return tmbrst2; + } + + /** + * @param tmbrst2 + * Brightness temperature 2 + */ + public void setTmbrst2(Double tmbrst2) { + this.tmbrst2 = tmbrst2; + } + + /** + * Brightness temperature 3 + * + * @param tmbrst3 + * Brightness temperature 3 + */ + public Double getTmbrst3() { + return tmbrst3; + } + + /** + * @param tmbrst3 + * Brightness temperature 3 + */ + public void setTmbrst3(Double tmbrst3) { + this.tmbrst3 = tmbrst3; + } + + /** + * Radiometer water vapor content + * + * @param rwvc + * Radiometer water vapor content to return + */ + public Double getRwvc() { + return rwvc; + } + + /** + * @param rwvc + * Radiometer water vapor content to set + */ + public void setRwvc(Double rwvc) { + this.rwvc = rwvc; + } + + /** + * Radiometer liquid content + * + * @param rlqc + * Radiometer liquid content to return + */ + public Double getRlqc() { + return rlqc; + } + + /** + * @param rlqc + * Radiometer liquid content to set + */ + public void setRlqc(Double rlqc) { + this.rlqc = rlqc; + } + + /** + * Height or altitude 1 + * + * @param hmsl + * Height or altitude 1 to return + */ + public Double getHmsl1() { + return hmsl1; + } + + /** + * @param hmsl + * Height or altitude 1 to set + */ + public void setHmsl1(Double hmsl1) { + this.hmsl1 = hmsl1; + } + + /** + * Height or altitude 2 + * + * @param hmsl + * Height or altitude 2 to return + */ + public Double getHmsl2() { + return hmsl2; + } + + /** + * @param hmsl + * Height or altitude 2 to set + */ + public void setHmsl2(Double hmsl2) { + this.hmsl2 = hmsl2; + } + + /** + * Wind speed from altimeter (m/s) + * + * @param wspa + * Wind speed from altimeter to return + */ + public Double getWspa() { + return wspa; + } + + /** + * @param wspa + * Wind speed from altimeter to set + */ + public void setWspa(Double wspa) { + this.wspa = wspa; + } + + /** + * Wind speed from radiometer (m/s) + * + * @param wspr + * Wind speed from radiometer to return + */ + public Double getWspr() { + return wspr; + } + + /** + * @param wspr + * Wind speed from radiometer to set + */ + public void setWspr(Double wspr) { + this.wspr = wspr; + } + + /** + * u-component of the model wind vector (m/s) + * + * @param umwv + * u-component of the model wind vector to return + */ + public Double getUmwv() { + return umwv; + } + + /** + * @param umwv + * u-component of the model wind vector to set + */ + public void setUmwv(Double umwv) { + this.umwv = umwv; + } + + /** + * u-component of the model wind vector (m/s) + * + * @param vwmv + * u-component of the model wind vector to return + */ + public Double getVwmv() { + return vwmv; + } + + /** + * @param vwmv + * u-component of the model wind vector to set + */ + public void setVwmv(Double vwmv) { + this.vwmv = vwmv; + } + + /** + * Mean dynamic topography (m) + * + * @param 1G Mean dynamic topography to return + */ + public Double getMdyt() { + return mdyt; + } + + /** + * @param mdyt + * Mean dynamic topography to set + */ + public void setMdyt(Double mdyt) { + this.mdyt = mdyt; + } + + /** + * Altitude of COG above reference ellipsoid (m) + * + * @param alre + * Altitude of COG above reference ellipsoid + */ + public Double getAlre() { + return alre; + } + + /** + * @param alre + * Altitude of COG above reference ellipsoid to set + */ + public void setAlre(Double alre) { + this.alre = alre; + } + + /** + * Instantaneous altitude rate (m/s) + * + * @param ialr + * Instantaneous altitude rate to return + */ + public Double getIalr() { + return ialr; + } + + /** + * @param ialr + * Instantaneous altitude rate to set + */ + public void setIalr(Double ialr) { + this.ialr = ialr; + } + + /** + * Squared off nadir angle of the satellite from platform data (degree**2) + * + * @param onap + * Squared off nadir angle of the satellite from platform data to + * set + */ + public Double getOnap() { + return onap; + } + + /** + * @param onap + * Squared off nadir angle of the satellite from platform data to + * set + */ + public void setOnap(Double onap) { + this.onap = onap; + } + + /** + * Squared off nadir angle of the satellite from waveform data (degree**2) + * + * @param sonaw + * Squared off nadir angle of the satellite from waveform data to + * return + */ + public Double getSonaw() { + return sonaw; + } + + /** + * @param sonaw + * Squared off nadir angle of the satellite from waveform data to + * set + */ + public void setSonaw(Double sonaw) { + this.sonaw = sonaw; + } + + /** + * Ionospheric correction from model on Ku band (m) + * + * @param icmk + * Ionospheric correction from model on Ku band to return + */ + public Double getIcmk() { + return icmk; + } + + /** + * @param icmk + * Ionospheric correction from model on Ku band to set + */ + public void setIcmk(Double icmk) { + this.icmk = icmk; + } + + /** + * Ionospheric correction from model on Ku band (m) + * + * @param aick + * Ionospheric correction from model on Ku band to return + */ + public Double getAick() { + return aick; + } + + /** + * @param aick + * Ionospheric correction from model on Ku band to set + */ + public void setAick(Double aick) { + this.aick = aick; + } + + /** + * Model dry tropospheric correction (m) + * + * @param mdtc + * Model dry tropospheric correction to return + */ + public Double getMdtc() { + return mdtc; + } + + /** + * @param mdtc + * Model dry tropospheric correction to set + */ + public void setMdtc(Double mdtc) { + this.mdtc = mdtc; + } + + /** + * Model wet tropospheric correction (m) + * + * @param mwtc + * Model wet tropospheric correction to return + */ + public Double getMwtc() { + return mwtc; + } + + /** + * @param mwtc + * Model wet tropospheric correction to set + */ + public void setMwtc(Double mwtc) { + this.mwtc = mwtc; + } + + /** + * Radiometer wet tropospheric correction (m) + * + * @param rwtc + * Radiometer wet tropospheric correction to return + */ + public Double getRwtc() { + return rwtc; + } + + /** + * @param rwtc + * Radiometer wet tropospheric correction to set + */ + public void setRwtc(Double rwtc) { + this.rwtc = rwtc; + } + + /** + * Mean sea-surface height (m) + * + * @param mssh + * Mean sea-surface height to return + */ + public Double getMssh() { + return mssh; + } + + /** + * @param mssh + * Mean sea-surface height to set + */ + public void setMssh(Double mssh) { + this.mssh = mssh; + } + + /** + * Mean sea-surface height from altimeter only (m) + * + * @param msha + * Mean sea-surface height from altimeter only to return + */ + public Double getMsha() { + return msha; + } + + /** + * @param msha + * Mean sea-surface height from altimeter only to set + */ + public void setMsha(Double msha) { + this.msha = msha; + } + + /** + * Geoid's height (m) + * + * @param geodh + * Geoid's height to return + */ + public Double getGeodh() { + return geodh; + } + + /** + * @param odle + * Ocean depth/land elevation (m) + */ + public void setGeodh(Double geodh) { + this.geodh = geodh; + } + + /** + * Ocean depth/land elevation (m) + * + * @param odle + * Ocean depth/land elevation to return + */ + public Double getOdle() { + return odle; + } + + /** + * @param odle + * Ocean depth/land elevation to set + */ + public void setOdle(Double odle) { + this.odle = odle; + } + + /** + * Solid earth tide height (m) + * + * @param seth + * Solid earth tide height to return + */ + public Double getSeth() { + return seth; + } + + /** + * @param seth + * Solid earth tide height to set + */ + public void setSeth(Double seth) { + this.seth = seth; + } + + /** + * Total geocentric ocean tide height solution 1 (m) + * + * @param tgoth1 + * Total geocentric ocean tide height solution 1 to return + */ + public Double getTgoth1() { + return tgoth1; + } + + /** + * @param tgoth1 + * Total geocentric ocean tide height solution 1 to set + */ + public void setTgoth1(Double tgoth1) { + this.tgoth1 = tgoth1; + } + + /** + * Total geocentric ocean tide height solution 2 (m) + * + * @param tgoth2 + * Total geocentric ocean tide height solution 2 to return + */ + public Double getTgoth2() { + return tgoth2; + } + + /** + * @param tgoth2 + * Total geocentric ocean tide height solution 2 to set + */ + public void setTgoth2(Double tgoth2) { + this.tgoth2 = tgoth2; + } + + /** + * Loading tide height geocentric ocean tide solution 1 (m) + * + * @param lths1 + * Loading tide height geocentric ocean tide solution 1 to return + */ + public Double getLths1() { + return lths1; + } + + /** + * @param lths1 + * Loading tide height geocentric ocean tide solution 1 to set + */ + public void setLths1(Double lths1) { + this.lths1 = lths1; + } + + /** + * Loading tide height geocentric ocean tide solution 2 (m) + * + * @param lths2 + * Loading tide height geocentric ocean tide solution 2 to return + */ + public Double getLths2() { + return lths2; + } + + /** + * @param lths2 + * Loading tide height geocentric ocean tide solution 2 to set + */ + public void setLths2(Double lths2) { + this.lths2 = lths2; + } + + /** + * Long period tide height (m) + * + * @param lpth + * Long period tide height to return + */ + public Double getLpth() { + return lpth; + } + + /** + * @param lpth + * Long period tide height to set + */ + public void setLpth(Double lpth) { + this.lpth = lpth; + } + + /** + * Non-equilibrium long period tide height (m) + * + * @param nlth + * Non-equilibrium long period tide height to return + */ + public Double getNlth() { + return nlth; + } + + /** + * @param nlth + * Non-equilibrium long period tide height to set + */ + public void setNlth(Double nlth) { + this.nlth = nlth; + } + + /** + * Geocentric pole tide height (m) + * + * @param gpth + * Geocentric pole tide height to return + */ + public Double getGpth() { + return gpth; + } + + /** + * @param gpth + * Geocentric pole tide height to set + */ + public void setGpth(Double gpth) { + this.gpth = gpth; + } + + /** + * Inverted barometer correction (m) + * + * @param ibco + * Inverted barometer correction to return + */ + public Double getIbco() { + return ibco; + } + + /** + * @param ibco + * Inverted barometer correction to set + */ + public void setIbco(Double ibco) { + this.ibco = ibco; + } + + /** + * High frequency fluctuations of the sea surface topography correction (m) + * + * @param hfstc + * High frequency fluctuations of the sea surface topography + * correction + * + */ + public Double getHfstc() { + return hfstc; + } + + /** + * @param hfstc + * High frequency fluctuations of the sea surface topography + * correction to set + */ + public void setHfstc(Double hfstc) { + this.hfstc = hfstc; + } + + /** + * Sea Surface Height Anomoly + * + * @param ssha + * Sea Surface Height Anomoly to return + */ + public Double getSsha() { + return ssha; + } + + /** + * @param ssha + * Sea Surface Height Anomoly to set + */ + public void setSsha(Double ssha) { + this.ssha = ssha; + } + + /** + * @return the obsTime + */ + public Calendar getObsTime() { + return obsTime; + } + + /** + * @param obsTime + * the obsTime to set + */ + public void setObsTime(Calendar obsTime) { + this.obsTime = obsTime; + } + + /** + * Get the value and units of a named parameter within this observation. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return An Amount with value and units. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Amount getValue(String paramName) { + return null; + } + + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public String getString(String paramName) { + return null; + } + + /** + * Get the value of a parameter that is represented as a String. + * + * @param paramName + * The name of the parameter value to retrieve. + * @return The String value of the parameter. If the parameter is unknown, a + * null reference is returned. + */ + @Override + public Collection getValues(String paramName) { + return null; + } + + /** + * Get the IDecoderGettable reference for this record. + * + * @return The IDecoderGettable reference for this record. + */ + @Override + public IDecoderGettable getDecoderGettable() { + return this; + } + + @Override + public void setDataURI(String dataURI) { + identifier = dataURI; + } + + @Override + public String[] getStrings(String paramName) { + return null; + } + + @Override + public Date getPersistenceTime() { + return this.dataTime.getRefTime(); + + } + + @Override + public void setPersistenceTime(Date persistTime) { + // TODO Auto-generated method stub + + } + + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } + + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + + } @Override @Column @@ -2570,4 +2569,9 @@ public class SshaRecord extends PersistablePluginDataObject implements public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "ssha"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.stormtrack/src/gov/noaa/nws/ncep/common/dataplugin/stormtrack/StormTrackRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.stormtrack/src/gov/noaa/nws/ncep/common/dataplugin/stormtrack/StormTrackRecord.java index bfad2c3fe9..4c29426f79 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.stormtrack/src/gov/noaa/nws/ncep/common/dataplugin/stormtrack/StormTrackRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.stormtrack/src/gov/noaa/nws/ncep/common/dataplugin/stormtrack/StormTrackRecord.java @@ -1,23 +1,3 @@ -/* - * - * StormTrackRecord - * - * This class performs the mapping to the database tables for the Automated - * Tropical Cyclone Forecast (ATCF) and ensemble storm tracks Decoder plug-in. - * - * SOFTWARE HISTORY - * Date Ticket# Engineer Description - * ------------ ----------- -------------- ----------------------------------- - * 06/23/10 283 F. J. Yen Initial creation - * * - * This code has been developed by the SIB for use in the AWIPS2 system. - * - * - * @author F. J. Yen, SIB - * @version 1 - - */ - package gov.noaa.nws.ncep.common.dataplugin.stormtrack; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; @@ -55,18 +35,20 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * 07/2011 T. Lee ATCF and Ensemble storm tracks - * 10/19/2011 858 Greg Hull remove forecastHr - * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. - * May 07, 2013 1869 bsteffen Remove dataURI column from - * PluginDataObject. - * + * Date Ticket# Engineer Description + * ------------ --------- ----------- -------------------------- + * Jun 23, 2010 283 F. J. Yen Initial creation + * 07/2011 T. Lee ATCF and Ensemble storm tracks + * Oct 19, 2011 858 Greg Hull remove forecastHr + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * May 07, 2013 1869 bsteffen Remove dataURI column from + * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * - * @author tlee + * @author F. J. Yen, SIB * @version 1.0 */ @Entity @@ -76,674 +58,672 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "stormtrack", - indexes = { - @Index(name = "stormtrack_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "stormtrack", indexes = { @Index(name = "stormtrack_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class StormTrackRecord extends PluginDataObject { - private static final long serialVersionUID = 1L; - private static final float RMISSD = IDecoderConstantsN.FLOAT_MISSING; - private static final Integer IMISSD = IDecoderConstantsN.INTEGER_MISSING; - - /** Report type */ - @Column(length = 32) - @XmlElement - @DynamicSerializeElement - @DataURI(position = 6) - private String reportType; - - /** - * Basin, e.g. WP, IO, SH, CP, EP, AL, SL, ML - */ - @DataURI(position = 1) - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String basin; - - /** - * Annual cyclone number; 1 through 99 - */ - @DataURI(position = 2) - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String cycloneNum; - - /** - * Warning Date-Time - */ - @Column - @DynamicSerializeElement - @XmlElement - private Calendar warnTime; - - /** - * Objective technique sorting number/Minutes for best track: 00-99 - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private int techniqueNum; - - /** - * Objective Technique or CARQ or WRNG, BEST for best Track - */ - @DataURI(position = 3) - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String model; - -// @DataURI(position = 4) -// @Column -// @DynamicSerializeElement -// @XmlElement -// private int fcstHour; - - /** - * Latitude (degrees) for the DTG: -900 through 900 - */ - @DynamicSerializeElement - @XmlElement - private float clat; - - /** - * Longitude (degrees) for the DTG: -1800 through 1800 - */ - @DynamicSerializeElement - @XmlElement - private float clon; - - /** - * Maximum sustained wind speed in knots: 0 through 300 - */ - @DynamicSerializeElement - @XmlElement - private float windMax; - - /** - * Minimum sea level pressure, 1 through 1100MB - */ - @DynamicSerializeElement - @XmlElement - private float mslp; - - /** - * Level of tropical cyclone development; such as DB, TD, TS, TY, ... - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String stormType; - - /** - * Wind intensity (kts) for the radii defined i this record: 34, 50, 64 - */ - @DataURI(position = 4) - @DynamicSerializeElement - @XmlElement - private float windCategory; - - /** - * Radius Code for wind intensity: AAA = full circle; QQQ = quadrant (NNQ, - * NEQ, EEQ, SEQ, SSQ, SWQ, WWQ, NWQ) - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String windCode; - - /** - * If full circle, radius of specified wind intensity. If semicircle or - * quadrant, radius of specified wind intensity of circle portion specified - * in radius code. 0 - 1200 nm. - */ - @DynamicSerializeElement - @XmlElement - private float quad1WindRad; - - /** - * If full circle, this field not used. If semicircle, radius (nm) of - * specified wind intensity for semicircle not specified in radius code. If - * quadrant, radius (nm) of specified wind intensity for 2nd quadrant - * (counting clockwise from quadrant specified in radius code). 0 - 1200 nm. - */ - @DynamicSerializeElement - @XmlElement - private float quad2WindRad; - - /** - * If full circle or semicircle this field not used. If quadrant, radius - * (nm) of specified wind intensity for 3rd quadrant (counting clockwise - * from quadrant specified in radius code). 0 - 1200 nm. - */ - @DynamicSerializeElement - @XmlElement - private float quad3WindRad; - - /** - * If full circle or semicircle this field not used. If quadrant, radius - * (nm) of specified wind intensity for 4th quadrant (counting clockwise - * from quadrant specified in radius code). 0 - 1200 nm. - */ - @DynamicSerializeElement - @XmlElement - private float quad4WindRad; - - /** - * Pressure in millibars of the last closed isobar. 900 - 1050 mb - */ - @DynamicSerializeElement - @XmlElement - private float closedP; - - /** - * Radius of the last closed isobar in nm. 0 - 9999 nm - */ - @DynamicSerializeElement - @XmlElement - private float radClosedP; - - /** - * Radius of max winds. 0 - 999 nm - */ - @DynamicSerializeElement - @XmlElement - private float maxWindRad; - - /** - * Gusts. 0 - 995 kts. - */ - @DynamicSerializeElement - @XmlElement - private float gust; - - /** - * Eye diameter. 0 - 999nm - */ - @DynamicSerializeElement - @XmlElement - private float eyeSize; - - /** - * Subregion code: A, B, C, E, L, P, Q, S, W - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String subRegion; - - /** - * Max seas: 0 through 999 ft. - */ - @DynamicSerializeElement - @XmlElement - private float maxSeas; - - /** - * Forecaster's initials, used for forecastHour 0 WRNG, up to 3 chars - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String forecaster; - - /** - * Storm direction in compass coordinates, 0 - 359 degrees - */ - @DynamicSerializeElement - @XmlElement - private float stormDrct; - - /** - * Storm speed. 0 - 999 kts - */ - @DynamicSerializeElement - @XmlElement - private float stormSped; - - /** - * Literal storm name, NONAME, or INVEST - */ - @DataURI(position = 5) - @Column(length = 32) - @DynamicSerializeElement - @XmlElement - private String stormName; - - /** - * System depth, D=deep, M=medium, S=shallow, X=unknown - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String stormDepth; - - /** - * Wave height for radii defined in seas1 - seas4. 0 - 99 ft. - */ - @DynamicSerializeElement - @XmlElement - private float waveHght; - - /** - * Radius code for seas wave height - */ - @Column(length = 8) - @DynamicSerializeElement - @XmlElement - private String waveCode; - - /** - * First quadrant seas radius as defined by waveCode, 0 - 999 nm - */ - @DynamicSerializeElement - @XmlElement - private float quad1WaveRad; - - /** - * Second quadrant seas radius as defined by waveCode, 0 - 999 nm - */ - @DynamicSerializeElement - @XmlElement - private float quad2WaveRad; - - /** - * Third quadrant seas radius as defined by waveCode, 0 - 999 nm - */ - @DynamicSerializeElement - @XmlElement - private float quad3WaveRad; - - /** - * Fourth quadrant seas radius as defined by waveCode, 0 - 999 nm - */ - @DynamicSerializeElement - @XmlElement - private float quad4WaveRad; - - /* - * 20 character description of format to follow in userData - */ - @Column(length = 20) - @DynamicSerializeElement - @XmlElement - private String userDefined; - - /* - * User data section as indicated by userDefined parameter - */ - @Column(length = 30) - @DynamicSerializeElement - @XmlElement - private String userData; - - /** - * Default Constructor - */ - public StormTrackRecord() { - this.reportType= " "; - this.basin = "XX"; - this.cycloneNum = "M"; - this.warnTime = null; - this.techniqueNum = IDecoderConstantsN.INTEGER_MISSING; - this.model = " "; -// this.fcstHour = IMISSD; - this.clat = RMISSD; - this.clon = RMISSD; - this.windMax = RMISSD; - this.mslp = RMISSD; - this.stormType = "XX"; - this.windCategory = RMISSD; - this.windCode = "M"; - this.quad1WindRad = RMISSD; - this.quad2WindRad = RMISSD; - this.quad3WindRad = RMISSD; - this.quad4WindRad = RMISSD; - this.closedP = RMISSD; - this.radClosedP = RMISSD; - this.maxWindRad = RMISSD; - this.gust = RMISSD; - this.eyeSize = RMISSD; - this.subRegion = " "; - this.maxSeas = RMISSD; - this.forecaster = ""; - this.stormDrct = RMISSD; - this.stormSped = RMISSD; - this.stormName = " "; - this.stormDepth = " "; - this.waveHght = RMISSD; - this.waveCode = " "; - this.quad1WaveRad = RMISSD; - this.quad2WaveRad = RMISSD; - this.quad3WaveRad = RMISSD; - this.quad4WaveRad = RMISSD; - this.userDefined = " "; - this.userData = " "; - } - - /** - * Constructs a StormTrack record from a dataURI - * - * @param uri - * The dataURI - */ - public StormTrackRecord(String uri) { - super(uri); - } - - @Override - public IDecoderGettable getDecoderGettable() { - // TODO Auto-generated method stub - return null; - } - - public String getReportType() { - return reportType; - } - - public void setReportType(String reportType) { - this.reportType = reportType; - } - - public String getBasin() { - return basin; - } - - public void setBasin(String basin) { - this.basin = basin; - } - - public String getCycloneNum() { - return cycloneNum; - } - - public void setCycloneNum(String cycloneNum) { - this.cycloneNum = cycloneNum; - } - - public Calendar getWarnTime() { - return warnTime; - } - - public void setWarnTime(Calendar warnTime) { - this.warnTime = warnTime; - } - - public int getTechniqueNum() { - return techniqueNum; - } - - public void setTechniqueNum(int techniqueNum) { - this.techniqueNum = techniqueNum; - } - - public String getModel() { - return model; - } - - public void setModel(String model) { - this.model = model; - } - - public int getFcstHour() { - return dataTime.getFcstTime()/3600; //fcstHour; - } - - public float getClat() { - return clat; - } - - public void setClat(float clat) { - this.clat = clat; - } - - public float getClon() { - return clon; - } - - public void setClon(float clon) { - this.clon = clon; - } - - public float getWindMax() { - return windMax; - } - - public void setWindMax(float windMax) { - this.windMax = windMax; - } - - public float getMslp() { - return mslp; - } - - public void setMslp(float mslp) { - this.mslp = mslp; - } - - public String getStormType() { - return stormType; - } - - public void setStormType(String stormType) { - this.stormType = stormType; - } + private static final long serialVersionUID = 1L; + + private static final float RMISSD = IDecoderConstantsN.FLOAT_MISSING; + + private static final Integer IMISSD = IDecoderConstantsN.INTEGER_MISSING; + + /** Report type */ + @Column(length = 32) + @XmlElement + @DynamicSerializeElement + @DataURI(position = 6) + private String reportType; + + /** + * Basin, e.g. WP, IO, SH, CP, EP, AL, SL, ML + */ + @DataURI(position = 1) + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String basin; + + /** + * Annual cyclone number; 1 through 99 + */ + @DataURI(position = 2) + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String cycloneNum; + + /** + * Warning Date-Time + */ + @Column + @DynamicSerializeElement + @XmlElement + private Calendar warnTime; + + /** + * Objective technique sorting number/Minutes for best track: 00-99 + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private int techniqueNum; + + /** + * Objective Technique or CARQ or WRNG, BEST for best Track + */ + @DataURI(position = 3) + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String model; + + // @DataURI(position = 4) + // @Column + // @DynamicSerializeElement + // @XmlElement + // private int fcstHour; + + /** + * Latitude (degrees) for the DTG: -900 through 900 + */ + @DynamicSerializeElement + @XmlElement + private float clat; + + /** + * Longitude (degrees) for the DTG: -1800 through 1800 + */ + @DynamicSerializeElement + @XmlElement + private float clon; + + /** + * Maximum sustained wind speed in knots: 0 through 300 + */ + @DynamicSerializeElement + @XmlElement + private float windMax; + + /** + * Minimum sea level pressure, 1 through 1100MB + */ + @DynamicSerializeElement + @XmlElement + private float mslp; + + /** + * Level of tropical cyclone development; such as DB, TD, TS, TY, ... + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String stormType; + + /** + * Wind intensity (kts) for the radii defined i this record: 34, 50, 64 + */ + @DataURI(position = 4) + @DynamicSerializeElement + @XmlElement + private float windCategory; + + /** + * Radius Code for wind intensity: AAA = full circle; QQQ = quadrant (NNQ, + * NEQ, EEQ, SEQ, SSQ, SWQ, WWQ, NWQ) + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String windCode; + + /** + * If full circle, radius of specified wind intensity. If semicircle or + * quadrant, radius of specified wind intensity of circle portion specified + * in radius code. 0 - 1200 nm. + */ + @DynamicSerializeElement + @XmlElement + private float quad1WindRad; + + /** + * If full circle, this field not used. If semicircle, radius (nm) of + * specified wind intensity for semicircle not specified in radius code. If + * quadrant, radius (nm) of specified wind intensity for 2nd quadrant + * (counting clockwise from quadrant specified in radius code). 0 - 1200 nm. + */ + @DynamicSerializeElement + @XmlElement + private float quad2WindRad; + + /** + * If full circle or semicircle this field not used. If quadrant, radius + * (nm) of specified wind intensity for 3rd quadrant (counting clockwise + * from quadrant specified in radius code). 0 - 1200 nm. + */ + @DynamicSerializeElement + @XmlElement + private float quad3WindRad; + + /** + * If full circle or semicircle this field not used. If quadrant, radius + * (nm) of specified wind intensity for 4th quadrant (counting clockwise + * from quadrant specified in radius code). 0 - 1200 nm. + */ + @DynamicSerializeElement + @XmlElement + private float quad4WindRad; + + /** + * Pressure in millibars of the last closed isobar. 900 - 1050 mb + */ + @DynamicSerializeElement + @XmlElement + private float closedP; + + /** + * Radius of the last closed isobar in nm. 0 - 9999 nm + */ + @DynamicSerializeElement + @XmlElement + private float radClosedP; + + /** + * Radius of max winds. 0 - 999 nm + */ + @DynamicSerializeElement + @XmlElement + private float maxWindRad; + + /** + * Gusts. 0 - 995 kts. + */ + @DynamicSerializeElement + @XmlElement + private float gust; + + /** + * Eye diameter. 0 - 999nm + */ + @DynamicSerializeElement + @XmlElement + private float eyeSize; + + /** + * Subregion code: A, B, C, E, L, P, Q, S, W + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String subRegion; + + /** + * Max seas: 0 through 999 ft. + */ + @DynamicSerializeElement + @XmlElement + private float maxSeas; + + /** + * Forecaster's initials, used for forecastHour 0 WRNG, up to 3 chars + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String forecaster; + + /** + * Storm direction in compass coordinates, 0 - 359 degrees + */ + @DynamicSerializeElement + @XmlElement + private float stormDrct; + + /** + * Storm speed. 0 - 999 kts + */ + @DynamicSerializeElement + @XmlElement + private float stormSped; + + /** + * Literal storm name, NONAME, or INVEST + */ + @DataURI(position = 5) + @Column(length = 32) + @DynamicSerializeElement + @XmlElement + private String stormName; + + /** + * System depth, D=deep, M=medium, S=shallow, X=unknown + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String stormDepth; + + /** + * Wave height for radii defined in seas1 - seas4. 0 - 99 ft. + */ + @DynamicSerializeElement + @XmlElement + private float waveHght; + + /** + * Radius code for seas wave height + */ + @Column(length = 8) + @DynamicSerializeElement + @XmlElement + private String waveCode; + + /** + * First quadrant seas radius as defined by waveCode, 0 - 999 nm + */ + @DynamicSerializeElement + @XmlElement + private float quad1WaveRad; + + /** + * Second quadrant seas radius as defined by waveCode, 0 - 999 nm + */ + @DynamicSerializeElement + @XmlElement + private float quad2WaveRad; + + /** + * Third quadrant seas radius as defined by waveCode, 0 - 999 nm + */ + @DynamicSerializeElement + @XmlElement + private float quad3WaveRad; + + /** + * Fourth quadrant seas radius as defined by waveCode, 0 - 999 nm + */ + @DynamicSerializeElement + @XmlElement + private float quad4WaveRad; + + /* + * 20 character description of format to follow in userData + */ + @Column(length = 20) + @DynamicSerializeElement + @XmlElement + private String userDefined; + + /* + * User data section as indicated by userDefined parameter + */ + @Column(length = 30) + @DynamicSerializeElement + @XmlElement + private String userData; + + /** + * Default Constructor + */ + public StormTrackRecord() { + this.reportType = " "; + this.basin = "XX"; + this.cycloneNum = "M"; + this.warnTime = null; + this.techniqueNum = IDecoderConstantsN.INTEGER_MISSING; + this.model = " "; + // this.fcstHour = IMISSD; + this.clat = RMISSD; + this.clon = RMISSD; + this.windMax = RMISSD; + this.mslp = RMISSD; + this.stormType = "XX"; + this.windCategory = RMISSD; + this.windCode = "M"; + this.quad1WindRad = RMISSD; + this.quad2WindRad = RMISSD; + this.quad3WindRad = RMISSD; + this.quad4WindRad = RMISSD; + this.closedP = RMISSD; + this.radClosedP = RMISSD; + this.maxWindRad = RMISSD; + this.gust = RMISSD; + this.eyeSize = RMISSD; + this.subRegion = " "; + this.maxSeas = RMISSD; + this.forecaster = ""; + this.stormDrct = RMISSD; + this.stormSped = RMISSD; + this.stormName = " "; + this.stormDepth = " "; + this.waveHght = RMISSD; + this.waveCode = " "; + this.quad1WaveRad = RMISSD; + this.quad2WaveRad = RMISSD; + this.quad3WaveRad = RMISSD; + this.quad4WaveRad = RMISSD; + this.userDefined = " "; + this.userData = " "; + } + + /** + * Constructs a StormTrack record from a dataURI + * + * @param uri + * The dataURI + */ + public StormTrackRecord(String uri) { + super(uri); + } + + @Override + public IDecoderGettable getDecoderGettable() { + // TODO Auto-generated method stub + return null; + } + + public String getReportType() { + return reportType; + } + + public void setReportType(String reportType) { + this.reportType = reportType; + } + + public String getBasin() { + return basin; + } + + public void setBasin(String basin) { + this.basin = basin; + } + + public String getCycloneNum() { + return cycloneNum; + } + + public void setCycloneNum(String cycloneNum) { + this.cycloneNum = cycloneNum; + } + + public Calendar getWarnTime() { + return warnTime; + } + + public void setWarnTime(Calendar warnTime) { + this.warnTime = warnTime; + } + + public int getTechniqueNum() { + return techniqueNum; + } + + public void setTechniqueNum(int techniqueNum) { + this.techniqueNum = techniqueNum; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public int getFcstHour() { + return dataTime.getFcstTime() / 3600; // fcstHour; + } + + public float getClat() { + return clat; + } + + public void setClat(float clat) { + this.clat = clat; + } + + public float getClon() { + return clon; + } + + public void setClon(float clon) { + this.clon = clon; + } + + public float getWindMax() { + return windMax; + } + + public void setWindMax(float windMax) { + this.windMax = windMax; + } + + public float getMslp() { + return mslp; + } + + public void setMslp(float mslp) { + this.mslp = mslp; + } + + public String getStormType() { + return stormType; + } + + public void setStormType(String stormType) { + this.stormType = stormType; + } - public float getWindCategory() { - return windCategory; - } + public float getWindCategory() { + return windCategory; + } - public void setWindCategory(float windCategory) { - this.windCategory = windCategory; - } + public void setWindCategory(float windCategory) { + this.windCategory = windCategory; + } - public String getWindCode() { - return windCode; - } + public String getWindCode() { + return windCode; + } - public void setWindCode(String windCode) { - this.windCode = windCode; - } + public void setWindCode(String windCode) { + this.windCode = windCode; + } - public float getQuad1WindRad() { - return quad1WindRad; - } + public float getQuad1WindRad() { + return quad1WindRad; + } - public void setQuad1WindRad(float quad1WindRad) { - this.quad1WindRad = quad1WindRad; - } + public void setQuad1WindRad(float quad1WindRad) { + this.quad1WindRad = quad1WindRad; + } - public float getQuad2WindRad() { - return quad2WindRad; - } + public float getQuad2WindRad() { + return quad2WindRad; + } - public void setQuad2WindRad(float quad2WindRad) { - this.quad2WindRad = quad2WindRad; - } + public void setQuad2WindRad(float quad2WindRad) { + this.quad2WindRad = quad2WindRad; + } - public float getQuad3WindRad() { - return quad3WindRad; - } + public float getQuad3WindRad() { + return quad3WindRad; + } - public void setQuad3WindRad(float quad3WindRad) { - this.quad3WindRad = quad3WindRad; - } + public void setQuad3WindRad(float quad3WindRad) { + this.quad3WindRad = quad3WindRad; + } - public float getQuad4WindRad() { - return quad4WindRad; - } + public float getQuad4WindRad() { + return quad4WindRad; + } - public void setQuad4WindRad(float quad4WindRad) { - this.quad4WindRad = quad4WindRad; - } + public void setQuad4WindRad(float quad4WindRad) { + this.quad4WindRad = quad4WindRad; + } - public float getClosedP() { - return closedP; - } + public float getClosedP() { + return closedP; + } - public void setClosedP(float closedP) { - this.closedP = closedP; - } + public void setClosedP(float closedP) { + this.closedP = closedP; + } - public float getRadClosedP() { - return radClosedP; - } + public float getRadClosedP() { + return radClosedP; + } - public void setRadClosedP(float radClosedP) { - this.radClosedP = radClosedP; - } + public void setRadClosedP(float radClosedP) { + this.radClosedP = radClosedP; + } - public float getMaxWindRad() { - return maxWindRad; - } + public float getMaxWindRad() { + return maxWindRad; + } - public void setMaxWindRad(float maxWindRad) { - this.maxWindRad = maxWindRad; - } + public void setMaxWindRad(float maxWindRad) { + this.maxWindRad = maxWindRad; + } - public float getGust() { - return gust; - } + public float getGust() { + return gust; + } - public void setGust(float gust) { - this.gust = gust; - } + public void setGust(float gust) { + this.gust = gust; + } - public float getEyeSize() { - return eyeSize; - } + public float getEyeSize() { + return eyeSize; + } - public void setEyeSize(float eyeSize) { - this.eyeSize = eyeSize; - } + public void setEyeSize(float eyeSize) { + this.eyeSize = eyeSize; + } - public String getSubRegion() { - return subRegion; - } + public String getSubRegion() { + return subRegion; + } - public void setSubRegion(String subRegion) { - this.subRegion = subRegion; - } + public void setSubRegion(String subRegion) { + this.subRegion = subRegion; + } - public float getMaxSeas() { - return maxSeas; - } + public float getMaxSeas() { + return maxSeas; + } - public void setMaxSeas(float maxSeas) { - this.maxSeas = maxSeas; - } + public void setMaxSeas(float maxSeas) { + this.maxSeas = maxSeas; + } - public String getForecaster() { - return forecaster; - } + public String getForecaster() { + return forecaster; + } - public void setForecaster(String forecaster) { - this.forecaster = forecaster; - } + public void setForecaster(String forecaster) { + this.forecaster = forecaster; + } - public float getStormDrct() { - return stormDrct; - } + public float getStormDrct() { + return stormDrct; + } - public void setStormDrct(float stormDrct) { - this.stormDrct = stormDrct; - } + public void setStormDrct(float stormDrct) { + this.stormDrct = stormDrct; + } - public float getStormSped() { - return stormSped; - } + public float getStormSped() { + return stormSped; + } - public void setStormSped(float stormSped) { - this.stormSped = stormSped; - } + public void setStormSped(float stormSped) { + this.stormSped = stormSped; + } - public String getStormName() { - return stormName; - } + public String getStormName() { + return stormName; + } - public void setStormName(String stormName) { - this.stormName = stormName; - } + public void setStormName(String stormName) { + this.stormName = stormName; + } - public String getStormDepth() { - return stormDepth; - } + public String getStormDepth() { + return stormDepth; + } - public void setStormDepth(String stormDepth) { - this.stormDepth = stormDepth; - } + public void setStormDepth(String stormDepth) { + this.stormDepth = stormDepth; + } - public float getWaveHght() { - return waveHght; - } + public float getWaveHght() { + return waveHght; + } - public void setWaveHght(float waveHght) { - this.waveHght = waveHght; - } + public void setWaveHght(float waveHght) { + this.waveHght = waveHght; + } - public String getWaveCode() { - return waveCode; - } + public String getWaveCode() { + return waveCode; + } - public void setWaveCode(String waveCode) { - this.waveCode = waveCode; - } + public void setWaveCode(String waveCode) { + this.waveCode = waveCode; + } - public float getQuad1WaveRad() { - return quad1WaveRad; - } + public float getQuad1WaveRad() { + return quad1WaveRad; + } - public void setQuad1WaveRad(float quad1WaveRad) { - this.quad1WaveRad = quad1WaveRad; - } + public void setQuad1WaveRad(float quad1WaveRad) { + this.quad1WaveRad = quad1WaveRad; + } - public float getQuad2WaveRad() { - return quad2WaveRad; - } + public float getQuad2WaveRad() { + return quad2WaveRad; + } - public void setQuad2WaveRad(float quad2WaveRad) { - this.quad2WaveRad = quad2WaveRad; - } + public void setQuad2WaveRad(float quad2WaveRad) { + this.quad2WaveRad = quad2WaveRad; + } - public float getQuad3WaveRad() { - return quad3WaveRad; - } + public float getQuad3WaveRad() { + return quad3WaveRad; + } - public void setQuad3WaveRad(float quad3WaveRad) { - this.quad3WaveRad = quad3WaveRad; - } + public void setQuad3WaveRad(float quad3WaveRad) { + this.quad3WaveRad = quad3WaveRad; + } - public float getQuad4WaveRad() { - return quad4WaveRad; - } + public float getQuad4WaveRad() { + return quad4WaveRad; + } - public void setQuad4WaveRad(float quad4WaveRad) { - this.quad4WaveRad = quad4WaveRad; - } + public void setQuad4WaveRad(float quad4WaveRad) { + this.quad4WaveRad = quad4WaveRad; + } - public String getUserDefined() { - return userDefined; - } + public String getUserDefined() { + return userDefined; + } - public void setUserDefined(String userDefined) { - this.userDefined = userDefined; - } + public void setUserDefined(String userDefined) { + this.userDefined = userDefined; + } - public String getUserData() { - return userData; - } + public String getUserData() { + return userData; + } - public void setUserData(String userData) { - this.userData = userData; - } + public void setUserData(String userData) { + this.userData = userData; + } @Override @Column @@ -752,4 +732,8 @@ public class StormTrackRecord extends PluginDataObject { return super.getDataURI(); } + @Override + public String getPluginName() { + return "stormtrack"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.tcm/src/gov/noaa/nws/ncep/common/dataplugin/tcm/TcmRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.tcm/src/gov/noaa/nws/ncep/common/dataplugin/tcm/TcmRecord.java index c4c96cc01b..27f67b511b 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.tcm/src/gov/noaa/nws/ncep/common/dataplugin/tcm/TcmRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.tcm/src/gov/noaa/nws/ncep/common/dataplugin/tcm/TcmRecord.java @@ -1,30 +1,3 @@ -/** - * - * TcmRecord - * - * This java class performs the mapping to the database tables for TCM. - * - *
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    	Engineer    Description
- * -------		------- 	-------- 	-----------
- * 06/2009		128			T. Lee		Initial coding
- * 07/2009		128			T. Lee		Migrated to TO11
- * 11/2009		128			T. Lee		Migrated to TO11D6
- * 09/2011      			Chin Chen   changed to improve purge performance and
- * 										removed xml serialization as well
- * 07/2012      #606        Greg Huoll  added reportType to the dataURI
- * Apr 4, 2013        1846 bkowal      Added an index on refTime and forecastTime
- * Apr 12, 2013 1857        bgonzale    Added SequenceGenerator annotation.
- * May 07, 2013 1869        bsteffen	Remove dataURI column from PluginDataObject.
- * 
- * 
- * - * @author T.Lee - * @version 1.0 - */ - package gov.noaa.nws.ncep.common.dataplugin.tcm; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; @@ -53,6 +26,32 @@ import com.raytheon.uf.common.dataplugin.annotations.DataURI; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +/** + * + * TcmRecord + * + * This java class performs the mapping to the database tables for TCM. + * + *
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket# Engineer   Description
+ * ------------ ------- ---------- ---------------------------------
+ * 06/2009      128     T. Lee     Initial coding
+ * 07/2009      128     T. Lee     Migrated to TO11
+ * 11/2009      128     T. Lee     Migrated to TO11D6
+ * 09/2011              Chin Chen  changed to improve purge performance and
+ *                                 removed xml serialization as well
+ * 07/2012      606     Greg Hull  added reportType to the dataURI
+ * Apr 04, 2013 1846    bkowal     Added an index on refTime and forecastTime
+ * Apr 12, 2013 1857    bgonzale   Added SequenceGenerator annotation.
+ * May 07, 2013 1869    bsteffen   Remove dataURI column from PluginDataObject.
+ * Aug 30, 2013 2298   rjpeter Make getPluginName abstract
+ * 
+ * + * @author T.Lee + * @version 1.0 + */ @Entity @SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "tcmseq") @Table(name = "tcm", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) @@ -60,66 +59,61 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "tcm", - indexes = { - @Index(name = "tcm_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) +@org.hibernate.annotations.Table(appliesTo = "tcm", indexes = { @Index(name = "tcm_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize - public class TcmRecord extends PluginDataObject { private static final long serialVersionUID = 1L; - + /** Report type */ - @Column(length=32) - @DataURI(position=6) - @DynamicSerializeElement + @Column(length = 32) + @DataURI(position = 6) + @DynamicSerializeElement private String reportType; /** Storm name */ - @Column(length=32) - @DataURI(position=2) + @Column(length = 32) + @DataURI(position = 2) @DynamicSerializeElement private String stormName; - + /** Tropical storm basin */ - @Column(length=8) - @DataURI(position=1) + @Column(length = 8) + @DataURI(position = 1) @DynamicSerializeElement private String basin; /** Storm number */ - @Column(length=8) - @DataURI(position=3) + @Column(length = 8) + @DataURI(position = 3) @DynamicSerializeElement private String stormNumber; - + /** Advisory number */ - @Column(length=8) - @DataURI(position=4) + @Column(length = 8) + @DataURI(position = 4) @DynamicSerializeElement private String advisoryNumber; - + /** Correction flag */ @Column - @DataURI(position=5) + @DataURI(position = 5) @DynamicSerializeElement private Boolean corr; - + /** Bulletin insurance time */ @Column @DynamicSerializeElement private Calendar issueTime; - - /** Storm observation time **/ - @Column - @DynamicSerializeElement - private Calendar obsTime; + + /** Storm observation time **/ + @Column + @DynamicSerializeElement + private Calendar obsTime; /** Storm type */ - @Column(length=32) + @Column(length = 32) @DynamicSerializeElement private String stormType; @@ -142,359 +136,379 @@ public class TcmRecord extends PluginDataObject { @Column @DynamicSerializeElement private String ne12ft; - + /** Twelve-foot wave height radii at the SE quadrant */ @Column @DynamicSerializeElement private String se12ft; - + /** Twelve-foot wave height radii at the SW quadrant */ @Column @DynamicSerializeElement private String sw12ft; - + /** Twelve-foot wave height radii at the NW quadrant */ @Column @DynamicSerializeElement private String nw12ft; /** Mass news disseminator (MND) */ - @Column(length=72) + @Column(length = 72) @DynamicSerializeElement private String mndTime; /** Bulletin messages */ - @Column(length=8000) + @Column(length = 8000) @DynamicSerializeElement private String bullMessage; - + /** TCM position and winds */ @DynamicSerializeElement @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinColumn(name = "parentID", nullable = false) + @JoinColumn(name = "parentID", nullable = false) @Index(name = "tcmPosWinds_parentid_idex") - private Set tcmPosWinds = new HashSet(); - + private Set tcmPosWinds = new HashSet(); + /** * Default constructor */ public TcmRecord() { - basin = null; - stormName = null; - stormNumber = null; - issueTime = null; - obsTime = null; - corr = false; - mndTime = null; - advisoryNumber = null; - centralPressure = IDecoderConstantsN.INTEGER_MISSING; - positionAccuracy = IDecoderConstantsN.INTEGER_MISSING; - ne12ft = null; - se12ft = null; - sw12ft = null; - nw12ft = null; - bullMessage = null; + basin = null; + stormName = null; + stormNumber = null; + issueTime = null; + obsTime = null; + corr = false; + mndTime = null; + advisoryNumber = null; + centralPressure = IDecoderConstantsN.INTEGER_MISSING; + positionAccuracy = IDecoderConstantsN.INTEGER_MISSING; + ne12ft = null; + se12ft = null; + sw12ft = null; + nw12ft = null; + bullMessage = null; } /** * Constructs a TCM record from a dataURI * - * @param uri the dataURI + * @param uri + * the dataURI */ public TcmRecord(String uri) { - super(uri); + super(uri); } - - /** - * Return the report type + + /** + * Return the report type */ public String getReportType() { return reportType; } /** - * @param reportType the report type to set + * @param reportType + * the report type to set */ public void setReportType(String reportType) { this.reportType = reportType; } - - /** + + /** * Return the basin, e.g., AL/EP */ - public String getBasin() { - return basin; - } - - /** - * @param basin the basin name to set - */ - public void setBasin(String basin) { - this.basin = basin; - } - - /** - * Return the storm name - */ - public String getStormName() { - return stormName; - } + public String getBasin() { + return basin; + } /** - * @param stormName the storm name to set + * @param basin + * the basin name to set */ - public void setStormName(String stormName) { - this.stormName = stormName; - } - - /** + public void setBasin(String basin) { + this.basin = basin; + } + + /** + * Return the storm name + */ + public String getStormName() { + return stormName; + } + + /** + * @param stormName + * the storm name to set + */ + public void setStormName(String stormName) { + this.stormName = stormName; + } + + /** * Return the storm number */ - public String getStormNumber() { - return stormNumber; - } + public String getStormNumber() { + return stormNumber; + } /** - * @param stormNumber the storm number to set + * @param stormNumber + * the storm number to set */ - public void setStormNumber(String stormNumber) { - this.stormNumber = stormNumber; - } - - /** + public void setStormNumber(String stormNumber) { + this.stormNumber = stormNumber; + } + + /** * Return the advisory number */ - - public String getAdvisoryNumber() { - return advisoryNumber; - } + + public String getAdvisoryNumber() { + return advisoryNumber; + } /** - * @param advisory the advisory number to set + * @param advisory + * the advisory number to set */ - public void setAdvisoryNumber(String advisoryNumber) { - this.advisoryNumber = advisoryNumber; - } - - /** + public void setAdvisoryNumber(String advisoryNumber) { + this.advisoryNumber = advisoryNumber; + } + + /** * Return the correction flag */ - public Boolean getCorr() { - return corr; - } + public Boolean getCorr() { + return corr; + } /** - * @param corr the correction flag to set + * @param corr + * the correction flag to set */ - public void setCorr(Boolean corr) { - this.corr = corr; - } - - /** + public void setCorr(Boolean corr) { + this.corr = corr; + } + + /** * Return the storm type */ - public String getStormType() { - return stormType; - } + public String getStormType() { + return stormType; + } /** - * @param stormType the storm type to set + * @param stormType + * the storm type to set */ - public void setStormType(String stormType) { - this.stormType = stormType; - } - - /** + public void setStormType(String stormType) { + this.stormType = stormType; + } + + /** * Return the eye size */ - public Integer getEyeSize() { - return eyeSize; - } + public Integer getEyeSize() { + return eyeSize; + } /** - * @param eyeSize the eye size to set + * @param eyeSize + * the eye size to set */ - public void setEyeSize(Integer eyeSize) { - this.eyeSize = eyeSize; - } - - /** + public void setEyeSize(Integer eyeSize) { + this.eyeSize = eyeSize; + } + + /** * Return the minimum central pressure */ - public Integer getCentralPressure() { - return centralPressure; - } + public Integer getCentralPressure() { + return centralPressure; + } /** - * @param centralPressure the minimum central pressure to set + * @param centralPressure + * the minimum central pressure to set */ - public void setCentralPressure(Integer centralPressure) { - this.centralPressure = centralPressure; - } - - /** - * Return the position accuracy - */ - public Integer getPositionAccuracy() { - return positionAccuracy; - } + public void setCentralPressure(Integer centralPressure) { + this.centralPressure = centralPressure; + } /** - * @param positionAccuracy the position accuracy to set + * Return the position accuracy */ - public void setPositionAccuracy(Integer positionAccuracy) { - this.positionAccuracy = positionAccuracy; - } - - /** + public Integer getPositionAccuracy() { + return positionAccuracy; + } + + /** + * @param positionAccuracy + * the position accuracy to set + */ + public void setPositionAccuracy(Integer positionAccuracy) { + this.positionAccuracy = positionAccuracy; + } + + /** * Return the twelve-foot wave height radii at the NE quadrant */ - public String getNe12ft() { - return ne12ft; - } + public String getNe12ft() { + return ne12ft; + } /** - * @param ne12ft the twelve-foot wave height radii at the NE quadrant to set + * @param ne12ft + * the twelve-foot wave height radii at the NE quadrant to set */ - public void setNe12ft(String ne12ft) { - this.ne12ft = ne12ft; - } + public void setNe12ft(String ne12ft) { + this.ne12ft = ne12ft; + } - /** + /** * Return the twelve-foot wave height radii at the SE quadrant */ - public String getSe12ft() { - return se12ft; - } + public String getSe12ft() { + return se12ft; + } - /** - * @param se12ft the twelve-foot wave height radii at the SE quadrant to set + /** + * @param se12ft + * the twelve-foot wave height radii at the SE quadrant to set */ - public void setSe12ft(String se12ft) { - this.se12ft = se12ft; - } + public void setSe12ft(String se12ft) { + this.se12ft = se12ft; + } - /** + /** * Return the twelve-foot wave height radii at the SW quadrant */ - public String getSw12ft() { - return sw12ft; - } + public String getSw12ft() { + return sw12ft; + } - /** - * @param sw12ft The twelve-foot wave height radii at the SW quadrant to set + /** + * @param sw12ft + * The twelve-foot wave height radii at the SW quadrant to set */ - public void setSw12ft(String sw12ft) { - this.sw12ft = sw12ft; - } + public void setSw12ft(String sw12ft) { + this.sw12ft = sw12ft; + } - /** + /** * Return the twelve-foot wave height radii at the NW quadrant */ - public String getNw12ft() { - return nw12ft; - } + public String getNw12ft() { + return nw12ft; + } - /** - * @param nw12ft The twelve-foot wave height radii at the NW quadrant to set + /** + * @param nw12ft + * The twelve-foot wave height radii at the NW quadrant to set */ - public void setNw12ft(String nw12ft) { - this.nw12ft = nw12ft; - } + public void setNw12ft(String nw12ft) { + this.nw12ft = nw12ft; + } /** * @return the issueTime */ public Calendar getIssueTime() { - return issueTime; + return issueTime; } /** - * @param obsTime The obsTime to set + * @param obsTime + * The obsTime to set */ public void setObsTime(Calendar obsTime) { - this.obsTime = obsTime; + this.obsTime = obsTime; } - + /** * @return the obsTime */ public Calendar getObsTime() { - return obsTime; + return obsTime; } /** - * @param issueTime the issueTime to set + * @param issueTime + * the issueTime to set */ public void setIssueTime(Calendar issueTime) { - this.issueTime = issueTime; + this.issueTime = issueTime; } - + /** * @return the bullMessage */ public String getBullMessage() { - return bullMessage; - } - + return bullMessage; + } + /** - * @param bullMessage the bullMessage to set + * @param bullMessage + * the bullMessage to set */ public void setBullMessage(String bullMessage) { - this.bullMessage = bullMessage; + this.bullMessage = bullMessage; } - + /** * @return the MndTime */ public String getMndTime() { - return mndTime; + return mndTime; } /** - * @param mndTime the mndTime to set + * @param mndTime + * the mndTime to set */ public void setMndTime(String mndTime) { - this.mndTime = mndTime; + this.mndTime = mndTime; } - + /** * @return the set of position and winds */ public Set getTcmPosWinds() { - return tcmPosWinds; + return tcmPosWinds; } /** - * @param tcmPW the set of position and winds to set + * @param tcmPW + * the set of position and winds to set */ - public void setTcmPosWinds(Set tcmPosWinds ) { - this.tcmPosWinds = tcmPosWinds; + public void setTcmPosWinds(Set tcmPosWinds) { + this.tcmPosWinds = tcmPosWinds; } /** * Add TcmPosWinds to set */ - public void addPosWinds(TcmPositionWinds poswinds){ - tcmPosWinds.add(poswinds); - - } + public void addPosWinds(TcmPositionWinds poswinds) { + tcmPosWinds.add(poswinds); - /** - * Override existing set method to modify any - * classes that use the dataURI as a foreign key - */ - @Override - public void setIdentifier(Object dataURI) { - this.identifier = dataURI; - } - @Override + /** + * Override existing set method to modify any classes that use the dataURI + * as a foreign key + */ + @Override + public void setIdentifier(Object dataURI) { + this.identifier = dataURI; + + } + + @Override public IDecoderGettable getDecoderGettable() { - // TODO Auto-generated method stub - return null; - } + // TODO Auto-generated method stub + return null; + } @Override @Column @@ -502,4 +516,9 @@ public class TcmRecord extends PluginDataObject { public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "tcm"; + } } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.wcp/src/gov/noaa/nws/ncep/common/dataplugin/wcp/WcpRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.wcp/src/gov/noaa/nws/ncep/common/dataplugin/wcp/WcpRecord.java index 757c3288ee..a04b47479f 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.wcp/src/gov/noaa/nws/ncep/common/dataplugin/wcp/WcpRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.wcp/src/gov/noaa/nws/ncep/common/dataplugin/wcp/WcpRecord.java @@ -1,4 +1,3 @@ - /** * WcpRecord is the Data Access component for WCP Watch Corner Point data. * This contains getters and setters for the main parent table wcp. @@ -10,16 +9,19 @@ * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 12Dec2008 37 F. J. Yen Initial Coding. - * 17Apr2009 37 F. J. Yen Refactored for TO10 - * 24Aug2009 37 F. J. Yen Refactored for TO11 - * 17May2010 37 F. J. Yen Refactored to dataplugin for migration to to11dr11 - * 09/2011 Chin Chen changed to improve purge performance and - * removed xml serialization as well - * * Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime - * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. + * 12Dec2008 37 F. J. Yen Initial Coding. + * 17Apr2009 37 F. J. Yen Refactored for TO10 + * 24Aug2009 37 F. J. Yen Refactored for TO11 + * 17May2010 37 F. J. Yen Refactored to dataplugin for migration to + * to11dr11 + * 09/2011 Chin Chen changed to improve purge performance and + * removed xml serialization as well + * Apr 04, 2013 1846 bkowal Added an index on refTime and + * forecastTime + * Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -52,6 +54,7 @@ import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.annotations.DataURI; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + @Entity @SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "wcpseq") @Table(name = "wcp", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) @@ -59,46 +62,40 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Both refTime and forecastTime are included in the refTimeIndex since * forecastTime is unlikely to be used. */ -@org.hibernate.annotations.Table( - appliesTo = "wcp", - indexes = { - @Index(name = "wcp_refTimeIndex", columnNames = { "refTime", "forecastTime" } ) - } -) - +@org.hibernate.annotations.Table(appliesTo = "wcp", indexes = { @Index(name = "wcp_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) @DynamicSerialize +public class WcpRecord extends PluginDataObject { -public class WcpRecord extends PluginDataObject{ - - private static final long serialVersionUID = 1L; - - /** Report type */ - @Column(length=32) - @DynamicSerializeElement - @DataURI(position = 2) - private String reportType; - - @Column + private static final long serialVersionUID = 1L; + + /** Report type */ + @Column(length = 32) @DynamicSerializeElement - private Calendar issueTime; + @DataURI(position = 2) + private String reportType; - @DataURI(position = 1) - @Column(length = 8) - @DynamicSerializeElement - private String designatorBBB; - - @Column(length = 2500) - @DynamicSerializeElement - private String bullMessage; + @Column + @DynamicSerializeElement + private Calendar issueTime; - /** WcpSevrln */ - @DynamicSerializeElement - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinColumn(name = "parentID", nullable = false) + @DataURI(position = 1) + @Column(length = 8) + @DynamicSerializeElement + private String designatorBBB; + + @Column(length = 2500) + @DynamicSerializeElement + private String bullMessage; + + /** WcpSevrln */ + @DynamicSerializeElement + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "parentID", nullable = false) @Index(name = "wcpSevrLn_parentid_idex") - private Set wcpSevrLn = new HashSet(); + private Set wcpSevrLn = new HashSet(); - /** + /** * Default Constructor */ public WcpRecord() { @@ -113,73 +110,83 @@ public class WcpRecord extends PluginDataObject{ public WcpRecord(String uri) { super(uri); } - + @Override public IDecoderGettable getDecoderGettable() { // TODO Auto-generated method stub return null; } - + public String getReportType() { - return reportType; + return reportType; } + public void setReportType(String reportType) { - this.reportType = reportType; + this.reportType = reportType; } - - public Calendar getIssueTime(){ - return issueTime; - } - public void setIssueTime(Calendar issueTime){ - this.issueTime=issueTime; - } - - public String getDesignatorBBB(){ - return designatorBBB; - } - public void setDesignatorBBB(String designatorBBB){ - this.designatorBBB=designatorBBB; - } - - public String getBullMessage(){ - return bullMessage; - } - public void setBullMessage(String bullMessage){ - this.bullMessage=bullMessage; - } - /** - * return the set of wcpSevrLn - */ - public Set getWcpSevrLn() { - return wcpSevrLn; - } - - /** - * @param wcpSevrln the wcpSevrln to set - */ - public void setWcpSevrLn(Set wcpSevrlin) { - this.wcpSevrLn = wcpSevrlin; - } - - /* - * Add wcpSevrln to set - */ - public void addWcpSevrLn(WcpSevrln psevrln) { - wcpSevrLn.add(psevrln); - - } - - public void setIdentifier(Object dataURI){ - this.identifier = dataURI; - - + public Calendar getIssueTime() { + return issueTime; } - + + public void setIssueTime(Calendar issueTime) { + this.issueTime = issueTime; + } + + public String getDesignatorBBB() { + return designatorBBB; + } + + public void setDesignatorBBB(String designatorBBB) { + this.designatorBBB = designatorBBB; + } + + public String getBullMessage() { + return bullMessage; + } + + public void setBullMessage(String bullMessage) { + this.bullMessage = bullMessage; + } + + /** + * return the set of wcpSevrLn + */ + public Set getWcpSevrLn() { + return wcpSevrLn; + } + + /** + * @param wcpSevrln + * the wcpSevrln to set + */ + public void setWcpSevrLn(Set wcpSevrlin) { + this.wcpSevrLn = wcpSevrlin; + } + + /* + * Add wcpSevrln to set + */ + public void addWcpSevrLn(WcpSevrln psevrln) { + wcpSevrLn.add(psevrln); + + } + + @Override + public void setIdentifier(Object dataURI) { + this.identifier = dataURI; + + } + @Override @Column @Access(AccessType.PROPERTY) public String getDataURI() { return super.getDataURI(); } + + @Override + public String getPluginName() { + return "wcp"; + } } diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.airmet/src/gov/noaa/nws/ncep/edex/plugin/airmet/decoder/AirmetDecoder.java b/ncep/gov.noaa.nws.ncep.edex.plugin.airmet/src/gov/noaa/nws/ncep/edex/plugin/airmet/decoder/AirmetDecoder.java old mode 100755 new mode 100644 index 7aad148a39..bff3c951cc --- a/ncep/gov.noaa.nws.ncep.edex.plugin.airmet/src/gov/noaa/nws/ncep/edex/plugin/airmet/decoder/AirmetDecoder.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.airmet/src/gov/noaa/nws/ncep/edex/plugin/airmet/decoder/AirmetDecoder.java @@ -109,7 +109,6 @@ public class AirmetDecoder extends AbstractDecoder { */ if (record != null) { record.setTraceId(traceId); - record.setPluginName(pluginName); record.setReportType(pluginName); record.setReportName(reportName); // Decode and set the update number diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.atcf/src/gov/noaa/nws/ncep/edex/plugin/atcf/decoder/AtcfDecoder.java b/ncep/gov.noaa.nws.ncep.edex.plugin.atcf/src/gov/noaa/nws/ncep/edex/plugin/atcf/decoder/AtcfDecoder.java index 0d5f84bfa1..6072c95d34 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.atcf/src/gov/noaa/nws/ncep/edex/plugin/atcf/decoder/AtcfDecoder.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.atcf/src/gov/noaa/nws/ncep/edex/plugin/atcf/decoder/AtcfDecoder.java @@ -1,15 +1,3 @@ -/** - * - * AtcfDecoder - * - * Decoder Plug-In for Automated Tropical Cyclone Forecast ATCF. - * - * 12 December 2008 - * - * This code has been developed by the SIB for use in the AWIPS2 system. - * - */ - package gov.noaa.nws.ncep.edex.plugin.atcf.decoder; import gov.noaa.nws.ncep.common.dataplugin.atcf.AtcfRecord; @@ -31,13 +19,15 @@ import com.raytheon.uf.common.dataplugin.PluginException; * * Decoder implementation for ATCF Plug-In * + * This code has been developed by the SIB for use in the AWIPS2 system. + * *
  * SOFTWARE HISTORY
  * 
- * Date       	Ticket#		Engineer	Description
- * ------------	----------	-----------	--------------------------
- * 06/23/10		208			F. J. Yen	Initial creation
- * 
+ * Date         Ticket#    Engineer     Description
+ * ------------ -------- ----------- --------------------------
+ * Jun 23, 2010 208      F. J. Yen   Initial creation
+ * Aug 30, 2013 2298     rjpeter     Make getPluginName abstract
  * 
* * @author Fee Jing Yen, SIB @@ -114,7 +104,6 @@ public class AtcfDecoder extends AbstractDecoder { if (record != null) { try { record.setTraceId(traceId); - record.setPluginName(pluginName); record.constructDataURI(); } catch (PluginException e) { throw new DecoderException( diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.aww/res/spring/aww-ingest.xml b/ncep/gov.noaa.nws.ncep.edex.plugin.aww/res/spring/aww-ingest.xml index 5199c6cc78..ecc5b995e3 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.aww/res/spring/aww-ingest.xml +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.aww/res/spring/aww-ingest.xml @@ -5,9 +5,7 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - - + - + diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.stormtrack/src/gov/noaa/nws/ncep/edex/plugin/stormtrack/decoder/StormTrackDecoder.java b/ncep/gov.noaa.nws.ncep.edex.plugin.stormtrack/src/gov/noaa/nws/ncep/edex/plugin/stormtrack/decoder/StormTrackDecoder.java index 46b51338a4..b4cc97e66f 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.stormtrack/src/gov/noaa/nws/ncep/edex/plugin/stormtrack/decoder/StormTrackDecoder.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.stormtrack/src/gov/noaa/nws/ncep/edex/plugin/stormtrack/decoder/StormTrackDecoder.java @@ -1,20 +1,8 @@ -/** - * - * StormTrackDecoder - * - * Decoder Plug-In for StormTrack (Automatic Tropical Cyclone Forecast & Ensemble cyclones). - * - * 12 December 2008 - * - * This code has been developed by the SIB for use in the AWIPS2 system. - * - */ - package gov.noaa.nws.ncep.edex.plugin.stormtrack.decoder; import gov.noaa.nws.ncep.common.dataplugin.stormtrack.StormTrackRecord; -import gov.noaa.nws.ncep.edex.plugin.stormtrack.util.StormTrackParser; import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; +import gov.noaa.nws.ncep.edex.plugin.stormtrack.util.StormTrackParser; import java.util.ArrayList; import java.util.List; @@ -27,32 +15,36 @@ import com.raytheon.edex.exception.DecoderException; import com.raytheon.edex.plugin.AbstractDecoder; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; /** - * * StormTrackDecoder * - * Decoder implementation for StormTrack Plug-In + * Decoder implementation for StormTrack Plug-In (Automatic Tropical Cyclone + * Forecast & Ensemble cyclones). + * + * This code has been developed by the SIB for use in the AWIPS2 system. * *
  * SOFTWARE HISTORY
  * 
- * Date       	Ticket#		Engineer	Description
- * ------------	----------	-----------	--------------------------
- * 08/2011					T. Lee		ATCF and Ensemble storm tracks	
- * 06/2012       #606       G. Hull     constructDataURI() after setReportType so it gets into the URI	
- * 07/2013				    T. Lee		Improved performance via batch processing	
- * 
+ * Date        Ticket#  Engineer   Description
+ * ------------ ------- ---------- --------------------------
+ * 08/2011              T. Lee     ATCF and Ensemble storm tracks
+ * 06/2012      606     G. Hull    constructDataURI() after setReportType so it
+ *                                 gets into the URI
+ * 07/2013              T. Lee     Improved performance via batch processing	
+ * Aug 30, 2013 2298    rjpeter    Make getPluginName abstract
  * 
* * @author tlee * @version 1 * */ - public class StormTrackDecoder extends AbstractDecoder { - // Name of the plugin controlling this decoder. - public final String pluginName; + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(StormTrackDecoder.class); protected Matcher regexMatcher; @@ -65,8 +57,7 @@ public class StormTrackDecoder extends AbstractDecoder { * * @throws DecoderException */ - public StormTrackDecoder(String name) throws DecoderException { - pluginName = name; + public StormTrackDecoder() throws DecoderException { } public PluginDataObject[] decode(byte[] data, Headers headers) @@ -96,15 +87,14 @@ public class StormTrackDecoder extends AbstractDecoder { Matcher stormTrackMatcher = stormTrackPattern.matcher(theMessage); if (stormTrackMatcher.find()) { - + } else { - System.out.println("StormTrack WARNING: Ignored invalid record: " + statusHandler.warn("StormTrack: Ignored invalid record: " + theMessage); } } catch (Exception e) { - System.out.println("StormTrack WARNING exception: Unable to decode: " - + theMessage); - e.printStackTrace(); + statusHandler.error("StormTrack exception: Unable to decode: " + + theMessage, e); } /* @@ -117,32 +107,32 @@ public class StormTrackDecoder extends AbstractDecoder { */ if (record != null) { try { - record.setTraceId(traceId); - record.setPluginName(pluginName); + record.setTraceId(traceId); - /* - * Set report type in record. - */ - if (theMessage.contains("FOF\n") || theMessage.contains("TCV\n")) { - record.setReportType("ENSCYC"); - } else { - record.setReportType("ATCF"); - } + /* + * Set report type in record. + */ + if (theMessage.contains("FOF\n") + || theMessage.contains("TCV\n")) { + record.setReportType("ENSCYC"); + } else { + record.setReportType("ATCF"); + } - record.constructDataURI(); + record.constructDataURI(); if ( record.getClat() != IDecoderConstantsN.FLOAT_MISSING && record.getClon() != IDecoderConstantsN.FLOAT_MISSING ) { records.add(record); } } catch (PluginException e) { - throw new DecoderException( - "StormTrack WARNING: Unable to construct dataURI--exception: ", - e); + throw new DecoderException( + "StormTrack WARNING: Unable to construct dataURI--exception: ", + e); } } } - + /* * Return StormTrack record object if not null */ diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.tcm/src/gov/noaa/nws/ncep/edex/plugin/tcm/decoder/TcmDecoder.java b/ncep/gov.noaa.nws.ncep.edex.plugin.tcm/src/gov/noaa/nws/ncep/edex/plugin/tcm/decoder/TcmDecoder.java index 7d8df076b7..ae6a67ef24 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.tcm/src/gov/noaa/nws/ncep/edex/plugin/tcm/decoder/TcmDecoder.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.tcm/src/gov/noaa/nws/ncep/edex/plugin/tcm/decoder/TcmDecoder.java @@ -1,24 +1,3 @@ -/* - * - * TcmDecoder - * - * This java class decodes TCM (Tropical Cyclone Message) data. - * - *
 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    	Engineer    Description
- * ----- 		------- 	--------	-----------
- * 06/2009		128			T. Lee		Creation
- * 07/2009		128			T. Lee		Migrated to TO11
- * 11/2009		128			T. Lee		Migrated to TO11D6
- * 06/2010		128			T. Lee		Migrated to TO11DR11
- * 
- * - * @author T.Lee - * @version 1.0 - */ - package gov.noaa.nws.ncep.edex.plugin.tcm.decoder; import gov.noaa.nws.ncep.common.dataplugin.tcm.TcmRecord; @@ -37,6 +16,26 @@ import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.edex.decodertools.core.IDecoderConstants; +/** + * TcmDecoder + * + * This java class decodes TCM (Tropical Cyclone Message) data. + * + *
 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket# Engineer   Description
+ * ------------ ------- ---------- -----------
+ * 06/2009      128     T. Lee     Creation
+ * 07/2009      128     T. Lee     Migrated to TO11
+ * 11/2009      128     T. Lee     Migrated to TO11D6
+ * 06/2010      128     T. Lee     Migrated to TO11DR11
+ * Aug 30, 2013 2298    rjpeter    Make getPluginName abstract
+ * 
+ * + * @author T.Lee + * @version 1.0 + */ public class TcmDecoder extends AbstractDecoder { private static String pluginName; @@ -128,7 +127,6 @@ public class TcmDecoder extends AbstractDecoder { traceId = (String) headers.get("traceId"); } record.setTraceId(traceId); - record.setPluginName(pluginName); record.constructDataURI(); } catch (PluginException e) { @@ -144,4 +142,4 @@ public class TcmDecoder extends AbstractDecoder { } return new PluginDataObject[] { record }; } -} \ No newline at end of file +} diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.wcp/src/gov/noaa/nws/ncep/edex/plugin/wcp/decoder/WcpDecoder.java b/ncep/gov.noaa.nws.ncep.edex.plugin.wcp/src/gov/noaa/nws/ncep/edex/plugin/wcp/decoder/WcpDecoder.java index 0c0102eab6..91fb6cd608 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.wcp/src/gov/noaa/nws/ncep/edex/plugin/wcp/decoder/WcpDecoder.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.wcp/src/gov/noaa/nws/ncep/edex/plugin/wcp/decoder/WcpDecoder.java @@ -1,15 +1,3 @@ -/** - * - * WcpDecoder - * - * Decoder Plug-In for Watch Corner Point WCP. - * - * 12 December 2008 - * - * This code has been developed by the SIB for use in the AWIPS2 system. - * - */ - package gov.noaa.nws.ncep.edex.plugin.wcp.decoder; import gov.noaa.nws.ncep.common.dataplugin.wcp.WcpRecord; @@ -28,28 +16,28 @@ import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.edex.decodertools.core.IDecoderConstants; /** - * * WcpDecoder * - * Decoder implementation for WCP Plug-In + * Decoder implementation for WCP Plug-In. + * + * This code has been developed by the SIB for use in the AWIPS2 system. * *
  * SOFTWARE HISTORY
  * 
- * Date       	Ticket#		Engineer	Description
- * ------------	----------	-----------	--------------------------
- * 12Dec2008		37		F. J. Yen	Initial creation
- * 17Apr2009		37		F. J. Yen	Refactored for TO10 and to allow for more unit testing
- * 24Aug2009		37		F. J. Yen	Modified for TO11 migration
- * 10Dec2009		37		F. J. Yen	Modified for To11d6
- * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * 12Dec2008    37         F. J. Yen   Initial creation
+ * 17Apr2009    37         F. J. Yen   Refactored for TO10 and to allow for more
+ *                                     unit testing
+ * 24Aug2009    37         F. J. Yen   Modified for TO11 migration
+ * 10Dec2009    37         F. J. Yen   Modified for To11d6
+ * Aug 30, 2013 2298       rjpeter     Make getPluginName abstract
  * 
* * @author Fee Jing Yen, SIB * @version 1 - * */ - public class WcpDecoder extends AbstractDecoder { // Name of the plugin controlling this decoder. public final String pluginName; @@ -140,7 +128,6 @@ public class WcpDecoder extends AbstractDecoder { if (record != null) { try { record.setTraceId(traceId); - record.setPluginName(pluginName); record.constructDataURI(); } catch (PluginException e) { throw new DecoderException("Unable to construct dataURI", e); diff --git a/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/ObservedSoundingQuery.java b/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/ObservedSoundingQuery.java index 06ae3e9471..d9a63eb9f8 100644 --- a/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/ObservedSoundingQuery.java +++ b/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/ObservedSoundingQuery.java @@ -1,40 +1,14 @@ package gov.noaa.nws.ncep.edex.uengine.tasks.profile; -/** - * - * gov.noaa.nws.ncep.edex.uengine.tasks.profile.ObservedSoundingQuery - * - * This java class performs the observed sounding data query functions. - * This code has been developed by the SIB for use in the AWIPS2 system. - * - *
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    	Engineer    Description
- * -------		------- 	-------- 	-----------
- * 09/13/2010	301			Chin Chen	Initial coding
- * 10/2010		301			T. Lee		Checked missing value
- * 11/05/2010   301         Chin Chen   Update to support uairSnd query to all data types, except ALLDATA  
- * 12/16/2010   301         Chin Chen   add support of BUFRUA observed sounding data
- * 09/14/2011   457         S. Gurung   Renamed h5 to nc
- * 10/20/2011               S. Gurung   Added ncuair changes related to replacing slat/slon/selv with location of type SurfaceObsLocation
- * Nov 2011                 Chin Chen   changed Ncuair table query algorithm for performance improvement
- * 01/05/2012               S. Gurung   Removed references to UAIR (performed cleanup)
- * 02/28/2012               Chin Chen   modify several sounding query algorithms for better performance
- * 
- * - * @author Chin Chen - * @version 1.0 - */ import gov.noaa.nws.ncep.common.dataplugin.ncuair.NcUairRecord; import gov.noaa.nws.ncep.common.dataplugin.ncuair.dao.NcUairToRecord; import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer; import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile; +import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile.ObsSndType; +import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile.SndQueryKeyType; import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingStnInfo; import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingStnInfoCollection; import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingTimeLines; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile.ObsSndType; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile.SndQueryKeyType; import java.io.File; import java.sql.Timestamp; @@ -49,13 +23,13 @@ import javax.measure.unit.NonSI; import javax.measure.unit.SI; import com.raytheon.edex.plugin.bufrua.dao.BufrUADao; +import com.raytheon.uf.common.dataplugin.bufrua.UAObs; +import com.raytheon.uf.common.dataplugin.bufrua.dao.BufrUAPointDataTransform; import com.raytheon.uf.common.datastorage.DataStoreFactory; import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.datastorage.Request; import com.raytheon.uf.common.datastorage.records.FloatDataRecord; import com.raytheon.uf.common.datastorage.records.IntegerDataRecord; -import com.raytheon.uf.common.dataplugin.bufrua.UAObs; -import com.raytheon.uf.common.dataplugin.bufrua.dao.BufrUAPointDataTransform; import com.raytheon.uf.common.pointdata.PointDataContainer; import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.dao.CoreDao; @@ -63,1677 +37,1974 @@ import com.raytheon.uf.edex.database.dao.DaoConfig; import com.raytheon.uf.edex.pointdata.PointDataQuery; import com.vividsolutions.jts.geom.Coordinate; +/** + * + * gov.noaa.nws.ncep.edex.uengine.tasks.profile.ObservedSoundingQuery + * + * This java class performs the observed sounding data query functions. + * This code has been developed by the SIB for use in the AWIPS2 system. + * + *
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket# Engineer   Description
+ * ------------ ------- ---------- -----------
+ * Sep 13, 2010 301     Chin Chen  Initial coding
+ * 10/2010      301     T. Lee     Checked missing value
+ * Nov 05, 2010 301     Chin Chen  Update to support uairSnd query to all data
+ *                                 types, except ALLDATA
+ * Dec 16, 2010 301     Chin Chen  add support of BUFRUA observed sounding data
+ * Sep 14, 2011 457     S. Gurung  Renamed h5 to nc
+ * Oct 20, 2011         S. Gurung  Added ncuair changes related to replacing
+ *                                 slat/slon/selv with location of type
+ *                                 SurfaceObsLocation
+ * Nov 2011             Chin Chen  changed Ncuair table query algorithm for
+ *                                 performance improvement
+ * Jan 05, 2012         S. Gurung  Removed references to UAIR (performed
+ *                                 cleanup)
+ * Feb 28, 2012         Chin Chen  modify several sounding query algorithms for
+ *                                 better performance
+ * Jul 19, 2013 1992    bsteffen   Remove redundant time columns from bufrua.
+ * Aug 30, 2013 2298    rjpeter    Make getPluginName abstract
+ * 
+ * + * @author Chin Chen + * @version 1.0 + */ public class ObservedSoundingQuery { - private static final UnitConverter metersPerSecondToKnots = SI.METERS_PER_SECOND.getConverterTo(NonSI.KNOT); - private static final UnitConverter kelvinToCelsius = SI.KELVIN.getConverterTo(SI.CELSIUS); - private static final String NCUAIR_TBL_NAME = "ncuair"; - private static final String BURFUA_TBL_NAME = "bufrua"; - private static String currentDBTblName = "nil"; - - /* - * This method is for caller to get sounding station's info lat/lon/stn id/stn num/elevation - * key: stn's lat/lon or stn ( either stn id or stn num) - */ - @SuppressWarnings("unchecked") - public static NcSoundingProfile getObservedSndStnInfo(Double lat, Double lon,String stn, String obType,Calendar refTimeCal,SndQueryKeyType queryType ) { - NcSoundingProfile pf = new NcSoundingProfile(); - CoreDao dao; - List fields = new ArrayList(); - List values = new ArrayList(); - /*if(obType.equals(ObsSndType.NCUAIR.toString())){ - List operands = new ArrayList(); - List lUairRecords = null; - if(queryType==SndQueryKeyType.STNID){ - fields.add("location.stationId");// the location.stationId field name defined in NcUairRecord - values.add(stn); - operands.add("="); - } - else if(queryType==SndQueryKeyType.STNNUM){ - fields.add("stnum");// the stnNum field name defined in NcUairRecord - values.add(stn); - operands.add("="); - } - else if(queryType==SndQueryKeyType.LATLON){ - fields.add("location.latitude"); // the location.latitude field name defined in NcUairRecord - values.add(lat); - operands.add(">="); - fields.add("location.latitude"); - values.add(lat); - operands.add("<="); - fields.add("location.longitude"); // the location.longitude field name defined in NcUairRecord - values.add(lon); - operands.add(">="); - fields.add("location.longitude"); - values.add(lon); - operands.add("<="); - } - else { - //System.out.println("request query type "+ queryType+ " is not supported in this API" ); - return pf; - } - fields.add("synopticTime");// the synoptic time field name defined in UairRecord - values.add(refTimeCal); - operands.add("="); - dao = new CoreDao(DaoConfig.forClass(NcUairRecord.class)); - try { - lUairRecords = (List) dao.queryByCriteria(fields, values,operands); - System.out.println("Nc uair at lat="+ lat+" lon="+lon+ " recorde size="+lUairRecords.size()); - if(lUairRecords.size() > 0){ - pf.setStationElevation((float)lUairRecords.get(0).getElevation()); - pf.setStationId(lUairRecords.get(0).getStationId()); - if(lUairRecords.get(0).getStnum() != null && lUairRecords.get(0).getStnum().length()>0) - pf.setStationNum(Integer.parseInt(lUairRecords.get(0).getStnum())); - pf.setStationLatitude((float)lUairRecords.get(0).getLatitude()); - pf.setStationLongitude((float)lUairRecords.get(0).getLongitude()); - } - }catch (DataAccessLayerException e) { - //System.out.println("obs sounding query exception"); - e.printStackTrace(); - } - } - else*/ if(obType.equals(ObsSndType.BUFRUA.toString())) { - List lUairRecords = null; - if(queryType==SndQueryKeyType.STNID){ - fields.add("stationName");// the stationName String field name defined in UAObs, dont be confused with UAIRRecord definition - values.add(stn); - } - else if(queryType==SndQueryKeyType.STNNUM){ - fields.add("location.stationId");// the location.stationId String field name defined in UAObs. dont be confused with UAIRRecord definition - values.add(stn); - } - else if(queryType==SndQueryKeyType.LATLON){ - fields.add("location.latitude");// the location.latitude field name defined in UAObs - values.add(lat); - fields.add("location.longitude");// the location.longitude field name defined in UAObs - values.add(lon); + private static final UnitConverter metersPerSecondToKnots = SI.METERS_PER_SECOND + .getConverterTo(NonSI.KNOT); - } - else { - return pf; - } + private static final UnitConverter kelvinToCelsius = SI.KELVIN + .getConverterTo(SI.CELSIUS); + + private static final String NCUAIR_TBL_NAME = "ncuair"; + + private static final String BURFUA_TBL_NAME = "bufrua"; + + private static String currentDBTblName = "nil"; + + /* + * This method is for caller to get sounding station's info lat/lon/stn + * id/stn num/elevation key: stn's lat/lon or stn ( either stn id or stn + * num) + */ + @SuppressWarnings("unchecked") + public static NcSoundingProfile getObservedSndStnInfo(Double lat, + Double lon, String stn, String obType, Calendar refTimeCal, + SndQueryKeyType queryType) { + NcSoundingProfile pf = new NcSoundingProfile(); + CoreDao dao; + List fields = new ArrayList(); + List values = new ArrayList(); + /* + * if(obType.equals(ObsSndType.NCUAIR.toString())){ List + * operands = new ArrayList(); List lUairRecords = + * null; if(queryType==SndQueryKeyType.STNID){ + * fields.add("location.stationId");// the location.stationId field name + * defined in NcUairRecord values.add(stn); operands.add("="); } else + * if(queryType==SndQueryKeyType.STNNUM){ fields.add("stnum");// the + * stnNum field name defined in NcUairRecord values.add(stn); + * operands.add("="); } else if(queryType==SndQueryKeyType.LATLON){ + * fields.add("location.latitude"); // the location.latitude field name + * defined in NcUairRecord values.add(lat); operands.add(">="); + * fields.add("location.latitude"); values.add(lat); operands.add("<="); + * fields.add("location.longitude"); // the location.longitude field + * name defined in NcUairRecord values.add(lon); operands.add(">="); + * fields.add("location.longitude"); values.add(lon); + * operands.add("<="); } else { + * //System.out.println("request query type "+ queryType+ + * " is not supported in this API" ); return pf; } + * fields.add("synopticTime");// the synoptic time field name defined in + * UairRecord values.add(refTimeCal); operands.add("="); dao = new + * CoreDao(DaoConfig.forClass(NcUairRecord.class)); try { lUairRecords = + * (List) dao.queryByCriteria(fields, values,operands); + * System.out.println("Nc uair at lat="+ lat+" lon="+lon+ + * " recorde size="+lUairRecords.size()); if(lUairRecords.size() > 0){ + * pf.setStationElevation((float)lUairRecords.get(0).getElevation()); + * pf.setStationId(lUairRecords.get(0).getStationId()); + * if(lUairRecords.get(0).getStnum() != null && + * lUairRecords.get(0).getStnum().length()>0) + * pf.setStationNum(Integer.parseInt(lUairRecords.get(0).getStnum())); + * pf.setStationLatitude((float)lUairRecords.get(0).getLatitude()); + * pf.setStationLongitude((float)lUairRecords.get(0).getLongitude()); } + * }catch (DataAccessLayerException e) { + * //System.out.println("obs sounding query exception"); + * e.printStackTrace(); } } else + */if (obType.equals(ObsSndType.BUFRUA.toString())) { + List lUairRecords = null; + if (queryType == SndQueryKeyType.STNID) { + fields.add("stationName");// the stationName String field name + // defined in UAObs, dont be confused + // with UAIRRecord definition + values.add(stn); + } else if (queryType == SndQueryKeyType.STNNUM) { + fields.add("location.stationId");// the location.stationId + // String field name defined in + // UAObs. dont be confused with + // UAIRRecord definition + values.add(stn); + } else if (queryType == SndQueryKeyType.LATLON) { + fields.add("location.latitude");// the location.latitude field + // name defined in UAObs + values.add(lat); + fields.add("location.longitude");// the location.longitude field + // name defined in UAObs + values.add(lon); + + } else { + return pf; + } fields.add("validTime");// the synoptic time field name defined in UAObs values.add(refTimeCal); - dao = new CoreDao(DaoConfig.forClass(UAObs.class)); - try { - lUairRecords = (List) dao.queryByCriteria(fields, values); - if(lUairRecords.size() > 0){ - pf.setStationLatitude((float)lUairRecords.get(0).getLatitude()); - pf.setStationLongitude((float)lUairRecords.get(0).getLongitude()); - pf.setStationElevation((float)lUairRecords.get(0).getElevation()); - if(lUairRecords.get(0).getStationId()!=null && lUairRecords.get(0).getStationId().length()>0) - pf.setStationNum(Integer.parseInt(lUairRecords.get(0).getStationId())); - pf.setStationId(lUairRecords.get(0).getStationName()); - pf.setFcsTime(lUairRecords.get(0).getDataTime().getRefTime().getTime()); - } - }catch (DataAccessLayerException e) { - //*System.out.println("obs sounding query exception"); - e.printStackTrace(); - } - } - return pf; - } - public static NcSoundingStnInfoCollection getObservedSndStnInfoCol(String obType, String selectedSndTime) { - NcSoundingStnInfoCollection stnInfoCol = new NcSoundingStnInfoCollection(); - List stationInfoList= new ArrayList(); - String queryStr, queryStr1; - Object [] rtnobjArray, rtnobjArray1; - CoreDao dao; - if(obType.equals(ObsSndType.BUFRUA.toString())){ - currentDBTblName = BURFUA_TBL_NAME; - queryStr = new String("Select Distinct latitude, longitude, id, stationname, elevation, reftime FROM "+ currentDBTblName + " where reftime='" + - selectedSndTime+"' AND latitude BETWEEN -89.9 AND 89.9 AND longitude BETWEEN -179.9 AND 179.9"); - queryStr1 = new String("Select Distinct latitude, longitude FROM "+ currentDBTblName + " where reftime='" + - selectedSndTime+"' AND latitude BETWEEN -89.9 AND 89.9 AND longitude BETWEEN -179.9 AND 179.9"); - dao = new CoreDao(DaoConfig.forClass(UAObs.class)); - - } - else if(obType.equals(ObsSndType.NCUAIR.toString())){ - currentDBTblName = NCUAIR_TBL_NAME; - queryStr = new String("Select Distinct latitude, longitude, id, stationId, elevation, synoptictime FROM "+ currentDBTblName + " where nil='FALSE' AND synoptictime='" + - selectedSndTime+"' AND latitude BETWEEN -89.9 AND 89.9 AND longitude BETWEEN -179.9 AND 179.9"); - queryStr1 = new String("Select Distinct latitude, longitude FROM "+ currentDBTblName + " where nil='FALSE' AND synoptictime='" + - selectedSndTime+"' AND latitude BETWEEN -89.9 AND 89.9 AND longitude BETWEEN -179.9 AND 179.9"); - dao = new CoreDao(DaoConfig.forClass(NcUairRecord.class)); - } - else { - return stnInfoCol; - } - rtnobjArray = dao.executeSQLQuery(queryStr); - - //*System.out.println("size of rtnobjArray " + rtnobjArray.length); - /* - Object[] obj; - for (int i =0; i 0) && (rtnobjArray.length > 0)){ - double lat, lon, elv; - String stnInfo; - - //System.out.println("queryAndMarkStn called mapresource = "+ nsharpMapResource.toString()); - //Note: A same station may have many reports and at some reports they dont provide elv and or stnid - // this implementation is "try" to make sure we get those info. - //If, all reports does not have elv or stnid, then we still can not report it. - for (int i =0; i = '"+ startTimeStr+"' AND synoptictime <= '"+endTimeStr+"' ORDER BY synoptictime DESC"); - dao = new CoreDao(DaoConfig.forClass(NcUairRecord.class)); - } - else{ - return null; - } - synopTimeAry = (Object[]) dao.executeSQLQuery(queryStr); - List timeLst = new ArrayList(); - //*System.out.println("size of synoptictime " + synopTimeAry.length); - - for(int i=0; i < synopTimeAry.length; i++){ - if(synopTimeAry[i] != null){ - System.out.println("synoptictime ="+synopTimeAry[i] ); - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - cal.setTimeInMillis(((Timestamp)synopTimeAry[i]).getTime()); - //String gmtTimeStr = String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS", cal); - timeLst.add(cal); - } - } - - return timeLst; - } - //static long totalRqTime=0; - /* - * Chin: Note: get NcUair based on stn is NOT supported yet!!! - * NEW: This function requests ONE station's all dataTypes data at once - * NSHARP is using this metod...dont remove it without consulting Nsharp developer - * - public static NcUairRecord[] getObservedSndNcUairData(Double lat, Double lon, String stn, String refTime){ - - PointDataQuery request = null; - PointDataContainer result = null; - NcUairRecord[] h5Records=null; - - List pickedH5Records = new ArrayList(); - try { - request = new PointDataQuery("ncuair"); - request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); - request.addParameter("location.latitude", String.valueOf(lat), "="); - request.addParameter("location.longitude", String.valueOf(lon), "="); - - request.addParameter("dataTime.refTime",refTime, "="); - request.addParameter("nil", String.valueOf(false), "="); - //Chin newQ request.addParameter("dataType", dataType, "="); - long t001 = System.currentTimeMillis(); - request.requestAllLevels(); - result = request.execute(); - long t002 = System.currentTimeMillis(); - //totalRqTime=totalRqTime+(t002-t001); - //System.out.println("getObservedSndNcUairData request at lat="+ lat+ " lon="+lon+" took "+(t002-t001)+"ms "); - if (result != null) { - //System.out.println("getObservedSndNcUairData: result is not null, getAllocatedSz= "+ result.getAllocatedSz()); - //System.out.println("getObservedSndNcUairData:getting "+dataType); - h5Records = NcUairToRecord.toNcUairRecords(result); - - if(h5Records!= null && h5Records.length > 0){ - // Chin: need to search through record list and keep one record for each record type - // If a record type comes with more than one record, then make decision to keep one based on - // its "issuetime" and "corr" columns in the ncuair table, then keep one record only - NcUairRecord orignalRd; - boolean addToList = true; - for(int i=0; i< h5Records.length; i++){ - orignalRd = h5Records[i]; - addToList = true; - for(NcUairRecord pickedRd: pickedH5Records){ - if(orignalRd.getDataType().equals( pickedRd.getDataType())){ - //the two records have same data type - //this records will either replace the one in list or be dropped - addToList = false; - if ((pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())<0) || - (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && orignalRd.getCorr()!=null && pickedRd.getCorr() != null && pickedRd.getCorr().compareTo(orignalRd.getCorr())<0 )|| - (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && orignalRd.getCorr()!=null && pickedRd.getCorr() == null) - ) - { - // decide to replace picked with original record, based on the following cases, in (priority) order - //case 1: original record has "later" issue time than picked record - //case 2: original record has "larger" correction "corr" than picked record - //case 3: original record has correction "corr", picked record does not have - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " ori= " + orignalRd.getDataURI()+ - // " picked="+ pickedRd.getDataURI()); - int pickedIndex = pickedH5Records.indexOf(pickedRd); - pickedH5Records.set(pickedIndex, orignalRd); - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " afterreplaced picked record ="+pickedH5Records.get(pickedIndex).getDataURI()); - - } - break; - } - } - if(addToList==true){ - // add this original record to picked list - pickedH5Records.add(orignalRd); - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " add ori to picked record ="+orignalRd.getDataURI()); - - } - } - - } - + dao = new CoreDao(DaoConfig.forClass(UAObs.class)); + try { + lUairRecords = (List) dao + .queryByCriteria(fields, values); + if (lUairRecords.size() > 0) { + pf.setStationLatitude((float) lUairRecords.get(0) + .getLatitude()); + pf.setStationLongitude((float) lUairRecords.get(0) + .getLongitude()); + pf.setStationElevation(lUairRecords.get(0).getElevation()); + if ((lUairRecords.get(0).getStationId() != null) + && (lUairRecords.get(0).getStationId().length() > 0)) { + pf.setStationNum(Integer.parseInt(lUairRecords.get(0) + .getStationId())); + } + pf.setStationId(lUairRecords.get(0).getStationName()); + pf.setFcsTime(lUairRecords.get(0).getDataTime() + .getRefTime().getTime()); + } + } catch (DataAccessLayerException e) { + // *System.out.println("obs sounding query exception"); + e.printStackTrace(); } - } catch (Exception e) { - e.printStackTrace(); } - if(pickedH5Records.size()>0){ - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " number of picked records = "+pickedH5Records.size()); - return pickedH5Records.toArray(new NcUairRecord[pickedH5Records.size()]); + return pf; + } + + public static NcSoundingStnInfoCollection getObservedSndStnInfoCol( + String obType, String selectedSndTime) { + NcSoundingStnInfoCollection stnInfoCol = new NcSoundingStnInfoCollection(); + List stationInfoList = new ArrayList(); + String queryStr, queryStr1; + Object[] rtnobjArray, rtnobjArray1; + CoreDao dao; + if (obType.equals(ObsSndType.BUFRUA.toString())) { + currentDBTblName = BURFUA_TBL_NAME; + queryStr = new String( + "Select Distinct latitude, longitude, id, stationname, elevation, reftime FROM " + + currentDBTblName + + " where reftime='" + + selectedSndTime + + "' AND latitude BETWEEN -89.9 AND 89.9 AND longitude BETWEEN -179.9 AND 179.9"); + queryStr1 = new String( + "Select Distinct latitude, longitude FROM " + + currentDBTblName + + " where reftime='" + + selectedSndTime + + "' AND latitude BETWEEN -89.9 AND 89.9 AND longitude BETWEEN -179.9 AND 179.9"); + dao = new CoreDao(DaoConfig.forClass(UAObs.class)); + + } else if (obType.equals(ObsSndType.NCUAIR.toString())) { + currentDBTblName = NCUAIR_TBL_NAME; + queryStr = new String( + "Select Distinct latitude, longitude, id, stationId, elevation, synoptictime FROM " + + currentDBTblName + + " where nil='FALSE' AND synoptictime='" + + selectedSndTime + + "' AND latitude BETWEEN -89.9 AND 89.9 AND longitude BETWEEN -179.9 AND 179.9"); + queryStr1 = new String( + "Select Distinct latitude, longitude FROM " + + currentDBTblName + + " where nil='FALSE' AND synoptictime='" + + selectedSndTime + + "' AND latitude BETWEEN -89.9 AND 89.9 AND longitude BETWEEN -179.9 AND 179.9"); + dao = new CoreDao(DaoConfig.forClass(NcUairRecord.class)); + } else { + return stnInfoCol; } - return null; - }*/ - /* - * Chin: Note: get NcUair based on stn is NOT supported yet!!! - * NEW: This function requests ALL stn with all dataTypes and returns all good ("corrected")records at once to improve performance - * Need performance improving by using Operand "in" for lat/lon pair, see getObservedSndNcUairDataByLatLonArrayNew() 02/15/2012 Chin - * - public static List getObservedSndNcUairDataByLatLonArray(double[][] latLonArray, String refTime){ - //List soundingProfileList= new ArrayList(); - PointDataQuery request = null; + rtnobjArray = dao.executeSQLQuery(queryStr); + + // *System.out.println("size of rtnobjArray " + rtnobjArray.length); + /* + * Object[] obj; for (int i =0; i 0) && (rtnobjArray.length > 0)) { + double lat, lon, elv; + String stnInfo; + + // System.out.println("queryAndMarkStn called mapresource = "+ + // nsharpMapResource.toString()); + // Note: A same station may have many reports and at some reports + // they dont provide elv and or stnid + // this implementation is "try" to make sure we get those info. + // If, all reports does not have elv or stnid, then we still can not + // report it. + for (Object element : rtnobjArray1) { + Object[] objArray1 = (Object[]) element; + Timestamp synoptictime = null; + stnInfo = ""; + elv = -999; + /* + * if(obType.equals(ObsSndType.NCUAIR.toString())){ lat = + * (Float)objArray1[0]; lon = (Float)objArray1[1]; } else{ + */ + lat = (Double) objArray1[0]; + lon = (Double) objArray1[1]; + // } + // System.out.println("lat = "+ lat +" lon= "+lon+"\n\n"); + for (Object element2 : rtnobjArray) { + Object[] objArray = (Object[]) element2; + if ((obType.equals(ObsSndType.NCUAIR.toString()) + && (lat == (Double) objArray[0]) && (lon == (Double) objArray[1])) + || ((obType.equals(ObsSndType.BUFRUA.toString())) + && (lat == (Double) objArray[0]) && (lon == (Double) objArray[1]))) { + // ids.add(((Integer)objArray[2])); + // System.out.println("id=" + (Integer)objArray[2]); + if (stnInfo == "") { + stnInfo = (String) objArray[3]; + } + if (elv == -999) { + if (obType.equals(ObsSndType.NCUAIR.toString())) { + elv = (Integer) objArray[4]; + } else if (obType.equals(ObsSndType.BUFRUA + .toString())) { + elv = (Integer) objArray[4]; + } + } + synoptictime = (Timestamp) objArray[5]; + } + + } + + NcSoundingStnInfo stn = stnInfoCol.getNewStnInfo(); + stn.setStnId(stnInfo); + stn.setStationLongitude(lon); + stn.setStationLatitude(lat); + stn.setStationElevation((float) elv); + stn.setSynopTime(synoptictime); + stationInfoList.add(stn); + // System.out.println("stn "+ stnInfo + " lon "+ lon + " lat "+ + // lat); + } + } + + NcSoundingStnInfo[] stationInfoAry = new NcSoundingStnInfo[stationInfoList + .size()]; + stnInfoCol.setStationInfo(stationInfoList.toArray(stationInfoAry)); + // *System.out.println("stn size = "+ + // stnInfoCol.getStationInfo().length); + return stnInfoCol; + } + + public static NcSoundingTimeLines getObservedSndTimeLine(String obType) { + Object[] synopTimeAry = null; + NcSoundingTimeLines tl = new NcSoundingTimeLines(); + String queryStr; + CoreDao dao; + if (obType.equals(ObsSndType.BUFRUA.toString())) { + currentDBTblName = BURFUA_TBL_NAME; + queryStr = new String("Select Distinct reftime FROM " + + currentDBTblName + " ORDER BY reftime DESC"); + dao = new CoreDao(DaoConfig.forClass(UAObs.class)); + + } else if (obType.equals(ObsSndType.NCUAIR.toString())) { + currentDBTblName = NCUAIR_TBL_NAME; + queryStr = new String("Select Distinct synoptictime FROM " + + currentDBTblName + + " where nil='FALSE' ORDER BY synoptictime DESC"); + dao = new CoreDao(DaoConfig.forClass(NcUairRecord.class)); + } else { + return tl; + } + synopTimeAry = dao.executeSQLQuery(queryStr); + // System.out.println("size of synoptictime " + synopTimeAry.length); + + // for(int i=0; i < synopTimeAry.length; i++){ + // if(synopTimeAry[i] != null) + // System.out.println("synoptictime ="+synopTimeAry[i] ); + // } + tl.setTimeLines(synopTimeAry); + + return tl; + } + + public static List getObservedSndTimeRangeList(String obType, + Calendar startTime, Calendar endTime) { + Object[] synopTimeAry = null; + String startTimeStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + .format(startTime.getTime()); + String endTimeStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + .format(endTime.getTime()); + String queryStr; + CoreDao dao; + if (obType.equals(ObsSndType.BUFRUA.toString())) { + currentDBTblName = BURFUA_TBL_NAME; + queryStr = new String("Select Distinct reftime FROM " + + currentDBTblName + " ORDER BY reftime DESC"); + dao = new CoreDao(DaoConfig.forClass(UAObs.class)); + + } else if (obType.equals(ObsSndType.NCUAIR.toString())) { + currentDBTblName = NCUAIR_TBL_NAME; + queryStr = new String("Select Distinct synoptictime FROM " + + currentDBTblName + + " where nil='FALSE' AND synoptictime >= '" + startTimeStr + + "' AND synoptictime <= '" + endTimeStr + + "' ORDER BY synoptictime DESC"); + dao = new CoreDao(DaoConfig.forClass(NcUairRecord.class)); + } else { + return null; + } + synopTimeAry = dao.executeSQLQuery(queryStr); + List timeLst = new ArrayList(); + // *System.out.println("size of synoptictime " + synopTimeAry.length); + + for (Object element : synopTimeAry) { + if (element != null) { + System.out.println("synoptictime =" + element); + Calendar cal = Calendar + .getInstance(TimeZone.getTimeZone("GMT")); + cal.setTimeInMillis(((Timestamp) element).getTime()); + // String gmtTimeStr = + // String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS", cal); + timeLst.add(cal); + } + } + + return timeLst; + } + + // static long totalRqTime=0; + /* + * Chin: Note: get NcUair based on stn is NOT supported yet!!! NEW: This + * function requests ONE station's all dataTypes data at once NSHARP is + * using this metod...dont remove it without consulting Nsharp developer + * + * public static NcUairRecord[] getObservedSndNcUairData(Double lat, Double + * lon, String stn, String refTime){ + * + * PointDataQuery request = null; PointDataContainer result = null; + * NcUairRecord[] h5Records=null; + * + * List pickedH5Records = new ArrayList(); try { + * request = new PointDataQuery("ncuair"); + * request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); + * request.addParameter("location.latitude", String.valueOf(lat), "="); + * request.addParameter("location.longitude", String.valueOf(lon), "="); + * + * request.addParameter("dataTime.refTime",refTime, "="); + * request.addParameter("nil", String.valueOf(false), "="); //Chin newQ + * request.addParameter("dataType", dataType, "="); long t001 = + * System.currentTimeMillis(); request.requestAllLevels(); result = + * request.execute(); long t002 = System.currentTimeMillis(); + * //totalRqTime=totalRqTime+(t002-t001); + * //System.out.println("getObservedSndNcUairData request at lat="+ lat+ + * " lon="+lon+" took "+(t002-t001)+"ms "); if (result != null) { + * //System.out + * .println("getObservedSndNcUairData: result is not null, getAllocatedSz= " + * + result.getAllocatedSz()); + * //System.out.println("getObservedSndNcUairData:getting "+dataType); + * h5Records = NcUairToRecord.toNcUairRecords(result); + * + * if(h5Records!= null && h5Records.length > 0){ // Chin: need to search + * through record list and keep one record for each record type // If a + * record type comes with more than one record, then make decision to keep + * one based on // its "issuetime" and "corr" columns in the ncuair table, + * then keep one record only NcUairRecord orignalRd; boolean addToList = + * true; for(int i=0; i< h5Records.length; i++){ orignalRd = h5Records[i]; + * addToList = true; for(NcUairRecord pickedRd: pickedH5Records){ + * if(orignalRd.getDataType().equals( pickedRd.getDataType())){ //the two + * records have same data type //this records will either replace the one in + * list or be dropped addToList = false; if + * ((pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())<0) || + * (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && + * orignalRd.getCorr()!=null && pickedRd.getCorr() != null && + * pickedRd.getCorr().compareTo(orignalRd.getCorr())<0 )|| + * (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && + * orignalRd.getCorr()!=null && pickedRd.getCorr() == null) ) { // decide to + * replace picked with original record, based on the following cases, in + * (priority) order //case 1: original record has "later" issue time than + * picked record //case 2: original record has "larger" correction "corr" + * than picked record //case 3: original record has correction "corr", + * picked record does not have + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " ori= " + orignalRd.getDataURI()+ // " picked="+ + * pickedRd.getDataURI()); int pickedIndex = + * pickedH5Records.indexOf(pickedRd); pickedH5Records.set(pickedIndex, + * orignalRd); //System.out.println("getObservedSndNcUairData: at lat="+ + * lat+ " lon="+lon+ + * " afterreplaced picked record ="+pickedH5Records.get(pickedIndex + * ).getDataURI()); + * + * } break; } } if(addToList==true){ // add this original record to picked + * list pickedH5Records.add(orignalRd); + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " add ori to picked record ="+orignalRd.getDataURI()); + * + * } } + * + * } + * + * } } catch (Exception e) { e.printStackTrace(); } + * if(pickedH5Records.size()>0){ + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " number of picked records = "+pickedH5Records.size()); + * return pickedH5Records.toArray(new NcUairRecord[pickedH5Records.size()]); + * } return null; } + */ + /* + * Chin: Note: get NcUair based on stn is NOT supported yet!!! NEW: This + * function requests ALL stn with all dataTypes and returns all good + * ("corrected")records at once to improve performance Need performance + * improving by using Operand "in" for lat/lon pair, see + * getObservedSndNcUairDataByLatLonArrayNew() 02/15/2012 Chin + * + * public static List + * getObservedSndNcUairDataByLatLonArray(double[][] latLonArray, String + * refTime){ //List soundingProfileList= new + * ArrayList(); PointDataQuery request = null; + * PointDataContainer result = null; //NcUairRecord[] h5Records=null; Double + * maxLat, minLat, maxLon, minLon, lat, lon; List + * returnedDbRecords = new ArrayList(); List + * finalRecordArrayList = new ArrayList(); + * maxLat=minLat=0.0; maxLon=minLon=0.0; for ( int i=0; i < + * latLonArray.length ; i++) { + * + * //make sure we have right precision... lat = latLonArray[i][0]; lon = + * latLonArray[i][1]; //latLonStr = latLonStr+ if(i==0){ maxLat=minLat=lat; + * maxLon=minLon=lon; } maxLat = Math.max(lat, maxLat); minLat = + * Math.min(lat, minLat); maxLon = Math.max(lon, maxLon); minLon = + * Math.min(lon, minLon); } try { request = new PointDataQuery("ncuair"); + * request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); + * + * request.addParameter("location.latitude", String.valueOf(minLat-0.1), + * ">="); request.addParameter("location.latitude", + * String.valueOf(maxLat+0.1), "<="); + * request.addParameter("location.longitude", String.valueOf(minLon-0.1), + * ">="); request.addParameter("location.longitude", + * String.valueOf(maxLon+0.1), "<="); + * request.addParameter("dataTime.refTime",refTime, "="); + * request.addParameter("nil", String.valueOf(false), "="); + * request.requestAllLevels(); result = request.execute(); //long t002 = + * System.currentTimeMillis(); //totalRqTime=totalRqTime+(t002-t001); + * //System.out.println("getObservedSndNcUairData request at lat="+ lat+ + * " lon="+lon+" took "+(t002-t001)+"ms total Qtime="+totalRqTime); if + * (result != null) { returnedDbRecords = + * NcUairToRecord.toNcUairRecordsList(result); + * + * if(returnedDbRecords!= null && returnedDbRecords.size() > 0){ + * + * //Chin: keep list of records for same station //search through all + * returned records and keep same staion's records in one list for ( int + * i=0; i < latLonArray.length ; i++) { //for each station lat = + * latLonArray[i][0]; lon = latLonArray[i][1]; NcUairRecord record; + * List stnRecords = new ArrayList(); + * //System.out + * .println("Before loop: Number of records in returnedDbRecords=" + * +returnedDbRecords.size()); for(int j=returnedDbRecords.size()-1; j >=0; + * j--){ record =returnedDbRecords.get(j); if(record.getLatitude() >= lat - + * 0.1 && record.getLatitude() <= lat + 0.1 && record.getLongitude() >= + * lon-0.1&& record.getLongitude() <= lon+0.1){ //remove this record from + * return list and add it to this stn list + * stnRecords.add(returnedDbRecords.remove(j)); } } if(stnRecords.size()>0){ + * //System.out.println("Before checking:stn lat="+lat + * +"stn record size="+stnRecords.size()); List + * pickedUairRecords = new ArrayList(); NcUairRecord + * orignalRd; boolean addToList = true; for(int ii=0; ii< stnRecords.size(); + * ii++){ orignalRd = stnRecords.get(ii); addToList = true; for(NcUairRecord + * pickedRd: pickedUairRecords){ if(orignalRd.getDataType().equals( + * pickedRd.getDataType())){ + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " find a same datatype="+pickedRd.getDataType()+ + * " orignalRd corr="+orignalRd.getCorr()+ // + * " pickedRd Corr="+pickedRd.getCorr()); + * + * //the two records have same data type //this records will either replace + * the one in list or be dropped addToList = false; if + * ((pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())<0) || + * (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && + * orignalRd.getCorr()!=null && pickedRd.getCorr() != null && + * pickedRd.getCorr().compareTo(orignalRd.getCorr())<0 )|| + * (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && + * orignalRd.getCorr()!=null && pickedRd.getCorr() == null) ) { // decide to + * replace picked with original record, based on the following cases, in + * (priority) order //case 1: original record has "later" issue time than + * picked record //case 2: original record has "larger" correction "corr" + * than picked record //case 3: original record has correction "corr", + * picked record does not have + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " ori= " + orignalRd.getDataURI()+ // " picked="+ + * pickedRd.getDataURI()); int pickedIndex = + * pickedUairRecords.indexOf(pickedRd); pickedUairRecords.set(pickedIndex, + * orignalRd); //System.out.println("getObservedSndNcUairData: at lat="+ + * lat+ " lon="+lon+ + * " afterreplaced picked record ="+pickedH5Records.get(pickedIndex + * ).getDataURI()); } break; } } if(addToList==true){ // add this original + * record to picked list pickedUairRecords.add(orignalRd); + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " add ori to picked record ="+orignalRd.getDataURI()); + * + * } } //pickedUairRecords.get(0).setNil(false); // set for special handling + * for its caller finalRecordArrayList.add(pickedUairRecords.toArray(new + * NcUairRecord[pickedUairRecords.size()])); + * //System.out.println("After checking: stn record size=" + * +pickedUairRecords.size()); }//Chin: If caller need all query stns + * returned (no matter there is no data), then we may need to add this + * code... else { //just add a null record array NcUairRecord dummy = new + * NcUairRecord(); dummy.setNil(true);// set for special handling for its + * caller SurfaceObsLocation location = new SurfaceObsLocation(); + * location.setLatitude(lat); location.setLongitude(lon); + * dummy.setLocation(location); + * + * NcUairRecord[] dummys= new NcUairRecord[1]; dummys[0] = dummy; + * finalRecordArrayList.add(dummys); }// } } } } catch (Exception e) { + * e.printStackTrace(); } return finalRecordArrayList; } + */ + /* + * Chin: Note: get NcUair based on stn is NOT supported yet!!! NEW: This + * function requests ALL stn with all dataTypes and returns all good + * ("corrected")records at once to improve performance Performance improved + * by using Operand "in" for lat/lon pair. 02/16/2012 Chin + * + * public static List + * getObservedSndNcUairDataByLatLonArrayNew(double[][] latLonArray, String + * refTime){ //List soundingProfileList= new + * ArrayList(); PointDataQuery request = null; + * PointDataContainer result = null; //NcUairRecord[] h5Records=null; Double + * lat, lon; List returnedDbRecords = new + * ArrayList(); List finalRecordArrayList = + * new ArrayList(); String latStr="", lonStr=""; for ( int + * i=0; i < latLonArray.length ; i++) { latStr = + * latStr+String.valueOf(latLonArray[i][0])+","; lonStr = + * lonStr+String.valueOf(latLonArray[i][1])+","; } + * latStr=latStr.substring(0, latStr.length()-1);//get rid of last "," + * lonStr=lonStr.substring(0, lonStr.length()-1);//get rid of last "," try { + * request = new PointDataQuery("ncuair"); + * request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); + * + * request.addParameter("location.latitude",latStr, "in"); + * request.addParameter("location.longitude", lonStr, "in"); + * request.addParameter("dataTime.refTime",refTime, "="); + * request.addParameter("nil", String.valueOf(false), "="); + * request.requestAllLevels(); result = request.execute(); //long t002 = + * System.currentTimeMillis(); //totalRqTime=totalRqTime+(t002-t001); + * //System.out.println("getObservedSndNcUairData request at lat="+ lat+ + * " lon="+lon+" took "+(t002-t001)+"ms total Qtime="+totalRqTime); if + * (result != null) { returnedDbRecords = + * NcUairToRecord.toNcUairRecordsList(result); + * + * if(returnedDbRecords!= null && returnedDbRecords.size() > 0){ + * System.out.println + * ("Before loop: Number of records in returnedDbRecords="+ + * returnedDbRecords.size()); //Chin: keep list of records for same station + * //search through all returned records and keep same staion's records in + * one list for ( int i=0; i < latLonArray.length ; i++) { //for each + * station lat = latLonArray[i][0]; lon = latLonArray[i][1]; NcUairRecord + * record; List stnRecords = new ArrayList(); + * + * for(int j=returnedDbRecords.size()-1; j >=0; j--){ record + * =returnedDbRecords.get(j); if(record.getLatitude() >= lat - 0.1 && + * record.getLatitude() <= lat + 0.1 && record.getLongitude() >= lon-0.1&& + * record.getLongitude() <= lon+0.1){ //remove this record from return list + * and add it to this stn list stnRecords.add(returnedDbRecords.remove(j)); + * } } if(stnRecords.size()>0){ + * //System.out.println("Before checking:stn lat="+lat + * +"stn record size="+stnRecords.size()); List + * pickedUairRecords = new ArrayList(); NcUairRecord + * orignalRd; boolean addToList = true; for(int ii=0; ii< stnRecords.size(); + * ii++){ orignalRd = stnRecords.get(ii); addToList = true; for(NcUairRecord + * pickedRd: pickedUairRecords){ if(orignalRd.getDataType().equals( + * pickedRd.getDataType())){ + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " find a same datatype="+pickedRd.getDataType()+ + * " orignalRd corr="+orignalRd.getCorr()+ // + * " pickedRd Corr="+pickedRd.getCorr()); + * + * //the two records have same data type //this records will either replace + * the one in list or be dropped addToList = false; if + * ((pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())<0) || + * (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && + * orignalRd.getCorr()!=null && pickedRd.getCorr() != null && + * pickedRd.getCorr().compareTo(orignalRd.getCorr())<0 )|| + * (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && + * orignalRd.getCorr()!=null && pickedRd.getCorr() == null) ) { // decide to + * replace picked with original record, based on the following cases, in + * (priority) order //case 1: original record has "later" issue time than + * picked record //case 2: original record has "larger" correction "corr" + * than picked record //case 3: original record has correction "corr", + * picked record does not have + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " ori= " + orignalRd.getDataURI()+ // " picked="+ + * pickedRd.getDataURI()); int pickedIndex = + * pickedUairRecords.indexOf(pickedRd); pickedUairRecords.set(pickedIndex, + * orignalRd); //System.out.println("getObservedSndNcUairData: at lat="+ + * lat+ " lon="+lon+ + * " afterreplaced picked record ="+pickedH5Records.get(pickedIndex + * ).getDataURI()); } break; } } if(addToList==true){ // add this original + * record to picked list pickedUairRecords.add(orignalRd); + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " add ori to picked record ="+orignalRd.getDataURI()); + * + * } } //pickedUairRecords.get(0).setNil(false); // set for special handling + * for its caller finalRecordArrayList.add(pickedUairRecords.toArray(new + * NcUairRecord[pickedUairRecords.size()])); + * //System.out.println("After checking: stn record size=" + * +pickedUairRecords.size()); } } } } } catch (Exception e) { + * e.printStackTrace(); } + * System.out.println(" Number of records in finalRecordArrayList=" + * +finalRecordArrayList.size()); return finalRecordArrayList; } + */ + /* + * Chin: Note: NEW: This function requests ALL stn with all dataTypes and + * returns all good ("corrected")records at once to improve performance + * Performance improved by using Operand "in" for stnId list. 02/16/2012 + * Chin + * + * public static List + * getObservedSndNcUairDataByStnIdArray(String[] stnIdArray, String + * refTime){ //List soundingProfileList= new + * ArrayList(); PointDataQuery request = null; + * PointDataContainer result = null; //NcUairRecord[] h5Records=null; String + * stnStr; List returnedDbRecords = new + * ArrayList(); List finalRecordArrayList = + * new ArrayList(); String stnIdListStr=""; for ( int i=0; i + * < stnIdArray.length ; i++) { + * + * if(i < stnIdArray.length -1){ stnIdListStr = + * stnIdListStr+stnIdArray[i]+","; } } try { request = new + * PointDataQuery("ncuair"); + * request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); + * + * request.addParameter("location.stationId",stnIdListStr, "in"); + * request.addParameter("dataTime.refTime",refTime, "="); + * request.addParameter("nil", String.valueOf(false), "="); + * request.requestAllLevels(); long t001 = System.currentTimeMillis(); + * result = request.execute(); long t002 = System.currentTimeMillis(); + * //totalRqTime=totalRqTime+(t002-t001); + * System.out.println("getObservedSndNcUairDataByStnIdArray request stn size=" + * + stnIdArray.length+ " took "+(t002-t001)+"ms"); + * + * if (result != null) { long t003 = System.currentTimeMillis(); + * returnedDbRecords = NcUairToRecord.toNcUairRecordsList(result); + * + * if(returnedDbRecords!= null && returnedDbRecords.size() > 0){ + * System.out.println( + * "getObservedSndNcUairDataByStnIdArray Before loop: Number of records in returnedDbRecords=" + * +returnedDbRecords.size()); //Chin: keep list of records for same station + * //search through all returned records and keep same staion's records in + * one list for ( int i=0; i < stnIdArray.length ; i++) { //for each station + * stnStr = stnIdArray[i]; NcUairRecord record; List + * stnRecords = new ArrayList(); + * + * for(int j=returnedDbRecords.size()-1; j >=0; j--){ record + * =returnedDbRecords.get(j); + * //System.out.println("requesting stn="+stnStr+" returned rd stnId=" + * +record.getStationId()+ " stnNum="+record.getStnum()); + * if(stnStr.equals(record.getStationId())){ //remove this record from + * return list and add it to this stn list + * stnRecords.add(returnedDbRecords.remove(j)); } } if(stnRecords.size()>0){ + * //System.out.println("Before checking:stn lat="+lat + * +"stn record size="+stnRecords.size()); List + * pickedUairRecords = new ArrayList(); NcUairRecord + * orignalRd; boolean addToList = true; for(int ii=0; ii< stnRecords.size(); + * ii++){ orignalRd = stnRecords.get(ii); addToList = true; for(NcUairRecord + * pickedRd: pickedUairRecords){ if(orignalRd.getDataType().equals( + * pickedRd.getDataType())){ + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " find a same datatype="+pickedRd.getDataType()+ + * " orignalRd corr="+orignalRd.getCorr()+ // + * " pickedRd Corr="+pickedRd.getCorr()); + * + * //the two records have same data type //this records will either replace + * the one in list or be dropped addToList = false; if + * ((pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())<0) || + * (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && + * orignalRd.getCorr()!=null && pickedRd.getCorr() != null && + * pickedRd.getCorr().compareTo(orignalRd.getCorr())<0 )|| + * (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && + * orignalRd.getCorr()!=null && pickedRd.getCorr() == null) ) { // decide to + * replace picked with original record, based on the following cases, in + * (priority) order //case 1: original record has "later" issue time than + * picked record //case 2: original record has "larger" correction "corr" + * than picked record //case 3: original record has correction "corr", + * picked record does not have + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " ori= " + orignalRd.getDataURI()+ // " picked="+ + * pickedRd.getDataURI()); int pickedIndex = + * pickedUairRecords.indexOf(pickedRd); pickedUairRecords.set(pickedIndex, + * orignalRd); //System.out.println("getObservedSndNcUairData: at lat="+ + * lat+ " lon="+lon+ + * " afterreplaced picked record ="+pickedH5Records.get(pickedIndex + * ).getDataURI()); } break; } } if(addToList==true){ // add this original + * record to picked list pickedUairRecords.add(orignalRd); + * //System.out.println("getObservedSndNcUairData: at lat="+ lat+ + * " lon="+lon+ " add ori to picked record ="+orignalRd.getDataURI()); + * + * } } //pickedUairRecords.get(0).setNil(false); // set for special handling + * for its caller finalRecordArrayList.add(pickedUairRecords.toArray(new + * NcUairRecord[pickedUairRecords.size()])); + * //System.out.println("After checking: stn record size=" + * +pickedUairRecords.size()); } } + * + * } long t004 = System.currentTimeMillis(); + * System.out.println(" sorting return records took "+(t004-t003)+"ms"); } } + * catch (Exception e) { e.printStackTrace(); } + * + * System.out.println( + * "getObservedSndNcUairDataByStnIdArray Number of records in finalRecordArrayList=" + * +finalRecordArrayList.size()); return finalRecordArrayList; } + */ + /* + * Chin: 2/21/2012 Using Lat/lon array OR StnId array, AND soundingTimeAry + * (fcst time array) as input. This function is to be generic for all cases. + * One and only one of latLonArray and stnIdArr should be not null and the + * other one should be null soundingTimeAry is a list of refer time (in + * Bufrua, only use refer time for query) should be not null Chin's note: + * NOT completed yet................. + */ + public static List getObservedSndBufruaDataGeneric( + Coordinate[] coordArray, String[] stnIdArray, + List soundingTimeStrList, long[] soundTimeLongArr) { + // List soundingProfileList= new + // ArrayList(); + PointDataQuery request = null; PointDataContainer result = null; - //NcUairRecord[] h5Records=null; - Double maxLat, minLat, maxLon, minLon, lat, lon; - List returnedDbRecords = new ArrayList(); - List finalRecordArrayList = new ArrayList(); - maxLat=minLat=0.0; - maxLon=minLon=0.0; - for ( int i=0; i < latLonArray.length ; i++) - { - - //make sure we have right precision... - lat = latLonArray[i][0]; - lon = latLonArray[i][1]; - //latLonStr = latLonStr+ - if(i==0){ - maxLat=minLat=lat; - maxLon=minLon=lon; - } - maxLat = Math.max(lat, maxLat); - minLat = Math.min(lat, minLat); - maxLon = Math.max(lon, maxLon); - minLon = Math.min(lon, minLon); - } - try { - request = new PointDataQuery("ncuair"); - request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); - - request.addParameter("location.latitude", String.valueOf(minLat-0.1), ">="); - request.addParameter("location.latitude", String.valueOf(maxLat+0.1), "<="); - request.addParameter("location.longitude", String.valueOf(minLon-0.1), ">="); - request.addParameter("location.longitude", String.valueOf(maxLon+0.1), "<="); - request.addParameter("dataTime.refTime",refTime, "="); - request.addParameter("nil", String.valueOf(false), "="); - request.requestAllLevels(); - result = request.execute(); - //long t002 = System.currentTimeMillis(); - //totalRqTime=totalRqTime+(t002-t001); - //System.out.println("getObservedSndNcUairData request at lat="+ lat+ " lon="+lon+" took "+(t002-t001)+"ms total Qtime="+totalRqTime); - if (result != null) { - returnedDbRecords = NcUairToRecord.toNcUairRecordsList(result); - - if(returnedDbRecords!= null && returnedDbRecords.size() > 0){ - - //Chin: keep list of records for same station - //search through all returned records and keep same staion's records in one list - for ( int i=0; i < latLonArray.length ; i++) - { - //for each station - lat = latLonArray[i][0]; - lon = latLonArray[i][1]; - NcUairRecord record; - List stnRecords = new ArrayList(); - //System.out.println("Before loop: Number of records in returnedDbRecords="+returnedDbRecords.size()); - for(int j=returnedDbRecords.size()-1; j >=0; j--){ - record =returnedDbRecords.get(j); - if(record.getLatitude() >= lat - 0.1 && record.getLatitude() <= lat + 0.1 && record.getLongitude() >= lon-0.1&& record.getLongitude() <= lon+0.1){ - //remove this record from return list and add it to this stn list - stnRecords.add(returnedDbRecords.remove(j)); - } - } - if(stnRecords.size()>0){ - //System.out.println("Before checking:stn lat="+lat +"stn record size="+stnRecords.size()); - List pickedUairRecords = new ArrayList(); - NcUairRecord orignalRd; - boolean addToList = true; - for(int ii=0; ii< stnRecords.size(); ii++){ - orignalRd = stnRecords.get(ii); - addToList = true; - for(NcUairRecord pickedRd: pickedUairRecords){ - if(orignalRd.getDataType().equals( pickedRd.getDataType())){ - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " find a same datatype="+pickedRd.getDataType()+ " orignalRd corr="+orignalRd.getCorr()+ - // " pickedRd Corr="+pickedRd.getCorr()); - - //the two records have same data type - //this records will either replace the one in list or be dropped - addToList = false; - if ((pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())<0) || - (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && orignalRd.getCorr()!=null && pickedRd.getCorr() != null && pickedRd.getCorr().compareTo(orignalRd.getCorr())<0 )|| - (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && orignalRd.getCorr()!=null && pickedRd.getCorr() == null) - ) - { - // decide to replace picked with original record, based on the following cases, in (priority) order - //case 1: original record has "later" issue time than picked record - //case 2: original record has "larger" correction "corr" than picked record - //case 3: original record has correction "corr", picked record does not have - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " ori= " + orignalRd.getDataURI()+ - // " picked="+ pickedRd.getDataURI()); - int pickedIndex = pickedUairRecords.indexOf(pickedRd); - pickedUairRecords.set(pickedIndex, orignalRd); - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " afterreplaced picked record ="+pickedH5Records.get(pickedIndex).getDataURI()); - } - break; - } - } - if(addToList==true){ - // add this original record to picked list - pickedUairRecords.add(orignalRd); - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " add ori to picked record ="+orignalRd.getDataURI()); - - } - } - //pickedUairRecords.get(0).setNil(false); // set for special handling for its caller - finalRecordArrayList.add(pickedUairRecords.toArray(new NcUairRecord[pickedUairRecords.size()])); - //System.out.println("After checking: stn record size="+pickedUairRecords.size()); - }//Chin: If caller need all query stns returned (no matter there is no data), then we may need to add this code... - else { - //just add a null record array - NcUairRecord dummy = new NcUairRecord(); - dummy.setNil(true);// set for special handling for its caller - SurfaceObsLocation location = new SurfaceObsLocation(); - location.setLatitude(lat); - location.setLongitude(lon); - dummy.setLocation(location); - - NcUairRecord[] dummys= new NcUairRecord[1]; - dummys[0] = dummy; - finalRecordArrayList.add(dummys); - }// - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return finalRecordArrayList; - }*/ - /* - * Chin: Note: get NcUair based on stn is NOT supported yet!!! - * NEW: This function requests ALL stn with all dataTypes and returns all good ("corrected")records at once to improve performance - * Performance improved by using Operand "in" for lat/lon pair. 02/16/2012 Chin - * - public static List getObservedSndNcUairDataByLatLonArrayNew(double[][] latLonArray, String refTime){ - //List soundingProfileList= new ArrayList(); - PointDataQuery request = null; - PointDataContainer result = null; - //NcUairRecord[] h5Records=null; - Double lat, lon; - List returnedDbRecords = new ArrayList(); - List finalRecordArrayList = new ArrayList(); - String latStr="", lonStr=""; - for ( int i=0; i < latLonArray.length ; i++) - { - latStr = latStr+String.valueOf(latLonArray[i][0])+","; - lonStr = lonStr+String.valueOf(latLonArray[i][1])+","; - } - latStr=latStr.substring(0, latStr.length()-1);//get rid of last "," - lonStr=lonStr.substring(0, lonStr.length()-1);//get rid of last "," - try { - request = new PointDataQuery("ncuair"); - request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); - - request.addParameter("location.latitude",latStr, "in"); - request.addParameter("location.longitude", lonStr, "in"); - request.addParameter("dataTime.refTime",refTime, "="); - request.addParameter("nil", String.valueOf(false), "="); - request.requestAllLevels(); - result = request.execute(); - //long t002 = System.currentTimeMillis(); - //totalRqTime=totalRqTime+(t002-t001); - //System.out.println("getObservedSndNcUairData request at lat="+ lat+ " lon="+lon+" took "+(t002-t001)+"ms total Qtime="+totalRqTime); - if (result != null) { - returnedDbRecords = NcUairToRecord.toNcUairRecordsList(result); - - if(returnedDbRecords!= null && returnedDbRecords.size() > 0){ - System.out.println("Before loop: Number of records in returnedDbRecords="+returnedDbRecords.size()); - //Chin: keep list of records for same station - //search through all returned records and keep same staion's records in one list - for ( int i=0; i < latLonArray.length ; i++) - { - //for each station - lat = latLonArray[i][0]; - lon = latLonArray[i][1]; - NcUairRecord record; - List stnRecords = new ArrayList(); - - for(int j=returnedDbRecords.size()-1; j >=0; j--){ - record =returnedDbRecords.get(j); - if(record.getLatitude() >= lat - 0.1 && record.getLatitude() <= lat + 0.1 && record.getLongitude() >= lon-0.1&& record.getLongitude() <= lon+0.1){ - //remove this record from return list and add it to this stn list - stnRecords.add(returnedDbRecords.remove(j)); - } - } - if(stnRecords.size()>0){ - //System.out.println("Before checking:stn lat="+lat +"stn record size="+stnRecords.size()); - List pickedUairRecords = new ArrayList(); - NcUairRecord orignalRd; - boolean addToList = true; - for(int ii=0; ii< stnRecords.size(); ii++){ - orignalRd = stnRecords.get(ii); - addToList = true; - for(NcUairRecord pickedRd: pickedUairRecords){ - if(orignalRd.getDataType().equals( pickedRd.getDataType())){ - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " find a same datatype="+pickedRd.getDataType()+ " orignalRd corr="+orignalRd.getCorr()+ - // " pickedRd Corr="+pickedRd.getCorr()); - - //the two records have same data type - //this records will either replace the one in list or be dropped - addToList = false; - if ((pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())<0) || - (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && orignalRd.getCorr()!=null && pickedRd.getCorr() != null && pickedRd.getCorr().compareTo(orignalRd.getCorr())<0 )|| - (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && orignalRd.getCorr()!=null && pickedRd.getCorr() == null) - ) - { - // decide to replace picked with original record, based on the following cases, in (priority) order - //case 1: original record has "later" issue time than picked record - //case 2: original record has "larger" correction "corr" than picked record - //case 3: original record has correction "corr", picked record does not have - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " ori= " + orignalRd.getDataURI()+ - // " picked="+ pickedRd.getDataURI()); - int pickedIndex = pickedUairRecords.indexOf(pickedRd); - pickedUairRecords.set(pickedIndex, orignalRd); - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " afterreplaced picked record ="+pickedH5Records.get(pickedIndex).getDataURI()); - } - break; - } - } - if(addToList==true){ - // add this original record to picked list - pickedUairRecords.add(orignalRd); - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " add ori to picked record ="+orignalRd.getDataURI()); - - } - } - //pickedUairRecords.get(0).setNil(false); // set for special handling for its caller - finalRecordArrayList.add(pickedUairRecords.toArray(new NcUairRecord[pickedUairRecords.size()])); - //System.out.println("After checking: stn record size="+pickedUairRecords.size()); - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - System.out.println(" Number of records in finalRecordArrayList="+finalRecordArrayList.size()); - return finalRecordArrayList; - }*/ - /* - * Chin: Note: - * NEW: This function requests ALL stn with all dataTypes and returns all good ("corrected")records at once to improve performance - * Performance improved by using Operand "in" for stnId list. 02/16/2012 Chin - * - public static List getObservedSndNcUairDataByStnIdArray(String[] stnIdArray, String refTime){ - //List soundingProfileList= new ArrayList(); - PointDataQuery request = null; - PointDataContainer result = null; - //NcUairRecord[] h5Records=null; - String stnStr; - List returnedDbRecords = new ArrayList(); - List finalRecordArrayList = new ArrayList(); - String stnIdListStr=""; - for ( int i=0; i < stnIdArray.length ; i++) - { - - if(i < stnIdArray.length -1){ - stnIdListStr = stnIdListStr+stnIdArray[i]+","; - } - } - try { - request = new PointDataQuery("ncuair"); - request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); - - request.addParameter("location.stationId",stnIdListStr, "in"); - request.addParameter("dataTime.refTime",refTime, "="); - request.addParameter("nil", String.valueOf(false), "="); - request.requestAllLevels(); - long t001 = System.currentTimeMillis(); - result = request.execute(); - long t002 = System.currentTimeMillis(); - //totalRqTime=totalRqTime+(t002-t001); - System.out.println("getObservedSndNcUairDataByStnIdArray request stn size="+ stnIdArray.length+ " took "+(t002-t001)+"ms"); - - if (result != null) { - long t003 = System.currentTimeMillis(); - returnedDbRecords = NcUairToRecord.toNcUairRecordsList(result); - - if(returnedDbRecords!= null && returnedDbRecords.size() > 0){ - System.out.println("getObservedSndNcUairDataByStnIdArray Before loop: Number of records in returnedDbRecords="+returnedDbRecords.size()); - //Chin: keep list of records for same station - //search through all returned records and keep same staion's records in one list - for ( int i=0; i < stnIdArray.length ; i++) - { - //for each station - stnStr = stnIdArray[i]; - NcUairRecord record; - List stnRecords = new ArrayList(); - - for(int j=returnedDbRecords.size()-1; j >=0; j--){ - record =returnedDbRecords.get(j); - //System.out.println("requesting stn="+stnStr+" returned rd stnId="+record.getStationId()+ " stnNum="+record.getStnum()); - if(stnStr.equals(record.getStationId())){ - //remove this record from return list and add it to this stn list - stnRecords.add(returnedDbRecords.remove(j)); - } - } - if(stnRecords.size()>0){ - //System.out.println("Before checking:stn lat="+lat +"stn record size="+stnRecords.size()); - List pickedUairRecords = new ArrayList(); - NcUairRecord orignalRd; - boolean addToList = true; - for(int ii=0; ii< stnRecords.size(); ii++){ - orignalRd = stnRecords.get(ii); - addToList = true; - for(NcUairRecord pickedRd: pickedUairRecords){ - if(orignalRd.getDataType().equals( pickedRd.getDataType())){ - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " find a same datatype="+pickedRd.getDataType()+ " orignalRd corr="+orignalRd.getCorr()+ - // " pickedRd Corr="+pickedRd.getCorr()); - - //the two records have same data type - //this records will either replace the one in list or be dropped - addToList = false; - if ((pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())<0) || - (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && orignalRd.getCorr()!=null && pickedRd.getCorr() != null && pickedRd.getCorr().compareTo(orignalRd.getCorr())<0 )|| - (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && orignalRd.getCorr()!=null && pickedRd.getCorr() == null) - ) - { - // decide to replace picked with original record, based on the following cases, in (priority) order - //case 1: original record has "later" issue time than picked record - //case 2: original record has "larger" correction "corr" than picked record - //case 3: original record has correction "corr", picked record does not have - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " ori= " + orignalRd.getDataURI()+ - // " picked="+ pickedRd.getDataURI()); - int pickedIndex = pickedUairRecords.indexOf(pickedRd); - pickedUairRecords.set(pickedIndex, orignalRd); - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " afterreplaced picked record ="+pickedH5Records.get(pickedIndex).getDataURI()); - } - break; - } - } - if(addToList==true){ - // add this original record to picked list - pickedUairRecords.add(orignalRd); - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " add ori to picked record ="+orignalRd.getDataURI()); - - } - } - //pickedUairRecords.get(0).setNil(false); // set for special handling for its caller - finalRecordArrayList.add(pickedUairRecords.toArray(new NcUairRecord[pickedUairRecords.size()])); - //System.out.println("After checking: stn record size="+pickedUairRecords.size()); - } - } - - } - long t004 = System.currentTimeMillis(); - System.out.println(" sorting return records took "+(t004-t003)+"ms"); - } - } catch (Exception e) { - e.printStackTrace(); - } - - System.out.println("getObservedSndNcUairDataByStnIdArray Number of records in finalRecordArrayList="+finalRecordArrayList.size()); - return finalRecordArrayList; - }*/ - /* - * Chin: 2/21/2012 - * Using Lat/lon array OR StnId array, AND soundingTimeAry (fcst time array) as input. - * This function is to be generic for all cases. - * One and only one of latLonArray and stnIdArr should be not null and the other one should be null - * soundingTimeAry is a list of refer time (in Bufrua, only use refer time for query) should be not null - * Chin's note: NOT completed yet................. - */ - public static List getObservedSndBufruaDataGeneric(Coordinate[] coordArray,String[] stnIdArray, List soundingTimeStrList, long[] soundTimeLongArr){ - //List soundingProfileList= new ArrayList(); - PointDataQuery request = null; - PointDataContainer result = null; - //NcUairRecord[] h5Records=null; - String stnStr=""; - Coordinate coord= new Coordinate();; + // NcUairRecord[] h5Records=null; + String stnStr = ""; + Coordinate coord = new Coordinate(); + ; List returnedDbRecords = new ArrayList(); UAObs[] returnedDbRecordArr; List finalRecordArrayList = new ArrayList(); boolean queryByStn; try { - request = new PointDataQuery("bufrua"); - request.setParameters(BufrUAPointDataTransform.MAN_PARAMS_LIST); - request.requestAllLevels(); - String d=""; - for (String timeStr: soundingTimeStrList){ - d = d+timeStr; - d= d+","; - } - d=d.substring(0, d.length()-1);//get rid of last "," - request.addParameter("dataTime.refTime",d, "in"); - if(coordArray != null){ - String latStr="", lonStr=""; - for ( int i=0; i < coordArray.length ; i++) - { - latStr = latStr+String.valueOf(coordArray[i].y)+","; - lonStr = lonStr+String.valueOf(coordArray[i].x)+","; - } - latStr=latStr.substring(0, latStr.length()-1);//get rid of last "," - lonStr=lonStr.substring(0, lonStr.length()-1);//get rid of last "," - request.addParameter("location.latitude",latStr, "in"); - request.addParameter("location.longitude", lonStr, "in"); - queryByStn = false; - } - else if(stnIdArray != null){ - String stnIdListStr=""; - for ( int i=0; i < stnIdArray.length ; i++) - { + request = new PointDataQuery("bufrua"); + request.setParameters(BufrUAPointDataTransform.MAN_PARAMS_LIST); + request.requestAllLevels(); + String d = ""; + for (String timeStr : soundingTimeStrList) { + d = d + timeStr; + d = d + ","; + } + d = d.substring(0, d.length() - 1);// get rid of last "," + request.addParameter("dataTime.refTime", d, "in"); + if (coordArray != null) { + String latStr = "", lonStr = ""; + for (Coordinate element : coordArray) { + latStr = latStr + String.valueOf(element.y) + ","; + lonStr = lonStr + String.valueOf(element.x) + ","; + } + latStr = latStr.substring(0, latStr.length() - 1);// get rid of + // last "," + lonStr = lonStr.substring(0, lonStr.length() - 1);// get rid of + // last "," + request.addParameter("location.latitude", latStr, "in"); + request.addParameter("location.longitude", lonStr, "in"); + queryByStn = false; + } else if (stnIdArray != null) { + String stnIdListStr = ""; + for (int i = 0; i < stnIdArray.length; i++) { - if(i < stnIdArray.length -1){ - stnIdListStr = stnIdListStr+stnIdArray[i]+","; - } - } - request.addParameter("location.stationId",stnIdListStr, "in"); - queryByStn= true; - } - else { - return finalRecordArrayList; - } - long t001 = System.currentTimeMillis(); - result = request.execute(); - long t002 = System.currentTimeMillis(); - //totalRqTime=totalRqTime+(t002-t001); - System.out.println("getObservedSndBufruaDataGeneric data query alone took "+(t002-t001)+"ms"); + if (i < (stnIdArray.length - 1)) { + stnIdListStr = stnIdListStr + stnIdArray[i] + ","; + } + } + request.addParameter("location.stationId", stnIdListStr, "in"); + queryByStn = true; + } else { + return finalRecordArrayList; + } + long t001 = System.currentTimeMillis(); + result = request.execute(); + long t002 = System.currentTimeMillis(); + // totalRqTime=totalRqTime+(t002-t001); + System.out + .println("getObservedSndBufruaDataGeneric data query alone took " + + (t002 - t001) + "ms"); - if (result != null) { - long t003 = System.currentTimeMillis(); - returnedDbRecordArr = BufrUAPointDataTransform.toUAObsRecords(result); - for(int i=0; i < returnedDbRecordArr.length; i++) - returnedDbRecords.add(returnedDbRecordArr[i]); - if(returnedDbRecords!= null && returnedDbRecords.size() > 0){ - System.out.println("getObservedSndBufruaDataGeneric Before loop: Number of records in returnedDbRecords="+returnedDbRecords.size()); - //Chin: keep list of records for same station - //search through all returned records and keep same staion's records in one list - int loopLen; - if(queryByStn== true){ - loopLen = stnIdArray.length; - } - else { - loopLen = coordArray.length; - } - UAObs record; - - for ( int i=0; i < loopLen ; i++) - { - //for each station - if(queryByStn== true){ - stnStr = stnIdArray[i]; - } - else{ - coord = coordArray[i]; - } - - List> stnRecordsList = new ArrayList>(); - for (long refT: soundTimeLongArr){ - List stnRecords = new ArrayList(); - stnRecordsList.add(stnRecords); - } - for(int j=returnedDbRecords.size()-1; j >=0; j--){ - record =returnedDbRecords.get(j); - boolean goodRecord = false; - //System.out.println("requesting stn="+stnStr+" returned rd stnId="+record.getStationId()+ " stnNum="+record.getStnum()); - if(queryByStn== true){ - if(stnStr.equals(record.getStationId()) ){ - //remove this record from return list and add it to this stn list - //stnRecords.add(returnedDbRecords.remove(j)); - goodRecord = true; - } - } - else { - //System.out.println("coor.x="+coord.x + " coor.y="+coord.y + " record lon="+record.getLongitude()+ " record lat="+ record.getLatitude()); - //Chin: for some unknown reason that record returned from DB with lat/lon extended with many digits - //For example, coor.x=-114.4 coor.y=32.85 record lon=-114.4000015258789 record lat=32.849998474121094 - //Therefore, do the following. - if( Math.abs(coord.x-record.getLongitude())< 0.01 && Math.abs(coord.y-record.getLatitude())<0.01){ - //remove this record from return list and add it to this stn list - //stnRecords.add(returnedDbRecords.remove(j)); - goodRecord = true; - } - } - if(goodRecord == true){ - for(int index=0; index< soundTimeLongArr.length; index++){ - long refT= soundTimeLongArr[index]; - if( refT == record.getDataTime().getRefTime().getTime()){ - stnRecordsList.get(index).add(returnedDbRecords.remove(j)); - } - } - } - } - for(List recordList:stnRecordsList){ - if(recordList.size()>0){ - - //pickedUairRecords.get(0).setNil(false); // set for special handling for its caller - finalRecordArrayList.add(recordList.toArray(new UAObs[recordList.size()])); - //System.out.println("getObservedSndNcUairDataGeneric Number of records in PF=" + pickedUairRecords.size()); - } - } - } + if (result != null) { + long t003 = System.currentTimeMillis(); + returnedDbRecordArr = BufrUAPointDataTransform + .toUAObsRecords(result); + for (UAObs element : returnedDbRecordArr) { + returnedDbRecords.add(element); + } + if ((returnedDbRecords != null) + && (returnedDbRecords.size() > 0)) { + System.out + .println("getObservedSndBufruaDataGeneric Before loop: Number of records in returnedDbRecords=" + + returnedDbRecords.size()); + // Chin: keep list of records for same station + // search through all returned records and keep same + // staion's records in one list + int loopLen; + if (queryByStn == true) { + loopLen = stnIdArray.length; + } else { + loopLen = coordArray.length; + } + UAObs record; - } - long t004 = System.currentTimeMillis(); - System.out.println(" sorting return records took "+(t004-t003)+"ms"); - } + for (int i = 0; i < loopLen; i++) { + // for each station + if (queryByStn == true) { + stnStr = stnIdArray[i]; + } else { + coord = coordArray[i]; + } + + List> stnRecordsList = new ArrayList>(); + for (long refT : soundTimeLongArr) { + List stnRecords = new ArrayList(); + stnRecordsList.add(stnRecords); + } + for (int j = returnedDbRecords.size() - 1; j >= 0; j--) { + record = returnedDbRecords.get(j); + boolean goodRecord = false; + // System.out.println("requesting stn="+stnStr+" returned rd stnId="+record.getStationId()+ + // " stnNum="+record.getStnum()); + if (queryByStn == true) { + if (stnStr.equals(record.getStationId())) { + // remove this record from return list and + // add it to this stn list + // stnRecords.add(returnedDbRecords.remove(j)); + goodRecord = true; + } + } else { + // System.out.println("coor.x="+coord.x + + // " coor.y="+coord.y + + // " record lon="+record.getLongitude()+ + // " record lat="+ record.getLatitude()); + // Chin: for some unknown reason that record + // returned from DB with lat/lon extended with + // many digits + // For example, coor.x=-114.4 coor.y=32.85 + // record lon=-114.4000015258789 record + // lat=32.849998474121094 + // Therefore, do the following. + if ((Math.abs(coord.x - record.getLongitude()) < 0.01) + && (Math.abs(coord.y + - record.getLatitude()) < 0.01)) { + // remove this record from return list and + // add it to this stn list + // stnRecords.add(returnedDbRecords.remove(j)); + goodRecord = true; + } + } + if (goodRecord == true) { + for (int index = 0; index < soundTimeLongArr.length; index++) { + long refT = soundTimeLongArr[index]; + if (refT == record.getDataTime() + .getRefTime().getTime()) { + stnRecordsList.get(index).add( + returnedDbRecords.remove(j)); + } + } + } + } + for (List recordList : stnRecordsList) { + if (recordList.size() > 0) { + + // pickedUairRecords.get(0).setNil(false); // + // set for special handling for its caller + finalRecordArrayList.add(recordList + .toArray(new UAObs[recordList.size()])); + // System.out.println("getObservedSndNcUairDataGeneric Number of records in PF=" + // + pickedUairRecords.size()); + } + } + } + + } + long t004 = System.currentTimeMillis(); + System.out.println(" sorting return records took " + + (t004 - t003) + "ms"); + } } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(); } - System.out.println("getObservedSndBufruaDataGeneric Number profiles (record[]s) in finalRecordArrayList="+finalRecordArrayList.size()); + System.out + .println("getObservedSndBufruaDataGeneric Number profiles (record[]s) in finalRecordArrayList=" + + finalRecordArrayList.size()); return finalRecordArrayList; - } - /* - * Chin: 2/21/2012 - * Using Lat/lon array OR StnId array, AND soundingTimeAry (fcst time array) as input. - * This function is to be generic for all cases. - * One and only one of latLonArray and stnIdArr should be not null and the other one should be null - * soundingTimeAry is a list of refer time (in NCUair, only use refer time for query) should be not null - * - */ - public static List getObservedSndNcUairDataGeneric(Coordinate[] coordArray,String[] stnIdArray, List soundingTimeStrList, long[] soundTimeLongArr){ - //List soundingProfileList= new ArrayList(); - PointDataQuery request = null; + } + + /* + * Chin: 2/21/2012 Using Lat/lon array OR StnId array, AND soundingTimeAry + * (fcst time array) as input. This function is to be generic for all cases. + * One and only one of latLonArray and stnIdArr should be not null and the + * other one should be null soundingTimeAry is a list of refer time (in + * NCUair, only use refer time for query) should be not null + */ + public static List getObservedSndNcUairDataGeneric( + Coordinate[] coordArray, String[] stnIdArray, + List soundingTimeStrList, long[] soundTimeLongArr) { + // List soundingProfileList= new + // ArrayList(); + PointDataQuery request = null; PointDataContainer result = null; - //NcUairRecord[] h5Records=null; - String stnStr=""; - Coordinate coord= new Coordinate();; + // NcUairRecord[] h5Records=null; + String stnStr = ""; + Coordinate coord = new Coordinate(); + ; List returnedDbRecords = new ArrayList(); List finalRecordArrayList = new ArrayList(); boolean queryByStn; try { - request = new PointDataQuery("ncuair"); - request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); - request.addParameter("nil", String.valueOf(false), "="); - request.requestAllLevels(); - String d=""; - for (String timeStr: soundingTimeStrList){ - d = d+timeStr; - d= d+","; - } - d=d.substring(0, d.length()-1);//get rid of last "," - request.addParameter("dataTime.refTime",d, "in"); - if(coordArray != null){ - String latStr="", lonStr=""; - for ( int i=0; i < coordArray.length ; i++) - { - latStr = latStr+String.valueOf(coordArray[i].y)+","; - lonStr = lonStr+String.valueOf(coordArray[i].x)+","; - } - latStr=latStr.substring(0, latStr.length()-1);//get rid of last "," - lonStr=lonStr.substring(0, lonStr.length()-1);//get rid of last "," - request.addParameter("location.latitude",latStr, "in"); - request.addParameter("location.longitude", lonStr, "in"); - queryByStn = false; - } - else if(stnIdArray != null){ - String stnIdListStr=""; - StringBuilder stringOfStnIds = new StringBuilder(); - for ( String thisStnId : stnIdArray ){ - stringOfStnIds.append(thisStnId); - stringOfStnIds.append(","); - } - stnIdListStr = stringOfStnIds.toString(); - //get rid of the last comma - stnIdListStr = stnIdListStr.substring(0, stnIdListStr.length() - 1 ); - - request.addParameter("location.stationId",stnIdListStr, "in"); - queryByStn= true; - } - else { - return finalRecordArrayList; - } - long t001 = System.currentTimeMillis(); - result = request.execute(); - long t002 = System.currentTimeMillis(); - //totalRqTime=totalRqTime+(t002-t001); - //System.out.println("getObservedSndNcUairDataGeneric data query alone took "+(t002-t001)+"ms"); + request = new PointDataQuery("ncuair"); + request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); + request.addParameter("nil", String.valueOf(false), "="); + request.requestAllLevels(); + String d = ""; + for (String timeStr : soundingTimeStrList) { + d = d + timeStr; + d = d + ","; + } + d = d.substring(0, d.length() - 1);// get rid of last "," + request.addParameter("dataTime.refTime", d, "in"); + if (coordArray != null) { + String latStr = "", lonStr = ""; + for (Coordinate element : coordArray) { + latStr = latStr + String.valueOf(element.y) + ","; + lonStr = lonStr + String.valueOf(element.x) + ","; + } + latStr = latStr.substring(0, latStr.length() - 1);// get rid of + // last "," + lonStr = lonStr.substring(0, lonStr.length() - 1);// get rid of + // last "," + request.addParameter("location.latitude", latStr, "in"); + request.addParameter("location.longitude", lonStr, "in"); + queryByStn = false; + } else if (stnIdArray != null) { + String stnIdListStr = ""; + StringBuilder stringOfStnIds = new StringBuilder(); + for (String thisStnId : stnIdArray) { + stringOfStnIds.append(thisStnId); + stringOfStnIds.append(","); + } + stnIdListStr = stringOfStnIds.toString(); + // get rid of the last comma + stnIdListStr = stnIdListStr.substring(0, + stnIdListStr.length() - 1); - if (result != null) { - long t003 = System.currentTimeMillis(); - returnedDbRecords = NcUairToRecord.toNcUairRecordsList(result); + request.addParameter("location.stationId", stnIdListStr, "in"); + queryByStn = true; + } else { + return finalRecordArrayList; + } + long t001 = System.currentTimeMillis(); + result = request.execute(); + long t002 = System.currentTimeMillis(); + // totalRqTime=totalRqTime+(t002-t001); + // System.out.println("getObservedSndNcUairDataGeneric data query alone took "+(t002-t001)+"ms"); - if(returnedDbRecords!= null && returnedDbRecords.size() > 0){ - //System.out.println("getObservedSndNcUairDataGeneric Before loop: Number of records in returnedDbRecords="+returnedDbRecords.size()); - //Chin: keep list of records for same station - //search through all returned records and keep same staion's records in one list - int loopLen; - if(queryByStn== true){ - loopLen = stnIdArray.length; - } - else { - loopLen = coordArray.length; - } - NcUairRecord record; - - for ( int i=0; i < loopLen ; i++) - { - //for each station - if(queryByStn== true){ - stnStr = stnIdArray[i]; - } - else{ - coord = coordArray[i]; - } - - List> stnRecordsList = new ArrayList>(); - for (long refT: soundTimeLongArr){ - //create empty List for each sounding time line - List stnRecords = new ArrayList(); - stnRecordsList.add(stnRecords); - } - for(int j=returnedDbRecords.size()-1; j >=0; j--){ - record =returnedDbRecords.get(j); - boolean goodRecord = false; - //System.out.println("requesting stn="+stnStr+" returned rd stnId="+record.getStationId()+ " stnNum="+record.getStnum()); - if(queryByStn== true){ - if(stnStr.equals(record.getStationId()) ){ - //remove this record from return list and add it to this stn list - //stnRecords.add(returnedDbRecords.remove(j)); - goodRecord = true; - } - } - else { - //System.out.println("coor.x="+coord.x + " coor.y="+coord.y + " record lon="+record.getLongitude()+ " record lat="+ record.getLatitude()); - //Chin: for some unknown reason that record returned from DB with lat/lon extended with many digits - //For example, coor.x=-114.4 coor.y=32.85 record lon=-114.4000015258789 record lat=32.849998474121094 - //Therefore, do the following. - if( Math.abs(coord.x-record.getLongitude())< 0.01 && Math.abs(coord.y-record.getLatitude())<0.01){ - //remove this record from return list and add it to this stn list - //stnRecords.add(returnedDbRecords.remove(j)); - goodRecord = true; - } - } - if(goodRecord == true){ - for(int index=0; index< soundTimeLongArr.length; index++){ - long refT= soundTimeLongArr[index]; - if( refT == record.getDataTime().getRefTime().getTime()){ - stnRecordsList.get(index).add(returnedDbRecords.remove(j)); - } - } - } - } - for(List recordList:stnRecordsList){ - if(recordList.size()>0){ - //System.out.println("Before checking:stn lat="+lat +"stn record size="+stnRecords.size()); - List pickedUairRecords = new ArrayList(); - NcUairRecord orignalRd; - boolean addToList = true; - for(int ii=0; ii< recordList.size(); ii++){ - orignalRd = recordList.get(ii); - addToList = true; - for(NcUairRecord pickedRd: pickedUairRecords){ - if(orignalRd.getDataType().equals( pickedRd.getDataType())){ - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " find a same datatype="+pickedRd.getDataType()+ " orignalRd corr="+orignalRd.getCorr()+ - // " pickedRd Corr="+pickedRd.getCorr()); - - //the two records have same data type - //this records will either replace the one in list or be dropped - addToList = false; - if ((pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())<0) || - (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && orignalRd.getCorr()!=null && pickedRd.getCorr() != null && pickedRd.getCorr().compareTo(orignalRd.getCorr())<0 )|| - (pickedRd.getIssueTime().compareTo(orignalRd.getIssueTime())==0 && orignalRd.getCorr()!=null && pickedRd.getCorr() == null) - ) - { - // decide to replace picked with original record, based on the following cases, in (priority) order - //case 1: original record has "later" issue time than picked record - //case 2: original record has "larger" correction "corr" than picked record - //case 3: original record has correction "corr", picked record does not have - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " ori= " + orignalRd.getDataURI()+ - // " picked="+ pickedRd.getDataURI()); - int pickedIndex = pickedUairRecords.indexOf(pickedRd); - pickedUairRecords.set(pickedIndex, orignalRd); - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " afterreplaced picked record ="+pickedH5Records.get(pickedIndex).getDataURI()); - } - break; - } - } - if(addToList==true){ - // add this original record to picked list - pickedUairRecords.add(orignalRd); - //System.out.println("getObservedSndNcUairData: at lat="+ lat+ " lon="+lon+ " add ori to picked record ="+orignalRd.getDataURI()); - - } - } - //pickedUairRecords.get(0).setNil(false); // set for special handling for its caller - finalRecordArrayList.add(pickedUairRecords.toArray(new NcUairRecord[pickedUairRecords.size()])); - //System.out.println("getObservedSndNcUairDataGeneric Number of records in PF=" + pickedUairRecords.size()); - } - } - } - - } - long t004 = System.currentTimeMillis(); - //System.out.println(" sorting return records took "+(t004-t003)+"ms"); - } - } catch (Exception e) { - e.printStackTrace(); - } - - //System.out.println("getObservedSndNcUairDataGeneric Number profiles (record[]s) in finalRecordArrayList="+finalRecordArrayList.size()); - return finalRecordArrayList; - } - /* - * This method query ONE station's specific one dataType data only - * - public static NcUairRecord getObservedSndNcUairData(Double lat, Double lon, String stn, String refTime, String dataType, SndQueryKeyType queryType){ - NcUairRecord effectRecord=null; - PointDataQuery request = null; - PointDataContainer result = null; - - try { - request = new PointDataQuery("ncuair"); - request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); - request.addParameter("location.latitude", String.valueOf(lat-0.1), ">="); - request.addParameter("location.latitude", String.valueOf(lat+0.1), "<="); - request.addParameter("location.longitude", String.valueOf(lon-0.1), ">="); - request.addParameter("location.longitude", String.valueOf(lon+0.1), "<="); - request.addParameter("dataTime.refTime",refTime, "="); - //System.out.println("getObservedSndNcUairData: lat="+lat+ " lon="+lon + " refTime="+refTime); - request.addParameter("nil", String.valueOf(false), "="); - request.addParameter("dataType", dataType, "="); - - request.requestAllLevels(); - result = request.execute(); if (result != null) { - //System.out.println("getObservedSndNcUairData: result is not null, getAllocatedSz= "+ result.getAllocatedSz()); - //System.out.println("getObservedSndNcUairData:getting "+dataType); - NcUairRecord[] h5Records = NcUairToRecord.toNcUairRecords(result); - //System.out.println("getObservedSndNcUairData: number of "+dataType+" records = "+h5Records.length); - - if(h5Records.length == 1){ - //effectRecord = h5Records[0]; - //System.out.println("getObservedSndNcUairData: real dataType =" + h5Records[0].getDataType()); - return h5Records[0]; - } - else if (h5Records.length > 1){ - // need to find out the latest corrected record - int lastCorrectedRecord=0; - String currentCorInd = ""; - Calendar curIssueTime = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - // set init time - curIssueTime.setTimeInMillis(0); - for(int i=0; i< h5Records.length; i++){ - //System.out.println("getObservedSndNcUairData2: real dataType =" + h5Records[i].getDataType()); - if( ( curIssueTime.compareTo(h5Records[i].getIssueTime())<0 ) || - (curIssueTime.compareTo(h5Records[i].getIssueTime())==0 && h5Records[i].getCorr()!= null && currentCorInd.compareTo(h5Records[i].getCorr()) < 0 ) - ) - { - currentCorInd = h5Records[i].getCorr(); - curIssueTime = h5Records[i].getIssueTime(); - lastCorrectedRecord = i; - //System.out.println("getObservedSndNcUairData: corr=" + h5Records[i].getCorr()); - } - } - //effectRecord = h5Records[lastCorrectedRecord]; - return h5Records[lastCorrectedRecord]; - } - + long t003 = System.currentTimeMillis(); + returnedDbRecords = NcUairToRecord.toNcUairRecordsList(result); + + if ((returnedDbRecords != null) + && (returnedDbRecords.size() > 0)) { + // System.out.println("getObservedSndNcUairDataGeneric Before loop: Number of records in returnedDbRecords="+returnedDbRecords.size()); + // Chin: keep list of records for same station + // search through all returned records and keep same + // staion's records in one list + int loopLen; + if (queryByStn == true) { + loopLen = stnIdArray.length; + } else { + loopLen = coordArray.length; + } + NcUairRecord record; + + for (int i = 0; i < loopLen; i++) { + // for each station + if (queryByStn == true) { + stnStr = stnIdArray[i]; + } else { + coord = coordArray[i]; + } + + List> stnRecordsList = new ArrayList>(); + for (long refT : soundTimeLongArr) { + // create empty List for each sounding + // time line + List stnRecords = new ArrayList(); + stnRecordsList.add(stnRecords); + } + for (int j = returnedDbRecords.size() - 1; j >= 0; j--) { + record = returnedDbRecords.get(j); + boolean goodRecord = false; + // System.out.println("requesting stn="+stnStr+" returned rd stnId="+record.getStationId()+ + // " stnNum="+record.getStnum()); + if (queryByStn == true) { + if (stnStr.equals(record.getStationId())) { + // remove this record from return list and + // add it to this stn list + // stnRecords.add(returnedDbRecords.remove(j)); + goodRecord = true; + } + } else { + // System.out.println("coor.x="+coord.x + + // " coor.y="+coord.y + + // " record lon="+record.getLongitude()+ + // " record lat="+ record.getLatitude()); + // Chin: for some unknown reason that record + // returned from DB with lat/lon extended with + // many digits + // For example, coor.x=-114.4 coor.y=32.85 + // record lon=-114.4000015258789 record + // lat=32.849998474121094 + // Therefore, do the following. + if ((Math.abs(coord.x - record.getLongitude()) < 0.01) + && (Math.abs(coord.y + - record.getLatitude()) < 0.01)) { + // remove this record from return list and + // add it to this stn list + // stnRecords.add(returnedDbRecords.remove(j)); + goodRecord = true; + } + } + if (goodRecord == true) { + for (int index = 0; index < soundTimeLongArr.length; index++) { + long refT = soundTimeLongArr[index]; + if (refT == record.getDataTime() + .getRefTime().getTime()) { + stnRecordsList.get(index).add( + returnedDbRecords.remove(j)); + } + } + } + } + for (List recordList : stnRecordsList) { + if (recordList.size() > 0) { + // System.out.println("Before checking:stn lat="+lat + // +"stn record size="+stnRecords.size()); + List pickedUairRecords = new ArrayList(); + NcUairRecord orignalRd; + boolean addToList = true; + for (int ii = 0; ii < recordList.size(); ii++) { + orignalRd = recordList.get(ii); + addToList = true; + for (NcUairRecord pickedRd : pickedUairRecords) { + if (orignalRd.getDataType().equals( + pickedRd.getDataType())) { + // System.out.println("getObservedSndNcUairData: at lat="+ + // lat+ " lon="+lon+ + // " find a same datatype="+pickedRd.getDataType()+ + // " orignalRd corr="+orignalRd.getCorr()+ + // " pickedRd Corr="+pickedRd.getCorr()); + + // the two records have same data + // type + // this records will either replace + // the one in list or be dropped + addToList = false; + if ((pickedRd + .getIssueTime() + .compareTo( + orignalRd + .getIssueTime()) < 0) + || ((pickedRd + .getIssueTime() + .compareTo( + orignalRd + .getIssueTime()) == 0) + && (orignalRd + .getCorr() != null) + && (pickedRd + .getCorr() != null) && (pickedRd + .getCorr() + .compareTo( + orignalRd + .getCorr()) < 0)) + || ((pickedRd + .getIssueTime() + .compareTo( + orignalRd + .getIssueTime()) == 0) + && (orignalRd + .getCorr() != null) && (pickedRd + .getCorr() == null))) { + // decide to replace picked with + // original record, based on the + // following cases, in + // (priority) order + // case 1: original record has + // "later" issue time than + // picked record + // case 2: original record has + // "larger" correction "corr" + // than picked record + // case 3: original record has + // correction "corr", picked + // record does not have + // System.out.println("getObservedSndNcUairData: at lat="+ + // lat+ " lon="+lon+ " ori= " + + // orignalRd.getDataURI()+ + // " picked="+ + // pickedRd.getDataURI()); + int pickedIndex = pickedUairRecords + .indexOf(pickedRd); + pickedUairRecords.set( + pickedIndex, orignalRd); + // System.out.println("getObservedSndNcUairData: at lat="+ + // lat+ " lon="+lon+ + // " afterreplaced picked record ="+pickedH5Records.get(pickedIndex).getDataURI()); + } + break; + } + } + if (addToList == true) { + // add this original record to picked + // list + pickedUairRecords.add(orignalRd); + // System.out.println("getObservedSndNcUairData: at lat="+ + // lat+ " lon="+lon+ + // " add ori to picked record ="+orignalRd.getDataURI()); + + } + } + // pickedUairRecords.get(0).setNil(false); // + // set for special handling for its caller + finalRecordArrayList + .add(pickedUairRecords + .toArray(new NcUairRecord[pickedUairRecords + .size()])); + // System.out.println("getObservedSndNcUairDataGeneric Number of records in PF=" + // + pickedUairRecords.size()); + } + } + } + + } + long t004 = System.currentTimeMillis(); + // System.out.println(" sorting return records took "+(t004-t003)+"ms"); } } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(); } - return effectRecord; - } -*/ - /* - * NOT used currently - * - * obsType: UAIR, TAMDAR or DROP, dataType: ALLDATA ONLY - */ - /*@SuppressWarnings("unchecked") - public static NcSoundingProfile getObservedSndData(int[] parentIds, String obType,String dataType) { - NcSoundingProfile pf = new NcSoundingProfile(); - //one StnPt represent one data time line - List soundLyLst = new ArrayList(); - NcSoundingLayer soundingLy; - soundLyLst.clear(); - - obType = ObsSndType.UAIR.toString(); // currently assume all uair sounding type - if(obType.equals(ObsSndType.UAIR.toString())){ - //*System.out.println("parentIds length = " + parentIds.length ); - for(int i=0; i fields = new ArrayList(); - List values = new ArrayList(); - List lObsLevels = null; - fields.add("id");// the record id field name defined in UairRecord - values.add(id); //testing 994872); - if(!dataType.equals(NcSoundingLayer.DataType.ALLDATA.toString()) && - !dataType.equals(NcSoundingLayer.DataType.MAXWIND_A.toString()) && - !dataType.equals(NcSoundingLayer.DataType.TROPOPAUSE_A.toString())){ - fields.add("dataType");// the record dataType field name defined in UairRecord - values.add(dataType); //testing "TTAA" - } - CoreDao dao = new CoreDao(DaoConfig.forClass(UairRecord.class)); - try { - lObsLevels = (List) dao.queryByCriteria(fields, values); - if(lObsLevels.size() > 0){ - //since we are using Records id to query uair table. lObsLevels.size() should always be one. - //*System.out.println("size of uairrecord " + lObsLevels.size()); - //*System.out.println("id ="+lObsLevels.get(0).getId() + " datauri=" +lObsLevels.get(0).getDataURI()); - //*System.out.println("size of ObsLevels ="+lObsLevels.get(0).getObsLevels().size() ); - //*System.out.println("size of maxWind ="+lObsLevels.get(0).getMaxWind().size() ); - //*System.out.println("size of Tropopause ="+lObsLevels.get(0).getTropopause().size() ); - if((lObsLevels.get(0).getObsLevels().size()>0) && - !dataType.equals(NcSoundingLayer.DataType.MAXWIND_A.toString()) && - !dataType.equals(NcSoundingLayer.DataType.TROPOPAUSE_A.toString())){ - java.util.Iterator it=lObsLevels.get(0).getObsLevels().iterator(); - while(it.hasNext()) - { - ObsLevels value=(ObsLevels)it.next(); - soundingLy = new NcSoundingLayer(); - soundingLy.setGeoHeight(value.getGeoHeight()); - soundingLy.setTemperature(value.getTemp()); - soundingLy.setPressure(value.getPressure()); - soundingLy.setWindDirection(value.getWindDirection()); - if ( value.getWindSpeed() != NcSoundingLayer.MISSING ) { - soundingLy.setWindSpeed((float)metersPerSecondToKnots.convert((float)value.getWindSpeed())); - } else { - soundingLy.setWindSpeed((float)value.getWindSpeed()); - } - soundingLy.setDewpoint(value.getDwpt()); - //*System.out.println("pressure :"+value.getPressure() + " temp:" + value.getTemp() + " H:"+value.getGeoHeight() ); - soundLyLst.add(soundingLy); - } - } - } - - if(lObsLevels.get(0).getMaxWind().size() >0 && - !dataType.equals(NcSoundingLayer.DataType.TROPOPAUSE_A.toString())){ - java.util.Iterator itWind=lObsLevels.get(0).getMaxWind().iterator(); - - while(itWind.hasNext()) - { - MaxWind value=(MaxWind)itWind.next(); - soundingLy = new NcSoundingLayer(); - soundingLy.setPressure(value.getPressure()); - soundingLy.setWindDirection(value.getWindDirection()); - if ( value.getWindSpeed() != NcSoundingLayer.MISSING ) { - soundingLy.setWindSpeed((float)metersPerSecondToKnots.convert((float)value.getWindSpeed())); - } else { - soundingLy.setWindSpeed((float)value.getWindSpeed()); - } - - soundLyLst.add(soundingLy); - } - } - - if(lObsLevels.get(0).getTropopause().size() >0 && - !dataType.equals(NcSoundingLayer.DataType.MAXWIND_A.toString())){ - java.util.Iterator it=lObsLevels.get(0).getTropopause().iterator(); - while(it.hasNext()) - { - Tropopause value=(Tropopause)it.next(); - soundingLy = new NcSoundingLayer(); - soundingLy.setTemperature(value.getTemp()); - soundingLy.setPressure(value.getPressure()); - soundingLy.setWindDirection(value.getWindDirection()); - if ( value.getWindSpeed() != NcSoundingLayer.MISSING ) { - soundingLy.setWindSpeed((float)metersPerSecondToKnots.convert((float)value.getWindSpeed())); - //*System.out.println("Tropopause pressure :"+value.getPressure() + " temp:" + value.getTemp()+" WD:" + value.getWindDirection() + " WS:"+(float)metersPerSecondToKnots.convert((float)value.getWindSpeed())); - - } else { - soundingLy.setWindSpeed((float)value.getWindSpeed()); - //*System.out.println("Tropopause pressure :"+value.getPressure() + " temp:" + value.getTemp()+" WD:" + value.getWindDirection() + " WS:"+(float)value.getWindSpeed()); - - } - - soundingLy.setDewpoint(value.getDwpt()); - - soundLyLst.add(soundingLy); - - } - } - } catch (DataAccessLayerException e) { - //*System.out.println("obs sounding query exception"); - //e.printStackTrace(); - } - - } - } - pf.setSoundingLyLst(soundLyLst); - return pf; - - } - */ - /* - * this api is provided for applications and for testing to retrieve observed bufruair data from PostgreSql DB & HDF5 - * dataType should use "enum DataType" defined in NcSoundingLayer.java - * Support "ALLDATA" data type only - */ - public static NcSoundingProfile getObservedSndBufruaAllData(Double lat, Double lon, String stn, long refTimeL, SndQueryKeyType queryType){ - Calendar refTimeCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - // for testing ...refTimeCal.setTimeInMillis(1276581600000L); - //refTimeCal.setTimeInMillis(refTime.getTime()); - refTimeCal.setTimeInMillis(refTimeL); - return getObservedSndBufruaAllData(lat, lon, stn, refTimeCal, queryType); - } - - /* - * this api is provided for applications and for testing to retrieve observed bufruair data from PostgreSql DB & HDF5 - * dataType should use "enum DataType" defined in NcSoundingLayer.java - * Support "ALLDATA" data type only - */ - public static NcSoundingProfile getObservedSndBufruaAllData(Double lat, Double lon, String stn, Calendar refTimeCal, SndQueryKeyType queryType){ - NcSoundingProfile pfAll= new NcSoundingProfile(); - List soundingLyLst, finalsoundingLyLst; - NcSoundingProfile pf = getObservedSndBufruaData(lat, lon, stn, refTimeCal, "TTAA", queryType); - pfAll.setStationElevation(pf.getStationElevation()); - finalsoundingLyLst = pf.getSoundingLyLst(); - soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, "TTBB", queryType).getSoundingLyLst(); - if (soundingLyLst.size() >= 0){ - finalsoundingLyLst.addAll(soundingLyLst); - } - soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, "TTCC", queryType).getSoundingLyLst(); - if (soundingLyLst.size() >= 0){ - finalsoundingLyLst.addAll(soundingLyLst); - } - soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, "TTDD", queryType).getSoundingLyLst(); - if (soundingLyLst.size() >= 0){ - finalsoundingLyLst.addAll(soundingLyLst); - } - //soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, "PPAA", queryType).getSoundingLyLst(); - //if (soundingLyLst.size() >= 0){ - // finalsoundingLyLst.addAll(soundingLyLst); - //} - soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, "PPBB", queryType).getSoundingLyLst(); - if (soundingLyLst.size() >= 0){ - finalsoundingLyLst.addAll(soundingLyLst); - } - //soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, "PPCC", queryType).getSoundingLyLst(); - //if (soundingLyLst.size() >= 0){ - // finalsoundingLyLst.addAll(soundingLyLst); - //} - soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, "PPDD", queryType).getSoundingLyLst(); - if (soundingLyLst.size() >= 0){ - finalsoundingLyLst.addAll(soundingLyLst); - } - soundingLyLst = getObservedSndBufruaData(lat, lon,stn, refTimeCal, "MAXWIND_A", queryType).getSoundingLyLst(); - if (soundingLyLst.size() >= 0){ - finalsoundingLyLst.addAll(soundingLyLst); - } - soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, "MAXWIND_C", queryType).getSoundingLyLst(); - if (soundingLyLst.size() >= 0){ - finalsoundingLyLst.addAll(soundingLyLst); - } - soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, "TROPOPAUSE_A", queryType).getSoundingLyLst(); - if (soundingLyLst.size() >= 0){ - finalsoundingLyLst.addAll(soundingLyLst); - } - soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, "TROPOPAUSE_C", queryType).getSoundingLyLst(); - if (soundingLyLst.size() >= 0){ - finalsoundingLyLst.addAll(soundingLyLst); - } - pfAll.setSoundingLyLst(finalsoundingLyLst); - return pfAll; - } + // System.out.println("getObservedSndNcUairDataGeneric Number profiles (record[]s) in finalRecordArrayList="+finalRecordArrayList.size()); + return finalRecordArrayList; + } /* - * this api is provided for applications and for testing to retrieve observed BufrUA data from PostgreSql DB and HDF5 - * dataType should use "enum DataType" defined in NcSoundingLayer.java - * Support all dataType except "ALLDATA" data type - * using either lat/lon, stnId or stnNum and validTime as key - * refTime is with unit of msec as input + * This method query ONE station's specific one dataType data only + * + * public static NcUairRecord getObservedSndNcUairData(Double lat, Double + * lon, String stn, String refTime, String dataType, SndQueryKeyType + * queryType){ NcUairRecord effectRecord=null; PointDataQuery request = + * null; PointDataContainer result = null; + * + * try { request = new PointDataQuery("ncuair"); + * request.setParameters(NcUairToRecord.MAN_PARAMS_LIST); + * request.addParameter("location.latitude", String.valueOf(lat-0.1), ">="); + * request.addParameter("location.latitude", String.valueOf(lat+0.1), "<="); + * request.addParameter("location.longitude", String.valueOf(lon-0.1), + * ">="); request.addParameter("location.longitude", + * String.valueOf(lon+0.1), "<="); + * request.addParameter("dataTime.refTime",refTime, "="); + * //System.out.println("getObservedSndNcUairData: lat="+lat+ " lon="+lon + + * " refTime="+refTime); request.addParameter("nil", String.valueOf(false), + * "="); request.addParameter("dataType", dataType, "="); + * + * request.requestAllLevels(); result = request.execute(); if (result != + * null) { //System.out.println( + * "getObservedSndNcUairData: result is not null, getAllocatedSz= "+ + * result.getAllocatedSz()); + * //System.out.println("getObservedSndNcUairData:getting "+dataType); + * NcUairRecord[] h5Records = NcUairToRecord.toNcUairRecords(result); + * //System + * .out.println("getObservedSndNcUairData: number of "+dataType+" records = " + * +h5Records.length); + * + * if(h5Records.length == 1){ //effectRecord = h5Records[0]; + * //System.out.println("getObservedSndNcUairData: real dataType =" + + * h5Records[0].getDataType()); return h5Records[0]; } else if + * (h5Records.length > 1){ // need to find out the latest corrected record + * int lastCorrectedRecord=0; String currentCorInd = ""; Calendar + * curIssueTime = Calendar.getInstance(TimeZone.getTimeZone("GMT")); // set + * init time curIssueTime.setTimeInMillis(0); for(int i=0; i< + * h5Records.length; i++){ + * //System.out.println("getObservedSndNcUairData2: real dataType =" + + * h5Records[i].getDataType()); if( ( + * curIssueTime.compareTo(h5Records[i].getIssueTime())<0 ) || + * (curIssueTime.compareTo(h5Records[i].getIssueTime())==0 && + * h5Records[i].getCorr()!= null && + * currentCorInd.compareTo(h5Records[i].getCorr()) < 0 ) ) { currentCorInd = + * h5Records[i].getCorr(); curIssueTime = h5Records[i].getIssueTime(); + * lastCorrectedRecord = i; + * //System.out.println("getObservedSndNcUairData: corr=" + + * h5Records[i].getCorr()); } } //effectRecord = + * h5Records[lastCorrectedRecord]; return h5Records[lastCorrectedRecord]; } + * + * } } catch (Exception e) { e.printStackTrace(); } return effectRecord; } */ - public static NcSoundingProfile getObservedSndBufruaData(Double lat, Double lon,String stn, long refTimeL, String dataType, SndQueryKeyType queryType){ - Calendar refTimeCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - // for testing ...refTimeCal.setTimeInMillis(1276581600000L); - //refTimeCal.setTimeInMillis(refTime.getTime()); - refTimeCal.setTimeInMillis(refTimeL); - return getObservedSndBufruaData(lat, lon, stn, refTimeCal, dataType, queryType); - } - - /* - * This API is provided for retrieving bufrUA data from PostgresSQL and HDF5 - * dataType should use "enum DataType" defined in NcSoundingLayer.java - * Support all dataType except "ALLDATA" data type - * using either lat/lon, stnId or stnNum and synopticTime as key - * reference time is with Calendar data type as input - * Chin's Note 2/28/2012:This API is used for bufrua query now. Should be replaced by - * getObservedSndBufruaDataGeneric() when point data query is implemented. + /* + * NOT used currently + * + * obsType: UAIR, TAMDAR or DROP, dataType: ALLDATA ONLY */ - @SuppressWarnings("unchecked") - public static NcSoundingProfile getObservedSndBufruaData(Double lat, Double lon, String stn, Calendar refTimeCal, String dataType,SndQueryKeyType queryType){ - //*System.out.println("getObservedSndBufruaData lat= " + lat+" lon="+lon+" refTime="+refTimeCal ); - //Timestamp refTime = new Timestamp(refTimeL); - //System.out.println("GMT ref time = "+ refTime.toGMTString()); - NcSoundingProfile pf = new NcSoundingProfile(); - List soundLyList = new ArrayList(); - if(dataType.equals(NcSoundingLayer.DataType.ALLDATA.toString())){ - //*System.out.println("request all data is not supported in this API"); - return pf; - } - else { - List fields = new ArrayList(); - List values = new ArrayList(); - List lUairRecords = null; - if(queryType==SndQueryKeyType.STNID){ - fields.add("stationName");// the stationName String field name defined in UAObs, dont be confused with UAIRRecord definition - values.add(stn); - } - else if(queryType==SndQueryKeyType.STNNUM){ - fields.add("location.stationId");// the location.stationId String field name defined in UAObs. dont be confused with UAIRRecord definition - values.add(stn); - } - else if(queryType==SndQueryKeyType.LATLON){ - fields.add("location.latitude");// the location.latitude field name defined in UAObs - values.add(lat); - fields.add("location.longitude");// the location.longitude field name defined in UAObs - values.add(lon); + /* + * @SuppressWarnings("unchecked") public static NcSoundingProfile + * getObservedSndData(int[] parentIds, String obType,String dataType) { + * NcSoundingProfile pf = new NcSoundingProfile(); //one StnPt represent one + * data time line List soundLyLst = new + * ArrayList(); NcSoundingLayer soundingLy; + * soundLyLst.clear(); + * + * obType = ObsSndType.UAIR.toString(); // currently assume all uair + * sounding type if(obType.equals(ObsSndType.UAIR.toString())){ + * //*System.out.println("parentIds length = " + parentIds.length ); for(int + * i=0; i + * fields = new ArrayList(); List values = new + * ArrayList(); List lObsLevels = null; + * fields.add("id");// the record id field name defined in UairRecord + * values.add(id); //testing 994872); + * if(!dataType.equals(NcSoundingLayer.DataType.ALLDATA.toString()) && + * !dataType.equals(NcSoundingLayer.DataType.MAXWIND_A.toString()) && + * !dataType.equals(NcSoundingLayer.DataType.TROPOPAUSE_A.toString())){ + * fields.add("dataType");// the record dataType field name defined in + * UairRecord values.add(dataType); //testing "TTAA" + * + * } CoreDao dao = new CoreDao(DaoConfig.forClass(UairRecord.class)); try { + * lObsLevels = (List) dao.queryByCriteria(fields, values); + * if(lObsLevels.size() > 0){ //since we are using Records id to query uair + * table. lObsLevels.size() should always be one. + * //*System.out.println("size of uairrecord " + lObsLevels.size()); + * //*System.out.println("id ="+lObsLevels.get(0).getId() + " datauri=" + * +lObsLevels.get(0).getDataURI()); + * //*System.out.println("size of ObsLevels =" + * +lObsLevels.get(0).getObsLevels().size() ); + * //*System.out.println("size of maxWind =" + * +lObsLevels.get(0).getMaxWind().size() ); + * //*System.out.println("size of Tropopause =" + * +lObsLevels.get(0).getTropopause().size() ); + * if((lObsLevels.get(0).getObsLevels().size()>0) && + * !dataType.equals(NcSoundingLayer.DataType.MAXWIND_A.toString()) && + * !dataType.equals(NcSoundingLayer.DataType.TROPOPAUSE_A.toString())){ + * java.util.Iterator + * it=lObsLevels.get(0).getObsLevels().iterator(); while(it.hasNext()) { + * ObsLevels value=(ObsLevels)it.next(); soundingLy = new NcSoundingLayer(); + * soundingLy.setGeoHeight(value.getGeoHeight()); + * soundingLy.setTemperature(value.getTemp()); + * soundingLy.setPressure(value.getPressure()); + * soundingLy.setWindDirection(value.getWindDirection()); if ( + * value.getWindSpeed() != NcSoundingLayer.MISSING ) { + * soundingLy.setWindSpeed + * ((float)metersPerSecondToKnots.convert((float)value.getWindSpeed())); } + * else { soundingLy.setWindSpeed((float)value.getWindSpeed()); } + * soundingLy.setDewpoint(value.getDwpt()); + * //*System.out.println("pressure :"+value.getPressure() + " temp:" + + * value.getTemp() + " H:"+value.getGeoHeight() ); + * soundLyLst.add(soundingLy); } } } + * + * if(lObsLevels.get(0).getMaxWind().size() >0 && + * !dataType.equals(NcSoundingLayer.DataType.TROPOPAUSE_A.toString())){ + * java.util.Iterator + * itWind=lObsLevels.get(0).getMaxWind().iterator(); + * + * while(itWind.hasNext()) { MaxWind value=(MaxWind)itWind.next(); + * soundingLy = new NcSoundingLayer(); + * soundingLy.setPressure(value.getPressure()); + * soundingLy.setWindDirection(value.getWindDirection()); if ( + * value.getWindSpeed() != NcSoundingLayer.MISSING ) { + * soundingLy.setWindSpeed + * ((float)metersPerSecondToKnots.convert((float)value.getWindSpeed())); } + * else { soundingLy.setWindSpeed((float)value.getWindSpeed()); } + * + * soundLyLst.add(soundingLy); } } + * + * if(lObsLevels.get(0).getTropopause().size() >0 && + * !dataType.equals(NcSoundingLayer.DataType.MAXWIND_A.toString())){ + * java.util.Iterator + * it=lObsLevels.get(0).getTropopause().iterator(); while(it.hasNext()) { + * Tropopause value=(Tropopause)it.next(); soundingLy = new + * NcSoundingLayer(); soundingLy.setTemperature(value.getTemp()); + * soundingLy.setPressure(value.getPressure()); + * soundingLy.setWindDirection(value.getWindDirection()); if ( + * value.getWindSpeed() != NcSoundingLayer.MISSING ) { + * soundingLy.setWindSpeed + * ((float)metersPerSecondToKnots.convert((float)value.getWindSpeed())); + * //*System.out.println("Tropopause pressure :"+value.getPressure() + + * " temp:" + value.getTemp()+" WD:" + value.getWindDirection() + + * " WS:"+(float + * )metersPerSecondToKnots.convert((float)value.getWindSpeed())); + * + * } else { soundingLy.setWindSpeed((float)value.getWindSpeed()); + * //*System.out.println("Tropopause pressure :"+value.getPressure() + + * " temp:" + value.getTemp()+" WD:" + value.getWindDirection() + + * " WS:"+(float)value.getWindSpeed()); + * + * } + * + * soundingLy.setDewpoint(value.getDwpt()); + * + * soundLyLst.add(soundingLy); + * + * } } } catch (DataAccessLayerException e) { + * //*System.out.println("obs sounding query exception"); + * //e.printStackTrace(); } + * + * } } pf.setSoundingLyLst(soundLyLst); return pf; + * + * } + */ + /* + * this api is provided for applications and for testing to retrieve + * observed bufruair data from PostgreSql DB & HDF5 dataType should use + * "enum DataType" defined in NcSoundingLayer.java Support "ALLDATA" data + * type only + */ + public static NcSoundingProfile getObservedSndBufruaAllData(Double lat, + Double lon, String stn, long refTimeL, SndQueryKeyType queryType) { + Calendar refTimeCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + // for testing ...refTimeCal.setTimeInMillis(1276581600000L); + // refTimeCal.setTimeInMillis(refTime.getTime()); + refTimeCal.setTimeInMillis(refTimeL); + return getObservedSndBufruaAllData(lat, lon, stn, refTimeCal, queryType); + } - } - else { - System.out.println("request query type "+ queryType+ " is not supported in this API" ); - return pf; - } - fields.add("dataTime.refTime");// the synoptic time field name defined in UAObs - //fields.add("validTime");// the synoptic time field name defined in UAObs - values.add(refTimeCal.getTime()); - fields.add("reportType");// the record dataType field name defined in UAObs - int intDataType = NcSoundingLayer.dataTypeMap.get(dataType); - values.add(intDataType); + /* + * this api is provided for applications and for testing to retrieve + * observed bufruair data from PostgreSql DB & HDF5 dataType should use + * "enum DataType" defined in NcSoundingLayer.java Support "ALLDATA" data + * type only + */ + public static NcSoundingProfile getObservedSndBufruaAllData(Double lat, + Double lon, String stn, Calendar refTimeCal, + SndQueryKeyType queryType) { + NcSoundingProfile pfAll = new NcSoundingProfile(); + List soundingLyLst, finalsoundingLyLst; + NcSoundingProfile pf = getObservedSndBufruaData(lat, lon, stn, + refTimeCal, "TTAA", queryType); + pfAll.setStationElevation(pf.getStationElevation()); + finalsoundingLyLst = pf.getSoundingLyLst(); + soundingLyLst = getObservedSndBufruaData(lat, lon, stn, refTimeCal, + "TTBB", queryType).getSoundingLyLst(); + if (soundingLyLst.size() >= 0) { + finalsoundingLyLst.addAll(soundingLyLst); + } + soundingLyLst = getObservedSndBufruaData(lat, lon, stn, refTimeCal, + "TTCC", queryType).getSoundingLyLst(); + if (soundingLyLst.size() >= 0) { + finalsoundingLyLst.addAll(soundingLyLst); + } + soundingLyLst = getObservedSndBufruaData(lat, lon, stn, refTimeCal, + "TTDD", queryType).getSoundingLyLst(); + if (soundingLyLst.size() >= 0) { + finalsoundingLyLst.addAll(soundingLyLst); + } + // soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, + // "PPAA", queryType).getSoundingLyLst(); + // if (soundingLyLst.size() >= 0){ + // finalsoundingLyLst.addAll(soundingLyLst); + // } + soundingLyLst = getObservedSndBufruaData(lat, lon, stn, refTimeCal, + "PPBB", queryType).getSoundingLyLst(); + if (soundingLyLst.size() >= 0) { + finalsoundingLyLst.addAll(soundingLyLst); + } + // soundingLyLst = getObservedSndBufruaData(lat, lon, stn,refTimeCal, + // "PPCC", queryType).getSoundingLyLst(); + // if (soundingLyLst.size() >= 0){ + // finalsoundingLyLst.addAll(soundingLyLst); + // } + soundingLyLst = getObservedSndBufruaData(lat, lon, stn, refTimeCal, + "PPDD", queryType).getSoundingLyLst(); + if (soundingLyLst.size() >= 0) { + finalsoundingLyLst.addAll(soundingLyLst); + } + soundingLyLst = getObservedSndBufruaData(lat, lon, stn, refTimeCal, + "MAXWIND_A", queryType).getSoundingLyLst(); + if (soundingLyLst.size() >= 0) { + finalsoundingLyLst.addAll(soundingLyLst); + } + soundingLyLst = getObservedSndBufruaData(lat, lon, stn, refTimeCal, + "MAXWIND_C", queryType).getSoundingLyLst(); + if (soundingLyLst.size() >= 0) { + finalsoundingLyLst.addAll(soundingLyLst); + } + soundingLyLst = getObservedSndBufruaData(lat, lon, stn, refTimeCal, + "TROPOPAUSE_A", queryType).getSoundingLyLst(); + if (soundingLyLst.size() >= 0) { + finalsoundingLyLst.addAll(soundingLyLst); + } + soundingLyLst = getObservedSndBufruaData(lat, lon, stn, refTimeCal, + "TROPOPAUSE_C", queryType).getSoundingLyLst(); + if (soundingLyLst.size() >= 0) { + finalsoundingLyLst.addAll(soundingLyLst); + } + pfAll.setSoundingLyLst(finalsoundingLyLst); + return pfAll; + } - //for (int i=0; i < fields.size(); i++) { - // System.out.println("field "+ fields.get(i) + " value "+ values.get(i)); - //} - CoreDao dao = new CoreDao(DaoConfig.forClass(UAObs.class)); - try { - lUairRecords = (List) dao.queryByCriteria(fields, values); - if(lUairRecords.size() > 0){ - //set pf data - //System.out.println("record size = "+ lUairRecords.size() + " reportType="+dataType); - - int lastCorrectedRecord=0; - String currentCorInd = ""; - - if(lUairRecords.size() > 1){ - for(int i=0; i< lUairRecords.size(); i++){ - //Since we are using lat/lon/refTime to query uair table. We may have several records returned for - // one query. It indicates there is a correction report, then we should use the newest one report. - // we compare corIndicator to find the latest record. - - if(lUairRecords.get(i).getCorIndicator()!= null && currentCorInd.compareTo(lUairRecords.get(i).getCorIndicator()) < 0){ - currentCorInd = lUairRecords.get(i).getCorIndicator(); - lastCorrectedRecord = i; - } - } - } - UAObs uairRecord = lUairRecords.get(lastCorrectedRecord); - pf.setStationLatitude((float)uairRecord.getLatitude()); - pf.setStationLongitude((float)uairRecord.getLongitude()); - pf.setStationElevation((float)uairRecord.getElevation()); - if(uairRecord.getStationId()!= null && uairRecord.getStationId().length()>0) - pf.setStationNum(Integer.parseInt(uairRecord.getStationId())); - pf.setStationId(uairRecord.getStationName()); - int hdfIndex = uairRecord.getIdx(); - if(hdfIndex >= 0) { - //System.out.println("selected stn lon= " + lon + - // " lat = "+ lat + " elv = "+ pf.getStationElevation() + " h5 table Y index ="+ hdfIndex); - BufrUADao uadao = new BufrUADao("bufrua"); - uairRecord.setPluginName("bufrua"); - File hdf5loc = uadao.getFullFilePath(uairRecord); - //System.out.println("hdf5 path = " + hdf5loc.getAbsolutePath()); - IDataStore dataStore = DataStoreFactory.getDataStore(hdf5loc); + /* + * this api is provided for applications and for testing to retrieve + * observed BufrUA data from PostgreSql DB and HDF5 dataType should use + * "enum DataType" defined in NcSoundingLayer.java Support all dataType + * except "ALLDATA" data type using either lat/lon, stnId or stnNum and + * validTime as key refTime is with unit of msec as input + */ + public static NcSoundingProfile getObservedSndBufruaData(Double lat, + Double lon, String stn, long refTimeL, String dataType, + SndQueryKeyType queryType) { + Calendar refTimeCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + // for testing ...refTimeCal.setTimeInMillis(1276581600000L); + // refTimeCal.setTimeInMillis(refTime.getTime()); + refTimeCal.setTimeInMillis(refTimeL); + return getObservedSndBufruaData(lat, lon, stn, refTimeCal, dataType, + queryType); + } - FloatDataRecord sfcPressurefloatData = (FloatDataRecord) dataStore.retrieve( - "/", "sfcPressure", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] sfcPressuredata = sfcPressurefloatData.getFloatData(); - if(sfcPressuredata.length>0) - pf.setSfcPress(sfcPressuredata[0]/100F); + /* + * This API is provided for retrieving bufrUA data from PostgresSQL and HDF5 + * dataType should use "enum DataType" defined in NcSoundingLayer.java + * Support all dataType except "ALLDATA" data type using either lat/lon, + * stnId or stnNum and synopticTime as key reference time is with Calendar + * data type as input Chin's Note 2/28/2012:This API is used for bufrua + * query now. Should be replaced by getObservedSndBufruaDataGeneric() when + * point data query is implemented. + */ + @SuppressWarnings("unchecked") + public static NcSoundingProfile getObservedSndBufruaData(Double lat, + Double lon, String stn, Calendar refTimeCal, String dataType, + SndQueryKeyType queryType) { + // *System.out.println("getObservedSndBufruaData lat= " + + // lat+" lon="+lon+" refTime="+refTimeCal ); + // Timestamp refTime = new Timestamp(refTimeL); + // System.out.println("GMT ref time = "+ refTime.toGMTString()); + NcSoundingProfile pf = new NcSoundingProfile(); + List soundLyList = new ArrayList(); + if (dataType.equals(NcSoundingLayer.DataType.ALLDATA.toString())) { + // *System.out.println("request all data is not supported in this API"); + return pf; + } else { + List fields = new ArrayList(); + List values = new ArrayList(); + List lUairRecords = null; + if (queryType == SndQueryKeyType.STNID) { + fields.add("stationName");// the stationName String field name + // defined in UAObs, dont be confused + // with UAIRRecord definition + values.add(stn); + } else if (queryType == SndQueryKeyType.STNNUM) { + fields.add("location.stationId");// the location.stationId + // String field name defined in + // UAObs. dont be confused with + // UAIRRecord definition + values.add(stn); + } else if (queryType == SndQueryKeyType.LATLON) { + fields.add("location.latitude");// the location.latitude field + // name defined in UAObs + values.add(lat); + fields.add("location.longitude");// the location.longitude field + // name defined in UAObs + values.add(lon); - NcSoundingLayer soundingLy; - //based on requested data type: - // get temp, dew point, pressure, wind u/v components, and height - //they are 2-D tables - if(dataType.equals(NcSoundingLayer.DataType.TTAA.toString()) || - dataType.equals(NcSoundingLayer.DataType.TTCC.toString())) - { - //get mandatory data size - IntegerDataRecord numManIntData = (IntegerDataRecord) dataStore.retrieve( - "/", "numMand", Request.buildYLineRequest(new int[] {hdfIndex})); - int[] sizes = numManIntData.getIntData(); - // sizes is a 1x1 2d table. Only first (0) element is valid. - if(sizes[0] >0){ - FloatDataRecord pressurefloatData = (FloatDataRecord) dataStore.retrieve( - "/", "prMan", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] pressuredata = pressurefloatData.getFloatData(); - FloatDataRecord temperaturefloatData = (FloatDataRecord) dataStore.retrieve( - "/", "tpMan", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] temperaturedata = temperaturefloatData.getFloatData(); - FloatDataRecord dewptfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "tdMan", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] dewptdata = dewptfloatData.getFloatData(); - FloatDataRecord windDfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "wdMan", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] windDdata = windDfloatData.getFloatData(); - FloatDataRecord windSfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "wsMan", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] windSdata = windSfloatData.getFloatData(); - FloatDataRecord htfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "htMan", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] htdata = htfloatData.getFloatData(); - for (int i=0; i0){ - FloatDataRecord pressurefloatData = (FloatDataRecord) dataStore.retrieve( - "/", "prSigT", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] pressuredata = pressurefloatData.getFloatData(); - FloatDataRecord temperaturefloatData = (FloatDataRecord) dataStore.retrieve( - "/", "tpSigT", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] temperaturedata = temperaturefloatData.getFloatData(); - FloatDataRecord dewptfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "tdSigT", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] dewptdata = dewptfloatData.getFloatData(); - for (int i=0; i0){ - FloatDataRecord htfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "htSigW", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] htdata = htfloatData.getFloatData(); - FloatDataRecord windDfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "wdSigW", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] windDdata = windDfloatData.getFloatData(); - FloatDataRecord windSfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "wsSigW", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] windSdata = windSfloatData.getFloatData(); - for (int i=0; i0){ - FloatDataRecord pressurefloatData = (FloatDataRecord) dataStore.retrieve( - "/", "prMaxW", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] pressuredata = pressurefloatData.getFloatData(); - FloatDataRecord windDfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "wdMaxW", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] windDdata = windDfloatData.getFloatData(); - FloatDataRecord windSfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "wsMaxW", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] windSdata = windSfloatData.getFloatData(); - for (int i=0; i0){ - FloatDataRecord pressurefloatData = (FloatDataRecord) dataStore.retrieve( - "/", "prTrop", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] pressuredata = pressurefloatData.getFloatData(); - FloatDataRecord temperaturefloatData = (FloatDataRecord) dataStore.retrieve( - "/", "tpTrop", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] temperaturedata = temperaturefloatData.getFloatData(); - FloatDataRecord dewptfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "tdTrop", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] dewptdata = dewptfloatData.getFloatData(); - FloatDataRecord windDfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "wdTrop", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] windDdata = windDfloatData.getFloatData(); - FloatDataRecord windSfloatData = (FloatDataRecord) dataStore.retrieve( - "/", "wsTrop", Request.buildYLineRequest(new int[] {hdfIndex})); - float[] windSdata = windSfloatData.getFloatData(); - for (int i=0; i) dao + .queryByCriteria(fields, values); + if (lUairRecords.size() > 0) { + // set pf data + // System.out.println("record size = "+ lUairRecords.size() + // + " reportType="+dataType); - } catch (Exception e) { - //*System.out.println("exception=" + e ); - e.printStackTrace(); - return pf; - } - //*System.out.println("sounding layer size = "+ soundLyList.size()); - - pf.setSoundingLyLst(soundLyList); + int lastCorrectedRecord = 0; + String currentCorInd = ""; - return pf; - - - } - } + if (lUairRecords.size() > 1) { + for (int i = 0; i < lUairRecords.size(); i++) { + // Since we are using lat/lon/refTime to query uair + // table. We may have several records returned for + // one query. It indicates there is a correction + // report, then we should use the newest one report. + // we compare corIndicator to find the latest + // record. + + if ((lUairRecords.get(i).getCorIndicator() != null) + && (currentCorInd.compareTo(lUairRecords + .get(i).getCorIndicator()) < 0)) { + currentCorInd = lUairRecords.get(i) + .getCorIndicator(); + lastCorrectedRecord = i; + } + } + } + UAObs uairRecord = lUairRecords.get(lastCorrectedRecord); + pf.setStationLatitude((float) uairRecord.getLatitude()); + pf.setStationLongitude((float) uairRecord.getLongitude()); + pf.setStationElevation(uairRecord.getElevation()); + if ((uairRecord.getStationId() != null) + && (uairRecord.getStationId().length() > 0)) { + pf.setStationNum(Integer.parseInt(uairRecord + .getStationId())); + } + pf.setStationId(uairRecord.getStationName()); + int hdfIndex = uairRecord.getIdx(); + if (hdfIndex >= 0) { + // System.out.println("selected stn lon= " + lon + + // " lat = "+ lat + " elv = "+ pf.getStationElevation() + // + " h5 table Y index ="+ hdfIndex); + BufrUADao uadao = new BufrUADao("bufrua"); + File hdf5loc = uadao.getFullFilePath(uairRecord); + // System.out.println("hdf5 path = " + + // hdf5loc.getAbsolutePath()); + IDataStore dataStore = DataStoreFactory + .getDataStore(hdf5loc); + + FloatDataRecord sfcPressurefloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "sfcPressure", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] sfcPressuredata = sfcPressurefloatData + .getFloatData(); + if (sfcPressuredata.length > 0) { + pf.setSfcPress(sfcPressuredata[0] / 100F); + } + + NcSoundingLayer soundingLy; + // based on requested data type: + // get temp, dew point, pressure, wind u/v components, + // and height + // they are 2-D tables + if (dataType.equals(NcSoundingLayer.DataType.TTAA + .toString()) + || dataType + .equals(NcSoundingLayer.DataType.TTCC + .toString())) { + // get mandatory data size + IntegerDataRecord numManIntData = (IntegerDataRecord) dataStore + .retrieve( + "/", + "numMand", + Request.buildYLineRequest(new int[] { hdfIndex })); + int[] sizes = numManIntData.getIntData(); + // sizes is a 1x1 2d table. Only first (0) element + // is valid. + if (sizes[0] > 0) { + FloatDataRecord pressurefloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "prMan", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] pressuredata = pressurefloatData + .getFloatData(); + FloatDataRecord temperaturefloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "tpMan", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] temperaturedata = temperaturefloatData + .getFloatData(); + FloatDataRecord dewptfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "tdMan", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] dewptdata = dewptfloatData + .getFloatData(); + FloatDataRecord windDfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "wdMan", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] windDdata = windDfloatData + .getFloatData(); + FloatDataRecord windSfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "wsMan", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] windSdata = windSfloatData + .getFloatData(); + FloatDataRecord htfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "htMan", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] htdata = htfloatData.getFloatData(); + for (int i = 0; i < sizes[0]; i++) { + soundingLy = new NcSoundingLayer(); + // if data is not available, dont convert it + // and just use default setting data + if (temperaturedata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setTemperature((float) kelvinToCelsius + .convert(temperaturedata[i])); + } + if (pressuredata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setPressure(pressuredata[i] / 100F); + } + if (windSdata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setWindSpeed((float) metersPerSecondToKnots + .convert(windSdata[i])); + } + soundingLy.setWindDirection(windDdata[i]); + if (dewptdata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setDewpoint((float) kelvinToCelsius + .convert(dewptdata[i])); + } + soundingLy.setGeoHeight(htdata[i]); + soundLyList.add(soundingLy); + } + // debug + // for(NcSoundingLayer ly: soundLyList){ + // System.out.println("Mandatory "+ dataType + + // ":: Pre= "+ly.getPressure()+ " Dew= "+ + // ly.getDewpoint()+ " T= "+ ly.getTemperature() + // + " WS= " + ly.getWindSpeed() + " WD= " + + // ly.getWindDirection()); + // } + } else { + System.out + .println("Mandatory data is not available! request data tye is " + + dataType); + } + } else if (dataType + .equals(NcSoundingLayer.DataType.TTBB + .toString()) + || dataType + .equals(NcSoundingLayer.DataType.TTDD + .toString())) { + // get significantT data size + IntegerDataRecord numSigtIntData = (IntegerDataRecord) dataStore + .retrieve( + "/", + "numSigT", + Request.buildYLineRequest(new int[] { hdfIndex })); + int[] sizes = numSigtIntData.getIntData(); + // sizes is a 1x1 2d table. Only first (0) element + // is valid. + if (sizes[0] > 0) { + FloatDataRecord pressurefloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "prSigT", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] pressuredata = pressurefloatData + .getFloatData(); + FloatDataRecord temperaturefloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "tpSigT", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] temperaturedata = temperaturefloatData + .getFloatData(); + FloatDataRecord dewptfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "tdSigT", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] dewptdata = dewptfloatData + .getFloatData(); + for (int i = 0; i < sizes[0]; i++) { + soundingLy = new NcSoundingLayer(); + // if data is not available, dont convert it + // and just use default setting data + if (temperaturedata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setTemperature((float) kelvinToCelsius + .convert(temperaturedata[i])); + } + if (pressuredata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setPressure(pressuredata[i] / 100F); + } + if (dewptdata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setDewpoint((float) kelvinToCelsius + .convert(dewptdata[i])); + } + soundLyList.add(soundingLy); + } + // for(NcSoundingLayer ly: soundLyList){ + // System.out.println("SigT "+ dataType + + // ":: Pre= "+ly.getPressure()+ " Dew= "+ + // ly.getDewpoint()+ " T= "+ + // ly.getTemperature()); + // } + } else { + System.out + .println("SigT data is not available! request data tye is " + + dataType); + } + + } else if (dataType + .equals(NcSoundingLayer.DataType.PPBB + .toString()) + || dataType + .equals(NcSoundingLayer.DataType.PPDD + .toString())) { + // get significantW data size + IntegerDataRecord numSigwIntData = (IntegerDataRecord) dataStore + .retrieve( + "/", + "numSigW", + Request.buildYLineRequest(new int[] { hdfIndex })); + int[] sizes = numSigwIntData.getIntData(); + // sizes is a 1x1 2d table. Only first (0) element + // is valid. + if (sizes[0] > 0) { + FloatDataRecord htfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "htSigW", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] htdata = htfloatData.getFloatData(); + FloatDataRecord windDfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "wdSigW", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] windDdata = windDfloatData + .getFloatData(); + FloatDataRecord windSfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "wsSigW", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] windSdata = windSfloatData + .getFloatData(); + for (int i = 0; i < sizes[0]; i++) { + soundingLy = new NcSoundingLayer(); + // if data is not available, dont convert it + // and just use default setting data + soundingLy.setGeoHeight(htdata[i]); + if (windSdata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setWindSpeed((float) metersPerSecondToKnots + .convert(windSdata[i])); + } + soundingLy.setWindDirection(windDdata[i]); + soundLyList.add(soundingLy); + } + // for(NcSoundingLayer ly: soundLyList){ + // System.out.println("SigW "+ dataType + + // ":: Ht= "+ly.getGeoHeight()+" WS= " + + // ly.getWindSpeed() + " WD= " + + // ly.getWindDirection()); + // } + } else { + System.out + .println("SigW data is not available! request data tye is " + + dataType); + } + } else if (dataType + .equals(NcSoundingLayer.DataType.MAXWIND_A + .toString()) + || dataType + .equals(NcSoundingLayer.DataType.MAXWIND_C + .toString())) { + // get max wind data size + IntegerDataRecord numMwndIntData = (IntegerDataRecord) dataStore + .retrieve( + "/", + "numMwnd", + Request.buildYLineRequest(new int[] { hdfIndex })); + int[] sizes = numMwndIntData.getIntData(); + // sizes is a 1x1 2d table. Only first (0) element + // is valid. + if (sizes[0] > 0) { + FloatDataRecord pressurefloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "prMaxW", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] pressuredata = pressurefloatData + .getFloatData(); + FloatDataRecord windDfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "wdMaxW", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] windDdata = windDfloatData + .getFloatData(); + FloatDataRecord windSfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "wsMaxW", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] windSdata = windSfloatData + .getFloatData(); + for (int i = 0; i < sizes[0]; i++) { + soundingLy = new NcSoundingLayer(); + // if data is not available, dont convert it + // and just use default setting data + if (pressuredata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setPressure(pressuredata[i] / 100F); + } + if (windSdata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setWindSpeed((float) metersPerSecondToKnots + .convert(windSdata[i])); + } + soundingLy.setWindDirection(windDdata[i]); + soundLyList.add(soundingLy); + } + // for(NcSoundingLayer ly: soundLyList){ + // System.out.println("MAXwind "+ dataType + + // ":: Pre= "+ly.getPressure()+ " WS= " + + // ly.getWindSpeed() + " WD= " + + // ly.getWindDirection()); + // } + } else { + System.out + .println("max wind data is not available! request data tye is " + + dataType); + } + } else if (dataType + .equals(NcSoundingLayer.DataType.TROPOPAUSE_A + .toString()) + || dataType + .equals(NcSoundingLayer.DataType.TROPOPAUSE_C + .toString())) { + // get troppause data size + IntegerDataRecord numTropIntData = (IntegerDataRecord) dataStore + .retrieve( + "/", + "numTrop", + Request.buildYLineRequest(new int[] { hdfIndex })); + int[] sizes = numTropIntData.getIntData(); + // sizes is a 1x1 2d table. Only first (0) element + // is valid. + if (sizes[0] > 0) { + FloatDataRecord pressurefloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "prTrop", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] pressuredata = pressurefloatData + .getFloatData(); + FloatDataRecord temperaturefloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "tpTrop", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] temperaturedata = temperaturefloatData + .getFloatData(); + FloatDataRecord dewptfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "tdTrop", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] dewptdata = dewptfloatData + .getFloatData(); + FloatDataRecord windDfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "wdTrop", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] windDdata = windDfloatData + .getFloatData(); + FloatDataRecord windSfloatData = (FloatDataRecord) dataStore + .retrieve( + "/", + "wsTrop", + Request.buildYLineRequest(new int[] { hdfIndex })); + float[] windSdata = windSfloatData + .getFloatData(); + for (int i = 0; i < sizes[0]; i++) { + soundingLy = new NcSoundingLayer(); + // if data is not available, dont convert it + // and just use default setting data + if (temperaturedata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setTemperature((float) kelvinToCelsius + .convert(temperaturedata[i])); + } + if (pressuredata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setPressure(pressuredata[i] / 100F); + } + if (windSdata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setWindSpeed((float) metersPerSecondToKnots + .convert(windSdata[i])); + } + soundingLy.setWindDirection(windDdata[i]); + if (dewptdata[i] != NcSoundingLayer.MISSING) { + soundingLy + .setDewpoint((float) kelvinToCelsius + .convert(dewptdata[i])); + } + soundLyList.add(soundingLy); + } + // debug + // for(NcSoundingLayer ly: soundLyList){ + // System.out.println("Troppause "+ dataType + + // ":: Pre= "+ly.getPressure()+ " Dew= "+ + // ly.getDewpoint()+ " T= "+ ly.getTemperature() + // + " WS= " + ly.getWindSpeed() + " WD= " + + // ly.getWindDirection()); + // } + } else { + System.out + .println("Troppause data is not available! request data tye is " + + dataType); + } + } + + } else { + System.out + .println("hdf5 index (idx) is less than 0!!!"); + return pf; + } + } else { + System.out + .println("buffrua (UAOb) record is not available!! request type " + + dataType); + return pf; + } + + } catch (Exception e) { + // *System.out.println("exception=" + e ); + e.printStackTrace(); + return pf; + } + // *System.out.println("sounding layer size = "+ + // soundLyList.size()); + + pf.setSoundingLyLst(soundLyList); + + return pf; + + } + } } diff --git a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/store/StorageUtils.java b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/store/StorageUtils.java index 2fd871e5d9..07ed6e5835 100644 --- a/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/store/StorageUtils.java +++ b/ncep/gov.noaa.nws.ncep.ui.pgen/src/gov/noaa/nws/ncep/ui/pgen/store/StorageUtils.java @@ -48,7 +48,8 @@ import com.raytheon.viz.core.mode.CAVEMode; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Apr 22, 2013 sgilbert Initial creation + * Apr 22, 2013 sgilbert Initial creation + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @@ -134,8 +135,9 @@ public class StorageUtils { if (promptOnOverwrite) { boolean answer = promptIfActivityExists(info); - if (!answer) + if (!answer) { return null; + } } try { @@ -208,7 +210,6 @@ public class StorageUtils { record.setStatus(info.getStatus()); record.setDataTime(new DataTime(info.getRefTime())); - record.setPluginName("pgen"); try { record.constructDataURI(); } catch (PluginException e1) { @@ -226,8 +227,9 @@ public class StorageUtils { DbQueryResponse response; try { response = (DbQueryResponse) ThriftClient.sendRequest(request); - if (response.getResults().size() == 1) + if (response.getResults().size() == 1) { exists = true; + } System.out.println("GOT RESPONSE BACK = " + response.getResults().size()); } catch (Exception e) { @@ -384,8 +386,9 @@ public class StorageUtils { if (promptOnOverwrite) { boolean answer = promptIfProductExists(dataURI, name); - if (!answer) + if (!answer) { return; + } } StoreDerivedProductRequest request = new StoreDerivedProductRequest( @@ -452,8 +455,9 @@ public class StorageUtils { "Cannot retrieve list of derived product names.", e); } for (String prod : products) { - if (prod.equals(name)) + if (prod.equals(name)) { return true; + } } return exists; diff --git a/ost/gov.noaa.nws.ost.edex.plugin.regionalsat/src/gov/noaa/nws/ost/edex/plugin/regionalsat/decoder/RegionalSatDecoder.java b/ost/gov.noaa.nws.ost.edex.plugin.regionalsat/src/gov/noaa/nws/ost/edex/plugin/regionalsat/decoder/RegionalSatDecoder.java index 59d2891382..0781ed88b5 100644 --- a/ost/gov.noaa.nws.ost.edex.plugin.regionalsat/src/gov/noaa/nws/ost/edex/plugin/regionalsat/decoder/RegionalSatDecoder.java +++ b/ost/gov.noaa.nws.ost.edex.plugin.regionalsat/src/gov/noaa/nws/ost/edex/plugin/regionalsat/decoder/RegionalSatDecoder.java @@ -53,13 +53,13 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * * SOFTWARE HISTORY * - * date Ticket# Engineer Description + * Date Ticket# Engineer Description * ----------- ---------- ----------- -------------------------- - * 7/15/11 tk Initial Creation - * - AWIPS2 Baseline Repository -------- - * 07/12/2012 798 jkorman Changed projection "magic" numbers - * 09/24/2012 1210 jkorman Modified the decode method to create the + * Jul 15, 2011 tk Initial Creation + * Jul 12, 2012 798 jkorman Changed projection "magic" numbers + * Sep 24, 2012 1210 jkorman Modified the decode method to create the * IDataRecord required by the SatelliteDao + * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * * * @author tk @@ -69,9 +69,9 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; public class RegionalSatDecoder extends AbstractDecoder { private static final IUFStatusHandler handler = UFStatus - .getHandler(AbstractDecoder.class); + .getHandler(AbstractDecoder.class); - private String traceId = ""; + private final String traceId = ""; private String source; @@ -91,7 +91,8 @@ public class RegionalSatDecoder extends AbstractDecoder { * alaskasat-ingest.xml and the dao and source members are set when the * RegionalSatDecoder instance is initialized: * - * @param data The file byte array data to be decoded. + * @param data + * The file byte array data to be decoded. * @return The decoded data record(s). */ public PluginDataObject[] decode(byte[] data) throws Exception { @@ -130,7 +131,7 @@ public class RegionalSatDecoder extends AbstractDecoder { if (entity != null) { String parsed = getCreatingEntity(entity); - if (parsed != null && parsed.length() > 0) { + if ((parsed != null) && (parsed.length() > 0)) { record.setCreatingEntity(parsed); } else { record.setCreatingEntity(entity); @@ -247,7 +248,7 @@ public class RegionalSatDecoder extends AbstractDecoder { ny = numRecords; // read the image as byte data and store as byte array - record.setMessageData((byte[]) netCdfFile.readSection("image") + record.setMessageData(netCdfFile.readSection("image") .get1DJavaArray(Class.forName("java.lang.Byte"))); // get the latitude of the first point, upper left corner @@ -315,15 +316,16 @@ public class RegionalSatDecoder extends AbstractDecoder { record.setCoverage(mapCoverage); record.setPersistenceTime(TimeTools.getSystemCalendar() .getTime()); - record.setPluginName("satellite"); record.constructDataURI(); // Set the data into the IDataRecord IDataRecord dataRec = SatelliteRecord.getDataRecord(record); - if(dataRec != null) { + if (dataRec != null) { record.setMessageData(dataRec); } else { - handler.error(String.format("Could not create datarecord for %s"), traceId); + handler.error( + String.format("Could not create datarecord for %s"), + traceId); record = null; } @@ -391,5 +393,5 @@ public class RegionalSatDecoder extends AbstractDecoder { public void setFilename(String file) { this.filename = file; } - + } diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/GFERecord.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/GFERecord.py index 4187bb40ae..8b8e150e1e 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/GFERecord.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/GFERecord.py @@ -87,10 +87,7 @@ class GFERecord(object): self.dataURI = dataURI def getPluginName(self): - return self.pluginName - - def setPluginName(self, pluginName): - self.pluginName = pluginName + return "gfe" def getDataTime(self): return self.dataTime diff --git a/rpms/build/i386/build.sh b/rpms/build/i386/build.sh index 02bb5cc53a..061f2699f7 100644 --- a/rpms/build/i386/build.sh +++ b/rpms/build/i386/build.sh @@ -390,12 +390,13 @@ if [ "${1}" = "-custom" ]; then # exit 1 #fi #buildRPM "awips2-httpd-pypies" - buildRPM "awips2-adapt-native" - buildRPM "awips2-hydroapps-shared" - #buildRPM "awips2-common-base" - #buildRPM "awips2-rcm" #buildRPM "awips2-ant" + #buildRPM "awips2-adapt-native" + #buildRPM "awips2-common-base" + #buildRPM "awips2-hydroapps-shared" #buildRPM "awips2-java" + buildRPM "awips2-python-dynamicserialize" + #buildRPM "awips2-rcm" #buildRPM "awips2-tools" exit 0 diff --git a/rpms/build/i386/build.sh-keep-10312013 b/rpms/build/i386/build.sh-keep-10312013 new file mode 100644 index 0000000000..061f2699f7 --- /dev/null +++ b/rpms/build/i386/build.sh-keep-10312013 @@ -0,0 +1,445 @@ +#!/bin/bash + +function buildRPM() +{ + # Arguments: + # ${1} == the name of the rpm. + lookupRPM "${1}" + if [ $? -ne 0 ]; then + echo "ERROR: '${1}' is not a recognized AWIPS II RPM." + exit 1 + fi + + /usr/bin/rpmbuild -ba \ + --define '_topdir %(echo ${AWIPSII_TOP_DIR})' \ + --define '_baseline_workspace %(echo ${WORKSPACE})' \ + --define '_uframe_eclipse %(echo ${UFRAME_ECLIPSE})' \ + --define '_awipscm_share %(echo ${AWIPSCM_SHARE})' \ + --define '_build_root %(echo ${AWIPSII_BUILD_ROOT})' \ + --define '_component_version %(echo ${AWIPSII_VERSION})' \ + --define '_component_release %(echo ${AWIPSII_RELEASE})' \ + --define '_component_build_date %(echo ${COMPONENT_BUILD_DATE})' \ + --define '_component_build_time %(echo ${COMPONENT_BUILD_TIME})' \ + --define '_component_build_system %(echo ${COMPONENT_BUILD_SYSTEM})' \ + --buildroot ${AWIPSII_BUILD_ROOT} \ + ${RPM_SPECIFICATION}/component.spec + if [ $? -ne 0 ]; then + echo "ERROR: Failed to build RPM ${1}." + exit 1 + fi + + return 0 +} + +# This script will build all of the 32-bit rpms. +# Ensure that we are on a machine with the correct architecture. + +architecture=`uname -i` +if [ ! "${architecture}" = "i386" ]; then + echo "ERROR: This build can only be performed on a 32-bit Operating System." + exit 1 +fi + +# Determine which directory we are running from. +path_to_script=`readlink -f $0` +dir=$(dirname $path_to_script) + +common_dir=`cd ${dir}/../common; pwd;` +if [ $? -ne 0 ]; then + echo "ERROR: Unable to find the common functions directory." + exit 1 +fi +# source the common functions. +source ${common_dir}/lookupRPM.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to source the common functions." + exit 1 +fi +source ${common_dir}/usage.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to source the common functions." + exit 1 +fi +source ${common_dir}/rpms.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to source the common functions." + exit 1 +fi +source ${common_dir}/systemInfo.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to retrieve the system information." + exit 1 +fi + +# prepare the build environment. +source ${dir}/buildEnvironment.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to prepare the build environment." + exit 1 +fi + +export LIGHTNING=true +# Determine if the optional '-nobinlightning' argument has been specified. +if [ "${2}" = "-nobinlightning" ]; then + LIGHTNING=false +fi + +if [ "${1}" = "-python-qpid" ]; then + buildRPM "awips2-python-qpid" + buildRPM "awips2-python" + buildRPM "awips2-python-cherrypy" + buildRPM "awips2-python-dynamicserialize" + buildRPM "awips2-python-nose" + buildRPM "awips2-python-numpy" + buildRPM "awips2-python-h5py" + buildRPM "awips2-python-jimporter" + buildRPM "awips2-python-matplotlib" + buildRPM "awips2-python-pil" + buildRPM "awips2-python-pmw" + buildRPM "awips2-python-pupynere" + buildRPM "awips2-python-scientific" + buildRPM "awips2-python-scipy" + buildRPM "awips2-python-tables" + buildRPM "awips2-python-thrift" + buildRPM "awips2-python-tpg" + buildRPM "awips2-python-ufpy" + buildRPM "awips2-python-werkzeug" + buildRPM "awips2-python-pygtk" + buildRPM "awips2-python-pycairo" + if [ $? -ne 0 ]; then + exit 1 + fi + + buildQPID + if [ $? -ne 0 ]; then + exit 1 + fi + + buildRPM "awips2-python-shapely" + + exit 0 +fi + +if [ "${1}" = "-postgres" ]; then + buildRPM "awips2-postgres" + buildRPM "awips2-database-server-configuration" + buildRPM "awips2-database-standalone-configuration" + buildRPM "awips2-database" + buildRPM "awips2-maps-database" + buildRPM "awips2-pgadmin3" + buildRPM "awips2-data.hdf5-gfe.climo" + buildRPM "awips2-data.hdf5-topo" + buildRPM "awips2-notification" + buildRPM "awips2-tools" + + exit 0 +fi + +if [ "${1}" = "-delta" ]; then + buildRPM "awips2-common-base" + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + buildEDEX + if [ $? -ne 0 ]; then + exit 1 + fi + + buildRPM "awips2-ncep-database" + buildRPM "awips2-gfesuite-client" + buildRPM "awips2-gfesuite-server" + buildRPM "awips2-python" + buildRPM "awips2-python-dynamicserialize" + buildRPM "awips2-python-ufpy" + buildRPM "awips2-python-qpid" + + buildRPM "awips2-adapt-native" + buildRPM "awips2-aviation-shared" + buildRPM "awips2-cli" + buildRPM "awips2-database" + buildRPM "awips2-database-server-configuration" + buildRPM "awips2-database-standalone-configuration" + buildRPM "awips2-data.hdf5-gfe.climo" + buildRPM "awips2-localapps-environment" + buildRPM "awips2-maps-database" + buildRPM "awips2-notification" + buildRPM "awips2-pypies" + buildRPM "awips2-data.hdf5-topo" + buildRPM "awips2-data.gfe" + buildRPM "awips2-rcm" + buildLocalizationRPMs + if [ $? -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + +if [ "${1}" = "-full" ]; then + buildRPM "awips2-common-base" + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + buildEDEX + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-python" + buildRPM "awips2-python-cherrypy" + buildRPM "awips2-python-dynamicserialize" + buildRPM "awips2-python-h5py" + buildRPM "awips2-python-jimporter" + buildRPM "awips2-python-matplotlib" + buildRPM "awips2-python-nose" + buildRPM "awips2-python-numpy" + buildRPM "awips2-python-pil" + buildRPM "awips2-python-pmw" + buildRPM "awips2-python-pupynere" + buildRPM "awips2-python-qpid" + buildRPM "awips2-python-scientific" + buildRPM "awips2-python-scipy" + buildRPM "awips2-python-tables" + buildRPM "awips2-python-thrift" + buildRPM "awips2-python-tpg" + buildRPM "awips2-python-ufpy" + buildRPM "awips2-python-werkzeug" + buildRPM "awips2-python-pygtk" + buildRPM "awips2-python-pycairo" + buildRPM "awips2-python-shapely" + + buildRPM "awips2-adapt-native" + buildRPM "awips2-aviation-shared" + buildRPM "awips2-cli" + buildRPM "awips2-database" + buildRPM "awips2-database-server-configuration" + buildRPM "awips2-database-standalone-configuration" + buildRPM "awips2-data.hdf5-gfe.climo" + buildRPM "awips2-data.gfe" + buildRPM "awips2-gfesuite-client" + buildRPM "awips2-gfesuite-server" + buildRPM "awips2-hydroapps-shared" + buildRPM "awips2-localapps-environment" + buildRPM "awips2-ncep-database" + buildRPM "awips2-maps-database" + buildRPM "awips2-notification" + buildRPM "awips2-pypies" + buildRPM "awips2-data.hdf5-topo" + buildRPM "awips2-rcm" + buildLocalizationRPMs + if [ $? -ne 0 ]; then + exit 1 + fi + + buildQPID + if [ $? -ne 0 ]; then + exit 1 + fi + + buildRPM "awips2-ant" + unpackHttpdPypies + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-httpd-pypies" + buildJava + buildRPM "awips2-groovy" + buildRPM "awips2-postgres" + buildRPM "awips2-pgadmin3" + buildRPM "awips2-tools" + buildRPM "awips2-openfire" + buildRPM "awips2-httpd-collaboration" + + exit 0 +fi + +if [ "${1}" = "-ade" ]; then + buildRPM "awips2-eclipse" + buildJava + buildRPM "awips2-ant" + buildRPM "awips2-python" + buildRPM "awips2-python-cherrypy" + buildRPM "awips2-python-dynamicserialize" + buildRPM "awips2-python-h5py" + buildRPM "awips2-python-jimporter" + buildRPM "awips2-python-matplotlib" + buildRPM "awips2-python-nose" + buildRPM "awips2-python-numpy" + buildRPM "awips2-python-pil" + buildRPM "awips2-python-pmw" + buildRPM "awips2-python-pupynere" + buildRPM "awips2-python-qpid" + buildRPM "awips2-python-scientific" + buildRPM "awips2-python-scipy" + buildRPM "awips2-python-tables" + buildRPM "awips2-python-thrift" + buildRPM "awips2-python-tpg" + buildRPM "awips2-python-ufpy" + buildRPM "awips2-python-werkzeug" + buildRPM "awips2-python-pygtk" + buildRPM "awips2-python-pycairo" + buildRPM "awips2-python-shapely" + buildQPID -ade + if [ $? -ne 0 ]; then + exit 1 + fi + + # Package the ade. + # Create the containing directory. + ade_directory="awips2-ade-${AWIPSII_VERSION}-${AWIPSII_RELEASE}" + if [ -d ${WORKSPACE}/${ade_directory} ]; then + rm -rf ${WORKSPACE}/${ade_directory} + if [ $? -ne 0 ]; then + exit 1 + fi + fi + mkdir -p ${WORKSPACE}/${ade_directory} + if [ $? -ne 0 ]; then + exit 1 + fi + + # Copy the rpms to the directory. + cp -v ${AWIPSII_TOP_DIR}/RPMS/i386/* \ + ${AWIPSII_TOP_DIR}/RPMS/noarch/* \ + ${WORKSPACE}/${ade_directory} + if [ $? -ne 0 ]; then + exit 1 + fi + + awips2_ade_directory="${WORKSPACE}/rpms/awips2.ade" + # Copy the install and uninstall script to the directory. + cp -v ${awips2_ade_directory}/tar.ade/scripts/*.sh \ + ${WORKSPACE}/${ade_directory} + if [ $? -ne 0 ]; then + exit 1 + fi + + # Tar the directory. + pushd . > /dev/null 2>&1 + cd ${WORKSPACE} + tar -cvf ${ade_directory}.tar ${ade_directory} + popd > /dev/null 2>&1 + RC=$? + if [ ${RC} -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + +if [ "${1}" = "-viz" ]; then + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + + exit 0 +fi + +if [ "${1}" = "-edex" ]; then + buildRPM "awips2-gfesuite-client" + buildRPM "awips2-gfesuite-server" + buildRPM "awips2-edex-environment" + buildEDEX + if [ $? -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + +if [ "${1}" = "-localization" ]; then + buildLocalizationRPMs + if [ $? -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + + +if [ "${1}" = "-qpid" ]; then + buildQPID + if [ $? -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + +if [ "${1}" = "-ldm" ]; then + buildRPM "awips2-ldm" + + exit 0 +fi + +if [ "${1}" = "-awips2" ]; then + buildRPM "awips2" + + exit 0 +fi + +# Use the custom flag for selecting specific rpms to build +if [ "${1}" = "-custom" ]; then + #unpackHttpdPypies + #if [ $? -ne 0 ]; then + # exit 1 + #fi + #buildRPM "awips2-httpd-pypies" + #buildRPM "awips2-ant" + #buildRPM "awips2-adapt-native" + #buildRPM "awips2-common-base" + #buildRPM "awips2-hydroapps-shared" + #buildRPM "awips2-java" + buildRPM "awips2-python-dynamicserialize" + #buildRPM "awips2-rcm" + #buildRPM "awips2-tools" + + exit 0 +fi + +if [ "${1}" = "-package" ]; then + repository_directory="awips2-repository-${AWIPSII_VERSION}-${AWIPSII_RELEASE}" + if [ -d ${WORKSPACE}/${repository_directory} ]; then + rm -rf ${WORKSPACE}/${repository_directory} + if [ $? -ne 0 ]; then + exit 1 + fi + fi + mkdir -p ${WORKSPACE}/${repository_directory}/${AWIPSII_VERSION}-${AWIPSII_RELEASE} + if [ $? -ne 0 ]; then + exit 1 + fi + + cp -r ${AWIPSII_TOP_DIR}/RPMS/* \ + ${WORKSPACE}/${repository_directory}/${AWIPSII_VERSION}-${AWIPSII_RELEASE} + if [ $? -ne 0 ]; then + exit 1 + fi + + rpms_directory="${WORKSPACE}/rpms" + comps_xml="${rpms_directory}/common/yum/arch.x86/comps.xml" + cp -v ${comps_xml} ${WORKSPACE}/${repository_directory} + if [ $? -ne 0 ]; then + exit 1 + fi + + pushd . > /dev/null + cd ${WORKSPACE} + tar -cvf ${repository_directory}.tar ${repository_directory} + RC=$? + popd > /dev/null + if [ ${RC} -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + + +usage +exit 0 diff --git a/tests/unit/com/raytheon/uf/common/archive/ArchiveConfigManagerTest.java b/tests/unit/com/raytheon/uf/common/archive/ArchiveConfigManagerTest.java index ce94df87df..8df168ed93 100644 --- a/tests/unit/com/raytheon/uf/common/archive/ArchiveConfigManagerTest.java +++ b/tests/unit/com/raytheon/uf/common/archive/ArchiveConfigManagerTest.java @@ -64,13 +64,13 @@ import com.raytheon.uf.common.util.TestUtil; * May 7, 2013 1965 bgonzale Initial creation. * Added additional test data for file newer than purge * time but in directory that is older than purge time. + * Aug 28, 2013 2299 rferrel purgeExpiredFromArchive now returns number of files purged. * * * * @author bgonzale * @version 1.0 */ - public class ArchiveConfigManagerTest { private static final String RAW = "Raw"; @@ -92,11 +92,13 @@ public class ArchiveConfigManagerTest { private final DateFormat mmFormat = new SimpleDateFormat("mm"); - private Collection archiveFiles = new ArrayList(); + private final Collection archiveFiles = new ArrayList(); - private Collection purgeFiles = new ArrayList(); + private final Collection purgeFiles = new ArrayList(); - private Collection archiveSelectedDisplays = new HashSet(); + private final Collection allFiles = new ArrayList(); + + private final Collection archiveSelectedDisplays = new HashSet(); private Calendar referenceCalendar; @@ -116,25 +118,9 @@ public class ArchiveConfigManagerTest { if (referenceCalendar == null) { setupTimes(); } - File testLocalization = TestUtil - .setupTestClassDir(PathManagerFactoryTest.class); PathManagerFactoryTest.initLocalization(); - // after setting up test localization get the production config files - // and copy them to the the test localization directory. - // utility/common_static/base/archive - File prodConfigDir = new File( - "../edexOsgi/com.raytheon.uf.edex.archive/utility"); - Collection configs = FileUtils.listFiles(prodConfigDir, - FileFilterUtils.trueFileFilter(), - FileFilterUtils.trueFileFilter()); - File destDir = new File(testLocalization, - "utility/common_static/base/archive"); - for (File srcConfig : configs) { - FileUtils.copyFileToDirectory(srcConfig, destDir); - } - ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); ArchiveConfig archiveProcessed = manager.getArchive(PROCESSED); @@ -154,6 +140,8 @@ public class ArchiveConfigManagerTest { // {6} file-dd // {7} file-kk // {8} file-mm + // {9} file-epochMS + // {10} file-epochSec // **** grib1 **** MessageFormat grib1Format_Raw = new MessageFormat( @@ -188,31 +176,64 @@ public class ArchiveConfigManagerTest { // **** binlightning **** MessageFormat binlightningFormat_Raw = new MessageFormat( "/binlightning/{0}{1}{2}/{3}/SFUS41_KWBC_{6}{7}{8}_22725485.nldn.{4}{5}{6}{7}"); - createTestFiles(binlightningFormat_Raw, archiveRaw, "Misc", + createTestFiles(binlightningFormat_Raw, archiveRaw, "Observation", false, archiveStart, archiveEnd); MessageFormat binlightningFormat_Processed = new MessageFormat( "/binlightning/binlightning-{4}-{5}-{6}-{7}.h5"); - createTestFiles(binlightningFormat_Processed, archiveProcessed, "Misc", - false, archiveStart, archiveEnd); + createTestFiles(binlightningFormat_Processed, archiveProcessed, + "Observation", false, archiveStart, archiveEnd); // **** bufrsigwx **** MessageFormat bufrsigwxFormat_Raw = new MessageFormat( "/bufrsigwx/{0}{1}{2}/{3}/JUWE96_KKCI_{6}{7}{8}_31368878.bufr.{4}{5}{6}{7}"); - createTestFiles(bufrsigwxFormat_Raw, archiveRaw, "Observation", false, + createTestFiles(bufrsigwxFormat_Raw, archiveRaw, "Products", false, archiveStart, archiveEnd); MessageFormat bufrsigwxFormat_Processed = new MessageFormat( "/bufrsigwx/SWH/sigwxCAT-{4}-{5}-{6}-{7}.h5"); createTestFiles(bufrsigwxFormat_Processed, archiveProcessed, - "Observation", false, archiveStart, archiveEnd); + "Products", false, archiveStart, archiveEnd); + + // *** manual **** + MessageFormat manualFormat_Raw1 = new MessageFormat( + "manual/mpe/ZETA98_BDHRMOSAIC{4}{5}{6}{7}{8}z_15180450.grib"); + createTestFiles(manualFormat_Raw1, archiveRaw, "Local", false, + archiveStart, archiveEnd); + MessageFormat manualFormat_Raw2 = new MessageFormat( + "manual/mpe/ZETA98_{0}{1}{2}{3}z_16122536.grib"); + createTestFiles(manualFormat_Raw2, archiveRaw, "Local", false, + archiveStart, archiveEnd); + MessageFormat manualFormat_RawE1 = new MessageFormat( + "manual/000-KOUNVFTOUN-NXUS98-KOUN-13{5}{6}{7}{8}-___-{10}"); + createTestFiles(manualFormat_RawE1, archiveRaw, "Local", false, + archiveStart, archiveEnd); + MessageFormat manualFormat_RawE2 = new MessageFormat( + "manual/AQIOUN.wan{10}"); + createTestFiles(manualFormat_RawE2, archiveRaw, "Local", false, + archiveStart, archiveEnd); + MessageFormat manualFormat_Raw3 = new MessageFormat( + "manual/wrf4nssl_{0}{1}{2}{3}.f00.OUN_subset.16122536"); + createTestFiles(manualFormat_Raw3, archiveRaw, "Local", false, + archiveStart, archiveEnd); + MessageFormat manualFormat_Raw4 = new MessageFormat( + "manual/ZETA98.LAPS.{4}{5}{6}_{7}{8}"); + createTestFiles(manualFormat_Raw4, archiveRaw, "Local", false, + archiveStart, archiveEnd); + + // **** manual using file last modified time. + createModTestFiles("manual/FOUS74KTUA.16130407.100", + "manual/FOUS74KTUA.16130407.200", + "manual/FOUS74KTUA.16130407.300", + "manual/FOUS74KTUA.16130407.400", archiveRaw, "Local", false, + archiveStart, archiveEnd); // create test archive data dir archiveDir = new File(TEST_DIR, TEST_ARCHIVE_DIR); + } private int getRetentionHours(ArchiveConfig archive, CategoryConfig category) { return category == null || category.getRetentionHours() == 0 ? archive - .getRetentionHours() - : category.getRetentionHours(); + .getRetentionHours() : category.getRetentionHours(); } private CategoryConfig getCategory(ArchiveConfig archive, @@ -224,12 +245,20 @@ public class ArchiveConfigManagerTest { break; } } + if (category == null) { + // This is part of setup and asserts will not give stack trace. + System.err.println(String.format("category: %s not in archive: %s", + categoryName, archive.getName())); + throw new IllegalArgumentException("bad category name: " + + categoryName); + } return category; } private void createTestFiles(MessageFormat fileNameFormat, ArchiveConfig archive, String categoryName, boolean isSelected, Calendar start, Calendar end) throws IOException { + CategoryConfig category = getCategory(archive, categoryName); int retentionHours = getRetentionHours(archive, category); String rootDir = archive.getRootDir(); @@ -306,6 +335,88 @@ public class ArchiveConfigManagerTest { .substring(rootDir.length())); } + private void createModTestFiles(String newFilename, String oldFilename, + String purgeFilename, String outsideFilename, + ArchiveConfig archive, String categoryName, boolean isSelected, + Calendar start, Calendar end) throws IOException { + + CategoryConfig category = getCategory(archive, categoryName); + int retentionHours = getRetentionHours(archive, category); + String rootDir = archive.getRootDir(); + + // create data file newer than purge time, within archive time, and + // isSelected + File dataFile = create_ModFile(end, newFilename, rootDir); + + if (isSelected) { + ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); + + archiveFiles.add(dataFile); + archiveSelectedDisplays.addAll(manager.getDisplayData( + archive.getName(), categoryName, true)); + } + System.out + .println("{newer modTime than purge/within archive/}\n\tFor archive:" + + archive.getName() + + " category:" + + categoryName + + "\n\tcreated file: " + + dataFile.getAbsolutePath() + .substring(rootDir.length())); + + // create data file newer than purge time, within archive time, but not + // in selected + Calendar moreThanOneDayOld = (Calendar) referenceCalendar.clone(); + moreThanOneDayOld.add(Calendar.DAY_OF_MONTH, -1); + dataFile = create_ModFile(moreThanOneDayOld, oldFilename, rootDir); + System.out + .println("{newer modTime than purge/within archive/Not Selected}\nFor archive:" + + archive.getName() + + " category:" + + categoryName + + "\n\tcreated file: " + + dataFile.getAbsolutePath() + .substring(rootDir.length())); + + // create data file older than purge time + Calendar lessThanExpiredCalendar = (Calendar) referenceCalendar.clone(); + lessThanExpiredCalendar.add(Calendar.HOUR, (-1 * retentionHours - 1)); + dataFile = create_ModFile(lessThanExpiredCalendar, purgeFilename, + rootDir); + purgeFiles.add(dataFile); + System.out.println("{older than purge}\nFor archive:" + + archive.getName() + " category:" + categoryName + + "\n\tcreated file: " + + dataFile.getAbsolutePath().substring(rootDir.length())); + + // // create data file newer than purge time, but in a directory that is + // // older than purge time, and outside of archive time frame + Calendar newerThanArchiveEnd = (Calendar) end.clone(); + // newerThanArchiveEnd.add(Calendar.HOUR, 3); + // dataFile = create_DataFile(lessThanExpiredCalendar, + // newerThanArchiveEnd, fileNameFormat, rootDir); + // System.out + // .println("{newer than purge/in directory older than purge/outside of archive}\nFor archive:" + // + archive.getName() + // + " category:" + // + categoryName + // + "\n created file: " + dataFile.getAbsolutePath()); + + // create data file newer than purge time and outside of archive time + // frame + newerThanArchiveEnd = (Calendar) end.clone(); + newerThanArchiveEnd.add(Calendar.HOUR, 3); + dataFile = create_ModFile(newerThanArchiveEnd, outsideFilename, rootDir); + System.out + .println("{newer modTime than purge/outside of archive}\nFor archive:" + + archive.getName() + + " category:" + + categoryName + + "\n\tcreated file: " + + dataFile.getAbsolutePath() + .substring(rootDir.length())); + } + private void setupTimes() { referenceCalendar = TimeUtil.newGmtCalendar(); referenceCalendar.set(Calendar.MINUTE, 0); @@ -345,8 +456,13 @@ public class ArchiveConfigManagerTest { String file_dd = ddFormat.format(fileReferenceTime); String file_kk = kkFormat.format(fileReferenceTime); String file_mm = mmFormat.format(fileReferenceTime); + String file_epochMS = String.format("%013d", + fileReferenceTime.getTime()); + String file_epochSec = String.format("%010d", + fileReferenceTime.getTime() / TimeUtil.MILLIS_PER_SECOND); String[] formatArgs = new String[] { dir_yyyy, dir_MM, dir_dd, dir_kk, - file_yyyy, file_MM, file_dd, file_kk, file_mm }; + file_yyyy, file_MM, file_dd, file_kk, file_mm, file_epochMS, + file_epochSec }; String filename = fileFormat.format(formatArgs, new StringBuffer(), new FieldPosition(0)).toString(); @@ -357,6 +473,23 @@ public class ArchiveConfigManagerTest { dir.mkdirs(); resultFile.createNewFile(); + allFiles.add(resultFile); + return resultFile; + } + + private File create_ModFile(Calendar fileReferenceCalendar, + String filename, String rootDir) throws IOException { + Date fileReferenceTime = fileReferenceCalendar.getTime(); + + File resultFile = new File(rootDir, filename); + String dirname = FilenameUtils + .getFullPath(resultFile.getAbsolutePath()); + File dir = new File(dirname); + + dir.mkdirs(); + resultFile.createNewFile(); + allFiles.add(resultFile); + resultFile.setLastModified(fileReferenceTime.getTime()); return resultFile; } @@ -416,9 +549,30 @@ public class ArchiveConfigManagerTest { public void testArchiveManagerPurge() throws IOException { ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); Collection filesFoundInPurge = new ArrayList(); + int purgeCount = 0; for (ArchiveConfig a : manager.getArchives()) { - filesFoundInPurge.addAll(manager.purgeExpiredFromArchive(a)); + purgeCount += manager.purgeExpiredFromArchive(a); + } + + // assertEquals( + // + // "The expected number of purged files and number of purge files not the same", + // purgeCount, purgeFiles.size()); + + for (File file : allFiles) { + if (!file.exists()) { + filesFoundInPurge.add(file); + } + } + System.out.println("purgeCount: " + purgeCount + ", pureFiles.size:" + + purgeFiles.size() + ", filesFoundInPurge.size(): " + + filesFoundInPurge.size()); + + for (File file : purgeFiles) { + if (!filesFoundInPurge.contains(file)) { + System.out.println("not purged: " + file.getAbsolutePath()); + } } assertEquals( From a4cc3f0bf6b52db9e286e8c573bffa353d26642d Mon Sep 17 00:00:00 2001 From: Steve Harris Date: Fri, 1 Nov 2013 14:20:00 -0400 Subject: [PATCH 15/26] 13.5.3-4 baseline Former-commit-id: 667ec69fbc3dda7cc266e0d88967924e07b5e209 [formerly 0ee69293ec3967cf89b9ca2f8ae1335f687f6249] [formerly 8aeae1c481a9528bd1a37f61f490f9642d8c8fa6] [formerly da7d1ce05ebe8adb09ff0848cdda3fc9a6f5eff0 [formerly 8aeae1c481a9528bd1a37f61f490f9642d8c8fa6 [formerly 103d478433e8d0aad0599511c30ef0792f854d13]]] Former-commit-id: da7d1ce05ebe8adb09ff0848cdda3fc9a6f5eff0 Former-commit-id: 7369078223f22949c985fdf82f677dcb829640f5 [formerly b8d3fd62d02c25949b342e0a31244c8d31562b08] Former-commit-id: 7454b37d59e3a25cd41a24f30e639e0f5a24b13b --- .../styleRules/d2dContourStyleRules.xml | 5 +- .../styleRules/gridImageryStyleRules.xml | 3 + .../edex_static/base/gfe/isc/ifpnetCDF.py | 255 ++++++------- .../library.ohd.pproc.so.REMOVED.git-id | 2 +- .../library.ohd.pproc.so.REMOVED.git-id | 2 +- .../src/nc2grib/TEXT/main_nc2grib.c | 261 ++++++++------ rpms/build/i386/build.sh | 6 +- rpms/build/x86_64/build.sh | 13 +- rpms/build/x86_64/build.sh-10312013 | 338 ++++++++++++++++++ 9 files changed, 642 insertions(+), 243 deletions(-) create mode 100644 rpms/build/x86_64/build.sh-10312013 diff --git a/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dContourStyleRules.xml b/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dContourStyleRules.xml index 8b18e14e74..610fc1f63c 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dContourStyleRules.xml +++ b/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dContourStyleRules.xml @@ -1028,7 +1028,10 @@ in|.0394|.0| 4 | |f5.2|@.|8000F0FF| |13|\ TP24hr - TP36hr + TP36hr + TP6hr_std + TP6hr_avg + TP24hr_avg in diff --git a/cave/com.raytheon.viz.grid/localization/styleRules/gridImageryStyleRules.xml b/cave/com.raytheon.viz.grid/localization/styleRules/gridImageryStyleRules.xml index 441bc15cc6..38ebe8914b 100644 --- a/cave/com.raytheon.viz.grid/localization/styleRules/gridImageryStyleRules.xml +++ b/cave/com.raytheon.viz.grid/localization/styleRules/gridImageryStyleRules.xml @@ -1227,6 +1227,9 @@ TP48hr TPrun TP120hr + TP6hr_std + TP6hr_avg + TP24hr_avg diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py index 76331c40bd..25ad53fbdf 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py @@ -67,6 +67,7 @@ from com.raytheon.uf.common.localization import LocalizationContext_Localization # 05/23/13 1759 dgilling Remove unnecessary imports. # 07/25/13 2233 randerso Improved memory utilization and performance # 09/20/13 2405 dgilling Clip grids before inserting into cache. +# 10/22/13 2405 rjpeter Remove WECache and store directly to cube. # # @@ -97,65 +98,98 @@ def logDebug(*msg): logVerbose(iscUtil.tupleToString(*msg)) -class WECache(object): - def __init__(self, we, inv, clipArea): - self._we = we - self._clipArea = clipArea - self._inv = OrderedDict() - lst = list(inv) - while len(lst): - i = lst[:BATCH_WRITE_COUNT] - javaTRs = ArrayList() - for tr in i: - javaTRs.add(iscUtil.toJavaTimeRange(tr)) - gridsAndHist = self._we.get(javaTRs, True) - for idx, tr in enumerate(i): - pair = gridsAndHist.get(idx) - g = self.__encodeGridSlice(pair.getFirst(), clipArea) - h = self.__encodeGridHistory(pair.getSecond()) - self._inv[tr] = (g, h) - lst = lst[BATCH_WRITE_COUNT:] - time.sleep(BATCH_DELAY) +def retrieveData(we, inv, clipArea): + lst = list(inv) + trs=[] + histDict = OrderedDict() + cube = None + keyList = None + gridType = str(we.getGpi().getGridType()) - def keys(self): - return tuple(self._inv.keys()) - - def __getitem__(self, key): - try: - return self._inv[key] - except KeyError: - logEvent("Cache miss for key:", str(key)) - grid = self._we.getItem(iscUtil.toJavaTimeRange(key)) - pyGrid = self.__encodeGridSlice(grid, self._clipArea) - history = grid.getGridDataHistory() - pyHist = self.__encodeGridHistory(history) - return (pyGrid, pyHist) + # clipped size + clipSize = (clipArea[1] - clipArea[0] + 1, clipArea[3] - clipArea[2] + 1) + gridCount = len(inv) - def __encodeGridSlice(self, grid, clipArea): - gridType = grid.getGridInfo().getGridType().toString() + if gridType == "SCALAR": + cube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]), dtype=numpy.float32) + elif gridType == "VECTOR": + magCube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]),dtype=numpy.float32) + dirCube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]),dtype=numpy.float32) + cube = (magCube, dirCube) + elif gridType == "WEATHER" or gridType == "DISCRETE": + cube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]), dtype=numpy.int8) + keyList = [] + + cubeIdx = 0 + while len(lst): + i = lst[:BATCH_WRITE_COUNT] + javaTRs = ArrayList() + for tr in i: + javaTRs.add(iscUtil.toJavaTimeRange(tr)) + gridsAndHist = we.get(javaTRs, True) + size = gridsAndHist.size() + for idx in xrange(size): + pair = gridsAndHist.get(idx) + grid = pair.getFirst() + tr = iscUtil.transformTime(grid.getValidTime()) + encodeGridSlice(grid, gridType, clipArea, cube, cubeIdx, keyList) + cubeIdx += 1 + histDict[tr] = encodeGridHistory(pair.getSecond()) + lst = lst[BATCH_WRITE_COUNT:] + time.sleep(BATCH_DELAY) + + if len(histDict) != gridCount: + # retrieved less grids than originally expected, purge ran? + gridCount = len(histDict) + if gridType == "SCALAR": - return clipToExtrema(grid.__numpy__[0], clipArea) + oldCube = cube + cube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]), dtype=numpy.float32) + for idx in xrange(gridCount): + cube[idx] = oldCube[idx] elif gridType == "VECTOR": - vecGrids = grid.__numpy__ - return (clipToExtrema(vecGrids[0], clipArea), clipToExtrema(vecGrids[1], clipArea)) - elif gridType == "WEATHER": - keys = grid.getKeys() - keyList = [] - for theKey in keys: - keyList.append(theKey.toString()) - return (clipToExtrema(grid.__numpy__[0], clipArea), keyList) - elif gridType =="DISCRETE": - keys = grid.getKey() - keyList = [] - for theKey in keys: - keyList.append(theKey.toString()) - return (clipToExtrema(grid.__numpy__[0], clipArea), keyList) - - def __encodeGridHistory(self, histories): - retVal = [] - for i in xrange(histories.size()): - retVal.append(histories.get(i).getCodedString()) - return tuple(retVal) + oldMagCube = magCube + magCube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]),dtype=numpy.float32) + oldDirCube = dirCube + dirCube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]),dtype=numpy.float32) + cube = (magCube, dirCube) + for idx in xrange(gridCount): + magCube[idx] = oldMagCube[idx] + dirCube[idx] = oldDirCube[idx] + elif gridType == "WEATHER" or gridType == "DISCRETE": + oldCube = cube + cube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]), dtype=numpy.int8) + for idx in xrange(gridCount): + cube[idx] = oldCube[idx] + return (cube, histDict, keyList) + +###-------------------------------------------------------------------------### +### cube and keyList are out parameters to be filled by this method, idx is the index into cube to use +def encodeGridSlice(grid, gridType, clipArea, cube, idx, keyList): + if gridType == "SCALAR": + cube[idx] = clipToExtrema(grid.__numpy__[0], clipArea) + elif gridType == "VECTOR": + vecGrids = grid.__numpy__ + cube[0][idx] = clipToExtrema(vecGrids[0], clipArea) + cube[1][idx] = clipToExtrema(vecGrids[1], clipArea) + elif gridType == "WEATHER" or gridType == "DISCRETE": + if gridType == "DISCRETE": + keys = grid.getKey() + else: + keys = grid.getKeys() + gridKeys = [] + + for theKey in keys: + gridKeys.append(theKey.toString()) + + keyList.append(gridKeys) + cube[idx]= clipToExtrema(grid.__numpy__[0], clipArea) + +def encodeGridHistory(histories): + retVal = [] + for i in xrange(histories.size()): + retVal.append(histories.get(i).getCodedString()) + return tuple(retVal) ###-------------------------------------------------------------------------### @@ -529,19 +563,18 @@ def storeTopoGrid(client, file, databaseID, invMask, clipArea): ###-------------------------------------------------------------------------### ### -def storeGridDataHistory(file, we, wec, trList): +def storeGridDataHistory(file, we, histDict): "Stores the Grid Data history string for each grid in we." # get the maximum size of the history string maxHistSize = 0 histList = [] - for tr in trList: - his = wec[tr][1] + for (tr, his) in histDict.items(): hisString = '' for i,h in enumerate(his): hisString = hisString + str(h) if i != len(his) - 1: - hisString = hisString + " ^" + hisString = hisString + " ^" histList.append(hisString) maxHistSize = max(maxHistSize,len(hisString)) @@ -727,21 +760,17 @@ def storeScalarWE(we, trList, file, timeRange, databaseID, # get the data and store it in a Numeric array. timeList, overlappingTimes = findOverlappingTimes(trList, timeRange) - # clipped size - clipSize = (clipArea[1] - clipArea[0] + 1, clipArea[3] - clipArea[2] + 1) - gridCount = len(overlappingTimes) + (cube, histDict, keyList) = retrieveData(we, overlappingTimes, clipArea) + gridCount = len(cube) + for i in xrange(len(overlappingTimes) -1, -1, -1): + ot = overlappingTimes[i] + if not ot in histDict: + del overlappingTime[i] + del timeList[i] + elif we.getGpi().isRateParm(): + durRatio = (float(timeList[i][1]-timeList[i][0]))/float((ot[1]-ot[0])) + cube[i] *= durRatio - cube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]), dtype=numpy.float32) - - wec = WECache(we, overlappingTimes, clipArea) - for i,t in enumerate(overlappingTimes): - grid = wec[t][0] - #adjust for time changes - if we.getGpi().isRateParm(): - durRatio = (float(timeList[i][1]-timeList[i][0]))/float((t[1]-t[0])) - grid *= durRatio - cube[i]= grid - ### Make sure we found some grids # make the variable name varName = we.getParmid().getParmName() + "_" + we.getParmid().getParmLevel() @@ -795,8 +824,8 @@ def storeScalarWE(we, trList, file, timeRange, databaseID, setattr(var, "fillValue", fillValue) ## Extract the GridDataHistory info and save it - storeGridDataHistory(file, we, wec, overlappingTimes) - + storeGridDataHistory(file, we, histDict) + logEvent("Saved", gridCount, varName, " grids") return gridCount @@ -811,23 +840,16 @@ def storeVectorWE(we, trList, file, timeRange, # get the data and store it in a Numeric array. timeList, overlappingTimes = findOverlappingTimes(trList, timeRange) - # clipped size - clipSize = (clipArea[1] - clipArea[0] + 1, clipArea[3] - clipArea[2] + 1) - gridCount = len(overlappingTimes) - - magCube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]),dtype=numpy.float32) - dirCube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]),dtype=numpy.float32) - - wec = WECache(we, overlappingTimes, clipArea) - for i,t in enumerate(overlappingTimes): - vecData = wec[t][0] - mag = vecData[0] - dir = vecData[1] - if we.getGpi().isRateParm(): - durRatio = (float(timeList[i][1]-timeList[i][0]))/float((t[1]-t[0])) - mag *= durRatio - magCube[i] = mag - dirCube[i] = dir + ((magCube, dirCube), histDict, keyList) = retrieveData(we, overlappingTimes, clipArea) + gridCount = len(magCube) + for i in xrange(len(overlappingTimes) -1, -1, -1): + ot = overlappingTimes[i] + if not ot in histDict: + del overlappingTime[i] + del timeList[i] + elif we.getGpi().isRateParm(): + durRatio = (float(timeList[i][1]-timeList[i][0]))/float((ot[1]-ot[0])) + magCube[i] *= durRatio varName = we.getParmid().getParmName() + "_" + we.getParmid().getParmLevel() @@ -924,8 +946,8 @@ def storeVectorWE(we, trList, file, timeRange, setattr(dirVar, "fillValue", dfillValue) ## Extract the GridDataHistory info and save it - storeGridDataHistory(file, we, wec, overlappingTimes) - + storeGridDataHistory(file, we, histDict) + logEvent("Saved", gridCount, varName, "grids") return gridCount * 2 #vector has two grids @@ -970,19 +992,14 @@ def storeWeatherWE(we, trList, file, timeRange, databaseID, invMask, clipArea): # get the data and store it in a Numeric array. timeList, overlappingTimes = findOverlappingTimes(trList, timeRange) - - # clipped size - clipSize = (clipArea[1] - clipArea[0] + 1, clipArea[3] - clipArea[2] + 1) - gridCount = len(overlappingTimes) - byteCube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]), dtype=numpy.int8) - - keyList = [] - wec = WECache(we, overlappingTimes, clipArea) - for i,t in enumerate(overlappingTimes): - wx = wec[t][0] - byteCube[i] = wx[0] - keyList.append(wx[1]) + (byteCube, histDict, keyList) = retrieveData(we, overlappingTimes, clipArea) + gridCount = len(histDict) + for i in xrange(len(overlappingTimes) -1, -1, -1): + ot = overlappingTimes[i] + if not ot in histDict: + del overlappingTime[i] + del timeList[i] # make the variable name varName = we.getParmid().getParmName() + "_" + we.getParmid().getParmLevel() @@ -1046,7 +1063,7 @@ def storeWeatherWE(we, trList, file, timeRange, databaseID, invMask, clipArea): setattr(var, "fillValue", fillValue) ## Extract the GridDataHistory info and save it - storeGridDataHistory(file, we, wec, overlappingTimes) + storeGridDataHistory(file, we, histDict) logEvent("Saved", gridCount, varName, "grids") @@ -1061,19 +1078,13 @@ def storeDiscreteWE(we, trList, file, timeRange, databaseID, invMask, clipArea): # get the data and store it in a Numeric array. timeList, overlappingTimes = findOverlappingTimes(trList, timeRange) - # clipped size - clipSize = (clipArea[1] - clipArea[0] + 1, clipArea[3] - clipArea[2] + 1) - gridCount = len(overlappingTimes) - - byteCube = numpy.empty(shape=(gridCount, clipSize[1], clipSize[0]), dtype=numpy.int8) - - keyList = [] - wec = WECache(we, overlappingTimes, clipArea) - for i,t in enumerate(overlappingTimes): - dis = wec[t][0] - byteCube[i] = dis[0] - keyList.append(dis[1]) - + (byteCube, histDict, keyList) = retrieveData(we, overlappingTimes, clipArea) + gridCount = len(histDict) + for i in xrange(len(overlappingTimes) -1, -1, -1): + ot = overlappingTimes[i] + if not ot in histDict: + del overlappingTime[i] + del timeList[i] # make the variable name varName = we.getParmid().getParmName() + "_" + we.getParmid().getParmLevel() @@ -1135,7 +1146,7 @@ def storeDiscreteWE(we, trList, file, timeRange, databaseID, invMask, clipArea): setattr(var, "fillValue", fillValue) ## Extract the GridDataHistory info and save it - storeGridDataHistory(file, we, wec, overlappingTimes) + storeGridDataHistory(file, we, histDict) logEvent("Saved", gridCount, varName, "grids") @@ -1325,7 +1336,7 @@ def main(outputFilename, parmList, databaseID, startTime, clipArea = extremaOfSetBits(maskGrid) maskGrid = clipToExtrema(maskGrid, clipArea) clippedGridSize = maskGrid.shape - validPointCount = numpy.add.reduce(numpy.add.reduce(maskGrid)) + validPointCount = float(numpy.add.reduce(numpy.add.reduce(maskGrid))) #invert the mask grid invMask = numpy.logical_not(maskGrid) diff --git a/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id b/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id index 7b5e854ce1..c23b9214f2 100644 --- a/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id +++ b/nativeLib/files.native/awipsShare/hydroapps/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id @@ -1 +1 @@ -759799451b20c427bdaa8cb8185b9602cc66c6c6 \ No newline at end of file +bd6cb2ea1de310abb0f576998cd03a437683289f \ No newline at end of file diff --git a/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id b/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id index 7b5e854ce1..c23b9214f2 100644 --- a/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id +++ b/nativeLib/files.native/edex/lib/native/linux32/library.ohd.pproc.so.REMOVED.git-id @@ -1 +1 @@ -759799451b20c427bdaa8cb8185b9602cc66c6c6 \ No newline at end of file +bd6cb2ea1de310abb0f576998cd03a437683289f \ No newline at end of file diff --git a/nativeLib/rary.ohd.pproc/src/nc2grib/TEXT/main_nc2grib.c b/nativeLib/rary.ohd.pproc/src/nc2grib/TEXT/main_nc2grib.c index 65d485b2c0..c9cab33640 100644 --- a/nativeLib/rary.ohd.pproc/src/nc2grib/TEXT/main_nc2grib.c +++ b/nativeLib/rary.ohd.pproc/src/nc2grib/TEXT/main_nc2grib.c @@ -34,7 +34,7 @@ * a text file requires no code change as long as the parameters don't change. * That logic could perhaps change as well. * -* The routine first uses standard C calls to read the netcdf file. The structure +* The routine first uses standard C calls to read the NetCDF file. The structure * of that file can be reviewed by reading the GFE help reference section on the * ifpnetCDF command. * @@ -61,12 +61,16 @@ * * Version 4 allows users to combine all GRIB messages into one file. This becomes useful * when dealing with a lot of files for a parameter such as 1 hour QPF or temperature that -* goes out to 240 hours. +* goes out to num_hours hours. * * This is still a work in progress and code can always be improved to increase efficiency. * * Oct 2011 - PTilles - added read of new token for defining number of days of data to process * +* Mar 2012 - PTilles - added functionality to allow for more than 10 days (more than 240 +* hours) of data in one file to be processed. This looks for a value of '10' +* in the 5th parameter of gfe2grib.txt. +* * Sep 2012 -Dan Stein - The original nc2grib program assumed the first variable in the * NetCDF file (variable[0]) would be the data variable to be converted to grib format. The * nc2grib tool was hard-coded to only look at variable[0]. In AWIPS-II, GFE began putting @@ -93,9 +97,14 @@ #include "packgrib.h" #include "getopt.h" - #include "cmapf.h" +/*#include "version_info.h"*/ +#define VERSION_NAME "AWIPS II" +#define VERSION_NUMBER "13.5.2" +#define VERSION_DATE "(Oct 30, 2013)" + + #define SECINHR 3600. #define PATH_LEN 500 #define FILE_LEN 300 @@ -200,23 +209,24 @@ int nc2grib_main (int argc, char *argv[]) char adayhrmin[7]={'\0'}; /* day, hour, minute info attached to WMO header */ - - int numgfeparms=0; - + char cnum[3] = {'\0'}; + int num_hours = 0; /* (num_days * 24) */ + /* number of days of data to process - read from token - previously hard coded as 10 */ + /* default value = 10 - if token not found then default value used */ + int num_days = 0; int numgfiles=0; /* number of grib files for combining files into one if desired */ - char *gfiles[240]; /* array of char pointers for holding grib filenames if combining files */ /* for reading the NetCDF file */ - int NetCDF_ID; /* Netcdf id */ - int ndims; /* number of dimensions */ + int NetCDF_ID; /* NetCDF id */ + int numDims; /* number of dimensions */ int numVars; /* number of variables */ - int ngatts; /* number of attributes */ - int recdim; + int numGlobalAttributes; /* number of attributes */ + int unlimitedDimensionID; long start[] = {0, 0, 0}; /* start at first value */ long start1r[] = {0, 0}; /* accounts for netcdf with only 1 record and 2 dimensions of y,x */ @@ -261,9 +271,9 @@ int nc2grib_main (int argc, char *argv[]) double *latlonLL, *latlonUR, lonOrigin,*domainOrigin, *domainExtent, *latLonOrigin; int *gridPointLL, *gridPointUR; double x1, y1, x2, y2, lat1, lon1, lat2, lon2; - nc_type vt_type, dn_type, ll_type, d_type, g_type; + nc_type dataType, dn_type, ll_type, d_type, g_type; nc_type varDataType; - int vt_len, ll_len, d_len, g_len; + int attributeLength, ll_len, d_len, g_len; int variableID, *gridSize; int numberOfVariableDimensions; int dimensionIDVector[MAX_VAR_DIMS]; @@ -274,7 +284,7 @@ int nc2grib_main (int argc, char *argv[]) char cdfunits[MAX_NC_NAME]={'\0'}; char projection[MAX_NC_NAME]={'\0'}; long dim_size; - float *cdfvargrid=NULL; /* this is the main array holding the actual data values */ + float *cdfDataArray=NULL; /* this is the main array holding the actual data values */ float arraysize; long *validTimes; @@ -361,7 +371,7 @@ int nc2grib_main (int argc, char *argv[]) output_buffer = (size_t *) malloc (sizeof(size_t)*odim); /* output buffer used when writing GRIB message */ - int variableFound = FALSE; /* Is the variable present in the NetCDF file? Stein Sep 2012 */ + int variableFound = FALSE; /* Is the variable present in the NetCDF file? */ /* output_buffer = (int *) malloc (sizeof(int)*odim); /* output buffer used when writing GRIB message */ @@ -378,7 +388,7 @@ int nc2grib_main (int argc, char *argv[]) /* parse command line arguments */ - while ((c = getopt(argc, argv, ":n:i:t:o::b:p:g:Nfrqhv1")) != -1) { + while ((c = getopt(argc, argv, ":n:i:t:o::b:p:g:Nfrqhv1V")) != -1) { switch (c) { @@ -710,6 +720,10 @@ int nc2grib_main (int argc, char *argv[]) case '1': /* process only one record of NetCDF, useful for debugging */ time1flag++; break; + case 'V': + printf("version number = %s-%s\n",VERSION_NAME,VERSION_NUMBER); + exit(0); + break; case ':': /* for options that need an operand */ if(optopt != 'o') { @@ -738,7 +752,8 @@ int nc2grib_main (int argc, char *argv[]) printf("Unrecognized program command line option: -%c\n", optopt); errflag++; } - } + + } /* while c = getopt */ if (errflag || helpflag || argc==1 || ( iflag==0 || pflag==0) ) @@ -753,6 +768,24 @@ int nc2grib_main (int argc, char *argv[]) return USAGE; } +/* Print CHPS build number */ + printf("version number = %s-%s\n",VERSION_NAME,VERSION_NUMBER); + + if(getAppsDefaults("nc2g_num_days",cnum) == -1) + { + num_days = 10; + } + else + { + + num_days = atoi(cnum); + } + + num_hours = num_days * 24; + + char *gfiles[num_hours]; /* array of char pointers for holding grib filenames if combining files */ + + printf("\n number of days to process = %d \n", num_days); if(nc_getAppsDefaults("nc2g_app_dir",appsdir) == -1) { @@ -805,7 +838,7 @@ int nc2grib_main (int argc, char *argv[]) /**************************************************************************/ /* debugflag > 0; debug option is on */ - if(debugflag>0) + if(debugflag) printf("\n Debug option on...reading from GFE to GRIB configuation file:\n" \ " %s\n\n",file_path); @@ -817,9 +850,11 @@ int nc2grib_main (int argc, char *argv[]) if(fileline[0] != '#') /* check for comments */ { - sscanf(fileline,"%s%s%d%d%d%d%d",gfe2grib.GFEParameterName, gfe2grib.gfename, &gfe2grib.processid, - &gfe2grib.gribnum,&gfe2grib.decscale, &gfe2grib.timerange, &gfe2grib.timeunit); - if(debugflag>0) + sscanf(fileline,"%s%s%d%d%d%d%d",gfe2grib.GFEParameterName, + gfe2grib.gfename, &gfe2grib.processid, + &gfe2grib.gribnum,&gfe2grib.decscale, &gfe2grib.timerange, + &gfe2grib.timeunit); + if(debugflag) printf(" DEBUG: Read in from gfe2grib.txt %s %s %d %d %d %d %d \n",gfe2grib.GFEParameterName, gfe2grib.gfename, gfe2grib.processid, gfe2grib.gribnum,gfe2grib.decscale, gfe2grib.timerange, gfe2grib.timeunit); @@ -828,12 +863,12 @@ int nc2grib_main (int argc, char *argv[]) if (!(strcmp(gfe2grib.GFEParameterName, process))) { - found = 1; break; } - } - } + } /* If not a comment */ + + } /* While we haven't reach the end of the gfe2grib.txt file */ @@ -851,13 +886,12 @@ int nc2grib_main (int argc, char *argv[]) fclose(fp); - /* open the Netcdf file*/ + /* open the NetCDF file*/ if(inpath==NULL) { inpath=(char *) malloc(sizeof(char)*(FILE_LEN+1)); - if(inpath==NULL) { printf(" ERROR: Something went wrong with memory allocation for the NetCDF input directory....exiting\n"); @@ -871,12 +905,13 @@ int nc2grib_main (int argc, char *argv[]) printf(" ERROR: Invalid token value for token \"netcdf_dir\".\n\t Program exit."); return APSDEFERR; } - else if (debugflag>0) + else if (debugflag) { printf(" Default path for the input NetCDF file not specified...Will use the following:\n" \ " %s\n",inpath); } - } + } /* if inpath is NULL */ + /***************************************************************************/ else if(debugflag) printf(" Will attempt to read NetCDF file from this path:\n" \ @@ -895,32 +930,21 @@ int nc2grib_main (int argc, char *argv[]) if (NetCDF_ID==-1) { - printf("\n ERROR: Could not open the netcdf file: %s\n", fn); + printf("\n ERROR: Could not open the NetCDF file: %s\n", fn); return CDFERR; } else { - printf ("\n Netcdf file %s was opened successfully.\n\n",fn); + printf ("\n NetCDF file %s was opened successfully.\n\n",fn); } - /* Inquire about the Netcdf file: No.of dimensions, No.of variables, - No. of global attributes etc.*/ + /* Inquire about the NetCDF file: No.of dimensions, No.of variables, No.of + * global attributes etc. + */ - ncinquire (NetCDF_ID, &ndims, &numVars, &ngatts, &recdim); -/*************************************************************************/ -/* debug */ + ncinquire (NetCDF_ID, &numDims, &numVars, &numGlobalAttributes, &unlimitedDimensionID); -if (debugflag >0) -{ - printf("\n Debug option on. Debug info from reading the netcdf file follows:\n\n"); - printf (" Number of dimensions for this netcdf file is: %d\n",ndims); - printf (" Number of variables for this netcdf file is: %d\n",numVars); - printf (" Number of global attributes for this netcdf file is: %d\n",ngatts); -} -/*************************************************************************/ - - /************************************************************************** - * Sep 2012 - Stein The utility that takes GFE data and converts it to + /* Sep 2012 - Stein The utility that takes GFE data and converts it to * NetCDF format is ifpNetCDF. To the best of my knowledge, this utility * always puts exactly one variable and exactly one history variable into * each NetCDF file. The section of code below originally assumed that the @@ -930,7 +954,7 @@ if (debugflag >0) * For whatever reason, this order was changed in AWIPS-II so that the * history variable showed up first and the program wouldn't work. I was * tasked with correcting this program to make it order independent. My - * solution was to loop through all the variables to see whether the + * solution is to loop through all the variables to see whether the * variable we're looking for is in the NetCDF file. If it is, variableID * is set to it's value. If not found, the program will exit as it did * before. @@ -989,11 +1013,6 @@ if (debugflag >0) * end of the section of code that I changed. */ - - - - - if(numberOfVariableDimensions==3) /* in some cases, this may not be true if file is produced from MPE/DQC */ { for (i=0; i0) return CDFERR; } /*************************************************************************/ -if (debugflag >0) + if (debugflag) { printf(" DEBUG: cdfvar dimension %d: name=%s size=%ld\n",i+1,dimname,dim_size); } /*************************************************************************/ - } - } + } /* for i */ + + } /* if (numberOfVariableDimensions == 3) */ + else if (numberOfVariableDimensions==2) { - for (i=0; i0) else if (i==1) x=dim_size; /*************************************************************************/ -if (debugflag >0) +if (debugflag) { printf(" DEBUG: cdfvar dimension %d: name=%s size=%ld\n",i+1,dimname,dim_size); } /*************************************************************************/ - } - } + } /* for i */ + + } /* else if (numberOfVariableDimensions == 2) */ + else { printf("\n nc2grib is not coded to handle %d number of dimensions for variable %s.\n" \ @@ -1055,17 +1077,29 @@ if (debugflag >0) /* get variable attributes */ + /* get the values of NetCDF attributes given the variable ID and name */ arraysize = x * y; - cdfvargrid = (float *) malloc (sizeof(float)*arraysize); + cdfDataArray = (float *) malloc (sizeof(float) * arraysize); long count[]={1,y,x}; long count1r[]={y,x}; - ncattinq(NetCDF_ID,variableID,"validTimes",&vt_type,&vt_len); +if (debugflag) +{ + printf ("DEBUG: ncattinq call Before\n"); +} - validTimes = (long *) malloc(vt_len * nctypelen(vt_type)); + /* Get Information about an Attribute (att inquiry) */ + ncattinq(NetCDF_ID, variableID, "validTimes", &dataType, &attributeLength); + +if (debugflag) +{ + printf ("DEBUG: ncattinq call After\n"); +} + + validTimes = (long *) malloc (attributeLength * nctypelen(dataType)); ncattget(NetCDF_ID, variableID, "validTimes", validTimes); @@ -1077,6 +1111,8 @@ if (debugflag >0) ncattget(NetCDF_ID, variableID, "projectionType", projection); + + /* Get Information about an Attribute (att inquiry) */ ncattinq(NetCDF_ID,variableID,"latLonLL",&ll_type,&ll_len); latlonLL = (double *) malloc(ll_len * nctypelen(ll_type)); @@ -1087,30 +1123,40 @@ if (debugflag >0) ncattget(NetCDF_ID, variableID, "latLonUR", (void *) latlonUR); + + /* Get Information about an Attribute (att inquiry) */ ncattinq(NetCDF_ID,variableID,"domainOrigin",&d_type,&d_len); domainOrigin = (double *) malloc(d_len * nctypelen(d_type)); ncattget(NetCDF_ID, variableID, "domainOrigin", (void *) domainOrigin); + + /* Get Information about an Attribute (att inquiry) */ ncattinq(NetCDF_ID,variableID,"domainExtent",&d_type,&d_len); domainExtent = (double *) malloc(d_len * nctypelen(d_type)); ncattget(NetCDF_ID, variableID, "domainExtent", (void *) domainExtent); + + /* Get Information about an Attribute (att inquiry) */ ncattinq(NetCDF_ID,variableID,"gridSize",&g_type,&g_len); gridSize = (int *) malloc(g_len * nctypelen(g_type)); ncattget(NetCDF_ID, variableID, "gridSize", (void *) gridSize); + + /* Get Information about an Attribute (att inquiry) */ ncattinq(NetCDF_ID,variableID,"gridPointLL",&g_type,&g_len); gridPointLL = (int *) malloc(g_len * nctypelen(g_type)); ncattget(NetCDF_ID, variableID, "gridPointLL", (void *) gridPointLL); + + /* Get Information about an Attribute (att inquiry) */ ncattinq(NetCDF_ID,variableID,"gridPointUR",&g_type,&g_len); gridPointUR = (int *) malloc(g_len * nctypelen(g_type)); @@ -1119,8 +1165,8 @@ if (debugflag >0) /* initialize the array to missing value */ - for (i=0;i0) { printf(" DEBUG: siteID = %s\n",siteID); - printf(" DEBUG: number of valid times = %d type = %d\n",vt_len, vt_type); + printf(" DEBUG: number of valid times = %d type = %d\n",attributeLength, dataType); printf(" DEBUG: descriptName = %s\n",descriptName); printf(" DEBUG: projection = %s\n",projection); @@ -1344,7 +1390,7 @@ if (debugflag >0) } else { - printf(" Unknown projection read from netcdf...Exiting"); + printf(" Unknown projection read from NetCDF...Exiting"); return CDFERR; /* might account for this as this is a lat,lon grid */ @@ -1602,16 +1648,15 @@ if (debugflag>0) */ - if (time1flag>0) /* for testing only to do just the first valid time from the netcdf file */ - vt_len=2; + if (time1flag>0) /* for testing only to do just the first valid time from the NetCDF file */ + attributeLength=2; /****************************************************************************/ if (debugflag>0) printf("\n ***Entering main loop to process NetCDF records(s) into GRIB files*** \n\n"); /****************************************************************************/ - for (m=0; m0) fcsth=0; - /* In the case of multiple accumulation periods in the same netcdf file, will need to attach this to the + /* In the case of multiple accumulation periods in the same NetCDF file, will need to attach this to the filename in both cases. Can't reuse fcsth as it might be needed to determine the WMO header for any future NPVU estimate/observed grids. */ @@ -1714,14 +1759,14 @@ if (debugflag>0) - if (esth > 240 || esth < 0) + if (esth > num_hours || esth < 0) { - printf(" The estimated/observed time period is either less than 0 or greater than 10 days (240 hours).\n" \ + printf(" The estimated/observed time period is either less than 0 or greater than %d hours.\n" \ " Therefore, valid times within the input NetCDF filename may not have been generated \n" \ " correctly. Or this is actually a forecast grid and the -b option should be used so it \n" \ " will be processed correctly. Check your options and ensure this is an estimate or observed grid\n" \ " You could also try to generate the file again.\n" \ - " For debug esth = %d\n",esth); + " For debug esth = %d\n",num_hours, esth); return FILEERR; } @@ -1784,13 +1829,13 @@ if (debugflag>0) printf(" DEBUG: fcsth = %d timediff=%f valid time = %ld basis time_t = %ld\n",fcsth, timediff,(*(validTimes+m+1)), basetime_t); /*************************************************************/ - if (fcsth > 240 || fcsth < 0) + if (fcsth > num_hours || fcsth < 0) { - printf(" The forecast time is either less than 0 or greater than 10 days (240 hours).\n" \ + printf(" The forecast time is either less than 0 or greater than %d hours.\n" \ " Therefore, the basis time may not be specified correctly or may need to be specified \n" \ " on the command line according to guidance. Please check your command options or \n" \ " or the NetCDF file creation and try again.\n" \ - " for debug fcsth = %d\n",fcsth); + " for debug fcsth = %d\n",num_hours, fcsth); return FILEERR; } @@ -1816,10 +1861,12 @@ if (debugflag >0) grib_lbl[16]=fcsth-(int)(timediff/SECINHR); /* P1 */ grib_lbl[17]=fcsth; /* P2 */ } - else if (gfe2grib.timerange==0) + else if (gfe2grib.timerange==0 || gfe2grib.timerange == 10) { /* this is for a forecast product valid at reference time + P1 and at present using this for PETF + OR + case of forecast hour > 255 */ grib_lbl[16]=fcsth; /* P1 */ @@ -1842,13 +1889,13 @@ if (debugflag >0) start[0]=(long) (m/2); - status = ncvarget(NetCDF_ID,variableID,start,count,cdfvargrid); + status = ncvarget(NetCDF_ID,variableID,start,count,cdfDataArray); } else if (numberOfVariableDimensions==2) { start1r[0]=(long) (m/2); - status = ncvarget(NetCDF_ID,variableID,start1r,count1r,cdfvargrid); + status = ncvarget(NetCDF_ID,variableID,start1r,count1r,cdfDataArray); } if (status != NC_NOERR) @@ -1862,7 +1909,7 @@ if (debugflag >0) for (i=0;i xmissing) + if((*(cdfDataArray+i))> xmissing) { mischek=1; break; @@ -1880,7 +1927,7 @@ if (debugflag >0) for (i=0;i0) for (i=0;i xmissing) + if((*(cdfDataArray+i))> xmissing) - *(cdfvargrid+i) *= 25.4; /* convert inches to mm */ + *(cdfDataArray+i) *= 25.4; /* convert inches to mm */ } } @@ -1920,9 +1967,9 @@ if (debugflag >0) for (i=0;i xmissing) + if((*(cdfDataArray+i))> xmissing) - *(cdfvargrid+i) = ((*(cdfvargrid+i)-32) * 5/9) + 273.16; /* convert F to K */ + *(cdfDataArray+i) = ((*(cdfDataArray+i)-32) * 5/9) + 273.16; /* convert F to K */ } @@ -1931,9 +1978,9 @@ if (debugflag >0) { for (i=0;i xmissing) - - *(cdfvargrid+i) += 273.16; /* convert C to K */ + if((*(cdfDataArray+i))> xmissing) + + *(cdfDataArray+i) += 273.16; /* convert C to K */ } } @@ -1953,9 +2000,9 @@ if (debugflag >0) for (i=0;i xmissing) + if((*(cdfDataArray+i))> xmissing) - *(cdfvargrid+i) *= 0.3048; /* convert feet to meters */ + *(cdfDataArray+i) *= 0.3048; /* convert feet to meters */ } } @@ -1983,9 +2030,8 @@ if (debugflag >0) } /*************************************************************************/ - - status = packgrib(grib_lbl,pds_ext,&iplen,cdfvargrid,&idim,&xmissing, - output_buffer,&odim,&length); + status = packgrib(grib_lbl, pds_ext, &iplen, cdfDataArray, &idim, + &xmissing, output_buffer,&odim,&length); if (status !=0) { @@ -2206,7 +2252,7 @@ if(debugflag) sprintf(ofn,ofn,fcsth); /* standard forecast product using forecast hours past basis time */ - } + } /* if (bflag) */ else /* without a basis time, this has to be an estimated/observed product using the valid time in the output file. Note that if "%%" is NULL and bflag == 0, specifying esth here is ignored in the output filename. @@ -2340,7 +2386,7 @@ if(debugflag>0) - if(bflag && qflag==0) /* old - strstr(process,"QPE")==NULL && strstr(process,"qpe")==NULL) */ + if(bflag && qflag==0) /* old - strstr(GFEParameterName,"QPE")==NULL && strstr(process,"qpe")==NULL) */ { if(debugflag>0) @@ -2357,6 +2403,7 @@ if(debugflag>0) /* first write out the main GRIB file using the copygb command without the header determined above to a temporary holding file. This file will now contain the QPF forecast on GRID218 at 10km resolution */ + copygb_main_(command); /* status = system(command); */ } @@ -2768,8 +2815,8 @@ if (debugflag >0) if(output_buffer!=NULL) free(output_buffer); - if(cdfvargrid!=NULL) - free(cdfvargrid); + if(cdfDataArray!=NULL) + free(cdfDataArray); if(gribdir!=NULL) free(gribdir); @@ -2868,15 +2915,15 @@ int timet_to_userformat_ansi(time_t timet, char *ansi, char* userformat) int display_usage(void) { printf("\n\n nc2grib GFE NetCDF to GRIB1 translator, usage:\n\n" \ - "./nc2grib.LX -n (input netcdf path) -i (netcdf file) -t (output grib path) -o (output grib file) \n" \ + "./nc2grib.LX -n (input NetCDF path) -i (NetCDF file) -t (output grib path) -o (output grib file) \n" \ " -b (basis time) -p (process ID) -g (one GRIB filename) -f -N -v -h\n" \ "where:\n" \ - "-n (input netcdf path) Refers to the path containing the NetCDF file\n" \ - " Optional, requires argument generated by the GFE routine ifpnetCDF.\n" \ + "-n (input NetCDF path) Refers to the path containing the NetCDF file\n" \ + " Optional, requires argument generated by the GFE routine ifpNetCDF.\n" \ " If not used, the token netcdf_dir will be used \n" \ " to retrieve this information\n\n" \ - "-i (input netcdf file) Refers to the NetCDF file generated in the format\n" \ - " Required, requires argument used by the GFE routine ifpnetCDF.\n\n" \ + "-i (input NetCDF file) Refers to the NetCDF file generated in the format\n" \ + " Required, requires argument used by the GFE routine ifpNetCDF.\n\n" \ " NOTE that this command line option and its argument\n" \ " must be specified in the call to nc2grib.\n\n" \ "-t (output grib path) Refers to the path of the GRIB file(s) generated by nc2grib.\n" \ @@ -2893,7 +2940,7 @@ int display_usage(void) " Required for forecast Example: -b 2009051412 \n" \ " grids and QPE grids going to \n" \ " NPVU,requires argument \n\n" \ - "-p (process ID) Refers to the parameter process ID relating to a GFE parameter\n" \ + "-p (GFEParameterName ID) Refers to the parameter process ID relating to a GFE parameter\n" \ " Required, requires argument such as QPF. Needs to match against a process in the gfe2grib.txt\n" \ " configuration file.\n" \ " NOTE that this command line option and its argument \n" \ @@ -2935,10 +2982,6 @@ int display_usage(void) return 0; -/* ============== Statements containing RCS keywords: */ -{static char rcs_id1[] = "$Source: /fs/hseb/ob9d/ohd/pproc/src/nc2grib/RCS/main_nc2grib.c,v $"; - static char rcs_id2[] = "$Id: main_nc2grib.c,v 1.2 2010/06/14 15:04:32 millerd Exp $";} -/* =================================================== */ - } + diff --git a/rpms/build/i386/build.sh b/rpms/build/i386/build.sh index 061f2699f7..31973469c5 100644 --- a/rpms/build/i386/build.sh +++ b/rpms/build/i386/build.sh @@ -391,11 +391,11 @@ if [ "${1}" = "-custom" ]; then #fi #buildRPM "awips2-httpd-pypies" #buildRPM "awips2-ant" - #buildRPM "awips2-adapt-native" + buildRPM "awips2-adapt-native" #buildRPM "awips2-common-base" - #buildRPM "awips2-hydroapps-shared" + buildRPM "awips2-hydroapps-shared" #buildRPM "awips2-java" - buildRPM "awips2-python-dynamicserialize" + #buildRPM "awips2-python-dynamicserialize" #buildRPM "awips2-rcm" #buildRPM "awips2-tools" diff --git a/rpms/build/x86_64/build.sh b/rpms/build/x86_64/build.sh index 82b3bb8fc1..ca2535f6e3 100644 --- a/rpms/build/x86_64/build.sh +++ b/rpms/build/x86_64/build.sh @@ -280,15 +280,16 @@ fi # Use the custom flag for selecting specific rpms to build if [ "${1}" = "-custom" ]; then - unpackHttpdPypies - if [ $? -ne 0 ]; then - exit 1 - fi - buildRPM "awips2-httpd-pypies" + #unpackHttpdPypies + #if [ $? -ne 0 ]; then + # exit 1 + #fi + #buildRPM "awips2-httpd-pypies" buildRPM "awips2-adapt-native" - buildRPM "awips2-hydroapps-shared" #buildRPM "awips2-ant" + buildRPM "awips2-hydroapps-shared" #buildRPM "awips2-java" + #buildRPM "awips2-python-dynamicserialize" #buildRPM "awips2-tools" exit 0 diff --git a/rpms/build/x86_64/build.sh-10312013 b/rpms/build/x86_64/build.sh-10312013 new file mode 100644 index 0000000000..fcd9f21030 --- /dev/null +++ b/rpms/build/x86_64/build.sh-10312013 @@ -0,0 +1,338 @@ +#!/bin/bash + +function buildRPM() +{ + # Arguments: + # ${1} == the name of the rpm. + lookupRPM "${1}" + if [ $? -ne 0 ]; then + echo "ERROR: '${1}' is not a recognized AWIPS II RPM." + exit 1 + fi + + /usr/bin/rpmbuild -ba \ + --define '_topdir %(echo ${AWIPSII_TOP_DIR})' \ + --define '_baseline_workspace %(echo ${WORKSPACE})' \ + --define '_uframe_eclipse %(echo ${UFRAME_ECLIPSE})' \ + --define '_awipscm_share %(echo ${AWIPSCM_SHARE})' \ + --define '_build_root %(echo ${AWIPSII_BUILD_ROOT})' \ + --define '_component_version %(echo ${AWIPSII_VERSION})' \ + --define '_component_release %(echo ${AWIPSII_RELEASE})' \ + --define '_component_build_date %(echo ${COMPONENT_BUILD_DATE})' \ + --define '_component_build_time %(echo ${COMPONENT_BUILD_TIME})' \ + --define '_component_build_system %(echo ${COMPONENT_BUILD_SYSTEM})' \ + --buildroot ${AWIPSII_BUILD_ROOT} \ + ${RPM_SPECIFICATION}/component.spec + if [ $? -ne 0 ]; then + echo "ERROR: Failed to build RPM ${1}." + exit 1 + fi + + return 0 +} + +# This script will build all of the 64-bit rpms. +# Ensure that we are on a machine with the correct architecture. + +architecture=`uname -i` +if [ ! "${architecture}" = "x86_64" ]; then + echo "ERROR: This build can only be performed on a 64-bit Operating System." + exit 1 +fi + +# Determine which directory we are running from. +path_to_script=`readlink -f $0` +dir=$(dirname $path_to_script) + +common_dir=`cd ${dir}/../common; pwd;` +if [ $? -ne 0 ]; then + echo "ERROR: Unable to find the common functions directory." + exit 1 +fi +# source the common functions. +source ${common_dir}/lookupRPM.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to source the common functions." + exit 1 +fi +source ${common_dir}/usage.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to source the common functions." + exit 1 +fi +source ${common_dir}/rpms.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to source the common functions." + exit 1 +fi +source ${common_dir}/systemInfo.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to retrieve the system information." + exit 1 +fi + +# prepare the build environment. +source ${dir}/buildEnvironment.sh +if [ $? -ne 0 ]; then + echo "ERROR: Unable to prepare the build environment." + exit 1 +fi + +export LIGHTNING=true +# Determine if the optional '-nobinlightning' argument has been specified. +if [ "${2}" = "-nobinlightning" ]; then + LIGHTNING=false +fi + +if [ "${1}" = "-64bit" ]; then + buildRPM "awips2-common-base" + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-python" + buildRPM "awips2-python-cherrypy" + buildRPM "awips2-python-dynamicserialize" + buildRPM "awips2-python-h5py" + buildRPM "awips2-python-jimporter" + buildRPM "awips2-python-matplotlib" + buildRPM "awips2-python-nose" + buildRPM "awips2-python-numpy" + buildRPM "awips2-python-pil" + buildRPM "awips2-python-pmw" + buildRPM "awips2-python-pupynere" + buildRPM "awips2-python-qpid" + buildRPM "awips2-python-scientific" + buildRPM "awips2-python-scipy" + buildRPM "awips2-python-tables" + buildRPM "awips2-python-thrift" + buildRPM "awips2-python-tpg" + buildRPM "awips2-python-ufpy" + buildRPM "awips2-python-werkzeug" + buildRPM "awips2-python-pygtk" + buildRPM "awips2-python-pycairo" + buildJava + buildRPM "awips2-python-shapely" + buildRPM "awips2-notification" + + exit 0 +fi + +if [ "${1}" = "-postgres" ]; then + buildRPM "awips2-postgres" + buildRPM "awips2-database-server-configuration" + buildRPM "awips2-database-standalone-configuration" + buildRPM "awips2-database" + buildRPM "awips2-maps-database" + buildRPM "awips2-ncep-database" + buildRPM "awips2-pgadmin3" + + exit 0 +fi + +if [ "${1}" = "-delta" ]; then + buildRPM "awips2-common-base" + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + buildEDEX + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-python-dynamicserialize" + buildRPM "awips2-python-ufpy" + buildRPM "awips2-cli" + buildRPM "awips2-data.hdf5-gfe.climo" + buildRPM "awips2-gfesuite-client" + buildRPM "awips2-gfesuite-server" + buildRPM "awips2-localapps-environment" + buildRPM "awips2-data.hdf5-topo" + buildRPM "awips2-data.gfe" + buildLocalizationRPMs + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-edex-environment" + buildRPM "awips2-notification" + + exit 0 +fi + +if [ "${1}" = "-full" ]; then + buildRPM "awips2-common-base" + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + buildEDEX + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-python" + buildRPM "awips2-python-cherrypy" + buildRPM "awips2-python-dynamicserialize" + buildRPM "awips2-python-h5py" + buildRPM "awips2-python-jimporter" + buildRPM "awips2-python-matplotlib" + buildRPM "awips2-python-nose" + buildRPM "awips2-python-numpy" + buildRPM "awips2-python-pil" + buildRPM "awips2-python-pmw" + buildRPM "awips2-python-pupynere" + buildRPM "awips2-python-qpid" + buildRPM "awips2-python-scientific" + buildRPM "awips2-python-scipy" + buildRPM "awips2-python-tables" + buildRPM "awips2-python-thrift" + buildRPM "awips2-python-tpg" + buildRPM "awips2-python-ufpy" + buildRPM "awips2-python-werkzeug" + buildRPM "awips2-python-pygtk" + buildRPM "awips2-python-pycairo" + buildRPM "awips2-cli" + buildRPM "awips2-data.hdf5-gfe.climo" + buildRPM "awips2-gfesuite-client" + buildRPM "awips2-gfesuite-server" + buildRPM "awips2-localapps-environment" + buildRPM "awips2-data.hdf5-topo" + buildRPM "awips2-data.gfe" + unpackHttpdPypies + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-httpd-pypies" + buildJava + buildRPM "awips2-groovy" + buildLocalizationRPMs + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-edex-environment" + buildRPM "awips2-notification" + buildRPM "awips2-python-shapely" + buildRPM "awips2-postgres" + buildRPM "awips2-database" + buildRPM "awips2-maps-database" + buildRPM "awips2-ncep-database" + buildRPM "awips2-pgadmin3" + buildRPM "awips2-ldm" + exit 0 +fi + +if [ "${1}" = "-ade" ]; then + echo "INFO: AWIPS II currently does not support a 64-bit version of the ADE." + exit 0 + buildRPM "awips2-eclipse" + + exit 0 +fi + +if [ "${1}" = "-viz" ]; then + buildRPM "awips2-common-base" + buildCAVE + if [ $? -ne 0 ]; then + exit 1 + fi + buildRPM "awips2-alertviz" + + exit 0 +fi + +if [ "${1}" = "-edex" ]; then + buildRPM "awips2-common-base" + buildRPM "awips2-edex-environment" + buildEDEX + if [ $? -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + +if [ "${1}" = "-qpid" ]; then + buildQPID + if [ $? -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + +if [ "${1}" = "-ldm" ]; then + buildRPM "awips2-ldm" + + exit 0 +fi + + +if [ "${1}" = "-awips2" ]; then + buildRPM "awips2" + + exit 0 +fi + +# Use the custom flag for selecting specific rpms to build +if [ "${1}" = "-custom" ]; then + #unpackHttpdPypies + #if [ $? -ne 0 ]; then + # exit 1 + #fi + #buildRPM "awips2-httpd-pypies" + #buildRPM "awips2-adapt-native" + #buildRPM "awips2-hydroapps-shared" + #buildRPM "awips2-ant" + buildRPM "awips2-python-dynamicserialize" + #buildRPM "awips2-java" + #buildRPM "awips2-tools" + + exit 0 +fi + + +if [ "${1}" = "-package" ]; then + repository_directory="awips2-repository-${AWIPSII_VERSION}-${AWIPSII_RELEASE}" + if [ -d ${WORKSPACE}/${repository_directory} ]; then + rm -rf ${WORKSPACE}/${repository_directory} + if [ $? -ne 0 ]; then + exit 1 + fi + fi + mkdir -p ${WORKSPACE}/${repository_directory}/${AWIPSII_VERSION}-${AWIPSII_RELEASE} + if [ $? -ne 0 ]; then + exit 1 + fi + + cp -r ${AWIPSII_TOP_DIR}/RPMS/* \ + ${WORKSPACE}/${repository_directory}/${AWIPSII_VERSION}-${AWIPSII_RELEASE} + if [ $? -ne 0 ]; then + exit 1 + fi + + rpms_directory="${WORKSPACE}/rpms" + comps_xml="${rpms_directory}/common/yum/arch.x86_64/comps.xml" + cp -v ${comps_xml} ${WORKSPACE}/${repository_directory} + if [ $? -ne 0 ]; then + exit 1 + fi + + pushd . > /dev/null + cd ${WORKSPACE} + tar -cvf ${repository_directory}.tar ${repository_directory} + RC=$? + popd > /dev/null + if [ ${RC} -ne 0 ]; then + exit 1 + fi + + exit 0 +fi + +usage +exit 0 From 1fc23c39928bf4fe7f1514dede2039751bdd8ca9 Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Mon, 4 Nov 2013 11:42:26 -0600 Subject: [PATCH 16/26] Issue #2502 Add data access factory for model sounding. Former-commit-id: 5d1fb6d4e40bf4b6c7dfd4b1db1f07512fa4169e [formerly bebfcc7555db1669f2911d4cf15b8f8ff0ea9c3e] [formerly e02ace280904562e7dd489850b626004c8c07f42] [formerly c2b14489bce79c2d8563cf22490b2600b8c733cc [formerly e02ace280904562e7dd489850b626004c8c07f42 [formerly 65758112879a9007adb5c83721e47217b5eb1cd6]]] Former-commit-id: c2b14489bce79c2d8563cf22490b2600b8c733cc Former-commit-id: fbc1abf40a555c45b4f470dadf70c9fbe6ef8af3 [formerly bf3bed979f9a82847f274a42ab586026645ac91c] Former-commit-id: 226e5b2261f6b9f057503ac9a00920d042a88ef7 --- .../META-INF/MANIFEST.MF | 10 +- .../modelsounding-common-dataaccess.xml | 29 ++ .../dataaccess/PointDataAccessFactory.java | 484 ++++++++++++++++++ 3 files changed, 521 insertions(+), 2 deletions(-) create mode 100644 edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-common-dataaccess.xml create mode 100644 edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/dataaccess/PointDataAccessFactory.java diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.edex.plugin.modelsounding/META-INF/MANIFEST.MF index c08c358715..760727d8ce 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.edex.plugin.modelsounding/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Modelsounding Plug-in Bundle-SymbolicName: com.raytheon.edex.plugin.modelsounding -Bundle-Version: 1.12.1174.qualifier +Bundle-Version: 1.13.0.qualifier Eclipse-RegisterBuddy: com.raytheon.edex.common, com.raytheon.uf.common.serialization Bundle-Vendor: RAYTHEON Require-Bundle: com.raytheon.edex.common, @@ -14,7 +14,13 @@ Require-Bundle: com.raytheon.edex.common, com.raytheon.uf.common.site;bundle-version="1.12.1174", com.raytheon.uf.common.status;bundle-version="1.12.1174", org.apache.commons.lang;bundle-version="2.3.0", - com.google.guava;bundle-version="1.0.0" + com.google.guava;bundle-version="1.0.0", + javax.measure, + com.raytheon.uf.common.comm, + com.raytheon.uf.common.dataaccess, + com.raytheon.uf.common.dataplugin.level, + com.raytheon.uf.common.dataquery, + com.raytheon.uf.common.serialization.comm Export-Package: com.raytheon.edex.plugin.modelsounding, com.raytheon.edex.plugin.modelsounding.common, com.raytheon.edex.plugin.modelsounding.dao, diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-common-dataaccess.xml b/edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-common-dataaccess.xml new file mode 100644 index 0000000000..163fd374aa --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-common-dataaccess.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + pressure + temperature + specHum + omega + uComp + vComp + cldCvr + + + + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/dataaccess/PointDataAccessFactory.java b/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/dataaccess/PointDataAccessFactory.java new file mode 100644 index 0000000000..b642487b9f --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/dataaccess/PointDataAccessFactory.java @@ -0,0 +1,484 @@ +/** + * 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.edex.plugin.modelsounding.dataaccess; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import javax.measure.unit.Unit; +import javax.measure.unit.UnitFormat; + +import com.raytheon.uf.common.comm.CommunicationException; +import com.raytheon.uf.common.dataaccess.DataAccessLayer; +import com.raytheon.uf.common.dataaccess.IDataRequest; +import com.raytheon.uf.common.dataaccess.exception.DataRetrievalException; +import com.raytheon.uf.common.dataaccess.exception.UnsupportedOutputTypeException; +import com.raytheon.uf.common.dataaccess.geom.IGeometryData; +import com.raytheon.uf.common.dataaccess.geom.IGeometryData.Type; +import com.raytheon.uf.common.dataaccess.grid.IGridData; +import com.raytheon.uf.common.dataaccess.impl.AbstractDataPluginFactory; +import com.raytheon.uf.common.dataaccess.impl.DefaultGeometryData; +import com.raytheon.uf.common.dataplugin.level.LevelFactory; +import com.raytheon.uf.common.dataplugin.level.MasterLevel; +import com.raytheon.uf.common.dataquery.requests.DbQueryRequest; +import com.raytheon.uf.common.dataquery.requests.RequestConstraint; +import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType; +import com.raytheon.uf.common.dataquery.responses.DbQueryResponse; +import com.raytheon.uf.common.pointdata.PointDataConstants; +import com.raytheon.uf.common.pointdata.PointDataContainer; +import com.raytheon.uf.common.pointdata.PointDataDescription; +import com.raytheon.uf.common.pointdata.PointDataServerRequest; +import com.raytheon.uf.common.pointdata.PointDataView; +import com.raytheon.uf.common.serialization.comm.RequestRouter; +import com.raytheon.uf.common.time.DataTime; +import com.raytheon.uf.common.time.TimeRange; +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.GeometryFactory; + +/** + * Data Access Factory for retrieving point data as a geometry. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Oct 31, 2013  2502     bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class PointDataAccessFactory extends AbstractDataPluginFactory { + + // TODO this should be in PointDataServerRequest + private static final String REQUEST_PARAMETERS_KEY = "requestedParameters"; + + // TODO this should be in PointDataServerRequest + private static final String REQUEST_MODE_KEY = "mode"; + + // TODO this should be in PointDataServerRequest + private static final String REQUEST_MODE_2D = "select2d"; + + private static class TwoDimensionalParameterGroup { + + public final String countParameter; + + public final String levelParameter; + + public final String levelType; + + public final String[] parameters; + + public TwoDimensionalParameterGroup(String countParameter, + String levelParameter, String levelType, String[] parameters) { + super(); + this.countParameter = countParameter; + this.levelParameter = levelParameter; + this.levelType = levelType; + this.parameters = parameters; + } + + } + + private String locationDatabaseKey = "location.stationId"; + + private String locationPointDataKey = PointDataConstants.DATASET_STATIONID; + + private String latitudePointDataKey = "latitude"; + + private String longitudePointDataKey = "longitude"; + + private String refTimePointDataKey = PointDataConstants.DATASET_REFTIME; + + private String fcstHrPointDataKey = PointDataConstants.DATASET_FORECASTHR; + + private Map parameters2D = new HashMap(); + + @Override + public String[] getAvailableLocationNames(IDataRequest request) { + return getAvailableLocationNames(request, locationDatabaseKey); + } + + @Override + public IGeometryData[] getGeometryData(IDataRequest request, + DataTime... times) { + /* + * Point data uses PointDataServerRequest instead of the DbQueryRequest + * that is used in AbstractDataPluginFactory. Override this method so + * the DbQueryRequest can be converted to a PointDataServerRequest + */ + validateRequest(request); + DbQueryRequest dbQueryRequest = this + .buildDbQueryRequest(request, times); + return getGeometryData(request, dbQueryRequest); + } + + @Override + public IGeometryData[] getGeometryData(IDataRequest request, + TimeRange timeRange) { + /* + * Point data uses PointDataServerRequest instead of the DbQueryRequest + * that is used in AbstractDataPluginFactory. Override this method so + * the DbQueryRequest can be converted to a PointDataServerRequest + */ + validateRequest(request); + DbQueryRequest dbQueryRequest = this.buildDbQueryRequest(request, + timeRange); + return getGeometryData(request, dbQueryRequest); + } + + @Override + protected IGeometryData[] getGeometryData(IDataRequest request, + DbQueryResponse dbQueryResponse) { + /* + * Since the public getGeometryData methods have been overriden, this is + * now unreachable code, but since it is an abstract method in the super + * class it must be implemented. + */ + throw new UnsupportedOperationException( + "This method should be unreachable"); + } + + @Override + protected IGridData[] getGridData(IDataRequest request, + DbQueryResponse dbQueryResponse) { + /* + * Point data cannot be gridded, so don't even try. + */ + throw new UnsupportedOutputTypeException(request.getDatatype(), "grid"); + } + + @Override + protected Map buildConstraintsFromRequest( + IDataRequest request) { + Map rcMap = new HashMap(); + String[] locations = request.getLocationNames(); + if (locations != null && locations.length != 0) { + RequestConstraint rc = new RequestConstraint(); + rc.setConstraintType(ConstraintType.IN); + rc.setConstraintValueList(locations); + rcMap.put(locationDatabaseKey, rc); + } + Map identifiers = request.getIdentifiers(); + if (identifiers != null) { + for (Entry entry : identifiers.entrySet()) { + rcMap.put(entry.getKey(), new RequestConstraint(entry + .getValue().toString())); + } + } + return rcMap; + } + + /** + * + * Request point data from the server and convert to {@link IGeometryData} + * + * @param request + * the original request from the {@link DataAccessLayer} + * @param dbQueryRequest + * the request generated by {@link AbstractDataPluginFactory}, + * this will be converted into a {@link PointDataServerRequest}. + * @return {@link IGeometryData} + */ + protected IGeometryData[] getGeometryData(IDataRequest request, + DbQueryRequest dbQueryRequest) { + PointDataServerRequest serverRequest = convertRequest(request, + dbQueryRequest); + + PointDataContainer pdc = null; + try { + pdc = (PointDataContainer) RequestRouter.route(serverRequest); + } catch (Exception e) { + throw new DataRetrievalException( + "Unable to complete the PointDataRequestMessage for request: " + + request, e); + } + LevelFactory lf = LevelFactory.getInstance(); + /* Convert the point data container into a list of IGeometryData */ + List result = new ArrayList( + pdc.getAllocatedSz()); + for (int i = 0; i < pdc.getCurrentSz(); i += 1) { + PointDataView pdv = pdc.readRandom(i); + DefaultGeometryData data = createNewGeometryData(pdv); + try { + data.setLevel(lf.getLevel(LevelFactory.UNKNOWN_LEVEL, 0.0)); + } catch (CommunicationException e) { + throw new DataRetrievalException( + "Unable to retrieve level data for request: " + request, + e); + } + Set parameters2D = new HashSet(); + for (String parameter : request.getParameters()) { + if (pdc.getParameters().contains(parameter)) { + int dim = pdc.getDimensions(parameter); + if (dim == 1) { + Unit unit = pdv.getUnit(parameter); + PointDataDescription.Type type = pdv.getType(parameter); + if (type == PointDataDescription.Type.STRING) { + data.addData(parameter, pdv.getString(parameter), + Type.STRING, unit); + } else { + data.addData(parameter, pdv.getNumber(parameter), + unit); + } + } else if (this.parameters2D.containsKey(parameter)) { + parameters2D.add(this.parameters2D.get(parameter)); + } else { + throw new DataRetrievalException( + "PointDataAccessFactory cannot handle " + dim + + "D parameters: " + parameter); + } + } + } + for (TwoDimensionalParameterGroup p2d : parameters2D) { + result.addAll(make2DData(request, p2d, pdv)); + } + if (!data.getParameters().isEmpty()) { + result.add(data); + } + } + return result.toArray(new IGeometryData[0]); + } + + /** + * Pull the constraints ouf of a {@link DbQueryRequest} and combine the + * information with an {@link IDataRequest} to build a + * {@link PointDataServerRequest}. This is done because + * {@link AbstractDataPluginFactory} makes really nice DbQueryRequests but + * we can't use them for point data. + * + * @param request + * @param dbQueryRequest + * @return + */ + private PointDataServerRequest convertRequest(IDataRequest request, + DbQueryRequest dbQueryRequest) { + Map constraints = dbQueryRequest + .getConstraints(); + constraints.put(REQUEST_MODE_KEY, + new RequestConstraint(REQUEST_MODE_2D)); + /* + * Figure out what parameters we actually need. + */ + Set parameters = new HashSet(); + Set parameters2D = new HashSet(); + + for (String parameter : request.getParameters()) { + /* + * Make sure that any 2D parameters also have the count parameter + * requested. + */ + TwoDimensionalParameterGroup p2d = this.parameters2D.get(parameter); + if (p2d != null) { + parameters.add(p2d.countParameter); + parameters.add(p2d.levelParameter); + parameters2D.add(p2d); + } + parameters.add(parameter); + } + /* Always request location parameters */ + parameters.add(locationPointDataKey); + parameters.add(latitudePointDataKey); + parameters.add(longitudePointDataKey); + parameters.add(refTimePointDataKey); + if (fcstHrPointDataKey != null) { + parameters.add(fcstHrPointDataKey); + } + + RequestConstraint rc = new RequestConstraint(); + rc.setConstraintType(ConstraintType.IN); + rc.setConstraintValueList(parameters.toArray(new String[0])); + constraints.put(REQUEST_PARAMETERS_KEY, rc); + + return new PointDataServerRequest(constraints); + } + + /** + * Pull out location and time data from a {@link PointDataView} to build a + * {@link DefaultGeometryData}. + * + * @param pdv + * view for a single record + * @return {@link DefaultGeometryData} with locationName, time, and geometry + * set. + */ + private DefaultGeometryData createNewGeometryData(PointDataView pdv) { + DefaultGeometryData data = new DefaultGeometryData(); + data.setLocationName(pdv.getString(locationPointDataKey)); + long refTime = pdv.getNumber(refTimePointDataKey).longValue(); + if (fcstHrPointDataKey != null) { + int fcstTime = pdv.getNumber(fcstHrPointDataKey).intValue(); + data.setDataTime(new DataTime(new Date(refTime), fcstTime)); + } else { + data.setDataTime(new DataTime(new Date(refTime))); + } + Coordinate c = new Coordinate(pdv.getFloat(longitudePointDataKey), + pdv.getFloat(latitudePointDataKey)); + data.setGeometry(new GeometryFactory().createPoint(c)); + // TODO python will break if attributes is null + data.setAttributes(new HashMap(0)); + return data; + } + + /** + * Make a {@link IGeometryData} object for each level in a 2 dimensional + * data set. + * + * @param request + * the original request + * @param p2d + * The 2d Parameter group + * @param pdv + * pdv contining data. + * @return One IGeometryData for each valid level in the 2d group. + */ + private List make2DData(IDataRequest request, + TwoDimensionalParameterGroup p2d, PointDataView pdv) { + List requestParameters = Arrays.asList(request.getParameters()); + LevelFactory lf = LevelFactory.getInstance(); + int count = pdv.getInt(p2d.countParameter); + List result = new ArrayList(count); + for (int j = 0; j < count; j += 1) { + /* Clone the data, not level or parameters though */ + DefaultGeometryData leveldata = createNewGeometryData(pdv); + double levelValue = pdv.getNumberAllLevels(p2d.levelParameter)[j] + .doubleValue(); + String levelUnit = UnitFormat.getUCUMInstance().format( + pdv.getUnit(p2d.levelParameter)); + try { + leveldata.setLevel(lf.getLevel(p2d.levelType, levelValue, + levelUnit)); + } catch (CommunicationException e) { + throw new DataRetrievalException( + "Unable to retrieve level data for request: " + request, + e); + } + for (String parameter : p2d.parameters) { + if (requestParameters.contains(parameter)) { + Unit unit = pdv.getUnit(parameter); + PointDataDescription.Type type = pdv.getType(parameter); + if (type == PointDataDescription.Type.STRING) { + leveldata.addData(parameter, + pdv.getStringAllLevels(parameter)[j], + Type.STRING, unit); + } else { + leveldata.addData(parameter, + pdv.getNumberAllLevels(parameter)[j], unit); + } + } + } + result.add(leveldata); + } + return result; + } + + /** + * Point data types with 2 dimensions need to register so the 2d parameters + * can be grouped appropriately + * + * @param countParameter + * parameter name of an integer parameter identifying the number + * of valid levels. + * @param levelParameter + * parameter which should be used to build the level object in + * IGeometryData, for example "pressure" + * @param levelType + * {@link MasterLevel} name for the levelParameter, for example + * "MB" + * @param parameters + * all the parameters that are valid on the same 2D levels. + * @return countParameter is returned so spring can have a bean. + */ + public String register2D(String countParameter, String levelParameter, + String levelType, String[] parameters) { + TwoDimensionalParameterGroup td = new TwoDimensionalParameterGroup( + countParameter, levelParameter, levelType, parameters); + for (String parameter : parameters) { + parameters2D.put(parameter, td); + } + return countParameter; + } + + /** + * @param locationDatabaseKey + * The hibernate field name of the field that is used to identify + * location names. Default values is "location.stationId" + */ + public void setLocationDatabaseKey(String locationDatabaseKey) { + this.locationDatabaseKey = locationDatabaseKey; + } + + /** + * @param locationPointDataKey + * The point data key that matches the location database key. + * Defaults to "stationId" + */ + public void setLocationPointDataKey(String locationPointDataKey) { + this.locationPointDataKey = locationPointDataKey; + } + + /** + * @param latitudePointDataKey + * The point data key of the station latitude. Default value is + * "latitude" + */ + public void setLatitudePointDataKey(String latitudePointDataKey) { + this.latitudePointDataKey = latitudePointDataKey; + } + + /** + * @param longitudePointDataKey + * The point data key of the station longitude. Default value is + * "longitude" + */ + public void setLongitudePointDataKey(String longitudePointDataKey) { + this.longitudePointDataKey = longitudePointDataKey; + } + + /** + * @param refTimePointDataKey + * The point data key of the reference time. Default value is + * "refTime" + */ + public void setRefTimePointDataKey(String refTimePointDataKey) { + this.refTimePointDataKey = refTimePointDataKey; + } + + /** + * @param fcstHrPointDataKey + * The point data key of the forecast hour. Default value is + * "forecastHr". For live data with no forecast times this can be + * set to null so that it is not retrieved. + */ + public void setFcstHrPointDataKey(String fcstHrPointDataKey) { + this.fcstHrPointDataKey = fcstHrPointDataKey; + } + +} From 31b3bb3645badd0e058b95815e3c1d08789d97ac Mon Sep 17 00:00:00 2001 From: Roger Ferrel Date: Tue, 5 Nov 2013 12:45:37 -0600 Subject: [PATCH 17/26] Issue #2497 Change process root directory to /archive. Change-Id: Ib5cecb7c0af0e844c4ee37b5dc7fb129023048dc Former-commit-id: 0a1ed62dd1402f02664c1cdca2bdd5912b78902d [formerly 484549ce4a869b945c4f80f899efe040fd53af63] [formerly acacd515a636f2ee61b052464593a32fcc59862e] [formerly 2f8903478e8a26d5530a8dc79269e64658a74020 [formerly acacd515a636f2ee61b052464593a32fcc59862e [formerly 6c932f08915704fcdf44b66ad396175ccd7f544f]]] Former-commit-id: 2f8903478e8a26d5530a8dc79269e64658a74020 Former-commit-id: 72a1519ad0df774b7a58c9deccd83a584d643b55 [formerly 553e189b056badbefc9bed405887b4e6dc909114] Former-commit-id: aee4d90569d90cc58b1036a359a5117512134133 --- .../common_static/base/archiver/purger/PROCESSED_DATA.xml | 5 +++-- .../utility/common_static/base/archiver/purger/RAW_DATA.xml | 2 +- edexOsgi/com.raytheon.uf.edex.base.feature/feature.xml | 6 ------ .../res/spring/maintenance-ingest.xml | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml index 6376546ab5..8a6fc621ee 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml +++ b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml @@ -25,7 +25,8 @@ * ============ ========== =========== ========================== * Jun 20, 2013 1966 rferrel Initial creation * Aug 05, 2013 2224 rferrel Changes to add dataSet tags. - * Oct 01, 2013 2147 rfrrel Date time stamp no longer requires an hour field. + * Oct 01, 2013 2147 rferrel Date time stamp no longer requires an hour field. + * Nov 05, 2013 2497 rferrel Change root directory. * * @author rferrel * @version 1.0 @@ -129,7 +130,7 @@ --> Processed - /awips2/edex/data/archive/ + /archive/ 24 Decision Assistance diff --git a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml index 5b7eb5cd63..8d24cbb9f2 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml +++ b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml @@ -25,7 +25,7 @@ * ============ ========== =========== ========================== * Jun 20, 2013 1966 rferrel Initial creation * Aug 05, 2013 2224 rferrel Changes to add dataSet tags. - * Oct 01, 2013 2147 rfrrel Date time stamp no longer requires an hour field. + * Oct 01, 2013 2147 rferrel Date time stamp no longer requires an hour field. * * @author rferrel * @version 1.0 diff --git a/edexOsgi/com.raytheon.uf.edex.base.feature/feature.xml b/edexOsgi/com.raytheon.uf.edex.base.feature/feature.xml index 547e059577..86abdf2f3c 100644 --- a/edexOsgi/com.raytheon.uf.edex.base.feature/feature.xml +++ b/edexOsgi/com.raytheon.uf.edex.base.feature/feature.xml @@ -183,10 +183,4 @@ install-size="0" version="0.0.0"/> - - diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/res/spring/maintenance-ingest.xml b/edexOsgi/com.raytheon.uf.edex.maintenance/res/spring/maintenance-ingest.xml index 65ed950ef8..d2d8f16110 100644 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/res/spring/maintenance-ingest.xml +++ b/edexOsgi/com.raytheon.uf.edex.maintenance/res/spring/maintenance-ingest.xml @@ -9,7 +9,7 @@ - + From 324b57d843e2c04ec79f6554dfd0ce2a9484260a Mon Sep 17 00:00:00 2001 From: Richard Peter Date: Tue, 5 Nov 2013 10:07:17 -0600 Subject: [PATCH 18/26] Issue #2499: Update Wes2Bridge Configuration and logging. Change-Id: I95a530bc8b647c58cff36f449d55bff39943fbc9 Former-commit-id: d76bd3b8ae7440592af5e97387f79b6f57bc1873 [formerly 0566c1976ecb95340710cbe566d6983160d3cbbf] [formerly 73d0d1236cf5172b74d5a9c5a50c3fca4f637acc] [formerly 55b226e104302be8a277c466284b5acaeac20f54 [formerly 73d0d1236cf5172b74d5a9c5a50c3fca4f637acc [formerly 9449bc5f562fd638e0a02ea6c2dc4c6828e73561]]] Former-commit-id: 55b226e104302be8a277c466284b5acaeac20f54 Former-commit-id: de953d3223b133cc7897e1be8e5c67e47a8bc0aa [formerly 0be00ed984ae13dd64b3ea6d6c01b3f4479e3fb8] Former-commit-id: 0a5323a7400f893d412e240d812c1437b105ece2 --- edexOsgi/build.edex/esb/conf/log4j-ingest.xml | 9 +- .../META-INF/MANIFEST.MF | 6 +- .../TextArchiveFileNameFormatter.java | 7 +- .../archive/config/ArchiveConfigManager.java | 7 +- .../dataplugin/text/db/StdTextProduct.java | 23 +- .../uf/common/time/util/TimeUtil.java | 67 ++++- .../META-INF/MANIFEST.MF | 12 +- .../res/spring/archive-spring.xml | 71 ++++++ .../res/spring/archivepurger-spring.xml | 33 --- ...m.raytheon.uf.edex.archive.cron.properties | 11 +- .../uf/edex/archive/DataArchiver.java | 138 +++++++++++ .../uf/edex}/archive/DatabaseArchiver.java | 77 ++---- ...DefaultPluginArchiveFileNameFormatter.java | 4 +- .../uf/edex}/archive/IDataArchiver.java | 6 +- .../IPluginArchiveFileNameFormatter.java | 7 +- .../uf/edex}/archive/IPluginArchiver.java | 9 +- .../uf/edex/archive/purge/ArchivePurger.java | 21 +- .../META-INF/MANIFEST.MF | 19 +- ...f.common.serialization.ISerializableObject | 1 - .../component-deploy.xml | 8 - .../res/spring/maintenance-ingest.xml | 46 +--- .../maintenance/archive/DataArchiver.java | 232 ------------------ .../archive/DataStoreArchiver.java | 79 ------ .../archive/config/DataArchiveConfig.java | 131 ---------- 24 files changed, 373 insertions(+), 651 deletions(-) create mode 100644 edexOsgi/com.raytheon.uf.edex.archive/res/spring/archive-spring.xml delete mode 100644 edexOsgi/com.raytheon.uf.edex.archive/res/spring/archivepurger-spring.xml create mode 100644 edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DataArchiver.java rename edexOsgi/{com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance => com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex}/archive/DatabaseArchiver.java (88%) rename edexOsgi/{com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance => com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex}/archive/DefaultPluginArchiveFileNameFormatter.java (98%) rename edexOsgi/{com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance => com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex}/archive/IDataArchiver.java (90%) rename edexOsgi/{com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance => com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex}/archive/IPluginArchiveFileNameFormatter.java (93%) rename edexOsgi/{com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance => com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex}/archive/IPluginArchiver.java (87%) delete mode 100644 edexOsgi/com.raytheon.uf.edex.maintenance/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject delete mode 100644 edexOsgi/com.raytheon.uf.edex.maintenance/component-deploy.xml delete mode 100644 edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataArchiver.java delete mode 100644 edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataStoreArchiver.java delete mode 100644 edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/config/DataArchiveConfig.java diff --git a/edexOsgi/build.edex/esb/conf/log4j-ingest.xml b/edexOsgi/build.edex/esb/conf/log4j-ingest.xml index 7c776b833a..8640e52fe9 100644 --- a/edexOsgi/build.edex/esb/conf/log4j-ingest.xml +++ b/edexOsgi/build.edex/esb/conf/log4j-ingest.xml @@ -169,7 +169,7 @@ - + @@ -177,6 +177,8 @@ + + @@ -277,11 +279,6 @@ - - - - - diff --git a/edexOsgi/com.raytheon.edex.plugin.text/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.edex.plugin.text/META-INF/MANIFEST.MF index a48d919f74..6e7afe265b 100644 --- a/edexOsgi/com.raytheon.edex.plugin.text/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.edex.plugin.text/META-INF/MANIFEST.MF @@ -13,11 +13,11 @@ Require-Bundle: com.raytheon.edex.textdb, com.raytheon.uf.common.serialization.comm, com.raytheon.uf.edex.decodertools;bundle-version="1.0.0", com.raytheon.uf.common.status;bundle-version="1.11.17", - com.raytheon.uf.common.site;bundle-version="1.12.1174" + com.raytheon.uf.common.site;bundle-version="1.12.1174", + com.raytheon.uf.edex.archive Export-Package: com.raytheon.edex.plugin.text, com.raytheon.edex.plugin.text.dao Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Import-Package: com.raytheon.uf.common.dataplugin.text, com.raytheon.uf.common.dataplugin.text.db, - com.raytheon.uf.common.dataplugin.text.request, - com.raytheon.uf.edex.maintenance.archive + com.raytheon.uf.common.dataplugin.text.request diff --git a/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/maintenance/archiver/TextArchiveFileNameFormatter.java b/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/maintenance/archiver/TextArchiveFileNameFormatter.java index e5631a13d1..b795ffb25e 100644 --- a/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/maintenance/archiver/TextArchiveFileNameFormatter.java +++ b/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/maintenance/archiver/TextArchiveFileNameFormatter.java @@ -34,12 +34,12 @@ import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; import com.raytheon.uf.common.dataplugin.text.db.StdTextProduct; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.edex.archive.IPluginArchiveFileNameFormatter; import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.plugin.PluginDao; -import com.raytheon.uf.edex.maintenance.archive.IPluginArchiveFileNameFormatter; /** - * TODO Add Description + * Properly stores StdTextProducts by time. * *
  * 
@@ -48,7 +48,7 @@ import com.raytheon.uf.edex.maintenance.archive.IPluginArchiveFileNameFormatter;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Apr 20, 2012            dgilling     Initial creation
- * 
+ * Nov 05, 2013 2499       rjpeter      Moved IPluginArchiveFileNameFormatter.
  * 
* * @author dgilling @@ -70,6 +70,7 @@ public class TextArchiveFileNameFormatter implements * com.raytheon.uf.edex.database.plugin.PluginDao, java.util.Map, * java.util.Calendar, java.util.Calendar) */ + @SuppressWarnings("rawtypes") @Override public Map> getPdosByFile( String pluginName, PluginDao dao, diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java index 7c7c470ed5..3c82b24d5e 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java @@ -188,7 +188,7 @@ public class ArchiveConfigManager { public Collection getArchives() { String fileName = ArchiveConstants.selectFileName(Type.Retention, null); SelectConfig selections = loadSelection(fileName); - if (selections != null && !selections.isEmpty()) { + if ((selections != null) && !selections.isEmpty()) { try { for (ArchiveSelect archiveSelect : selections.getArchiveList()) { ArchiveConfig archiveConfig = archiveMap.get(archiveSelect @@ -407,7 +407,8 @@ public class ArchiveConfigManager { private Calendar calculateExpiration(ArchiveConfig archive, CategoryConfig category) { Calendar expireCal = TimeUtil.newGmtCalendar(); - int retHours = category == null || category.getRetentionHours() == 0 ? archive + int retHours = (category == null) + || (category.getRetentionHours() == 0) ? archive .getRetentionHours() : category.getRetentionHours(); if (retHours != 0) { expireCal.add(Calendar.HOUR, (-1) * retHours); @@ -453,7 +454,7 @@ public class ArchiveConfigManager { for (LocalizationFile lFile : files) { try { ArchiveConfig archiveConfig = unmarshalArhiveConfigFromXmlFile(lFile); - if (archiveConfig != null && archiveConfig.isValid()) { + if ((archiveConfig != null) && archiveConfig.isValid()) { archiveNameToLocalizationFileMap.put( archiveConfig.getName(), lFile); archiveMap.put(archiveConfig.getName(), archiveConfig); diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.text/src/com/raytheon/uf/common/dataplugin/text/db/StdTextProduct.java b/edexOsgi/com.raytheon.uf.common.dataplugin.text/src/com/raytheon/uf/common/dataplugin/text/db/StdTextProduct.java index a87c33c165..581bc4e7ca 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.text/src/com/raytheon/uf/common/dataplugin/text/db/StdTextProduct.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.text/src/com/raytheon/uf/common/dataplugin/text/db/StdTextProduct.java @@ -58,6 +58,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * 04/06/2010 4734 mhuang Moved from edex server * 17May2010 2187 cjeanbap Change class to be Abstract * 27 May 2012 #647 dgilling Implement getIdentifier/setIdentifier. + * Nov 05, 2013 2499 rjpeter Fix generics. * * * @author jkorman @@ -67,8 +68,8 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public abstract class StdTextProduct extends PersistableDataObject implements - ISerializableObject { +public abstract class StdTextProduct extends + PersistableDataObject implements ISerializableObject { private static final long serialVersionUID = 1L; @@ -185,10 +186,8 @@ public abstract class StdTextProduct extends PersistableDataObject implements * (java.lang.Object) */ @Override - public void setIdentifier(Object identifier) { - if (identifier instanceof StdTextProductId) { - setProdId((StdTextProductId) identifier); - } + public void setIdentifier(StdTextProductId identifier) { + setProdId(identifier); } public String getBbbid() { @@ -227,7 +226,7 @@ public abstract class StdTextProduct extends PersistableDataObject implements Matcher m = ControlCharacterPattern.matcher(this.product); String result = this.product; - for (int i = 0; m.find(); ++i) { + for (; m.find();) { String nonAscii = m.group(); char[] charArr = nonAscii.toCharArray(); if (charArr.length == 1) { @@ -342,10 +341,12 @@ public abstract class StdTextProduct extends PersistableDataObject implements public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((bbbid == null) ? 0 : bbbid.hashCode()); - result = prime * result + ((refTime == null) ? 0 : refTime.hashCode()); - result = prime * result + ((prodId == null) ? 0 : prodId.hashCode()); - result = prime * result + ((product == null) ? 0 : product.hashCode()); + result = (prime * result) + ((bbbid == null) ? 0 : bbbid.hashCode()); + result = (prime * result) + + ((refTime == null) ? 0 : refTime.hashCode()); + result = (prime * result) + ((prodId == null) ? 0 : prodId.hashCode()); + result = (prime * result) + + ((product == null) ? 0 : product.hashCode()); return result; } diff --git a/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java b/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java index cf0d55bb7e..6a45fc1d52 100644 --- a/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java +++ b/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java @@ -52,6 +52,7 @@ import com.raytheon.uf.common.time.domain.api.ITimePoint; * Mar 20, 2013 1774 randerso Add SECONDS_PER_DAY, changed SECONDS_PER_HOUR to int. * Apr 24, 2013 1628 mschenke Added GMT TimeZone Object constant * Jun 05, 2013 DR 16279 D. Friedman Add timeOfDayToAbsoluteTime + * Nov 05, 2013 2499 rjpeter Added prettyDuration. * * * @author njensen @@ -165,6 +166,13 @@ public final class TimeUtil { static final ITimer NULL_CLOCK = new NullClock(); + private static final long[] DURATION_INTERVALS = { MILLIS_PER_YEAR, + MILLIS_PER_WEEK, MILLIS_PER_DAY, MILLIS_PER_HOUR, + MILLIS_PER_MINUTE, MILLIS_PER_SECOND }; + + private static final String[] DURATION_QUALIFIERS = { "y", "w", "d", "h", + "m", "s" }; + /** * The strategy to retrieve the "current time" value from. */ @@ -415,20 +423,24 @@ public final class TimeUtil { } } - /** Converts a time-of-day (in seconds) to an absolute time given an - * absolute reference time. The resulting time is within a day of the - * reference time. - * @param timeOfDaySeconds The time of day in seconds past midnight - * @param referenceTime The reference time (should have GMT time zone) + /** + * Converts a time-of-day (in seconds) to an absolute time given an absolute + * reference time. The resulting time is within a day of the reference time. + * + * @param timeOfDaySeconds + * The time of day in seconds past midnight + * @param referenceTime + * The reference time (should have GMT time zone) * @return */ - public static Calendar timeOfDayToAbsoluteTime(int timeOfDaySeconds, Calendar referenceTime) { + public static Calendar timeOfDayToAbsoluteTime(int timeOfDaySeconds, + Calendar referenceTime) { Calendar targetDay = (Calendar) referenceTime.clone(); - int refTimeTodSeconds = referenceTime.get(Calendar.HOUR_OF_DAY) * SECONDS_PER_HOUR - + referenceTime.get(Calendar.MINUTE) * SECONDS_PER_MINUTE + int refTimeTodSeconds = (referenceTime.get(Calendar.HOUR_OF_DAY) * SECONDS_PER_HOUR) + + (referenceTime.get(Calendar.MINUTE) * SECONDS_PER_MINUTE) + referenceTime.get(Calendar.SECOND); int absTodDiff = Math.abs(refTimeTodSeconds - timeOfDaySeconds); - if (absTodDiff < SECONDS_PER_DAY - absTodDiff) { + if (absTodDiff < (SECONDS_PER_DAY - absTodDiff)) { // nothing; use current targetDay } else if (refTimeTodSeconds < timeOfDaySeconds) { targetDay.add(Calendar.DAY_OF_MONTH, -1); @@ -442,6 +454,43 @@ public final class TimeUtil { return targetDay; } + /** + * Formats millis keeping the two most significant digits. + * + * 1y16w 2d15h 3m5s + * + * @param durationInMillis + * @return + */ + public static String prettyDuration(long durationInMillis) { + StringBuilder timeString = new StringBuilder(); + // handle s/ms separately + for (int i = 0; i < (DURATION_INTERVALS.length - 1); i++) { + long interval = DURATION_INTERVALS[i]; + if (durationInMillis > interval) { + timeString.append(durationInMillis / interval).append( + DURATION_QUALIFIERS[i]); + durationInMillis %= interval; + timeString.append(durationInMillis / DURATION_INTERVALS[i + 1]) + .append(DURATION_QUALIFIERS[i + 1]); + + return timeString.toString(); + } + } + + // seconds/ms + if (durationInMillis > MILLIS_PER_SECOND) { + timeString.append(durationInMillis / MILLIS_PER_SECOND).append('.'); + durationInMillis %= MILLIS_PER_SECOND; + int tenth = (int) (durationInMillis / 100); + timeString.append(tenth).append('s'); + } else { + timeString.append(durationInMillis).append("ms"); + } + + return timeString.toString(); + } + /** * Disabled constructor. */ diff --git a/edexOsgi/com.raytheon.uf.edex.archive/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.archive/META-INF/MANIFEST.MF index dd531b7090..038586a1a9 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.edex.archive/META-INF/MANIFEST.MF @@ -5,13 +5,19 @@ Bundle-SymbolicName: com.raytheon.uf.edex.archive Bundle-Version: 1.0.0.qualifier Bundle-Vendor: RAYTHEON Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Export-Package: com.raytheon.uf.edex.archive.purge +Export-Package: com.raytheon.uf.edex.archive, + com.raytheon.uf.edex.archive.purge Import-Package: com.raytheon.uf.common.archive.config, com.raytheon.uf.common.archive.request Require-Bundle: com.raytheon.uf.common.auth;bundle-version="1.12.1174", - com.raytheon.uf.edex.auth;bundle-version="1.12.1174", + com.raytheon.uf.edex.database, + com.raytheon.uf.common.dataplugin, + com.raytheon.uf.common.datastorage, + com.raytheon.uf.common.localization;bundle-version="1.12.1174", com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174", com.raytheon.uf.common.status;bundle-version="1.12.1174", com.raytheon.uf.common.serialization;bundle-version="1.12.1174", + com.raytheon.uf.common.time, com.raytheon.uf.common.util;bundle-version="1.12.1174", - com.raytheon.uf.common.localization;bundle-version="1.12.1174" + com.raytheon.uf.edex.auth;bundle-version="1.12.1174", + com.raytheon.uf.edex.core diff --git a/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archive-spring.xml b/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archive-spring.xml new file mode 100644 index 0000000000..aa18209389 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archive-spring.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + java.lang.Throwable + + + + + + + + + + + java.lang.Throwable + + + + + + + + + + + + + + + + + java.lang.Throwable + + + + + + + diff --git a/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archivepurger-spring.xml b/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archivepurger-spring.xml deleted file mode 100644 index 8dd6192d7d..0000000000 --- a/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archivepurger-spring.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - java.lang.Throwable - - - - - - - diff --git a/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties b/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties index 9b9705e607..5cdaa2a6c6 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties +++ b/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties @@ -1,6 +1,11 @@ +# enable archive +archive.enable=true # runs database and hdf5 archive for archive server to pull data from archive.cron=0+40+*+*+*+? -# purge archives -archive.purge.cron=0+5+*+*+*+? # enable archive purge -archive.purge.enable=false +archive.purge.enable=true +# purge archives +archive.purge.cron=0+5+0/3+*+*+? + +# to disable a specific archive, use property archive.disable=pluginName,pluginName... +#archive.disable=grid,text,acars \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DataArchiver.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DataArchiver.java new file mode 100644 index 0000000000..73449c929f --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DataArchiver.java @@ -0,0 +1,138 @@ +/** + * 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.archive; + +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.time.util.ITimer; +import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; + +/** + * Handles archiving of data. Has two interfaces for registering data archive. + * Data archived based on archiving for each plugin and general data archive + * programs. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 16, 2011            rjpeter     Initial creation
+ * Nov 05, 2013 2499       rjpeter     Repackaged, updated to use System properties.
+ * 
+ * + * @author rjpeter + * @version 1.0 + */ +public class DataArchiver { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(DataArchiver.class); + + // enables/disables archiving as a whole + private final static String ENABLE_PROPERTY = "archive.enable"; + + // allows for disabling of specific plugins if desired + private final static String DISABLE_PROPERTY = "archive.disable"; + + private final boolean ARCHIVING_ENABLED; + + private final Set DISABLED_PLUGINS; + + private final List pluginArchivers = new LinkedList(); + + private final List dataArchivers = new LinkedList(); + + private String archivePath = null; + + public DataArchiver(String archivePath) { + this.archivePath = archivePath; + ARCHIVING_ENABLED = Boolean.getBoolean(ENABLE_PROPERTY); + String disabledPluginList = System.getProperty(DISABLE_PROPERTY); + if (disabledPluginList != null) { + String[] plugins = disabledPluginList.split(","); + DISABLED_PLUGINS = new HashSet(plugins.length); + for (String plugin : plugins) { + DISABLED_PLUGINS.add(plugin.trim()); + } + } else { + DISABLED_PLUGINS = Collections.emptySet(); + } + } + + public void archivePlugins() { + Thread.currentThread().setName("Archiver"); + if (ARCHIVING_ENABLED) { + ITimer timer = TimeUtil.getTimer(); + timer.start(); + statusHandler.info("Archival of plugin data started"); + + // get list of plugins, ordered by plugin + Set availablePlugins = new TreeSet(PluginRegistry + .getInstance().getRegisteredObjects()); + + for (String pluginName : availablePlugins) { + if (DISABLED_PLUGINS.contains(pluginName)) { + statusHandler.info(pluginName + ": Archiving disabled"); + } else { + for (IPluginArchiver pluginArchiver : pluginArchivers) { + pluginArchiver.archivePlugin(pluginName, archivePath); + } + } + } + + timer.stop(); + statusHandler + .info("Archival of plugin data completed. Time to run: " + + TimeUtil.prettyDuration(timer.getElapsedTime())); + } else { + statusHandler.info("Archival of plugin data disabled, exiting"); + } + } + + public Object registerPluginArchiver(IPluginArchiver archiver) { + if (!pluginArchivers.contains(archiver)) { + pluginArchivers.add(archiver); + } else { + statusHandler.warn("Plugin archiver already registered: " + + archiver); + } + + return this; + } + + public Object registerDataArchiver(IDataArchiver archiver) { + if (!dataArchivers.contains(archiver)) { + dataArchivers.add(archiver); + } else { + statusHandler.warn("Data archiver already registered: " + archiver); + } + + return this; + } +} diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DatabaseArchiver.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java similarity index 88% rename from edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DatabaseArchiver.java rename to edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java index 20f51f2798..e3d7ddb493 100644 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DatabaseArchiver.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java @@ -17,10 +17,8 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.uf.edex.maintenance.archive; +package com.raytheon.uf.edex.archive; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -55,6 +53,7 @@ import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; import com.raytheon.uf.edex.database.DataAccessLayerException; @@ -64,7 +63,6 @@ import com.raytheon.uf.edex.database.cluster.ClusterTask; import com.raytheon.uf.edex.database.cluster.handler.CurrentTimeClusterLockHandler; import com.raytheon.uf.edex.database.plugin.PluginDao; import com.raytheon.uf.edex.database.plugin.PluginFactory; -import com.raytheon.uf.edex.maintenance.archive.config.DataArchiveConfig; /** * This class handles moving processed data to the archiver directory. @@ -78,7 +76,7 @@ import com.raytheon.uf.edex.maintenance.archive.config.DataArchiveConfig; * Nov 17, 2011 rjpeter Initial creation * Jan 18, 2013 1469 bkowal Removed the hdf5 data directory. * Oct 23, 2013 2478 rferrel Make date format thread safe. - * + * Nov 05, 2013 2499 rjpeter Repackaged, removed config files, always compresses. * * * @author rjpeter @@ -125,8 +123,7 @@ public class DatabaseArchiver implements IPluginArchiver { } @Override - public void archivePlugin(String pluginName, String archivePath, - DataArchiveConfig conf) { + public void archivePlugin(String pluginName, String archivePath) { PluginProperties props = PluginRegistry.getInstance() .getRegisteredObject(pluginName); if ((props != null) && (props.getRecord() != null) @@ -135,7 +132,7 @@ public class DatabaseArchiver implements IPluginArchiver { if (recordClass != null) { try { recordClass.asSubclass(PluginDataObject.class); - archivePluginData(pluginName, archivePath, conf); + archivePluginData(pluginName, archivePath); } catch (ClassCastException e) { // not an error, using asSubClass to filter non // PluginDataObjects @@ -145,8 +142,7 @@ public class DatabaseArchiver implements IPluginArchiver { } @SuppressWarnings("rawtypes") - public boolean archivePluginData(String pluginName, String archivePath, - DataArchiveConfig conf) { + public boolean archivePluginData(String pluginName, String archivePath) { SimpleDateFormat dateFormat = TL_DATE_FORMAT.get(); // set archive time Calendar runTime = Calendar.getInstance(); @@ -184,7 +180,7 @@ public class DatabaseArchiver implements IPluginArchiver { Set datastoreFilesToArchive = new HashSet(); startTime = determineStartTime(pluginName, ct.getExtraInfo(), - runTime, dao, conf); + runTime, dao); Calendar endTime = determineEndTime(startTime, runTime); Map> pdoMap = new HashMap>(); @@ -201,7 +197,7 @@ public class DatabaseArchiver implements IPluginArchiver { if ((pdosToSave != null) && !pdosToSave.isEmpty()) { recordCount += savePdoMap(pluginName, archivePath, - pdosToSave, conf.getCompressionEnabled()); + pdosToSave); for (Map.Entry> entry : pdosToSave .entrySet()) { List pdoList = entry.getValue(); @@ -217,8 +213,7 @@ public class DatabaseArchiver implements IPluginArchiver { } if ((pdoMap != null) && !pdoMap.isEmpty()) { - recordCount += savePdoMap(pluginName, archivePath, pdoMap, - conf.getCompressionEnabled()); + recordCount += savePdoMap(pluginName, archivePath, pdoMap); // don't forget to archive the HDF5 for the records that weren't // saved off by the prior while block for (Map.Entry> entry : pdoMap @@ -257,15 +252,11 @@ public class DatabaseArchiver implements IPluginArchiver { try { // data must be older than 30 minutes, and no older than - // hours - // to keep hours need to lookup plugin and see if - // compression - // matches, or embed in configuration the compression - // level on - // archive, but would still need to lookup plugin - ds.copy(outputDir, compRequired, "lastArchived", - 1800000, - conf.getHoursToKeep() * 60000 + 1800000); + // hours to keep hours need to lookup plugin and see if + // compression matches, or embed in configuration the + // compression level on archive, but would still need to + // lookup plugin + ds.copy(outputDir, compRequired, "lastArchived", 0, 0); } catch (StorageException e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage()); @@ -280,10 +271,12 @@ public class DatabaseArchiver implements IPluginArchiver { } if (recordCount > 0) { - statusHandler.info(pluginName + ": successfully archived " - + recordCount + " records in " - + (System.currentTimeMillis() - timimgStartMillis) - + " ms"); + statusHandler.info(pluginName + + ": successfully archived " + + recordCount + + " records in " + + TimeUtil.prettyDuration(System.currentTimeMillis() + - timimgStartMillis)); } else { statusHandler .info(pluginName + ": Found no records to archive"); @@ -309,9 +302,8 @@ public class DatabaseArchiver implements IPluginArchiver { @SuppressWarnings("rawtypes") protected int savePdoMap(String pluginName, String archivePath, - Map> pdoMap, - boolean compressMetadata) throws SerializationException, - IOException { + Map> pdoMap) + throws SerializationException, IOException { int recordsSaved = 0; for (Map.Entry> entry : pdoMap @@ -324,7 +316,7 @@ public class DatabaseArchiver implements IPluginArchiver { path = path.substring(0, path.length() - 3); } - path += (compressMetadata ? ".bin.gz" : ".bin"); + path += ".bin.gz"; File file = new File(path); List pdosToSerialize = entry.getValue(); @@ -337,10 +329,7 @@ public class DatabaseArchiver implements IPluginArchiver { try { // created gzip'd stream - is = (compressMetadata ? new GZIPInputStream( - new FileInputStream(file), 8192) - : new BufferedInputStream( - new FileInputStream(file), 8192)); + is = new GZIPInputStream(new FileInputStream(file), 8192); // transform back for list append @SuppressWarnings("unchecked") @@ -397,10 +386,7 @@ public class DatabaseArchiver implements IPluginArchiver { } // created gzip'd stream - os = (compressMetadata ? new GZIPOutputStream( - new FileOutputStream(file), 8192) - : new BufferedOutputStream(new FileOutputStream(file), - 8192)); + os = new GZIPOutputStream(new FileOutputStream(file), 8192); // Thrift serialize pdo list SerializationUtil.transformToThriftUsingStream(pdosToSerialize, @@ -427,13 +413,11 @@ public class DatabaseArchiver implements IPluginArchiver { * @param extraInfo * @param runTime * @param dao - * @param conf * @return startTime * @throws DataAccessLayerException */ protected Calendar determineStartTime(String pluginName, String extraInfo, - Calendar runTime, PluginDao dao, DataArchiveConfig conf) - throws DataAccessLayerException { + Calendar runTime, PluginDao dao) throws DataAccessLayerException { Calendar startTime = null; SimpleDateFormat dateFormat = TL_DATE_FORMAT.get(); @@ -474,14 +458,7 @@ public class DatabaseArchiver implements IPluginArchiver { } } - // earliest time based on default retention - Calendar earliestTime = Calendar.getInstance(TimeZone - .getTimeZone("GMT")); - earliestTime - .add(Calendar.HOUR, (-1 * conf.getHoursToKeep().intValue())); - - return (startTime.compareTo(earliestTime) < 0) ? earliestTime - : startTime; + return startTime; } /** diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DefaultPluginArchiveFileNameFormatter.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DefaultPluginArchiveFileNameFormatter.java similarity index 98% rename from edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DefaultPluginArchiveFileNameFormatter.java rename to edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DefaultPluginArchiveFileNameFormatter.java index 2cdec811dc..1246c23c10 100644 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DefaultPluginArchiveFileNameFormatter.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DefaultPluginArchiveFileNameFormatter.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.uf.edex.maintenance.archive; +package com.raytheon.uf.edex.archive; import java.io.File; import java.util.Calendar; @@ -51,7 +51,7 @@ import com.raytheon.uf.edex.database.plugin.PluginDao; * Mar 12, 2013 1783 rferrel Replace ArrayList with LinkedList to * remove excess capacity and reduce * time to resize a growing list. - * + * Nov 05, 2013 2499 rjpeter Repackaged * * * @author dgilling diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/IDataArchiver.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IDataArchiver.java similarity index 90% rename from edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/IDataArchiver.java rename to edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IDataArchiver.java index a922e0d4ee..59a035ffae 100644 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/IDataArchiver.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IDataArchiver.java @@ -17,10 +17,10 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.uf.edex.maintenance.archive; +package com.raytheon.uf.edex.archive; /** - * TODO Add Description + * Data Archiver interface * *
  * 
@@ -29,7 +29,7 @@ package com.raytheon.uf.edex.maintenance.archive;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Dec 16, 2011            rjpeter     Initial creation
- * 
+ * Nov 05, 2013 2499       rjpeter     Repackaged
  * 
* * @author rjpeter diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/IPluginArchiveFileNameFormatter.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IPluginArchiveFileNameFormatter.java similarity index 93% rename from edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/IPluginArchiveFileNameFormatter.java rename to edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IPluginArchiveFileNameFormatter.java index 92d2d47b83..b0e106df98 100644 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/IPluginArchiveFileNameFormatter.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IPluginArchiveFileNameFormatter.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.uf.edex.maintenance.archive; +package com.raytheon.uf.edex.archive; import java.util.Calendar; import java.util.List; @@ -28,7 +28,7 @@ import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.plugin.PluginDao; /** - * TODO Add Description + * Interface for archive file name formatters. * *
  * 
@@ -37,7 +37,7 @@ import com.raytheon.uf.edex.database.plugin.PluginDao;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Apr 20, 2012            dgilling     Initial creation
- * 
+ * Nov 05, 2013 2499       rjpeter     Repackaged
  * 
* * @author dgilling @@ -64,6 +64,7 @@ public interface IPluginArchiveFileNameFormatter { * If the DAO is unable to retrieve the records from the * database. */ + @SuppressWarnings("rawtypes") public abstract Map> getPdosByFile( String pluginName, PluginDao dao, Map> pdoMap, diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/IPluginArchiver.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IPluginArchiver.java similarity index 87% rename from edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/IPluginArchiver.java rename to edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IPluginArchiver.java index 1abd3d7f62..879818b5a6 100644 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/IPluginArchiver.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IPluginArchiver.java @@ -17,9 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.uf.edex.maintenance.archive; - -import com.raytheon.uf.edex.maintenance.archive.config.DataArchiveConfig; +package com.raytheon.uf.edex.archive; /** * Interface for archiving data based on plugins. @@ -31,7 +29,7 @@ import com.raytheon.uf.edex.maintenance.archive.config.DataArchiveConfig; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Dec 16, 2011 rjpeter Initial creation - * + * Nov 05, 2013 2499 rjpeter Repackaged * * * @author rjpeter @@ -39,6 +37,5 @@ import com.raytheon.uf.edex.maintenance.archive.config.DataArchiveConfig; */ public interface IPluginArchiver { - public void archivePlugin(String pluginName, String archivePath, - DataArchiveConfig config); + public void archivePlugin(String pluginName, String archivePath); } diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java index 3802050faa..6af9a95018 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java @@ -26,6 +26,8 @@ import com.raytheon.uf.common.archive.config.ArchiveConfigManager; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.util.ITimer; +import com.raytheon.uf.common.time.util.TimeUtil; /** * Purge task to purge archived data based on configured expiration. @@ -41,7 +43,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * Aug 28, 2013 2299 rferrel manager.purgeExpiredFromArchive now returns * number of files purged. * Sep 03, 2013 2224 rferrel Add check to enable/disable purger. - * + * Nov 05, 2013 2499 rjpeter Repackaged * * * @author bgonzale @@ -58,12 +60,17 @@ public class ArchivePurger { * Purge expired elements from the archives. */ public static void purge() { + Thread.currentThread().setName("Purge-Archive"); String enableString = System.getProperty(ENABLE_PROPERTY, "false"); if (Boolean.parseBoolean(enableString)) { - statusHandler.info("::Archive Purged started."); + ITimer timer = TimeUtil.getTimer(); + timer.start(); + statusHandler.info("Archive Purge started."); ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); Collection archives = manager.getArchives(); for (ArchiveConfig archive : archives) { + ITimer archiveTimer = TimeUtil.getTimer(); + archiveTimer.start(); int purgeCount = manager.purgeExpiredFromArchive(archive); if (statusHandler.isPriorityEnabled(Priority.INFO)) { StringBuilder sb = new StringBuilder(archive.getName()); @@ -73,11 +80,17 @@ public class ArchivePurger { if (purgeCount != 1) { sb.append("s"); } - sb.append("."); + sb.append(" in ") + .append(TimeUtil.prettyDuration(archiveTimer + .getElapsedTime())).append("."); statusHandler.info(sb.toString()); } } - statusHandler.info("::Archive Purged finished."); + statusHandler.info("Archive Purge finished. Time to run: " + + TimeUtil.prettyDuration(timer.getElapsedTime())); + } else { + statusHandler.info("Archive Purge disabled, exiting"); } + } } diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.maintenance/META-INF/MANIFEST.MF index 7be9583144..cb074f7ac8 100644 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.edex.maintenance/META-INF/MANIFEST.MF @@ -5,22 +5,11 @@ Bundle-SymbolicName: com.raytheon.uf.edex.maintenance Bundle-Version: 1.0.0.qualifier Bundle-Vendor: RAYTHEON Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Import-Package: com.raytheon.uf.common.dataplugin, - com.raytheon.uf.common.dataplugin.persist, - com.raytheon.uf.common.dataquery.db, +Require-Bundle: com.raytheon.uf.common.dataplugin, com.raytheon.uf.common.datastorage, - com.raytheon.uf.common.localization, com.raytheon.uf.common.serialization, com.raytheon.uf.common.status, - com.raytheon.uf.common.time, com.raytheon.uf.common.util, - com.raytheon.uf.common.util.registry, - com.raytheon.uf.edex.core.dataplugin, - com.raytheon.uf.edex.core.props, - com.raytheon.uf.edex.database, - com.raytheon.uf.edex.database.cluster, - com.raytheon.uf.edex.database.cluster.handler, - com.raytheon.uf.edex.database.plugin, - com.raytheon.uf.edex.pointdata, - org.springframework.orm.hibernate3.support -Export-Package: com.raytheon.uf.edex.maintenance.archive + com.raytheon.uf.edex.core, + com.raytheon.uf.edex.pointdata + diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject b/edexOsgi/com.raytheon.uf.edex.maintenance/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject deleted file mode 100644 index 708c60ff8c..0000000000 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject +++ /dev/null @@ -1 +0,0 @@ -com.raytheon.uf.edex.maintenance.archive.config.DataArchiveConfig diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/component-deploy.xml b/edexOsgi/com.raytheon.uf.edex.maintenance/component-deploy.xml deleted file mode 100644 index 2fa640c974..0000000000 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/component-deploy.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/res/spring/maintenance-ingest.xml b/edexOsgi/com.raytheon.uf.edex.maintenance/res/spring/maintenance-ingest.xml index d2d8f16110..a4e1376efa 100644 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/res/spring/maintenance-ingest.xml +++ b/edexOsgi/com.raytheon.uf.edex.maintenance/res/spring/maintenance-ingest.xml @@ -8,32 +8,10 @@
- - - - - + - - - - - - - - - - - - - - - + @@ -47,23 +25,5 @@ - - - - - - - - java.lang.Throwable - - - - - - - - diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataArchiver.java b/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataArchiver.java deleted file mode 100644 index 991d6a98e2..0000000000 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataArchiver.java +++ /dev/null @@ -1,232 +0,0 @@ -/** - * 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.maintenance.archive; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import com.raytheon.uf.common.localization.IPathManager; -import com.raytheon.uf.common.localization.LocalizationContext; -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; -import com.raytheon.uf.common.localization.LocalizationFile; -import com.raytheon.uf.common.localization.PathManagerFactory; -import com.raytheon.uf.common.serialization.SerializationUtil; -import com.raytheon.uf.common.status.IUFStatusHandler; -import com.raytheon.uf.common.status.UFStatus; -import com.raytheon.uf.common.status.UFStatus.Priority; -import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; -import com.raytheon.uf.edex.maintenance.archive.config.DataArchiveConfig; - -/** - * Handles archiving of data. Has two interfaces for registering data archive. - * Data archived based on archiving for each plugin and general data archive - * programs. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Dec 16, 2011            rjpeter     Initial creation
- * 
- * 
- * - * @author rjpeter - * @version 1.0 - */ -public class DataArchiver { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(DataArchiver.class); - - private List pluginArchivers = new ArrayList(); - - private List dataArchivers = new ArrayList(); - - private String archivePath = null; - - private String defaultPlugin = "default"; - - private String configDir = "archiver"; - - public DataArchiver(String archivePath) { - this.archivePath = archivePath; - } - - public void archivePlugins() { - statusHandler.info("Archival of plugin data starting"); - - // get list of plugins, ordered by plugin - Set availablePlugins = new TreeSet(PluginRegistry - .getInstance().getRegisteredObjects()); - - Map configs = getDataArchiveConfigs(); - DataArchiveConfig defaultConf = configs.get(defaultPlugin); - File baseArchive = new File(archivePath); - - for (String pluginName : availablePlugins) { - DataArchiveConfig conf = configs.get(pluginName); - if (conf == null) { - conf = defaultConf; - } - - if (Boolean.TRUE.equals(conf.getArchivingEnabled())) { - for (IPluginArchiver pluginArchiver : pluginArchivers) { - pluginArchiver.archivePlugin(pluginName, archivePath, conf); - } - } - } - - statusHandler.info("Archival of plugin data complete"); - } - - public Object registerPluginArchiver(IPluginArchiver archiver) { - if (!pluginArchivers.contains(archiver)) { - pluginArchivers.add(archiver); - } else { - statusHandler.warn("Plugin archiver already registered: " - + archiver); - } - - return this; - } - - public Object registerDataArchiver(IDataArchiver archiver) { - if (!dataArchivers.contains(archiver)) { - dataArchivers.add(archiver); - } else { - statusHandler.warn("Data archiver already registered: " + archiver); - } - - return this; - } - - private Map getDataArchiveConfigs() { - Map configs = new HashMap(); - IPathManager pathMgr = PathManagerFactory.getPathManager(); - // process in reverse order so BASE is processed before CONFIGURED - // before SITE - List contexts = Arrays.asList(pathMgr - .getLocalSearchHierarchy(LocalizationType.COMMON_STATIC)); - Collections.reverse(contexts); - String[] extensions = new String[] { "xml" }; - for (LocalizationContext ctx : contexts) { - statusHandler.info("Loading context: " + ctx); - LocalizationFile[] lfs = pathMgr.listFiles(ctx, configDir, - extensions, false, true); - if (lfs != null && lfs.length > 0) { - for (LocalizationFile lf : lfs) { - String fileName = lf.getName(); - try { - File f = lf.getFile(true); - fileName = f.getAbsolutePath(); - Object obj = SerializationUtil - .jaxbUnmarshalFromXmlFile(f); - if (obj instanceof DataArchiveConfig) { - DataArchiveConfig conf = (DataArchiveConfig) obj; - String plugin = conf.getPluginName(); - if (plugin != null) { - plugin = plugin.trim(); - if (!plugin.isEmpty()) { - configs.put(plugin, conf); - } else { - throw new Exception( - "Configuration file does not specify pluginName"); - } - } else { - throw new Exception( - "Configuration file does not specify pluginName"); - } - } else { - throw new Exception( - "File in wrong format, expected " - + DataArchiveConfig.class - + ", found " + obj.getClass()); - } - } catch (Throwable e) { - statusHandler.error( - "Failed to load archive configuration file: " - + fileName, e); - } - } - } - } - - DataArchiveConfig defaultConf = configs.get(defaultPlugin); - if (defaultConf == null) { - // default plugin didn't load from disk, force a default config - statusHandler - .warn("Failed to find default configuration, using internal defaults"); - defaultConf = new DataArchiveConfig(); - defaultConf.setPluginName(defaultPlugin); - configs.put(defaultPlugin, defaultConf); - } - - if (!defaultConf.isArchivingEnabledSet()) { - defaultConf.setArchivingEnabled(Boolean.TRUE); - } - - if (!defaultConf.isCompressionEnabledSet()) { - defaultConf.setCompressionEnabled(Boolean.TRUE); - } - - if (!defaultConf.isHoursToKeepSet()) { - defaultConf.setHoursToKeep(6); - } - - // override unset fields with default - for (DataArchiveConfig pluginConf : configs.values()) { - if (pluginConf.getPluginName().equals(defaultPlugin)) { - // skip default conf - continue; - } - - if (!pluginConf.isArchivingEnabledSet()) { - pluginConf.setArchivingEnabled(defaultConf - .getArchivingEnabled()); - } - - if (!pluginConf.isCompressionEnabledSet()) { - pluginConf.setCompressionEnabled(defaultConf - .getArchivingEnabled()); - } - - if (!pluginConf.isHoursToKeepSet()) { - pluginConf.setHoursToKeep(defaultConf.getHoursToKeep()); - } - } - - try { - statusHandler.info("DefaultConfiguration:\n" - + SerializationUtil.marshalToXml(defaultConf)); - } catch (Exception e) { - statusHandler.handle(Priority.WARN, "Failed to deserialize config", - e); - } - return configs; - } -} diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataStoreArchiver.java b/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataStoreArchiver.java deleted file mode 100644 index ba7ea799da..0000000000 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/DataStoreArchiver.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * 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.maintenance.archive; - -import java.io.File; - -import com.raytheon.uf.common.datastorage.DataStoreFactory; -import com.raytheon.uf.common.datastorage.IDataStore; -import com.raytheon.uf.common.datastorage.StorageException; -import com.raytheon.uf.common.datastorage.StorageProperties.Compression; -import com.raytheon.uf.common.status.IUFStatusHandler; -import com.raytheon.uf.common.status.UFStatus; -import com.raytheon.uf.common.status.UFStatus.Priority; -import com.raytheon.uf.edex.maintenance.archive.config.DataArchiveConfig; - -/** - * Uses the repack feature of IDataStore to archive data by repacking it to a - * specified compression at the hdf5 dataset level and moving the resulting file - * to the archive dir. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Dec 8, 2011            njensen     Initial creation
- * Jan 14, 2013 1469      bkowal      Removed the hdf5 data directory.
- * Jul 23, 2013 2216      rferrel     Removed the time stamp filter in hdf5 copy.
- * 
- * 
- * - * @author njensen - * @version 1.0 - */ - -public class DataStoreArchiver { - - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(DataStoreArchiver.class); - - private Compression compression = Compression.NONE; - - public DataStoreArchiver(String compression) { - this.compression = Compression.valueOf(compression); - } - - public void archiveFiles(String[] hdf5Files, String archiveDir, - DataArchiveConfig conf) { - for (String hdf5File : hdf5Files) { - IDataStore ds = DataStoreFactory.getDataStore(new File(hdf5File)); - String outputDir = archiveDir; // + dirs of hdf5 file - - try { - // Do not perform time stamp check. - ds.copy(outputDir, compression, null, 0, 0); - } catch (StorageException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage()); - } - } - } -} diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/config/DataArchiveConfig.java b/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/config/DataArchiveConfig.java deleted file mode 100644 index 406e9536a6..0000000000 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/src/com/raytheon/uf/edex/maintenance/archive/config/DataArchiveConfig.java +++ /dev/null @@ -1,131 +0,0 @@ -/** - * 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.maintenance.archive.config; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -/** - * Data archive configuration. Configuration should be pulled from common_static - * localization. Configuration with a pluginName of default will all to all - * plugins. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jan 14, 2012            rjpeter     Initial creation
- * 
- * 
- * - * @author rjpeter - * @version 1.0 - */ -@XmlRootElement -@XmlAccessorType(XmlAccessType.NONE) -public class DataArchiveConfig { - @XmlElement - private String pluginName; - - @XmlElement - private Integer hoursToKeep; - - @XmlElement - private Boolean archivingEnabled; - - @XmlElement - private Boolean compressionEnabled; - - /** - * @return the pluginName - */ - public String getPluginName() { - return pluginName; - } - - /** - * @param pluginName - * the pluginName to set - */ - public void setPluginName(String pluginName) { - this.pluginName = pluginName; - } - - /** - * @return the hoursToKeep - */ - public Integer getHoursToKeep() { - return hoursToKeep; - } - - /** - * @param hoursToKeep - * the hoursToKeep to set - */ - public void setHoursToKeep(Integer hoursToKeep) { - this.hoursToKeep = hoursToKeep; - } - - /** - * @return the archivingEnabled - */ - public Boolean getArchivingEnabled() { - return archivingEnabled; - } - - /** - * @param archivingEnabled - * the archivingEnabled to set - */ - public void setArchivingEnabled(Boolean archivingEnabled) { - this.archivingEnabled = archivingEnabled; - } - - /** - * @param compressionEnabled - * the compressionEnabled to set - */ - public void setCompressionEnabled(Boolean compressionEnabled) { - this.compressionEnabled = compressionEnabled; - } - - /** - * @return the compressionEnabled - */ - public Boolean getCompressionEnabled() { - return compressionEnabled; - } - - public boolean isArchivingEnabledSet() { - return archivingEnabled != null; - } - - public boolean isHoursToKeepSet() { - return hoursToKeep != null; - } - - public boolean isCompressionEnabledSet() { - return (compressionEnabled != null); - } -} From 992690ef611b12e4d90793c27d5d70c001203cfc Mon Sep 17 00:00:00 2001 From: Richard Peter Date: Tue, 5 Nov 2013 15:56:50 -0600 Subject: [PATCH 19/26] Issue #2499: Remove defaultArchiveConfig.xml Former-commit-id: efcd3c6454ce6e653d4710e42347f5cd88848fdb [formerly 6af3e69ec811a8fe9c48aa906a92ed576e2aaf5f] [formerly 7507ae3460e3f4bddbf6a9fd7206e8b0bc578a38] [formerly 055057ed60dd9b7db1f4d80db08709e52eb4ff7d [formerly 7507ae3460e3f4bddbf6a9fd7206e8b0bc578a38 [formerly affca91a2999675f1e91f2add7cb276ae90535af]]] Former-commit-id: 055057ed60dd9b7db1f4d80db08709e52eb4ff7d Former-commit-id: 5ebb5a5308b8cf5aa6810663aaf886c73334b2ea [formerly 406687d67f8c0598196c62e58792c5c29713ea0a] Former-commit-id: bdce762633355b17473c7acc46f2522f96e20bc1 --- .../common_static/base/archiver/defaultArchiveConfig.xml | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 edexOsgi/com.raytheon.uf.edex.maintenance/utility/common_static/base/archiver/defaultArchiveConfig.xml diff --git a/edexOsgi/com.raytheon.uf.edex.maintenance/utility/common_static/base/archiver/defaultArchiveConfig.xml b/edexOsgi/com.raytheon.uf.edex.maintenance/utility/common_static/base/archiver/defaultArchiveConfig.xml deleted file mode 100644 index 5f69229316..0000000000 --- a/edexOsgi/com.raytheon.uf.edex.maintenance/utility/common_static/base/archiver/defaultArchiveConfig.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - default - 6 - false - true - From 3ed0339762d40894b0c5fec5174d9a6897dce3fb Mon Sep 17 00:00:00 2001 From: Richard Peter Date: Wed, 6 Nov 2013 09:41:29 -0600 Subject: [PATCH 20/26] Issue #2499: Update text feature dependency Former-commit-id: f7f33364d972440ed23beb015124994e6bc1c740 [formerly cf4a5d659ca16022ec9e83a8a207dfda1f848ea0] [formerly 361789672b96f3aab423ca5d5dbc83cf4b50152d] [formerly 3910b81d1aee2c78a99a04a07a1ba4143676a7af [formerly 361789672b96f3aab423ca5d5dbc83cf4b50152d [formerly fe6fdf5a457be3e13774c946c9f425feac2bd88d]]] Former-commit-id: 3910b81d1aee2c78a99a04a07a1ba4143676a7af Former-commit-id: cf9089b38edc0d5ca492c9b2c734dbec1392170f [formerly 374710dfffeeda72e6305404f46f0aedfad5c462] Former-commit-id: 4081e959e50d26318a5eb911dff33804cda55f7c --- edexOsgi/com.raytheon.uf.edex.text.feature/feature.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/edexOsgi/com.raytheon.uf.edex.text.feature/feature.xml b/edexOsgi/com.raytheon.uf.edex.text.feature/feature.xml index 49bff7ab36..10df591fb1 100644 --- a/edexOsgi/com.raytheon.uf.edex.text.feature/feature.xml +++ b/edexOsgi/com.raytheon.uf.edex.text.feature/feature.xml @@ -19,6 +19,7 @@ + Date: Wed, 6 Nov 2013 11:43:31 -0600 Subject: [PATCH 21/26] Issue #2499: Fix build Change-Id: I6f5269e3fe424f1c7c77225f9b8aa70218c1845c Former-commit-id: 10764ed80025d0496d95a953850045e8f9f79660 [formerly 15fd2f7a55c89e7d6f56717207bdd6c2f3d7a835] [formerly f3d8768b94a75f083a256a1f778c59719f542e63] [formerly c09f68615cd4178557e786ec23778aae9046ffdc [formerly f3d8768b94a75f083a256a1f778c59719f542e63 [formerly 037b2730e59d52f13d3cb3b50490a57b9befb2c1]]] Former-commit-id: c09f68615cd4178557e786ec23778aae9046ffdc Former-commit-id: 2caca803544425b06082edf14d9c7fc48db84b66 [formerly a653f9625a56c60b27eece29ff3ab1d4ae7b8b08] Former-commit-id: 1b65a09a52077475a7fa087d46418c6b422cbb4f --- cave/com.raytheon.viz.text.feature/feature.xml | 15 +-------------- edexOsgi/build.edex/build.xml | 8 ++++---- .../com.raytheon.edex.feature.uframe/feature.xml | 8 ++++---- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/cave/com.raytheon.viz.text.feature/feature.xml b/cave/com.raytheon.viz.text.feature/feature.xml index a455507f1a..d1fbd0dd9b 100644 --- a/cave/com.raytheon.viz.text.feature/feature.xml +++ b/cave/com.raytheon.viz.text.feature/feature.xml @@ -22,6 +22,7 @@ + - - - - + + + @@ -102,10 +106,6 @@ - - - diff --git a/edexOsgi/com.raytheon.edex.feature.uframe/feature.xml b/edexOsgi/com.raytheon.edex.feature.uframe/feature.xml index 22c3c97dc2..354e29525a 100644 --- a/edexOsgi/com.raytheon.edex.feature.uframe/feature.xml +++ b/edexOsgi/com.raytheon.edex.feature.uframe/feature.xml @@ -68,6 +68,10 @@ id="com.raytheon.uf.edex.grib.feature" version="0.0.0"/> + + @@ -124,8 +128,4 @@ id="com.raytheon.uf.edex.registry.feature" version="0.0.0"/> - - From f583a4cef6f6107cae41fac30615348b1b3904e1 Mon Sep 17 00:00:00 2001 From: Roger Ferrel Date: Tue, 5 Nov 2013 16:47:56 -0600 Subject: [PATCH 22/26] Issue #2478 Add debug infromation. Change-Id: I830a760e2505a744da4962299bf97f46462f4784 Former-commit-id: 89645eca104d19233af481b2b150c89c24758b97 [formerly f198c27f3f7d6f2e3882f6e34763252c9a4a7dd2] [formerly 07a7dd63c3df0e7a5cf3b27001708b536246ee55] [formerly e01b5245429b8041a5a4fb2604d5afd4920ae735 [formerly 07a7dd63c3df0e7a5cf3b27001708b536246ee55 [formerly db0434a66ca415554d1ab0c90586dc7358fd730d]]] Former-commit-id: e01b5245429b8041a5a4fb2604d5afd4920ae735 Former-commit-id: 228271710b56b51b9c4e8ee70ffda8ab1200c391 [formerly 274d52a694f6468f0c205188bcbd5db89f2121b7] Former-commit-id: d10ffdcca7b6314e6232b3df46977d02333bb11f --- .../feature.xml | 6 -- .../uf/edex/archive/DatabaseArchiver.java | 70 ++++++++++++++++--- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/cave/com.raytheon.uf.viz.archive.feature/feature.xml b/cave/com.raytheon.uf.viz.archive.feature/feature.xml index 37b1cd68f2..6b25bdef69 100644 --- a/cave/com.raytheon.uf.viz.archive.feature/feature.xml +++ b/cave/com.raytheon.uf.viz.archive.feature/feature.xml @@ -36,12 +36,6 @@ version="0.0.0" unpack="false"/> - - * @@ -113,6 +115,9 @@ public class DatabaseArchiver implements IPluginArchiver { /** Mapping for plug-in formatters. */ private final Map pluginArchiveFormatters; + /** When true dump the pdos. */ + private final boolean debugArchiver; + /** * The constructor. */ @@ -120,6 +125,7 @@ public class DatabaseArchiver implements IPluginArchiver { pluginArchiveFormatters = new HashMap(); pluginArchiveFormatters.put("default", new DefaultPluginArchiveFileNameFormatter()); + debugArchiver = Boolean.parseBoolean(System.getenv("DEBUG_ARCHIVER")); } @Override @@ -306,19 +312,20 @@ public class DatabaseArchiver implements IPluginArchiver { throws SerializationException, IOException { int recordsSaved = 0; + StringBuilder path = new StringBuilder(); for (Map.Entry> entry : pdoMap .entrySet()) { - String path = archivePath + File.separator + pluginName - + File.separator + entry.getKey(); - + path.setLength(0); + path.append(archivePath).append(File.separator).append(pluginName) + .append(File.separator).append(entry.getKey()); // remove .h5 - if (path.endsWith(".h5")) { - path = path.substring(0, path.length() - 3); + if (path.lastIndexOf(".h5") == (path.length() - 3)) { + path.setLength(path.length() - 3); } + int pathDebugLength = path.length(); + path.append(".bin.gz"); - path += ".bin.gz"; - - File file = new File(path); + File file = new File(path.toString()); List pdosToSerialize = entry.getValue(); recordsSaved += pdosToSerialize.size(); @@ -385,6 +392,11 @@ public class DatabaseArchiver implements IPluginArchiver { file.getParentFile().mkdirs(); } + if (debugArchiver) { + String debugRootName = path.substring(0, pathDebugLength); + dumpPdos(pluginName, pdosToSerialize, debugRootName); + } + // created gzip'd stream os = new GZIPOutputStream(new FileOutputStream(file), 8192); @@ -406,6 +418,48 @@ public class DatabaseArchiver implements IPluginArchiver { return recordsSaved; } + /** + * Dump the record information being archived to a file. + */ + @SuppressWarnings("rawtypes") + private void dumpPdos(String pluginName, + List pdosToSerialize, String debugRootName) { + StringBuilder sb = new StringBuilder(debugRootName); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); + sdf.setTimeZone(TimeZone.getTimeZone("GMT")); + sb.append("_").append(sdf.format(Calendar.getInstance().getTime())) + .append(".txt"); + File file = new File(sb.toString()); + FileWriter writer = null; + try { + PersistableDataObject[] pdoArray = pdosToSerialize + .toArray(new PersistableDataObject[0]); + writer = new FileWriter(file); + statusHandler.info(String.format("Dumping %s records to: %s", + pdoArray.length, file.getAbsolutePath())); + for (int i = 0; i < pdosToSerialize.size(); ++i) { + if (pdoArray[i] instanceof PluginDataObject) { + PluginDataObject pdo = (PluginDataObject) pdoArray[i]; + writer.write(pdo.getDataURI()); + } else { + writer.write(pdoArray[i].toString()); + } + writer.write("\n"); + } + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (Exception e) { + // Ignore + } + writer = null; + } + } + } + /** * Get the plug-in's start time for a query. * From 1f5a97c4abec62566def080b20527307312d01d9 Mon Sep 17 00:00:00 2001 From: Richard Peter Date: Wed, 6 Nov 2013 15:45:23 -0600 Subject: [PATCH 23/26] Issue #2478: Update log message Former-commit-id: 1e10d9e303e9b78802d9572d55a5a2af345ad0a5 [formerly d4bf633bd24fb11dcaafc7959ff539a6b31eede4] [formerly f9faa53eb48c9c9bd33bf0fffef730dbec2f885a] [formerly b0746db723f47744a14e1e2ef26e58d5079ed589 [formerly f9faa53eb48c9c9bd33bf0fffef730dbec2f885a [formerly ab993718b7e4f2b77461226a49bee76813166dbb]]] Former-commit-id: b0746db723f47744a14e1e2ef26e58d5079ed589 Former-commit-id: 1268ba531f54842268c09b3d7604419aa390dbd3 [formerly f1a67f4dc1be3c26213098b0924e6ed85eceedff] Former-commit-id: 6e929c0deea0ba1fe50ad337a55828af11aba417 --- .../raytheon/uf/edex/archive/DatabaseArchiver.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java index e1abccc45d..d07477edeb 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.edex.archive; +import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -26,6 +27,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.Writer; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -125,7 +127,7 @@ public class DatabaseArchiver implements IPluginArchiver { pluginArchiveFormatters = new HashMap(); pluginArchiveFormatters.put("default", new DefaultPluginArchiveFileNameFormatter()); - debugArchiver = Boolean.parseBoolean(System.getenv("DEBUG_ARCHIVER")); + debugArchiver = Boolean.getBoolean("archive.debug.enable"); } @Override @@ -430,17 +432,21 @@ public class DatabaseArchiver implements IPluginArchiver { sb.append("_").append(sdf.format(Calendar.getInstance().getTime())) .append(".txt"); File file = new File(sb.toString()); - FileWriter writer = null; + Writer writer = null; try { PersistableDataObject[] pdoArray = pdosToSerialize .toArray(new PersistableDataObject[0]); - writer = new FileWriter(file); + writer = new BufferedWriter(new FileWriter(file)); statusHandler.info(String.format("Dumping %s records to: %s", pdoArray.length, file.getAbsolutePath())); for (int i = 0; i < pdosToSerialize.size(); ++i) { if (pdoArray[i] instanceof PluginDataObject) { PluginDataObject pdo = (PluginDataObject) pdoArray[i]; - writer.write(pdo.getDataURI()); + if (pdo.getId() != 0) { + // otherwise was read from file + writer.write("" + pdo.getId() + ":"); + writer.write(pdo.getDataURI()); + } } else { writer.write(pdoArray[i].toString()); } From 4d95bba61e8a54964dcd463c3240d5703df9e557 Mon Sep 17 00:00:00 2001 From: Bryan Kowal Date: Wed, 6 Nov 2013 15:57:14 -0600 Subject: [PATCH 24/26] Fix 13.5.3 build; eliminate mix of EDEX and CAVE features Former-commit-id: 21df98b0bc021cf6f601e5dbdb3511dc48aad2f4 [formerly 0f104b036547b141eaf8433638e1da2934a8c07a] [formerly 4f1c08303298754ea98e5fff6d39f6d31366d076] [formerly bb15605aa26db216edc252f31c3f4b31fd05d0d4 [formerly 4f1c08303298754ea98e5fff6d39f6d31366d076 [formerly 8a1605e74c716ae070028df42d61953a19ffefd6]]] Former-commit-id: bb15605aa26db216edc252f31c3f4b31fd05d0d4 Former-commit-id: 0befac69bd8c3c5e0fa05e61b8473d5f24fccdaf [formerly 0bc8cdc9bef621bee8e08a4128acf09afc705364] Former-commit-id: 0b006511dcfe02a245a3fbad346d931056cdbc2e --- cave/com.raytheon.viz.text.feature/feature.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cave/com.raytheon.viz.text.feature/feature.xml b/cave/com.raytheon.viz.text.feature/feature.xml index d1fbd0dd9b..c1c17a287a 100644 --- a/cave/com.raytheon.viz.text.feature/feature.xml +++ b/cave/com.raytheon.viz.text.feature/feature.xml @@ -72,4 +72,18 @@ version="0.0.0" unpack="false"/> + + + + From e3ab7a38e456078ea51f36a01a3b3a1a980f9ca6 Mon Sep 17 00:00:00 2001 From: Richard Peter Date: Wed, 6 Nov 2013 16:03:45 -0600 Subject: [PATCH 25/26] Issue #2478: Remove blank lines in debug Former-commit-id: 81279edc30afe01ac8e177b410683084b5f724bf [formerly f099fb6936a69d823f71d8bb08318ebb104f4e9c] [formerly 357eb795197ea30b8848c8e9dd5960cb7479f416] [formerly 18eff02d7a8a9922d523451dd7f8fc719abfd0fc [formerly 357eb795197ea30b8848c8e9dd5960cb7479f416 [formerly 489528b7869254f69ea65391b576e82e67cbfc8f]]] Former-commit-id: 18eff02d7a8a9922d523451dd7f8fc719abfd0fc Former-commit-id: e63155859c1fd922ae1be9fae52888b1ef1f2982 [formerly 46f19c22ea3892f53c8bb5f8d9c98a1ca5f8d78d] Former-commit-id: b62dd963211c6e8c08e8be33ced8b36214ee3173 --- .../src/com/raytheon/uf/edex/archive/DatabaseArchiver.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java index d07477edeb..056bc09950 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java @@ -446,11 +446,12 @@ public class DatabaseArchiver implements IPluginArchiver { // otherwise was read from file writer.write("" + pdo.getId() + ":"); writer.write(pdo.getDataURI()); + writer.write("\n"); } } else { writer.write(pdoArray[i].toString()); + writer.write("\n"); } - writer.write("\n"); } } catch (Exception e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); From a18f2109cfb9b5b23db86c82acac0ccaa957628a Mon Sep 17 00:00:00 2001 From: Bryan Kowal Date: Wed, 6 Nov 2013 18:24:25 -0600 Subject: [PATCH 26/26] 13.5.3 build "fix" Former-commit-id: b94071a58b58001582b15f917ad15a6a4d9a2f61 [formerly 503762af19c9b8325fcd00c5079004ee4db91e09] [formerly 6692b985f3b4ea6f016d918cd95f9f5dba2ee7ef] [formerly a28133117ce46384976d6a4e07faa442aa529aec [formerly 6692b985f3b4ea6f016d918cd95f9f5dba2ee7ef [formerly 084e906e9f85ebd11cabf6e14e94ac75d25a0af2]]] Former-commit-id: a28133117ce46384976d6a4e07faa442aa529aec Former-commit-id: 120324fb9c6e8815d7af7c3a1fc21863b808696c [formerly ce6d80409d7d9547ccbe266b9385e31d9839d534] Former-commit-id: cdf643510a4dff78e14ab82c38bf4aebd81dc3da --- .../com.raytheon.viz.text.feature/feature.xml | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/cave/com.raytheon.viz.text.feature/feature.xml b/cave/com.raytheon.viz.text.feature/feature.xml index c1c17a287a..f444fcabfd 100644 --- a/cave/com.raytheon.viz.text.feature/feature.xml +++ b/cave/com.raytheon.viz.text.feature/feature.xml @@ -22,9 +22,29 @@ - + + + + + + - - - -

9eP7D@E5ya@@ruviOddv0FAm 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 z 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