From 1792158ef8bb9a7595252ab79fce6040fc1c4c82 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 15 Aug 2012 22:15:20 +0000 Subject: [PATCH] Merge 12.9.1-4 into development_on_ss_builds Former-commit-id: cb46f578791f5b64d6706ae92cfd9c6b5ed375b1 [formerly cb46f578791f5b64d6706ae92cfd9c6b5ed375b1 [formerly a178af491f4b4cd75ed1517f023354bab0b9c8c8]] Former-commit-id: 5a453ee98401bfaa4480243b3165e8682ef4ff61 Former-commit-id: 8a66b2f2092d4e9d2cbd07e7186f00374383b125 --- .../cfgbits/data/config/drop-ins/cronOTRs.xml | 4 +- .../rcm/server/RadarServerAvailable.java | 132 +- cave/build/p2-build.xml | 4 - .../aviation/config/gui/ClimateTimeouts.xml | 3 +- .../cave/etc/aviation/python/CigVisTrend.py | 6 +- .../etc/aviation/python/toolpy/AdjustTimes.py | 5 +- .../python/toolpy/UseMetarForPrevailing.py | 5 +- .../textProducts/MultipleElementTable.py | 2 - .../textUtilities/headline/FormatterRunner.py | 14 +- .../textUtilities/regular/FWS_Overrides.py | 3 - .../gfe/userPython/utilities/SmartScript.py | 2 +- .../.project | 17 - .../build.properties | 1 - ...n.uf.viz.alertviz.localization.feature.ecl | 0 .../feature.xml | 33 - .../.classpath | 7 - .../.project | 28 - .../.settings/org.eclipse.jdt.core.prefs | 7 - .../META-INF/MANIFEST.MF | 25 - .../build.properties | 5 - ....raytheon.uf.viz.alertviz.localization.ecl | 0 .../plugin.xml | 102 - .../AlertVizLocalizationAdapter.java | 78 - .../actions/AlertVizFileImportAction.java | 161 - .../alertviz/ui/dialogs/FileSelectDlg.java | 2 +- cave/com.raytheon.uf.viz.alertviz/plugin.xml | 76 +- .../uf/viz/core/catalog/ScriptCreator.java | 6 +- .../uf/viz/core/requests/ThriftClient.java | 16 +- .../styleRules/d2dArrowStyleRules.xml | 2 +- .../styleRules/d2dContourStyleRules.xml | 9 + .../styleRules/d2dGraphStyleRules.xml | 9 + cave/com.raytheon.uf.viz.d2d.ui/plugin.xml | 2 +- .../viz/d2d/ui/actions/AddAWIPSProcedure.java | 2 +- .../d2d/ui/actions/OpenAWIPSProcedure.java | 21 +- .../ui/dialogs/procedures/ProcedureDlg.java | 64 +- .../dialogs/procedures/ProcedureListDlg.java | 57 +- .../derivedParameters/definitions/CCP.xml | 6 +- .../derivedParameters/definitions/MnT12hr.xml | 7 +- .../derivedParameters/definitions/MxT12hr.xml | 7 +- .../derivedParameters/definitions/Wind.xml | 2 +- .../perspective/view/FileTreeView.java | 2 +- .../view/actions/ImportFileAction.java | 24 +- .../uf/viz/monitor/ffmp/FFMPMonitor.java | 23 +- .../viz/monitor/ffmp/ffti/FFTIControlDlg.java | 17 +- .../uf/viz/monitor/ffmp/ffti/SettingComp.java | 93 +- .../monitor/ffmp/ui/dialogs/FFMPConfig.java | 151 +- .../monitor/ffmp/ui/dialogs/FFMPTable.java | 161 +- .../ffmp/ui/dialogs/FfmpBasinTableDlg.java | 168 +- .../viz/monitor/ffmp/ui/rsc/FFMPResource.java | 17 +- .../ffmp/ui/rsc/FFMPTableDataLoader.java | 7 +- .../monitor/scan/resource/ScanResource.java | 4 +- .../uf/viz/monitor/data/TableUtil.java | 398 +- .../monitor/ui/dialogs/StationTableComp.java | 2 +- .../uf/viz/profiler/ProfilerResource.java | 20 +- .../uf/viz/radarapps/client/RcmClient.java | 26 +- .../rsc/AbstractCrossSectionResource.java | 4 +- .../rsc/CrossSectionImageResource.java | 10 +- .../rsc/AbstractTimeHeightResource.java | 1 + .../xy/timeseries/rsc/TimeSeriesResource.java | 31 +- .../viz/xy/varheight/util/ScaleHandler.java | 42 +- cave/com.raytheon.viz.aviation/plugin.xml | 7 + .../aviation/climatology/WindRosePlotDlg.java | 83 +- .../aviation/editor/TafViewerEditorDlg.java | 18 +- .../viz/aviation/guidance/MetarViewer.java | 10 +- .../viz/aviation/monitor/SiteMonitor.java | 5 +- .../viz/aviation/monitor/TafUtil.java | 11 +- .../viz/aviation/observer/SendDialog.java | 52 +- .../src/com/raytheon/viz/bcd/BCDResource.java | 10 + .../feature.xml | 4 - .../viz/gfe/PythonPreferenceStore.java | 20 +- .../viz/gfe/config/ConfigCatalog.java | 9 +- .../viz/gfe/core/ISelectTimeRangeManager.java | 5 +- .../gfe/core/griddata/AbstractGridData.java | 20 +- .../viz/gfe/core/griddata/IGridData.java | 2 +- .../core/internal/SelectTimeRangeManager.java | 5 +- .../raytheon/viz/gfe/core/parm/DbParm.java | 12 +- .../raytheon/viz/gfe/core/parm/VCParm.java | 5 +- .../dialogs/AbstractSaveParameterDialog.java | 133 +- .../viz/gfe/dialogs/DefineRefSetDialog.java | 121 +- .../gfe/dialogs/FormatterLauncherDialog.java | 3 + .../gfe/dialogs/SaveDeleteSelectTRDialog.java | 10 +- .../viz/gfe/edittool/contour/ContourTool.java | 15 +- .../gfe/edittool/sample/SamplePainter.java | 32 +- .../gfe/edittool/sample/SampleRenderable.java | 27 +- .../raytheon/viz/gfe/gridmanager/GridBar.java | 3 +- .../com/raytheon/viz/gfe/smarttool/Tool.java | 4 +- .../styleRules/gridImageryStyleRules.xml | 4 +- .../viz/grid/rsc/GridResourceData.java | 3 +- .../viz/grid/rsc/GridVectorResource.java | 5 +- .../grid/rsc/general/D2DGribGridResource.java | 4 +- .../FlashFloodGuidanceDlg.java | 4 +- .../hydro/resource/MultiPointResource.java | 32 +- .../timeseries/TimeSeriesDisplayDlg.java | 22 +- .../viz/hydro/timeseries/TimeSeriesDlg.java | 91 +- .../graph/TimeSeriesGraphCanvas.java | 9 +- .../cresthistory/CrestHistoryCanvas.java | 1408 +++---- .../datamanager/RiverDataManager.java | 1354 ++++--- .../ratingcurve/IRatingCurveSort.java | 45 - .../ratingcurve/RatingCurveData.java | 40 + .../ratingcurve/RatingCurveDlg.java | 532 ++- .../ratingcurve/RatingCurveShiftData.java | 30 +- .../hydrocommon/resource/FFGGridResource.java | 4 +- .../viz/hydrocommon/whfslib/GagePPWrite.java | 34 +- .../viz/mpe/ui/MPEDisplayManager.java | 3 +- .../ui/dialogs/gagetable/GageTableDlg.java | 7 +- .../viz/mpe/ui/rsc/MPEGageResource.java | 5 +- .../raytheon/viz/mpe/core/MpeFieldGenJob.java | 20 +- .../raytheon/viz/mpe/core/RegenHrFlds.java | 3 +- .../viz/pointdata/rsc/PlotResource.java | 13 +- .../menus/radar/baseTerminal4Panel.xml | 26 +- .../menus/radar/baseTerminalReflVel.xml | 28 +- .../radar/baseTerminalReflectivityMotion.xml | 34 +- .../menus/radar/baseTerminalSRMSpecWidth.xml | 18 +- .../localization/bundles/DefaultSatellite.xml | 1 - .../bundles/DerivedPOESSatellite.xml | 1 - .../localization/bundles/DerivedSatellite.xml | 1 - .../viz/texteditor/AfosBrowserModel.java | 99 +- .../alarmalert/dialogs/AlarmAlertBell.java | 54 +- .../dialogs/AlarmAlertSaveLoadDlg.java | 55 +- .../dialogs/AlarmDisplayWindow.java | 8 +- .../alarmalert/util/AlarmAlertFunctions.java | 92 +- .../alarmalert/util/AlarmBeepJob.java | 41 +- .../dialogs/AWIPSHeaderBlockDlg.java | 33 +- .../texteditor/dialogs/AfosBrowserDlg.java | 29 +- .../texteditor/dialogs/TextEditorDialog.java | 559 +-- .../viz/texteditor/print/PrintDisplay.java | 257 +- .../raytheon/viz/texteditor/qc/IQCCheck.java | 4 +- .../texteditor/util/SiteAbbreviationUtil.java | 17 + .../textworkstation/TextWorkstationDlg.java | 27 +- .../raytheon/viz/ui/VizWorkbenchManager.java | 3 + .../localization/menus/xml/fieldsMenus.xml | 4 +- .../viz/warngen/comm/WarningSender.java | 342 +- .../config/DbPointSourceDataAdaptor.java | 5 + .../com/raytheon/viz/warngen/gis/Area.java | 4 +- .../src/com/raytheon/viz/warngen/gis/Wx.java | 145 +- .../viz/warngen/gui/WarngenDialog.java | 12 +- .../viz/warngen/gui/WarngenLayer.java | 4 +- .../viz/warngen/gui/WarngenUIManager.java | 38 +- .../viz/warngen/template/TemplateRunner.java | 229 +- .../viz/warngen/util/WarnGenMathTool.java | 14 + .../viz/warngen/util/WarningTextHandler.java | 485 +-- .../warnings/rsc/AbstractWarningResource.java | 141 +- deltaScripts/future/relocateTextUtilities.py | 95 + .../db/hibernateConfig/maps/hibernate.cfg.xml | 4 +- edexOsgi/build.edex/esb/conf/log4j-ingest.xml | 8 +- edexOsgi/build.edex/esb/conf/log4j.xml | 34 +- .../esb/conf/res/base/attributeNames.xml | 2 - .../esb/conf/res/base/environment.xml | 2 - .../base/python/gfe/TimeRange.py | 15 + .../base/warngen/VM_global_library.vm | 10 +- .../base/warngen/arealFloodAdvisory.xml | 1 + .../warngen/arealFloodAdvisoryFollowup.xml | 1 + .../arealFloodAdvisoryFollowup_Zones.xml | 1 + .../base/warngen/arealFloodAdvisory_Zones.xml | 1 + .../base/warngen/arealFloodWarning.xml | 1 + .../warngen/arealFloodWarningFollowup.xml | 1 + .../arealFloodWarningFollowup_Zones.xml | 1 + .../base/warngen/arealFloodWarning_Zones.xml | 1 + .../base/warngen/customTemplate.vm | 12 +- .../base/warngen/extremeWindWarning.vm | 19 +- .../warngen/extremeWindWarningFollowup.vm | 5 +- .../common_static/base/warngen/ffwfaw.xml | 1 + .../base/warngen/flashFloodWarning.xml | 1 + .../warngen/flashFloodWarningFollowup.xml | 1 + .../flashFloodWarningFollowup_Zones.xml | 1 + .../base/warngen/flashFloodWarning_Zones.xml | 1 + .../impactSevereThunderstormWarning.vm | 6 +- .../warngen/impactSevereWeatherStatement.vm | 5 +- .../base/warngen/impactTornadoWarning.vm | 3 +- .../nonConvectiveFlashFloodWarning.xml | 1 + ...nonConvectiveFlashFloodWarningFollowup.xml | 1 + ...vectiveFlashFloodWarningFollowup_Zones.xml | 1 + .../nonConvectiveFlashFloodWarning_Zones.xml | 1 + .../base/warngen/severeThunderstormWarning.vm | 6 +- .../base/warngen/severeWeatherStatement.vm | 5 +- .../warngen/significantWeatherAdvisory.vm | 3 +- .../base/warngen/specialMarineWarning.vm | 8 +- .../warngen/specialMarineWarningFollowup.vm | 7 +- .../base/warngen/tornadoWarning.vm | 6 +- .../edex_static/base/protectedFiles.txt | 6 + .../edex_static/base/smartinit/Init.py | 13 +- .../base/textproducts/Generator.py | 220 +- .../textproducts/templates/product/AFD.py | 2 - .../templates/product/AreaFcst.py | 2 - .../textproducts/templates/product/CCF.py | 2 - .../textproducts/templates/product/CWF.py | 2 - .../templates/product/CWF_Pacific.py | 4 +- .../templates/product/CivilEmerg.py | 2 - .../product/CivilEmerg_EQR_MultiPil_Local.py | 2 - .../textproducts/templates/product/FWF.py | 4 +- .../templates/product/FWFTable.py | 2 - .../textproducts/templates/product/FWM.py | 4 +- .../textproducts/templates/product/GLF.py | 2 - .../templates/product/GenericHazards.py | 2 - .../templates/product/GenericReport.py | 2 - .../templates/product/Hazard_HLS.py | 16 +- .../textproducts/templates/product/MVF.py | 2 - .../textproducts/templates/product/NSH.py | 2 - .../textproducts/templates/product/OFF.py | 2 - .../textproducts/templates/product/PFM.py | 2 - .../textproducts/templates/product/SFT.py | 2 - .../textproducts/templates/product/SRF.py | 2 - .../res/spring/gfe-request.xml | 14 +- .../plugin/gfe/reference/ReferenceMgr.java | 162 + .../handler/GetActiveSitesRequestHandler.java | 64 - .../handler/GetSelectTimeRangeHandler.java | 192 + .../edex/plugin/gfe/smartinit/IFPWE.java | 43 +- .../edex/plugin/gfe/smartinit/InitClient.java | 47 +- .../plugin/gfe/textproducts/Configurator.java | 11 +- .../edex_static/base/gfe/isc/ifpnetCDF.py | 14 +- .../edex_static/base/gfe/isc/iscMosaic.py | 14 +- ...f.common.serialization.ISerializableObject | 2 + .../GribPostProcessor.java | 298 +- .../PostProcessedModel.java | 100 + .../PostProcessedModelSet.java | 70 + .../spatial/DefaultSubGridCenterPoint.java | 79 + .../plugin/grib/spatial/GribSpatialCache.java | 1391 +++---- .../base/grid/models/gribModels_NCEP-7.xml | 13 + .../base/grib/defaultSubGridCenterPoint.xml | 30 + .../postProcessModels/postProcessedModels.txt | 80 - .../postProcessModels/postProcessedModels.xml | 125 + .../base/grib/subgrids/HPCGuideClip.xml | 4 + .../base/grib/subgrids/HiresEastClip.xml | 4 + .../base/grib/subgrids/HiresWestClip.xml | 4 + .../base/grib/subgrids/NamDng5Clip.xml | 4 + .../base/grib/subgrids/RTMAClip.xml | 4 + .../base/grib/subgrids/TPCSurgeProbClip.xml | 4 + .../base/grib/subgrids/eta12Clip.xml | 4 + .../base/grib/subgrids/lampClip.xml | 4 + .../base/grib/subgrids/mEtaClip.xml | 4 + .../base/grib/subgrids/mosGuideClip.xml | 4 + .../base/grib/subgrids/mosGuideClip_AK.xml | 4 + .../base/grib/subgrids/qpf218Clip.xml | 4 + .../base/grib/subgrids/ruc13Clip.xml | 4 + .../com.raytheon.edex.plugin.pirep/.classpath | 1 + .../META-INF/MANIFEST.MF | 3 +- .../plugin/pirep/decoder/PirepParser.java | 299 +- .../edex/plugin/pirep/decoder/PirepTools.java | 73 +- .../edex/plugin/pirep/decoder/TEI.java | 124 + .../edex/plugin/pirep/decoder/TEIInfo.java | 210 ++ .../unit-test/test/pirep/TestPIREPParser.java | 167 + .../unit-test/test/pirep/TestPIREPRecord.java | 233 ++ .../unit-test/test/pirep/TestTEIInfo.java | 118 + .../text/impl/TextSeparatorFactory.java | 14 +- .../raytheon/uf/common/comm/HttpClient.java | 1307 +++---- .../dataplugin/ffmp/FFMPDataContainer.java | 287 +- .../META-INF/MANIFEST.MF | 1 + .../gfe/request/GetActiveSitesRequest.java | 44 - .../request/GetSelectTimeRangeRequest.java | 90 + .../dataplugin/gfe}/time/SelectTimeRange.java | 6 +- .../dataplugin/grib/subgrid/SubGridDef.java | 73 +- .../dataplugin/grib/util/GribModelLookup.java | 5 + .../common/dataplugin/pirep/PirepRecord.java | 194 +- .../warning/gis/GeospatialFactory.java | 29 +- .../DestinationGeodeticCalculator.java | 233 +- .../monitor/data/CommonTableConfig.java | 187 +- .../META-INF/MANIFEST.MF | 1 + .../serialization/comm/RequestWrapper.java | 101 + .../util/PythonFileGenerator.java | 4 +- .../site/requests/GetActiveSitesRequest.java | 26 +- .../com/raytheon/uf/common/util/SizeUtil.java | 69 + .../edex/auth/RemoteRequestRouteWrapper.java | 73 +- .../uf/edex/auth/RemoteRequestServer.java | 14 +- .../res/spring/ffmp-ingest.xml | 16 +- .../uf/edex/plugin/ffmp/FFMPGenerator.java | 3273 +++++++++-------- .../common/FFMPInterpolatedGuidanceDelay.java | 8 +- .../uf/edex/plugin/ffmp/common/FFTI.java | 559 +-- .../uf/edex/plugin/ffmp/common/FFTIAccum.java | 16 +- .../uf/edex/plugin/ffmp/common/FFTIData.java | 74 +- .../plugin/ffmp/common/FFTIProcessor.java | 460 +-- .../plugin/ffmp/common/FFTIRatioDiff.java | 24 +- .../edex_static/base/roles/userRoles.xml | 10 + .../uf/edex/site/SiteAwareRegistry.java | 12 +- .../configuration/svcbu.properties | 4 +- .../cli/publishGFE | 50 + .../cli/rsyncGridsToCWF.sh | 21 +- .../cli/rsync_parms.ccc | 8 + .../cli/src/ifpservertext/ifpServerText.py | 59 +- .../cli/src/publishgfe/publishGFE.py | 190 + .../com/raytheon/uf/common/__init__.py | 1 + .../dataplugin/gfe/db/objects/ParmID.py | 16 +- .../gfe/request/CommitGridsRequest.py | 47 + ...eSitesRequest.py => GetParmListRequest.py} | 9 +- .../gfe/request/GetSelectTimeRangeRequest.py | 47 + .../common/dataplugin/gfe/request/__init__.py | 16 +- .../gfe/server/request/CommitGridRequest.py | 54 + .../dataplugin/gfe/server/request/__init__.py | 2 + .../com/raytheon/uf/common/site/__init__.py | 27 + .../site/requests/GetActiveSitesRequest.py | 27 + .../uf/common/site/requests/__init__.py | 28 + .../com/raytheon/uf/common/time/TimeRange.py | 82 +- pythonPackages/ufpy/gfe/IFPClient.py | 173 + pythonPackages/ufpy/gfe/__init__.py | 37 + .../Installer.version/component.spec | 2 +- rpms/awips2.edex/deploy.builder/build.sh | 1 + .../Installer.qpid/component.spec | 2 +- 296 files changed, 12695 insertions(+), 9259 deletions(-) delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization.feature/.project delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization.feature/build.properties delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization.feature/com.raytheon.uf.viz.alertviz.localization.feature.ecl delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization.feature/feature.xml delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization/.classpath delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization/.project delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization/.settings/org.eclipse.jdt.core.prefs delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization/META-INF/MANIFEST.MF delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization/build.properties delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization/com.raytheon.uf.viz.alertviz.localization.ecl delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization/plugin.xml delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/AlertVizLocalizationAdapter.java delete mode 100644 cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/actions/AlertVizFileImportAction.java delete mode 100644 cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/IRatingCurveSort.java create mode 100644 deltaScripts/future/relocateTextUtilities.py create mode 100644 edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/reference/ReferenceMgr.java delete mode 100644 edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetActiveSitesRequestHandler.java create mode 100644 edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetSelectTimeRangeHandler.java create mode 100644 edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/PostProcessedModel.java create mode 100644 edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/PostProcessedModelSet.java create mode 100644 edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/DefaultSubGridCenterPoint.java create mode 100644 edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/defaultSubGridCenterPoint.xml delete mode 100644 edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.txt create mode 100644 edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.xml create mode 100644 edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEI.java create mode 100644 edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEIInfo.java create mode 100644 edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPParser.java create mode 100644 edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPRecord.java create mode 100644 edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestTEIInfo.java delete mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.java create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.java rename {cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core => edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe}/time/SelectTimeRange.java (95%) create mode 100644 edexOsgi/com.raytheon.uf.common.serialization.comm/src/com/raytheon/uf/common/serialization/comm/RequestWrapper.java create mode 100644 edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/SizeUtil.java create mode 100644 edexOsgi/com.raytheon.uf.tools.gfesuite/cli/publishGFE create mode 100644 edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsync_parms.ccc create mode 100644 edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/publishgfe/publishGFE.py create mode 100644 pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/CommitGridsRequest.py rename pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/{GetActiveSitesRequest.py => GetParmListRequest.py} (87%) create mode 100644 pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.py create mode 100644 pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/CommitGridRequest.py create mode 100644 pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/__init__.py create mode 100644 pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.py create mode 100644 pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/__init__.py create mode 100644 pythonPackages/ufpy/gfe/IFPClient.py create mode 100644 pythonPackages/ufpy/gfe/__init__.py diff --git a/RadarServer/build.rcm/cfgbits/data/config/drop-ins/cronOTRs.xml b/RadarServer/build.rcm/cfgbits/data/config/drop-ins/cronOTRs.xml index 0c532c4fb2..e3b1fec4cd 100644 --- a/RadarServer/build.rcm/cfgbits/data/config/drop-ins/cronOTRs.xml +++ b/RadarServer/build.rcm/cfgbits/data/config/drop-ins/cronOTRs.xml @@ -30,6 +30,6 @@ 34 16 34 32 - - + + \ No newline at end of file diff --git a/RadarServer/com.raytheon.rcm.server/src/com/raytheon/rcm/server/RadarServerAvailable.java b/RadarServer/com.raytheon.rcm.server/src/com/raytheon/rcm/server/RadarServerAvailable.java index 2d6f4c98c7..a917743d28 100644 --- a/RadarServer/com.raytheon.rcm.server/src/com/raytheon/rcm/server/RadarServerAvailable.java +++ b/RadarServer/com.raytheon.rcm.server/src/com/raytheon/rcm/server/RadarServerAvailable.java @@ -21,14 +21,18 @@ package com.raytheon.rcm.server; import java.io.File; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Scanner; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; import com.raytheon.rcm.event.RadarEvent; import com.raytheon.rcm.event.RadarEventAdapter; /** - * TODO Add Description + * Send AlertViz notifications * *
  * 
@@ -37,6 +41,7 @@ import com.raytheon.rcm.event.RadarEventAdapter;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Nov 9, 2011            mnash     Initial creation
+ * 2012-07-27   DR 14896   D. Friedman  Handle multiple RPGs.
  * 
  * 
* @@ -46,13 +51,15 @@ import com.raytheon.rcm.event.RadarEventAdapter; public class RadarServerAvailable extends RadarEventAdapter { - private static boolean attempted = false; + private static final String CONNECTION_DOWN_MESSAGE = "RPG connection is down."; + private static final String CONNECTION_UP_MESSAGE = "RPG connection is back up."; + + private static final String AWIPS2_FXA_PROPERTY = "awips2_fxa"; + private static final String DEFAULT_AWIPS2_FXA = "/awips2/fxa"; + private static final String ANNOUNCER_PATH = "bin" + File.separator + "fxaAnnounce"; - private ProcessBuilder builder; + private HashSet knownFailures = new HashSet(); - /** - * - */ public RadarServerAvailable(RadarServer server) { } @@ -65,64 +72,73 @@ public class RadarServerAvailable extends RadarEventAdapter { */ @Override public void handleRadarEvent(RadarEvent event) { - Process proc = null; - String home = System.getProperty("awips2_fxa"); - if (home != null && !home.endsWith(File.separator)) { - home += File.separator; - } else if (home == null) { - Log.event("Cannot find awips2_fxa system variable"); - return; - } - List values = new ArrayList(); - values.add(home + "bin" + File.separator + "fxaAnnounce"); - try { - if (event.getType() == RadarEvent.CONNECTION_ATTEMPT_FAILED) { - if (!attempted) { - Log.event("Executing " + values.get(0)); - values.add(event.getRadarID() + " rpg connection is down."); - values.add("RADAR"); - values.add("URGENT"); - builder = new ProcessBuilder(values); - builder.redirectErrorStream(true); - - proc = builder.start(); - StringBuilder output = new StringBuilder(); - Scanner s = new Scanner(proc.getInputStream()); - while (s.hasNextLine()) { - if (output.length() > 0) - output.append('\n'); - output.append(s.nextLine()); - } - proc.waitFor(); - attempted = true; - } - } else if (event.getType() == RadarEvent.CONNECTION_UP) { - if (attempted) { - Log.event("Executing " + values.get(0)); - values.add(event.getRadarID() - + " rpg connection is back up."); - values.add("RADAR"); - values.add("URGENT"); - builder = new ProcessBuilder(values); - builder.redirectErrorStream(true); - proc = builder.start(); - StringBuilder output = new StringBuilder(); - Scanner s = new Scanner(proc.getInputStream()); - while (s.hasNextLine()) { - if (output.length() > 0) - output.append('\n'); - output.append(s.nextLine()); - } - proc.waitFor(); - attempted = false; - } + final String radarId = event.getRadarID(); + if (event.getType() == RadarEvent.CONNECTION_ATTEMPT_FAILED) { + if (! knownFailures.contains(radarId)) { + knownFailures.add(radarId); + sendNotification(radarId, CONNECTION_DOWN_MESSAGE); } + } else if (event.getType() == RadarEvent.CONNECTION_UP) { + if (knownFailures.contains(radarId)) { + knownFailures.remove(radarId); + sendNotification(radarId, CONNECTION_UP_MESSAGE); + } + } + } + + private void sendNotification(final String radarId, final String message) { + getExecutorService().submit(new Runnable() { + @Override + public void run() { + sendNotification2(radarId, message); + } + }); + } + + private void sendNotification2(String radarId, String message) { + ProcessBuilder builder; + Process proc = null; + + String fxaDir = System.getProperty(AWIPS2_FXA_PROPERTY); + if (fxaDir == null) + fxaDir = DEFAULT_AWIPS2_FXA; + + List values = new ArrayList(); + values.add(fxaDir + File.separator + ANNOUNCER_PATH); + Log.event("Executing " + values.get(0)); + values.add(radarId + ' ' + message); + values.add("RADAR"); + values.add("URGENT"); + builder = new ProcessBuilder(values); + builder.redirectErrorStream(true); + + try { + proc = builder.start(); + Scanner s = new Scanner(proc.getInputStream()); + while (s.hasNextLine()) + s.nextLine(); + proc.waitFor(); } catch (Exception e) { - e.printStackTrace(); + Log.errorf("Error running fxaAnnounce: %s", e); } finally { if (proc != null) { proc.destroy(); } } } + + // TODO: has to be daemon until there is a shutdown notification + private static ExecutorService executorService = Executors + .newSingleThreadExecutor(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setDaemon(true); + return t; + } + }); + + private static ExecutorService getExecutorService() { + return executorService; + } } diff --git a/cave/build/p2-build.xml b/cave/build/p2-build.xml index dd00a25f0e..7acd223efc 100644 --- a/cave/build/p2-build.xml +++ b/cave/build/p2-build.xml @@ -178,10 +178,6 @@ - - - diff --git a/cave/build/static/common/cave/etc/aviation/config/gui/ClimateTimeouts.xml b/cave/build/static/common/cave/etc/aviation/config/gui/ClimateTimeouts.xml index 0796d4eaa0..27f8fd2b59 100644 --- a/cave/build/static/common/cave/etc/aviation/config/gui/ClimateTimeouts.xml +++ b/cave/build/static/common/cave/etc/aviation/config/gui/ClimateTimeouts.xml @@ -21,10 +21,11 @@ 20 - 20 + 120 90 1800 diff --git a/cave/build/static/common/cave/etc/aviation/python/CigVisTrend.py b/cave/build/static/common/cave/etc/aviation/python/CigVisTrend.py index d075571611..6ed8e9d677 100644 --- a/cave/build/static/common/cave/etc/aviation/python/CigVisTrend.py +++ b/cave/build/static/common/cave/etc/aviation/python/CigVisTrend.py @@ -26,6 +26,10 @@ # DELIVERED # # History: +# Revision 17 +# Created: 10-AUG-2012 15:00:00 GZHANG +# DR 14702: Added fix for PyTables in Gui().trend() +# # Revision 16 (DELIVERED) # Created: 06-MAR-2008 17:01:20 OBERFIEL # Added fix for leap-years. @@ -661,7 +665,7 @@ class Gui(): n1 = max(0, n-2*int((t-t1)//3600.0)-1) # small enough n2 = n1 + 5*self.MaxHours # big enough data = [(row['date_time'], row['cig'], row['vis']) for row in \ - table.where('(t1<=date_time) & (date_time - - com.raytheon.uf.viz.alertviz.localization.feature - - - - - - org.eclipse.pde.FeatureBuilder - - - - - - org.eclipse.pde.FeatureNature - - diff --git a/cave/com.raytheon.uf.viz.alertviz.localization.feature/build.properties b/cave/com.raytheon.uf.viz.alertviz.localization.feature/build.properties deleted file mode 100644 index 64f93a9f0b..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization.feature/build.properties +++ /dev/null @@ -1 +0,0 @@ -bin.includes = feature.xml diff --git a/cave/com.raytheon.uf.viz.alertviz.localization.feature/com.raytheon.uf.viz.alertviz.localization.feature.ecl b/cave/com.raytheon.uf.viz.alertviz.localization.feature/com.raytheon.uf.viz.alertviz.localization.feature.ecl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cave/com.raytheon.uf.viz.alertviz.localization.feature/feature.xml b/cave/com.raytheon.uf.viz.alertviz.localization.feature/feature.xml deleted file mode 100644 index af5b04e473..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization.feature/feature.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - [Enter Feature Description here.] - - - - [Enter Copyright Description here.] - - - - [Enter License Description here.] - - - - - - - - - - - diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/.classpath b/cave/com.raytheon.uf.viz.alertviz.localization/.classpath deleted file mode 100644 index 751c8f2e50..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/.project b/cave/com.raytheon.uf.viz.alertviz.localization/.project deleted file mode 100644 index 1fcbe82ecd..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - com.raytheon.uf.viz.alertviz.localization - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/.settings/org.eclipse.jdt.core.prefs b/cave/com.raytheon.uf.viz.alertviz.localization/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index c56eb27ffa..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,7 +0,0 @@ -#Mon Apr 04 17:11:52 CDT 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/META-INF/MANIFEST.MF b/cave/com.raytheon.uf.viz.alertviz.localization/META-INF/MANIFEST.MF deleted file mode 100644 index 8aaa5e3ec4..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/META-INF/MANIFEST.MF +++ /dev/null @@ -1,25 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Ui Plug-in -Bundle-SymbolicName: com.raytheon.uf.viz.alertviz.localization;singleton:=true -Bundle-Version: 1.12.1174.qualifier -Bundle-Activator: com.raytheon.uf.viz.alertviz.Activator -Bundle-Vendor: Raytheon -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - com.raytheon.uf.common.localization, - com.raytheon.uf.common.message;bundle-version="1.11.11", - com.raytheon.uf.viz.alertviz;bundle-version="1.11.11" -Bundle-ActivationPolicy: lazy -Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization -Export-Package: com.raytheon.uf.viz.alertviz.localization, - com.raytheon.uf.viz.alertviz.localization.actions -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Import-Package: com.raytheon.uf.common.alertmonitor, - com.raytheon.uf.common.util, - com.raytheon.uf.viz.localization, - com.raytheon.uf.viz.localization.adapter, - com.raytheon.uf.viz.localization.filetreeview, - com.raytheon.uf.viz.localization.service, - com.raytheon.viz.ui, - com.raytheon.viz.ui.dialogs diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/build.properties b/cave/com.raytheon.uf.viz.alertviz.localization/build.properties deleted file mode 100644 index e9863e281e..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/build.properties +++ /dev/null @@ -1,5 +0,0 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - plugin.xml diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/com.raytheon.uf.viz.alertviz.localization.ecl b/cave/com.raytheon.uf.viz.alertviz.localization/com.raytheon.uf.viz.alertviz.localization.ecl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/plugin.xml b/cave/com.raytheon.uf.viz.alertviz.localization/plugin.xml deleted file mode 100644 index d9f64b49b6..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/plugin.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/AlertVizLocalizationAdapter.java b/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/AlertVizLocalizationAdapter.java deleted file mode 100644 index 2a019cab00..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/AlertVizLocalizationAdapter.java +++ /dev/null @@ -1,78 +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.viz.alertviz.localization; - -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.jface.action.IMenuManager; - -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; -import com.raytheon.uf.viz.alertviz.localization.actions.AlertVizFileImportAction; -import com.raytheon.uf.viz.localization.adapter.LocalizationPerspectiveAdapter; -import com.raytheon.uf.viz.localization.filetreeview.FileTreeEntryData; - -/** - * Localization perspective adapter for AlertViz. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Apr 04, 2011  5853       bgonzale    Initial creation
- * 
- * 
- * - * @author bgonzale - * @version 1.0 - */ - -public class AlertVizLocalizationAdapter extends LocalizationPerspectiveAdapter { - - private static final Map localizationMap = getLocalizationMap(); - - @Override - public boolean addContextMenuItems(IMenuManager menuMgr, - FileTreeEntryData[] selectedData) { - if (selectedData.length == 1) { - FileTreeEntryData selected = selectedData[0]; - - if (selected.getClass() == FileTreeEntryData.class) { - LocalizationLevel level = localizationMap.get(selected - .getName()); - menuMgr.add(new AlertVizFileImportAction( - (FileTreeEntryData) selected, level)); - return true; - } - } - return false; - } - - private static Map getLocalizationMap() { - Map map = new HashMap(); - map.put("Audio", LocalizationLevel.SITE); - map.put("Configurations", LocalizationLevel.USER); - map.put("Scripts", LocalizationLevel.SITE); - map.put("Python", LocalizationLevel.SITE); - return map; - } -} diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/actions/AlertVizFileImportAction.java b/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/actions/AlertVizFileImportAction.java deleted file mode 100644 index 103ab383f1..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/actions/AlertVizFileImportAction.java +++ /dev/null @@ -1,161 +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.viz.alertviz.localization.actions; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import org.eclipse.jface.action.Action; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.FileDialog; -import org.eclipse.swt.widgets.Shell; - -import com.raytheon.uf.common.localization.IPathManager; -import com.raytheon.uf.common.localization.LocalizationContext; -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; -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.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; -import com.raytheon.uf.viz.localization.filetreeview.FileTreeEntryData; -import com.raytheon.viz.ui.VizWorkbenchManager; - -/** - * Opens a file dialog for importing files. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Apr 04, 2011  5853       bgonzale    Initial creation
- * 
- * 
- * - * @author bgonzale - * @version 1.0 - */ - -public class AlertVizFileImportAction extends Action { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(AlertVizFileImportAction.class, "GDN_ADMIN", - "GDN_ADMIN"); - - private static final String PLUGIN_ID = "com.raytheon.uf.viz.alertviz.ui"; - - private static final String ASTERISK = "*"; - - private static final String ALL_FILES = "*.*"; - - private LocalizationLevel level; - - private String[] extensions; - - private String path; - - /** - * @param fileEntry - * - */ - public AlertVizFileImportAction(FileTreeEntryData fileEntry) { - this(fileEntry, LocalizationLevel.USER); - } - - /** - * @param fileEntry - * @param level - * - */ - public AlertVizFileImportAction(FileTreeEntryData fileEntry, - LocalizationLevel level) { - super("Import"); - this.level = level == null ? LocalizationLevel.USER : level; - this.path = fileEntry.getPath(); - String[] fileEntryExtensions = fileEntry.getPathData().getFilter(); - this.extensions = new String[fileEntryExtensions.length + 1]; - for (int i = 0; i < fileEntryExtensions.length; ++i) { - this.extensions[i] = ASTERISK + fileEntryExtensions[i]; - } - this.extensions[this.extensions.length - 1] = ALL_FILES; - } - - @Override - public void run() { - Shell shell = VizWorkbenchManager.getInstance().getCurrentWindow() - .getShell(); - FileDialog fd = new FileDialog(shell, SWT.OPEN | SWT.MULTI); - - fd.setText("Import " + level + " File"); - fd.setFilterExtensions(extensions); - fd.setFilterPath(System.getProperty("user.home")); - - String fileName = fd.open(); - - if (fileName != null) { - File file = new File(fileName); - - if (file.exists() && file.isFile()) { - IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationContext ctx = pm.getContext( - LocalizationType.CAVE_STATIC, level); - LocalizationFile locFile = pm.getLocalizationFile(ctx, path - + File.separator + file.getName()); - - try { - saveToLocalizationFile(file, locFile); - } catch (FileNotFoundException e) { - statusHandler.handle(Priority.PROBLEM, - e.getLocalizedMessage(), e); - } catch (IOException e) { - statusHandler.handle(Priority.PROBLEM, - e.getLocalizedMessage(), e); - } catch (LocalizationOpFailedException e) { - statusHandler.handle(Priority.CRITICAL, - "Error Importing file " + fileName, e); - } - } - } - } - - private void saveToLocalizationFile(File file, LocalizationFile locFile) - throws IOException, LocalizationOpFailedException { - File newFile = locFile.getFile(); - InputStream in = new FileInputStream(file); - OutputStream out = new FileOutputStream(newFile); - byte[] buff = new byte[1024]; - int len; - - while ((len = in.read(buff)) > 0) { - out.write(buff, 0, len); - } - in.close(); - out.close(); - locFile.save(); - } -} diff --git a/cave/com.raytheon.uf.viz.alertviz.ui/src/com/raytheon/uf/viz/alertviz/ui/dialogs/FileSelectDlg.java b/cave/com.raytheon.uf.viz.alertviz.ui/src/com/raytheon/uf/viz/alertviz/ui/dialogs/FileSelectDlg.java index 1583162020..d6ca0ce033 100644 --- a/cave/com.raytheon.uf.viz.alertviz.ui/src/com/raytheon/uf/viz/alertviz/ui/dialogs/FileSelectDlg.java +++ b/cave/com.raytheon.uf.viz.alertviz.ui/src/com/raytheon/uf/viz/alertviz/ui/dialogs/FileSelectDlg.java @@ -341,7 +341,7 @@ public class FileSelectDlg extends Dialog { importNewBtn1.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { FileDialog newFileDlg = new FileDialog(shell, SWT.OPEN - | SWT.MULTI); + | SWT.SINGLE); newFileDlg.setFilterExtensions(fileExtensions); String newFileName = newFileDlg.open(); if (newFileName != null) { diff --git a/cave/com.raytheon.uf.viz.alertviz/plugin.xml b/cave/com.raytheon.uf.viz.alertviz/plugin.xml index 4e5ec8901c..2cac8a257e 100644 --- a/cave/com.raytheon.uf.viz.alertviz/plugin.xml +++ b/cave/com.raytheon.uf.viz.alertviz/plugin.xml @@ -27,5 +27,79 @@ id="com.raytheon.viz.notification.statusHandler"> - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/catalog/ScriptCreator.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/catalog/ScriptCreator.java index 94052790a2..6fb89eeb6c 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/catalog/ScriptCreator.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/catalog/ScriptCreator.java @@ -50,7 +50,10 @@ import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.localization.LocalizationManager; /** - * Creates uEngine scripts on the fly. + * Creates uEngine scripts on the fly. DEPRECATED: Requests from viz should go + * through ThriftClient to the thrift service instead of using ScriptCreator and + * then going to the uengine service. The thrift service performs faster and is + * more maintainable. Use ThriftClient. * *
  * 
@@ -73,6 +76,7 @@ import com.raytheon.uf.viz.core.localization.LocalizationManager;
  * @author brockwoo
  * @version 1
  */
+@Deprecated
 public class ScriptCreator {
     private static final transient IUFStatusHandler statusHandler = UFStatus
             .getHandler(ScriptCreator.class);
diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/requests/ThriftClient.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/requests/ThriftClient.java
index 4399790fbb..22bcb88135 100644
--- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/requests/ThriftClient.java
+++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/requests/ThriftClient.java
@@ -4,6 +4,7 @@ import java.io.IOException;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.util.UUID;
 
 import javax.jws.WebService;
 
@@ -20,6 +21,7 @@ import com.raytheon.uf.common.serialization.SerializationException;
 import com.raytheon.uf.common.serialization.SerializationUtil;
 import com.raytheon.uf.common.serialization.comm.IServerRequest;
 import com.raytheon.uf.common.serialization.comm.RemoteServiceRequest;
+import com.raytheon.uf.common.serialization.comm.RequestWrapper;
 import com.raytheon.uf.common.serialization.comm.ServiceException;
 import com.raytheon.uf.common.serialization.comm.response.ServerErrorResponse;
 import com.raytheon.uf.common.serialization.comm.util.ExceptionWrapper;
@@ -50,9 +52,9 @@ import com.raytheon.uf.viz.core.localization.LocalizationManager;
  **/
 
 /**
- * The thrift client. used to send requests to the RemoteReqeustServer. Make
+ * The thrift client. used to send requests to the RemoteRequestServer. Make
  * sure request type has registered a handler to handle the request on the
- * server
+ * server.
  * 
  * 
  * 
@@ -60,6 +62,7 @@ import com.raytheon.uf.viz.core.localization.LocalizationManager;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Aug 3, 2009            mschenke     Initial creation
+ * Jul 24, 2012             njensen         Enhanced logging
  * 
  * 
* @@ -273,9 +276,12 @@ public class ThriftClient { private static Object sendRequest(IServerRequest request, String httpAddress, String uri) throws VizException { httpAddress += uri; + String uniqueId = UUID.randomUUID().toString(); + RequestWrapper wrapper = new RequestWrapper(request, VizApp.getWsId(), + uniqueId); byte[] message; try { - message = SerializationUtil.transformToThrift(request); + message = SerializationUtil.transformToThrift(wrapper); } catch (SerializationException e) { throw new VizException("unable to serialize request object", e); } @@ -287,8 +293,8 @@ public class ThriftClient { .postBinary(httpAddress, message); long time = System.currentTimeMillis() - t0; if (time >= SIMPLE_LOG_TIME) { - System.out.println("Took " + time + "ms to run request " - + request); + System.out.println("Took " + time + "ms to run request id[" + + uniqueId + "] " + request.toString()); } if (time >= BAD_LOG_TIME) { new Exception() { diff --git a/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dArrowStyleRules.xml b/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dArrowStyleRules.xml index 1daeeb5004..3879db62cb 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dArrowStyleRules.xml +++ b/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dArrowStyleRules.xml @@ -80,9 +80,9 @@ K/m*1.0E6 --> + K/m*1.0E6 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 66a272a6c3..bab5801554 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 @@ -4084,4 +4084,13 @@ in | .03937 | 0 | 4 | | |..|8000F0FF| | 16 | \ + + + Wind + Gust + + + kts + + diff --git a/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dGraphStyleRules.xml b/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dGraphStyleRules.xml index 1f2f625258..55d705073b 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dGraphStyleRules.xml +++ b/cave/com.raytheon.uf.viz.d2d.ui/localization/styleRules/d2dGraphStyleRules.xml @@ -498,4 +498,13 @@ + + + MTV + + + g*m/(kg*s) + + + \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.d2d.ui/plugin.xml b/cave/com.raytheon.uf.viz.d2d.ui/plugin.xml index cbeadc3c23..0f116eb2dd 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui/plugin.xml +++ b/cave/com.raytheon.uf.viz.d2d.ui/plugin.xml @@ -1548,7 +1548,7 @@ diff --git a/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/actions/AddAWIPSProcedure.java b/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/actions/AddAWIPSProcedure.java index 15e570416e..056292b90f 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/actions/AddAWIPSProcedure.java +++ b/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/actions/AddAWIPSProcedure.java @@ -57,7 +57,7 @@ public class AddAWIPSProcedure extends AbstractHandler { @Override public Object execute(ExecutionEvent event) throws ExecutionException { Procedure procedure = new Procedure(); - ProcedureDlg dlg = new ProcedureDlg(null, procedure, + ProcedureDlg dlg = ProcedureDlg.getOrCreateDialog(null, procedure, HandlerUtil.getActiveShell(event)); dlg.open(); diff --git a/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/actions/OpenAWIPSProcedure.java b/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/actions/OpenAWIPSProcedure.java index 7e8183533b..7e9d075b4b 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/actions/OpenAWIPSProcedure.java +++ b/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/actions/OpenAWIPSProcedure.java @@ -24,6 +24,8 @@ import java.io.File; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.handlers.HandlerUtil; import com.raytheon.uf.common.localization.LocalizationFile; @@ -53,6 +55,8 @@ import com.raytheon.viz.ui.actions.LoadSerializedXml; */ public class OpenAWIPSProcedure extends AbstractHandler { + private OpenProcedureListDlg dialog; + /* * (non-Javadoc) * @@ -62,16 +66,21 @@ public class OpenAWIPSProcedure extends AbstractHandler { */ @Override public Object execute(ExecutionEvent event) throws ExecutionException { - ProcedureListDlg listDlg = new OpenProcedureListDlg( + if(dialog != null){ + dialog.open(); + return null; + } + + dialog = new OpenProcedureListDlg( HandlerUtil.getActiveShell(event)); - listDlg.open(); - - LocalizationFile selectedFile = listDlg.getSelectedFile(); - + dialog.open(); + + LocalizationFile selectedFile = dialog.getSelectedFile(); + dialog = null; if (selectedFile != null) { File f = selectedFile.getFile(); Procedure p = (Procedure) LoadSerializedXml.deserialize(f); - ProcedureDlg dlg = new ProcedureDlg( + ProcedureDlg dlg = ProcedureDlg.getOrCreateDialog( LocalizationUtil.extractName(selectedFile.getName()), p, VizWorkbenchManager.getInstance().getCurrentWindow() .getShell()); diff --git a/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/dialogs/procedures/ProcedureDlg.java b/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/dialogs/procedures/ProcedureDlg.java index 3af3ceef9c..cd0eae8c30 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/dialogs/procedures/ProcedureDlg.java +++ b/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/dialogs/procedures/ProcedureDlg.java @@ -23,6 +23,7 @@ package com.raytheon.uf.viz.d2d.ui.dialogs.procedures; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; @@ -83,6 +84,22 @@ import com.raytheon.viz.ui.actions.SaveBundle; import com.raytheon.viz.ui.dialogs.CaveSWTDialog; import com.raytheon.viz.ui.editor.AbstractEditor; +/** + * + * Dialog for loading or modifying procedures. + * + *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ *
+ * 
+ * + * @author unknown + * @version 1.0 + */ public class ProcedureDlg extends CaveSWTDialog { private static final transient IUFStatusHandler statusHandler = UFStatus @@ -94,6 +111,8 @@ public class ProcedureDlg extends CaveSWTDialog { public static final String PROCEDURES_DIR = "/procedures"; + private static Collection openDialogs = new ArrayList(); + private Font font; private List dataList; @@ -148,7 +167,7 @@ public class ProcedureDlg extends CaveSWTDialog { private final java.util.List bundles; - public ProcedureDlg(String fileName, Procedure p, Shell parent) { + private ProcedureDlg(String fileName, Procedure p, Shell parent) { // Win32 super(parent, SWT.DIALOG_TRIM | SWT.RESIZE, CAVE.INDEPENDENT_SHELL | CAVE.DO_NOT_BLOCK); @@ -203,6 +222,9 @@ public class ProcedureDlg extends CaveSWTDialog { @Override protected void disposed() { font.dispose(); + synchronized (openDialogs) { + openDialogs.remove(this); + } } @Override @@ -989,4 +1011,44 @@ public class ProcedureDlg extends CaveSWTDialog { }; dlg.open(); } + + /** + * If there is a procedure dialog open for the given filename, return it, + * otherwise null. + * + * @param fileName + * @return + */ + public static ProcedureDlg getDialog(String fileName) { + synchronized (openDialogs) { + if (fileName != null) { + for (ProcedureDlg dialog : openDialogs) { + if (fileName.equals(dialog.fileName)) { + return dialog; + } + } + } + return null; + } + } + + /** + * Get the ProcedureDlg for the given fileName. If the fileName is null or if there is no open dialog, create a new ProcedureDlg. + * + * @param fileName + * @param p + * @param parent + * @return + */ + public static ProcedureDlg getOrCreateDialog(String fileName, Procedure p, + Shell parent) { + synchronized (openDialogs) { + ProcedureDlg dialog = getDialog(fileName); + if (dialog == null) { + dialog = new ProcedureDlg(fileName, p, parent); + openDialogs.add(dialog); + } + return dialog; + } + } } diff --git a/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/dialogs/procedures/ProcedureListDlg.java b/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/dialogs/procedures/ProcedureListDlg.java index 657be9c429..baea4279c1 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/dialogs/procedures/ProcedureListDlg.java +++ b/cave/com.raytheon.uf.viz.d2d.ui/src/com/raytheon/uf/viz/d2d/ui/dialogs/procedures/ProcedureListDlg.java @@ -54,6 +54,24 @@ import com.raytheon.uf.common.localization.LocalizationUtil; import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.viz.ui.dialogs.CaveSWTDialog; +/** + * + * A dialog which displays a list of procedures for opening, saving, or deleting. + * + *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * ???                                 Initial creation
+ * 07/31/2012   DR 15036   D. Friedman Ensure current user's procedures
+ *                                     are visible.
+ * 
+ * + * @author unknown + * @version 1.0 + */ public class ProcedureListDlg extends CaveSWTDialog { protected boolean oneLevel = true; @@ -317,10 +335,18 @@ public class ProcedureListDlg extends CaveSWTDialog { if (treeViewer.getContentProvider() instanceof ProcedureTreeContentProvider) { ProcedureTreeContentProvider content = (ProcedureTreeContentProvider) treeViewer .getContentProvider(); - Object find = content.findItem(user); + final Object find = content.findItem(user); if (find != null) { treeViewer.setExpandedElements(new Object[] { find }); - treeViewer.reveal(find); + treeViewer.getTree().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + TreeItem[] items = treeViewer.getTree().getItems(); + if (items != null && items.length > 0) + treeViewer.getTree().showItem(items[items.length - 1]); + treeViewer.reveal(find); + } + }); } } } @@ -449,14 +475,25 @@ public class ProcedureListDlg extends CaveSWTDialog { procedureTF.setText(procedureTF.getText().concat(".xml")); } if (dataListContains(procedureTF.getText())) { - // Pop up a warning - boolean result = MessageDialog.openQuestion(shell, - "Confirm Overwrite", - "The procedure " + procedureTF.getText() - + " already exists. Overwrite anyways?"); - if (result == true) { - fileName = procedureTF.getText(); - shell.dispose(); + if (ProcedureDlg.getDialog(procedureTF.getText()) != null) { + // User cannot save if dialog is open. + MessageDialog + .openError( + shell, + "Cannot Save Procedure", + "The procedure " + + procedureTF.getText() + + " is currently open. It cannot be overwritten until it is closed or saved under another name."); + } else { + // Pop up a warning + boolean result = MessageDialog.openQuestion(shell, + "Confirm Overwrite", + "The procedure " + procedureTF.getText() + + " already exists. Overwrite anyways?"); + if (result == true) { + fileName = procedureTF.getText(); + shell.dispose(); + } } } else { fileName = procedureTF.getText(); diff --git a/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/CCP.xml b/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/CCP.xml index 427b0b177f..0286ffc47a 100644 --- a/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/CCP.xml +++ b/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/CCP.xml @@ -24,15 +24,15 @@ - + - + - + diff --git a/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/MnT12hr.xml b/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/MnT12hr.xml index c841e9824a..f7ed0115c1 100644 --- a/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/MnT12hr.xml +++ b/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/MnT12hr.xml @@ -18,4 +18,9 @@ See_the_AWIPS_II_Master_Rights_File_("Master_Rights_File.pdf")_for further_licensing_information. --> - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/MxT12hr.xml b/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/MxT12hr.xml index f019fcc212..8db5cc4b07 100644 --- a/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/MxT12hr.xml +++ b/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/MxT12hr.xml @@ -18,4 +18,9 @@ See_the_AWIPS_II_Master_Rights_File_("Master_Rights_File.pdf")_for further_licensing_information. --> - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/Wind.xml b/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/Wind.xml index 12c62202c1..550260cb4d 100644 --- a/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/Wind.xml +++ b/cave/com.raytheon.uf.viz.derivparam/localization/derivedParameters/definitions/Wind.xml @@ -18,7 +18,7 @@ See_the_AWIPS_II_Master_Rights_File_("Master_Rights_File.pdf")_for further_licensing_information. --> - + diff --git a/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/FileTreeView.java b/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/FileTreeView.java index 6d66dbc462..d9b598edac 100644 --- a/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/FileTreeView.java +++ b/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/FileTreeView.java @@ -819,7 +819,7 @@ public class FileTreeView extends ViewPart implements IPartListener2, // We can import into true directories, not group datas mgr.add(new Separator()); mgr.add(new ImportFileAction(fdata.getPathData().getType(), - fdata.getPath())); + fdata.getPath(), fdata.getPathData().getFilter())); } } } diff --git a/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/actions/ImportFileAction.java b/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/actions/ImportFileAction.java index c597c8fdf4..f3d9d62c50 100644 --- a/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/actions/ImportFileAction.java +++ b/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/actions/ImportFileAction.java @@ -67,17 +67,36 @@ public class ImportFileAction extends Action { private static final String FORMAT_STRING = "The file '%s' already exists at the %s level and " + "will be deleted. Proceed?"; + private static final String ASTERISK = "*"; + private String directoryPath; private LocalizationType contextType; + private String[] fileExtensionFilterArr; + public ImportFileAction(LocalizationType contextType, String directoryPath) { super("Import File..."); this.contextType = contextType; this.directoryPath = directoryPath; } - /* + public ImportFileAction(LocalizationType contextType, String directoryPath, String[] filter) { + this(contextType, directoryPath); + if (filter != null) { + this.fileExtensionFilterArr = new String[filter.length]; + for (int i = 0; i < filter.length; ++i) { + if (filter[i] != null && filter[i].startsWith(".")) { + // prepend an asterisk as required by FileDialog. + this.fileExtensionFilterArr[i] = ASTERISK + filter[i]; + } else { + this.fileExtensionFilterArr[i] = filter[i]; + } + } + } + } + + /* * (non-Javadoc) * * @see org.eclipse.jface.action.Action#run() @@ -87,6 +106,9 @@ public class ImportFileAction extends Action { Shell parent = VizWorkbenchManager.getInstance().getCurrentWindow() .getShell(); FileDialog dialog = new FileDialog(parent); + if (fileExtensionFilterArr != null) { + dialog.setFilterExtensions(fileExtensionFilterArr); + } String fileToImport = dialog.open(); if (fileToImport != null) { File importFile = new File(fileToImport); diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java index b4acf0afe6..6e967c627b 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java @@ -820,20 +820,15 @@ public class FFMPMonitor extends ResourceMonitor { populateFFMPRecord(product, siteKey, dataKey, sourceName, ptime, phuc, retrieveNew); } - } else { - // special case where FFG is the primary source - // check for special case with dual stand alone and table - // display loaded - SourceXML sourcexml = getSourceConfig().getSource(sourceName); + } else { + // special case where FFG is the primary source + // check for special case with dual stand alone and table + // display loaded - if (sourcexml.getSourceType().equals( - SOURCE_TYPE.GUIDANCE.getSourceType())) { - sourceName = sourcexml.getDisplayName(); - } else { - populateFFMPRecord(product, siteKey, dataKey, sourceName, - ptime, phuc, retrieveNew); - } - } + populateFFMPRecord(product, siteKey, dataKey, sourceName, + ptime, phuc, retrieveNew); + + } record = ffmpData.get(siteKey).get(sourceName); } @@ -1109,6 +1104,8 @@ public class FFMPMonitor extends ResourceMonitor { } resourceListeners.remove(listener); + // clean up if we can + System.gc(); } public ArrayList getResourceListenerList() { diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/FFTIControlDlg.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/FFTIControlDlg.java index c6833d5cfb..9ee15a3950 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/FFTIControlDlg.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/FFTIControlDlg.java @@ -279,8 +279,11 @@ public class FFTIControlDlg extends Dialog { && (thisItem.getQpeDurHr() == nextItem.getQpeDurHr()) && (thisItem.getGuidDurHr() == nextItem.getGuidDurHr()) && (thisItem.getQpfDurHr() == nextItem.getQpfDurHr()) - && (thisItem.getTotalDurHr() == nextItem.getTotalDurHr())) { - + && (thisItem.getTotalDurHr() == nextItem.getTotalDurHr()) + && (thisItem.getQpeSrc().length > 0 && nextItem.getQpeSrc().length > 0 && thisItem.getQpeSrc()[0].equals(nextItem.getQpeSrc()[0])) + && (thisItem.getQpfSrc().length > 0 && nextItem.getQpfSrc().length > 0 && thisItem.getQpfSrc()[0].equals(nextItem.getQpfSrc()[0])) + && (thisItem.getGuidSrc().length > 0 && nextItem.getGuidSrc().length > 0 && thisItem.getGuidSrc()[0].equals(nextItem.getGuidSrc()[0]))) { + duplicateLst.add(i + 1); duplicateLst.add(j + 1); } @@ -295,8 +298,14 @@ public class FFTIControlDlg extends Dialog { HashSet duplicates = getDuplicates(); if (duplicates.size() > 0) { String setsStr = ""; - for (Integer setIndex : duplicates) - setsStr += setIndex + "/"; + int i = 0; + for (Integer setIndex : duplicates) { + setsStr += setIndex; + if (i != duplicates.size()-1) { + setsStr = setsStr + "/"; + } + i++; + } MessageBox messageBox = new MessageBox(shell, SWT.OK); messageBox.setText("Warning: Duplicate Setting(s)!"); messageBox diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/SettingComp.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/SettingComp.java index d66d03f65e..23009cd527 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/SettingComp.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/SettingComp.java @@ -20,6 +20,7 @@ package com.raytheon.uf.viz.monitor.ffmp.ffti; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import org.eclipse.swt.SWT; @@ -45,6 +46,17 @@ import com.raytheon.uf.common.monitor.xml.ProductRunXML; import com.raytheon.uf.common.monitor.xml.ProductXML; import com.raytheon.uf.common.monitor.xml.SourceXML; +/** + * FFTI Setting Composite. + * + *
+ * SOFTWARE HISTORY
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * 08/07/2012   578        mpduff      FFTI now only a single selection and populates
+ *                                     correctly.
+ * 
+ */ public class SettingComp extends Composite implements DurationInterface { /** * Parent tab folder. @@ -102,6 +114,8 @@ public class SettingComp extends Composite implements DurationInterface { // temporary storage for qpf private String selectedQpfVal = "0"; + + private FFTISettingXML fftiSetting; public SettingComp(TabFolder parent) { super(parent, 0); @@ -115,7 +129,8 @@ public class SettingComp extends Composite implements DurationInterface { super(parent, 0); this.parent = parent; - + this.fftiSetting = fftiSetting; + init(); // set the attributes @@ -217,6 +232,8 @@ public class SettingComp extends Composite implements DurationInterface { accumRdo.setEnabled(true); accumAction(accumAttrib); + + setSettings(); } private void createAttributeControls() { @@ -318,7 +335,7 @@ public class SettingComp extends Composite implements DurationInterface { gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false); gd.widthHint = listWidth; gd.heightHint = listHeight; - qpeList = new List(precipSrcComp, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); + qpeList = new List(precipSrcComp, SWT.BORDER | SWT.V_SCROLL); qpeList.setLayoutData(gd); fillQpeList(); @@ -327,8 +344,7 @@ public class SettingComp extends Composite implements DurationInterface { gd.horizontalSpan = 2; gd.widthHint = listWidth - 75; gd.heightHint = listHeight; - guidList = new List(precipSrcComp, SWT.BORDER | SWT.MULTI - | SWT.V_SCROLL); + guidList = new List(precipSrcComp, SWT.BORDER | SWT.V_SCROLL); guidList.setLayoutData(gd); fillGuidList(); @@ -337,7 +353,7 @@ public class SettingComp extends Composite implements DurationInterface { gd.horizontalSpan = 2; gd.widthHint = listWidth; gd.heightHint = listHeight; - qpfList = new List(precipSrcComp, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); + qpfList = new List(precipSrcComp, SWT.BORDER | SWT.V_SCROLL); qpfList.setLayoutData(gd); fillQpfList(); @@ -393,9 +409,6 @@ public class SettingComp extends Composite implements DurationInterface { guidSet.add(sourceName); guidList.add(sourceName); } - if (guidList.getItemCount() > 0) { - guidList.setSelection(0); - } guidList.addSelectionListener(new SelectionListener() { @@ -438,9 +451,10 @@ public class SettingComp extends Composite implements DurationInterface { if (source.isMosaic()) { if (!qpeSet.contains(product.getProductKey())) { - if (!qpeSet.contains(source.getDisplayName())) { - qpeSet.add(source.getDisplayName()); - qpeList.add(source.getDisplayName()); + String displayName = source.getDisplayName(); + if (!qpeSet.contains(displayName)) { + qpeSet.add(displayName); + qpeList.add(displayName); } break; } @@ -460,10 +474,6 @@ public class SettingComp extends Composite implements DurationInterface { } } } - - if (qpeList.getItemCount() > 0) { - qpeList.setSelection(0); - } } /** @@ -516,10 +526,6 @@ public class SettingComp extends Composite implements DurationInterface { } } } - - if (qpfList.getItemCount() > 0) { - qpfList.setSelection(0); - } } /** @@ -598,6 +604,55 @@ public class SettingComp extends Composite implements DurationInterface { SWT.COLOR_WHITE)); attrLbl.setLayoutData(gd); } + + /** + * Set the dialog to reflect the saved configuration. + */ + private void setSettings() { + // Select the configured items, otherwise select the first + + if (this.fftiSetting != null) { + // QPE + if (fftiSetting.getQpeSource().getDisplayNameList() == null || + fftiSetting.getQpeSource().getDisplayNameList().isEmpty()) { + qpeList.setSelection(0); + } else { + // Only using the first one in the list to match A1 + java.util.List items = Arrays.asList(qpeList.getItems()); + String name = fftiSetting.getQpeSource().getDisplayNameList().get(0); + int idx = items.indexOf(name); + qpeList.select(idx); + qpeList.showSelection(); + } + + // GUID + if (fftiSetting.getGuidSource().getDisplayNameList() == null || + fftiSetting.getGuidSource().getDisplayNameList().isEmpty()) { + guidList.setSelection(0); + } else { + // Only using the first one in the list to match A1 + java.util.List items = Arrays.asList(guidList.getItems()); + String name = fftiSetting.getGuidSource().getDisplayNameList().get(0); + int idx = items.indexOf(name); + guidList.select(idx); + guidList.showSelection(); + } + + // QPF + if (fftiSetting.getQpfSource().getDisplayNameList() == null || + fftiSetting.getQpfSource().getDisplayNameList().isEmpty()) { + qpfList.setSelection(0); + } else { + // Only using the first one in the list to match A1 + java.util.List items = Arrays.asList(qpfList.getItems()); + String name = fftiSetting.getQpfSource().getDisplayNameList().get(0); + int idx = items.indexOf(name); + qpfList.select(idx); + qpfList.showSelection(); + } + + } + } private void accumAction(FFTIAttribute attribVal) { // change attribute values diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPConfig.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPConfig.java index dd17900eb3..04d9846250 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPConfig.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPConfig.java @@ -45,6 +45,22 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData.COLUMN_NA import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPConfigBasinXML; import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPTableColumnXML; +/** + * FFMP GUI Config Object. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 01, 2012 14168      mpduff       Add convenience methods for 
+ *                                      getting ColorCell and ReverseFilter
+ * 
+ * 
+ * + * @author lvenable + * @version 1.0 + */ public class FFMPConfig { private static FFMPConfig classInstance = new FFMPConfig(); @@ -97,9 +113,9 @@ public class FFMPConfig { private HashMap threshMgrMap; private HashMap thresholdLookup; - + private AttributesDlgData attrData = null; - + private boolean reReadAttrData = false; private FFMPConfig() { @@ -357,7 +373,7 @@ public class FFMPConfig { return null; } - + public void createAttributesDlgData(String siteKey) { ArrayList columnData = ffmpCfgBasin .getTableColumnData(); @@ -371,7 +387,7 @@ public class FFMPConfig { for (int i = 0; i < columns.length; i++) { String column = columns[i]; String displayName = null; - + for (FFMPTableColumnXML tcXML : columnData) { if (column.contains("_")) { String[] parts = column.split("_"); @@ -380,10 +396,14 @@ public class FFMPConfig { } if (column.equalsIgnoreCase(tcXML.getColumnName())) { boolean includedInTable = false; - if (column.equalsIgnoreCase(COLUMN_NAME.GUID.getColumnName()) || - column.equalsIgnoreCase(COLUMN_NAME.RATIO.getColumnName()) || - column.equalsIgnoreCase(COLUMN_NAME.DIFF.getColumnName())) { - if (ffmpCfgBasin.getIncludedGuids().contains(displayName)) { + if (column.equalsIgnoreCase(COLUMN_NAME.GUID + .getColumnName()) + || column.equalsIgnoreCase(COLUMN_NAME.RATIO + .getColumnName()) + || column.equalsIgnoreCase(COLUMN_NAME.DIFF + .getColumnName())) { + if (ffmpCfgBasin.getIncludedGuids().contains( + displayName)) { includedInTable = true; attrData.setGuidColumnIncluded(displayName, includedInTable); @@ -397,8 +417,9 @@ public class FFMPConfig { } } } - - public AttributesDlgData getVisibleColumns(String siteKey, boolean reReadAttrData) { + + public AttributesDlgData getVisibleColumns(String siteKey, + boolean reReadAttrData) { this.reReadAttrData = reReadAttrData; return getVisibleColumns(siteKey); } @@ -413,33 +434,46 @@ public class FFMPConfig { public void setVisibleColumns(AttributesDlgData attrData) { this.attrData = attrData; - + ArrayList columnData = ffmpCfgBasin .getTableColumnData(); - for (FFMPTableColumnXML tcXML : columnData) { - if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.RATE.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.RATE.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.NAME.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.NAME.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.QPE.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.QPE.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.QPF.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.QPF.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.GUID.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.GUID.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.RATIO.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.RATIO.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.DIFF.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.DIFF.getColumnName())); + if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.RATE.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.RATE.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.NAME.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.NAME.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.QPE.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.QPE.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.QPF.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.QPF.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.GUID.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.GUID.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.RATIO.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.RATIO.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.DIFF.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.DIFF.getColumnName())); } } - + HashMap guidanceMap = attrData.getGuidanceList(); String list = ""; boolean first = true; - for (String key: guidanceMap.keySet()) { + for (String key : guidanceMap.keySet()) { if (first == false) { list.concat(","); } @@ -496,7 +530,8 @@ public class FFMPConfig { * starts. If the column is not visible then default the sort column to be * the name column. * - * @param siteKey The siteKey being used + * @param siteKey + * The siteKey being used * @return Column index. */ public int getStartSortIndex(String siteKey) { @@ -506,7 +541,7 @@ public class FFMPConfig { FfmpTableConfig tableCfg = FfmpTableConfig.getInstance(); FFMPSourceConfigurationManager sourceConfigManager = FFMPSourceConfigurationManager .getInstance(); - + FFMPRunXML runner = configManager.getRunner(monitor.getWfo()); ProductRunXML prodRunXml = runner.getProduct(siteKey); String name = prodRunXml.getProductName(); @@ -514,7 +549,7 @@ public class FFMPConfig { ProductXML productXml = sourceConfigManager.getProduct(name); ArrayList guidTypes = productXml.getAvailableGuidanceTypes(); - + String guidRankSource = null; if (guidTypes.size() > 1) { String colSorted = ffmpCfgBasin.getColumnSorted(); @@ -523,7 +558,7 @@ public class FFMPConfig { guidRankSource = parts[1]; } } - + FfmpTableConfigData tableCfgData = tableCfg.getTableConfigData(siteKey); String[] tableColumns = tableCfgData.getTableColumnKeys(); String sortedColName = ffmpCfgBasin.getColumnSorted(); @@ -539,7 +574,7 @@ public class FFMPConfig { column = parts[1]; guidType = parts[0]; } - + if (column.equalsIgnoreCase(sortedColName)) { if ((guidType != null) && (guidRankSource != null)) { if (guidType.equalsIgnoreCase(guidRankSource)) { @@ -554,7 +589,7 @@ public class FFMPConfig { } } } - + return 0; } @@ -562,10 +597,16 @@ public class FFMPConfig { if (columnName.contains("_")) { return true; } - + return false; } - + + /** + * Get the filter value for this column. + * + * @param threshColName + * @return The filter value + */ public double getFilterValue(ThreshColNames threshColName) { ArrayList columnData = ffmpCfgBasin .getTableColumnData(); @@ -575,6 +616,36 @@ public class FFMPConfig { return data.getFilter(); } + /** + * Get the ColorCell value for this column. + * + * @param threshColName + * @return The ColorCell value + */ + public boolean isColorCell(ThreshColNames threshColName) { + ArrayList columnData = ffmpCfgBasin + .getTableColumnData(); + + FFMPTableColumnXML data = columnData.get(threshColName.getColIndex()); + + return data.getColorCell(); + } + + /** + * Get the reverse filter value for this column. + * + * @param threshColName + * @return The Reverse Filter value + */ + public boolean isReverseFilter(ThreshColNames threshColName) { + ArrayList columnData = ffmpCfgBasin + .getTableColumnData(); + + FFMPTableColumnXML data = columnData.get(threshColName.getColIndex()); + + return data.getReverseFilter(); + } + /** * @return the attrData */ @@ -583,7 +654,8 @@ public class FFMPConfig { } /** - * @param attrData the attrData to set + * @param attrData + * the attrData to set */ public void setAttrData(AttributesDlgData attrData) { this.attrData = attrData; @@ -597,12 +669,13 @@ public class FFMPConfig { } /** - * @param reReadAttrData the reReadAttrData to set + * @param reReadAttrData + * the reReadAttrData to set */ public void setReReadAttrData(boolean reReadAttrData) { this.reReadAttrData = reReadAttrData; } - + public String getIncludedGuids() { return ffmpCfgBasin.getIncludedGuids(); } diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java index 62a18c9fc8..00e9c2d972 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java @@ -52,6 +52,7 @@ import com.raytheon.uf.common.monitor.data.CommonConfig; import com.raytheon.uf.common.monitor.data.CommonConfig.AppName; import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPConfig.ThreshColNames; import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData.COLUMN_NAME; +import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPConfigBasinXML; import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPTableColumnXML; /** @@ -67,17 +68,20 @@ import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPTableColumnXML; * Apr 7, 2009 lvenable Initial creation * Mar 15,2012 DR 14406 gzhang Fixing QPF Column Title Missing * Mar 20,2012 DR 14250 gzhang Eliminating column Missing values + * Aug 01, 2012 14168 mpduff Only allow filtering if ColorCell is true *
+ * * @author lvenable * @version 1.0 */ public abstract class FFMPTable extends Composite { /** Default column width */ - protected static final int DEFAULT_COLUMN_WIDTH = 95;//DR14406: old value: 75 too small + protected static final int DEFAULT_COLUMN_WIDTH = 95;// DR14406: old value: + // 75 too small - /** DR14406: For columns with more words */ + /** DR14406: For columns with more words */ protected static final int EXTRA_COLUMN_WIDTH = 28; - + protected String currentPfaf = null; /** @@ -326,10 +330,10 @@ public abstract class FFMPTable extends Composite { cols[j].setImage(null); cols[j].setWidth(defaultColWidth); } - + // reset the tableIndex tableIndex = -1; - + /* * Check of the column is sortable. */ @@ -377,17 +381,36 @@ public abstract class FFMPTable extends Composite { int sortColIndex = table.indexOf(sortedTableColumn); boolean isAFilterCol = false; ThreshColNames sortedThreshCol = null; + boolean reverseFilter = false; double filterNum = Double.NaN; - String columnName = getColumnKeys()[sortColIndex]; + String sortedColumnName = getColumnKeys()[sortColIndex]; + + FFMPConfigBasinXML ffmpCfgBasin = FFMPConfig.getInstance() + .getFFMPConfigData(); + + ArrayList ffmpTableCols = ffmpCfgBasin + .getTableColumnData(); + + for (ThreshColNames threshColName : ThreshColNames.values()) { + if (sortedColumnName.contains(threshColName.name())) { + sortedThreshCol = threshColName; + break; + } + } + // Check if the sorted column is a column that will contain a filter. - if (!columnName.equalsIgnoreCase("NAME")) { - isAFilterCol = true; - for (ThreshColNames threshColName : ThreshColNames.values()) { - if (columnName.contains(threshColName.name())) { - sortedThreshCol = threshColName; - filterNum = ffmpConfig.getFilterValue(threshColName); + // Check the gui config to see if colorCell is true. If false then do + // not apply filter + for (FFMPTableColumnXML xml : ffmpTableCols) { + if (xml.getColumnName().contains(sortedThreshCol.name())) { + if (ffmpConfig.isColorCell(sortedThreshCol)) { + // Only filter if colorCell is true + isAFilterCol = true; + filterNum = ffmpConfig.getFilterValue(sortedThreshCol); + reverseFilter = ffmpConfig.isReverseFilter(sortedThreshCol); } + break; } } @@ -414,38 +437,16 @@ public abstract class FFMPTable extends Composite { extent.x); /* - * Check if the sorted column is a filter column. + * Check if the data value is Not A Number. */ - if (isAFilterCol == true) { - /* - * Check if the data value is Not A Number. - */ - float dataVal = cellData[sortColIndex] - .getValueAsFloat(); - //DR 14250 fix: any value not a number will be omitted - if (/*sortedThreshCol.name().equalsIgnoreCase("RATIO") &&*/ Float.isNaN(dataVal)) { - continue; - } - - // if (sortedThreshCol.name().equalsIgnoreCase("RATIO") == false) { - - // If the data value is less/more than the filter value - // continue - // so we don't put the data in the table. Less for normal - // filtering, - // more for reverse filtering - ArrayList tcList = ffmpConfig - .getFFMPConfigData().getTableColumnData(); - boolean reverseFilter = false; - for (FFMPTableColumnXML tc : tcList) { - if (tc.getColumnName().equalsIgnoreCase( - sortedThreshCol.name())) { - reverseFilter = tc.getReverseFilter(); - break; - } - } - // } + float dataVal = cellData[sortColIndex].getValueAsFloat(); + // DR 14250 fix: any value not a number will be omitted + if (/* sortedThreshCol.name().equalsIgnoreCase("RATIO") && */Float + .isNaN(dataVal)) { + continue; + } + if (isAFilterCol) { if (reverseFilter) { if (dataVal > filterNum) { continue; @@ -458,7 +459,7 @@ public abstract class FFMPTable extends Composite { } indexArray.add(t); - + // Check to see if this is the selected row if (rowData.getPfaf().equals(currentPfaf)) { tableIndex = indexArray.indexOf(t); @@ -667,7 +668,10 @@ public abstract class FFMPTable extends Composite { } } - imageWidth = maxTextLength * textWidth + EXTRA_COLUMN_WIDTH;//DR14406: old value 6 too small + imageWidth = maxTextLength * textWidth + EXTRA_COLUMN_WIDTH;// DR14406: + // old value + // 6 too + // small imageHeight = textHeight * 2; gc.dispose(); @@ -722,25 +726,34 @@ public abstract class FFMPTable extends Composite { String[] tmpArray = colName.split("\n"); for (int j = 0; j < tmpArray.length; j++) { -// if (tmpArray[j].length() > maxTextLen) { -// maxTextLen = tmpArray[j].length(); -// } -// } + // if (tmpArray[j].length() > maxTextLen) { + // maxTextLen = tmpArray[j].length(); + // } + // } - xCoord = Math.round((imageWidth / 2)- (tmpArray[j].length() /*DR14406: old value: maxTextLen*/* textWidth / 2)); - yCoord = j*(textHeight+1);//DR14406: old value 0 is only for the 1st line - gc.drawText(tmpArray[j], xCoord, yCoord, true);//DR14406: draw each line separately + xCoord = Math.round((imageWidth / 2) + - (tmpArray[j].length() /* + * DR14406: old value: + * maxTextLen + */* textWidth / 2)); + yCoord = j * (textHeight + 1);// DR14406: old value 0 is + // only for the 1st line + gc.drawText(tmpArray[j], xCoord, yCoord, true);// DR14406: + // draw each + // line + // separately } } else { xCoord = Math.round((imageWidth / 2) - (colName.length() * textWidth / 2)); yCoord = imageHeight / 2 - textHeight / 2 - 1; - gc.drawText(colName, xCoord, yCoord, true);//DR14406: draw text with a single line + gc.drawText(colName, xCoord, yCoord, true);// DR14406: draw text + // with a single line } -// System.out.println("Column name = " + colName); - //DR14406: move the below text drawing code into the if-else blocks - //gc.drawText(colName, xCoord, yCoord, true); + // System.out.println("Column name = " + colName); + // DR14406: move the below text drawing code into the if-else blocks + // gc.drawText(colName, xCoord, yCoord, true); gc.dispose(); tc.setImage(img); @@ -794,9 +807,10 @@ public abstract class FFMPTable extends Composite { tCols[i].setWidth(table.getColumn(i).getWidth()); } else { tCols[i].setWidth(defaultColWidth); - } - - setQPFColName(tCols[i], col);//DR14406: set QPF title with quicker response + } + + setQPFColName(tCols[i], col);// DR14406: set QPF title with + // quicker response } else { tCols[i].setWidth(0); } @@ -876,27 +890,24 @@ public abstract class FFMPTable extends Composite { */ protected abstract int getColumnIndex(String sortCol); - - - - /** - * DR14406 code: QPF column's name should be re-set - * when a user choose another type of QPF from the - * Attributes... button. + * DR14406 code: QPF column's name should be re-set when a user choose + * another type of QPF from the Attributes... button. * * See FfmpTableConfigData.setQpfType() with ColumnAttribData * - * @param tCols: TableColumn - * @param col: Column name + * @param tCols + * : TableColumn + * @param col + * : Column name */ - private void setQPFColName(TableColumn tCols, String col){ - - if(COLUMN_NAME.QPF.getColumnName().equalsIgnoreCase(col)){ - - setColumnImages(); - tCols.setWidth(defaultColWidth+EXTRA_COLUMN_WIDTH);//38); - - } + private void setQPFColName(TableColumn tCols, String col) { + + if (COLUMN_NAME.QPF.getColumnName().equalsIgnoreCase(col)) { + + setColumnImages(); + tCols.setWidth(defaultColWidth + EXTRA_COLUMN_WIDTH);// 38); + + } } } \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java index e306edc226..0501df28d1 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java @@ -84,6 +84,8 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPLoaderStatus; import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPResource; import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPTableDataLoader; import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPTableDataUpdate; +import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPConfigBasinXML; +import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPTableColumnXML; import com.raytheon.uf.viz.monitor.listeners.IMonitorListener; import com.raytheon.viz.ui.dialogs.CaveSWTDialog; @@ -96,6 +98,10 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Sep 30, 2009 lvenable Initial creation + * Jul 31, 2012 14517 mpduff Fix map blanking on updates and table updates + * for rapid slider changes. + * Aug 01, 2012 14168 mpduff Only allow items into the Thresholds menu if + * ColorCell is true. * * * @@ -110,7 +116,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements .getHandler(FfmpBasinTableDlg.class); private List retrievalQueue = new ArrayList(); - + private MenuItem linkToFrameMI; private MenuItem worstCaseMI; @@ -220,7 +226,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements private Composite tableComp; private FFMPTableDataLoader dataRetrieveThread = null; - + private boolean sweet = true; public FfmpBasinTableDlg(Shell parent, FFMPTableData tData, @@ -496,10 +502,11 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements mi.setSelection(true); break; } - } + } } else { sourceMenuItems.get(0).setSelection(true); - ffmpConfig.getFFMPConfigData().setGuidSrc(sourceMenuItems.get(0).getText()); + ffmpConfig.getFFMPConfigData().setGuidSrc( + sourceMenuItems.get(0).getText()); } fireFieldChangedEvent(FFMPRecord.FIELDS.RATIO, false); @@ -561,7 +568,8 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements for (int i = 0; i < sourceMenuItems.size(); i++) { String rdo = sourceMenuItems.get(i).getText(); if (rdo.equals(guidSrc)) { - ffmpConfig.getFFMPConfigData().setGuidSrc(guidSrc); + ffmpConfig.getFFMPConfigData().setGuidSrc( + guidSrc); fireConfigUpdateEvent(); break; } @@ -1023,18 +1031,21 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements // Loop over enum from config singleton to create menu items for (ThreshColNames colName : ThreshColNames.values()) { - MenuItem mi = new MenuItem(popupMenu, SWT.NONE); - mi.setText(colName.name()); - mi.setData(colName); - mi.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - MenuItem mi = (MenuItem) e.getSource(); - ThreshColNames colName = (ThreshColNames) mi.getData(); + if (ffmpConfig.isColorCell(colName)) { + // only add a menu item if colorCell is true + MenuItem mi = new MenuItem(popupMenu, SWT.NONE); + mi.setText(colName.name()); + mi.setData(colName); + mi.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + MenuItem mi = (MenuItem) e.getSource(); + ThreshColNames colName = (ThreshColNames) mi.getData(); - displayThresholdsDialog(colName); - } - }); + displayThresholdsDialog(colName); + } + }); + } } // Set the pop-up menu as the pop-up for the shell @@ -1267,27 +1278,27 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements this.ffmpConfig.setAttrData(attrData); this.ffmpTable.showHideTableColumns(); boolean changeSplit = false; - + if (timeDurScale.split != ffmpConfig.isSplit()) { - changeSplit = true; + changeSplit = true; } timeDurScale.setSplit(ffmpConfig.isSplit()); updateTimeDurationLabel(timeDurScale.getSelectedHoursValue(), ffmpConfig.isSplit()); - if (updateData) { + if (updateData) { - if (changeSplit) { - fireTimeChangedEvent(timeDurScale.getSelectedHoursValue(), - ffmpConfig.isSplit(), true); - } - resource.clearTables(); - resource.getDrawable(resource.getPaintTime()).setDirty(true); - FFMPMonitor.getInstance().fireMonitorEvent( - this.getClass().getName()); + if (changeSplit) { + fireTimeChangedEvent(timeDurScale.getSelectedHoursValue(), + ffmpConfig.isSplit(), true); + } + resource.clearTables(); + resource.getDrawable(resource.getPaintTime()).setDirty(true); + FFMPMonitor.getInstance().fireMonitorEvent( + this.getClass().getName()); - } + } ffmpTable.calculateTableSize(); shell.pack(); @@ -1330,7 +1341,8 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements ffmpListeners.remove(fl); } - public void fireTimeChangedEvent(double newTime, boolean split, boolean override) { + public void fireTimeChangedEvent(double newTime, boolean split, + boolean override) { FFMPRecord.FIELDS field = FFMPRecord.FIELDS.QPE; @@ -1381,7 +1393,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements if (waitCursor == true) { shell.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); } - + FFMPFieldChangeEvent ffce = new FFMPFieldChangeEvent(field); Iterator iter = ffmpListeners.iterator(); @@ -1420,9 +1432,9 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements if (!selected) { cwas.remove(cwa); } else { - if (!cwas.contains(cwa)) { - cwas.add(cwa); - } + if (!cwas.contains(cwa)) { + cwas.add(cwa); + } } FFMPCWAChangeEvent fcce = new FFMPCWAChangeEvent(cwas); @@ -1659,23 +1671,22 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements * @param tData */ public void resetData(FFMPTableData tData) { - if (!ffmpTable.isDisposed()) { this.mainTableData = tData; - //System.out.println("---" + tData.getTableRows().size()); + // System.out.println("---" + tData.getTableRows().size()); ffmpTable.clearTableSelection(); - //long time = System.currentTimeMillis(); + // long time = System.currentTimeMillis(); ffmpTable .setCenteredAggregationKey(resource.centeredAggregationKey); ffmpTable.setTableData(mainTableData); - //long time1 = System.currentTimeMillis(); + // long time1 = System.currentTimeMillis(); resetCursor(); shell.pack(); shell.redraw(); - //System.out - // .println("Time to load Data into table " + (time1 - time)); + // System.out + // .println("Time to load Data into table " + (time1 - time)); } } @@ -1689,7 +1700,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements || allOnlySmallBasinsMI.getSelection()) { groupLbl.setText(name); } - + shell.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); fireScreenRecenterEvent(pfaf, 1); } @@ -1776,7 +1787,8 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements */ timeDurScale.setTimeDurationAndUpdate(ffmpConfig.getFFMPConfigData() .getTimeFrame()); - fireTimeChangedEvent(ffmpConfig.getFFMPConfigData().getTimeFrame(), false, false); + fireTimeChangedEvent(ffmpConfig.getFFMPConfigData().getTimeFrame(), + false, false); /* * Layer @@ -1847,7 +1859,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements } fireAutoRefreshEvent(false); - + /* * CWAs * @@ -2039,7 +2051,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements resource, basinTrendDlg, allowNewTableUpdate, sourceUpdate, date, this); - synchronized (retrievalQueue) { + synchronized (retrievalQueue) { if (dataRetrieveThread == null || dataRetrieveThread.isDone()) { retrievalQueue.clear(); dataRetrieveThread = tableLoader; @@ -2050,7 +2062,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements } } } - + /** * Get the latest TableDataLoader and clear all previous loaders * @@ -2058,7 +2070,8 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements */ private FFMPTableDataLoader getLoader() { synchronized (retrievalQueue) { - FFMPTableDataLoader loader = retrievalQueue.get(retrievalQueue.size() - 1); + FFMPTableDataLoader loader = retrievalQueue.get(retrievalQueue + .size() - 1); retrievalQueue.clear(); return loader; } @@ -2091,45 +2104,54 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements public void tableDataUpdateComplete(FFMPTableDataUpdate updateData) { final FFMPTableDataUpdate fupdateData = updateData; - + if (!this.isDisposed()) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { - allowNewTableUpdate = fupdateData.isAllowNewTableUpdate(); - sourceUpdate = fupdateData.isSourceUpdate(); - - if (fupdateData.getTableData() != null && sweet) { - resetData(fupdateData.getTableData()); - } - - if (fupdateData.isFireGraph()) { - fireGraphDataEvent(fupdateData.getGraphPfaf(), false, - fupdateData.getGraphTime()); - } - - setValidTime(fupdateData.getValidTime()); - updateGapValueLabel(fupdateData.getGapValueLabel()); - - resetCursor(); - sweet = true; - - if (retrievalQueue.size() > 0) { - dataRetrieveThread = getLoader(); - dataRetrieveThread.start(); - } + processUpdate(fupdateData); } }); } } + /** - * used to blank the group label when channging HUC - * while in an aggregate. + * Process the update + */ + private void processUpdate(FFMPTableDataUpdate fupdateData) { + allowNewTableUpdate = fupdateData.isAllowNewTableUpdate(); + sourceUpdate = fupdateData.isSourceUpdate(); + + if (retrievalQueue.size() > 0) { + dataRetrieveThread = getLoader(); + dataRetrieveThread.start(); + return; + } else { + } + + if (fupdateData.getTableData() != null && sweet) { + resetData(fupdateData.getTableData()); + } + + if (fupdateData.isFireGraph()) { + fireGraphDataEvent(fupdateData.getGraphPfaf(), false, + fupdateData.getGraphTime()); + } + + setValidTime(fupdateData.getValidTime()); + updateGapValueLabel(fupdateData.getGapValueLabel()); + + resetCursor(); + sweet = true; + } + + /** + * used to blank the group label when channging HUC while in an aggregate. */ public void blankGroupLabel() { - if (groupLbl != null) { - groupLbl.setText(""); - } + if (groupLbl != null) { + groupLbl.setText(""); + } } } 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 e5e565d4c3..0a0dd588bb 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 @@ -149,6 +149,8 @@ import com.vividsolutions.jts.geom.Point; * ------------ ---------- ----------- -------------------------- * 29 June, 2009 2521 dhladky Initial creation * 11 Apr. 2012 DR 14522 gzhang Fixing invalid thread error. + * 31 July 2012 14517 mpduff Fix for blanking map on update. + * * * @author dhladky * @version 1.0 @@ -376,6 +378,9 @@ public class FFMPResource extends /** force utility **/ private FFFGForceUtil forceUtil = null; + /** Restore Table flag */ + private boolean restoreTable = false; + /** * FFMP resource * @@ -2441,7 +2446,8 @@ public class FFMPResource extends } if ((cwaBasins.size() == 0) || !req.extent.equals(drawable.getExt()) - || !phuc.equals(drawable.getHuc())) { + || !phuc.equals(drawable.getHuc()) + || restoreTable) { Envelope env = null; try { Envelope e = req.descriptor.pixelToWorld(req.extent, @@ -2466,7 +2472,7 @@ public class FFMPResource extends templates, getSiteKey(), cwa, phuc); for (Entry entry : envMap.entrySet()) { - if (env.intersects(entry.getValue())) { + if (env.intersects(entry.getValue()) || env.contains(entry.getValue())) { // add the individual basins cwaBasins.add(entry.getKey()); } @@ -2766,6 +2772,10 @@ public class FFMPResource extends } } + if (restoreTable) { + restoreTable = false; + } + drawable.setTime(req.time); if (lowestCenter != ZOOM.BASIN) { drawable.setCenterAggrKey(centeredAggregationKey); @@ -3189,7 +3199,8 @@ public class FFMPResource extends public void restoreTable() { centeredAggregationKey = null; centeredAggregatePfafList = null; - + restoreTable = true; + lowestCenter = FFMPRecord.ZOOM.WFO; getDescriptor().getRenderableDisplay().getExtent().reset(); zoom(1.0f); diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java index 1d80cf92f8..7a62a2bff9 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java @@ -41,7 +41,8 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpBasinTableDlg; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Oct 13, 2011 dhladky Initial creation + * Oct 13, 2011 dhladky Initial creation. + * Jul 31, 2012 14517 mpduff Fix for Rapid slider changes * * * @@ -142,11 +143,13 @@ public class FFMPTableDataLoader extends Thread { // System.out // .println(" Cache MISSSSSSSSSSSS!!!!!"); + + double origDrawTime = resource.getTime(); FFMPDataGenerator dg = new FFMPDataGenerator( ffmp, resource); tData = dg.generateFFMPData(); drawable.setTableData(iHuc, tData); - drawable.setDrawTime(resource.getTime()); + drawable.setDrawTime(origDrawTime); } } } catch (Exception e) { diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/ScanResource.java b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/ScanResource.java index 8c29ae880c..0b314f53ec 100644 --- a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/ScanResource.java +++ b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/ScanResource.java @@ -79,6 +79,8 @@ import com.vividsolutions.jts.geom.Coordinate; * ------------ ---------- ----------- -------------------------- * Oct 13, 2009 dhladky Initial creation * + * Jul 24 2012 12996 Xiaochuan Compare with MidVal() + * * * * @author dhladky @@ -359,7 +361,7 @@ public class ScanResource extends d = Double.valueOf(rank); } - if (d >= getScanDrawer().ddfc.getLowerVal()) { + if (d >= getScanDrawer().ddfc.getMidVal()) { if (!getScanDrawer().ddfc.isOverlap()) { if ((dtdr != null) && !dtdr.getOverlap()) { isOverlap = false; diff --git a/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/data/TableUtil.java b/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/data/TableUtil.java index d6938540ae..146af00d7c 100644 --- a/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/data/TableUtil.java +++ b/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/data/TableUtil.java @@ -902,192 +902,232 @@ public final class TableUtil { return null; } - private static TableRowData getSnowMetarHistTableRowData(ObReport report) { - TableRowData tblRowData = new TableRowData(8); - tblRowData.setTableCellData(0, new TableCellData(report.getObservationTime(),"HH:mm MMM dd",CellType.ObsHist)); - tblRowData.setTableCellData(1, - new TableCellData(Math.round(new Float(report.getWindDir())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(2, - new TableCellData(Math.round(new Float(report.getWindSpeed())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(3, - new TableCellData(Math.round(new Float(report.getWindGust())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(4, new TableCellData(report.getPressure(), CellType.ObsHist, CommonTableConfig.obsHistCols.P)); - tblRowData.setTableCellData( - 5, - new TableCellData( - Math.round(new Float(report.getTemperature())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(6, - new TableCellData(Math.round(new Float(report.getDewpoint())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(7, new TableCellData(report.getPressureChange(), CellType.ObsHist, CommonTableConfig.obsHistCols.PTend)); - return tblRowData; - } + private static TableRowData getSnowMetarHistTableRowData(ObReport report) { + TableRowData tblRowData = new TableRowData(10); + tblRowData.setTableCellData(0, + new TableCellData(report.getObservationTime(), "HH:mm MMM dd", + CellType.ObsHist)); + tblRowData.setTableCellData(1, + new TableCellData(new Float(report.getLatitude()), + CellType.ObsHist, true)); + tblRowData.setTableCellData(2, + new TableCellData(new Float(report.getLongitude()), + CellType.ObsHist, true)); + tblRowData.setTableCellData(3, + new TableCellData(Math.round(new Float(report.getWindDir())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(4, + new TableCellData(Math.round(new Float(report.getWindSpeed())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(5, + new TableCellData(Math.round(new Float(report.getWindGust())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(6, new TableCellData(report.getPressure(), + CellType.ObsHist, CommonTableConfig.obsHistCols.P)); + tblRowData.setTableCellData(7, + new TableCellData( + Math.round(new Float(report.getTemperature())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(8, + new TableCellData(Math.round(new Float(report.getDewpoint())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(9, + new TableCellData(report.getPressureChange(), CellType.ObsHist, + CommonTableConfig.obsHistCols.PTend)); + return tblRowData; + } private static TableRowData getSafeSeasMetarHistTableRowData(ObReport report) { // same as getSnowHistTableRowData return getSnowMetarHistTableRowData(report); } - private static TableRowData getSafeseasMaritimeHistTableRowData(ObReport report) { - TableRowData tblRowData = new TableRowData(15); - tblRowData.setTableCellData(0, new TableCellData(report.getObservationTime(),"HH:mm MMM dd",CellType.ObsHist)); - tblRowData.setTableCellData(1, - new TableCellData(Math.round(new Float(report.getWindSpeed())), - CellType.ObsHist, true)); - tblRowData.setTableCellData( - 2, - new TableCellData( - Math.round(new Float(report.getMaxWindSpeed())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(3, - new TableCellData(Math.round(new Float(report.getWindGust())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(4, - new TableCellData( - Math.round(new Float(report.getVisibility())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(5, new TableCellData(report.getPressure(), CellType.ObsHist, CommonTableConfig.obsHistCols.P)); - tblRowData.setTableCellData( - 6, - new TableCellData(Math.round(new Float(report - .getPressureChange())), CellType.ObsHist, true)); - tblRowData.setTableCellData( - 7, - new TableCellData( - Math.round(new Float(report.getTemperature())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(8, - new TableCellData(Math.round(new Float(report.getDewpoint())), - CellType.ObsHist, true)); - tblRowData.setTableCellData( - 9, - new TableCellData(Math.round(new Float(report - .getSeaSurfaceTemp())), CellType.ObsHist, true)); - tblRowData.setTableCellData( - 10, - new TableCellData(Math.round(new Float(report - .getHighResWaveHeight())), CellType.ObsHist, true)); - tblRowData.setTableCellData( - 11, - new TableCellData(Math.round(new Float(report - .getWaveSteepness())), CellType.ObsHist, true)); - tblRowData.setTableCellData( - 12, - new TableCellData( - Math.round(new Float(report.getPSwellHeight())), - CellType.ObsHist, true)); - tblRowData.setTableCellData( - 13, - new TableCellData( - Math.round(new Float(report.getPSwellPeriod())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(14, - new TableCellData(Math.round(new Float(report.getPSwellDir())), - CellType.ObsHist, true)); - return tblRowData; - } + private static TableRowData getSafeseasMaritimeHistTableRowData( + ObReport report) { + TableRowData tblRowData = new TableRowData(17); + tblRowData.setTableCellData(0, + new TableCellData(report.getObservationTime(), "HH:mm MMM dd", + CellType.ObsHist)); + tblRowData.setTableCellData(1, + new TableCellData(new Float(report.getLatitude()), + CellType.ObsHist, true)); + tblRowData.setTableCellData(2, + new TableCellData(new Float(report.getLongitude()), + CellType.ObsHist, true)); + tblRowData.setTableCellData(3, + new TableCellData(Math.round(new Float(report.getWindSpeed())), + CellType.ObsHist, true)); + tblRowData.setTableCellData( + 4, + new TableCellData( + Math.round(new Float(report.getMaxWindSpeed())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(5, + new TableCellData(Math.round(new Float(report.getWindGust())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(6, + new TableCellData( + Math.round(new Float(report.getVisibility())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(7, new TableCellData(report.getPressure(), + CellType.ObsHist, CommonTableConfig.obsHistCols.P)); + tblRowData.setTableCellData( + 8, + new TableCellData(Math.round(new Float(report + .getPressureChange())), CellType.ObsHist, true)); + tblRowData.setTableCellData( + 9, + new TableCellData( + Math.round(new Float(report.getTemperature())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(10, + new TableCellData(Math.round(new Float(report.getDewpoint())), + CellType.ObsHist, true)); + tblRowData.setTableCellData( + 11, + new TableCellData(Math.round(new Float(report + .getSeaSurfaceTemp())), CellType.ObsHist, true)); + tblRowData.setTableCellData( + 12, + new TableCellData(Math.round(new Float(report + .getHighResWaveHeight())), CellType.ObsHist, true)); + tblRowData.setTableCellData( + 13, + new TableCellData(Math.round(new Float(report + .getWaveSteepness())), CellType.ObsHist, true)); + tblRowData.setTableCellData( + 14, + new TableCellData( + Math.round(new Float(report.getPSwellHeight())), + CellType.ObsHist, true)); + tblRowData.setTableCellData( + 15, + new TableCellData( + Math.round(new Float(report.getPSwellPeriod())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(16, + new TableCellData(Math.round(new Float(report.getPSwellDir())), + CellType.ObsHist, true)); + return tblRowData; + } - private static TableRowData getFogMaritimeHistTableRowData(ObReport report) { - TableRowData tblRowData = new TableRowData(16); - tblRowData.setTableCellData(0, new TableCellData(report.getObservationTime(),"HH:mm MMM dd",CellType.ObsHist)); - tblRowData.setTableCellData(1, - new TableCellData(Math.round(new Float(report.getWindSpeed())), - CellType.ObsHist, true)); - tblRowData.setTableCellData( - 2, - new TableCellData( - Math.round(new Float(report.getMaxWindSpeed())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(3, - new TableCellData(Math.round(new Float(report.getWindGust())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(4, - new TableCellData( - Math.round(new Float(report.getVisibility())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(5, new TableCellData(report.getPressure(), CellType.ObsHist, CommonTableConfig.obsHistCols.P)); - tblRowData.setTableCellData( - 6, - new TableCellData(Math.round(new Float(report - .getPressureChange())), CellType.ObsHist, true)); - tblRowData.setTableCellData( - 7, - new TableCellData( - Math.round(new Float(report.getTemperature())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(8, - new TableCellData(Math.round(new Float(report.getDewpoint())), - CellType.ObsHist, true)); - tblRowData.setTableCellData( - 9, - new TableCellData(Math.round(new Float(report - .getSeaSurfaceTemp())), CellType.ObsHist, true)); - tblRowData.setTableCellData( - 10, - new TableCellData(Math.round(new Float(report - .getHighResWaveHeight())), CellType.ObsHist, true)); - tblRowData.setTableCellData( - 11, - new TableCellData(Math.round(new Float(report - .getWaveSteepness())), CellType.ObsHist, true)); - tblRowData.setTableCellData( - 12, - new TableCellData( - Math.round(new Float(report.getPSwellHeight())), - CellType.ObsHist, true)); - tblRowData.setTableCellData( - 13, - new TableCellData( - Math.round(new Float(report.getPSwellPeriod())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(14, - new TableCellData(Math.round(new Float(report.getPSwellDir())), - CellType.ObsHist, true)); - tblRowData.setTableCellData( - 15, - new TableCellData(Math.round(new Float(report - .getRelativeHumidity())), CellType.ObsHist, true)); - return tblRowData; - } + private static TableRowData getFogMaritimeHistTableRowData(ObReport report) { + TableRowData tblRowData = new TableRowData(18); + tblRowData.setTableCellData(0, + new TableCellData(report.getObservationTime(), "HH:mm MMM dd", + CellType.ObsHist)); + tblRowData.setTableCellData(1, + new TableCellData(new Float(report.getLatitude()), + CellType.ObsHist, true)); + tblRowData.setTableCellData(2, + new TableCellData(new Float(report.getLongitude()), + CellType.ObsHist, true)); + tblRowData.setTableCellData(3, + new TableCellData(Math.round(new Float(report.getWindSpeed())), + CellType.ObsHist, true)); + tblRowData.setTableCellData( + 4, + new TableCellData( + Math.round(new Float(report.getMaxWindSpeed())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(5, + new TableCellData(Math.round(new Float(report.getWindGust())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(6, + new TableCellData( + Math.round(new Float(report.getVisibility())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(7, new TableCellData(report.getPressure(), + CellType.ObsHist, CommonTableConfig.obsHistCols.P)); + tblRowData.setTableCellData( + 8, + new TableCellData(Math.round(new Float(report + .getPressureChange())), CellType.ObsHist, true)); + tblRowData.setTableCellData( + 9, + new TableCellData( + Math.round(new Float(report.getTemperature())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(10, + new TableCellData(Math.round(new Float(report.getDewpoint())), + CellType.ObsHist, true)); + tblRowData.setTableCellData( + 11, + new TableCellData(Math.round(new Float(report + .getSeaSurfaceTemp())), CellType.ObsHist, true)); + tblRowData.setTableCellData( + 12, + new TableCellData(Math.round(new Float(report + .getHighResWaveHeight())), CellType.ObsHist, true)); + tblRowData.setTableCellData( + 13, + new TableCellData(Math.round(new Float(report + .getWaveSteepness())), CellType.ObsHist, true)); + tblRowData.setTableCellData( + 14, + new TableCellData( + Math.round(new Float(report.getPSwellHeight())), + CellType.ObsHist, true)); + tblRowData.setTableCellData( + 15, + new TableCellData( + Math.round(new Float(report.getPSwellPeriod())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(16, + new TableCellData(Math.round(new Float(report.getPSwellDir())), + CellType.ObsHist, true)); + tblRowData.setTableCellData( + 17, + new TableCellData(Math.round(new Float(report + .getRelativeHumidity())), CellType.ObsHist, true)); + return tblRowData; + } - private static TableRowData getFogMetarHistTableRowData(ObReport report) { - TableRowData tblRowData = new TableRowData(12); - tblRowData.setTableCellData(0, new TableCellData(report.getObservationTime(),"HH:mm MMM dd",CellType.ObsHist)); - tblRowData.setTableCellData( - 1, - new TableCellData(Math.round(new Float(report - .getRelativeHumidity())), CellType.ObsHist, true)); - tblRowData.setTableCellData(2, - new TableCellData( - Math.round(new Float(report.getVisibility())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(3, - new TableCellData(Math.round(new Float(report.getCeiling())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(4, - new TableCellData(Math.round(new Float(report.getWindDir())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(5, - new TableCellData(Math.round(new Float(report.getWindSpeed())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(6, - new TableCellData(Math.round(new Float(report.getWindGust())), - CellType.ObsHist, true)); - tblRowData.setTableCellData(7, new TableCellData(report.getPressure(), CellType.ObsHist, CommonTableConfig.obsHistCols.P)); - int tmph = Math.round(new Float(report.getTemperature())); - int dpth = Math.round(new Float(report.getDewpoint())); - tblRowData.setTableCellData(8, new TableCellData(tmph, - CellType.ObsHist, true)); - tblRowData.setTableCellData(9, new TableCellData(dpth, - CellType.ObsHist, true)); - tblRowData.setTableCellData(10, new TableCellData(tmph - dpth, - CellType.ObsHist, true)); - tblRowData.setTableCellData(11, new TableCellData(report.getPressureChange(), CellType.ObsHist, CommonTableConfig.obsHistCols.PTend)); - return tblRowData; - } + private static TableRowData getFogMetarHistTableRowData(ObReport report) { + TableRowData tblRowData = new TableRowData(14); + tblRowData.setTableCellData(0, + new TableCellData(report.getObservationTime(), "HH:mm MMM dd", + CellType.ObsHist)); + tblRowData.setTableCellData(1, + new TableCellData(new Float(report.getLatitude()), + CellType.ObsHist, true)); + tblRowData.setTableCellData(2, + new TableCellData(new Float(report.getLongitude()), + CellType.ObsHist, true)); + tblRowData.setTableCellData( + 3, + new TableCellData(Math.round(new Float(report + .getRelativeHumidity())), CellType.ObsHist, true)); + tblRowData.setTableCellData(4, + new TableCellData( + Math.round(new Float(report.getVisibility())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(5, + new TableCellData(Math.round(new Float(report.getCeiling())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(6, + new TableCellData(Math.round(new Float(report.getWindDir())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(7, + new TableCellData(Math.round(new Float(report.getWindSpeed())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(8, + new TableCellData(Math.round(new Float(report.getWindGust())), + CellType.ObsHist, true)); + tblRowData.setTableCellData(9, new TableCellData(report.getPressure(), + CellType.ObsHist, CommonTableConfig.obsHistCols.P)); + int tmph = Math.round(new Float(report.getTemperature())); + int dpth = Math.round(new Float(report.getDewpoint())); + tblRowData.setTableCellData(10, new TableCellData(tmph, + CellType.ObsHist, true)); + tblRowData.setTableCellData(11, new TableCellData(dpth, + CellType.ObsHist, true)); + tblRowData.setTableCellData(12, new TableCellData(tmph - dpth, + CellType.ObsHist, true)); + tblRowData.setTableCellData(13, + new TableCellData(report.getPressureChange(), CellType.ObsHist, + CommonTableConfig.obsHistCols.PTend)); + return tblRowData; + } } diff --git a/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/ui/dialogs/StationTableComp.java b/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/ui/dialogs/StationTableComp.java index 0fda01f220..f15e3df3ac 100644 --- a/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/ui/dialogs/StationTableComp.java +++ b/cave/com.raytheon.uf.viz.monitor/src/com/raytheon/uf/viz/monitor/ui/dialogs/StationTableComp.java @@ -301,7 +301,7 @@ public class StationTableComp extends TableComp { * @param name */ public void setIdLabel(String name) { - idLbl.setText("Zone/County: " + name); + idLbl.setText("Zone/County: "+ this.id +" - "+ name); controlComp.layout(); } diff --git a/cave/com.raytheon.uf.viz.profiler/src/com/raytheon/uf/viz/profiler/ProfilerResource.java b/cave/com.raytheon.uf.viz.profiler/src/com/raytheon/uf/viz/profiler/ProfilerResource.java index e1b43413f6..f75fd316c8 100644 --- a/cave/com.raytheon.uf.viz.profiler/src/com/raytheon/uf/viz/profiler/ProfilerResource.java +++ b/cave/com.raytheon.uf.viz.profiler/src/com/raytheon/uf/viz/profiler/ProfilerResource.java @@ -67,9 +67,12 @@ import com.vividsolutions.jts.geom.Coordinate; * replaced deprecated function calls * replaced deprecated function calls * Feb 10, 2011 8030 bkowal access to the plots ArrayList is now synchronized - * Feb 15, 2011 8036 bkowal magnification only affects the x-axis, wind bards, and + * Feb 15, 2011 8036 bkowal magnification only affects the x-axis, wind barbs, and * the color bar. - * + * ====================================== + * AWIPS2 DR Work + * 08/10/2012 1035 jkorman Changed number of 'staffs' from 12 to 13 and changed time + * display to match AWIPS I. * * * @author dhladky @@ -81,6 +84,8 @@ public class ProfilerResource extends private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(ProfilerResource.class); + private static final int NUM_PROFILE_STAFFS = 13; + /* Graphic target */ private IGraphicsTarget target = null; @@ -137,7 +142,7 @@ public class ProfilerResource extends protected void initInternal(IGraphicsTarget target) throws VizException { this.target = target; dataTimes = new ArrayList(); - incX = (ProfilerUtils.profilerRectangle.width / 12); + incX = (ProfilerUtils.profilerRectangle.width / NUM_PROFILE_STAFFS); incYheight = ProfilerUtils.profilerRectangle.height / maxY; @@ -222,7 +227,7 @@ public class ProfilerResource extends earliestTime = Math.min(earliestTime, validTime); latestTime = Math.max(latestTime, validTime); } - long earliestRequestTime = earliestTime - 12 * 3600000; + long earliestRequestTime = earliestTime - NUM_PROFILE_STAFFS * 3600000; List requestTimes = new ArrayList(); for (DataTime time : resourceData.getAvailableTimes()) { long validTime = time.getValidTime().getTimeInMillis(); @@ -343,7 +348,7 @@ public class ProfilerResource extends if (x < 0) { continue; } - if (x >= 12) { + if (x >= NUM_PROFILE_STAFFS) { continue; } ArrayList plots = entry.getValue(); @@ -463,9 +468,10 @@ public class ProfilerResource extends } Calendar c = paintProps.getDataTime().getValidTime(); - for (int i = 0; i < 12; i++) { + for (int i = 0; i < NUM_PROFILE_STAFFS; i++) { - String d = String.format("%1$tH:%1$tM", c); +// String d = String.format("%1$tH:%1$tM", c); + String d = String.format("%1$tH", c); parameters.setText(d, ProfilerUtils.GRAPH_COLOR); parameters.basics.x = ProfilerUtils.profilerRectangle.x + (i * incX) + (incX / 2); diff --git a/cave/com.raytheon.uf.viz.radarapps.core/src/com/raytheon/uf/viz/radarapps/client/RcmClient.java b/cave/com.raytheon.uf.viz.radarapps.core/src/com/raytheon/uf/viz/radarapps/client/RcmClient.java index 0a8a95501d..3887a91ecc 100644 --- a/cave/com.raytheon.uf.viz.radarapps.core/src/com/raytheon/uf/viz/radarapps/client/RcmClient.java +++ b/cave/com.raytheon.uf.viz.radarapps.core/src/com/raytheon/uf/viz/radarapps/client/RcmClient.java @@ -61,7 +61,6 @@ import com.raytheon.rcm.mqsrvr.ReqObj; import com.raytheon.rcm.rmr.RmrEvent; import com.raytheon.uf.common.dataplugin.radar.request.RadarServerConnectionRequest; import com.raytheon.uf.viz.core.exception.VizException; -import com.raytheon.uf.viz.core.preferences.JMSPreferences; import com.raytheon.uf.viz.core.requests.ThriftClient; // TODO: use of queueSession outside synchronized(stateLock) could cause @@ -69,6 +68,23 @@ import com.raytheon.uf.viz.core.requests.ThriftClient; // TODO: conflicts over setting fatalMsg +/** + * Manages client connection to RadarServer + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer     Description
+ * ------------ ---------- ------------ --------------------------
+ * ????                    D. Friedman  Initial version
+ * 2012-07-27   DR 14896   D. Friedman  Fix even topic name
+ * 
+ * 
+ * + * @author dfriedma + * @version 1.0 + */ public class RcmClient implements MessageListener, ExceptionListener { private String connectionURL; @@ -211,6 +227,11 @@ public class RcmClient implements MessageListener, ExceptionListener { return; } + /* + * TODO: ActiveMQ is hard-coded. If switching to Qpid or another + * service, it may be necessary to use JMSPreferences.getPolicyString on + * the topic name below. + */ ActiveMQConnectionFactory connFac = new ActiveMQConnectionFactory(uri); // This stuff can block... try { @@ -238,8 +259,7 @@ public class RcmClient implements MessageListener, ExceptionListener { topicConn.setExceptionListener(this); topicSession = topicConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); - topic = topicSession.createTopic(JMSPreferences - .getPolicyString("RadarEvents")); + topic = topicSession.createTopic("RadarEvents"); queueConn.start(); topicConn.start(); diff --git a/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/AbstractCrossSectionResource.java b/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/AbstractCrossSectionResource.java index 00e4e60017..1f22a67fc5 100644 --- a/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/AbstractCrossSectionResource.java +++ b/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/AbstractCrossSectionResource.java @@ -231,11 +231,13 @@ public abstract class AbstractCrossSectionResource extends time = time.clone(); time.setLevelValue((double) i); times.add(time); + sliceMap.put(time, null); + dataRetrievalJob.times.add(time); } } dataTimes = new ArrayList(times); Collections.sort(dataTimes); - sliceMap.clear(); + dataRetrievalJob.schedule(); } protected void loadSlice(DataTime time) throws VizException { diff --git a/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionImageResource.java b/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionImageResource.java index 148e5e9228..9957941d55 100644 --- a/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionImageResource.java +++ b/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionImageResource.java @@ -138,10 +138,12 @@ public class CrossSectionImageResource extends AbstractCrossSectionResource super.initInternal(target); // defaults - ImagingCapability imageCap = getCapability(ImagingCapability.class); - imageCap.setInterpolationState(true); - imageCap.setBrightness(1.0f); - imageCap.setContrast(1.0f); + if (!hasCapability(ImagingCapability.class)) { + ImagingCapability imageCap = getCapability(ImagingCapability.class); + imageCap.setInterpolationState(true); + imageCap.setBrightness(1.0f); + imageCap.setContrast(1.0f); + } } private IImage constructImage(float[] floatData, IGraphicsTarget target) diff --git a/cave/com.raytheon.uf.viz.xy.timeheight/src/com/raytheon/uf/viz/xy/timeheight/rsc/AbstractTimeHeightResource.java b/cave/com.raytheon.uf.viz.xy.timeheight/src/com/raytheon/uf/viz/xy/timeheight/rsc/AbstractTimeHeightResource.java index b35100d512..b8cb40b58f 100644 --- a/cave/com.raytheon.uf.viz.xy.timeheight/src/com/raytheon/uf/viz/xy/timeheight/rsc/AbstractTimeHeightResource.java +++ b/cave/com.raytheon.uf.viz.xy.timeheight/src/com/raytheon/uf/viz/xy/timeheight/rsc/AbstractTimeHeightResource.java @@ -450,6 +450,7 @@ public abstract class AbstractTimeHeightResource extends secondaryResource.setDescriptor(descriptor); } super.setDescriptor(descriptor); + interpolatedData = null; loadDataJob.schedule(); } diff --git a/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/rsc/TimeSeriesResource.java b/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/rsc/TimeSeriesResource.java index 6be8e20194..9e8e7b17d0 100644 --- a/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/rsc/TimeSeriesResource.java +++ b/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/rsc/TimeSeriesResource.java @@ -26,6 +26,7 @@ import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.ListIterator; import java.util.Set; import java.util.TimeZone; import java.util.TreeSet; @@ -76,6 +77,7 @@ import com.raytheon.viz.core.graphing.util.GraphPrefsFactory; import com.raytheon.viz.core.graphing.xy.XYData; import com.raytheon.viz.core.graphing.xy.XYDataList; import com.raytheon.viz.core.graphing.xy.XYImageData; +import com.raytheon.viz.core.graphing.xy.XYWindImageData; import com.raytheon.viz.core.rsc.ICombinedResourceData; import com.raytheon.viz.core.rsc.ICombinedResourceData.CombineOperation; import com.raytheon.viz.core.style.graph.GraphPreferences; @@ -157,10 +159,22 @@ public class TimeSeriesResource extends if (currentUnit.isCompatible(prefs.getDisplayUnits())) { UnitConverter conv = currentUnit.getConverterTo(prefs .getDisplayUnits()); - for (XYData d : data.getData()) { - double converted = conv.convert(((Number) d.getY()) - .doubleValue()); - d.setY(converted); + ListIterator it = data.getData().listIterator(); + while(it.hasNext()) { + XYData d = it.next(); + if(d instanceof XYWindImageData){ + XYWindImageData wind = (XYWindImageData) d; + double converted = conv.convert(wind.getWindSpd()); + it.remove(); + if(wind.getImage() != null){ + wind.getImage().dispose(); + } + it.add(new XYWindImageData(wind.getX(), wind.getY(), converted, wind.getWindDir())); + }else{ + double converted = conv.convert(((Number) d.getY()) + .doubleValue()); + d.setY(converted); + } } units = prefs.getDisplayUnitLabel(); } else { @@ -457,13 +471,6 @@ public class TimeSeriesResource extends String lat = nf.format(Math.abs(y)); String stnID = ""; String source = resourceData.getSource(); - String unit = ""; - - if (prefs != null && prefs.getDisplayUnits() != null) { - unit = prefs.getDisplayUnitLabel(); - } else { - unit = adapter.getDataUnit().toString(); - } if (resourceData.getMetadataMap().get("location.stationId") != null) { stnID = resourceData.getMetadataMap().get("location.stationId") @@ -488,7 +495,7 @@ public class TimeSeriesResource extends sb.append(" ").append(resourceData.getLevelKey()); } sb.append(String.format(" %s %s %s", adapter.getParameterName(), - "TSer", unit != null && unit.equals("") == false ? "(" + unit + "TSer", units != null && units.equals("") == false ? "(" + units + ")" : "")); if (secondaryResource != null) { diff --git a/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/util/ScaleHandler.java b/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/util/ScaleHandler.java index d1e49fe28c..a669e8f8fb 100644 --- a/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/util/ScaleHandler.java +++ b/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/util/ScaleHandler.java @@ -26,6 +26,7 @@ import org.eclipse.core.commands.ExecutionException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandService; +import com.raytheon.uf.viz.core.IDisplayPane; import com.raytheon.uf.viz.core.IDisplayPaneContainer; import com.raytheon.uf.viz.core.globals.VizGlobalsManager; import com.raytheon.uf.viz.d2d.core.ID2DRenderableDisplay; @@ -75,30 +76,29 @@ public class ScaleHandler extends AbstractHandler { * @param scale */ static void setScale(IDisplayPaneContainer editor, String scale) { - if (editor.getActiveDisplayPane().getRenderableDisplay() instanceof ID2DRenderableDisplay) { - ID2DRenderableDisplay disp = (ID2DRenderableDisplay) editor - .getActiveDisplayPane().getRenderableDisplay(); + for (IDisplayPane pane : editor.getDisplayPanes()) { + if (pane.getRenderableDisplay() instanceof ID2DRenderableDisplay) { + ID2DRenderableDisplay disp = (ID2DRenderableDisplay) pane + .getRenderableDisplay(); + if (scale.equals(disp.getScale())) { + // don't set the scale if it is the same as the display's + // current scale + return; + } - if (scale.equals(disp.getScale())) { - // don't set the scale if it is the same as the display's - // current - // scale - return; + disp.setScale(scale); + if (pane == editor.getActiveDisplayPane()) { + VizGlobalsManager.getCurrentInstance().updateChanges( + editor.getActiveDisplayPane() + .getRenderableDisplay().getGlobalsMap()); + } } - - disp.setScale(scale); - - // update the scale button - final ICommandService service = (ICommandService) PlatformUI - .getWorkbench().getService(ICommandService.class); - - VizGlobalsManager.getCurrentInstance().updateChanges( - editor.getActiveDisplayPane().getRenderableDisplay() - .getGlobalsMap()); - - service.refreshElements( - "com.raytheon.uf.viz.xy.height.scalebutton", null); } + + ICommandService service = (ICommandService) PlatformUI.getWorkbench() + .getService(ICommandService.class); + service.refreshElements("com.raytheon.uf.viz.xy.height.scalebutton", + null); } } diff --git a/cave/com.raytheon.viz.aviation/plugin.xml b/cave/com.raytheon.viz.aviation/plugin.xml index 8d2737e59a..2a6e132304 100644 --- a/cave/com.raytheon.viz.aviation/plugin.xml +++ b/cave/com.raytheon.viz.aviation/plugin.xml @@ -87,5 +87,12 @@ value="aviation/config" recursive="true"> + + diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/climatology/WindRosePlotDlg.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/climatology/WindRosePlotDlg.java index bffc923418..db908b75f9 100755 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/climatology/WindRosePlotDlg.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/climatology/WindRosePlotDlg.java @@ -55,7 +55,6 @@ import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Spinner; - import com.raytheon.viz.avncommon.AvnMessageMgr.StatusMessageType; import com.raytheon.viz.avnconfig.HelpUsageDlg; import com.raytheon.viz.avnconfig.ITafSiteConfig; @@ -80,6 +79,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * 9/12/2008 1444 grichard Accommodate separate message logs. * 3/31/2011 8774 rferrel killProcess when doing a disposed * 4/14/2011 8861 rferrel Use SaveImageDlg class + * 23JUL2012 15169 zhao Use Combo for 'Month' and 'Number of Months' + * & disabled site controls while drawing * * * @@ -101,14 +102,14 @@ public class WindRosePlotDlg extends CaveSWTDialog { private List siteList; /** - * Month spinner. + * Month */ - private Spinner monthSpnr; + private Combo monthCbo; /** * Number of months. */ - private Spinner numMonthsSpnr; + private Combo numMonthsCbo; /** * Hours spinner. @@ -427,20 +428,19 @@ public class WindRosePlotDlg extends CaveSWTDialog { Label monthLbl = new Label(monthHourComp, SWT.NONE); monthLbl.setText("Month:"); - gd = new GridData(40, SWT.DEFAULT); - monthSpnr = new Spinner(monthHourComp, SWT.BORDER); - monthSpnr.setDigits(0); - monthSpnr.setIncrement(1); - monthSpnr.setPageIncrement(3); - monthSpnr.setMinimum(1); - monthSpnr.setMaximum(12); - monthSpnr.setSelection(cal.get(Calendar.MONTH) + 1); - monthSpnr.setLayoutData(gd); - monthSpnr.addSelectionListener(new SelectionAdapter() { + gd = new GridData(66, SWT.DEFAULT); + monthCbo = new Combo(monthHourComp, SWT.DROP_DOWN | SWT.READ_ONLY); + monthCbo.setLayoutData(gd); + for ( int i = 1; i <= 12; i++ ) { + monthCbo.add(""+i, i-1); + } + monthCbo.select(cal.get(Calendar.MONTH)); + monthCbo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { + //System.out.println(" *************** monthsCbo.getText() = " + monthCbo.getText() ); if (autoRedrawChk.getSelection()) { - redrawWindRose(); + redrawWindRose(); } } }); @@ -448,20 +448,19 @@ public class WindRosePlotDlg extends CaveSWTDialog { Label numMonthLbl = new Label(monthHourComp, SWT.NONE); numMonthLbl.setText("Num Months:"); - gd = new GridData(40, SWT.DEFAULT); - numMonthsSpnr = new Spinner(monthHourComp, SWT.BORDER); - numMonthsSpnr.setDigits(0); - numMonthsSpnr.setIncrement(1); - numMonthsSpnr.setPageIncrement(3); - numMonthsSpnr.setMinimum(1); - numMonthsSpnr.setMaximum(12); - numMonthsSpnr.setSelection(1); - numMonthsSpnr.setLayoutData(gd); - numMonthsSpnr.addSelectionListener(new SelectionAdapter() { + gd = new GridData(66, SWT.DEFAULT); + numMonthsCbo = new Combo(monthHourComp, SWT.DROP_DOWN | SWT.READ_ONLY); + numMonthsCbo.setLayoutData(gd); + for ( int i = 1; i <= 12; i++ ) { + numMonthsCbo.add(""+i, i-1); + } + numMonthsCbo.select(0); + numMonthsCbo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { + //System.out.println(" *************** numMonthsCbo.getText() = " + numMonthsCbo.getText() ); if (autoRedrawChk.getSelection()) { - redrawWindRose(); + redrawWindRose(); } } }); @@ -586,8 +585,10 @@ public class WindRosePlotDlg extends CaveSWTDialog { generateWindRoseHeader(); windRoseCanvasComp.updateAndRedraw(windRoseConfigData.cloneData(), - windRoseHeader, monthSpnr.getText(), - numMonthsSpnr.getText(), hourSpnr.getText(), + windRoseHeader, + monthCbo.getText(), + numMonthsCbo.getText(), + hourSpnr.getText(), numHoursSpnr.getText(), flightCatCbo.getSelectionIndex(), siteList.getItem(siteList.getSelectionIndex()), this); } @@ -599,11 +600,21 @@ public class WindRosePlotDlg extends CaveSWTDialog { if (state == true) { ++busyCount; shell.setCursor(waitCursor); + monthCbo.setEnabled(false); + numMonthsCbo.setEnabled(false); + hourSpnr.setEnabled(false); + numHoursSpnr.setEnabled(false); + flightCatCbo.setEnabled(false); drawBtn.setEnabled(false); } else { --busyCount; if (busyCount == 0) { shell.setCursor(defaultCursor); + monthCbo.setEnabled(true); + numMonthsCbo.setEnabled(true); + hourSpnr.setEnabled(true); + numHoursSpnr.setEnabled(true); + flightCatCbo.setEnabled(true); drawBtn.setEnabled(true); } } @@ -634,23 +645,21 @@ public class WindRosePlotDlg extends CaveSWTDialog { header.append(siteList.getItem(siteList.getSelectionIndex())); header.append(" "); - header.append(MONTHS[monthSpnr.getSelection() - 1]); + header.append(MONTHS[monthCbo.getSelectionIndex()]); - if (numMonthsSpnr.getSelection() == 1) { + if ( numMonthsCbo.getSelectionIndex() == 0 ) { header.append(" "); } else { header.append("-"); int endMonth = 0; - if (((numMonthsSpnr.getSelection() - 1) + monthSpnr.getSelection()) > 12) { - endMonth = (numMonthsSpnr.getSelection() - 1) - + monthSpnr.getSelection() - 12; - header.append(MONTHS[endMonth - 1]); + if ( ( numMonthsCbo.getSelectionIndex() + monthCbo.getSelectionIndex() ) > 11 ) { + endMonth = numMonthsCbo.getSelectionIndex() + monthCbo.getSelectionIndex() - 12; + header.append(MONTHS[endMonth]); } else { - endMonth = (numMonthsSpnr.getSelection() - 1) - + monthSpnr.getSelection(); - header.append(MONTHS[endMonth - 1]); + endMonth = numMonthsCbo.getSelectionIndex() + monthCbo.getSelectionIndex(); + header.append(MONTHS[endMonth]); } header.append(" "); } 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 247f812f67..527abe027c 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 @@ -213,6 +213,7 @@ import com.raytheon.viz.texteditor.msgs.IAviationObserver; * 08/12/2011 10612 rferrel saveFile will now always push file back to the server. * 11/29/2011 11612 rferrel Added getViewerTabList. * 20JUL2012 14570 gzhang/zhao Highlight correct time groups in TAF Viewer + * 08AGU2012 15613 zhao Modified highlightTAF() * * * @@ -3674,8 +3675,11 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, } ResourceConfigMgr configMgr = ResourceConfigMgr.getInstance(); - String taf = tafViewerStTxt.getText(); + String taf = tafViewerStTxt.getText(); int offset = taf.indexOf("TAF"); + if ( showHeadersChk.getSelection() ) { + offset = taf.indexOf("TAF", offset + 3); + } try { int end = taf.indexOf("TAF", offset + 3); if (end > 0) { @@ -3705,7 +3709,7 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, for (String alertKey : tempoMap.keySet()) { //System.out.println("2___alertKey: "+ alertKey); for (String value : tempoMap.get(alertKey)) { - System.out.println("3___value: "+ value); + //System.out.println("3___value: "+ value); str.setLength(1); str.append(value); int len = str.length(); @@ -3745,6 +3749,11 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, str.setLength(len); str.append("\n"); startIndex = taf.indexOf(str.toString()); + if (startIndex < 0) { + str.setLength(len); + str.append("="); + startIndex = taf.indexOf(str.toString()); + } } if (startIndex >= 0 /*within the same line*/&& startIndex < endIndex) { @@ -3983,11 +3992,11 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, // Only load the latest TAF, and assume it is the first one in // the Viewer. sb.append(TafUtil.safeFormatTaf(tafsInViewer[0], false)); - String bbb = ""; + String originalBbb = ""; String[] header = tafsInViewer[0].getWmoHeader().split(" "); if (header.length > 3) { - bbb = header[3]; + originalBbb = header[3]; } ITafSiteConfig config = TafSiteConfigFactory.getInstance(); @@ -3997,6 +4006,7 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, String stationId = siteData.wmo.split(" ")[1]; String issueTime = header[2]; + String bbb = ""; if (type == null) { // Do nothing } else if (type == TafSettings.OPEN_AMD) { diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java index ab01929c16..bbd0b85599 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java @@ -63,7 +63,7 @@ import com.raytheon.viz.aviation.resource.ResourceConfigMgr.ResourceTag; * and set default value for check hours. * 04/28/2011 8065 rferrel Add flag to indicate display is current * and implement data caching - * 20JUL2012 14570 gzhang/zhao Added "tempo" to alertMap + * 31JUL2012 14570 zhao Highlight Metar alert for case of 'cat' * * * @@ -127,6 +127,7 @@ public class MetarViewer extends ViewerTab implements */ private static final HashMap alertMap = new HashMap(); static { + //alertMap.put("cat", new String[] { "", "", "", "" }); // 14570 alertMap.put("tempo", new String[] { "", "", "", "", "", "", "", "" }); // 14570 alertMap.put("vsby", new String[] { "", "" }); alertMap.put("wind", new String[] { "", "" }); @@ -410,7 +411,12 @@ public class MetarViewer extends ViewerTab implements if (alertMap != null && alertMap.size() > 0) { for (String key : alertMap.keySet()) { - colorViewerAlert(key, configMgr); + if ( key.equals("cat") ) { // "cat" involves "visibility" and "sky condition" + colorViewerAlert("vsby", configMgr); + colorViewerAlert("sky", configMgr); + } else { + colorViewerAlert(key, configMgr); + } } } } diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java index ad6f475855..aefc1f5df2 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java @@ -63,7 +63,7 @@ import com.raytheon.viz.aviation.xml.MonitorCfg; * May 13, 2011 8611 rferrel Added type to help determine blink state. * Apr 30, 2012 14717 zhao Indicators turn gray when Metar is outdated * 20JUL2012 14570 gzhang/zhao Modified for highlighting correct time groups in TAF Viewer - * + * 11AUG2012 14570 zhao Added 'cat' to alert_key_map * * * @author lvenable @@ -126,7 +126,8 @@ public class SiteMonitor implements IRequestCompleteListener> { */ private static final Map ALERT_KEY_MAP = new HashMap(); { - ALERT_KEY_MAP.put("tempo", new String[] { "wind", "vsby", "pcp", "obv", "vcnty", "sky" } ); // 14570 + ALERT_KEY_MAP.put("cat", new String[] { "vsby", "sky" }); // 14570 + //ALERT_KEY_MAP.put("tempo", new String[] { "wind", "vsby", "pcp", "obv", "vcnty", "sky" } ); // 14570 ALERT_KEY_MAP.put("vsby", new String[] { "vsby" }); ALERT_KEY_MAP.put("wind", new String[] { "wind" }); ALERT_KEY_MAP.put("wx", new String[] { "pcp", "obv", "vcnty" }); diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafUtil.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafUtil.java index b17b58b198..556459afad 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafUtil.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafUtil.java @@ -49,6 +49,7 @@ import com.raytheon.uf.viz.core.exception.VizException; * Jul 6, 2010 5792 rferrel getLatestTafs now returns tafs * sorted by issue date newest at * the start of the array. + * 08AUG2012 15613 zhao Modified safeFormatTaf() * * * @@ -161,12 +162,13 @@ public class TafUtil { */ public static String safeFormatTaf(TafRecord t, boolean includeHeader) { StringBuilder sb = new StringBuilder(); - if (includeHeader) { - sb.append(t.getWmoHeader()); - sb.append(LINE_BREAK); - } if (t != null) { String[] text = t.getTafText().split("[\r\n]"); + if (includeHeader) { + sb.append(t.getWmoHeader()); + sb.append(LINE_BREAK); + sb.append("TAF").append(t.getStationId().substring(1,4)).append(LINE_BREAK); + } String firstLine = text[0]; if (firstLine.startsWith("TAF AMD") || firstLine.startsWith("TAF COR")) { @@ -191,6 +193,7 @@ public class TafUtil { sb.append(LINE_BREAK); } } + sb.append(LINE_BREAK); } return sb.toString(); } diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/SendDialog.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/SendDialog.java index 1f643714eb..4866319bec 100755 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/SendDialog.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/SendDialog.java @@ -68,6 +68,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * 28 FEB 2008 938 lvenable Initial creation. * 4/15/2009 1982 grichard Provide feedback when saving a working TAF. * 12/08/2011 11745 rferrel Updated header time to transmission time. + * 08AUG2012 15613 zhao Determine proper BBB for transmission * * * @@ -364,7 +365,7 @@ public class SendDialog extends CaveSWTDialog { String siteWmoId = tabComp.getWmoId(); // WMO Site String siteNode = null; - java.util.List stationIds = new ArrayList(); + //java.util.List stationIds = new ArrayList(); ArrayList tafs = new ArrayList(); ArrayList updatedTafs = new ArrayList(); @@ -402,6 +403,16 @@ public class SendDialog extends CaveSWTDialog { // Site ID String siteId = fourLetterId.substring(1); + /* + * If "AAX" or "CCX" or "RRX", determine BBB for transmission + */ + String xmitBbb = bbb; + if ( bbb.equals("AAX") || bbb.equals("CCX") || bbb.equals("RRX") ) { + String type = bbb.substring(0, 2); + xmitBbb = getXmitBbb( type, siteId); + } + + // Update Header Time to transmission time. tafText = TIMESTAMP_PATTERN.matcher(tafText).replaceFirst( xmitTimestamp); @@ -418,7 +429,7 @@ public class SendDialog extends CaveSWTDialog { } TafQueueRecord record = new TafQueueRecord(forecasterId, - xmitTime.getTime(), tafText, bbb, siteId, siteWmoId, + xmitTime.getTime(), tafText, xmitBbb, siteId, siteWmoId, siteNode, xmitTime.getTime()); records.add(record); } @@ -455,4 +466,41 @@ public class SendDialog extends CaveSWTDialog { tabComp.setTafSent(tafsQeueued); shell.dispose(); } + + @SuppressWarnings("unchecked") + private String getXmitBbb(String type, String siteId) { + + try { + TafQueueRequest request = new TafQueueRequest(); + request.setType(Type.GET_LIST); + request.setState(TafQueueRecord.TafQueueState.SENT); + ServerResponse> response = (ServerResponse>) ThriftClient.sendRequest(request); + java.util.List payload = response.getPayload(); + String [] records = (String []) payload.toArray(new String[0]); + int numRecords = records.length; + for ( int i = numRecords-1; i >=0; i-- ) { + if ( records[i].contains(siteId) ) { + String [] texts = records[i].split("-"); + String bbb = texts[texts.length-2]; + if ( bbb.equals(" ") ) { + return type+"A"; + } + if ( bbb.subSequence(0, 2).equals(type) ) { + char[] newX = new char[] { bbb.charAt(2) }; + if ( newX[0] == 'X' ) { + newX[0] = 'A'; + } else { + newX[0]++; + } + return type + new String( newX ); + } + } + } + } catch (VizException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return type + "A"; + } } diff --git a/cave/com.raytheon.viz.bcd/src/com/raytheon/viz/bcd/BCDResource.java b/cave/com.raytheon.viz.bcd/src/com/raytheon/viz/bcd/BCDResource.java index 063bebf687..ee088160f1 100644 --- a/cave/com.raytheon.viz.bcd/src/com/raytheon/viz/bcd/BCDResource.java +++ b/cave/com.raytheon.viz.bcd/src/com/raytheon/viz/bcd/BCDResource.java @@ -26,6 +26,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.util.ArrayList; @@ -69,6 +70,7 @@ import com.vividsolutions.jts.geom.Coordinate; * 7/1/06 chammack Initial Creation. * 1/10/08 562 bphillip Modified to handle .bcx files * 02/11/09 njensen Refactored to new rsc architecture + * 07/31/12 DR 14935 D. Friedman Handle little-endian files * * * @@ -190,6 +192,14 @@ public class BCDResource extends ByteBuffer buffer = fc.map(MapMode.READ_ONLY, 0, file.length()); + // Determine byte order of data + if (buffer.remaining() >= 4) { + // Whether BCX or not, first value is an int. + // Note: Different from A1 which tests >31 or >500 + if (buffer.getInt(0) > Short.MAX_VALUE) + buffer.order(ByteOrder.LITTLE_ENDIAN); + } + int i = 0; double minLat = Double.MAX_VALUE; diff --git a/cave/com.raytheon.viz.feature.awips.developer/feature.xml b/cave/com.raytheon.viz.feature.awips.developer/feature.xml index f892126f88..ff7e3c0570 100644 --- a/cave/com.raytheon.viz.feature.awips.developer/feature.xml +++ b/cave/com.raytheon.viz.feature.awips.developer/feature.xml @@ -50,10 +50,6 @@ id="com.raytheon.uf.viz.d2d.core.feature" version="0.0.0"/> - - diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/PythonPreferenceStore.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/PythonPreferenceStore.java index bd2a643dc7..5015cb67da 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/PythonPreferenceStore.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/PythonPreferenceStore.java @@ -34,6 +34,7 @@ import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.SafeRunnable; +import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil; import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; @@ -76,7 +77,6 @@ public class PythonPreferenceStore implements IPreferenceStore, private String configName; - @SuppressWarnings("unchecked") public PythonPreferenceStore(String configName) { this.propertyChangeListeners = new ArrayList(); this.configurationChangeListeners = new ArrayList(); @@ -84,7 +84,8 @@ public class PythonPreferenceStore implements IPreferenceStore, this.loadConfiguration(configName); } - public void loadConfiguration(String configName) { + @SuppressWarnings("unchecked") + public void loadConfiguration(String configName) { IPathManager pathMgr = PathManagerFactory.getPathManager(); String utilityDir = pathMgr.getFile( pathMgr.getContext(LocalizationType.CAVE_STATIC, @@ -92,23 +93,14 @@ public class PythonPreferenceStore implements IPreferenceStore, com.raytheon.uf.common.util.FileUtil.join("gfe", "utility")) .getPath(); - String configDir = com.raytheon.uf.common.util.FileUtil.join("gfe", - "userPython", "gfeConfig"); - String baseDir = pathMgr.getFile( - pathMgr.getContext(LocalizationType.CAVE_STATIC, - LocalizationLevel.BASE), configDir).getPath(); - String siteDir = pathMgr.getFile( - pathMgr.getContext(LocalizationType.CAVE_STATIC, - LocalizationLevel.SITE), configDir).getPath(); - String userDir = pathMgr.getFile( - pathMgr.getContext(LocalizationType.CAVE_STATIC, - LocalizationLevel.USER), configDir).getPath(); + String configPath = GfePyIncludeUtil.getConfigIncludePath(); + String vtecPath = GfePyIncludeUtil.getVtecIncludePath(); PythonScript py = null; try { py = new PythonScript( utilityDir + File.separator + "loadConfig.py", - PyUtil.buildJepIncludePath(userDir, siteDir, baseDir)); + PyUtil.buildJepIncludePath(configPath, vtecPath)); } catch (JepException e) { statusHandler.handle(Priority.CRITICAL, "Unable to load GFE config", e); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/config/ConfigCatalog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/config/ConfigCatalog.java index 83a05ff985..fb440bd456 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/config/ConfigCatalog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/config/ConfigCatalog.java @@ -121,10 +121,11 @@ public class ConfigCatalog extends AbstractScriptCatalog { // Look for HideConfigFile = True in the file PythonScript pscript = null; try { - String includePath = PyUtil - .buildJepIncludePath(GfePyIncludeUtil - .getConfigIncludePath()); - pscript = new PythonScript(file.getAbsolutePath(), includePath, + String configPath = GfePyIncludeUtil.getConfigIncludePath(); + String vtecPath = GfePyIncludeUtil.getVtecIncludePath(); + + pscript = new PythonScript(file.getAbsolutePath(), + PyUtil.buildJepIncludePath(configPath, vtecPath), getClass().getClassLoader(), preEvals); Boolean scriptValue = (Boolean) pscript.execute( "checkHideConfigFile", null); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISelectTimeRangeManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISelectTimeRangeManager.java index 173551c912..9beaf6d463 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISelectTimeRangeManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISelectTimeRangeManager.java @@ -19,8 +19,8 @@ **/ package com.raytheon.viz.gfe.core; -import com.raytheon.viz.gfe.core.time.SelectTimeRange; -import com.raytheon.viz.gfe.core.time.SelectTimeRange.Mode; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange.Mode; /** * TODO Add Description @@ -31,6 +31,7 @@ import com.raytheon.viz.gfe.core.time.SelectTimeRange.Mode; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Dec 3, 2009 randerso Initial creation + * Aug 1, 2012 #965 dgilling Change location of SelectTimeRange. * * * diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/AbstractGridData.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/AbstractGridData.java index 50df7c16a5..c9650039c1 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/AbstractGridData.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/AbstractGridData.java @@ -79,12 +79,12 @@ public abstract class AbstractGridData implements IGridData { protected boolean iscCapable = true; - protected Date lastAccessTime; + protected long lastAccessTime; protected Grid2DBit changedPoints; protected AbstractGridData(Parm aParm, IGridSlice aSlice) { - this.lastAccessTime = SimulatedTime.getSystemTime().getTime(); + this.lastAccessTime = System.currentTimeMillis(); this.parm = aParm; this.gridSlice = aSlice; // this.gridSlice.setUseCache(true); @@ -135,7 +135,7 @@ public abstract class AbstractGridData implements IGridData { } @Override - public Date getLastAccessTime() { + public long getLastAccessTime() { return this.lastAccessTime; } @@ -184,7 +184,7 @@ public abstract class AbstractGridData implements IGridData { } } - this.lastAccessTime = SimulatedTime.getSystemTime().getTime(); + this.lastAccessTime = System.currentTimeMillis(); } @Override @@ -458,7 +458,7 @@ public abstract class AbstractGridData implements IGridData { public boolean applyDelta(Date time, float delta, boolean taper, Grid2DBit pointsToChange) { if (delta == 0.0) { - return false; // nothing to change + return true; // nothing to change } populate(); checkOkayForEdit(); @@ -863,12 +863,12 @@ public abstract class AbstractGridData implements IGridData { if (!this.isPopulated()) { return; } - String msg = "Depopulating " + getParm().getParmID() + " tr=" - + getGridTime(); - statusHandler.handle(Priority.DEBUG, msg, new Exception("Debug: " - + msg)); + // String msg = "Depopulating " + getParm().getParmID() + " tr=" + // + getGridTime(); + // statusHandler.handle(Priority.DEBUG, msg, new Exception("Debug: " + // + msg)); - this.lastAccessTime = SimulatedTime.getSystemTime().getTime(); + this.lastAccessTime = 0; setGridSliceDataToNull(); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/IGridData.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/IGridData.java index bbc4e48220..ffb59f56c4 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/IGridData.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/IGridData.java @@ -158,7 +158,7 @@ public interface IGridData extends Comparable { * * @return time the grid was last accessed */ - public Date getLastAccessTime(); + public long getLastAccessTime(); /** * Returns the time range associated with this grid. diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java index d55affa041..2b2f10887d 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java @@ -32,6 +32,8 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange.Mode; import com.raytheon.uf.common.localization.FileUpdatedMessage; import com.raytheon.uf.common.localization.ILocalizationFileObserver; import com.raytheon.uf.common.localization.IPathManager; @@ -47,8 +49,6 @@ import com.raytheon.viz.gfe.GFEServerException; import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.ISelectTimeRangeManager; import com.raytheon.viz.gfe.core.msgs.SelectTimeRangesChangedMsg; -import com.raytheon.viz.gfe.core.time.SelectTimeRange; -import com.raytheon.viz.gfe.core.time.SelectTimeRange.Mode; /** * Class which manages the selection time range definitions that are stored on @@ -60,6 +60,7 @@ import com.raytheon.viz.gfe.core.time.SelectTimeRange.Mode; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Dec 3, 2009 #3135 randerso Initial creation + * Aug 1, 2012 #965 dgilling Change location of SelectTimeRange. * * * diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/DbParm.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/DbParm.java index 5722909063..1e92636a5f 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/DbParm.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/DbParm.java @@ -718,10 +718,7 @@ public class DbParm extends Parm { continue; // grid overlaps spatial editor time -- skip it } - long lastAccess = 0; - if (grid.getLastAccessTime() != null) { - lastAccess = grid.getLastAccessTime().getTime(); - } + long lastAccess = grid.getLastAccessTime(); long delta = now - lastAccess; if (delta < milliseconds) { @@ -735,9 +732,10 @@ public class DbParm extends Parm { // only deallocate unlocked grids if (!locked) { - String msg = "Deallocating " + getParmID() + " tr=" + gTime; - statusHandler.handle(Priority.DEBUG, msg, new Exception( - "Debug: " + msg)); + // String msg = "Deallocating " + getParmID() + " tr=" + + // gTime; + // statusHandler.handle(Priority.DEBUG, msg, new Exception( + // "Debug: " + msg)); grid.depopulate(); } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java index 71cf6c9270..d9f70456a5 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java @@ -304,10 +304,7 @@ public class VCParm extends VParm implements IParmListChangedListener, continue; } // grid overlaps spatial editor time -- skip it - long lastAccess = 0; - if (grid.getLastAccessTime() != null) { - lastAccess = grid.getLastAccessTime().getTime(); - } + long lastAccess = grid.getLastAccessTime(); long delta = now - lastAccess; if (delta < milliseconds) { diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AbstractSaveParameterDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AbstractSaveParameterDialog.java index a11e9be7e0..857d4da0af 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AbstractSaveParameterDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AbstractSaveParameterDialog.java @@ -158,77 +158,84 @@ public abstract class AbstractSaveParameterDialog extends CaveJFACEDialog @Override protected IStatus run(IProgressMonitor monitor) { long t0 = System.currentTimeMillis(); - final CountDownLatch latch = new CountDownLatch( - MAX_CONCURRENT_SAVES); final AtomicBoolean allSuccessful = new AtomicBoolean(true); - - // spawn separate jobs top save parms - for (int i = 0; i < MAX_CONCURRENT_SAVES; i++) { - new Job("Saving Parms") { - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - Parm parm = null; - while ((parm = parms.poll()) != null) { - String parmString = parm.getParmID() - .toString(); - try { - // save data - if (statusHandler - .isPriorityEnabled(Priority.DEBUG)) { - statusHandler.handle( - Priority.DEBUG, "Save: " - + parmString); - } - if (!parm.saveParameter(true)) { - allSuccessful.set(false); - } - } catch (Exception e) { - allSuccessful.set(false); - statusHandler.handle(Priority.ERROR, - "Error occurred saving parm " - + parmString, e); - } - } - } finally { - latch.countDown(); - } - - return Status.OK_STATUS; - } - }.schedule(); - } - try { - latch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + final CountDownLatch latch = new CountDownLatch( + MAX_CONCURRENT_SAVES); - if (!allSuccessful.get()) { - statusHandler.handle(Priority.PROBLEM, - "Some grids were not saved. See log for details."); - } else { - statusHandler.handle(Priority.DEBUG, "Save Complete"); - } + // spawn separate jobs top save parms + for (int i = 0; i < MAX_CONCURRENT_SAVES; i++) { + new Job("Saving Parms") { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + Parm parm = null; + while ((parm = parms.poll()) != null) { + String parmString = parm.getParmID() + .toString(); + try { + // save data + if (statusHandler + .isPriorityEnabled(Priority.DEBUG)) { + statusHandler.handle( + Priority.DEBUG, + "Save: " + parmString); + } + if (!parm.saveParameter(true)) { + allSuccessful.set(false); + } + } catch (Throwable e) { + allSuccessful.set(false); + statusHandler.handle( + Priority.ERROR, + "Error occurred saving parm " + + parmString, e); + } + } + } catch (Throwable e) { + allSuccessful.set(false); + statusHandler.handle(Priority.ERROR, + e.getLocalizedMessage(), e); + } finally { + latch.countDown(); + } - VizApp.runAsync(new Runnable() { - - @Override - public void run() { - AbstractSaveParameterDialog.this.getShell().setCursor( - origCursor); - AbstractSaveParameterDialog.this - .saveFinished(allSuccessful.get()); + return Status.OK_STATUS; + } + }.schedule(); } - }); - long t1 = System.currentTimeMillis(); - System.out.println("GFE Save Forecast took: " + (t1 - t0) - + " ms"); + latch.await(); + } catch (Throwable e) { + allSuccessful.set(false); + statusHandler.handle(Priority.PROBLEM, + e.getLocalizedMessage(), e); + } finally { + if (!allSuccessful.get()) { + statusHandler + .handle(Priority.PROBLEM, + "Some grids were not saved. See log for details."); + } else { + statusHandler.handle(Priority.DEBUG, "Save Complete"); + } + + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + AbstractSaveParameterDialog.this.getShell() + .setCursor(origCursor); + AbstractSaveParameterDialog.this + .saveFinished(allSuccessful.get()); + } + }); + + long t1 = System.currentTimeMillis(); + System.out.println("GFE Save Forecast took: " + (t1 - t0) + + " ms"); + } return Status.OK_STATUS; } - }; saveJob.setSystem(true); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/DefineRefSetDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/DefineRefSetDialog.java index 7e19625468..4324498a8d 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/DefineRefSetDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/DefineRefSetDialog.java @@ -811,7 +811,13 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements @Override public void referenceSetChanged(ReferenceData refSet, ArrayList domains) { - activeChanged(); + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + activeChanged(); + } + }); } /* @@ -822,7 +828,13 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements */ @Override public void referenceSetIDChanged(ReferenceID refID) { - activeChanged(); + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + activeChanged(); + } + }); } /* @@ -838,7 +850,13 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements java.util.List deletions, java.util.List changes) { - this.refreshRefsets(); + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + refreshRefsets(); + } + }); } /* @@ -849,7 +867,13 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements */ @Override public void editAreaGroupInvChanged() { - this.refreshRefsets(); + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + refreshRefsets(); + } + }); } /* @@ -863,36 +887,35 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements @Override public void displayedParmListChanged(Parm[] parms, Parm[] deletions, Parm[] additions) { - refreshParms(); - } - - private void activeChanged() { VizApp.runAsync(new Runnable() { @Override public void run() { - // Update display when active refset changes - ReferenceData refData = refSetMgr.getActiveRefSet(); - - // Fix active refset display - if (!activeDisplay.isDisposed()) { - activeDisplay.setText(getActiveRefDesc(refData)); - } - - // Enable/Disable Undo button - if (!undoButton.isDisposed()) { - undoButton.setEnabled(!refData.refType().equals( - RefType.NONE)); - } - - // Enable/Disable Convert to Location button - if (!convertButton.isDisposed()) { - convertButton.setEnabled(refData.isQuery()); - } + refreshParms(); } }); } + private void activeChanged() { + // Update display when active refset changes + ReferenceData refData = refSetMgr.getActiveRefSet(); + + // Fix active refset display + if (!activeDisplay.isDisposed()) { + activeDisplay.setText(getActiveRefDesc(refData)); + } + + // Enable/Disable Undo button + if (!undoButton.isDisposed()) { + undoButton.setEnabled(!refData.refType().equals(RefType.NONE)); + } + + // Enable/Disable Convert to Location button + if (!convertButton.isDisposed()) { + convertButton.setEnabled(refData.isQuery()); + } + } + private String getActiveRefDesc(ReferenceData refData) { String s = ""; @@ -947,37 +970,29 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements } private void refreshRefsets() { - VizApp.runAsync(new Runnable() { + if (groupList.isDisposed() || editAreasList.isDisposed()) { + return; + } - @Override - public void run() { - if (groupList.isDisposed() || editAreasList.isDisposed()) { - return; - } + String[] groups = groupList.getSelection(); - String[] groups = groupList.getSelection(); + // Refresh the Group and Areas lists + java.util.List availGroups = refSetMgr.getGroupInventory(); + availGroups.add("Misc"); + groupList.setItems(availGroups.toArray(new String[availGroups.size()])); - // Refresh the Group and Areas lists - java.util.List availGroups = refSetMgr - .getGroupInventory(); - availGroups.add("Misc"); - groupList.setItems(availGroups.toArray(new String[availGroups - .size()])); - - // update selection - groupList.deselectAll(); - for (String group : groups) { - int index = groupList.indexOf(group); - if (index >= 0) { - groupList.select(index); - } - } - - groups = groupList.getSelection(); - String[] areaNames = getAreaNames(groups); - editAreasList.setItems(areaNames); + // update selection + groupList.deselectAll(); + for (String group : groups) { + int index = groupList.indexOf(group); + if (index >= 0) { + groupList.select(index); } - }); + } + + groups = groupList.getSelection(); + String[] areaNames = getAreaNames(groups); + editAreasList.setItems(areaNames); } private void refreshParms() { diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/FormatterLauncherDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/FormatterLauncherDialog.java index e1d95dadb0..9f123d61a4 100755 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/FormatterLauncherDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/FormatterLauncherDialog.java @@ -88,6 +88,7 @@ import com.raytheon.viz.ui.dialogs.CaveJFACEDialog; * practice and test modes * Sep 16, 2010 6831 ryu Show same product for different areas on a sub-menu * Nov 22, 2011 8781 mli remove Processor menu + * Jul 26, 2012 15165 ryu Set default db source when formatter has no db defined. * * * @@ -776,6 +777,8 @@ public class FormatterLauncherDialog extends CaveJFACEDialog implements ProductDefinition prodDef = textProductMgr .getProductDefinition(productName); String dataSource = (String) prodDef.get("database"); + if (dataSource == null) + dataSource = "Official"; if (dataSource.equals("ISC")) { selectedDataSource = getIscDataSource(); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/SaveDeleteSelectTRDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/SaveDeleteSelectTRDialog.java index a36f733657..72a83422b2 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/SaveDeleteSelectTRDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/SaveDeleteSelectTRDialog.java @@ -41,17 +41,15 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange.Mode; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; 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.viz.gfe.Activator; import com.raytheon.viz.gfe.GFEServerException; -import com.raytheon.viz.gfe.constants.StatusConstants; import com.raytheon.viz.gfe.core.DataManager; -import com.raytheon.viz.gfe.core.time.SelectTimeRange; -import com.raytheon.viz.gfe.core.time.SelectTimeRange.Mode; import com.raytheon.viz.ui.dialogs.CaveJFACEDialog; import com.raytheon.viz.ui.widgets.SpinScale; @@ -64,6 +62,7 @@ import com.raytheon.viz.ui.widgets.SpinScale; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Dec 7, 2009 randerso Initial creation + * Aug 1, 2012 #965 dgilling Change location of SelectTimeRange. * * * @@ -72,7 +71,8 @@ import com.raytheon.viz.ui.widgets.SpinScale; */ public class SaveDeleteSelectTRDialog extends CaveJFACEDialog { - private static final transient IUFStatusHandler statusHandler = UFStatus.getHandler(SaveDeleteSelectTRDialog.class); + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(SaveDeleteSelectTRDialog.class); private DataManager dataManager; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java index b8f43e364d..aa25309507 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java @@ -115,6 +115,8 @@ import com.vividsolutions.jts.geom.LineString; * Jul 29, 2009 randerso Initial creation * Jul 02, 2010 6285 mpduff Fixed contours to update after * drawing and calculating new grid. + * Aug 08, 2012 #621 dgilling Fix ConcurrentModificationException + * in handling of renderables field. * * * @@ -323,6 +325,9 @@ public class ContourTool extends AbstractFreeformTool implements */ private void replaceCLines(List contours) { clearRenderables(); + + List renderables = new ArrayList( + this.renderables); renderables.add(freeformRenderable); if (currentGrid != null) { @@ -353,26 +358,34 @@ public class ContourTool extends AbstractFreeformTool implements } } renderables.add(renderable); - refresh(); } + + this.renderables = renderables; + refresh(); } private void disposeRenderables() { + List renderables = new ArrayList( + this.renderables); for (IRenderable renderable : renderables) { if (renderable instanceof JTSRenderable) { ((JTSRenderable) renderable).dispose(); } } renderables.clear(); + this.renderables = renderables; } private void clearRenderables() { + List renderables = new ArrayList( + this.renderables); for (IRenderable renderable : renderables) { if (renderable instanceof JTSRenderable) { ((JTSRenderable) renderable).clear(); } } renderables.clear(); + this.renderables = renderables; } private void initializeContourData(IGridData grid) { diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/sample/SamplePainter.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/sample/SamplePainter.java index bae55eb71d..03d528d974 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/sample/SamplePainter.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/sample/SamplePainter.java @@ -66,6 +66,8 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 04/08/2008 chammack Initial Port from AWIPS I (minus ISC support) + * 07/23/2012 #936 dgilling Reinstate config-handling code to + * calcGridLabels(). * * * @@ -253,7 +255,7 @@ public class SamplePainter { private void calcGridLabels(Coordinate worldLoc, final List grids, final GridID imageGrid, List sampleLabels, List colors) { - if (grids.size() == 0) { + if (grids.isEmpty()) { return; } @@ -261,9 +263,9 @@ public class SamplePainter { // all parms List limitSamples = Arrays.asList(Activator.getDefault() .getPreferenceStore().getStringArray("SampleParms")); + // assumes all grids shared same grid location. boolean inGrid = false; - Coordinate gridCoordinate = MapUtil.latLonToGridCoordinate(worldLoc, PixelOrientation.UPPER_LEFT, grids.get(0).getParm() .getGridInfo().getGridLoc()); @@ -280,27 +282,41 @@ public class SamplePainter { inGrid = true; } - // sample label color - RGB labelColor = new RGB(255, 255, 255); - // get the list of samples that should be painted and in the // order for (GridID grid : grids) { String pName = grid.getParm().getParmID().compositeNameUI(); // do we plot this weather element? - if ((limitSamples.size() != 0) && !limitSamples.contains(pName)) { + if ((!limitSamples.isEmpty()) && !limitSamples.contains(pName)) { continue; // skip } + // calculate color + RGB labelColor = grid.getParm().getDisplayAttributes() + .getBaseColor(); + + if (grid.equals(imageGrid)) { + RGB color = new RGB(255, 255, 255); + String colorName = Activator.getDefault().getPreferenceStore() + .getString("ImageLegend_color"); + if (!colorName.isEmpty()) { + color = RGBColors.getRGBColor(colorName); + } + labelColor = color; + } + String parmColorName = Activator.getDefault().getPreferenceStore() + .getString(pName + "_Sample_color"); + if (!parmColorName.isEmpty()) { + labelColor = RGBColors.getRGBColor(parmColorName); + } + // get the data value String label = NO_DATA_LABEL; if (inGrid) { - // isc mode or grid from isc database if (showISC || grid.getParm().getParmState().isIscParm()) { label = iscSampleLabel(grid, gridCoordinate); - } else if (showDataValues) { final IGridData gridData = grid.grid(); if (gridData != null) { diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/sample/SampleRenderable.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/sample/SampleRenderable.java index 4a9f2b70e0..675a712363 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/sample/SampleRenderable.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/sample/SampleRenderable.java @@ -38,6 +38,7 @@ import com.raytheon.viz.gfe.core.msgs.Message; import com.raytheon.viz.gfe.core.msgs.Message.IMessageClient; import com.raytheon.viz.gfe.core.msgs.ShowQuickViewDataMsg; import com.raytheon.viz.gfe.core.parm.Parm; +import com.raytheon.viz.gfe.core.parm.ParmDisplayAttributes.VisMode; import com.raytheon.viz.gfe.edittool.EditToolPaintProperties; import com.raytheon.viz.gfe.edittool.GridID; import com.raytheon.viz.gfe.rsc.GFEFonts; @@ -45,16 +46,18 @@ import com.vividsolutions.jts.geom.Coordinate; /** * Handles the display for on-demand sampling capability. - * - * Roughly based on AWIPS I class of the same name. + *

+ * Roughly based on AWIPS I class SampleVisual. * *

  * SOFTWARE HISTORY
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * 04/08/2008              chammack    Initial Creation.
- * 11Jun2008    #1193       ebabin      Updates for toggling lat/lon for sample set.
+ * 06/11/2008   #1193      ebabin      Updates for toggling lat/lon for sample set.
  * 07/21/2009              bphillip    Removed the points field
+ * 07/23/2012   #936       dgilling    Properly retrieve imageGrid for paintMarkers()
+ *                                     and paintSamples().
  * 
  * 
* @@ -148,13 +151,17 @@ public class SampleRenderable implements IRenderable, IMessageClient { imageGrid = qvGrid; } else { Parm[] parms = sdm.getCurrentlyEnabledParms(); - Parm imageParm = sdm.getActivatedParm(); + Parm imageParm = null; Arrays.sort(parms); gids = new ArrayList(parms.length); - Date date = sdm.getSpatialEditorTime(); - for (int i = 0; i < parms.length; i++) { - gids.add(new GridID(parms[i], date)); + + for (Parm p : parms) { + gids.add(new GridID(p, date)); + + if (p.getDisplayAttributes().getVisMode() == VisMode.IMAGE) { + imageParm = p; + } } imageGrid = new GridID(imageParm, date); @@ -184,12 +191,16 @@ public class SampleRenderable implements IRenderable, IMessageClient { Date date = sdm.getSpatialEditorTime(); Parm[] parms = sdm.getCurrentlyEnabledParms(); - Parm imageParm = sdm.getActivatedParm(); + Parm imageParm = null; Arrays.sort(parms); GridID[] grids = new GridID[parms.length]; for (int i = 0; i < parms.length; i++) { grids[i] = new GridID(parms[i], date); + + if (parms[i].getDisplayAttributes().getVisMode() == VisMode.IMAGE) { + imageParm = parms[i]; + } } GridID imageGrid = new GridID(imageParm, date); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java index 4151787349..558e5f1cbb 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java @@ -647,13 +647,14 @@ public class GridBar implements IMessageClient, IParmInventoryChangedListener, Rectangle rect = computeRect(dataTR); gc.setFont(timeBlockSourceFont); + gc.setTextAntialias(SWT.OFF); String s = truncateLabelToFit(gc, text, rect.width); Point textSize = gc.stringExtent(s); if (textSize.x < rect.width + DATA_BLOCK_HORIZONTAL_MARGIN) { int xOffset = (rect.width - textSize.x) / 2; int yOffset = (rect.height - textSize.y) / 2; - gc.drawString(s, rect.x + xOffset, rect.y + yOffset, false); + gc.drawString(s, rect.x + xOffset, rect.y + yOffset, true); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/Tool.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/Tool.java index 70ed2e10ef..f5f1fbd529 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/Tool.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/Tool.java @@ -603,7 +603,9 @@ public class Tool { parmToEdit.startParmEdit(new Date[] { timeInfluence }); } catch (GFEOperationFailedException e) { statusHandler.handle(Priority.PROBLEM, - "Error during start parm edit", e); + "Error during start parm edit for " + toolName + " - already running." + + " Please wait for the operation to complete and try again.", + e); return; } startedParmEdit = true; diff --git a/cave/com.raytheon.viz.grid/localization/styleRules/gridImageryStyleRules.xml b/cave/com.raytheon.viz.grid/localization/styleRules/gridImageryStyleRules.xml index 3a65243be8..da570400d3 100644 --- a/cave/com.raytheon.viz.grid/localization/styleRules/gridImageryStyleRules.xml +++ b/cave/com.raytheon.viz.grid/localization/styleRules/gridImageryStyleRules.xml @@ -2422,12 +2422,12 @@ % - 5 + -1 105 Grid/warm to cold - 20 + 20 40 60 80 100 diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridResourceData.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridResourceData.java index 875a7612a2..474a6b69aa 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridResourceData.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridResourceData.java @@ -162,6 +162,7 @@ public class GridResourceData extends AbstractRequestableResourceData implements sampling = sampling == null ? false : sampling; return new GridIconResource(this, loadProperties); case BARB: + sampling = sampling == null ? false : sampling; case ARROW: case DUALARROW: case STREAMLINE: @@ -170,7 +171,7 @@ public class GridResourceData extends AbstractRequestableResourceData implements // grib data in D2D is in one location. There are only a few // products that do not work correctly, contours of vector // direction, and data mapped images. - sampling = sampling == null ? false : sampling; + sampling = sampling == null ? true : sampling; return new D2DGribGridResource(this, loadProperties); case CONTOUR: default: diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridVectorResource.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridVectorResource.java index 662e9a92ec..41783bd7c4 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridVectorResource.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GridVectorResource.java @@ -109,6 +109,7 @@ import com.vividsolutions.jts.geom.Coordinate; * 05/16/2012 14993 D. Friedman Fix "blocky" contours * 06/19/2012 14988 D. Friedman Reproject based on conformality * 07/09/2012 14940 M. Porricelli Apply reprojection to streamlines + * 07/23/2012 14968 M. Porricelli Changed wording of streamline legend * * * @@ -491,7 +492,7 @@ public class GridVectorResource extends AbstractMapVectorResource implements legendParams.dataTime = getDisplayedDataTime(); if (displayType == DisplayType.STREAMLINE) { - legendParams.type = " Streamlines"; + legendParams.type = " Strmlns"; } else if (displayType == DisplayType.BARB) { legendParams.type = "Wind Barbs"; } else if (displayType == DisplayType.ARROW) { @@ -526,7 +527,7 @@ public class GridVectorResource extends AbstractMapVectorResource implements legendParams.dataTime = getDisplayedDataTime(); if (displayType == DisplayType.STREAMLINE) { - legendParams.type = " Streamlines"; + legendParams.type = " Strmlns"; } else if (displayType == DisplayType.BARB) { legendParams.type = "Wind Barbs"; } else if (displayType == DisplayType.ARROW) { diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/D2DGribGridResource.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/D2DGribGridResource.java index 28888ed1a6..99df74b47f 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/D2DGribGridResource.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/D2DGribGridResource.java @@ -74,6 +74,8 @@ import com.vividsolutions.jts.geom.Coordinate; * ------------ ---------- ----------- -------------------------- * Mar 9, 2011 bsteffen Initial creation * 06/19/2012 14988 D. Friedman Reproject based on conformality + * 07/23/2012 14968 M. Porricelli Changed wording of streamline + * legend * * * @@ -258,7 +260,7 @@ public class D2DGribGridResource extends GribGridResource // The default type does not display in the legend legendParams.type = ""; } else if (displayType == DisplayType.STREAMLINE) { - legendParams.type = "Streamlines"; + legendParams.type = "Strmlns"; } else if (displayType == DisplayType.BARB) { legendParams.type = "Wind Barbs"; } else if (displayType == DisplayType.ARROW) { diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/flashfloodguidance/FlashFloodGuidanceDlg.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/flashfloodguidance/FlashFloodGuidanceDlg.java index 953d9b0b1b..b91ddd7bbb 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/flashfloodguidance/FlashFloodGuidanceDlg.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/flashfloodguidance/FlashFloodGuidanceDlg.java @@ -237,7 +237,7 @@ public class FlashFloodGuidanceDlg extends CaveSWTDialog { /** * The duration in millis being displayed. */ - private int duration; + private int duration = 3600; /** * Holds the display string and insert time for later use. @@ -1126,7 +1126,7 @@ public class FlashFloodGuidanceDlg extends CaveSWTDialog { String day = parts[2]; String date = parts[3]; String hour = parts[4]; - duration = Integer.parseInt(durationStr) * FFGConstants.MILLIS_PER_HOUR; + duration = Integer.parseInt(durationStr) * FFGConstants.SECONDS_PER_HOUR; String paramAbr = "FFG" + durationStr + "24hr"; diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/resource/MultiPointResource.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/resource/MultiPointResource.java index 3e95444f0f..bb592a4dca 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/resource/MultiPointResource.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/resource/MultiPointResource.java @@ -343,24 +343,21 @@ public class MultiPointResource extends Coordinate xy = new Coordinate(gage.getLon(), gage.getLat()); gage.setCoordinate(xy); - double latInc = .05; - double lonInc = .03; + /* Create a small envelope around the point */ + double shiftHeightValue = getShiftHeight(gage); + double shiftWidthValue = getShiftWidth(gage); if (existing != null) { - Coordinate p1 = new Coordinate(existing.getLon() + lonInc, - existing.getLat() + latInc); - Coordinate p2 = new Coordinate(existing.getLon() - lonInc, - existing.getLat() - latInc); - Envelope oldEnv = new Envelope(p1, p2); + PixelExtent pe = getPixelExtent(existing, getShiftWidth(existing), + getShiftHeight(existing)); + Envelope oldEnv = descriptor.pixelToWorld(pe); strTree.remove(oldEnv, existing); } /* Create a small envelope around the point */ - Coordinate p1 = new Coordinate(gage.getLon() + lonInc, - gage.getLat() + latInc); - Coordinate p2 = new Coordinate(gage.getLon() - lonInc, - gage.getLat() - latInc); - Envelope newEnv = new Envelope(p1, p2); + PixelExtent pe = getPixelExtent(gage, getShiftWidth(gage), + getShiftHeight(gage)); + Envelope newEnv = descriptor.pixelToWorld(pe); strTree.insert(newEnv, gage); dataMap.put(lid, gage); @@ -871,12 +868,19 @@ public class MultiPointResource extends Envelope env = new Envelope(coord.asLatLon()); List elements = strTree.query(env); if (elements.size() > 0) { + StringBuffer sb = new StringBuffer(); + boolean first = true; Iterator iter = elements.iterator(); while (iter.hasNext()) { GageData gage = (GageData) iter.next(); - return "GAGE: " + gage.getName() + " VALUE: " - + gage.getGageValue(); + if (!first) { + sb.append("\n"); + } + sb.append("GAGE: " + gage.getName() + " VALUE: " + + gage.getGageValue()); + first = false; } + return sb.toString(); } } catch (Exception e) { throw new VizException(e); diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayDlg.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayDlg.java index cdb7102a22..d034dafafe 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayDlg.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayDlg.java @@ -87,8 +87,9 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * so that it would place the * entire time series within the * printable area of the page. - * 04 Mar 2011 7644 lbousaid fixed Zoom in feature - * 30 May 2012 14967 wkwock fix insert deleted data to rejecteddata table + * 04 Mar 2011 7644 lbousaid fixed Zoom in feature + * 30 May 2012 14967 wkwock fix insert deleted data to rejecteddata table + * 23 Jul 2012 15195 mpduff Fix dates for displaying groups * * * @@ -1360,22 +1361,9 @@ public class TimeSeriesDisplayDlg extends CaveSWTDialog { linesMI.setSelection(true); } - /* Get time data from group info */ - int pastHours = groupInfo.getPastHours(); - int futureHours = groupInfo.getFutureHours(); - - Calendar futureCal = Calendar.getInstance(TimeZone - .getTimeZone("GMT")); - Date d = SimulatedTime.getSystemTime().getTime(); - futureCal.setTime(d); - futureCal.add(Calendar.HOUR_OF_DAY, futureHours); - Calendar pastCal = Calendar.getInstance(TimeZone - .getTimeZone("GMT")); - pastCal.setTime(d); - pastCal.add(Calendar.HOUR_OF_DAY, pastHours * -1); displayCanvas = new TimeSeriesDisplayCanvas(this, - canvasComp, gd, pastCal.getTime(), - futureCal.getTime(), groupInfo.isGroupSelected()); + canvasComp, gd, beginDate, + endDate, groupInfo.isGroupSelected()); displayCanvas.setHorizontalSpan(gd.getXsize()); displayCanvas.setVerticalSpan(gd.getYsize()); displayCanvas.showGridLines(groupInfo.isGridLines()); diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDlg.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDlg.java index c473e39c1c..9500bea336 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDlg.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDlg.java @@ -111,6 +111,11 @@ import com.raytheon.viz.hydrocommon.util.StnClassSyncUtil; * be ran as a standalone application * without starting CAVE. * 01 June 2011 9499 djingtao update openGraph() + * 23 Jul 2012 15180 mpduff Auto select the first group in the predefined group list + * 23 Jul 2012 15195 mpduff Fix Group graphing to use the date widgets. + * 08 Aug 2012 570 mpduff Fix a Ctrl-F in Station list causing IndexOutOfBounds error. + * 08 Aug 2012 657 mpduff Fix error when selecting a TS while no selection has been made + * in the Station List. * * * @author lvenable @@ -437,6 +442,9 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog { /** Holds the Group Information */ private GroupInfo groupInfo; + + /** Holds the last graphed GroupInfo object */ + private GroupInfo prevGroupInfo; /** Holds the page information */ private PageInfo pageInfo = null; @@ -1156,10 +1164,12 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog { tsOrderCbo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - String line = topDataList.getItem(topDataList - .getSelectionIndex()); - String selectedLid = line.substring(0, line.indexOf(" ")); - populateBottomList(selectedLid, tsOrderCbo.getSelectionIndex()); + if (topDataList.getSelectionIndex() != -1) { + String line = topDataList.getItem(topDataList + .getSelectionIndex()); + String selectedLid = line.substring(0, line.indexOf(" ")); + populateBottomList(selectedLid, tsOrderCbo.getSelectionIndex()); + } } }); tsOrderCbo.select(1); @@ -1202,9 +1212,11 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog { topDataList.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - populateBottomList( - lidList.get(topDataList.getSelectionIndex()), - tsOrderCbo.getSelectionIndex()); + if (topDataList.getSelectionIndex() != -1) { + populateBottomList( + lidList.get(topDataList.getSelectionIndex()), + tsOrderCbo.getSelectionIndex()); + } } }); } @@ -1365,6 +1377,20 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog { endDayBtn.setText(String.valueOf(endCal.get(Calendar.DAY_OF_MONTH))); endHourBtn.setText(String.valueOf(endCal.get(Calendar.HOUR_OF_DAY))); } + + private void updateTimeButtons() { + beginYearBtn.setText(String.valueOf(beginCal.get(Calendar.YEAR))); + beginMonthBtn.setText(String.valueOf(beginCal.get(Calendar.MONTH) + 1)); + beginDayBtn + .setText(String.valueOf(beginCal.get(Calendar.DAY_OF_MONTH))); + beginHourBtn + .setText(String.valueOf(beginCal.get(Calendar.HOUR_OF_DAY))); + + endYearBtn.setText(String.valueOf(endCal.get(Calendar.YEAR))); + endMonthBtn.setText(String.valueOf(endCal.get(Calendar.MONTH) + 1)); + endDayBtn.setText(String.valueOf(endCal.get(Calendar.DAY_OF_MONTH))); + endHourBtn.setText(String.valueOf(endCal.get(Calendar.HOUR_OF_DAY))); + } /** * Populates the station list box. @@ -1962,7 +1988,12 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog { } else { // TODO log error here, invalid value System.err.println("Error in Group Definition Config file: " + line); - } + } + + // select the first item in the list + if (groupDataList.getItemCount() > 0) { + groupDataList.select(0); + } } /** @@ -2225,32 +2256,26 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog { GroupInfo groupInfo = groupList.get(groupDataList .getSelectionIndex()); - int pastHours = groupInfo.getPastHours(); - int futureHours = groupInfo.getFutureHours(); - -// long beginMillis = beginDate.getTime(); -// long endMillis = endDate.getTime(); -// long currentMillis = SimulatedTime.getSystemTime().getTime().getTime(); -// -// long hoursBack = (currentMillis - beginMillis) / (1000*60*60); -// long hoursAhead = (endMillis - currentMillis) / (1000*60*60); -// groupInfo.setPastHours((int) hoursBack); -// groupInfo.setFutureHours((int) hoursAhead); - groupInfo.setPastHours(pastHours); - groupInfo.setFutureHours(futureHours); - -// Calendar futureCal = Calendar.getInstance(TimeZone -// .getTimeZone("GMT")); -// Date d = SimulatedTime.getSystemTime().getTime(); -// futureCal.setTime(d); -// futureCal.add(Calendar.HOUR_OF_DAY, futureHours); -// Calendar pastCal = Calendar.getInstance(TimeZone -// .getTimeZone("GMT")); -// pastCal.setTime(d); -// pastCal.add(Calendar.HOUR_OF_DAY, pastHours * -1); - - + if (prevGroupInfo == null || !prevGroupInfo.equals(groupInfo)) { + int pastHours = groupInfo.getPastHours(); + int futureHours = groupInfo.getFutureHours(); + beginCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + beginCal.add(Calendar.HOUR_OF_DAY, pastHours * -1); + + endCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + endCal.add(Calendar.HOUR_OF_DAY, futureHours); + + beginDate = beginCal.getTime(); + endDate = endCal.getTime(); + + updateTimeButtons(); + + groupInfo.setPastHours(pastHours); + groupInfo.setFutureHours(futureHours); + } timeSeriesDisplayDlg.setGroupInfo(groupInfo); + + prevGroupInfo = groupInfo; } timeSeriesDisplayDlg.setBeginDate(beginDate); timeSeriesDisplayDlg.setEndDate(endDate); diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/graph/TimeSeriesGraphCanvas.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/graph/TimeSeriesGraphCanvas.java index 7461fd3279..d2bc279daf 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/graph/TimeSeriesGraphCanvas.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/graph/TimeSeriesGraphCanvas.java @@ -62,7 +62,8 @@ import com.raytheon.viz.hydrocommon.HydroConstants; * Apr 18, 2011 8963 jpiatt Removed Left Scale call to scale manager. * July 12 2011 9709 djingtao draw right Y axis for showPP is true. add new * function adjust_pcymax() - * Aug. 10, 2011 10457 djingtao allow the red rubberband box to be drawn for setMissing in Edit + * Aug. 10, 2011 10457 djingtao allow the red rubberband box to be drawn for setMissing in Edit + * Jul. 24, 2012 15195 mpduff Fix x axis scales. * * * @@ -492,7 +493,7 @@ public class TimeSeriesGraphCanvas extends Canvas { } // Check canvas width. if small then need to skip extra days - if (this.canvasWidth < 600) { + if (this.canvasWidth < 500) { daysSkip++; } @@ -537,8 +538,8 @@ public class TimeSeriesGraphCanvas extends Canvas { /* ******************** */ /* Hour annotation */ /* ******************** */ - dy = 10; - if (ndays < 4) { + dy = 10; + if (ndays < 8 && this.canvasWidth > 450) { if (hour < 10) { gc.drawText("0" + hour, x + leftBorder - dx, bottomBorder + 22); } else { diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/cresthistory/CrestHistoryCanvas.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/cresthistory/CrestHistoryCanvas.java index 5179e342d3..c7bf0af623 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/cresthistory/CrestHistoryCanvas.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/cresthistory/CrestHistoryCanvas.java @@ -63,684 +63,732 @@ import com.raytheon.viz.hydrocommon.HydroConstants; * @version 1.0 */ public class CrestHistoryCanvas extends Canvas { - /** - * Parent component. - */ - private Composite parentComp; - - /** - * Text font on the canvas. - */ - private Font canvasFont; - - /** - * Canvas width. - */ - private final int CANVAS_WIDTH = 700; - - /** - * Canvas height. - */ - private final int CANVAS_HEIGHT = 520; - - /** - * Y coordinate of the horizontal axis line. - */ - private final int HLINE_YCOORD = CANVAS_HEIGHT - 40; - - /** - * X coordinate of the vertical axis line. - */ - private final int VLINE_XCOORD = 80; - - private final int HLINE_LEFT_OFFSET = 20; - - /** - * Length of the horizontal axis line. - */ - private final int HLINE_LENGTH = CANVAS_WIDTH - VLINE_XCOORD - - HLINE_LEFT_OFFSET; - - /** - * Length of the vertical axis line. - */ - private final int VLINE_LENGTH = 450; - - /** - * The number of pixels the vertical lines is from the top of the canvas. - */ - private final int VLINE_PIXELS_FROM_TOP = CANVAS_HEIGHT - 40 - VLINE_LENGTH; - - /** - * "STAGE IN FEET" text. - */ - private final String STAGE_IN_FEET = "STAGE IN FEET"; - - /** - * Hash mark length. - */ - private final int HASH_MARK = 10; - - /** - * Small hash mark length. - */ - private final int SMALL_HASH_MARK = 5; - - /** - * Label Y coordinate offset. - */ - private final int LABEL_Y_OFFSET = 15; - - /** - * Label X coordinate offset. - */ - private final int LABEL_X_OFFSET = 5; - - /** - * Starting X coordinate for the year hash mark. - */ - private final int YEAR_HASH_X_COORD_START = VLINE_XCOORD + 15; - - /** - * Maximum stage value. - */ - private double stageMaxVal = 0.0; - - /** - * Minimum stage value. - */ - private double stageMinVal = 0.0; - - /** - * Number of MAJOR data items. - */ - private int majorCount = 0; - - /** - * Number of MODERATE data items. - */ - private int modCount = 0; - - /** - * Number of ACTION data items. - */ - private int actionCount = 0; - - /** - * Number of MINOR data items. - */ - private int minorCount = 0; - - /** - * Crest history data. - */ - private CrestHistoryData crestHistoryData; - - /** - * Map of the crest data (value) and the rectangle area on the canvas the - * data occupies (key). - */ - private HashMap crestDataMap; - - /** - * Callback for selecting crest data. - */ - private ISelectedCrestData selectCrestDataCB; - - /** - * Constructor. - * - * @param parent - * Parent composite. - * @param crestHistoryData - * Crest history data. - * @param callback - * Crest data selection callback. - */ - public CrestHistoryCanvas(Composite parent, - CrestHistoryData crestHistoryData, ISelectedCrestData callback) { - super(parent, SWT.DOUBLE_BUFFERED); - - parentComp = parent; - this.crestHistoryData = crestHistoryData; - // work around for missing data - if (crestHistoryData != null) { - selectCrestDataCB = callback; - stageMaxVal = crestHistoryData.getMaxStageLevel(); - stageMinVal = 0.0; - } else { - stageMaxVal = 0.0; - stageMinVal = 0.0; - } - // another work around - if ((crestHistoryData.getEndingYear() == 0) - || (crestHistoryData.getStartingYear() == 0)) { - Calendar cal = new GregorianCalendar(); - cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - Date date = SimulatedTime.getSystemTime().getTime(); - cal.setTime(date); - crestHistoryData.setStartingYear(1900); - crestHistoryData.setEndingYear(cal.get(Calendar.YEAR)); - } - - init(); - } - - /** - * Initialize method. - */ - private void init() { - if (crestHistoryData != null) { - generateCrestDataMap(); - } - - canvasFont = new Font(parentComp.getDisplay(), "Monospace", 9, - SWT.NORMAL); - - setupCanvas(); - - addMouseListener(new MouseAdapter() { - @Override - public void mouseDown(MouseEvent e) { - processMouseEvent(e); - } - }); - } - - /** - * Regenerate the Crest history canvas - * - * @param crestHistoryData - */ - public void updateCrestHistotryData(CrestHistoryData crestHistoryData) { - this.crestHistoryData = crestHistoryData; - - if (crestHistoryData != null) { - stageMaxVal = crestHistoryData.getMaxStageLevel(); - stageMinVal = 0.0; - } else { - stageMaxVal = 0.0; - stageMinVal = 0.0; - } - - generateCrestDataMap(); - redraw(); - } - - /** - * Setup the drawing canvas. - */ - private void setupCanvas() { - GridData gd = new GridData(SWT.DEFAULT, SWT.TOP, false, true); - gd.heightHint = CANVAS_HEIGHT; - gd.widthHint = CANVAS_WIDTH; - - this.setSize(CANVAS_WIDTH, CANVAS_HEIGHT); - - setLayoutData(gd); - addPaintListener(new PaintListener() { - public void paintControl(PaintEvent e) { - drawCrestHistory(e); - } - }); - - addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - canvasFont.dispose(); - } - }); - } - - /** - * Draw the crest history data and the graph lines & labels on the canvas. - * - * @param e - * Paint event. - */ - private void drawCrestHistory(PaintEvent e) { - e.gc.setFont(canvasFont); - int fontHeightMid = (e.gc.getFontMetrics().getHeight() / 2); - int fontHeight = (e.gc.getFontMetrics().getHeight()); - - e.gc.setBackground(parentComp.getDisplay().getSystemColor( - SWT.COLOR_BLACK)); - - e.gc.fillRectangle(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); - - e.gc.setForeground(parentComp.getDisplay().getSystemColor( - SWT.COLOR_WHITE)); - - // ---------------------------------------- - // Draw horizontal and vertical axis lines - // ---------------------------------------- - - e.gc.drawLine(VLINE_XCOORD, HLINE_YCOORD, VLINE_XCOORD, HLINE_YCOORD - - VLINE_LENGTH); - - e.gc.drawLine(VLINE_XCOORD, HLINE_YCOORD, VLINE_XCOORD + HLINE_LENGTH, - HLINE_YCOORD); - - // ------------------------------------------------ - // Draw STAGE IN FEET vertical label - // ------------------------------------------------ - char[] charArray = STAGE_IN_FEET.toCharArray(); - - int tmpY = 120; - for (int i = 0; i < charArray.length; i++) { - e.gc.drawString(String.valueOf(charArray[i]), 5, tmpY, true); - tmpY += fontHeight; - } - - if (crestHistoryData != null) { - // ------------------------------------------------ - // Draw the years and the hash marks - // ------------------------------------------------ - int startyear = crestHistoryData.getStartingYear(); - int endyear = crestHistoryData.getEndingYear(); - int years = (endyear - startyear); - double pixelsPerIncX; - if (years == 0) { - pixelsPerIncX = 0; - } else { - pixelsPerIncX = HLINE_LENGTH / years; - } - - int yearXcoord = VLINE_XCOORD; - int yearHashXcoord = YEAR_HASH_X_COORD_START; - DecimalFormat df = new DecimalFormat(); - df.setMinimumIntegerDigits(1); - df.setMaximumFractionDigits(0); - df.setGroupingUsed(false); - - for (int i = 0; i <= years; i++) { - int inc = new Double(Math.rint(pixelsPerIncX * i)).intValue(); - yearXcoord = YEAR_HASH_X_COORD_START + inc - 15; - yearHashXcoord = YEAR_HASH_X_COORD_START + inc; - if (years < 75) { - if (i % 5 == 0) { - e.gc.drawString(df.format(startyear + i), yearXcoord, - CANVAS_HEIGHT - fontHeight - 3, true); - e.gc.drawLine(yearHashXcoord, HLINE_YCOORD, yearHashXcoord, - HLINE_YCOORD + HASH_MARK); - } - } else { - if (i % 10 == 0) { - e.gc.drawString(df.format(startyear + i), yearXcoord, - CANVAS_HEIGHT - fontHeight - 3, true); - e.gc.drawLine(yearHashXcoord, HLINE_YCOORD, yearHashXcoord, - HLINE_YCOORD + HASH_MARK); - } - } - } - - // ----------------------------------------- - // Draw stage hash marks - // ----------------------------------------- - - double maxPixValue = VLINE_LENGTH + VLINE_PIXELS_FROM_TOP; - double numHashsY = stageMaxVal; - double pixelsPerIncY = VLINE_LENGTH / numHashsY; - - for (int x = 0; x <= stageMaxVal; ++x) { - int yCoord = HLINE_YCOORD - - new Double(Math.round(x * pixelsPerIncY)).intValue(); - - if (x % 5 == 0) { - // draw little hash - e.gc.drawLine(VLINE_XCOORD, yCoord, VLINE_XCOORD - - SMALL_HASH_MARK, yCoord); - - String recStr = String.format("%5.1f", new Float(x) - .floatValue()); - e.gc.drawString(recStr, 35, yCoord - fontHeightMid, true); - } - } - - // ----------------------------------------- - // Draw MAJOR line and label - // ----------------------------------------- - - double majorLevel = crestHistoryData.getMajorLevel(); - - e.gc.setForeground(parentComp.getDisplay().getSystemColor( - SWT.COLOR_MAGENTA)); - - int majorYCoord = (int) (maxPixValue - Math - .round(((majorLevel - stageMinVal) * pixelsPerIncY))); - - e.gc.drawLine(VLINE_XCOORD + 1, majorYCoord, VLINE_XCOORD - + HLINE_LENGTH, majorYCoord); - - String majorLabel = String.format("%5.1f MAJOR (%d)", majorLevel, - majorCount); - e.gc.drawString(majorLabel, VLINE_XCOORD + LABEL_X_OFFSET, - majorYCoord - LABEL_Y_OFFSET, true); - - // ----------------------------------------- - // Draw MODERATE line and label - // ----------------------------------------- - - double moderateLevel = crestHistoryData.getModerateLevel(); - - e.gc.setForeground(parentComp.getDisplay().getSystemColor( - SWT.COLOR_BLUE)); - - int modYCoord = (int) (maxPixValue - Math - .round(((moderateLevel - stageMinVal) * pixelsPerIncY))); - - e.gc.drawLine(VLINE_XCOORD + 1, modYCoord, VLINE_XCOORD - + HLINE_LENGTH, modYCoord); - - String modLabel = String.format("%5.1f MODERATE (%d)", - moderateLevel, modCount); - e.gc.drawString(modLabel, VLINE_XCOORD + LABEL_X_OFFSET, modYCoord - - LABEL_Y_OFFSET, true); - - // ----------------------------------------- - // Draw MINOR line and label - // ----------------------------------------- - - double minorLevel = crestHistoryData.getMinorLevel(); - - e.gc.setForeground(parentComp.getDisplay().getSystemColor( - SWT.COLOR_RED)); - - int minorYCoord = (int) (maxPixValue - Math - .round(((minorLevel - stageMinVal) * pixelsPerIncY))); - - e.gc.drawLine(VLINE_XCOORD + 1, minorYCoord, VLINE_XCOORD - + HLINE_LENGTH, minorYCoord); - - String minorLabel = String.format("%5.1f MINOR (%d)", minorLevel, - minorCount); - e.gc.drawString(minorLabel, VLINE_XCOORD + LABEL_X_OFFSET, - minorYCoord - LABEL_Y_OFFSET, true); - - e.gc.drawString("FLOOD", VLINE_XCOORD + HLINE_LENGTH - 40, - minorYCoord - LABEL_Y_OFFSET, true); - - // ----------------------------------------- - // Draw ACTION line and label - // ----------------------------------------- - - double actionLevel = crestHistoryData.getActionLevel(); - - e.gc.setForeground(parentComp.getDisplay().getSystemColor( - SWT.COLOR_YELLOW)); - - int actionYCoord = (int) (maxPixValue - Math - .round(((actionLevel - stageMinVal) * pixelsPerIncY))); - - e.gc.drawLine(VLINE_XCOORD + 1, actionYCoord, VLINE_XCOORD - + HLINE_LENGTH, actionYCoord); - - String actionLabel = String.format("%5.1f ACTION (%d)", - actionLevel, actionCount); - e.gc.drawString(actionLabel, VLINE_XCOORD + LABEL_X_OFFSET, - actionYCoord - LABEL_Y_OFFSET, true); - - // ------------------------------------------- - // Draw crest data - // ------------------------------------------- - - CrestDrawData drawData; - Rectangle rec; - - Set keys = crestDataMap.keySet(); - - for (Iterator iterator = keys.iterator(); iterator - .hasNext();) { - rec = iterator.next(); - drawData = crestDataMap.get(rec); - - if (drawData.getDrawData() == false) { - continue; - } - - if (drawData.isSelected() == true) { - e.gc.setBackground(parentComp.getDisplay().getSystemColor( - SWT.COLOR_WHITE)); - } else { - e.gc.setBackground(drawData.getColor()); - } - - e.gc.fillRectangle(rec.x, rec.y, rec.width, rec.height); - } - } - } - - /** - * Generate the map of crest data (value) and the rectangle areas on the - * canvas (key). - */ - private void generateCrestDataMap() { - crestDataMap = new HashMap(); - CrestDrawData drawData; - Rectangle rec; - - int circleWidth = 8; - int circleHeight = 8; - - double maxPixValue = VLINE_LENGTH + VLINE_PIXELS_FROM_TOP; - double numHashs = crestHistoryData.getMaxStageLevel(); - double pixelsPerIncY = VLINE_LENGTH / numHashs; - int startyear = crestHistoryData.getStartingYear(); - int endyear = crestHistoryData.getEndingYear(); - int years = endyear - startyear; - int pixelsPerIncX; - if (years == 0) { - pixelsPerIncX = 0; - } else { - pixelsPerIncX = HLINE_LENGTH / years; - } - - //Init the counts - this.majorCount=0; - this.minorCount=0; - this.actionCount=0; - this.modCount=0; - - for (CrestData crestData : crestHistoryData.getCrestDataArray()) { - - int yCoord = (int) (maxPixValue - Math - .round((crestData.getStage() * pixelsPerIncY))); - - double yearXOffset = crestData.getYear() - startyear; - int xCoord = YEAR_HASH_X_COORD_START - + new Double(Math.round(yearXOffset * pixelsPerIncX)) - .intValue(); - - rec = new Rectangle(xCoord - circleWidth / 2, yCoord - circleHeight - / 2, circleWidth, circleHeight); - - drawData = new CrestDrawData(crestData.getStage(), crestData - .getYear(), calculateDataColor(crestData.getStage())); - - crestDataMap.put(rec, drawData); - } - } - - /** - * Calculate color of the crest data. - * - * @param stage - * Stage (in feet). - * @return The color associated with the data. - */ - private Color calculateDataColor(double stage) { - if ((stage > crestHistoryData.getMajorLevel()) && - (crestHistoryData.getMajorLevel() != HydroConstants.MISSING_VALUE)) { - ++majorCount; - return parentComp.getDisplay().getSystemColor(SWT.COLOR_MAGENTA); - } else if ((stage > crestHistoryData.getModerateLevel()) && - (crestHistoryData.getModerateLevel() != HydroConstants.MISSING_VALUE)) { - ++modCount; - return parentComp.getDisplay().getSystemColor(SWT.COLOR_BLUE); - } else if ((stage > crestHistoryData.getMinorLevel()) && - (crestHistoryData.getMinorLevel() != HydroConstants.MISSING_VALUE)) { - ++minorCount; - return parentComp.getDisplay().getSystemColor(SWT.COLOR_RED); - } else if ((stage > crestHistoryData.getActionLevel()) && - (crestHistoryData.getActionLevel() != HydroConstants.MISSING_VALUE)) { - ++actionCount; - return parentComp.getDisplay().getSystemColor(SWT.COLOR_YELLOW); - } - - return parentComp.getDisplay().getSystemColor(SWT.COLOR_GREEN); - } - - /** - * Select the crest data if the mouse click is in the data rectangle. - * - * @param e - * Mouse event. - */ - public void processMouseEvent(MouseEvent e) { - Rectangle rec; - Rectangle foundRec = null; - Rectangle selectedRec = null; - - Set keys = crestDataMap.keySet(); - - for (Iterator iterator = keys.iterator(); iterator.hasNext();) { - rec = iterator.next(); - - // Check if the mouse's x & y coords is in the rectangle area or on - // the - // edge of the rectangle - if (recContains(e.x, e.y, rec)) { - foundRec = rec; - // crestDataMap.get(rec).setSelected(true); - } else if (crestDataMap.get(rec).isSelected() == true) { - selectedRec = rec; - } - - if (foundRec != null) { - crestDataMap.get(foundRec).setSelected(true); - - if (selectedRec != null) { - crestDataMap.get(selectedRec).setSelected(false); - } - - if (selectCrestDataCB != null) { - selectCrestDataCB.crestDataSelected(crestDataMap.get( - foundRec).getStage(), crestDataMap.get(foundRec) - .getYear()); - } - } - } - this.redraw(); - } - - /** - * This method is used in place of the Rectangle.contains() method. The - * contains method only checks if the x,y is inside the rectangle area. This - * method accounts for the x,y being on the edges of the rectangle. - * - * @param x - * Mouse's x coordinate. - * @param y - * Mouse's y coordinate. - * @param rec - * Rectangle the mouse coordinates will be checked against. - * @return True if the mouse's x & y coordinates are in/on the rectangle. - */ - private boolean recContains(int x, int y, Rectangle rec) { - if ((x < rec.x) || (x > (rec.x + rec.width))) { - return false; - } - - if ((y < rec.y) || (y > (rec.y + rec.height))) { - return false; - } - - return true; - } - - /** - * Select the crest data based on the stage nad year passed in. - * - * @param stage - * Stage in feet. - * @param year - * Year. - */ - public void selectCrestData(double stage, int year) { - Rectangle rec; - - Set keys = crestDataMap.keySet(); - - for (Iterator iterator = keys.iterator(); iterator.hasNext();) { - rec = iterator.next(); - - crestDataMap.get(rec).setSelected(false); - - if ((crestDataMap.get(rec).getStage() == stage) - && (crestDataMap.get(rec).getYear() == year)) { - crestDataMap.get(rec).setSelected(true); - } - } - this.redraw(); - } - - /** - * Draw all of the crest data on the canvas. - */ - public void drawAllCrestData() { - Rectangle rec; - - Set keys = crestDataMap.keySet(); - - for (Iterator iterator = keys.iterator(); iterator.hasNext();) { - rec = iterator.next(); - - crestDataMap.get(rec).setDrawData(true); - } - - this.redraw(); - } - - /** - * Draw only the crest data below the action stage. - */ - public void drawDataBelowActionStage() { - Rectangle rec; - - Set keys = crestDataMap.keySet(); - - for (Iterator iterator = keys.iterator(); iterator.hasNext();) { - rec = iterator.next(); - - if (crestDataMap.get(rec).getStage() > crestHistoryData - .getActionLevel()) { - crestDataMap.get(rec).setDrawData(false); - } else { - crestDataMap.get(rec).setDrawData(true); - } - } - - this.redraw(); - } - - /** - * Draw only the crest data above the action stage. - */ - public void drawDataAboveActionStage() { - Rectangle rec; - - Set keys = crestDataMap.keySet(); - - for (Iterator iterator = keys.iterator(); iterator.hasNext();) { - rec = iterator.next(); - - if (crestDataMap.get(rec).getStage() < crestHistoryData - .getActionLevel()) { - crestDataMap.get(rec).setDrawData(false); - } else { - crestDataMap.get(rec).setDrawData(true); - } - } - - this.redraw(); - } + /** + * Parent component. + */ + private Composite parentComp; + + /** + * Text font on the canvas. + */ + private Font canvasFont; + + /** + * Canvas width. + */ + private final int CANVAS_WIDTH = 700; + + /** + * Canvas height. + */ + private final int CANVAS_HEIGHT = 520; + + /** + * Y coordinate of the horizontal axis line. + */ + private final int HLINE_YCOORD = CANVAS_HEIGHT - 40; + + /** + * X coordinate of the vertical axis line. + */ + private final int VLINE_XCOORD = 80; + + private final int HLINE_LEFT_OFFSET = 20; + + /** + * Length of the horizontal axis line. + */ + private final int HLINE_LENGTH = CANVAS_WIDTH - VLINE_XCOORD + - HLINE_LEFT_OFFSET; + + /** + * Length of the vertical axis line. + */ + private final int VLINE_LENGTH = 450; + + /** + * The number of pixels the vertical lines is from the top of the canvas. + */ + private final int VLINE_PIXELS_FROM_TOP = CANVAS_HEIGHT - 40 - VLINE_LENGTH; + + /** + * "STAGE IN FEET" text. + */ + private final String STAGE_IN_FEET = "STAGE IN FEET"; + + /** + * Hash mark length. + */ + private final int HASH_MARK = 10; + + /** + * Small hash mark length. + */ + private final int SMALL_HASH_MARK = 5; + + /** + * Label Y coordinate offset. + */ + private final int LABEL_Y_OFFSET = 15; + + /** + * Label X coordinate offset. + */ + private final int LABEL_X_OFFSET = 5; + + /** + * Starting X coordinate for the year hash mark. + */ + private final int YEAR_HASH_X_COORD_START = VLINE_XCOORD + 15; + + /** + * number of intervals on the y-axis + */ + private final int NUM_VERTICAL_INTERVALS = 5; + /** + * Maximum stage value. + */ + private double stageMaxVal = 0.0; + + /** + * Minimum stage value. + */ + private double stageMinVal = 0.0; + + /** + * Number of MAJOR data items. + */ + private int majorCount = 0; + + /** + * Number of MODERATE data items. + */ + private int modCount = 0; + + /** + * Number of ACTION data items. + */ + private int actionCount = 0; + + /** + * Number of MINOR data items. + */ + private int minorCount = 0; + + /** + * Crest history data. + */ + private CrestHistoryData crestHistoryData; + + /** + * Map of the crest data (value) and the rectangle area on the canvas the + * data occupies (key). + */ + private HashMap crestDataMap; + + /** + * Callback for selecting crest data. + */ + private ISelectedCrestData selectCrestDataCB; + + /** + * Constructor. + * + * @param parent + * Parent composite. + * @param crestHistoryData + * Crest history data. + * @param callback + * Crest data selection callback. + */ + public CrestHistoryCanvas(Composite parent, + CrestHistoryData crestHistoryData, ISelectedCrestData callback) { + super(parent, SWT.DOUBLE_BUFFERED); + + parentComp = parent; + this.crestHistoryData = crestHistoryData; + // work around for missing data + if (crestHistoryData != null) { + selectCrestDataCB = callback; + stageMaxVal = crestHistoryData.getMaxStageLevel(); + stageMinVal = crestHistoryData.getMinStageLevel(); + } else { + stageMaxVal = 0.0; + stageMinVal = 0.0; + } + setYAxisMaxMin(); + // another work around + if ((crestHistoryData.getEndingYear() == 0) + || (crestHistoryData.getStartingYear() == 0)) { + Calendar cal = new GregorianCalendar(); + cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + Date date = SimulatedTime.getSystemTime().getTime(); + cal.setTime(date); + crestHistoryData.setStartingYear(1900); + crestHistoryData.setEndingYear(cal.get(Calendar.YEAR)); + } + + init(); + } + + /** + * Initialize method. + */ + private void init() { + if (crestHistoryData != null) { + generateCrestDataMap(); + } + + canvasFont = new Font(parentComp.getDisplay(), "Monospace", 9, + SWT.NORMAL); + + setupCanvas(); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseDown(MouseEvent e) { + processMouseEvent(e); + } + }); + } + + /** + * Regenerate the Crest history canvas + * + * @param crestHistoryData + */ + public void updateCrestHistotryData(CrestHistoryData crestHistoryData) { + this.crestHistoryData = crestHistoryData; + + if (crestHistoryData != null) { + stageMaxVal = crestHistoryData.getMaxStageLevel(); + stageMinVal = crestHistoryData.getMinStageLevel(); + } else { + stageMaxVal = 0.0; + stageMinVal = 0.0; + } + + setYAxisMaxMin(); + generateCrestDataMap(); + redraw(); + } + + /** + * Setup the drawing canvas. + */ + private void setupCanvas() { + GridData gd = new GridData(SWT.DEFAULT, SWT.TOP, false, true); + gd.heightHint = CANVAS_HEIGHT; + gd.widthHint = CANVAS_WIDTH; + + this.setSize(CANVAS_WIDTH, CANVAS_HEIGHT); + + setLayoutData(gd); + addPaintListener(new PaintListener() { + public void paintControl(PaintEvent e) { + drawCrestHistory(e); + } + }); + + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + canvasFont.dispose(); + } + }); + } + + /** + * Calculate for the max. and min. Y axis value + */ + private void setYAxisMaxMin() { + int roundFactor = 5; + long lmax, lmin; + + /* + * Round min down. If the original min data > 0, then don't round below + * 0. + */ + lmin = (long) (stageMinVal / roundFactor); + + if (lmin >= 0) { + stageMinVal = (lmin - 1) * roundFactor; + if (stageMinVal < 0) + stageMinVal = 0; + } else /* lmin < 0 */ + { + stageMinVal = (lmin - 1) * roundFactor; + } + + /* + * Round max up. + */ + lmax = (long) (stageMaxVal / roundFactor); + + /* + * If the difference between max_y and min_y < 10, round max_y up again. + */ + if ((stageMaxVal - stageMaxVal) < 10) { + stageMaxVal = (lmax + 2) * roundFactor; + } + + if (stageMinVal < 0) { + stageMinVal=0; + } + + } + + /** + * Draw the crest history data and the graph lines & labels on the canvas. + * + * @param e + * Paint event. + */ + private void drawCrestHistory(PaintEvent e) { + e.gc.setFont(canvasFont); + int fontHeightMid = (e.gc.getFontMetrics().getHeight() / 2); + int fontHeight = (e.gc.getFontMetrics().getHeight()); + + e.gc.setBackground(parentComp.getDisplay().getSystemColor( + SWT.COLOR_BLACK)); + + e.gc.fillRectangle(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); + + e.gc.setForeground(parentComp.getDisplay().getSystemColor( + SWT.COLOR_WHITE)); + + // ---------------------------------------- + // Draw horizontal and vertical axis lines + // ---------------------------------------- + + e.gc.drawLine(VLINE_XCOORD, HLINE_YCOORD, VLINE_XCOORD, HLINE_YCOORD + - VLINE_LENGTH); + + e.gc.drawLine(VLINE_XCOORD, HLINE_YCOORD, VLINE_XCOORD + HLINE_LENGTH, + HLINE_YCOORD); + + // ------------------------------------------------ + // Draw STAGE IN FEET vertical label + // ------------------------------------------------ + char[] charArray = STAGE_IN_FEET.toCharArray(); + + int tmpY = 120; + for (int i = 0; i < charArray.length; i++) { + e.gc.drawString(String.valueOf(charArray[i]), 5, tmpY, true); + tmpY += fontHeight; + } + + if (crestHistoryData != null) { + // ------------------------------------------------ + // Draw the years and the hash marks + // ------------------------------------------------ + int startyear = crestHistoryData.getStartingYear(); + int endyear = crestHistoryData.getEndingYear(); + int years = (endyear - startyear); + double pixelsPerIncX; + if (years == 0) { + pixelsPerIncX = 0; + } else { + pixelsPerIncX = HLINE_LENGTH / years; + } + + int yearXcoord = VLINE_XCOORD; + int yearHashXcoord = YEAR_HASH_X_COORD_START; + DecimalFormat df = new DecimalFormat(); + df.setMinimumIntegerDigits(1); + df.setMaximumFractionDigits(0); + df.setGroupingUsed(false); + + for (int i = 0; i <= years; i++) { + int inc = new Double(Math.rint(pixelsPerIncX * i)).intValue(); + yearXcoord = YEAR_HASH_X_COORD_START + inc - 15; + yearHashXcoord = YEAR_HASH_X_COORD_START + inc; + if (years < 75) { + if (i % 5 == 0) { + e.gc.drawString(df.format(startyear + i), yearXcoord, + CANVAS_HEIGHT - fontHeight - 3, true); + e.gc.drawLine(yearHashXcoord, HLINE_YCOORD, + yearHashXcoord, HLINE_YCOORD + HASH_MARK); + } + } else { + if (i % 10 == 0) { + e.gc.drawString(df.format(startyear + i), yearXcoord, + CANVAS_HEIGHT - fontHeight - 3, true); + e.gc.drawLine(yearHashXcoord, HLINE_YCOORD, + yearHashXcoord, HLINE_YCOORD + HASH_MARK); + } + } + } + + // ----------------------------------------- + // Draw stage hash marks + // ----------------------------------------- + + double maxPixValue = VLINE_LENGTH + VLINE_PIXELS_FROM_TOP; + double numHashsY = stageMaxVal - stageMinVal; + double valInc = (stageMaxVal - stageMinVal) + / NUM_VERTICAL_INTERVALS; + + double pixelsPerIncY = VLINE_LENGTH / numHashsY; + + for (int x = (int) (stageMinVal); x <= stageMaxVal; x += valInc) { + int yCoord = HLINE_YCOORD + - new Double(Math.round((x - stageMinVal) + * pixelsPerIncY)).intValue(); + + e.gc.drawLine(VLINE_XCOORD, yCoord, VLINE_XCOORD + - SMALL_HASH_MARK, yCoord); + + String recStr = String.format("%5.1f", + new Float(x).floatValue()); + e.gc.drawString(recStr, 35, yCoord - fontHeightMid, true); + } + + // ----------------------------------------- + // Draw MAJOR line and label + // ----------------------------------------- + + double majorLevel = crestHistoryData.getMajorLevel(); + + e.gc.setForeground(parentComp.getDisplay().getSystemColor( + SWT.COLOR_MAGENTA)); + + int majorYCoord = (int) (maxPixValue - Math + .round(((majorLevel - stageMinVal) * pixelsPerIncY))); + + e.gc.drawLine(VLINE_XCOORD + 1, majorYCoord, VLINE_XCOORD + + HLINE_LENGTH, majorYCoord); + + String majorLabel = String.format("%5.1f MAJOR (%d)", majorLevel, + majorCount); + e.gc.drawString(majorLabel, VLINE_XCOORD + LABEL_X_OFFSET, + majorYCoord - LABEL_Y_OFFSET, true); + + // ----------------------------------------- + // Draw MODERATE line and label + // ----------------------------------------- + + double moderateLevel = crestHistoryData.getModerateLevel(); + + e.gc.setForeground(parentComp.getDisplay().getSystemColor( + SWT.COLOR_BLUE)); + + int modYCoord = (int) (maxPixValue - Math + .round(((moderateLevel - stageMinVal) * pixelsPerIncY))); + + e.gc.drawLine(VLINE_XCOORD + 1, modYCoord, VLINE_XCOORD + + HLINE_LENGTH, modYCoord); + + String modLabel = String.format("%5.1f MODERATE (%d)", + moderateLevel, modCount); + e.gc.drawString(modLabel, VLINE_XCOORD + LABEL_X_OFFSET, modYCoord + - LABEL_Y_OFFSET, true); + + // ----------------------------------------- + // Draw MINOR line and label + // ----------------------------------------- + + double minorLevel = crestHistoryData.getMinorLevel(); + + e.gc.setForeground(parentComp.getDisplay().getSystemColor( + SWT.COLOR_RED)); + + int minorYCoord = (int) (maxPixValue - Math + .round(((minorLevel - stageMinVal) * pixelsPerIncY))); + + e.gc.drawLine(VLINE_XCOORD + 1, minorYCoord, VLINE_XCOORD + + HLINE_LENGTH, minorYCoord); + + String minorLabel = String.format("%5.1f MINOR (%d)", minorLevel, + minorCount); + e.gc.drawString(minorLabel, VLINE_XCOORD + LABEL_X_OFFSET, + minorYCoord - LABEL_Y_OFFSET, true); + + e.gc.drawString("FLOOD", VLINE_XCOORD + HLINE_LENGTH - 40, + minorYCoord - LABEL_Y_OFFSET, true); + + // ----------------------------------------- + // Draw ACTION line and label + // ----------------------------------------- + + double actionLevel = crestHistoryData.getActionLevel(); + + e.gc.setForeground(parentComp.getDisplay().getSystemColor( + SWT.COLOR_YELLOW)); + + int actionYCoord = (int) (maxPixValue - Math + .round(((actionLevel - stageMinVal) * pixelsPerIncY))); + + e.gc.drawLine(VLINE_XCOORD + 1, actionYCoord, VLINE_XCOORD + + HLINE_LENGTH, actionYCoord); + + String actionLabel = String.format("%5.1f ACTION (%d)", + actionLevel, actionCount); + e.gc.drawString(actionLabel, VLINE_XCOORD + LABEL_X_OFFSET, + actionYCoord - LABEL_Y_OFFSET, true); + + // ------------------------------------------- + // Draw crest data + // ------------------------------------------- + + CrestDrawData drawData; + Rectangle rec; + + Set keys = crestDataMap.keySet(); + + for (Iterator iterator = keys.iterator(); iterator + .hasNext();) { + rec = iterator.next(); + drawData = crestDataMap.get(rec); + + if (drawData.getDrawData() == false) { + continue; + } + + if (drawData.isSelected() == true) { + e.gc.setBackground(parentComp.getDisplay().getSystemColor( + SWT.COLOR_WHITE)); + } else { + e.gc.setBackground(drawData.getColor()); + } + + e.gc.fillRectangle(rec.x, rec.y, rec.width, rec.height); + } + } + } + + /** + * Generate the map of crest data (value) and the rectangle areas on the + * canvas (key). + */ + private void generateCrestDataMap() { + crestDataMap = new HashMap(); + CrestDrawData drawData; + Rectangle rec; + + int circleWidth = 8; + int circleHeight = 8; + + double maxPixValue = VLINE_LENGTH + VLINE_PIXELS_FROM_TOP; + double numHashs = stageMaxVal - stageMinVal; + double pixelsPerIncY = VLINE_LENGTH / numHashs; + int startyear = crestHistoryData.getStartingYear(); + int endyear = crestHistoryData.getEndingYear(); + int years = endyear - startyear; + int pixelsPerIncX; + if (years == 0) { + pixelsPerIncX = 0; + } else { + pixelsPerIncX = HLINE_LENGTH / years; + } + + // Init the counts + this.majorCount = 0; + this.minorCount = 0; + this.actionCount = 0; + this.modCount = 0; + + for (CrestData crestData : crestHistoryData.getCrestDataArray()) { + + int yCoord = (int) (maxPixValue - Math + .round(((crestData.getStage() - stageMinVal) * pixelsPerIncY))); + + double yearXOffset = crestData.getYear() - startyear; + int xCoord = YEAR_HASH_X_COORD_START + + new Double(Math.round(yearXOffset * pixelsPerIncX)) + .intValue(); + + rec = new Rectangle(xCoord - circleWidth / 2, yCoord - circleHeight + / 2, circleWidth, circleHeight); + + drawData = new CrestDrawData(crestData.getStage(), + crestData.getYear(), + calculateDataColor(crestData.getStage())); + + crestDataMap.put(rec, drawData); + } + } + + /** + * Calculate color of the crest data. + * + * @param stage + * Stage (in feet). + * @return The color associated with the data. + */ + private Color calculateDataColor(double stage) { + if ((stage > crestHistoryData.getMajorLevel()) + && (crestHistoryData.getMajorLevel() != HydroConstants.MISSING_VALUE)) { + ++majorCount; + return parentComp.getDisplay().getSystemColor(SWT.COLOR_MAGENTA); + } else if ((stage > crestHistoryData.getModerateLevel()) + && (crestHistoryData.getModerateLevel() != HydroConstants.MISSING_VALUE)) { + ++modCount; + return parentComp.getDisplay().getSystemColor(SWT.COLOR_BLUE); + } else if ((stage > crestHistoryData.getMinorLevel()) + && (crestHistoryData.getMinorLevel() != HydroConstants.MISSING_VALUE)) { + ++minorCount; + return parentComp.getDisplay().getSystemColor(SWT.COLOR_RED); + } else if ((stage > crestHistoryData.getActionLevel()) + && (crestHistoryData.getActionLevel() != HydroConstants.MISSING_VALUE)) { + ++actionCount; + return parentComp.getDisplay().getSystemColor(SWT.COLOR_YELLOW); + } + + return parentComp.getDisplay().getSystemColor(SWT.COLOR_GREEN); + } + + /** + * Select the crest data if the mouse click is in the data rectangle. + * + * @param e + * Mouse event. + */ + public void processMouseEvent(MouseEvent e) { + Rectangle rec; + Rectangle foundRec = null; + Rectangle selectedRec = null; + + Set keys = crestDataMap.keySet(); + + for (Iterator iterator = keys.iterator(); iterator.hasNext();) { + rec = iterator.next(); + + // Check if the mouse's x & y coords is in the rectangle area or on + // the + // edge of the rectangle + if (recContains(e.x, e.y, rec)) { + foundRec = rec; + // crestDataMap.get(rec).setSelected(true); + } else if (crestDataMap.get(rec).isSelected() == true) { + selectedRec = rec; + } + + if (foundRec != null) { + crestDataMap.get(foundRec).setSelected(true); + + if (selectedRec != null) { + crestDataMap.get(selectedRec).setSelected(false); + } + + if (selectCrestDataCB != null) { + selectCrestDataCB.crestDataSelected( + crestDataMap.get(foundRec).getStage(), crestDataMap + .get(foundRec).getYear()); + } + } + } + this.redraw(); + } + + /** + * This method is used in place of the Rectangle.contains() method. The + * contains method only checks if the x,y is inside the rectangle area. This + * method accounts for the x,y being on the edges of the rectangle. + * + * @param x + * Mouse's x coordinate. + * @param y + * Mouse's y coordinate. + * @param rec + * Rectangle the mouse coordinates will be checked against. + * @return True if the mouse's x & y coordinates are in/on the rectangle. + */ + private boolean recContains(int x, int y, Rectangle rec) { + if ((x < rec.x) || (x > (rec.x + rec.width))) { + return false; + } + + if ((y < rec.y) || (y > (rec.y + rec.height))) { + return false; + } + + return true; + } + + /** + * Select the crest data based on the stage nad year passed in. + * + * @param stage + * Stage in feet. + * @param year + * Year. + */ + public void selectCrestData(double stage, int year) { + Rectangle rec; + + Set keys = crestDataMap.keySet(); + + for (Iterator iterator = keys.iterator(); iterator.hasNext();) { + rec = iterator.next(); + + crestDataMap.get(rec).setSelected(false); + + if ((crestDataMap.get(rec).getStage() == stage) + && (crestDataMap.get(rec).getYear() == year)) { + crestDataMap.get(rec).setSelected(true); + } + } + this.redraw(); + } + + /** + * Draw all of the crest data on the canvas. + */ + public void drawAllCrestData() { + Rectangle rec; + + Set keys = crestDataMap.keySet(); + + for (Iterator iterator = keys.iterator(); iterator.hasNext();) { + rec = iterator.next(); + + crestDataMap.get(rec).setDrawData(true); + } + + this.redraw(); + } + + /** + * Draw only the crest data below the action stage. + */ + public void drawDataBelowActionStage() { + Rectangle rec; + + Set keys = crestDataMap.keySet(); + + for (Iterator iterator = keys.iterator(); iterator.hasNext();) { + rec = iterator.next(); + + if (crestDataMap.get(rec).getStage() > crestHistoryData + .getActionLevel()) { + crestDataMap.get(rec).setDrawData(false); + } else { + crestDataMap.get(rec).setDrawData(true); + } + } + + this.redraw(); + } + + /** + * Draw only the crest data above the action stage. + */ + public void drawDataAboveActionStage() { + Rectangle rec; + + Set keys = crestDataMap.keySet(); + + for (Iterator iterator = keys.iterator(); iterator.hasNext();) { + rec = iterator.next(); + + if (crestDataMap.get(rec).getStage() < crestHistoryData + .getActionLevel()) { + crestDataMap.get(rec).setDrawData(false); + } else { + crestDataMap.get(rec).setDrawData(true); + } + } + + this.redraw(); + } } diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/datamanager/RiverDataManager.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/datamanager/RiverDataManager.java index 64d9492796..691aa82a6f 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/datamanager/RiverDataManager.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/datamanager/RiverDataManager.java @@ -66,683 +66,679 @@ import com.raytheon.viz.hydrocommon.data.RiverDataPoint; public class RiverDataManager { - /** Singleton instance of this class */ - private static RiverDataManager riverManager = null; - - /* Private Constructor */ - private RiverDataManager() { - } - - /** - * Get an instance of this singleton. - * - * @return Instance of this class - */ - public static synchronized RiverDataManager getInstance() { - if (riverManager == null) { - riverManager = new RiverDataManager(); - } - return riverManager; - } - - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(RiverDataManager.class); - - private LinkedHashMap crestData = null; - - private LinkedHashMap> riverData = null; - - private static String locationQuery = "SELECT name, county, state, elev, hsa, lat, lon, rb from location WHERE lid ="; - - private static String riverStatQuery = "SELECT stream, mile, zd, tide, bf, wstg, fs, fq, action_flow, primary_pe FROM riverstat WHERE lid ="; - - private static String descriptionQuery = "SELECT proximity, reach FROM descrip WHERE lid ="; - - private static String crestQuery = "select stage, q, datcrst, timcrst, cremark, hw, jam, olddatum, suppress, prelim from crest where lid = '"; - - private static String floodCatQuery = "SELECT minor_stage, moderate_stage, major_stage, minor_flow, moderate_flow, major_flow from floodcat WHERE lid = "; - - private static String riverInfoQuery = "SELECT rivermonlocation.group_id, rivermongroup.group_name FROM rivermongroup, rivermonlocation WHERE rivermongroup.group_id = rivermonlocation.group_id AND rivermonlocation.lid = "; - - private static String riverPointQuery = "SELECT l.lid, l.name, l.county, l.state, l.elev, l.hsa, l.lat, l.lon, " - + "rml.group_id, " - + "rmg.group_name, " - + "r.stream, r.mile, r.zd AS zero, r.tide, r.bf AS bankfull, r.wstg AS action_stage, r.fs AS flood_stage, r.fq AS flood_flow, r.action_flow, r.primary_pe, " - + "d.proximity, d.reach, " - + "f.minor_stage AS minor, f.moderate_stage AS moderate, f.major_stage AS major, f.minor_flow AS minor, f.moderate_flow AS moderate, f.major_flow AS major " - + "FROM location l " - + "LEFT JOIN floodcat f ON l.lid::text = f.lid::text " - + "LEFT JOIN descrip d ON l.lid::text = d.lid::text, riverstat r, rivermonlocation rml " - + "LEFT JOIN rivermongroup rmg ON rml.group_id::text = rmg.group_id::text " - + "WHERE l.lid::text = r.lid::text and r.lid::text = rml.lid::text " - + "ORDER BY rml.group_id, r.mile desc"; - - private static String riverObsvalueQueryFront = "SELECT distinct(foo.lid), foo.value, foo.maxtime from " - + "(SELECT distinct height.lid, height.value, max(height.obstime) as maxtime " - + "FROM height " - + "WHERE height.lid in " - + "(select distinct(lid) " - + "from rivermonlocation " - + "where rivermonlocation.group_id = "; - - private static String riverObsvalueQueryBack = ") GROUP BY height.lid, height.value) " - + "AS foo " - + "GROUP BY foo.lid, foo.value, foo.maxtime order by foo.lid, foo.maxtime desc"; - - private static String riverFcstvalueQueryFront = "SELECT distinct(foo.lid), foo.value, foo.maxtime from " - + "(SELECT distinct fcstheight.lid, fcstheight.value, max(fcstheight.validtime) as maxtime " - + "FROM fcstheight " - + "WHERE fcstheight.lid in " - + "(select distinct(lid) " - + "from rivermonlocation " - + "where rivermonlocation.group_id = "; - - private static String riverFcstvalueQueryBack = ") GROUP BY fcstheight.lid, fcstheight.value) " - + "AS foo " - + "GROUP BY foo.lid, foo.value, foo.maxtime order by foo.lid, foo.maxtime desc"; - - private static String riverIDQuery = "SELECT group_id FROM rivermonlocation where lid ="; - - /** - * River Query Crest - * - * @param lid - * @return CrestHistoryData - */ - public CrestHistoryData getRiverCrests(RiverDataPoint rdp, int allFlag) { - CrestHistoryData crests = null; - - if (crestData == null) { - crestData = new LinkedHashMap(); - } - - crests = new CrestHistoryData(); - String query = null; - - /* get crest data depending on action stage */ - if (rdp != null) { - String sql = "select stage, q, datcrst, timcrst, cremark, hw, jam, olddatum, suppress, prelim " - + "from crest where lid = '" + rdp.getLid(); - - if (allFlag == 1) { - query = sql + "' and stage >'" + rdp.getActionStage() - + "' ORDER BY stage, q"; - } else if (allFlag == 2) { - query = sql + "' and stage <'" + rdp.getActionStage() - + "' ORDER BY stage, q"; - } else { - query = sql + "' ORDER BY stage, q"; - } - - ArrayList objects = null; - - try { - objects = (ArrayList) DirectDbQuery.executeQuery( - query, HydroConstants.IHFS, QueryLanguage.SQL); - if (objects != null) { - for (Object[] crestob : objects) { - crests.addCrestData(new CrestData(crestob)); - } - } - } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - } - - if (crests.getCrestDataArray().size() > 0) { - // max stage level, default sort mode - // There is a problem when the stage is not set in the db. - // Added this work around here to manually find the max stage value - double maxStag = 0; - for (int i = 0; i < crests.getCrestDataArray().size(); i++) { - if (crests.getCrestDataArray().get(i).getStage() > maxStag) { - maxStag = crests.getCrestDataArray().get(i).getStage(); - } - } - crests.setMaxStageLevel(maxStag); - - // set the values to gage by - crests.setActionLevel(rdp.getActionStage()); - crests.setMajorLevel(rdp.getMajorStage()); - crests.setMinorLevel(rdp.getMinorStage()); - crests.setModerateLevel(rdp.getModerateStage()); - - // we assume a top of zero at all times, find oldest record - crests.sortByDate(); - CrestData cd5 = crests.getCrestDataArray().get( - crests.getCrestDataArray().size() - 1); - - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - Date now = SimulatedTime.getSystemTime().getTime(); - cal.setTime(now); - - if (cd5.getCrestDate() != null) { - crests.setStartingYear(cd5.getCrestDate().get(Calendar.YEAR)); - } else { - crests.setStartingYear(HydroConstants.DEFAULT_YEAR); - } - crests.setEndingYear(cal.get(Calendar.YEAR)); - - crests.sortByStage(); - - crestData.put(rdp.getLid(), crests); - } - - return crests; - } - - /** - * Gets the crest data for just the record flood, flow - * - * @param rdp - * @return - */ - public RiverDataPoint getRiverCrest(RiverDataPoint rdp) { - Date date = SimulatedTime.getSystemTime().getTime(); - int allFlag = 0; - CrestHistoryData crests = getRiverCrests(rdp, allFlag); - ArrayList temp = crests.getCrestDataArray(); - if (temp.size() > 0) { - // maximum stage value - crests.sortByStage(); - CrestData cd = temp.get(0); - rdp.setCrestValue(cd.getStage()); - - // maximum flow (q) value for max stage value - rdp.setCrestFlow(cd.getFlow()); - - // Stage Crest date - rdp.setCrestTime(cd.getCrestDate()); - - } else { - // maximum stage value - rdp.setCrestValue(HydroConstants.MISSING_VALUE); - - // maximum flow value - rdp.setCrestFlow(HydroConstants.MISSING_VALUE); - - // sort by date - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - cal.setTime(date); - rdp.setCrestTime(cal); - } - - return rdp; - } - - /** - * data structure to house the river water shed data - * - * @return HashMap> - */ - public LinkedHashMap> getRiverSummaryData() { - ArrayList data = null; - - try { - data = (ArrayList) DirectDbQuery.executeQuery( - riverPointQuery, HydroConstants.IHFS, QueryLanguage.SQL); - if (data != null) { - riverData = new LinkedHashMap>(); - String riverID = null; - LinkedHashMap riverPoints = null; - for (Object[] point : data) { - RiverDataPoint rdp = new RiverDataPoint(point); - // start - if (riverID == null) { - riverID = rdp.getRiverID(); - riverPoints = new LinkedHashMap(); - riverPoints.put(rdp.getLid(), rdp); - } - // new river switch - else if (!rdp.getRiverID().equals(riverID)) { - // sock away the old one - riverData.put(riverID, riverPoints); - // rename Name - riverID = rdp.getRiverID(); - // create new - riverPoints = new LinkedHashMap(); - riverPoints.put(rdp.getLid(), rdp); - } - // in river run - else { - riverPoints.put(rdp.getLid(), rdp); - } - } - // take care of last river - riverData.put(riverID, riverPoints); - } - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - - return riverData; - } - - /** - * Populate the Data for time and point obs and fcst, really not pretty - * avert your eyes. - * - * @param riverPoints - * @param riverID - * @return HashMap - */ - public LinkedHashMap populateRiverData( - String riverID, LinkedHashMap riverPoints) { - - ArrayList obsdata = null; - ArrayList fcstdata = null; - - try { - String obsquery = riverObsvalueQueryFront + "'" + riverID + "'" - + riverObsvalueQueryBack; - String fcstquery = riverFcstvalueQueryFront + "'" + riverID + "'" - + riverFcstvalueQueryBack; - obsdata = (ArrayList) DirectDbQuery.executeQuery( - obsquery, HydroConstants.IHFS, QueryLanguage.SQL); - fcstdata = (ArrayList) DirectDbQuery.executeQuery( - fcstquery, HydroConstants.IHFS, QueryLanguage.SQL); - if (obsdata != null) { - String lid = null; - Calendar obstime = null; - - for (Object[] obspoint : obsdata) { - if (obspoint[0] != null) { - String newlid = (String) obspoint[0]; - // into - if (!newlid.equals(lid) || (lid == null)) { - lid = newlid; - // we care about this data - if (obspoint[1] != null) { - riverPoints.get(lid).setObsValue( - (Double) obspoint[1]); - } - if (obspoint[2] != null) { - obstime = Calendar.getInstance(TimeZone - .getTimeZone("GMT")); - obstime.setTimeInMillis(((Timestamp) obspoint[2]) - .getTime()); - riverPoints.get(lid).setObsTime(obstime); - } - } - } - } - } - if (fcstdata != null) { - String lid = null; - Calendar fcsttime = null; - - for (Object[] fcstpoint : fcstdata) { - if (fcstpoint[0] != null) { - String newlid = (String) fcstpoint[0]; - // into - if (!newlid.equals(lid) || (lid == null)) { - lid = newlid; - // we care about this data - if (fcstpoint[1] != null) { - riverPoints.get(lid).setFcstValue( - (Double) fcstpoint[1]); - } - if (fcstpoint[2] != null) { - fcsttime = Calendar.getInstance(TimeZone - .getTimeZone("GMT")); - fcsttime.setTimeInMillis(((Timestamp) fcstpoint[2]) - .getTime()); - riverPoints.get(lid).setFcstTime(fcsttime); - } - } - } - } - } - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - - return riverPoints; - } - - /** - * Gets the RiverID for the GageData - * - * @param lid - * @return - */ - public String getRiverID(String lid) { - String riverID = null; - - try { - ArrayList riverObject = (ArrayList) DirectDbQuery - .executeQuery(riverIDQuery + "'" + lid + "'", - HydroConstants.IHFS, QueryLanguage.SQL); - - if (riverObject.size() > 0) { - riverID = (String) (riverObject.get(0))[0]; - } - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - - return riverID; - } - - /** - * Get an individual River Data Point - * - * @param lid - * @return - */ - public RiverDataPoint getRiverDataPoint(String lid) { - - // Get the location information first - RiverDataPoint rdp = new RiverDataPoint(lid); - try { - ArrayList locationObject = (ArrayList) DirectDbQuery - .executeQuery(locationQuery + "'" + lid + "'", - HydroConstants.IHFS, QueryLanguage.SQL); - if (locationObject.size() == 1) { - Object[] location = locationObject.get(0); - if ((String) location[0] != null) { - rdp.setLocName((String) location[0]); - } - if ((String) location[1] != null) { - rdp.setCounty((String) location[1]); - } - if ((String) location[2] != null) { - rdp.setState((String) location[2]); - } - if ((Double) location[3] != null) { - rdp.setElevation((Double) location[3]); - } - if ((String) location[4] != null) { - rdp.setHsa((String) location[4]); - } - if ((Double) location[5] != null) { - rdp.setLat((Double) location[5]); - } - if ((Double) location[6] != null) { - rdp.setLon((Double) location[6]); - } - if ((String) location[7] != null) { - rdp.setRiverName((String) location[7]); - } - } - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - // next find the river stat values - try { - ArrayList statObject = (ArrayList) DirectDbQuery - .executeQuery(riverStatQuery + "'" + lid + "'", - HydroConstants.IHFS, QueryLanguage.SQL); - if (statObject.size() == 1) { - Object[] stat = statObject.get(0); - if ((String) stat[0] != null) { - rdp.setStreamName((String) stat[0]); - } - if ((Double) stat[1] != null) { - rdp.setMile((Double) stat[1]); - } - if ((Double) stat[2] != null) { - rdp.setZeroDatum((Double) stat[2]); - } - if ((String) stat[3] != null) { - rdp.setTide((String) stat[3]); - } - if ((Double) stat[4] != null) { - rdp.setBankFull((Double) stat[4]); - } - if ((Double) stat[5] != null) { - rdp.setActionStage((Double) stat[5]); - } - if ((Double) stat[6] != null) { - rdp.setFloodStage((Double) stat[6]); - } - if ((Double) stat[7] != null) { - rdp.setFloodFlow((Double) stat[7]); - } - if ((Double) stat[8] != null) { - rdp.setActionFlow((Double) stat[8]); - } - if ((String) stat[9] != null) { - rdp.setPrimaryPE((String) stat[9]); - } - } - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - // next find the description values - try { - ArrayList descripObject = (ArrayList) DirectDbQuery - .executeQuery(descriptionQuery + "'" + lid + "'", - HydroConstants.IHFS, QueryLanguage.SQL); - if (descripObject.size() == 1) { - Object[] descrip = descripObject.get(0); - if ((String) descrip[0] != null) { - rdp.setProximity((String) descrip[0]); - } - if ((String) descrip[1] != null) { - rdp.setReach((String) descrip[1]); - } - } - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - // get data for the flood categories - try { - ArrayList floodObject = (ArrayList) DirectDbQuery - .executeQuery(floodCatQuery + "'" + lid + "'", - HydroConstants.IHFS, QueryLanguage.SQL); - if (floodObject.size() == 1) { - Object[] flood = floodObject.get(0); - if ((Double) flood[0] != null) { - rdp.setMinorStage((Double) flood[0]); - } - if ((Double) flood[1] != null) { - rdp.setModerateStage((Double) flood[1]); - } - if ((Double) flood[2] != null) { - rdp.setMajorStage((Double) flood[2]); - } - if ((Double) flood[3] != null) { - rdp.setMinorFlow((Double) flood[3]); - } - if ((Double) flood[4] != null) { - rdp.setModerateFlow((Double) flood[4]); - } - if ((Double) flood[5] != null) { - rdp.setMajorFlow((Double) flood[5]); - } - } - } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - // Get data for Crest information - try { - CrestHistoryData crests = new CrestHistoryData(); - ArrayList crestList = crests.getCrestDataArray(); - - ArrayList crestObject = (ArrayList) DirectDbQuery - .executeQuery(crestQuery + lid + "' ORDER BY stage, q", - HydroConstants.IHFS, QueryLanguage.SQL); - - if (crestObject != null) { - for (Object[] crestob : crestObject) { - crests.addCrestData(new CrestData(crestob)); - } - } - if (crestList.size() > 0) { - crests.sortByStage(); - CrestData cd = crestList.get(0); - - rdp.setCrestValue(cd.getStage()); - rdp.setCrestFlow(cd.getFlow()); - rdp.setCrestTime(cd.getCrestDate()); - } - - } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - // get data for the river information - try { - ArrayList riverInfoObject = (ArrayList) DirectDbQuery - .executeQuery(riverInfoQuery + "'" + lid + "'", - HydroConstants.IHFS, QueryLanguage.SQL); - if (riverInfoObject.size() == 1) { - Object[] riverInfo = riverInfoObject.get(0); - if ((String) riverInfo[0] != null) { - rdp.setRiverID((String) riverInfo[0]); - } - } - } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - - return rdp; - } - - public String getStreamName(String lid) { - List results = null; - String stream = null; - try { - results = DirectDbQuery.executeQuery( - "select stream from riverstat where lid = '" + lid + "'", - HydroConstants.IHFS, QueryLanguage.SQL); - if ((results != null) && (results.size() > 0)) { - stream = (String) results.get(0)[0]; - } - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - - return stream; - } - - /** - * Get the Statprof data for the specified stream. - * - * @param stream - * The stream - * @return The statprof data for the stream. - */ - public List getStatProf(String stream) { -// String query = "from " -// + com.raytheon.edex.plugin.shef.objects.Statprof.class -// .getName(); -// query += " where stream = '" + stream + "' order by mile desc"; - String query = "select lid, name, primary_pe, stream, fs, wstg, fq, " + - "action_flow, zd, mile, reach, proximity from statprof " + - "where stream = '" + stream + "' order by mile desc"; - - List dataList = new ArrayList(); - try { - List results = DirectDbQuery.executeQuery(query, - HydroConstants.IHFS, QueryLanguage.SQL); - if ((results != null) && (results.size() > 0)) { - for (Object[] oa : results) { - if (oa[0] != null) { -// dataList.add((Statprof) oa[0]); - Statprof sp = new Statprof(); - StatprofId spid = new StatprofId(); - spid.setLid((String) oa[0]); - spid.setName((String) oa[1]); - spid.setPrimaryPe((String) oa[2]); - spid.setStream((String) oa[3]); - spid.setFs((Double) oa[4]); - spid.setWstg((Double) oa[5]); - spid.setFq((Double) oa[6]); - spid.setActionFlow((Double) oa[7]); - spid.setZd((Double) oa[8]); - spid.setMile((Double) oa[9]); - spid.setReach((String) oa[10]); - spid.setProximity((String) oa[11]); - sp.setId(spid); - - // Check for missing data values - if (spid.getPrimaryPe() == null) { - continue; - } else if (spid.getPrimaryPe().startsWith("H")) { - if ((spid.getFs() == null) || (spid.getWstg() == null)) { - continue; - } - } else { - if ((spid.getFq() == null) || (spid.getActionFlow() == null)) { - continue; - } - } - dataList.add(sp); - } - } - } - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - - return dataList; - } - - public ArrayList getRiverStatus(String lid, String pe, - long validTime, long basisTime) { - - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - Date validTimeDate = new Date(); - validTimeDate.setTime(validTime); - String validTimeStr = sdf.format(validTimeDate); - Date basisTimeDate = new Date(); - basisTimeDate.setTime(basisTime); - String basisTimeStr = sdf.format(basisTimeDate); - - String where = " where lid = '" + lid + "' " + "and pe = '" + pe - + "' and (validTime > '" + validTimeStr - + "' or ts like 'F%%') and " - + "basisTime is null or basistime >= '" + basisTimeStr + "')"; - - String query = "from " - + com.raytheon.uf.common.dataplugin.shef.tables.Riverstatus.class - .getName(); - query += where; - - ArrayList dataList = null; - try { - List results = DirectDbQuery.executeQuery(query, - HydroConstants.IHFS, QueryLanguage.HQL); - if ((results != null) && (results.size() > 0)) { - dataList = new ArrayList(); - for (Object[] oa : results) { - dataList.add((Riverstatus) oa[0]); - } - } - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - - return dataList; - } - - public List getTsList() { - List rs = null; - - String query = "select distinct(ts), ts_rank from ingestfilter"; - - try { - rs = DirectDbQuery.executeQuery(query, HydroConstants.IHFS, - QueryLanguage.SQL); - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - - return rs; - } + /** Singleton instance of this class */ + private static RiverDataManager riverManager = null; + + /* Private Constructor */ + private RiverDataManager() { + } + + /** + * Get an instance of this singleton. + * + * @return Instance of this class + */ + public static synchronized RiverDataManager getInstance() { + if (riverManager == null) { + riverManager = new RiverDataManager(); + } + return riverManager; + } + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(RiverDataManager.class); + + private LinkedHashMap crestData = null; + + private LinkedHashMap> riverData = null; + + private static String locationQuery = "SELECT name, county, state, elev, hsa, lat, lon, rb from location WHERE lid ="; + + private static String riverStatQuery = "SELECT stream, mile, zd, tide, bf, wstg, fs, fq, action_flow, primary_pe FROM riverstat WHERE lid ="; + + private static String descriptionQuery = "SELECT proximity, reach FROM descrip WHERE lid ="; + + private static String crestQuery = "select stage, q, datcrst, timcrst, cremark, hw, jam, olddatum, suppress, prelim from crest where lid = '"; + + private static String floodCatQuery = "SELECT minor_stage, moderate_stage, major_stage, minor_flow, moderate_flow, major_flow from floodcat WHERE lid = "; + + private static String riverInfoQuery = "SELECT rivermonlocation.group_id, rivermongroup.group_name FROM rivermongroup, rivermonlocation WHERE rivermongroup.group_id = rivermonlocation.group_id AND rivermonlocation.lid = "; + + private static String riverPointQuery = "SELECT l.lid, l.name, l.county, l.state, l.elev, l.hsa, l.lat, l.lon, " + + "rml.group_id, " + + "rmg.group_name, " + + "r.stream, r.mile, r.zd AS zero, r.tide, r.bf AS bankfull, r.wstg AS action_stage, r.fs AS flood_stage, r.fq AS flood_flow, r.action_flow, r.primary_pe, " + + "d.proximity, d.reach, " + + "f.minor_stage AS minor, f.moderate_stage AS moderate, f.major_stage AS major, f.minor_flow AS minor, f.moderate_flow AS moderate, f.major_flow AS major " + + "FROM location l " + + "LEFT JOIN floodcat f ON l.lid::text = f.lid::text " + + "LEFT JOIN descrip d ON l.lid::text = d.lid::text, riverstat r, rivermonlocation rml " + + "LEFT JOIN rivermongroup rmg ON rml.group_id::text = rmg.group_id::text " + + "WHERE l.lid::text = r.lid::text and r.lid::text = rml.lid::text " + + "ORDER BY rml.group_id, r.mile desc"; + + private static String riverObsvalueQueryFront = "SELECT distinct(foo.lid), foo.value, foo.maxtime from " + + "(SELECT distinct height.lid, height.value, max(height.obstime) as maxtime " + + "FROM height " + + "WHERE height.lid in " + + "(select distinct(lid) " + + "from rivermonlocation " + + "where rivermonlocation.group_id = "; + + private static String riverObsvalueQueryBack = ") GROUP BY height.lid, height.value) " + + "AS foo " + + "GROUP BY foo.lid, foo.value, foo.maxtime order by foo.lid, foo.maxtime desc"; + + private static String riverFcstvalueQueryFront = "SELECT distinct(foo.lid), foo.value, foo.maxtime from " + + "(SELECT distinct fcstheight.lid, fcstheight.value, max(fcstheight.validtime) as maxtime " + + "FROM fcstheight " + + "WHERE fcstheight.lid in " + + "(select distinct(lid) " + + "from rivermonlocation " + + "where rivermonlocation.group_id = "; + + private static String riverFcstvalueQueryBack = ") GROUP BY fcstheight.lid, fcstheight.value) " + + "AS foo " + + "GROUP BY foo.lid, foo.value, foo.maxtime order by foo.lid, foo.maxtime desc"; + + private static String riverIDQuery = "SELECT group_id FROM rivermonlocation where lid ="; + + /** + * River Query Crest + * + * @param lid + * @return CrestHistoryData + */ + public CrestHistoryData getRiverCrests(RiverDataPoint rdp, int allFlag) { + CrestHistoryData crests = null; + + if (crestData == null) { + crestData = new LinkedHashMap(); + } + + crests = new CrestHistoryData(); + String query = null; + + /* get crest data depending on action stage */ + if (rdp != null) { + String sql = "select stage, q, datcrst, timcrst, cremark, hw, jam, olddatum, suppress, prelim " + + "from crest where lid = '" + rdp.getLid(); + + if (allFlag == 1) { + query = sql + "' and stage >'" + rdp.getActionStage() + + "' ORDER BY stage, q"; + } else if (allFlag == 2) { + query = sql + "' and stage <'" + rdp.getActionStage() + + "' ORDER BY stage, q"; + } else { + query = sql + "' ORDER BY stage, q"; + } + + ArrayList objects = null; + + try { + objects = (ArrayList) DirectDbQuery.executeQuery( + query, HydroConstants.IHFS, QueryLanguage.SQL); + if (objects != null) { + for (Object[] crestob : objects) { + crests.addCrestData(new CrestData(crestob)); + } + } + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + e); + } + } + + if (crests.getCrestDataArray().size() > 0) { + // max stage level, default sort mode + // There is a problem when the stage is not set in the db. + // Added this work around here to manually find the max stage value + double maxStag = 0; + double minStag = Double.MAX_VALUE; + for (int i = 0; i < crests.getCrestDataArray().size(); i++) { + if (crests.getCrestDataArray().get(i).getStage() > maxStag) { + maxStag = crests.getCrestDataArray().get(i).getStage(); + } + if (crests.getCrestDataArray().get(i).getStage() < minStag && + crests.getCrestDataArray().get(i).getStage() >= 0) { + minStag = crests.getCrestDataArray().get(i).getStage(); + } + + } + crests.setMaxStageLevel(maxStag); + crests.setMinStageLevel(minStag); + + // set the values to gage by + crests.setActionLevel(rdp.getActionStage()); + crests.setMajorLevel(rdp.getMajorStage()); + crests.setMinorLevel(rdp.getMinorStage()); + crests.setModerateLevel(rdp.getModerateStage()); + + // we assume a top of zero at all times, find oldest record + crests.sortByDate(); + CrestData cd5 = crests.getCrestDataArray().get( + crests.getCrestDataArray().size() - 1); + + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + Date now = SimulatedTime.getSystemTime().getTime(); + cal.setTime(now); + + if (cd5.getCrestDate() != null) { + crests.setStartingYear(cd5.getCrestDate().get(Calendar.YEAR)); + } else { + crests.setStartingYear(HydroConstants.DEFAULT_YEAR); + } + crests.setEndingYear(cal.get(Calendar.YEAR)); + + crests.sortByStage(); + + crestData.put(rdp.getLid(), crests); + } + + return crests; + } + + /** + * Gets the crest data for just the record flood, flow + * + * @param rdp + * @return + */ + public RiverDataPoint getRiverCrest(RiverDataPoint rdp) { + Date date = SimulatedTime.getSystemTime().getTime(); + int allFlag = 0; + CrestHistoryData crests = getRiverCrests(rdp, allFlag); + ArrayList temp = crests.getCrestDataArray(); + if (temp.size() > 0) { + // maximum stage value + crests.sortByStage(); + CrestData cd = temp.get(0); + rdp.setCrestValue(cd.getStage()); + + // maximum flow (q) value for max stage value + rdp.setCrestFlow(cd.getFlow()); + + // Stage Crest date + rdp.setCrestTime(cd.getCrestDate()); + + } else { + // maximum stage value + rdp.setCrestValue(HydroConstants.MISSING_VALUE); + + // maximum flow value + rdp.setCrestFlow(HydroConstants.MISSING_VALUE); + + // sort by date + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + cal.setTime(date); + rdp.setCrestTime(cal); + } + + return rdp; + } + + /** + * data structure to house the river water shed data + * + * @return HashMap> + */ + public LinkedHashMap> getRiverSummaryData() { + ArrayList data = null; + + try { + data = (ArrayList) DirectDbQuery.executeQuery( + riverPointQuery, HydroConstants.IHFS, QueryLanguage.SQL); + if (data != null) { + riverData = new LinkedHashMap>(); + String riverID = null; + LinkedHashMap riverPoints = null; + for (Object[] point : data) { + RiverDataPoint rdp = new RiverDataPoint(point); + // start + if (riverID == null) { + riverID = rdp.getRiverID(); + riverPoints = new LinkedHashMap(); + riverPoints.put(rdp.getLid(), rdp); + } + // new river switch + else if (!rdp.getRiverID().equals(riverID)) { + // sock away the old one + riverData.put(riverID, riverPoints); + // rename Name + riverID = rdp.getRiverID(); + // create new + riverPoints = new LinkedHashMap(); + riverPoints.put(rdp.getLid(), rdp); + } + // in river run + else { + riverPoints.put(rdp.getLid(), rdp); + } + } + // take care of last river + riverData.put(riverID, riverPoints); + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + + return riverData; + } + + /** + * Populate the Data for time and point obs and fcst, really not pretty + * avert your eyes. + * + * @param riverPoints + * @param riverID + * @return HashMap + */ + public LinkedHashMap populateRiverData( + String riverID, LinkedHashMap riverPoints) { + + ArrayList obsdata = null; + ArrayList fcstdata = null; + + try { + String obsquery = riverObsvalueQueryFront + "'" + riverID + "'" + + riverObsvalueQueryBack; + String fcstquery = riverFcstvalueQueryFront + "'" + riverID + "'" + + riverFcstvalueQueryBack; + obsdata = (ArrayList) DirectDbQuery.executeQuery( + obsquery, HydroConstants.IHFS, QueryLanguage.SQL); + fcstdata = (ArrayList) DirectDbQuery.executeQuery( + fcstquery, HydroConstants.IHFS, QueryLanguage.SQL); + if (obsdata != null) { + String lid = null; + Calendar obstime = null; + + for (Object[] obspoint : obsdata) { + if (obspoint[0] != null) { + String newlid = (String) obspoint[0]; + // into + if (!newlid.equals(lid) || (lid == null)) { + lid = newlid; + // we care about this data + if (obspoint[1] != null) { + riverPoints.get(lid).setObsValue( + (Double) obspoint[1]); + } + if (obspoint[2] != null) { + obstime = Calendar.getInstance(TimeZone + .getTimeZone("GMT")); + obstime.setTimeInMillis(((Timestamp) obspoint[2]) + .getTime()); + riverPoints.get(lid).setObsTime(obstime); + } + } + } + } + } + if (fcstdata != null) { + String lid = null; + Calendar fcsttime = null; + + for (Object[] fcstpoint : fcstdata) { + if (fcstpoint[0] != null) { + String newlid = (String) fcstpoint[0]; + // into + if (!newlid.equals(lid) || (lid == null)) { + lid = newlid; + // we care about this data + if (fcstpoint[1] != null) { + riverPoints.get(lid).setFcstValue( + (Double) fcstpoint[1]); + } + if (fcstpoint[2] != null) { + fcsttime = Calendar.getInstance(TimeZone + .getTimeZone("GMT")); + fcsttime.setTimeInMillis(((Timestamp) fcstpoint[2]) + .getTime()); + riverPoints.get(lid).setFcstTime(fcsttime); + } + } + } + } + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + + return riverPoints; + } + + /** + * Gets the RiverID for the GageData + * + * @param lid + * @return + */ + public String getRiverID(String lid) { + String riverID = null; + + try { + ArrayList riverObject = (ArrayList) DirectDbQuery + .executeQuery(riverIDQuery + "'" + lid + "'", + HydroConstants.IHFS, QueryLanguage.SQL); + + if (riverObject.size() > 0) { + riverID = (String) (riverObject.get(0))[0]; + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + + return riverID; + } + + /** + * Get an individual River Data Point + * + * @param lid + * @return + */ + public RiverDataPoint getRiverDataPoint(String lid) { + + // Get the location information first + RiverDataPoint rdp = new RiverDataPoint(lid); + try { + ArrayList locationObject = (ArrayList) DirectDbQuery + .executeQuery(locationQuery + "'" + lid + "'", + HydroConstants.IHFS, QueryLanguage.SQL); + if (locationObject.size() == 1) { + Object[] location = locationObject.get(0); + if ((String) location[0] != null) { + rdp.setLocName((String) location[0]); + } + if ((String) location[1] != null) { + rdp.setCounty((String) location[1]); + } + if ((String) location[2] != null) { + rdp.setState((String) location[2]); + } + if ((Double) location[3] != null) { + rdp.setElevation((Double) location[3]); + } + if ((String) location[4] != null) { + rdp.setHsa((String) location[4]); + } + if ((Double) location[5] != null) { + rdp.setLat((Double) location[5]); + } + if ((Double) location[6] != null) { + rdp.setLon((Double) location[6]); + } + if ((String) location[7] != null) { + rdp.setRiverName((String) location[7]); + } + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + // next find the river stat values + try { + ArrayList statObject = (ArrayList) DirectDbQuery + .executeQuery(riverStatQuery + "'" + lid + "'", + HydroConstants.IHFS, QueryLanguage.SQL); + if (statObject.size() == 1) { + Object[] stat = statObject.get(0); + if ((String) stat[0] != null) { + rdp.setStreamName((String) stat[0]); + } + if ((Double) stat[1] != null) { + rdp.setMile((Double) stat[1]); + } + if ((Double) stat[2] != null) { + rdp.setZeroDatum((Double) stat[2]); + } + if ((String) stat[3] != null) { + rdp.setTide((String) stat[3]); + } + if ((Double) stat[4] != null) { + rdp.setBankFull((Double) stat[4]); + } + if ((Double) stat[5] != null) { + rdp.setActionStage((Double) stat[5]); + } + if ((Double) stat[6] != null) { + rdp.setFloodStage((Double) stat[6]); + } + if ((Double) stat[7] != null) { + rdp.setFloodFlow((Double) stat[7]); + } + if ((Double) stat[8] != null) { + rdp.setActionFlow((Double) stat[8]); + } + if ((String) stat[9] != null) { + rdp.setPrimaryPE((String) stat[9]); + } + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + // next find the description values + try { + ArrayList descripObject = (ArrayList) DirectDbQuery + .executeQuery(descriptionQuery + "'" + lid + "'", + HydroConstants.IHFS, QueryLanguage.SQL); + if (descripObject.size() == 1) { + Object[] descrip = descripObject.get(0); + if ((String) descrip[0] != null) { + rdp.setProximity((String) descrip[0]); + } + if ((String) descrip[1] != null) { + rdp.setReach((String) descrip[1]); + } + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + // get data for the flood categories + try { + ArrayList floodObject = (ArrayList) DirectDbQuery + .executeQuery(floodCatQuery + "'" + lid + "'", + HydroConstants.IHFS, QueryLanguage.SQL); + if (floodObject.size() == 1) { + Object[] flood = floodObject.get(0); + if ((Double) flood[0] != null) { + rdp.setMinorStage((Double) flood[0]); + } + if ((Double) flood[1] != null) { + rdp.setModerateStage((Double) flood[1]); + } + if ((Double) flood[2] != null) { + rdp.setMajorStage((Double) flood[2]); + } + if ((Double) flood[3] != null) { + rdp.setMinorFlow((Double) flood[3]); + } + if ((Double) flood[4] != null) { + rdp.setModerateFlow((Double) flood[4]); + } + if ((Double) flood[5] != null) { + rdp.setMajorFlow((Double) flood[5]); + } + } + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + // Get data for Crest information + try { + CrestHistoryData crests = new CrestHistoryData(); + ArrayList crestList = crests.getCrestDataArray(); + + ArrayList crestObject = (ArrayList) DirectDbQuery + .executeQuery(crestQuery + lid + "' ORDER BY stage, q", + HydroConstants.IHFS, QueryLanguage.SQL); + + if (crestObject != null) { + for (Object[] crestob : crestObject) { + crests.addCrestData(new CrestData(crestob)); + } + } + if (crestList.size() > 0) { + crests.sortByStage(); + CrestData cd = crestList.get(0); + + rdp.setCrestValue(cd.getStage()); + rdp.setCrestFlow(cd.getFlow()); + rdp.setCrestTime(cd.getCrestDate()); + } + + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + // get data for the river information + try { + ArrayList riverInfoObject = (ArrayList) DirectDbQuery + .executeQuery(riverInfoQuery + "'" + lid + "'", + HydroConstants.IHFS, QueryLanguage.SQL); + if (riverInfoObject.size() == 1) { + Object[] riverInfo = riverInfoObject.get(0); + if ((String) riverInfo[0] != null) { + rdp.setRiverID((String) riverInfo[0]); + } + } + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + + return rdp; + } + + public String getStreamName(String lid) { + List results = null; + String stream = null; + try { + results = DirectDbQuery.executeQuery( + "select stream from riverstat where lid = '" + lid + "'", + HydroConstants.IHFS, QueryLanguage.SQL); + if ((results != null) && (results.size() > 0)) { + stream = (String) results.get(0)[0]; + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + + return stream; + } + + /** + * Get the Statprof data for the specified stream. + * + * @param stream + * The stream + * @return The statprof data for the stream. + */ + public List getStatProf(String stream) { + // String query = "from " + // + com.raytheon.edex.plugin.shef.objects.Statprof.class + // .getName(); + // query += " where stream = '" + stream + "' order by mile desc"; + String query = "select lid, name, primary_pe, stream, fs, wstg, fq, " + + "action_flow, zd, mile, reach, proximity from statprof " + + "where stream = '" + stream + "' order by mile desc"; + + List dataList = new ArrayList(); + try { + List results = DirectDbQuery.executeQuery(query, + HydroConstants.IHFS, QueryLanguage.SQL); + if ((results != null) && (results.size() > 0)) { + for (Object[] oa : results) { + if (oa[0] != null) { + // dataList.add((Statprof) oa[0]); + Statprof sp = new Statprof(); + StatprofId spid = new StatprofId(); + spid.setLid((String) oa[0]); + spid.setName((String) oa[1]); + spid.setPrimaryPe((String) oa[2]); + spid.setStream((String) oa[3]); + spid.setFs((Double) oa[4]); + spid.setWstg((Double) oa[5]); + spid.setFq((Double) oa[6]); + spid.setActionFlow((Double) oa[7]); + spid.setZd((Double) oa[8]); + spid.setMile((Double) oa[9]); + spid.setReach((String) oa[10]); + spid.setProximity((String) oa[11]); + sp.setId(spid); + + // Check for missing data values + if (spid.getPrimaryPe() == null) { + continue; + } else if (spid.getPrimaryPe().startsWith("H")) { + if ((spid.getFs() == null) + || (spid.getWstg() == null)) { + continue; + } + } else { + if ((spid.getFq() == null) + || (spid.getActionFlow() == null)) { + continue; + } + } + dataList.add(sp); + } + } + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + + return dataList; + } + + public ArrayList getRiverStatus(String lid, String pe, + long validTime, long basisTime) { + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date validTimeDate = new Date(); + validTimeDate.setTime(validTime); + String validTimeStr = sdf.format(validTimeDate); + Date basisTimeDate = new Date(); + basisTimeDate.setTime(basisTime); + String basisTimeStr = sdf.format(basisTimeDate); + + String where = " where lid = '" + lid + "' " + "and pe = '" + pe + + "' and (validTime > '" + validTimeStr + + "' or ts like 'F%%') and " + + "basisTime is null or basistime >= '" + basisTimeStr + "')"; + + String query = "from " + + com.raytheon.uf.common.dataplugin.shef.tables.Riverstatus.class + .getName(); + query += where; + + ArrayList dataList = null; + try { + List results = DirectDbQuery.executeQuery(query, + HydroConstants.IHFS, QueryLanguage.HQL); + if ((results != null) && (results.size() > 0)) { + dataList = new ArrayList(); + for (Object[] oa : results) { + dataList.add((Riverstatus) oa[0]); + } + } + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + + return dataList; + } + + public List getTsList() { + List rs = null; + + String query = "select distinct(ts), ts_rank from ingestfilter"; + + try { + rs = DirectDbQuery.executeQuery(query, HydroConstants.IHFS, + QueryLanguage.SQL); + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } + + return rs; + } } diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/IRatingCurveSort.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/IRatingCurveSort.java deleted file mode 100644 index e4d299537c..0000000000 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/IRatingCurveSort.java +++ /dev/null @@ -1,45 +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.viz.hydrocommon.ratingcurve; - -/** - * Interface for getting the sort type for the rating curve data. - * - *
- *
- * SOFTWARE HISTORY
- *
- * Date        Ticket#     Engineer Description
- * ------------   ----------  ----------- --------------------------
- *24 Nov, 2008    1628      dhladky  Initial creation
- * 
- * 
- * - * @author dhladky - * @version 1.0 - */ -public interface IRatingCurveSort -{ - /** - * Get the sort type. - * @return The sort type. - */ - String getSortType(); -} \ No newline at end of file diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveData.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveData.java index 3ec557f301..d917f3a8e9 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveData.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveData.java @@ -167,4 +167,44 @@ public class RatingCurveData implements Comparable return ret; } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(discharge); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(stage); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + /* + * (non-Javadoc) + * + * @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; + RatingCurveData other = (RatingCurveData) obj; + if (Double.doubleToLongBits(discharge) != Double + .doubleToLongBits(other.discharge)) + return false; + if (Double.doubleToLongBits(stage) != Double + .doubleToLongBits(other.stage)) + return false; + return true; + } } diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveDlg.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveDlg.java index 1fbe6264bc..12f37e144c 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveDlg.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveDlg.java @@ -38,12 +38,12 @@ import org.eclipse.core.runtime.Status; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; 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.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Layout; @@ -77,7 +77,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * @author lvenable * @version 1.0 */ -public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { +public class RatingCurveDlg extends CaveSWTDialog { /** * Control font. @@ -229,18 +229,6 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { */ private Button saveBtn; - /** - * Sort by enumeration. - */ - private enum sortBy { - Stage, Discharge - }; - - /** - * Sort by - */ - private sortBy sortKey; - /** * Dialog lid information. */ @@ -285,11 +273,6 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { */ private RatingCurveShiftData selectedRatingShift = null; - /** - * The current selected rating point - */ - private RatingCurveData selectedRatingPoint = null; - /** * Shift amount */ @@ -488,91 +471,6 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { df.setMaximumFractionDigits(2); df.setMaximumIntegerDigits(3); - shiftDataList.addSelectionListener(new SelectionListener() { - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - int index = 0; // default - RatingCurveShiftData rcsd = shiftData.get(index); - - shiftValueTF.setText(df.format(rcsd.getValue())); - shiftDateTF.setText(sdf.format(rcsd.getDate().getTime())); - shiftActiveChk.setSelection(rcsd.isActive()); - generateShiftList(rcsd); - setSelectedShift(rcsd); - - if (shiftActiveChk.getSelection()) { - // redraw the canvas with shifted data - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } - } - - @Override - public void widgetSelected(SelectionEvent e) { - int index = shiftDataList.getSelectionIndex(); - setSelectedShift(shiftData.get(index)); - RatingCurveShiftData rcsd = shiftData.get(index); - - shiftValueTF.setText(df.format(rcsd.getValue())); - shiftDateTF.setText(sdf.format(rcsd.getDate().getTime())); - shiftActiveChk.setSelection(rcsd.isActive()); - - if (shiftActiveChk.getSelection()) { - // redraw the canvas with shifted data - generateShiftList(getEditingShiftData()); - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } - } - - }); - - shiftActiveChk.addSelectionListener(new SelectionListener() { - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - // redraw the canvas with shifted data - if ((shiftData.size() > 0) && (shiftDataList != null)) { - int index = 0; - RatingCurveShiftData rcsd = shiftData.get(index); - if (rcsd.isActive()) { - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); - shiftActiveChk.setSelection(rcsd.isActive()); - } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } - } - } - - @Override - public void widgetSelected(SelectionEvent e) { - // redraw the canvas with shifted data - if ((shiftData.size() > 0) - && (shiftDataList.getSelectionIndex() != -1)) { - RatingCurveShiftData rcsd = shiftData.get(shiftDataList - .getSelectionIndex()); - generateShiftList(rcsd); - if (rcsd.isActive()) { - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } - } - } - - }); - // -------------------------------------------------------- // Create the Shift Remove & Update/Insert buttons // -------------------------------------------------------- @@ -589,25 +487,7 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { shftRemoveBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - if (getEditingShiftData() != null) { - int index = shiftDataList.getSelectionIndex(); - removedCurveShifts.add(getEditingShiftData()); - shiftData.remove(index); - selectedRatingShift = null; - - shiftDataList.removeAll(); - for (RatingCurveShiftData rcsd : shiftData) { - shiftDataList.add(getShiftListString(rcsd)); - } - shiftDataList.redraw(); - - shiftValueTF.setText(""); - shiftDateTF.setText(""); - shiftActiveChk.setSelection(false); - // default without shifting - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } + removeShift(); } }); @@ -656,25 +536,31 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { curveClearAllBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - // get rid of every point - removedPoints = noShiftCurveArray; - noShiftCurveArray.clear(); - noShiftCurveDataList.removeAll(); - noShiftCurveDataList.redraw(); + MessageBox messageDialog = new MessageBox(shell, SWT.OK | SWT.CANCEL); + messageDialog.setText("Clear Confirmation"); + messageDialog.setMessage("This will clear the list for " + lid + "."); + int response = messageDialog.open(); - if (shiftCurveArray != null) { - shiftCurveArray.clear(); - shiftCurveDataList.removeAll(); - shiftCurveDataList.redraw(); + if (response == SWT.OK) { + // get rid of every point + removedPoints = noShiftCurveArray; + noShiftCurveArray.clear(); + noShiftCurveDataList.removeAll(); + noShiftCurveDataList.redraw(); + + if (shiftCurveArray != null) { + shiftCurveArray.clear(); + } + shiftCurveDataList.removeAll(); + shiftCurveDataList.redraw(); + + stageTF.setText(""); + dischargeTF.setText(""); + selectedRatingShift = null; + + ratingCurveCanvas.updateCurveData(noShiftCurveArray, floodDbl, + recordDbl, shiftAmount); } - - stageTF.setText(""); - dischargeTF.setText(""); - selectedRatingShift = null; - selectedRatingPoint = null; - - ratingCurveCanvas.updateCurveData(noShiftCurveArray, floodDbl, - recordDbl, shiftAmount); } }); @@ -686,20 +572,28 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { @Override public void widgetSelected(SelectionEvent event) { if (noShiftCurveDataList.getSelectionIndex() != -1) { - // get rid of this point - int index = noShiftCurveDataList.getSelectionIndex(); - removedPoints.add(noShiftCurveArray.remove(index)); - remakeRatingCurveDataList(); + MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION + | SWT.OK | SWT.CANCEL); + mb.setText("Remove Base Rating Point Confirmation"); + mb.setMessage("This will remove the highlighted pair."); + int response = mb.open(); - stageTF.setText(""); - dischargeTF.setText(""); + if (response == SWT.OK) { + // get rid of this point + int index = noShiftCurveDataList.getSelectionIndex(); + removedPoints.add(noShiftCurveArray.remove(index)); + remakeRatingCurveDataList(); - if (getEditingShiftData() != null) { - generateShiftList(getEditingShiftData()); - } + stageTF.setText(""); + dischargeTF.setText(""); - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); + if (getEditingShiftData() != null) { + generateShiftList(getEditingShiftData()); + } + + ratingCurveCanvas.updateCurveData(noShiftCurveArray, + floodDbl, recordDbl, shiftAmount); + } } } }); @@ -712,47 +606,10 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { @Override public void widgetSelected(SelectionEvent event) { if (verifyDouble(stageTF) && verifyInt(dischargeTF)) { - RatingCurveData rcd = new RatingCurveData(new Double( stageTF.getText().trim()), new Double(dischargeTF .getText().trim())); - - if (noShiftCurveDataList != null) { - if (getEditingCurveData() != null) { - int index = noShiftCurveDataList - .getSelectionIndex(); - if (index > -1) { - noShiftCurveArray.remove(index); - noShiftCurveDataList.remove(index); - } - } - } - - if (!addedPoints.contains(rcd)) { - addedPoints.add(rcd); - } else { - addedPoints.remove(rcd); - addedPoints.add(rcd); - } - - noShiftCurveArray.add(rcd); - remakeRatingCurveDataList(); - - if (getEditingShiftData() != null) { - if (getEditingShiftData().isActive()) { - int index = shiftDataList.getSelectionIndex(); - generateShiftList(shiftData.get(index)); - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } else { - ratingCurveCanvas.updateCurveData( - noShiftCurveArray, floodDbl, recordDbl, - shiftAmount); - } - } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } + insertBaseCurvePoint(rcd); } } }); @@ -769,6 +626,49 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { shiftValueTF.setEditable(true); } } + + private void insertBaseCurvePoint(RatingCurveData rcd) { + if (!noShiftCurveArray.contains(rcd)) { + // Check for a matching stage value + RatingCurveData data = null; + for (RatingCurveData d: noShiftCurveArray) { + if (d.getStage() == rcd.getStage()) { + data = d; + break; + } + } + + if (data != null) { + noShiftCurveArray.remove(data); + } + + noShiftCurveArray.add(rcd); + if (!addedPoints.contains(rcd)) { + addedPoints.add(rcd); + } else { + addedPoints.remove(rcd); + addedPoints.add(rcd); + } + + remakeRatingCurveDataList(); + + if (getEditingShiftData() != null) { + if (getEditingShiftData().isActive()) { + int index = shiftDataList.getSelectionIndex(); + generateShiftList(shiftData.get(index)); + ratingCurveCanvas.updateCurveData(shiftCurveArray, + floodDbl, recordDbl, shiftAmount); + } else { + ratingCurveCanvas.updateCurveData( + noShiftCurveArray, floodDbl, recordDbl, + shiftAmount); + } + } else { + ratingCurveCanvas.updateCurveData(noShiftCurveArray, + floodDbl, recordDbl, shiftAmount); + } + } + } /** * Create the controls on the right side of the dialog. @@ -789,10 +689,17 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { createStageDischargeLabels(rightComp); gd = new GridData(220, 400); - shiftCurveDataList = new List(rightComp, SWT.BORDER | SWT.SINGLE - | SWT.V_SCROLL); + shiftCurveDataList = new List(rightComp, SWT.BORDER | SWT.V_SCROLL); shiftCurveDataList.setFont(controlFont); shiftCurveDataList.setLayoutData(gd); + shiftCurveDataList.deselectAll(); + shiftCurveDataList.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GRAY)); + shiftCurveDataList.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + shiftCurveDataList.deselectAll(); + } + }); gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false); ratingLbl = new Label(rightComp, SWT.CENTER); @@ -804,17 +711,6 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { | SWT.V_SCROLL); noShiftCurveDataList.setFont(controlFont); noShiftCurveDataList.setLayoutData(gd); - - if (noShiftCurveArray != null) { - // populate the list - for (RatingCurveData curve : noShiftCurveArray) { - noShiftCurveDataList.add(curve.toString()); - } - noShiftCurveDataList.setEnabled(true); - } else { - noShiftCurveDataList.setEnabled(false); - } - noShiftCurveDataList.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -823,10 +719,27 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { stageTF.setText(String.format("%7.2f", data.getStage())); dischargeTF .setText(String.format("%7.1f", data.getDischarge())); - setSelectedCurveData(data); } }); + if (noShiftCurveArray != null) { + // populate the list + RatingCurveShiftData currentShift = null; + if (shiftData != null && shiftData.size() > 0) { + if (shiftData.get(0).isActive()) { + currentShift = shiftData.get(0); + } + } + + for (RatingCurveData curve : noShiftCurveArray) { + noShiftCurveDataList.add(curve.toString()); + } + if (noShiftCurveDataList.getItemCount() > 0) { + noShiftCurveDataList.select(0); + generateShiftList(currentShift); + } + } + createStageDischargeTextFields(rightComp); } @@ -987,7 +900,12 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { if (label != null) { ratingLbl.setText(label); } - + + if (noShiftCurveArray.size() > 0) { + RatingCurveData rcd = noShiftCurveArray.get(0); + this.stageTF.setText(String.valueOf(rcd.getStage())); + this.dischargeTF.setText(String.valueOf(rcd.getDischarge())); + } } /** @@ -1052,10 +970,10 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { * @param rcsd */ public void generateShiftList(RatingCurveShiftData rcsd) { + shiftCurveDataList.removeAll(); if (rcsd != null) { shiftAmount = rcsd.getValue(); - shiftCurveDataList.removeAll(); shiftCurveArray = new ArrayList(); // remake the rating curve with shift data @@ -1067,38 +985,14 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { } // redraw for the full effect shiftCurveDataList.redraw(); + } else { + // make the rating curve with no shift data + for (RatingCurveData curve : noShiftCurveArray) { + shiftCurveDataList.add(curve.toString()); + } } } - @Override - public String getSortType() { - // TODO Auto-generated method stub - return "Stage"; - } - - /** - * Sort the crest data by stage value. - */ - public void sortByStage() { - sortKey = sortBy.Stage; - sortCurveData(); - } - - /** - * Sort the crest data by flow value. - */ - public void sortByDischarge() { - sortKey = sortBy.Discharge; - sortCurveData(); - } - - /** - * Sort the curve data. - */ - private void sortCurveData() { - Collections.sort(noShiftCurveArray); - } - /** * Imports a rating curve * @@ -1268,51 +1162,101 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { RatingCurveShiftData rcsd = new RatingCurveShiftData(lid, cal, new Double(shiftValueTF.getText()), shiftActiveChk .getSelection()); - // remove old - if (shiftDataList != null) { - int index = shiftDataList.getSelectionIndex(); - if (index != -1) { - if (rcsd.getDate().getTime().equals( - shiftData.get(index).getDate().getTime())) { - shiftDataList.remove(index); - shiftData.remove(index); - } - } else { - for (int i = 0; i < shiftData.size(); i++) { - RatingCurveShiftData data = shiftData.get(i); - if (data.getDate().getTime().equals(cal.getTime())) { - shiftData.remove(i); - shiftDataList.remove(i); - i--; - } - } - } + + if (shiftData.size() > 0 && shiftData.contains(rcsd)) { + for (RatingCurveShiftData sd: shiftData) { + if (rcsd.toString().equals(sd.toString())) { + sd.setActive(rcsd.isActive()); + sd.setDate(rcsd.getDate()); + sd.setLid(rcsd.getLid()); + sd.setValue(rcsd.getValue()); + break; + } + } + } else { + shiftData.add(rcsd); } - + if (!addedCurveShifts.contains(rcsd)) { - addedCurveShifts.add(rcsd); + addedCurveShifts.add(rcsd); } else { - addedCurveShifts.remove(rcsd); - addedCurveShifts.add(rcsd); + addedCurveShifts.remove(rcsd); + addedCurveShifts.add(rcsd); } - shiftData.add(rcsd); - shiftDataList.add(getShiftListString(rcsd)); - shiftDataList.redraw(); + shiftDataList.removeAll(); + Collections.sort(shiftData); - if (shiftActiveChk.getSelection()) { - generateShiftList(rcsd); - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); + for (RatingCurveShiftData sd: shiftData) { + shiftDataList.add(getShiftListString(sd)); + } + + // Display the latest shift + RatingCurveShiftData currentShift = shiftData.get(0); + if (currentShift.isActive()) { + generateShiftList(currentShift); + ratingCurveCanvas.updateCurveData(shiftCurveArray, + floodDbl, recordDbl, currentShift.getValue()); } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); + ratingCurveCanvas.updateCurveData(noShiftCurveArray, + floodDbl, recordDbl, 0); } } + + shiftValueTF.setText(""); + shiftDateTF.setText(""); + shiftActiveChk.setSelection(false); } catch (Exception e) { e.printStackTrace(); } } + + private void removeShift() { + if (shiftDataList.getItemCount() > 0 && shiftDataList.getSelectionCount() > 0) { + MessageBox messageDialog = new MessageBox(shell, SWT.OK | SWT.CANCEL); + messageDialog.setText("Shift Remove Confirmation"); + messageDialog.setMessage("This will remove the highlighted shift."); + int response = messageDialog.open(); + + if (response == SWT.OK) { + String selection = shiftDataList.getItem(shiftDataList.getSelectionIndex()); + for (RatingCurveShiftData sd: shiftData) { + if (getShiftListString(sd).equals(selection)) { + removedCurveShifts.add(sd); + break; + } + } + + shiftData.removeAll(removedCurveShifts); + shiftDataList.removeAll(); + Collections.sort(shiftData); + for (RatingCurveShiftData rcsd : shiftData) { + shiftDataList.add(getShiftListString(rcsd)); + } + shiftDataList.redraw(); + + if (shiftData.size() > 0) { + shiftAmount = shiftData.get(0).getValue(); + } else { + shiftAmount = 0; + } + + ratingCurveCanvas.updateCurveData(noShiftCurveArray, + floodDbl, recordDbl, shiftAmount); + + if (shiftData.size() > 0) { + RatingCurveShiftData currentShift = shiftData.get(0); + if (currentShift.isActive()) { + generateShiftList(currentShift); + } else { + generateShiftList(null); + } + } else { + generateShiftList(null); + } + } + } + } /** * Verify validity of input @@ -1371,44 +1315,40 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { return selectedRatingShift; } - /** - * set the current curve shift - * - * @param selectedRatingShift - */ - private void setSelectedShift(RatingCurveShiftData selectedRatingShift) { - this.selectedRatingShift = selectedRatingShift; - } - - /** - * Get the editing curve data - * - * @return - */ - private RatingCurveData getEditingCurveData() { - return selectedRatingPoint; - } - - /** - * Sets the selected curve data - * - * @param selectedRatingPoint - */ - private void setSelectedCurveData(RatingCurveData selectedRatingPoint) { - this.selectedRatingPoint = selectedRatingPoint; - } - /** * update the noShiftCurveDataList */ private void remakeRatingCurveDataList() { - - sortCurveData(); + Collections.sort(noShiftCurveArray); + int index = noShiftCurveDataList.getSelectionIndex(); noShiftCurveDataList.removeAll(); + shiftCurveDataList.removeAll(); for (RatingCurveData rcd : noShiftCurveArray) { noShiftCurveDataList.add(rcd.toString()); } - noShiftCurveDataList.redraw(); + + if (shiftData.size() > 0) { + RatingCurveShiftData currentShift = shiftData.get(0); + if (currentShift.isActive()) { + generateShiftList(currentShift); + } else { + remakeRatingCurveDataList(); + } + } else { + remakeRatingCurveDataList(); + } + + if (noShiftCurveDataList.getItemCount() > 0) { + if (index >= noShiftCurveDataList.getItemCount()) { + noShiftCurveDataList.select(noShiftCurveDataList.getItemCount() - 1); + } else if (index >= 0 && index < noShiftCurveArray.size()) { + noShiftCurveDataList.select(index); + } else { + noShiftCurveDataList.select(0); + } + noShiftCurveDataList.showSelection(); + + } } /** diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveShiftData.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveShiftData.java index 564b6474d3..756993d02f 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveShiftData.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveShiftData.java @@ -40,7 +40,7 @@ import java.util.TimeZone; * @version 1.0 */ -public class RatingCurveShiftData { +public class RatingCurveShiftData implements Comparable { private String lid = null; @@ -90,18 +90,34 @@ public class RatingCurveShiftData { public String getLid() { return lid; } + + public void setLid(String lid) { + this.lid = lid; + } public Calendar getDate() { return date; } + + public void setDate(Calendar date) { + this.date = date; + } public double getValue() { return value; } + public void setValue(double value) { + this.value = value; + } + public boolean isActive() { return active; } + + public void setActive(boolean active) { + this.active = active; + } /** * Get the date in a MM/DD/YYYY format. @@ -125,4 +141,16 @@ public class RatingCurveShiftData { return sb.toString(); } + + @Override + public int compareTo(RatingCurveShiftData o) { + if (this.date.getTime().equals(o.getDate().getTime())) { + return 0; + } else if (this.date.getTime().before(o.getDate().getTime())) { + return 1; + } else if (this.date.getTime().after(o.getDate().getTime())) { + return -1; + } + return 0; + } } diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/FFGGridResource.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/FFGGridResource.java index 4afad9088b..6d12ba1311 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/FFGGridResource.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/resource/FFGGridResource.java @@ -141,7 +141,7 @@ public class FFGGridResource extends String user_id = System.getProperty("user.name"); this.duration = data.getDuration(); colorSet = HydroDisplayManager.getInstance().getFFGColorMap(user_id, - "FFG", duration * 60 * 1000); + "FFG", duration); loadData(); } @@ -260,7 +260,7 @@ public class FFGGridResource extends sdf.setTimeZone(TimeZone.getTimeZone("GMT")); int hours = this.resourceData.getDuration() - / HydroConstants.MILLIS_PER_HOUR; + / HydroConstants.SECONDS_PER_HOUR; String hourStr = "hour"; if (hours != 1) { hourStr = hourStr.concat("s"); diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/whfslib/GagePPWrite.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/whfslib/GagePPWrite.java index 0b00304560..40267ea053 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/whfslib/GagePPWrite.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/whfslib/GagePPWrite.java @@ -54,6 +54,7 @@ import com.raytheon.viz.hydrocommon.whfslib.GagePPOptions.upd_action; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 5, 2008 1649 snaples Initial creation + * Aug 8, 2012 15271 snaples Updated hourly slot * * * @@ -140,12 +141,6 @@ public final class GagePPWrite { String obstime = sdf.format(dto); GagePPOptions opts = options; int hr = dt.get(Calendar.HOUR_OF_DAY); - if (hr == 0) { - hr = 24; - dt.add(Calendar.HOUR_OF_DAY, -1); - obstime = sdf.format(dt); - dto = dt.getTime(); - } int min = dt.get(Calendar.MINUTE); char sixhroffset = get_offset_code(min); char sixhrqc = 'M'; @@ -212,7 +207,7 @@ public final class GagePPWrite { pHourpp.setSixhroffset(String.valueOf(sixhr_offset)); pHourpp.setSixhrqc(String.valueOf(sixhr_qc)); set_hour_slot_value(pHourpp, hr, new_hourly_value); - set_6hour_slot_value(pHourpp, six + 1, pp_value); + set_6hour_slot_value(pHourpp, six, pp_value); update_gage_rec(pHourpp); } @@ -283,7 +278,7 @@ public final class GagePPWrite { if (hpp.getSixhrqc() != null) { old_six_qc = hpp.getSixhrqc().toCharArray(); } - Short sixval = get_6hour_slot_value(hpp, six + 1); + Short sixval = get_6hour_slot_value(hpp, six); prev_sixhroff = old_sixhroffset[six]; prev_sixqc = old_six_qc[six]; @@ -363,7 +358,7 @@ public final class GagePPWrite { pHourpp.setSixhroffset(String.valueOf(sixhr_offset)); pHourpp.setSixhrqc(String.valueOf(six_hr_qc)); set_hour_slot_value(pHourpp, hr, hr_value); - set_6hour_slot_value(pHourpp, six + 1, six_hr_slot_val); + set_6hour_slot_value(pHourpp, six, six_hr_slot_val); update_gage_rec(pHourpp); } } @@ -733,22 +728,22 @@ public final class GagePPWrite { * the HourPC structure. */ switch (hour) { - case 1: /* 00z - 06z */ + case 0: /* 00z - 06z */ precip_value = pHourlyPP.getSixhr06(); break; - case 2: /* 06z - 12z */ + case 1: /* 06z - 12z */ precip_value = pHourlyPP.getSixhr12(); break; - case 3: /* 12z - 18z */ + case 2: /* 12z - 18z */ precip_value = pHourlyPP.getSixhr18(); break; - case 4: /* 18z - 00z */ + case 3: /* 18z - 00z */ precip_value = pHourlyPP.getSixhr24(); break; @@ -773,25 +768,25 @@ public final class GagePPWrite { * the HourPC structure. */ switch (hour) { - case 1: /* 00z - 06z */ + case 0: /* 00z - 06z */ precip_value = new Short((short) val); pHourlyPP.setSixhr06(precip_value); break; - case 2: /* 06z - 12z */ + case 1: /* 06z - 12z */ precip_value = new Short((short) val); pHourlyPP.setSixhr12(precip_value); break; - case 3: /* 12z - 18z */ + case 2: /* 12z - 18z */ precip_value = new Short((short) val); pHourlyPP.setSixhr18(precip_value); break; - case 4: /* 18z - 00z */ + case 3: /* 18z - 00z */ precip_value = new Short((short) val); pHourlyPP.setSixhr24(precip_value); @@ -927,7 +922,7 @@ public final class GagePPWrite { precip_value = pHourlyPP.getHour23(); break; - case 24: + case 0: precip_value = pHourlyPP.getHour24(); break; @@ -1068,12 +1063,13 @@ public final class GagePPWrite { pHourly.setHour23(precip_value); break; - case 24: + case 0: precip_value = new Short((short) val); pHourly.setHour24(precip_value); break; default: + precip_value = new Short((short) MISSING_PRECIP); break; } diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEDisplayManager.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEDisplayManager.java index 4c06832a89..7c51dc064c 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEDisplayManager.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEDisplayManager.java @@ -104,6 +104,7 @@ import com.raytheon.viz.ui.editor.IMultiPaneEditor; * Dec 1, 2008 1748 snaples Added enum for Gage Color * Aug 11, 2010 5733 jwang Removed Polygon Edit and Gages * legend from MPE perspective + * Aug 8, 2012 15271 snaples Updated hourly slot * * * @author randerso @@ -536,7 +537,7 @@ public class MPEDisplayManager { clearMPEData(); try { dm.readRadarData(newDate); - dm.readGageData(newDate); + dm.readGageData(newDate, newDate); if (gageTableDlg != null) { gageTableDlg.updateDate(newDate); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/gagetable/GageTableDlg.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/gagetable/GageTableDlg.java index c4f37e91d2..019cd22112 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/gagetable/GageTableDlg.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/gagetable/GageTableDlg.java @@ -586,8 +586,6 @@ public class GageTableDlg extends JFrame { int columnCount = table.getModel().getColumnCount(); - // List columnList = null; - // columnList = dataManager.getColumnDataList(); ColumnHeaderToolTips tips = new ColumnHeaderToolTips(); for (int i = 0; i < columnCount; i++) { @@ -636,7 +634,6 @@ public class GageTableDlg extends JFrame { Vector> data = model.getDataVector(); Collections.sort(data, new ColumnSorter(colIndex, ascending)); model.setDataVector(data); - // model.fireTableStructureChanged(); } /** @@ -766,8 +763,7 @@ public class GageTableDlg extends JFrame { GageTableSettings settings = null; if (f.exists()) { -// settings = JAXB.unmarshal(path, GageTableSettings.class); - settings = JAXB.unmarshal(f, GageTableSettings.class); + settings = JAXB.unmarshal(f, GageTableSettings.class); } else { settings = getDefaultSettings(); } @@ -817,7 +813,6 @@ public class GageTableDlg extends JFrame { dataManager.setColumnDataList(columnDataList); dataManager.setColumnWidthMap(columnWidthMap); } catch (Exception e) { - e.printStackTrace(); System.out.println("MPE Settings file not found"); } } diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java index 2e79a7355e..69baa84367 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java @@ -94,6 +94,7 @@ import com.vividsolutions.jts.index.strtree.STRtree; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Feb 8, 2011 mschenke Initial creation + * Aug 8, 2012 15271 snaples Updated hourly slot * * * @@ -152,7 +153,7 @@ public class MPEGageResource extends AbstractMPEInputResource { fontFactory = new MPEFontFactory(target, this); loadColors(); lastDate = displayMgr.getCurrentDate(); - addPoints(MPEDataManager.getInstance().readGageData(lastDate)); + addPoints(MPEDataManager.getInstance().readGageData(lastDate, lastDate)); } @Override @@ -206,7 +207,7 @@ public class MPEGageResource extends AbstractMPEInputResource { synchronized (mutex) { if (curDate != null && curDate.equals(lastDate) == false) { lastDate = curDate; - addPoints(MPEDataManager.getInstance().readGageData(lastDate)); + addPoints(MPEDataManager.getInstance().readGageData(lastDate, lastDate)); } } diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/MpeFieldGenJob.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/MpeFieldGenJob.java index 0da0eb648c..5117cb61ea 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/MpeFieldGenJob.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/MpeFieldGenJob.java @@ -47,6 +47,7 @@ import com.raytheon.viz.mpe.Activator; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 1/08/09 1674 bphillip Initial creation + * 08/09/12 15307 snaples Updated job to use postStreamingByteArray. * * * @author bphillip @@ -78,11 +79,12 @@ public class MpeFieldGenJob extends Job { protected IStatus run(IProgressMonitor monitor) { final Integer[] mpeExitValue = new Integer[1]; - String httpAddress = VizApp.getHttpServer(); - + String httpAddress = VizApp.getHttpServer() + ENDPOINT_NAME; + String args = fieldGenArg; + byte[] ba = args.getBytes(); + try { - HttpClient.getInstance().postStreamingString( - httpAddress + ENDPOINT_NAME, fieldGenArg, + HttpClient.getInstance().postStreamingByteArray(httpAddress, ba, new HttpClient.IStreamHandler() { /* @@ -113,15 +115,7 @@ public class MpeFieldGenJob extends Job { return new Status(Status.ERROR, Activator.PLUGIN_ID, "MPE Field Gen execution failed with exit code: " + mpeExitValue[0]); - } catch (UnsupportedEncodingException e) { - // TODO Auto-generated catch block. Please revise as appropriate. - handler.handle(Priority.CRITICAL, e.getLocalizedMessage(), e); - - // copied from above - return new Status(Status.ERROR, Activator.PLUGIN_ID, - "MPE Field Gen execution failed with exit code: " - + mpeExitValue[0]); - } + } if (mpeExitValue[0] != null && mpeExitValue[0] == 0) { return Status.OK_STATUS; diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/RegenHrFlds.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/RegenHrFlds.java index e5838698b4..e8cdad8fc6 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/RegenHrFlds.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/RegenHrFlds.java @@ -54,6 +54,7 @@ import com.raytheon.viz.mpe.core.MPEDataManager.MPEGageData; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 30, 2008 snaples Initial creation + * Aug 8, 2012 15271 snaples Updated hourly slot * * * @author snaples @@ -301,7 +302,7 @@ public class RegenHrFlds { e.printStackTrace(); } - MPEDataManager.getInstance().readGageData(datetime); + MPEDataManager.getInstance().readGageData(datetime, datetime); /* Read radar data */ MPEDataManager.getInstance().readRadarData(datetime); MPEDataManager.getInstance().clearEditGages(); diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java index d0feff35d4..fa0e6bccf3 100644 --- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java +++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java @@ -85,6 +85,9 @@ import com.vividsolutions.jts.geom.Envelope; * 04/13/2009 2251 jsanchez Plot profilers. * 05/12/2009 2338 jsanchez Updated resourceChanged. Registered units. * 06/08/2009 2450 jsanchez Updated inpsect method to find closest plot. + * ====================================== + * AWIPS2 DR Work + * 08/09/2012 1011 jkorman Added screenToWorldRatio calc to paintInternal. * * * @@ -230,6 +233,8 @@ public class PlotResource extends if (this.stationsToParse.size() > 0) { this.updateRecords(); } + this.screenToWorldRatio = paintProps.getCanvasBounds().width + / paintProps.getView().getExtent().getWidth(); boolean delayLoop = false; DataTime thisFrameTime = this.displayedObsTime; if (thisFrameTime != null) { @@ -847,14 +852,18 @@ public class PlotResource extends ArrayList availableCoord) { double x1 = latlon.x; double y1 = latlon.y; - double minDistance = MAX_SAMPLE_DISANCE; +// double minDistance = MAX_SAMPLE_DISANCE; + double minDistance = MAX_SAMPLE_DISANCE * MAX_SAMPLE_DISANCE; int minIndex = -1; for (int i = 0; i < availableCoord.size(); i++) { Coordinate coord = availableCoord.get(i); double x2 = coord.x; double y2 = coord.y; - double d = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); +// double d = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); + double dx = x2 - x1; + double dy = y2 - y1; + double d = (dx * dx) + (dy * dy); if (d < minDistance) { minDistance = d; diff --git a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminal4Panel.xml b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminal4Panel.xml index 969d6942df..b6a428a02d 100644 --- a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminal4Panel.xml +++ b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminal4Panel.xml @@ -24,8 +24,8 @@ @@ -38,17 +38,17 @@ - - - - + + + + @@ -61,10 +61,10 @@ - - - - + + + + - \ No newline at end of file + diff --git a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflVel.xml b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflVel.xml index 149cf60dc8..a4158266f6 100644 --- a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflVel.xml +++ b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflVel.xml @@ -29,17 +29,7 @@ - - - - - - - - - - + @@ -289,20 +279,10 @@ - + - - - - - - - - - @@ -552,7 +532,7 @@ - + - \ No newline at end of file + diff --git a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflectivityMotion.xml b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflectivityMotion.xml index 6c36c917d4..d98f3891e1 100644 --- a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflectivityMotion.xml +++ b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflectivityMotion.xml @@ -21,22 +21,6 @@ - - - - - - - - - - - - - - @@ -443,22 +427,6 @@ - - - - - - - - - - - - - - @@ -862,4 +830,4 @@ - \ No newline at end of file + diff --git a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalSRMSpecWidth.xml b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalSRMSpecWidth.xml index c000445c52..bc2752d053 100644 --- a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalSRMSpecWidth.xml +++ b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalSRMSpecWidth.xml @@ -21,16 +21,6 @@ - - - - - - - - - @@ -284,12 +274,6 @@ - - - - - @@ -435,4 +419,4 @@ - \ No newline at end of file + diff --git a/cave/com.raytheon.viz.satellite/localization/bundles/DefaultSatellite.xml b/cave/com.raytheon.viz.satellite/localization/bundles/DefaultSatellite.xml index f484bc9e18..378e53b0e6 100644 --- a/cave/com.raytheon.viz.satellite/localization/bundles/DefaultSatellite.xml +++ b/cave/com.raytheon.viz.satellite/localization/bundles/DefaultSatellite.xml @@ -34,7 +34,6 @@ - 12 diff --git a/cave/com.raytheon.viz.satellite/localization/bundles/DerivedPOESSatellite.xml b/cave/com.raytheon.viz.satellite/localization/bundles/DerivedPOESSatellite.xml index 9eb5f9b308..7c19d6c02e 100644 --- a/cave/com.raytheon.viz.satellite/localization/bundles/DerivedPOESSatellite.xml +++ b/cave/com.raytheon.viz.satellite/localization/bundles/DerivedPOESSatellite.xml @@ -31,7 +31,6 @@ - 12 diff --git a/cave/com.raytheon.viz.satellite/localization/bundles/DerivedSatellite.xml b/cave/com.raytheon.viz.satellite/localization/bundles/DerivedSatellite.xml index fc3f481e85..5898a9cc83 100644 --- a/cave/com.raytheon.viz.satellite/localization/bundles/DerivedSatellite.xml +++ b/cave/com.raytheon.viz.satellite/localization/bundles/DerivedSatellite.xml @@ -37,7 +37,6 @@ - 12 diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/AfosBrowserModel.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/AfosBrowserModel.java index 5df303dc08..0c9b3c9f1c 100755 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/AfosBrowserModel.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/AfosBrowserModel.java @@ -64,7 +64,10 @@ import com.raytheon.uf.viz.core.localization.LocalizationManager; * 11/8/2007 520 grichard Implemented build 11 features. * 11/26/2007 520 grichard Implemented SuperSite in preparation for JiBX'ng. * 12/14/2007 582 grichard Implemented build 12 features. - * + * ====================================== + * AWIPS2 DR Work + * 07/24/2012 939 jkorman Modified parseAfosMasterPil() handle blank lines as well + * as lines with trailing whitespace. * * * @author grichard @@ -73,6 +76,21 @@ public final class AfosBrowserModel { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(AfosBrowserModel.class); + // Need at least this many characters in an afosMasterPIL entry + // Need the CCCNNN and at least a 1 character XXX + private static final int MIN_MASTPIL_LEN = 7; + // but no more than 9 characters. + private static final int MAX_MASTPIL_LEN = 9; + + private static final int CCC_PIL_POS = 0; + + private static final int NNN_PIL_POS = 3; + + private static final int XXX_PIL_POS = 6; + + private static final String SITE_WILDCARD = "@@@"; + + private static final String COMMENT_DELIM = "#"; /** * The VTEC Afos Product enumeration */ @@ -265,7 +283,7 @@ public final class AfosBrowserModel { br = new BufferedReader(new FileReader(fileToParse)); while ((line = br.readLine()) != null) { // skip comments. - if (line.startsWith("#")) { + if (line.startsWith(COMMENT_DELIM)) { continue; } @@ -294,7 +312,7 @@ public final class AfosBrowserModel { br = new BufferedReader(new FileReader(fileToParse)); while ((line = br.readLine()) != null) { // skip comments. - if (line.startsWith("#")) { + if (line.startsWith(COMMENT_DELIM)) { continue; } @@ -324,7 +342,7 @@ public final class AfosBrowserModel { br = new BufferedReader(new FileReader(fileToParse)); while ((line = br.readLine()) != null) { // skip comments. - if (line.startsWith("#")) { + if (line.startsWith(COMMENT_DELIM)) { continue; } @@ -351,42 +369,69 @@ public final class AfosBrowserModel { return cccOriginMap; } + /** + * Read and parse an afos PIL list. In the event of processing multiple + * files, the most recent entry overwrites a current entry. + * + * @param fileToParse + * File reference containing the PIL list. + */ private void parseAfosMasterPil(File fileToParse) { if (fileToParse != null && fileToParse.exists()) { BufferedReader br = null; String line = null; + String localCCC = SiteMap.getInstance() + .getCCCFromXXXCode(localSite); try { br = new BufferedReader(new FileReader(fileToParse)); while ((line = br.readLine()) != null) { - // skip comments. - if (line.startsWith("#")) { + // Remove any trailing spaces. + line = line.trim(); + // skip blank lines or comments. + if ((line.length() == 0) || line.startsWith(COMMENT_DELIM)) { continue; } - String ccc = line.substring(0, 3); + if (line.length() >= MIN_MASTPIL_LEN) { + String ccc = line.substring(CCC_PIL_POS, NNN_PIL_POS); + if (ccc.equals(SITE_WILDCARD)) { + ccc = localCCC; + } + String nnn = line.substring(NNN_PIL_POS, XXX_PIL_POS); + String xxx; + if(line.length() > MAX_MASTPIL_LEN) { + // Only take the first 9 characters of the line. + // Trim in case there are any internal spaces. + xxx = line.substring(XXX_PIL_POS, MAX_MASTPIL_LEN + 1).trim(); + } else { + // Just grab the remainder of the input line. + // Its already been trimmed. + xxx = line.substring(6); + } - if (ccc.equals("@@@")) { - ccc = SiteMap.getInstance() - .getCCCFromXXXCode(localSite); + Map> nnnxxx = masterPil + .get(ccc); + if (nnnxxx == null) { + nnnxxx = new HashMap>(); + masterPil.put(ccc, nnnxxx); + } + + SortedSet xxxList = nnnxxx.get(nnn); + if (xxxList == null) { + xxxList = new TreeSet(); + nnnxxx.put(nnn, xxxList); + } + + xxxList.add(xxx); + } else { + String msg = String.format( + "Line [%s] in file %s incorrect", line, + fileToParse.getPath()); + + statusHandler.handle(Priority.SIGNIFICANT, msg); } - String nnn = line.substring(3, 6); - String xxx = line.substring(6); - - Map> nnnxxx = masterPil.get(ccc); - if (nnnxxx == null) { - nnnxxx = new HashMap>(); - masterPil.put(ccc, nnnxxx); - } - - SortedSet xxxList = nnnxxx.get(nnn); - if (xxxList == null) { - xxxList = new TreeSet(); - nnnxxx.put(nnn, xxxList); - } - - xxxList.add(xxx); } // while } catch (IOException e) { statusHandler.handle(Priority.PROBLEM, @@ -519,7 +564,7 @@ public final class AfosBrowserModel { public boolean contains(String ccc, String nnn, String xxx) { boolean rval = false; Map> catMap = masterPil.get(ccc); - if (catMap != null) { + if ((catMap != null) && (xxx != null)) { SortedSet desList = catMap.get(nnn); if (desList != null) { rval = desList.contains(xxx); diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmAlertBell.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmAlertBell.java index 18d5075f78..099e8c73c6 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmAlertBell.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmAlertBell.java @@ -67,6 +67,7 @@ import com.raytheon.viz.texteditor.alarmalert.util.FlashBellJob; * Dec 23, 2010 7375 cjeanbap Force dialog ON TOP of over Dialog/Windows. * 03/19/2012 D. Friedman Fix alarming. Disable runloop in open(). * May 18, 2012 jkorman Added flashing alarm image. + * Jul 25, 2012 15122 rferrel Add sound delay interval. * * * @author mnash @@ -75,10 +76,15 @@ import com.raytheon.viz.texteditor.alarmalert.util.FlashBellJob; public class AlarmAlertBell extends Dialog implements MouseMoveListener, MouseListener { - + // delay in milliseconds - flash every 1 1/2 seconds private static final int FLASH_DELAY = 1500; - + + /** + * Repeat the alarm sound every minute. + */ + private static final long SOUND_DELAY = 60 * 1000L; + private Shell parentShell; private Shell alarmShell; @@ -90,15 +96,15 @@ public class AlarmAlertBell extends Dialog implements MouseMoveListener, private String bellPath; private FlashBellJob flasher; - + private Image norm_bell; private Image revs_bell; private boolean invert = false; - + private boolean active = false; - + private Button button; private AlarmBeepJob abj = null; @@ -196,9 +202,9 @@ public class AlarmAlertBell extends Dialog implements MouseMoveListener, } public Object open(boolean alarm) { - if (alarm) { + if (alarm && abj == null) { // provides the beep to alert the user that an alarm has come in - abj = new AlarmBeepJob("AlarmBeepJob"); + abj = new AlarmBeepJob("AlarmBeepJob", SOUND_DELAY); abj.schedule(); } @@ -216,28 +222,33 @@ public class AlarmAlertBell extends Dialog implements MouseMoveListener, alarmShell.setActive(); active = true; // Start a new flash job only if one isn't currently running! - if(flasher == null) { + if (flasher == null) { invert = false; flasher = new FlashBellJob("FlashBell", this, FLASH_DELAY); } + return null; } /** - * Close the AlarmAlertBell and turn off the "flasher" job - * if running. + * Close the AlarmAlertBell and turn off the "flasher" and "abj" job if + * running. */ public void close() { - if(!alarmShell.isDisposed()) { + if (!alarmShell.isDisposed()) { alarmShell.setVisible(false); } active = false; - if(flasher != null) { + if (flasher != null) { flasher.cancel(); flasher = null; } + if (abj != null) { + abj.cancel(); + abj = null; + } } - + private void setInitialDialogLocation() { if (locationX < 0) { Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); @@ -263,7 +274,7 @@ public class AlarmAlertBell extends Dialog implements MouseMoveListener, bellPath = imageFile.getFile().getAbsolutePath(); norm_bell = new Image(display, bellPath); button = new Button(alarmShell, SWT.IMAGE_GIF); - if(norm_bell != null) { + if (norm_bell != null) { createInvertImage(bellPath); button.setImage(norm_bell); } @@ -330,12 +341,12 @@ public class AlarmAlertBell extends Dialog implements MouseMoveListener, private void createInvertImage(String path) { if (norm_bell != null) { ImageData id = new ImageData(path); - for(int i = 0;i < id.width;i++) { - for(int j = 0;j < id.height;j++) { - if(id.getPixel(i,j) == 0) { - id.setPixel(i,j,1); + for (int i = 0; i < id.width; i++) { + for (int j = 0; j < id.height; j++) { + if (id.getPixel(i, j) == 0) { + id.setPixel(i, j, 1); } else { - id.setPixel(i,j,0); + id.setPixel(i, j, 0); } } } @@ -345,17 +356,18 @@ public class AlarmAlertBell extends Dialog implements MouseMoveListener, /** * Check to see if the dialog is active. + * * @return */ public boolean isActive() { return active; } - + /** * Alternate between normal and reverse images. */ public void flash() { - if(invert) { + if (invert) { button.setImage(revs_bell); } else { button.setImage(norm_bell); diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmAlertSaveLoadDlg.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmAlertSaveLoadDlg.java index ee467d4ba4..d36cf44d40 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmAlertSaveLoadDlg.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmAlertSaveLoadDlg.java @@ -20,6 +20,7 @@ package com.raytheon.viz.texteditor.alarmalert.dialogs; import java.io.File; +import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; @@ -37,6 +38,10 @@ import org.eclipse.swt.widgets.Text; import com.raytheon.uf.common.localization.LocalizationContext; import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.PathManagerFactory; +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; import com.raytheon.viz.texteditor.alarmalert.util.AlarmAlertFunctions; import com.raytheon.viz.ui.dialogs.CaveSWTDialog; @@ -49,6 +54,10 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Sep 17, 2009 mnash Initial creation + * ====================================== + * AWIPS2 DR Work + * 07/25/2012 953 jkorman Modified file "search" to return LocalizationFile + * instead of File so references are deleted in all locations. * * * @@ -58,6 +67,9 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; public class AlarmAlertSaveLoadDlg extends CaveSWTDialog { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(AlarmAlertSaveLoadDlg.class); + private Font font; private Composite shellComp; @@ -136,13 +148,21 @@ public class AlarmAlertSaveLoadDlg extends CaveSWTDialog { gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); lists.setLayoutData(gd); LocalizationContext lc = AlarmAlertFunctions.initUserLocalization(); - LocalizationFile fileDir = PathManagerFactory.getPathManager() - .getLocalizationFile(lc, "alarms"); - File file = fileDir.getFile(); - final File[] fileList = file.listFiles(); - for (File locFile : fileList) { - if (locFile.getName().endsWith(".xml")) { - lists.add(locFile.getName()); + + // Get a list of localization files! + LocalizationFile[] fList = PathManagerFactory.getPathManager() + .listFiles(lc, "alarms", new String[] { "xml" }, false, true); + + final java.util.List fileList = new ArrayList(); + for (LocalizationFile locFile : fList) { + // We only want the filename in the display list. + String[] s = locFile.getName().split("/"); + // Make sure we have some data! + if (s.length > 0) { + // The last element is the filename. + lists.add(s[s.length - 1]); + // Complete file reference here. + fileList.add(locFile); } } @@ -170,17 +190,30 @@ public class AlarmAlertSaveLoadDlg extends CaveSWTDialog { // loads the loadButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { + // Set the filename to be returned through getFileName() fileName = lists.getSelection()[0]; - // TODO load the file shell.close(); } }); - // delete the file from the list and from the file system + // delete the file from the display list and from the file system deleteButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { int num = lists.getSelectionIndex(); - fileList[num].delete(); + LocalizationFile f = fileList.get(num); + try { + if (!f.delete()) { + String msg = String.format( + "ALARM/ALERT:Failed deleting file %s", f + .getFile().getPath()); + statusHandler.handle(Priority.PROBLEM, msg); + } + } catch (LocalizationOpFailedException e) { + String msg = String.format( + "ALARM/ALERT:Failed deleting file %s", f.getFile() + .getPath()); + statusHandler.handle(Priority.PROBLEM, msg, e); + } lists.remove(num); } }); @@ -250,8 +283,8 @@ public class AlarmAlertSaveLoadDlg extends CaveSWTDialog { // get the file name saveButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { + // Set the filename to be returned through getFileName() fileName = textBox.getText(); - // TODO load the file shell.close(); } }); diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmDisplayWindow.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmDisplayWindow.java index 01d6dc1b7e..f6c7545f1d 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmDisplayWindow.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmDisplayWindow.java @@ -188,15 +188,17 @@ public class AlarmDisplayWindow extends CaveSWTDialog { lines.append(text.getLine(lineIndex)).append("\n"); } - PrintDisplay.print(true, lines.toString(), - UFStatus.getHandler(AlarmDisplayWindow.class)); + PrintDisplay.print(lines.toString(), text.getFont() + .getFontData()[0], UFStatus + .getHandler(AlarmDisplayWindow.class)); } }); printBuffer.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - PrintDisplay.print(true, text.getText(), + PrintDisplay.print(text.getText(), + text.getFont().getFontData()[0], UFStatus.getHandler(AlarmDisplayWindow.class)); } }); diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertFunctions.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertFunctions.java index 8b1290ff2a..5092709723 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertFunctions.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertFunctions.java @@ -27,8 +27,6 @@ import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.xml.bind.JAXB; @@ -76,7 +74,7 @@ public class AlarmAlertFunctions { private static final AlarmAlertProduct.ProductType AA = AlarmAlertProduct.ProductType.Alarm_Alert; private static final AlarmAlertProduct.ProductType PA = AlarmAlertProduct.ProductType.Proximity_Alarm; - + private static final Object configFileLock = new Object(); private static final String ALARM_ALERT_PATH = "alarms" + File.separator; @@ -130,50 +128,52 @@ public class AlarmAlertFunctions { */ public static void isInAlarmList(AlarmAlertProduct prod) { AlarmAlertLists instance = AlarmAlertLists.getInstance(); - + List currentAlarms = instance.getFilteredProducts(); boolean alarm = false; - List prods = findMatches(prod.getProductId(), currentAlarms); + List prods = findMatches(prod.getProductId(), + currentAlarms); // did we match anything? boolean alertAlarm = (prods.size() > 0); - if(alertAlarm) { + if (alertAlarm) { String pId = prods.get(0).getProductId(); - // first go get the product. All of the matching product identifiers are + // first go get the product. All of the matching product identifiers + // are // the same so just get the first. List prodList = getProduct(pId); AlarmAlertProduct productFound = null; - if(prodList.size() > 0) { + if (prodList.size() > 0) { String s = prodList.get(0).getProduct(); - for(AlarmAlertProduct p : prods) { + for (AlarmAlertProduct p : prods) { String search = p.getSearchString(); - + boolean match = false; - if((search != null) && (search.length() > 0)) { - if(s.indexOf(search) >= 0) { - match = true; + if ((search != null) && (search.length() > 0)) { + if (s.indexOf(search) >= 0) { + match = true; } } else { - match = true; + match = true; } if (match) { - if (productFound == null) - productFound = p; - if ("Alarm".equals(p.getAlarmType()) && p.isAlarm()) { - alarm = true; - productFound = p; - } - if (alarm) - break; + if (productFound == null) + productFound = p; + if ("Alarm".equals(p.getAlarmType()) && p.isAlarm()) { + alarm = true; + productFound = p; + } + if (alarm) + break; } } } - if(productFound != null) { + if (productFound != null) { prod.setAlarm(productFound.isAlarm()); prod.setAlarmType(productFound.getAlarmType()); - + instance.getCurrentAlarms().add(prod); instance.fireNewCurrentAlarmEvent(prod); - + ringBell(alarm); } } @@ -184,46 +184,51 @@ public class AlarmAlertFunctions { } /** - * Retrieve a text product from the text database based on its productId. - * @param productId AFOS ProductId to retrieve from the text database. + * Retrieve a text product from the text database based on its productId. + * + * @param productId + * AFOS ProductId to retrieve from the text database. * @return A list of text products. Will always return a not null reference. */ private static List getProduct(String productId) { List productList = null; - + ICommand command = CommandFactory.getAfosCommand(productId); try { - productList = command.executeCommand(TextEditorUtil.getTextDbsrvTransport()); + productList = command.executeCommand(TextEditorUtil + .getTextDbsrvTransport()); } catch (CommandFailedException e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); } - if(productList == null) { + if (productList == null) { productList = new ArrayList(); } return productList; } - - + /** * Return a list of all alarms that match the incoming product identifier. + * * @param productId * @param currentAlarms * @return */ - private static List findMatches(String productId, List currentAlarms) { + private static List findMatches(String productId, + List currentAlarms) { List prods = new ArrayList(); - if(productId != null) { - productId = productId.toUpperCase(); + if (productId != null) { + productId = productId.trim().toUpperCase(); for (AlarmAlertProduct a : currentAlarms) { - //************** + // ************** // TODO : For now disable Proximity Alerts - //************** - if(AA.equals(a.getProductType())) { + // ************** + if (AA.equals(a.getProductType())) { String s = a.getProductId(); - if(s != null) { - s = s.toUpperCase(); - if(s.equals(productId)) { - // Reset the productId so we know we're dealing with uppercase + if (s != null) { + s = s.trim().toUpperCase(); + if (s.equals(productId)) { + // Reset the productId so we know we're dealing with + // uppercase a.setProductId(s); prods.add(a); } @@ -233,8 +238,7 @@ public class AlarmAlertFunctions { } return prods; } - - + /** * initialize the localization for user with the save/load functions * diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmBeepJob.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmBeepJob.java index 8c558b288a..b4d7a89ec3 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmBeepJob.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmBeepJob.java @@ -24,7 +24,7 @@ import java.awt.Toolkit; 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.ui.progress.UIJob; /** * TODO Add Description @@ -35,6 +35,7 @@ import org.eclipse.core.runtime.jobs.Job; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 19, 2009 mnash Initial creation + * Jul 25, 2012 15122 rferrel Add sound repeat interval. * * * @@ -42,17 +43,29 @@ import org.eclipse.core.runtime.jobs.Job; * @version 1.0 */ -public class AlarmBeepJob extends Job { +public class AlarmBeepJob extends UIJob { + + private static final int BEEP_COUNT = 5; + + private static final long BEEP_INTERVAL = 1000L; private boolean disposed; + private long delay; + private int count = 0; /** * @param name */ - public AlarmBeepJob(String name) { + public AlarmBeepJob(String name, long delay) { super(name); + + if (delay > (BEEP_COUNT * BEEP_INTERVAL)) { + this.delay = delay; + } else { + this.delay = (BEEP_COUNT + 1) * BEEP_INTERVAL; + } } /* @@ -62,27 +75,21 @@ public class AlarmBeepJob extends Job { * IProgressMonitor) */ @Override - protected IStatus run(IProgressMonitor monitor) { + public IStatus runInUIThread(IProgressMonitor monitor) { IStatus status = Status.OK_STATUS; - if (count < 5) { + if (count < BEEP_COUNT) { Toolkit.getDefaultToolkit().beep(); - reSchedule(); + if (!disposed) { + this.schedule(BEEP_INTERVAL); + } count++; - } else { - dispose(); + } else if (!disposed) { + schedule(delay - (BEEP_COUNT * BEEP_INTERVAL)); + count = 0; } return status; } - /** - * Schedule this job to run after the desired interval - */ - public void reSchedule() { - if (!disposed) { - this.schedule(1 * 1000); - } - } - /** * Cancel this job and release its reference to the DataManager */ diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AWIPSHeaderBlockDlg.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AWIPSHeaderBlockDlg.java index c709f65720..c577058570 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AWIPSHeaderBlockDlg.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AWIPSHeaderBlockDlg.java @@ -90,6 +90,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * 01/26/2012 14468 D.Friedman Fix initial BBB field selection. * 05/30/2012 15046 D.Friedman Always set addressee field to ALL. * 06/19/2012 14975 D.Friedman Run callback when dialog is dismissed. + * 07/26/2012 15171 rferrel Disable editor's send and clear AFOS PIL fields when + * invalid product Id and user want to edit it anyway, * * * @author lvenable @@ -202,11 +204,11 @@ public class AWIPSHeaderBlockDlg extends CaveSWTDialog implements @Override public void widgetDisposed(DisposeEvent e) { if (parentEditor != null) - parentEditor.headerBlockDlgDismissed( - Boolean.TRUE.equals(getReturnValue())); + parentEditor.headerBlockDlgDismissed(Boolean.TRUE + .equals(getReturnValue())); } }); - + setReturnValue(false); createWmoIdFields(); @@ -274,7 +276,7 @@ public class AWIPSHeaderBlockDlg extends CaveSWTDialog implements // Create the message/indicator group combo box. gd = new GridData(70, SWT.DEFAULT); - bbbCboBx = new Combo(wmoIdComp, SWT.DROP_DOWN|SWT.READ_ONLY); + bbbCboBx = new Combo(wmoIdComp, SWT.DROP_DOWN | SWT.READ_ONLY); bbbCboBx.setItems(BBB_LIST); bbbCboBx.select(3); bbbCboBx.setLayoutData(gd); @@ -298,7 +300,7 @@ public class AWIPSHeaderBlockDlg extends CaveSWTDialog implements // Create the message/indicator version group combo box. gd = new GridData(70, SWT.DEFAULT); - bbbVerCboBx = new Combo(wmoIdComp, SWT.DROP_DOWN|SWT.READ_ONLY); + bbbVerCboBx = new Combo(wmoIdComp, SWT.DROP_DOWN | SWT.READ_ONLY); bbbVerCboBx.setItems(CHAR_LIST); bbbVerCboBx.select(0); bbbVerCboBx.setLayoutData(gd); @@ -473,7 +475,7 @@ public class AWIPSHeaderBlockDlg extends CaveSWTDialog implements .getTextLimit()) { wmoTtaaiiTF.setFocus(); } - + handleAddresseeModified(); } }); @@ -595,6 +597,7 @@ public class AWIPSHeaderBlockDlg extends CaveSWTDialog implements enterBtn.setEnabled(true); enterBtn.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { + boolean sendEnabled = true; if (!isProductValid()) { // Notify the user that the product may not be valid. // @@ -614,15 +617,25 @@ public class AWIPSHeaderBlockDlg extends CaveSWTDialog implements if (mb.open() == SWT.NO) { return; } + parentEditor.enableSend(false); + sendEnabled = false; + } else { + parentEditor.enableSend(true); } // call the set methods parentEditor.setCurrentWmoId(wmoTtaaiiTF.getText()); parentEditor.setCurrentSiteId(ccccTF.getText()); - parentEditor.setCurrentWsfoId(wsfoIdTF.getText()); - parentEditor.setCurrentProdCategory(prodCatTF.getText()); - parentEditor.setCurrentProdDesignator(prodDesignatorTF - .getText()); + if (sendEnabled) { + parentEditor.setCurrentWsfoId(wsfoIdTF.getText()); + parentEditor.setCurrentProdCategory(prodCatTF.getText()); + parentEditor.setCurrentProdDesignator(prodDesignatorTF + .getText()); + } else { + parentEditor.setCurrentWsfoId(""); + parentEditor.setCurrentProdCategory(""); + parentEditor.setCurrentProdDesignator(""); + } parentEditor.setAddressee(addresseeTF.getText()); setBbbId(); setReturnValue(true); diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AfosBrowserDlg.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AfosBrowserDlg.java index 6a03971590..325ab00017 100755 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AfosBrowserDlg.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AfosBrowserDlg.java @@ -535,22 +535,9 @@ public class AfosBrowserDlg extends CaveSWTDialog implements loadContinueBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - /* - * if ((nodeList.getSelectionIndex() > -1) && - * (categoryList.getSelectionIndex() > -1) && - * designatorList.getSelectionIndex() > -1) { - */ - /* - * TextDisplayModel.getInstance().setProductNode(token, - * selectedNode); - * TextDisplayModel.getInstance().setProductCategory(token, - * selectedCategory); - * TextDisplayModel.getInstance().setProductDesignator(token, - * selectedDesignator); - */ callbackClient.executeCommand(CommandFactory .getAfosCommand(currentAfosCommand)); - // } + loadContinueBtn.setFocus(); } }); @@ -563,20 +550,8 @@ public class AfosBrowserDlg extends CaveSWTDialog implements loadCloseBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - /* - * if ((nodeList.getSelectionIndex() > -1) && - * (categoryList.getSelectionIndex() > -1) && - * designatorList.getSelectionIndex() > -1) { - * TextDisplayModel.getInstance().setProductNode(token, - * selectedNode); - * TextDisplayModel.getInstance().setProductCategory(token, - * selectedCategory); - * TextDisplayModel.getInstance().setProductDesignator(token, - * selectedDesignator); - */ callbackClient.executeCommand(CommandFactory .getAfosCommand(currentAfosCommand)); - // } setReturnValue(false); shell.setVisible(false); @@ -778,7 +753,7 @@ public class AfosBrowserDlg extends CaveSWTDialog implements // Get the designator list - ensure that the entries are three // characters in length. for (String s : xxx) { - if(s.length() == 1) { + if (s.length() == 1) { s = s + " "; } else if (s.length() == 2) { s = s + " "; 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 4d59bd155a..cc4ef078e7 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 @@ -44,6 +44,7 @@ import java.util.Scanner; import java.util.TimeZone; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -67,8 +68,6 @@ import org.eclipse.swt.custom.VerifyKeyListener; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusAdapter; @@ -87,6 +86,7 @@ import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; @@ -279,6 +279,9 @@ import com.raytheon.viz.ui.dialogs.SWTMessageBox; * 24Apr2012 14548 rferrel Merging lines for wrap places a space beween words when needed. * 27Apr2012 14902 rferrel No longer have blank line between AWIPS ID and UGC line. * 06/19/2012 14975 D.Friedman Prevent zeroed-out WMO header times. + * 18JUL2012 14457 rferrel Add mouse listener to clear site's update obs when clicked on. + * 25JUL2012 14459 rferrel Strip WMH headers when getting all METARs. + * 13AUG2012 14613 M.Gamazaychikov Ensured the WMO and MND header times are the same. * * * @author lvenable @@ -308,6 +311,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, private static final int END_ELEMENT_TAG_LEN = END_ELEMENT_TAG.length(); + private static final String METAR_LINE = "^(METAR |SPECI |\\s+\\S)"; + + private static final Pattern METAR_PATTERN = Pattern.compile(METAR_LINE); + private final List displayedPils = new ArrayList(); private Pattern obsRegex = null; @@ -943,13 +950,13 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, /** * flag to indicate it a product request is from the GUI or an updated ob. */ - private boolean updating = false; + private AtomicInteger updateCount = new AtomicInteger(0); private NotifyExpiration notify; private NotifyExpiration queuedNotify = null; - private String queuedAfos = null; + private String queuedProduct = null; /** * The Warngen work product id for draft PILs. @@ -1090,9 +1097,13 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, private RemoteRetrievalRequest lastRemoteRetrievalRequest; private Clipboard clipboard; - - private enum HeaderEditSession { CLOSE_ON_EXIT, IN_EDITOR } - + + private MouseListener updateObsListener = null; + + private enum HeaderEditSession { + CLOSE_ON_EXIT, IN_EDITOR + } + private HeaderEditSession headerEditSession; static { @@ -1192,7 +1203,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, @Override protected void initializeComponents(final Shell shell) { - shell.setSize(MIN_WIDTH, MIN_HEIGHT); Display display = getDisplay(); clipboard = new Clipboard(getDisplay()); @@ -1201,32 +1211,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, medFont = new Font(display, "Courier", 11, SWT.NORMAL); lrgFont = new Font(display, "Courier", 13, SWT.NORMAL); - // this.shell = shell; - shell.addControlListener(new ControlAdapter() { - public void controlResized(ControlEvent e) { - if (canRedraw == false) { - return; - } - - final Shell resizedShell = (Shell) e.getSource(); - final Point point = resizedShell.getSize(); - - if (point.x != MIN_WIDTH || point.y < (MIN_HEIGHT / 2)) { - canRedraw = false; - Display.getDefault().asyncExec(new Runnable() { - public void run() { - if (point.y < (MIN_HEIGHT / 2)) { - point.y = (MIN_HEIGHT / 2); - } - - resizedShell.setSize(MIN_WIDTH, point.y); - canRedraw = true; - } - }); - } - } - }); - if (textWorkstationFlag || isWarnGenDlg) { shell.addShellListener(new ShellAdapter() { @Override @@ -2632,8 +2616,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (rv == true) { recompileRegex(); wordWrapEnabled = true; - // textEditor.setWordWrap(true); - // sizeTextEditor(); } } @@ -2650,10 +2632,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, smallFontItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - textEditor.setFont(smlFont); - // textEditorComp.layout(); - sizeTextEditor(); - headerTF.setFont(smlFont); + if (smallFontItem.getSelection()) { + textEditor.setFont(smlFont); + headerTF.setFont(smlFont); + } } }); @@ -2663,10 +2645,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, mediumFontItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - textEditor.setFont(medFont); - // textEditorComp.layout(); - sizeTextEditor(); - headerTF.setFont(medFont); + if (mediumFontItem.getSelection()) { + textEditor.setFont(medFont); + headerTF.setFont(medFont); + } } }); @@ -2675,10 +2657,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, largeFontItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - textEditor.setFont(lrgFont); - // textEditorComp.layout(); - sizeTextEditor(); - headerTF.setFont(lrgFont); + if (largeFontItem.getSelection()) { + textEditor.setFont(lrgFont); + headerTF.setFont(lrgFont); + } } }); } @@ -2816,6 +2798,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, @Override public void widgetSelected(SelectionEvent event) { clearTextEditor(); + if (updateObsListener != null) { + textEditor.removeMouseListener(updateObsListener); + updateObsListener = null; + } } }); } @@ -2871,7 +2857,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } public void widgetDefaultSelected(SelectionEvent event) { - String tmp = afosCmdTF.getText(); tmp = tmp.trim(); afosCmdTF.setText(tmp); @@ -2959,7 +2944,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } public void widgetDefaultSelected(SelectionEvent event) { - textEditor.setFocus(); wmoTtaaiiTF.setText(wmoTtaaiiTF.getText().toUpperCase()); ccccTF.setText(ccccTF.getText().toUpperCase()); wmoSearch(); @@ -3018,7 +3002,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } public void widgetDefaultSelected(SelectionEvent event) { - textEditor.setFocus(); wmoTtaaiiTF.setText(wmoTtaaiiTF.getText().toUpperCase()); ccccTF.setText(ccccTF.getText().toUpperCase()); wmoSearch(); @@ -3080,22 +3063,15 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } public void widgetDefaultSelected(SelectionEvent event) { - textEditor.setFocus(); awipsIdTF.setText(awipsIdTF.getText().trim().toUpperCase()); int charCount = awipsIdTF.getCharCount(); if (charCount < 4 || charCount > 6) { - // System.out - // .printf("Must enter a 6 or 9 character AFOS PIL%n"); - // System.out.printf("Character Count = %d%n", charCount); userInformation("Must enter a 4 to 6 character AWIPS ID"); awipsIdTF.setFocus(); return; } else { - // System.out.printf("NNN = %s%n", awipsIdTF.getText(0, 2)); TextDisplayModel.getInstance().setProductCategory(token, awipsIdTF.getText(0, 2)); - // System.out.printf("XXX = %s%n", - // awipsIdTF.getText(3, charCount - 1)); TextDisplayModel.getInstance().setProductDesignator(token, awipsIdTF.getText(3, charCount - 1)); } @@ -3151,10 +3127,33 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, * state of the check box */ private void handleUpdateObsChkBtn(boolean checked) { - // String pil = TextDisplayModel.getInstance().getAfosPil(token); - // System.out.println("Update Obs: state = " + checked + ", AFOS PIL = " - // + pil); if (checked) { + if (updateObsListener == null) { + updateObsListener = new MouseListener() { + + @Override + public void mouseUp(MouseEvent e) { + try { + int offset = textEditor + .getOffsetAtLocation(new Point(e.x, e.y)); + clearUpdateFlag(offset); + } catch (IllegalArgumentException ex) { + // bad mouse location ignore + } + } + + @Override + public void mouseDown(MouseEvent e) { + // Ignore + } + + @Override + public void mouseDoubleClick(MouseEvent e) { + // Ignore + } + }; + textEditor.addMouseListener(updateObsListener); + } NotificationManagerJob.addObserver(ALARM_ALERT_TOPIC, this); } else { NotificationManagerJob.removeObserver(ALARM_ALERT_TOPIC, this); @@ -3162,6 +3161,18 @@ 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)) { + StyleRange lock = (StyleRange) range.clone(); + lock.background = null; + lock.foreground = null; + textEditor.setStyleRange(lock); + break; + } + } + } + private void clearAfosCmdTF() { if (!afosCmdTF.isDisposed()) { afosCmdTF.setText(""); @@ -3364,7 +3375,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, * Create the text editor (styled text) control. */ private void createTextAreaEditor() { - GridData gd = new GridData(GridData.FILL_BOTH); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); textEditorComp = new Composite(shell, SWT.NONE); GridLayout gridLayout = new GridLayout(1, false); textEditorComp.setLayout(gridLayout); @@ -3372,8 +3383,16 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, textEditor = new StyledText(textEditorComp, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL); - textEditor.setWordWrap(false); + gd = new GridData(SWT.FILL, SWT.FILL, true, true); textEditor.setFont(medFont); + GC gc = new GC(textEditor); + FontMetrics fm = gc.getFontMetrics(); + gc.dispose(); + int width = EDITOR_WIDTH * fm.getAverageCharWidth(); + gd.widthHint = width; + + textEditor.setLayoutData(gd); + textEditor.setWordWrap(false); textEditor.setEditable(false); textEditor.setKeyBinding(SWT.INSERT, SWT.NULL); // DR 7826 @@ -3436,22 +3455,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // } // }); - sizeTextEditor(); - textEditor.addVerifyKeyListener(new VerifyKeyListener() { public void verifyKey(VerifyEvent event) { - - // System.out.println("event.keyCode = " + event.keyCode); - // System.out.println("event.character = <" + event.character - // + ">"); - // - // System.out.println("String.valueOf(event.character) = <" - // + String.valueOf(event.character) + ">"); - // - // System.out.println("String.valueOf(event.character).length = - // <" - // + String.valueOf(event.character).length() + ">"); - if (event.keyCode == SWT.DEL || event.character == SWT.BS || event.keyCode == SWT.SHIFT) { // Do nothing... @@ -3667,20 +3672,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, statusBarLabel.setLayoutData(gd); } - /** - * Size the text editor based on the text font size. - */ - private void sizeTextEditor() { - GC gc = new GC(textEditor); - FontMetrics fm = gc.getFontMetrics(); - gc.dispose(); - int width = EDITOR_WIDTH * fm.getAverageCharWidth(); - GridData data = new GridData(GridData.FILL_VERTICAL); - data.widthHint = width; - textEditor.setLayoutData(data); - textEditorComp.layout(); - } - /** * Enter the text editor mode. */ @@ -3764,12 +3755,12 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, stopAutoSave(); - if (warnGenFlag && queuedAfos != null) { + if (warnGenFlag && queuedProduct != null) { // Display the WarnGen in the queue, perform the popup and stop the // cancel. - showWarngenProduct(queuedAfos, queuedNotify); + showWarngenProduct(queuedProduct, queuedNotify); queuedNotify = null; - queuedAfos = null; + queuedProduct = null; return false; } // Set the edit mode flag @@ -3866,14 +3857,14 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // Create and display the AWIPS header block dialog. AWIPSHeaderBlockDlg awipsHeaderBlockDlg = new AWIPSHeaderBlockDlg( shell, this); - - headerEditSession = closeEditorOnCancel ? - HeaderEditSession.CLOSE_ON_EXIT : HeaderEditSession.IN_EDITOR; + + headerEditSession = closeEditorOnCancel ? HeaderEditSession.CLOSE_ON_EXIT + : HeaderEditSession.IN_EDITOR; awipsHeaderBlockDlg.open(); // headerBlockDlgDismissed() is called when the dialog is dismissed. } - + /** * Called by AWIPSHeaderBlockDlg when it is dismissed. * @@ -3884,23 +3875,24 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, public void headerBlockDlgDismissed(boolean dialogResult) { HeaderEditSession lastSession = headerEditSession; headerEditSession = null; - + // If the user cancels the AWIPS header block dialog then // get out of edit mode. // Otherwise use the node, product category, and product designator. - + boolean editing = false; - + if (dialogResult == true) { TextDisplayModel tdm = TextDisplayModel.getInstance(); - + // Update the buttonology. updateButtonology(tdm.getAfosPil(token)); String bbbid = tdm.getBbbId(token); - + String nnnxxx = workProductId != null ? workProductId : tdm - .getProductCategory(token) + tdm.getProductDesignator(token); + .getProductCategory(token) + + tdm.getProductDesignator(token); // Set the header text field. if (bbbid.equals("NOR")) { String wmoId = tdm.getWmoId(token); @@ -3912,25 +3904,26 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, setHeaderTextField(tdm.getWmoId(token), tdm.getSiteId(token), currentDateId + " " + bbbid, "\n", nnnxxx); } - + // Update the "now editing" title of the text editor window. updateNowEditingTitle(); - + editing = true; } else { if (lastSession == HeaderEditSession.CLOSE_ON_EXIT) - editing = !cancelEditor(false); + editing = !cancelEditor(false); } - + if (lastSession == HeaderEditSession.CLOSE_ON_EXIT) if (editing) { StdTextProduct product = TextDisplayModel.getInstance() - .getStdTextProduct(token); + .getStdTextProduct(token); 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 the + // displayed, verify it was not cancelled before starting + // the // autoSave task. autoSave = new AutoSaveTask(product.getWmoid(), product.getSite()); @@ -4080,7 +4073,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, * Print all text from the text editor to the default printer. */ private void printAllText() { - PrintDisplay.print(true, textEditor.getText(), statusHandler); + FontData fontData = textEditor.getFont().getFontData()[0]; + PrintDisplay.print(textEditor.getText(), fontData, statusHandler); } /** @@ -4102,7 +4096,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (mb.open() == SWT.YES) { String tmpText = textEditor.getText(); Point point = textEditor.getSelection(); - PrintDisplay.print(true, textEditor.getSelectionText(), + FontData fontData = textEditor.getFont().getFontData()[0]; + PrintDisplay.print(textEditor.getSelectionText(), fontData, statusHandler); textEditor.setText(tmpText); textEditor.setSelection(point); @@ -4609,10 +4604,16 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } boolean successful = false; - // Convert the text in the text editor to uppercase - String currentDate = getCurrentDate(); + /* + * 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(); + String currentDate = getCurrentDate(now); TextDisplayModel tdmInst = TextDisplayModel.getInstance(); + // Convert the text in the text editor to uppercase if (!isAutoSave) { if (!verifyRequiredFields()) { return false; @@ -4642,17 +4643,19 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } if (!isAutoSave) { - if (! resend) { + if (!resend) { // If not a resend, set the DDHHMM field to the current time productText = replaceDDHHMM(productText, currentDate); - + VtecObject vtecObj = VtecUtil.parseMessage(productText); if (warnGenFlag) { - // TODO: Pass in some flavor of currentDate to use to set the - // times. Currently roll over to the next minute between getting - // currentDate and getting the times in this method will cause - // them to be different. - productText = updateVtecTimes(productText, vtecObj); + /* + * DR14613 - string currectDate is derived from Date now + * ensuring the same time in WMO heading and in the + * MND heading. + */ + productText = updateVtecTimes(productText, vtecObj, now); + productText = updateHeaderTimes(productText, now); // Update editor so the proper send times are displayed. String[] b = productText.split("\n"); StringBuilder body = new StringBuilder(); @@ -4726,10 +4729,14 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, return successful; } - - /** Replaces the WMO heading DDHHMM field with the given text. - * @param productText Product text which includes the WMO heading - * @param ddhhmm Replacement text + + /** + * Replaces the WMO heading DDHHMM field with the given text. + * + * @param productText + * Product text which includes the WMO heading + * @param ddhhmm + * Replacement text * @return The modified product text */ private static String replaceDDHHMM(String productText, String ddhhmm) { @@ -4748,8 +4755,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, sb.append(' '); sb.append(s); } - if (parts.length > 1) - sb.append('\n').append(parts[1]); + if (parts.length > 1) { + sb.append('\n').append(parts[1]); + } + productText = sb.toString(); } @@ -4889,14 +4898,11 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // Capture the input from the styled text widget. StringBuffer sb = new StringBuffer(st.getText()); String errMsg = null; - // System.out.println("Initial: " + sb); - // int counter = 0; int currentIndex = 0; int startIndex = 0; int endIndex = 0; try { while (sb.indexOf(BEGIN_ELEMENT_TAG, 0) >= 0) { - // System.out.println("Trial " + counter++ + ": " + sb); currentIndex = 0; startIndex = 0; endIndex = 0; @@ -4956,7 +4962,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, */ @Override public void verifyText(VerifyEvent event) { - // System.out.println("verify text event.start="+event.star0t); int length = event.end - event.start; try { if (length == 0) { @@ -5110,19 +5115,28 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, headerTF.setText(""); } - private String getCurrentDate() { - Date now = SimulatedTime.getSystemTime().getTime(); + private String getCurrentDate(Date now) { + /* + * DR14613 - pass the Date now as an argument + */ SimpleDateFormat formatter = new SimpleDateFormat("ddHHmm"); formatter.setTimeZone(TimeZone.getTimeZone("GMT")); return (formatter.format(now)); } - private String updateVtecTimes(String product, VtecObject vtecObj) { + /** + * Update the VTEC time using the Date now. + * + * @param product + * @param vtecObj + * @param now + * @return + */ + private String updateVtecTimes(String product, VtecObject vtecObj, Date now) { if (vtecObj == null || vtecObj.getAction().equals("COR")) { return product; } - Date now = SimulatedTime.getSystemTime().getTime(); // Update the vtec start time if (vtecObj.getAction().equals("NEW")) { SimpleDateFormat vtecFormatter = new SimpleDateFormat( @@ -5131,9 +5145,20 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, product = product.replace( vtecFormatter.format(vtecObj.getStartTime().getTime()), vtecFormatter.format(now)); - } + } - // Update the header time + return product; + } + + /** + * Update the MND header time using the Date now. + * + * @param product + * @param now + * @return + */ + private String updateHeaderTimes(String product, Date now) { + // Update the header time Matcher m = datePtrn.matcher(product); if (m.find()) { SimpleDateFormat headerFormat = new SimpleDateFormat( @@ -5144,9 +5169,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, product = product.replace(m.group(1), headerFormat.format(now) .toUpperCase()); } - - return product; + return product; } + public void setCurrentWmoId(String wmoId) { TextDisplayModel.getInstance().setWmoId(token, wmoId); @@ -5203,6 +5228,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, statusBarLabel.update(); boolean hasAttachment = false; String attachedFilename = new String(); + boolean validExecuteCommand = true; try { if (queryTransport == null) { @@ -5237,7 +5263,17 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, hasAttachment = true; } - if (updating) { + String commandText = command.getCommandTextFields()[0]; + StdTextProductId stdProdId = prod.getProdId(); + + if ("MTR".equals(stdProdId.getNnnid()) + && (commandText.startsWith("ALL:") + || commandText.startsWith("A:") || commandText + .endsWith("000"))) { + stripWMOHeaders(prod); + } + + if (updateCount.get() > 0) { updateDisplayedProduct(prod); } else { setDisplayedProduct(prod); @@ -5293,10 +5329,12 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (!accumChkBtn.getSelection()) { textEditor.setText(""); } + validExecuteCommand = false; } } catch (CommandFailedException e) { statusHandler.handle(Priority.PROBLEM, "Error retrieving metatdata", e); + validExecuteCommand = false; } if (!this.isDisposed()) { @@ -5312,104 +5350,104 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } else { resendWarningProductnItem.setEnabled(true); } + + // Always give focus to textEditor after populating it. + if (validExecuteCommand) { + textEditor.setFocus(); + } } } - public void showWarngenProduct(String afosId, NotifyExpiration notify) { + private void stripWMOHeaders(StdTextProduct prod) { + String[] lines = prod.getProduct().split("\n"); + StringBuilder sb = new StringBuilder(); + for (String line : lines) { + Matcher m = METAR_PATTERN.matcher(line); + if (m.find()) { + sb.append(line).append("\n"); + } + } + prod.setProduct(sb.toString()); + } + + public void showWarngenProduct(String product, NotifyExpiration notify) { inEditMode = true; this.notify = notify; - StdTextProduct tmp = null; - final SimpleDateFormat sdf = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss.SSS"); - sdf.setTimeZone(TimeZone.getTimeZone("GMT")); - long t0 = System.currentTimeMillis(); - try { - if (queryTransport == null) { - queryTransport = TextEditorUtil.getTextDbsrvTransport(); - } - long t2 = System.currentTimeMillis(); - System.out - .println("Time getting TextDbSrv transport: " + (t2 - t0)); - ICommand cmd = CommandFactory.getAfosCommand(afosId); - long t3 = System.currentTimeMillis(); - System.out.println("Time getting afos command: " + (t3 - t2)); - tmp = cmd.executeCommand(queryTransport).get(0); - long t4 = System.currentTimeMillis(); - System.out.println("Time executing afos cmd: " + (t4 - t3)); - } catch (CommandFailedException e) { - e.printStackTrace(); - } - long t1 = System.currentTimeMillis(); - System.out - .println(sdf.format(new Date()) - + ": Text Workstation retrieving work product from database in " - + (t1 - t0) + "ms."); + String[] tokens = product.split(":", 2); - String warning = tmp.getProduct(); - String[] nnnxxx = TextDisplayModel.getNnnXxx(warning); - String siteNode = SiteAbbreviationUtil.getSiteNode(nnnxxx[1]); - String ttaaii = SiteAbbreviationUtil.getTtaaii(siteNode + nnnxxx[0] - + nnnxxx[1]); - final String w = warning.replace(TextWarningConstants.TTAAII, ttaaii); + if (tokens.length == 2) { + String afosId = tokens[0]; + String warning = tokens[1]; - TextDisplayModel.getInstance().createStdTextProduct(token, w, siteNode); + String[] nnnxxx = TextDisplayModel.getNnnXxx(warning); + String siteNode = SiteAbbreviationUtil.getSiteNode(nnnxxx[1]); + String ttaaii = SiteAbbreviationUtil.getTtaaii(siteNode + nnnxxx[0] + + nnnxxx[1]); + final String w = warning.replace(TextWarningConstants.TTAAII, + ttaaii); - workProductId = afosId.substring(3); - warnGenFlag = true; - VizApp.runAsync(new Runnable() { - @Override - public void run() { - long t0 = System.currentTimeMillis(); - // For VTEC related warning messages, turn off wordwrap by - // default. - if (textEditor == null) { - openDialog(); - } + TextDisplayModel.getInstance().createStdTextProduct(token, w, + siteNode); - if (textEditor.isDisposed()) { - return; - } + workProductId = afosId.substring(3); + warnGenFlag = true; + VizApp.runAsync(new Runnable() { + @Override + public void run() { + long t0 = System.currentTimeMillis(); + // For VTEC related warning messages, turn off wordwrap by + // default. + if (textEditor == null) { + openDialog(); + } - // textEditor.setWordWrap(false); + if (textEditor.isDisposed()) { + return; + } - // Set the text editor's contents to the warning message. - textEditor.removeVerifyListener(TextEditorDialog.this); - textEditor.setText(w); - // - // // Mark the uneditable warning text - // if (markUneditableText(textEditor)) { - // // Add listener to monitor attempt to edit locked text - // textEditor.addVerifyListener(TextEditorDialog.this); - // } - showDialog(); - long t1 = System.currentTimeMillis(); + // textEditor.setWordWrap(false); - System.out.println(sdf.format(new Date()) - + ": Text Workstation took " + (t1 - t0) - + "ms to show dialog"); - enterEditor(); + // Set the text editor's contents to the warning message. + textEditor.removeVerifyListener(TextEditorDialog.this); + textEditor.setText(w); + // + // // Mark the uneditable warning text + // if (markUneditableText(textEditor)) { + // // Add listener to monitor attempt to edit locked text + // textEditor.addVerifyListener(TextEditorDialog.this); + // } + showDialog(); + long t1 = System.currentTimeMillis(); + SimpleDateFormat sdf = new SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss.SSS"); + sdf.setTimeZone(TimeZone.getTimeZone("GMT")); + System.out.println(sdf.format(new Date()) + + ": Text Workstation took " + (t1 - t0) + + "ms to show dialog"); + enterEditor(); - if (autoWrapMenuItem != null) { - Menu menu = autoWrapMenuItem.getMenu(); - for (MenuItem item : menu.getItems()) { - if (item.getSelection()) { - Object obj = item.getData(); - if (obj instanceof WrapButtonCfg) { - WrapButtonCfg buttonCfg = (WrapButtonCfg) obj; - if (buttonCfg.isWrapEnabled()) { - charWrapCol = buttonCfg.getWrapCol(); - wordWrapEnabled = true; - recompileRegex(); - } else { - wordWrapEnabled = false; + if (autoWrapMenuItem != null) { + Menu menu = autoWrapMenuItem.getMenu(); + for (MenuItem item : menu.getItems()) { + if (item.getSelection()) { + Object obj = item.getData(); + if (obj instanceof WrapButtonCfg) { + WrapButtonCfg buttonCfg = (WrapButtonCfg) obj; + if (buttonCfg.isWrapEnabled()) { + charWrapCol = buttonCfg.getWrapCol(); + wordWrapEnabled = true; + recompileRegex(); + } else { + wordWrapEnabled = false; + } } } } } + saved = false; } - saved = false; - } - }); + }); + } } private void replaceWorkProductId() { @@ -5574,7 +5612,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } // open the script output window scriptOutput.open(); - System.out.println("output window closed..."); // update the menu following close if (scriptsShowOutputItem != null && !scriptsShowOutputItem.isDisposed()) { @@ -5779,7 +5816,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, @Override public void windowClosing() { - System.out.println("script editor window closing"); if (scriptRunner == null) { setScriptMenuControls(true); } @@ -5882,17 +5918,27 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, regex = "(METAR |SPECI )K" + product.getXxxid(); } + boolean haveWMOHeader = false; + if (regex != null) { // Find METAR to replace. // This assumes the product's METAR is the latest METAR and not a - // duplicate or older then the display. If not the case a check of + // duplicate or older in the display. If not the case a check of // the timestamp can be performed adjusting for possible roll over // to the next month. Pattern pattern = Pattern.compile(regex); for (int i = 0; i < noOfLines; ++i) { if (pattern.matcher(textEditor.getLine(i)).find()) { - // Adjust to the METAR's Wmo Header line. - lineIndex = i - 1; + lineIndex = i; + if (i > 0) { + Matcher m = METAR_PATTERN.matcher(textEditor + .getLine(i - 1)); + if (!m.find()) { + // Adjust to the METAR's Wmo Header line. + --lineIndex; + haveWMOHeader = true; + } + } break; } } @@ -5903,11 +5949,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } } else { String prefix = product.getWmoid() + " " + product.getSite(); - // System.out.println("new header" + prefix); for (int i = 0; i < noOfLines; i++) { if (textEditor.getLine(i).startsWith(prefix)) { // found replacement point - // System.out.println("found " + prefix + " at line " + i); lineIndex = i; break; } @@ -5916,46 +5960,61 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (lineIndex == -1) { lineIndex = noOfLines; } - // note: this returns the number of lines in the text display area - // Since lines are zero indexed, this points to the second line - // of the product. Assuming a WMO header, this is the first line - // of the product - // System.out.println("inserting text at: " + lineIndex); + + String productText = product.getProduct(); + if (lineIndex == noOfLines) { textEditor.append("\n"); - textEditor.append(product.getProduct()); + textEditor.append(productText); } else { // need to find end of current product, then replace. int nextProductLoc = -1; - for (int i = lineIndex + 2; i < noOfLines; i++) { - String temp = textEditor.getLine(i); - if (!temp.startsWith(" ")) { + if (haveWMOHeader) { + // Assume next product also has WMO header + for (int i = lineIndex + 2; i < noOfLines; i++) { + String temp = textEditor.getLine(i); + if (!temp.startsWith(" ")) { + if (temp.startsWith("METAR") + || temp.startsWith("SPECI")) { + continue; + } else { + // found next product + nextProductLoc = i; + break; + } + } + } + } else { + // Remove WMO header + productText = productText + .substring(productText.indexOf('\n') + 1); + // Assume next product does not have a WMO header + for (int i = lineIndex + 1; i < noOfLines; ++i) { + String temp = textEditor.getLine(i); if (temp.startsWith("METAR") || temp.startsWith("SPECI")) { - continue; - } else { - // found next product nextProductLoc = i; break; } } } + int start = textEditor.getOffsetAtLine(lineIndex); int end = textEditor.getCharCount(); if (nextProductLoc != -1) { end = textEditor.getOffsetAtLine(nextProductLoc); - textEditor.replaceTextRange(start, end - start, - product.getProduct() + "\n"); + textEditor.replaceTextRange(start, end - start, productText + + "\n"); } else { - textEditor.replaceTextRange(start, end - start, - product.getProduct()); + textEditor.replaceTextRange(start, end - start, productText); } } // if updating, we need to highlight the site name. If the first word of // the line is "METAR" or "SPECI", we need to highlight the second word - lineIndex++; // need to skip the WMO header + if (haveWMOHeader) { + lineIndex++; // need to skip the WMO header + } String line = textEditor.getLine(lineIndex); - // System.out.println(line); int startIndex = textEditor.getOffsetAtLine(lineIndex); if (line.startsWith("METAR") || line.startsWith("SPECI")) { startIndex += 6; // skip first word plus a space @@ -5970,7 +6029,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // retrieved for display in this text editor dialog // instance. TextDisplayModel.getInstance().setStdTextProduct(token, product); - updating = false; + updateCount.addAndGet(-1); } @Override @@ -6280,7 +6339,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, msgPIL = ""; } if (isObsDisplayed(msgPIL)) { - updating = true; + updateCount.addAndGet(1); ICommand command = CommandFactory.getAfosCommand(msgPIL); UpdateObsRun run = new UpdateObsRun(command); VizApp.runSync(run); @@ -7182,9 +7241,13 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } } + public void enableSend(boolean state) { + editorSendBtn.setEnabled(state); + } + public void enqueue(String afosId, NotifyExpiration notify2) { queuedNotify = notify2; - queuedAfos = afosId; + queuedProduct = afosId; } private boolean gfeForbidden(String ccc, String nnn) { diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/print/PrintDisplay.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/print/PrintDisplay.java index 6825f617cc..bb83845693 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/print/PrintDisplay.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/print/PrintDisplay.java @@ -19,13 +19,15 @@ **/ package com.raytheon.viz.texteditor.print; -import java.awt.Color; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.print.PageFormat; -import java.awt.print.Printable; -import java.awt.print.PrinterException; -import java.awt.print.PrinterJob; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.printing.Printer; +import org.eclipse.swt.printing.PrinterData; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus.Priority; @@ -39,6 +41,8 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Sep 15, 2011 10557 rferrel Initial creation + * Jul 17, 2012 14274 rferrel Now use eclipse Printer instead of awt. + * Text is printed using same font as the GUI * * * @@ -47,107 +51,182 @@ import com.raytheon.uf.common.status.UFStatus.Priority; */ public class PrintDisplay { - /** - * Print the text/document to the default print. - * - * @param autoPrint - * true send text directly to printer without prompting user for - * selecting a different printer. - * @param printedText - * the text to print. - */ - public static void print(boolean autoPrint, String printedText, + public static void print(final String printedText, final FontData fontData, IUFStatusHandler statusHandler) { - if (printedText == null || printedText.trim().length() == 0) { - // Do not waste paper on blank text. + PrinterData data = Printer.getDefaultPrinterData(); + if (data == null) { + statusHandler.handle(Priority.PROBLEM, + "No default printer specified."); return; } - PrintDisplay printer = new PrintDisplay(autoPrint, statusHandler); - printer.printIt(printedText); + if (printedText == null || printedText.trim().length() == 0) { + // Do not waste paper when nothing to print. + return; + } + + final Printer printer = new Printer(data); + PrintDisplay pd = new PrintDisplay(printer, printedText, fontData); + pd.printJob(); } - private boolean autoPrint; + private Printer printer; - private IUFStatusHandler statusHandler; + private String textToPrint; - private PrintDisplay(boolean autoPrint, IUFStatusHandler statusHandler) { - this.autoPrint = autoPrint; - this.statusHandler = statusHandler; + private FontData printerFontData; + + private int leftMargin; + + private int rightMargin; + + private int topMargin; + + private int bottomMargin; + + private String tabs; + + private GC gc; + + private int tabWidth; + + private int lineHeight; + + StringBuilder wordBuffer; + + int x; + + int y; + + int index; + + int end; + + private PrintDisplay(Printer printer, String text, FontData fontData) { + this.printer = printer; + this.textToPrint = text; + this.printerFontData = fontData; } - private void printIt(String printedText) { - PrinterJob printerJob = PrinterJob.getPrinterJob(); - - if (autoPrint || printerJob.printDialog()) { - printerJob.setPrintable(new Document(printedText)); - try { - printerJob.print(); - } catch (PrinterException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); + private void printJob() { + Thread thread = new Thread("Printing") { + public void run() { + printIt(); + printer.dispose(); } + }; + thread.start(); + } + + private void printIt() { + if (printer.startJob("Text")) { // the string is the job name - shows up + // in the printer's job list + Rectangle clientArea = printer.getClientArea(); + Rectangle trim = printer.computeTrim(0, 0, 0, 0); + Point dpi = printer.getDPI(); + + // one inch from left side of paper + leftMargin = dpi.x + trim.x; + // one inch from right side of paper + rightMargin = clientArea.width - dpi.x + trim.x + trim.width; + topMargin = dpi.y + trim.y; // one inch from top edge of paper + // one inch from bottom edge of paper + bottomMargin = clientArea.height - dpi.y + trim.y + trim.height; + + // Create a buffer for computing tab width. + int tabSize = 4; + StringBuilder tabBuffer = new StringBuilder(tabSize); + for (int i = 0; i < tabSize; i++) + tabBuffer.append(' '); + tabs = tabBuffer.toString(); + + /* + * Create printer GC, and create and set the printer font & + * foreground color. + */ + gc = new GC(printer); + Font printerFont = new Font(printer, printerFontData); + Color printerForegroundColor = new Color(printer, new RGB(0, 0, 0)); + Color printerBackgroundColor = new Color(printer, new RGB(255, 255, + 255)); + + gc.setFont(printerFont); + gc.setForeground(printerForegroundColor); + gc.setBackground(printerBackgroundColor); + tabWidth = gc.stringExtent(tabs).x; + lineHeight = gc.getFontMetrics().getHeight(); + + // Print text to current gc using word wrap + printText(); + printer.endJob(); + + // Cleanup graphics resources used in printing + printerFont.dispose(); + printerForegroundColor.dispose(); + printerBackgroundColor.dispose(); + gc.dispose(); } } - private class Document implements Printable { - - private final String[] printedText; - - private int numPages = 0; - - public Document(String printedText) { - super(); - this.printedText = printedText.split("\n"); + private void printText() { + printer.startPage(); + wordBuffer = new StringBuilder(); + x = leftMargin; + y = topMargin; + index = 0; + end = textToPrint.length(); + while (index < end) { + char c = textToPrint.charAt(index); + index++; + if (c != 0) { + if (c == 0x0a || c == 0x0d) { + if (c == 0x0d && index < end + && textToPrint.charAt(index) == 0x0a) { + index++; // if this is cr-lf, skip the lf + } + printWordBuffer(); + newline(); + } else { + if (c != '\t') { + wordBuffer.append(c); + } + if (Character.isWhitespace(c)) { + printWordBuffer(); + if (c == '\t') { + x += tabWidth; + } + } + } + } } + if (y + lineHeight <= bottomMargin) { + printer.endPage(); + } + } - @Override - public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) - throws PrinterException { - // --- Create the Graphics2D object - Graphics2D g2d = (Graphics2D) graphics; - - // --- Set the drawing color to black - g2d.setPaint(Color.black); - java.awt.Font font = g2d.getFont(); - String name = font.getName(); - int style = font.getStyle(); - int size = font.getSize(); - - g2d.setFont(new java.awt.Font(name, style, size - 2)); - - // --- Translate the origin to 0,0 for the top left corner - g2d.translate(pageFormat.getImageableX(), - pageFormat.getImageableY()); - - // Determine the lines per page and number of pages to print. - java.awt.FontMetrics metrics = g2d.getFontMetrics(); - int lineHeight = metrics.getHeight(); - int linesPerPage = (int) Math.floor(pageFormat.getImageableHeight() - / lineHeight); - numPages = ((printedText.length - 1) / linesPerPage) + 1; - - // Calculate the start line for this page. - int startLine = pageIndex * linesPerPage; - int endLine = startLine + linesPerPage - 1; - if (endLine >= printedText.length) { - endLine = printedText.length - 1; + private void printWordBuffer() { + if (wordBuffer.length() > 0) { + String word = wordBuffer.toString(); + int wordWidth = gc.stringExtent(word).x; + if (x + wordWidth > rightMargin) { + // word doesn't fit on current line, so wrap + newline(); } + gc.drawString(word, x, y, false); + x += wordWidth; + wordBuffer.setLength(0); + } + } - // Tell the PrinterJob if the page number is not a legal one. - if (pageIndex >= numPages) { - return NO_SUCH_PAGE; + private void newline() { + x = leftMargin; + y += lineHeight; + if (y + lineHeight > bottomMargin) { + printer.endPage(); + if (index + 1 < end) { + y = topMargin; + printer.startPage(); } - - int y = 0; - for (int i = startLine; i <= endLine; i++) { - y += lineHeight; - g2d.drawString(printedText[i], 0, y); - } - - g2d.dispose(); - // --- Validate the page - return (PAGE_EXISTS); } } } \ No newline at end of file diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/qc/IQCCheck.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/qc/IQCCheck.java index eda6d4048d..0a5d9d1365 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/qc/IQCCheck.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/qc/IQCCheck.java @@ -32,6 +32,8 @@ import java.util.regex.Pattern; * ------------ ---------- ----------- -------------------------- * Initial creation * Aug 25, 2011 10719 rferrel Removed the no longer common ugcPtrn. + * Aug 6, 2012 15219 Qinglu Lin For tmlPtrn, changed d{1,3}DEG to d{3}DEG. + * * * @version 1.0 @@ -72,7 +74,7 @@ public interface IQCCheck { .compile("\\s{1,}\\d{3,4}\\s\\d{3,5}(|(\\s\\d{3,4}\\s\\d{3,5}){1,})"); public static final Pattern tmlPtrn = Pattern - .compile("TIME...MOT...LOC \\d{3,4}Z\\s\\d{1,3}DEG\\s\\d{1,3}KT((\\s\\d{3,4}\\s\\d{3,5}){1,})"); + .compile("TIME...MOT...LOC \\d{3,4}Z\\s\\d{3}DEG\\s\\d{1,3}KT((\\s\\d{3,4}\\s\\d{3,5}){1,})"); public static final Pattern subTMLPtrn = Pattern .compile("(\\d{3,5}\\s){1,}"); diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/util/SiteAbbreviationUtil.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/util/SiteAbbreviationUtil.java index f131873652..f6d37b613b 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/util/SiteAbbreviationUtil.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/util/SiteAbbreviationUtil.java @@ -25,6 +25,7 @@ import com.raytheon.uf.common.site.SiteMap; import com.raytheon.uf.viz.core.catalog.DirectDbQuery; import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage; import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.localization.LocalizationManager; import com.raytheon.viz.texteditor.TextWarningConstants; /** @@ -45,6 +46,22 @@ import com.raytheon.viz.texteditor.TextWarningConstants; public class SiteAbbreviationUtil { + private static String mySiteNode; + + /** + * Returns the 3 letter site node for the current localization. + * + * @return + */ + public static String getMySiteNode() { + if (mySiteNode == null) { + mySiteNode = getSiteNode(LocalizationManager.getInstance() + .getCurrentSite()); + } + + return mySiteNode; + } + /** * Grabs the site node from the FXA database afoslookup table. * diff --git a/cave/com.raytheon.viz.textworkstation/src/com/raytheon/viz/textworkstation/TextWorkstationDlg.java b/cave/com.raytheon.viz.textworkstation/src/com/raytheon/viz/textworkstation/TextWorkstationDlg.java index b72e6e73b4..d6a77e7f38 100755 --- a/cave/com.raytheon.viz.textworkstation/src/com/raytheon/viz/textworkstation/TextWorkstationDlg.java +++ b/cave/com.raytheon.viz.textworkstation/src/com/raytheon/viz/textworkstation/TextWorkstationDlg.java @@ -22,6 +22,7 @@ package com.raytheon.viz.textworkstation; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import java.util.Timer; @@ -110,9 +111,9 @@ public class TextWorkstationDlg extends CaveSWTDialog implements private Label utcTimeLabel; - private Label gmtTimeLabel; + private Label localTimeLabel; - SimpleDateFormat sdfGMT = new SimpleDateFormat("EEE dd MMM yyyy HH:mm z"); + SimpleDateFormat sdfLocal = new SimpleDateFormat("EEE dd MMM yyyy HH:mm z"); SimpleDateFormat sdfUTC = new SimpleDateFormat("EEE dd MMM yyyy HH:mm z"); @@ -197,8 +198,8 @@ public class TextWorkstationDlg extends CaveSWTDialog implements } private void initializeComponents() { - sdfGMT.setTimeZone(TimeZone.getTimeZone("GMT")); sdfUTC.setTimeZone(TimeZone.getTimeZone("UTC")); + sdfLocal.setTimeZone(Calendar.getInstance().getTimeZone()); createMenus(); new Label(shell, SWT.NONE).setText("host: " @@ -365,16 +366,18 @@ public class TextWorkstationDlg extends CaveSWTDialog implements } private void createTimeLabels() { - GridData gd = new GridData(300, SWT.DEFAULT); - gmtTimeLabel = new Label(shell, SWT.CENTER); - gmtTimeLabel.setLayoutData(gd); + GridData gd = null; gd = new GridData(300, SWT.DEFAULT); utcTimeLabel = new Label(shell, SWT.CENTER); utcTimeLabel.setLayoutData(gd); + gd = new GridData(300, SWT.DEFAULT); + localTimeLabel = new Label(shell, SWT.CENTER); + localTimeLabel.setLayoutData(gd); + date = SimulatedTime.getSystemTime().getTime(); - gmtTimeLabel.setText(sdfGMT.format(date)); + localTimeLabel.setText(sdfLocal.format(date)); utcTimeLabel.setText(sdfUTC.format(date)); } @@ -510,7 +513,7 @@ public class TextWorkstationDlg extends CaveSWTDialog implements private void updateTimeLabels() { date = SimulatedTime.getSystemTime().getTime(); - gmtTimeLabel.setText(sdfGMT.format(date)); + localTimeLabel.setText(sdfLocal.format(date)); utcTimeLabel.setText(sdfUTC.format(date)); } @@ -596,14 +599,14 @@ public class TextWorkstationDlg extends CaveSWTDialog implements // messages. delta += TextWorkstationDlg.incDelta; } else if (message.isNotExpired()) { - String afosId = message.getMessagePayload().toString(); + String product = message.getMessagePayload().toString(); if (wgDlg == null) { - productToDisplay = afosId; + productToDisplay = product; } else { if (!wgDlg.isEditMode()) { - wgDlg.showWarngenProduct(afosId, notify); + wgDlg.showWarngenProduct(product, notify); } else { - wgDlg.enqueue(afosId, notify); + wgDlg.enqueue(product, notify); } } } diff --git a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/VizWorkbenchManager.java b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/VizWorkbenchManager.java index a45c3b9d47..de749799bb 100644 --- a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/VizWorkbenchManager.java +++ b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/VizWorkbenchManager.java @@ -394,6 +394,9 @@ public class VizWorkbenchManager implements IPartListener, IPartListener2, } activeEditorMap .put(part.getSite().getWorkbenchWindow(), active); + if (active instanceof IDisplayPaneContainer) { + notifyListeners(); + } } } } diff --git a/cave/com.raytheon.viz.volumebrowser/localization/menus/xml/fieldsMenus.xml b/cave/com.raytheon.viz.volumebrowser/localization/menus/xml/fieldsMenus.xml index 1a7d1e5442..b1021f011f 100644 --- a/cave/com.raytheon.viz.volumebrowser/localization/menus/xml/fieldsMenus.xml +++ b/cave/com.raytheon.viz.volumebrowser/localization/menus/xml/fieldsMenus.xml @@ -529,9 +529,9 @@ - - diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/comm/WarningSender.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/comm/WarningSender.java index b985c4cdc7..0eeb06932a 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/comm/WarningSender.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/comm/WarningSender.java @@ -33,12 +33,12 @@ import javax.jms.MessageProducer; import javax.jms.Session; import com.raytheon.uf.common.dataplugin.text.request.InsertStdTextProductRequest; -import com.raytheon.uf.common.serialization.DynamicSerializationManager; -import com.raytheon.uf.common.serialization.DynamicSerializationManager.SerializationType; +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.viz.core.comm.JMSConnection; +import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.localization.LocalizationManager; import com.raytheon.uf.viz.core.requests.ThriftClient; import com.raytheon.viz.core.mode.CAVEMode; @@ -65,173 +65,209 @@ import com.raytheon.viz.texteditor.util.SiteAbbreviationUtil; */ public class WarningSender implements IWarngenObserver { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(WarningSender.class); + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(WarningSender.class); - private String hostName = null; + private String hostName = null; - private boolean notifyError; + private boolean notifyError; - private static final long MILLISECONDS_PER_SECOND = 1000; + private static final long MILLISECONDS_PER_SECOND = 1000; - private static final long SECONDS_PER_MINUTE = 60; + private static final long SECONDS_PER_MINUTE = 60; - private static final long TTL_MINUTES = 5; + private static final long TTL_MINUTES = 5; - private static Pattern PATTERN = Pattern.compile("(\\d{1,1})"); + private static Pattern PATTERN = Pattern.compile("(\\d{1,1})"); - private static final SimpleDateFormat sdf; + private static final SimpleDateFormat sdf; - static { - sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - sdf.setTimeZone(TimeZone.getTimeZone("GMT")); - } + static { + sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + sdf.setTimeZone(TimeZone.getTimeZone("GMT")); + } - /* - * (non-Javadoc) Incoming message was not a binary - * - * @see - * com.raytheon.viz.texteditor.msgs.IWarngenObserver#setTextWarngenDisplay - * (java.lang.String) - */ - @Override - public void setTextWarngenDisplay(String warning, boolean ne) { - this.notifyError = ne; + /* + * (non-Javadoc) Incoming message was not a binary + * + * @see + * com.raytheon.viz.texteditor.msgs.IWarngenObserver#setTextWarngenDisplay + * (java.lang.String) + */ + @Override + public void setTextWarngenDisplay(String warning, boolean ne) { + this.notifyError = ne; - String number = "0"; - String host = TextWorkstationConstants.getId(); - long t0 = System.currentTimeMillis(); - String siteNode = SiteAbbreviationUtil.getSiteNode(LocalizationManager - .getInstance().getCurrentSite()); - System.out.println("Get site node time: " - + (System.currentTimeMillis() - t0)); - if (host == null) { - statusHandler.handle(Priority.ERROR, - "Text Workstation host not set in preferences."); - } else { - Matcher m = PATTERN.matcher(host); - if (m.find()) { - number = m.group(); - } - } + String number = "0"; + String host = TextWorkstationConstants.getId(); + long t0 = System.currentTimeMillis(); + String siteNode = SiteAbbreviationUtil.getSiteNode(LocalizationManager + .getInstance().getCurrentSite()); + System.out.println("Get site node time: " + + (System.currentTimeMillis() - t0)); + if (host == null) { + statusHandler.handle(Priority.ERROR, + "Text Workstation host not set in preferences."); + } else { + Matcher m = PATTERN.matcher(host); + if (m.find()) { + number = m.group(); + } + } - String id = siteNode + "WRKWG" + number; + String id = siteNode + "WRKWG" + number; + boolean sentToTextDatabase = false; - try { - CAVEMode mode = CAVEMode.getMode(); - boolean operationalMode = (CAVEMode.OPERATIONAL.equals(mode) - || CAVEMode.TEST.equals(mode) ? true : false); + try { + boolean messageNotSent = true; + int connectCount = 0; + t0 = System.currentTimeMillis(); + byte[] data = SerializationUtil.transformToThrift(id + ":" + + warning); + while (messageNotSent && connectCount < 4) { + Session s = null; + MessageProducer mp = null; + Connection conn = null; + try { + conn = JMSConnection.getInstance().getFactory() + .createConnection(); + s = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE); + mp = s.createProducer(s + .createQueue(TextWorkstationConstants + .getDestinationTextWorkstationQueueName())); + mp.setTimeToLive(TTL_MINUTES * SECONDS_PER_MINUTE + * MILLISECONDS_PER_SECOND); + BytesMessage m = s.createBytesMessage(); + m.writeBytes(data); + mp.send(m); + long t1 = System.currentTimeMillis(); + System.out.println(WarningSender.getCurTimeString() + ": " + + id + " sent to text workstation in " + (t1 - t0) + + "ms in " + (connectCount + 1) + + (connectCount > 0 ? " tries" : " try")); + messageNotSent = false; + } catch (JMSException e) { + if (notifyError) { + statusHandler + .handle(Priority.PROBLEM, + "Error trying to send product [" + + id + + "] to Text Workstation. Attempting to reconnect. ", + e); + notifyError = false; + } + } finally { + if (mp != null) { + try { + mp.close(); + mp = null; + } catch (Exception e) { + mp = null; + } + } + if (s != null) { + try { + s.close(); + s = null; + } catch (Exception e) { + s = null; + } + } + if (conn != null) { + try { + conn.close(); + conn = null; + } catch (Exception e) { + conn = null; + } + } + } + if (messageNotSent) { + if (!sentToTextDatabase) { + try { + sendToTextDatabase(id, warning); + sentToTextDatabase = true; + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Error trying to save product [" + id + + "] to Text Database: ", e); + } + } - // Generate StdTextProduct and insert into db - t0 = System.currentTimeMillis(); - ThriftClient.sendRequest(new InsertStdTextProductRequest(id, - warning, operationalMode)); + connectCount++; + switch (connectCount) { + case 1: + Thread.sleep(1000); + break; + case 2: + Thread.sleep(5 * 1000); + break; + case 3: + Thread.sleep(30 * 1000); + break; + case 4: + statusHandler.handle(Priority.PROBLEM, + "Could not reconnect (" + id + + ") after 3 tries: ", null); + break; + } + } + } - System.out.println(WarningSender.getCurTimeString() + ": " + id - + " saved to textdb in " - + (System.currentTimeMillis() - t0) + "ms"); + if (!sentToTextDatabase) { + try { + sendToTextDatabase(id, warning); + sentToTextDatabase = true; + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Error trying to save product [" + id + + "] to Text Database: ", e); + } + } + } catch (UnknownHostException uhe) { + if (notifyError) { + statusHandler.handle(Priority.PROBLEM, + "unable to map hostname, " + hostName + + ", to an ip address", uhe); + notifyError = false; + } - boolean messageNotSent = true; - int connectCount = 0; - t0 = System.currentTimeMillis(); - while (messageNotSent && connectCount < 4) { - Session s = null; - MessageProducer mp = null; - Connection conn = null; - try { - conn = JMSConnection.getInstance().getFactory() - .createConnection(); - s = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE); - mp = s.createProducer(s - .createQueue(TextWorkstationConstants - .getDestinationTextWorkstationQueueName())); - mp.setTimeToLive(TTL_MINUTES * SECONDS_PER_MINUTE - * MILLISECONDS_PER_SECOND); - BytesMessage m = s.createBytesMessage(); - m.writeBytes(DynamicSerializationManager.getManager( - SerializationType.Thrift).serialize(id)); - mp.send(m); - System.out.println(WarningSender.getCurTimeString() + ": " - + id + " sent to text workstation in " - + (System.currentTimeMillis() - t0) + "ms"); - messageNotSent = false; - } catch (JMSException e) { - if (notifyError) { - statusHandler - .handle(Priority.PROBLEM, - "Error trying to send message (" - + id - + ") to Text Workstation. Attempting to reconnect. ", - e); - notifyError = false; - } - } finally { - if (mp != null) { - try { - mp.close(); - mp = null; - } catch (Exception e) { - mp = null; - } - } - if (s != null) { - try { - s.close(); - s = null; - } catch (Exception e) { - s = null; - } - } - if (conn != null) { - try { - conn.close(); - conn = null; - } catch (Exception e) { - conn = null; - } - } - } - if (messageNotSent) { - connectCount++; - switch (connectCount) { - case 1: - Thread.sleep(1000); - break; - case 2: - Thread.sleep(5 * 1000); - break; - case 3: - Thread.sleep(30 * 1000); - break; - case 4: - statusHandler.handle(Priority.PROBLEM, - "Could not reconnect (" + id - + ") after 3 tries: ", null); - break; - } - } - } - } catch (UnknownHostException uhe) { - if (notifyError) { - statusHandler.handle(Priority.PROBLEM, - "unable to map hostname, " + hostName - + ", to an ip address", uhe); - notifyError = false; - } + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Error trying to send product [" + id + + "] to Text Workstation: ", e); + } - } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, - "Error trying to send message (" + id - + ") to Text Workstation: ", e); - } + } - } + /** + * Saves a product to the text database. + * + * @param id + * @param warning + * @throws VizException + */ + public static void sendToTextDatabase(String id, String warning) + throws VizException { + CAVEMode mode = CAVEMode.getMode(); + boolean operationalMode = (CAVEMode.OPERATIONAL.equals(mode) + || CAVEMode.TEST.equals(mode) ? true : false); - public static String getCurTimeString() { - String rval = null; - synchronized (sdf) { - rval = sdf.format(new Date()); - } - return rval; - } + // Generate StdTextProduct and insert into db + long t0 = System.currentTimeMillis(); + ThriftClient.sendRequest(new InsertStdTextProductRequest(id, warning, + operationalMode)); + + System.out.println(WarningSender.getCurTimeString() + ": " + id + + " saved to textdb in " + (System.currentTimeMillis() - t0) + + "ms"); + } + + public static String getCurTimeString() { + String rval = null; + synchronized (sdf) { + rval = sdf.format(new Date()); + } + return rval; + } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbPointSourceDataAdaptor.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbPointSourceDataAdaptor.java index 351224ce2c..fd530137b8 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbPointSourceDataAdaptor.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/config/DbPointSourceDataAdaptor.java @@ -19,15 +19,20 @@ **/ package com.raytheon.viz.warngen.config; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.commons.lang.StringUtils; + import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.geospatial.SpatialQueryResult; +import com.raytheon.uf.viz.core.maps.rsc.DbMapQueryFactory; import com.raytheon.viz.warngen.PreferenceUtil; import com.raytheon.viz.warngen.gis.ClosestPoint; import com.vividsolutions.jts.geom.Coordinate; diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java index d9a6e9f085..1448711c68 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java @@ -336,7 +336,9 @@ public class Area { for (int i = 0; i < warnArea.getNumGeometries(); i++) { Geometry geom = warnArea.getGeometryN(i); if (f.geometry.intersects(geom)) { - GeometryUtil.buildGeometryList(geoms, f.geometry); + Geometry intersect = f.geometry.intersection(geom); + intersect.setUserData(f.geometry.getUserData()); + GeometryUtil.buildGeometryList(geoms, intersect); break; } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Wx.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Wx.java index f182519702..f7fc246d90 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Wx.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Wx.java @@ -53,6 +53,8 @@ import com.raytheon.uf.common.dataplugin.warning.config.PathcastConfiguration; import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration; import com.raytheon.uf.common.dataplugin.warning.config.PointSourceConfiguration.SearchMethod; import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration; +import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialData; +import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialFactory; import com.raytheon.uf.common.dataplugin.warning.util.FileUtil; import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.geospatial.DestinationGeodeticCalculator; @@ -264,6 +266,7 @@ public class Wx { Date start = DateUtil.roundDate(new Date(wwaStartTime + delta), pathcastConfiguration.getInterval()); Date stormTime = new Date(wwaStartTime); + DestinationGeodeticCalculator gc = new DestinationGeodeticCalculator(); while (start.getTime() <= wwaStopTime) { PathCast cast = new PathCast(); cast.time = new Date(start.getTime()); @@ -277,7 +280,6 @@ public class Wx { Coordinate[] pathCoords = new Coordinate[stormLocations.length]; for (int i = 0; i < pathCoords.length; ++i) { Coordinate loc = stormLocations[i]; - DestinationGeodeticCalculator gc = new DestinationGeodeticCalculator(); gc.setStartingGeographicPoint(loc.x, loc.y); long time = (cast.time.getTime() - stormTime.getTime()) / 1000; double distance = stormTrackState.speed * time; @@ -363,11 +365,9 @@ public class Wx { null, false, SearchMode.INTERSECTS); } - SpatialQueryResult[] timeZoneFeatures = SpatialQueryFactory - .create().query(timezoneTable, - new String[] { timezoneField }, - bufferedPathCastArea, null, false, - SearchMode.INTERSECTS); + // timeZones are limited, use data for whole CWA and further + // intersection later + GeospatialData[] timeZones = GeospatialFactory.getTimezones(); Map> pcPoints = new HashMap>(); for (PathCast pc : pathcasts) { @@ -383,7 +383,8 @@ public class Wx { Point centroid = pcGeom != null ? pcGeom.getCentroid() : warningPolygon.getCentroid(); - SpatialQueryResult myArea = null, myTz = null; + SpatialQueryResult myArea = null; + GeospatialData myTz = null; if (areaFeatures != null) { // Find area and parent area @@ -395,13 +396,13 @@ public class Wx { } } - if (timeZoneFeatures != null) { + if (timeZones != null) { // Find time zone - if (timeZoneFeatures.length == 1) { - myTz = timeZoneFeatures[0]; + if (timeZones.length == 1) { + myTz = timeZones[0]; } else { - for (SpatialQueryResult tzResult : timeZoneFeatures) { - if (tzResult.geometry.contains(centroid)) { + for (GeospatialData tzResult : timeZones) { + if (tzResult.prepGeom.contains(centroid)) { myTz = tzResult; break; } @@ -435,7 +436,9 @@ public class Wx { } // Find closest points - List points = new ArrayList(); + GeodeticCalculator gc = new GeodeticCalculator(); + List points = new ArrayList( + ptFeatures.length); for (SpatialQueryResult pointRslt : ptFeatures) { Geometry localPt = (Geometry) pointRslt.attributes .get(transformedKey); @@ -467,7 +470,6 @@ public class Wx { cp.distance = minDist; cp.roundedDistance = (int) metersToDistance .convert(minDist); - GeodeticCalculator gc = new GeodeticCalculator(); gc.setStartingGeographicPoint(cp.point.x, cp.point.y); gc.setDestinationGeographicPoint(closestCoord.x, closestCoord.y); @@ -529,8 +531,7 @@ public class Wx { // check for same point in other pathcast objects. If same point // exists, remove from which ever pathcast is furthest away Set closestPtNames = new HashSet(30); - List tmpPoints = new ArrayList( - maxCount); + List tmpPoints = new ArrayList(maxCount); Queue tmp = new ArrayDeque(pathcasts); while (tmp.isEmpty() == false) { PathCast pc = tmp.remove(); @@ -560,14 +561,14 @@ public class Wx { tmpPoints.clear(); for (int i = 0; i < points.size() && i < maxCount; ++i) { - ClosestPoint point = points.get(i); - String name = point.getName(); - if (!closestPtNames.contains(name)) { - // To prevent duplicate cities in pathcast, - // only unused point is added to tmpPoints - tmpPoints.add(point); - closestPtNames.add(name); - } + ClosestPoint point = points.get(i); + String name = point.getName(); + if (!closestPtNames.contains(name)) { + // To prevent duplicate cities in pathcast, + // only unused point is added to tmpPoints + tmpPoints.add(point); + closestPtNames.add(name); + } } if (tmpPoints.size() > 0) { pc.points = tmpPoints.toArray(new ClosestPoint[tmpPoints @@ -711,7 +712,7 @@ public class Wx { // Sort by fields should have been validated to be same as well List fields = pointConfigs[0].getSortBy() != null ? Arrays - .asList(pointConfigs[0].getSortBy()) : new ArrayList(); + .asList(pointConfigs[0].getSortBy()) : new ArrayList(0); Geometry searchArea = null; double bufferVal = thresholdInMeters; @@ -734,9 +735,9 @@ public class Wx { stormCoords.length + endStormCoords.length); allCoords.addAll(Arrays.asList(stormCoords)); long time = (wwaStopTime - wwaStartTime) / 1000; + DestinationGeodeticCalculator gc = new DestinationGeodeticCalculator(); for (int i = stormCoords.length - 1; i >= 0; --i) { Coordinate loc = stormCoords[i]; - DestinationGeodeticCalculator gc = new DestinationGeodeticCalculator(); gc.setStartingGeographicPoint(loc.x, loc.y); double distance = stormTrackState.speed * time; gc.setDirection(StormTrackDisplay @@ -769,25 +770,32 @@ public class Wx { List availablePoints = new ArrayList(); for (PointSourceConfiguration pointConfig : pointConfigs) { + long t0 = System.currentTimeMillis(); availablePoints.addAll(DataAdaptorFactory.createPointSource( pointConfig).getData(config, pointConfig, bufferedSearchArea, localizedSite)); + long t1 = System.currentTimeMillis(); + System.out.println("getClosestPoint.dbQuery took " + (t1 - t0) + + " for point source " + pointConfig.getPointSource()); } // Convert searchArea to a local projection Geometry localSearchArea = JTS.transform(searchArea, latLonToLocal); - List> points = new ArrayList>(); Coordinate[] localCoords = localSearchArea.getCoordinates(); Coordinate[] coords = searchArea.getCoordinates(); + List> points = new ArrayList>( + coords.length); + GeodeticCalculator gc = new GeodeticCalculator(); + Map nameMap = new HashMap( + (int) (availablePoints.size() * 1.3)); for (int i = 0; i < coords.length; ++i) { Coordinate coord = localCoords[i]; Geometry localDistanceGeom = dimensions == 1 ? localSearchArea : gf .createPoint(coord); Geometry distanceGeom = dimensions == 1 ? searchArea : gf .createPoint(coords[i]); - List pts = new ArrayList(); - Map nameMap = new HashMap(); + nameMap.clear(); for (ClosestPoint cp : availablePoints) { Geometry localPt = JTS.transform(gf.createPoint(cp.point), @@ -800,16 +808,10 @@ public class Wx { ClosestPoint existingPt = nameMap.get(cp.name); if (existingPt == null || distance < existingPt.distance) { // Set the distances - ClosestPoint cp2 = new ClosestPoint(cp); - cp2.distance = distance; + ClosestPoint cp2 = new ClosestPoint(cp); + cp2.distance = distance; cp2.roundedDistance = (int) metersToDistance .convert(distance); - // No point by name or we are better at this location - if (existingPt != null) { - // There was an existing point, remove it - pts.remove(existingPt); - } - GeodeticCalculator gc = new GeodeticCalculator(); gc.setStartingGeographicPoint(cp2.point.x, cp2.point.y); Coordinate cen = distanceGeom.getCentroid() .getCoordinate(); @@ -822,11 +824,12 @@ public class Wx { cp2.oppositeRoundedAzimuth = ClosestPoint .adjustAngle(cp2.roundedAzimuth + 180); nameMap.put(cp2.name, cp2); - pts.add(cp2); } } } + List pts = new ArrayList( + nameMap.values()); if (fields.isEmpty() == false) { // Sort the points based on sortBy fields Collections.sort(pts, new ClosestPointComparator(fields)); @@ -839,38 +842,52 @@ public class Wx { } // Filter to maxCount (Somewhat duplicate logic as pathcast) - Queue> tmp = new ArrayDeque>( - points); - while (tmp.isEmpty() == false) { - List pts = tmp.remove(); - for (int i = 0; i < pts.size() && i < maxCount; ++i) { - // For each point, look for duplicate points in another - ClosestPoint cp = pts.get(i); - for (List pts2 : tmp) { - if (pts2 != pts) { - ClosestPoint found = find(cp, pts2, maxCount); - if (found != null) { - // We found a point within maxCount in this - // list. - if (found.distance < cp.distance) { - // This point is closer to the other - pts.remove(i--); - break; - } else { - // Remove from other pathcast, we are closer - pts2.remove(found); + if (points.size() == 1) { + // optimized for single instance + List pts = points.get(0); + if (pts.size() > maxCount) { + // need to reduce points + pts.subList(maxCount, pts.size()).clear(); + } + } else if (points.size() > 1) { + Queue> tmp = new ArrayDeque>( + points); + while (!tmp.isEmpty()) { + List pts = tmp.remove(); + int maxIndex = Math.min(pts.size(), maxCount); + for (int i = 0; i < maxIndex; ++i) { + // For each point, look for duplicate points in another + ClosestPoint cp = pts.get(i); + for (List pts2 : tmp) { + if (pts2 != pts) { + ClosestPoint found = find(cp, pts2, maxCount); + if (found != null) { + // We found a point within maxCount in this + // list. + if (found.distance < cp.distance) { + // This point is closer to the other + pts.remove(i--); + // changed size of pts, may need to change + // maxIndex + if (pts.size() < maxIndex) { + maxIndex--; + } + break; + } else { + // Remove from other pathcast, we are + // closer + pts2.remove(found); + } } } } } - } - List tmpPoints = new ArrayList(maxCount); - for (int i = 0; i < pts.size() && i < maxCount; ++i) { - tmpPoints.add(pts.get(i)); + if (pts.size() > maxIndex) { + // need to reduce points + pts.subList(maxIndex, pts.size()).clear(); + } } - pts.clear(); - pts.addAll(tmpPoints); } if (points.size() == 1) { List rval = points.get(0); 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 d357d3ae62..9c0ecffe9c 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 @@ -2045,14 +2045,12 @@ public class WarngenDialog extends CaveSWTDialog implements /** * Set the shell to visible and then move it on top of the CAVE dialog. */ - public void showDialog(boolean show) { - if (shell != null && shell.isDisposed() == false) { - if (shell.isVisible() != show) { - // Only call setVisible if we aren't what we need - shell.setVisible(show); - } - + public void showDialog(boolean show) { + if (shell != null && shell.isDisposed() == false) { if (show) { + if (shell.isVisible() == false) { + shell.setVisible(true); + } // Move above parent shell if we are showing it shell.moveAbove(getParent()); } 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 e2aa149cc5..21549832db 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 @@ -1229,7 +1229,7 @@ public class WarngenLayer extends AbstractStormTrackResource { ((oldWarningPolygon.intersection(warningPolygon) .getArea() / oldWarningArea.getArea()) * 100)) .intValue(); - if (oldWarningPolygon.intersects(warningPolygon) == false + if (GeometryUtil.intersects(oldWarningPolygon, warningPolygon) == false && !state.isMarked()) { // Snap back to polygon state.setWarningPolygon(localToLatLon((Polygon) oldWarningPolygon)); @@ -1868,7 +1868,7 @@ public class WarngenLayer extends AbstractStormTrackResource { IDisplayPaneContainer container = getResourceContainer(); Coordinate[] coords = warningPolygon.getExteriorRing().getCoordinates(); - if (vertexId >= coords.length) { + if (vertexId >= coords.length || vertexId < 0) { return vertexId; } int rval = vertexId; diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java index bec48e778f..c7684911d7 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java @@ -126,7 +126,6 @@ public class WarngenUIManager extends InputAdapter { @Override public boolean handleMouseDown(int x, int y, int button) { warngenLayer.showDialog(true); - menuMove = false; lastMouseX = x; lastMouseY = y; if (!handleInput || warngenLayer.isBoxEditable() == false) { @@ -135,7 +134,7 @@ public class WarngenUIManager extends InputAdapter { boolean rval = false; if (button == 1 && moveType != null) { return true; - } else if (button == 2) { + } else if (button == 2 && menuMove == false) { /** Try to add vertex */ new AddVertexAction().run(); if (pointCreated) { @@ -202,11 +201,7 @@ public class WarngenUIManager extends InputAdapter { return super.handleMouseUp(x, y, mouseButton); } - if (mouseButton == 2 && !pointCreated) { - new DeleteVertexAction().run(); - } - - if (mouseButton == 3) { + if (mouseButton == 3 && menuMove == false) { Coordinate c = container.translateClick(x, y); WarngenUIState state = warngenLayer.getWarngenState(); boolean geomsEqual = true; @@ -248,13 +243,14 @@ public class WarngenUIManager extends InputAdapter { boolean rval = false; - if (moveType != null || pointDeleted || pointCreated) { + if (moveType != null || pointDeleted || pointCreated || menuMove) { try { if (moveType == MoveType.ALL_POINTS) { WarngenUIState state = warngenLayer.getWarngenState(); - Coordinate[] coordinates = state.getWarningPolygon().getCoordinates(); + Coordinate[] coordinates = state.getWarningPolygon() + .getCoordinates(); PolygonUtil.truncate(coordinates, 2); - + GeometryFactory gf = new GeometryFactory(); LinearRing lr = gf.createLinearRing(coordinates); state.setWarningPolygon(gf.createPolygon(lr, null)); @@ -268,15 +264,13 @@ public class WarngenUIManager extends InputAdapter { } pointDeleted = false; pointCreated = false; + menuMove = false; return rval; } @Override public boolean handleMouseMove(int x, int y) { if (menuMove) { - movePointIndex = StormTrackUIManager.getCoordinateIndex( - warngenLayer, warngenLayer.getPolygon().getCoordinates(), - new Coordinate(lastMouseX, lastMouseY)); move(x, y); warngenLayer.getWarngenState().geometryChanged = true; return true; @@ -425,11 +419,15 @@ public class WarngenUIManager extends InputAdapter { Coordinate toRemove = (Coordinate) coords[idx].clone(); GeometryFactory gf = new GeometryFactory(); List coordList = new ArrayList(); - + List alreadyRemoved = new ArrayList(); + for (int i = 0; i < coords.length; ++i) { Coordinate toAdd = (Coordinate) coords[i].clone(); - if (!toAdd.equals(toRemove)) { + if (!toAdd.equals(toRemove) + || alreadyRemoved.contains(toAdd)) { coordList.add(toAdd); + } else { + alreadyRemoved.add(toAdd); } } @@ -441,11 +439,11 @@ public class WarngenUIManager extends InputAdapter { LinearRing lr = gf.createLinearRing(coordList .toArray(new Coordinate[coordList.size()])); Polygon newPoly = gf.createPolygon(lr, null); - + if (newPoly.isValid() == false) { return; } - + warngenLayer.getWarngenState().setWarningPolygon(newPoly); try { warngenLayer.updateWarnedAreas(true, true); @@ -498,6 +496,9 @@ public class WarngenUIManager extends InputAdapter { @Override public void run() { moveType = MoveType.SINGLE_POINT; + movePointIndex = StormTrackUIManager.getCoordinateIndex( + warngenLayer, warngenLayer.getPolygon().getCoordinates(), + new Coordinate(lastMouseX, lastMouseY)); menuMove = true; } @@ -511,6 +512,9 @@ public class WarngenUIManager extends InputAdapter { @Override public void run() { moveType = MoveType.ALL_POINTS; + movePointIndex = StormTrackUIManager.getCoordinateIndex( + warngenLayer, warngenLayer.getPolygon().getCoordinates(), + new Coordinate(lastMouseX, lastMouseY)); menuMove = true; } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java index fc75fba333..e162b349d9 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java @@ -29,14 +29,15 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.HashMap; import java.util.Properties; import java.util.Set; +import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -100,7 +101,6 @@ import com.raytheon.viz.warngen.util.WeatherAdvisoryWatch; import com.raytheon.viz.warnings.DateUtil; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.prep.PreparedGeometry; import com.vividsolutions.jts.io.WKTReader; @@ -122,6 +122,7 @@ import com.vividsolutions.jts.io.WKTReader; * Jun 15, 2012 15043 Qinglu Lin Added duration to context. * Jul 16, 2012 15091 Qinglu Lin Compute intersection area, which is used for prevent 2nd timezone * from appearing in 2nd and 3rd bullets when not necessary. + * Aug 13, 2012 14493 Qinglu Lin Handled MND time, event time, and TML time specially for COR to NEW. * * * @@ -181,6 +182,7 @@ public class TemplateRunner { .getFrameTimes(); Date eventTime = datatimes != null && datatimes.length > 0 ? datatimes[datatimes.length - 1] .getRefTimeAsCalendar().getTime() : startTime; + Date simulatedTime = SimulatedTime.getSystemTime().getTime(); WarngenConfiguration config = warngenLayer.getConfiguration(); StormTrackState stormTrackState = warngenLayer.getStormTrackState(); @@ -236,6 +238,8 @@ public class TemplateRunner { AffectedAreas[] areas = null; AffectedAreas[] cancelareas = null; Map intersectAreas = null; + Wx wx = null; + long wwaMNDTime = 0l; try { t0 = System.currentTimeMillis(); areas = Area.findAffectedAreas(config, warnPolygon, warningArea, @@ -260,71 +264,92 @@ public class TemplateRunner { Set timeZones = new HashSet(); for (AffectedAreas area : areas) { if (area.getTimezone() != null) { - // Handles counties that span two time zones + // Handles counties that span two time zones String oneLetterTimeZones = area.getTimezone().trim(); oneLetterTZ = new String[oneLetterTimeZones.length()]; if (oneLetterTimeZones.length() == 1) { timeZones.add(String.valueOf(oneLetterTimeZones .charAt(0))); } else { - // Determine if one letter timezone is going to be put into timeZones. - Polygon[] poly1, poly2; - int n1, n2; - double size, totalSize; + // Determine if one letter timezone is going to be + // put into timeZones. + Polygon[] poly1, poly2; + int n1, n2; + double size, totalSize; for (int i = 0; i < oneLetterTimeZones.length(); i++) { - oneLetterTZ[i] = String.valueOf(oneLetterTimeZones.charAt(i)); - Geometry timezoneGeom = warngenLayer.getTimezoneGeom(oneLetterTZ[i]); - t0 = System.currentTimeMillis(); - poly1 = null; poly2 = null; - n1 = 0; n2 = 0; - size = 0.0d; totalSize = 0.0d; - if (timezoneGeom != null && warningArea!= null) { - if (intersectSize.get(oneLetterTZ[i]) != null) continue; - poly1 = new Polygon[warningArea.getNumGeometries()]; - n1 = warningArea.getNumGeometries(); - for (int j = 0; j < n1; j++) { - poly1[j] = (Polygon)warningArea.getGeometryN(j); - } - poly2 = new Polygon[timezoneGeom.getNumGeometries()]; - n2 = timezoneGeom.getNumGeometries(); - for (int j = 0; j < n2; j++) { - poly2[j] = (Polygon)timezoneGeom.getGeometryN(j); - } - // Calculate the total size of intersection - for (Polygon p1: poly1) { - for (Polygon p2: poly2) { - size = p1.intersection(p2).getArea(); - if (size > 0.0) - totalSize += size; - } - if (totalSize > minSize) break; //save time when the size of poly1 or poly2 is large - } - intersectSize.put(oneLetterTZ[i],totalSize); - } else - throw new VizException("Either timezoneGeom or/and warningArea is null. " + - "Timezone cannot be determined."); - System.out.println("Time to do size computation = " - + (System.currentTimeMillis() - t0)); - if (totalSize > minSize) { - timeZones.add(oneLetterTZ[i]); + oneLetterTZ[i] = String + .valueOf(oneLetterTimeZones.charAt(i)); + Geometry timezoneGeom = warngenLayer + .getTimezoneGeom(oneLetterTZ[i]); + t0 = System.currentTimeMillis(); + poly1 = null; + poly2 = null; + n1 = 0; + n2 = 0; + size = 0.0d; + totalSize = 0.0d; + if (timezoneGeom != null && warningArea != null) { + if (intersectSize.get(oneLetterTZ[i]) != null) + continue; + poly1 = new Polygon[warningArea + .getNumGeometries()]; + n1 = warningArea.getNumGeometries(); + for (int j = 0; j < n1; j++) { + poly1[j] = (Polygon) warningArea + .getGeometryN(j); + } + poly2 = new Polygon[timezoneGeom + .getNumGeometries()]; + n2 = timezoneGeom.getNumGeometries(); + for (int j = 0; j < n2; j++) { + poly2[j] = (Polygon) timezoneGeom + .getGeometryN(j); + } + // Calculate the total size of intersection + for (Polygon p1 : poly1) { + for (Polygon p2 : poly2) { + size = p1.intersection(p2) + .getArea(); + if (size > 0.0) + totalSize += size; + } + if (totalSize > minSize) + break; // save time when the size of + // poly1 or poly2 is large + } + intersectSize + .put(oneLetterTZ[i], totalSize); + } else + throw new VizException( + "Either timezoneGeom or/and warningArea is null. " + + "Timezone cannot be determined."); + System.out + .println("Time to do size computation = " + + (System.currentTimeMillis() - t0)); + if (totalSize > minSize) { + timeZones.add(oneLetterTZ[i]); } } - // If timeZones has nothing in it when the hatched area is very small, - // use the timezone of larger intersection size. - if (timeZones.size() == 0 ) { - if (intersectSize.size() > 1) - if (intersectSize.get(oneLetterTZ[0]) > intersectSize.get(oneLetterTZ[1])) { - timeZones.add(oneLetterTZ[0]); - } else { - timeZones.add(oneLetterTZ[1]); - } - else - throw new VizException("The size of intersectSize is less than 1, " + - "timezone cannot be determined."); - } + // If timeZones has nothing in it when the hatched + // area is very small, + // use the timezone of larger intersection size. + if (timeZones.size() == 0) { + if (intersectSize.size() > 1) + if (intersectSize.get(oneLetterTZ[0]) > intersectSize + .get(oneLetterTZ[1])) { + timeZones.add(oneLetterTZ[0]); + } else { + timeZones.add(oneLetterTZ[1]); + } + else + throw new VizException( + "The size of intersectSize is less than 1, " + + "timezone cannot be determined."); + } } } else { - throw new VizException("Calling to area.getTimezone() returns null."); + throw new VizException( + "Calling to area.getTimezone() returns null."); } } @@ -342,22 +367,28 @@ public class TemplateRunner { if (!(selectedAction == WarningAction.CAN || selectedAction == WarningAction.EXP)) { Coordinate[] stormLocs = warngenLayer .getStormLocations(stormTrackState); - Wx wx = new Wx(config, stormTrackState, + wx = new Wx(config, stormTrackState, warngenLayer.getStormLocations(stormTrackState), startTime.getTime(), DateUtil.roundDateTo15(endTime) .getTime(), warnPolygon); - context.put("now", SimulatedTime.getSystemTime().getTime()); - context.put("start", wx.getStartTime()); + if (selectedAction == WarningAction.COR) { + wwaMNDTime = wx.getStartTime().getTime(); + } else { + context.put("now", simulatedTime); + context.put("start", wx.getStartTime()); + } context.put( "expire", DateUtil.roundDateTo15(selectedAction == WarningAction.EXT ? endTime : wx.getEndTime())); - + // duration: convert millisecond to minute - long duration = (wx.getEndTime().getTime()-wx.getStartTime().getTime())/(1000*60); + long duration = (wx.getEndTime().getTime() - wx.getStartTime() + .getTime()) / (1000 * 60); context.put("duration", duration); - + context.put("event", eventTime); + context.put("TMLtime", eventTime); context.put("ugcline", FipsUtil.getUgcLine(areas, wx.getEndTime(), 15)); context.put("areaPoly", GisUtil.convertCoords(warngenLayer @@ -381,7 +412,7 @@ public class TemplateRunner { StormTrackData std = ToolsDataManager.getInstance() .getStormTrackData(); - std.setDate(SimulatedTime.getSystemTime().getTime()); + std.setDate(simulatedTime); std.setMotionDirection((int) wx.getMovementDirection()); std.setMotionSpeed((int) Math.round(wx.getMovementSpeed("kn"))); @@ -417,11 +448,12 @@ public class TemplateRunner { // Example: s[0-5] = T.CON-KLWX.SV.W.0123 AbstractWarningRecord oldWarn = CurrentWarnings.getInstance( threeLetterSiteId).getNewestByTracking(etn, phenSig); - context.put("now", SimulatedTime.getSystemTime().getTime()); + context.put("now", simulatedTime); context.put("event", eventTime); context.put("start", oldWarn.getStartTime().getTime()); context.put("expire", oldWarn.getEndTime().getTime()); Calendar canOrExpCal = Calendar.getInstance(); + canOrExpCal.setTimeZone(TimeZone.getTimeZone("GMT")); canOrExpCal.add(Calendar.MINUTE, 10); canOrExpCal.add(Calendar.MILLISECOND, 1); context.put( @@ -451,7 +483,7 @@ public class TemplateRunner { StormTrackData std = ToolsDataManager.getInstance() .getStormTrackData(); - std.setDate(SimulatedTime.getSystemTime().getTime()); + std.setDate(simulatedTime); std.setMotionDirection(oldWarn.getMotdir()); std.setMotionSpeed(oldWarn.getMotspd()); t0 = System.currentTimeMillis(); @@ -514,8 +546,68 @@ public class TemplateRunner { } context.put("etn", etn); context.put("start", oldWarn.getIssueTime().getTime()); - context.put("now", SimulatedTime.getSystemTime().getTime()); + if (oldWarn.getAct().equals("NEW")) { + context.put("now", new Date(wwaMNDTime)); + } else + context.put("now", simulatedTime); context.put("event", oldWarn.getIssueTime().getTime()); + + String message = oldWarn.getRawmessage(); + if (!stormTrackState.originalTrack) { + context.put("TMLtime", oldWarn.getStartTime().getTime()); + } else { + int hour = 0; + int minute = 0; + int tmlIndex = message.indexOf("TIME...MOT...LOC"); + int zIndex = -1; + if (tmlIndex > 0) { + zIndex = message.indexOf("Z", tmlIndex); + if (zIndex > 0) { + int startIndex = tmlIndex+16+1; + String tmlTime = null; + tmlTime = message.substring(startIndex,startIndex+4); + if (tmlTime.length() == 4) { + hour = Integer.parseInt(tmlTime.substring(0,2)); + minute = Integer.parseInt(tmlTime.substring(2,4)); + } else if (tmlTime.length() == 3) { + hour = Integer.parseInt(tmlTime.substring(0,1)); + minute = Integer.parseInt(tmlTime.substring(1,3)); + } else { + throw new VizException("The length of hour and minute for TML time is neither 3 nor 4."); + } + Calendar c = Calendar.getInstance(); + c.set(Calendar.HOUR_OF_DAY,hour); + c.set(Calendar.MINUTE, minute); + context.put("TMLtime", c.getTime()); + } else { + throw new VizException("Z, therefore hour and minute, cannot be found in TIME...MOT...LOC line."); + } + } else { + // To prevent errors resulting from undefined context("TMLtime") + context.put("TMLtime", oldWarn.getIssueTime().getTime()); + } + } + + // corEventtime for "COR to NEW", not for "COR to CON, CAN, or CANCON" + if (oldWarn.getAct().equals("NEW")) { + int untilIndex = message.indexOf("UNTIL"); + int atIndex = -1; + int elipsisIndex = -1; + if (untilIndex > 0) { + atIndex = message.indexOf("AT", untilIndex); + if (atIndex > 0) { + int hhmmIndex = atIndex+3; + elipsisIndex = message.indexOf("...", hhmmIndex); + if (elipsisIndex > 0) { + context.put("corToNewMarker","cortonewmarker"); + context.put("corEventtime",message.substring(hhmmIndex,elipsisIndex)); + } + } + } + if (untilIndex < 0 || atIndex < 0 || elipsisIndex < 0) + throw new VizException("Cannot find * AT line."); + } + Calendar cal = oldWarn.getEndTime(); cal.add(Calendar.MILLISECOND, 1); context.put("expire", cal.getTime()); @@ -547,7 +639,9 @@ public class TemplateRunner { context.put("expire", oldWarn.getEndTime().getTime()); context.put("ugcline", FipsUtil.getUgcLine(areas, oldWarn .getEndTime().getTime(), 15)); - Calendar cancelTime = (Calendar) oldWarn.getEndTime().clone(); + Calendar cancelTime = Calendar.getInstance(); + cancelTime.setTime(simulatedTime); + cancelTime.setTimeZone(TimeZone.getTimeZone("GMT")); cancelTime.add(Calendar.MINUTE, 10); String[] tmp = compareGeomsForFollowUp(oldWarn, warnPolygon, areas, cancelTime.getTime(), config); @@ -879,5 +973,4 @@ public class TemplateRunner { return rval; } - } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarnGenMathTool.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarnGenMathTool.java index 2a33ee53ee..e33f00bda2 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarnGenMathTool.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarnGenMathTool.java @@ -27,6 +27,12 @@ import org.apache.velocity.tools.generic.MathTool; /** * @author bwoodle * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Jul 31, 2012 15219 Qinglu Lin Added roundAndPad(). + * */ public class WarnGenMathTool extends MathTool { @@ -57,4 +63,12 @@ public class WarnGenMathTool extends MathTool { return roundToInt(num, 5); } + /** + * Round movement direction to integer, and pad it with leading zeros + * if it's less than 100 + */ + public static String roundAndPad(double direction) { + return String.format("%03d",Math.round(direction)); + } + } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java index 1f382b3e4e..3754150537 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java @@ -63,7 +63,7 @@ import com.raytheon.viz.warngen.gis.AffectedAreasComparator; * c)Locking does not work for areal flood advisory followup; * d)NullointException/locking does not work for special marine warning * and locking beyond first paragragh. - * Jul 17, 2012 14989 Qinglu Lin Removed locks, and , for county names in pathcast line. + * Jul 17, 2012 14989 Qinglu Lin Removed locks, and , for county names in pathcast line. * * * @@ -133,10 +133,14 @@ public class WarningTextHandler { .compile("(\\.\\.\\.((A|THE)\\s(.*)\\s(WARNING|ADVISORY))\\s(FOR|(REMAINS IN EFFECT (|(UNTIL\\s\\d{3,4}\\s(AM|PM)\\s\\w{3})))))(|(.*))"); private static final Pattern canVtecPtrn = Pattern.compile("(\\.CAN\\.)"); + private static final Pattern smwCanPtrn = Pattern.compile("(\\.MA\\.W\\.)"); + private static final Pattern afaCanPtrn = Pattern.compile("(\\.FA\\.Y\\.)"); - private static final Pattern smwHeadlinePtrn = Pattern.compile("(THE AFFECTED AREAS WERE)"); - + + private static final Pattern smwHeadlinePtrn = Pattern + .compile("(THE AFFECTED AREAS WERE)"); + private static Pattern immediateCausePtrn = null; /** ex. SARPY NE-DOUGLAS NE-WASHINGTON NE- */ @@ -154,19 +158,22 @@ public class WarningTextHandler { private static final Pattern subLatLonPtrn = Pattern .compile("^((?!TIME...MOT... LOC))\\s{1,}\\d{3,4}\\s\\d{3,5}(|(\\s\\d{3,4}\\s\\d{3,5}){1,})"); - + private static final Pattern tmlPtrn = Pattern - .compile("TIME...MOT...LOC \\d{3,4}Z\\s\\d{1,3}DEG\\s\\d{1,3}KT((\\s\\d{3,4}\\s\\d{3,5}){1,})"); + .compile("TIME...MOT...LOC \\d{3,4}Z\\s\\d{3}DEG\\s\\d{1,3}KT((\\s\\d{3,4}\\s\\d{3,5}){1,})"); private static final Pattern subTMLPtrn = Pattern .compile("(\\d{3,5}\\s){1,}"); private static final Pattern lockedBlankLinesPattern = Pattern.compile( "(\\s*+)", Pattern.MULTILINE); - - private static final String LOCK_REPLACEMENT_TEXT = LOCK_START + "$0" + LOCK_END; - private static final Pattern extraTokensPattern = Pattern.compile("\\b(?:THE|IS|CANCELLED)\\b"); - + + private static final String LOCK_REPLACEMENT_TEXT = LOCK_START + "$0" + + LOCK_END; + + private static final Pattern extraTokensPattern = Pattern + .compile("\\b(?:THE|IS|CANCELLED)\\b"); + static { String pattern = ""; @@ -176,7 +183,7 @@ public class WarningTextHandler { pattern = "(.*)(A DAM BREAK"; for (String ic : immediateCause.split("\n")) { String[] parts = ic.split("\\\\"); - pattern += "|" + parts[1].trim(); + pattern += "| " + parts[1].trim(); } pattern += ")(.*)"; immediateCausePtrn = Pattern.compile(pattern); @@ -189,8 +196,8 @@ public class WarningTextHandler { } public static String handle(String originalMessage, AffectedAreas[] areas, - AffectedAreas[] canceledAreas, WarningAction action, WarningAction action2, - boolean autoLock) { + AffectedAreas[] canceledAreas, WarningAction action, + WarningAction action2, boolean autoLock) { long t0 = System.currentTimeMillis(); if (action == WarningAction.NEW) { try { @@ -293,9 +300,10 @@ public class WarningTextHandler { boolean startLines = true; - // Set before to false if the line is beyond "THE NATIONAL WEATHER SERVICE IN" line. + // Set before to false if the line is beyond + // "THE NATIONAL WEATHER SERVICE IN" line. boolean before = true; - + boolean isCancelledFound = false; // for CAN of CANCON of Special Marine Warning @@ -304,56 +312,57 @@ public class WarningTextHandler { // for CAN of CANCON of Areal Flood Advisory boolean afaCan = false; - int afaCanBlankline = 0; + int afaCanBlankline = 0; String[] tokens = null; if (canceledAreas != null) { - String areaNames = ""; - for (AffectedAreas area : canceledAreas) { - String areaName = area.getName(); - if (areaName != null && areaName.length()>0) { - areaName = areaName.toUpperCase(); - areaNames += areaName + " "; - } - } - areaNames = areaNames.trim(); - HashSet areaNameSet = new HashSet(); - String[] tokens0 = areaNames.split(" "); - int tokensLength = tokens0.length; - for (int i=0;i s0.length()) { - s1 = s0; - s0 = tokens[j]; - tokens[j] = s1; - } - } - tokens[i] = s0; - } + String areaNames = ""; + for (AffectedAreas area : canceledAreas) { + String areaName = area.getName(); + if (areaName != null && areaName.length() > 0) { + areaName = areaName.toUpperCase(); + areaNames += areaName + " "; + } + } + areaNames = areaNames.trim(); + HashSet areaNameSet = new HashSet(); + String[] tokens0 = areaNames.split(" "); + int tokensLength = tokens0.length; + for (int i = 0; i < tokensLength; i++) { + areaNameSet.add(tokens0[i]); + } + + tokens = (String[]) areaNameSet.toArray(new String[areaNameSet + .size()]); + String s0; + for (int i = 0; i < areaNameSet.size() - 1; i++) { + s0 = tokens[i]; + String s1; + for (int j = i; j < areaNameSet.size(); j++) { + if (tokens[j].length() > s0.length()) { + s1 = s0; + s0 = tokens[j]; + tokens[j] = s1; + } + } + tokens[i] = s0; + } } - boolean ruralFound=false, ruralReplace=false; + boolean ruralFound = false, ruralReplace = false; ArrayList usedAreaNotations = new ArrayList(); for (int lineIndex = 0; lineIndex < seperatedLines.length; ++lineIndex) { String line = seperatedLines[lineIndex]; - if (line.contains("THE NATIONAL WEATHER SERVICE IN") || line.contains("OTHER LOCATIONS IMPACTED")) { + if (line.contains("THE NATIONAL WEATHER SERVICE IN") + || line.contains("OTHER LOCATIONS IMPACTED")) { before = false; } - + if (!ruralFound && line.contains("MAINLY RURAL AREAS")) { - ruralFound = true; + ruralFound = true; } - + // This prevents blank line(s) after the header from being locked. if (startLines && lineIndex > 1) { startLines = line.trim().length() == 0; @@ -393,10 +402,10 @@ public class WarningTextHandler { cancelVtecLineFound = true; m = smwCanPtrn.matcher(line); if (m.find()) - smwCan = true; + smwCan = true; m = afaCanPtrn.matcher(line); if (m.find()) - afaCan = true; + afaCan = true; } continue; } @@ -409,13 +418,14 @@ public class WarningTextHandler { } if (before) { - m = listOfAreaNamePtrn.matcher(line); - if (m.find()) { - if (!(line.contains("!**") || line.contains("**!") || line.contains("OTHER LOCATIONS"))) { - sb.append(LOCK_START + line + "\n" + LOCK_END); - continue; - } - } + m = listOfAreaNamePtrn.matcher(line); + if (m.matches()) { + if (!(line.contains("!**") || line.contains("**!") || line + .contains("OTHER LOCATIONS"))) { + sb.append(LOCK_START + line + "\n" + LOCK_END); + continue; + } + } } // Locking Date in the MND header @@ -426,33 +436,34 @@ public class WarningTextHandler { } if (ruralFound) - if (!ruralReplace) - ruralReplace = true; - else - if (ruralReplace) { - if (line.trim().length() == 0) - ruralFound = false; - else { - line = line.replace("",""); - line = line.replace("",""); - sb.append(line + "\n"); - continue; - } - } + if (!ruralReplace) + ruralReplace = true; + else if (ruralReplace) { + if (line.trim().length() == 0) + ruralFound = false; + else { + line = line.replace("", ""); + line = line.replace("", ""); + sb.append(line + "\n"); + continue; + } + } if (line.trim().length() == 0) { + insideTML = false; + insideLatLon = false; headlineFound = false; if (smwCan) { - if (lockSmwCan) - cancelVtecLineFound = false; - lockSmwCan = false; + if (lockSmwCan) + cancelVtecLineFound = false; + lockSmwCan = false; } if (afaCan) { - afaCanBlankline += 1; - if (afaCanBlankline > 1) { - afaCan = false; - cancelVtecLineFound = false; - } + afaCanBlankline += 1; + if (afaCanBlankline > 1) { + afaCan = false; + cancelVtecLineFound = false; + } } if (startLines) { // Don't lock blank line after header @@ -561,140 +572,157 @@ public class WarningTextHandler { continue; } } else { - usedAreaNotations.clear(); - // head line pattern - m = headlinePtrn.matcher(line); - if (m.find()) { - checkForMND = false; - headlineFound = true; - line = line.replace(m.group(2), LOCK_START + m.group(2) - + LOCK_END); - } - // CAN portion in a CANCON - if (cancelVtecLineFound) { - if (smwCan) { - // lock marine zone names - if (lockSmwCan) { - if (line.length()==0) { - lockSmwCan = false; - } else - line = LOCK_START + line + LOCK_END; - } else { - m = smwHeadlinePtrn.matcher(line); - if (m.find()) - lockSmwCan = true; - } - } else { - for (String s: tokens) - if (line.contains(s)) - line = line.replace(s, LOCK_START - + s + LOCK_END); - for (AffectedAreas area : canceledAreas) { - String areaNotation = area.getAreaNotation(); - if (areaNotation != null) { - // areaNotation, e.g., COUNTY - if (areaNotation != null && areaNotation.length()>0 - && !usedAreaNotations.contains(areaNotation) - && line.contains(areaNotation)) { - line = line.replaceAll(areaNotation, LOCK_START - + areaNotation + LOCK_END); - usedAreaNotations.add(areaNotation); - } - // areasNotation, e.g., COUNTIES - String areasNotation = area.getAreasNotation().toUpperCase(); - if (areasNotation != null && areasNotation.length()>0 - && !usedAreaNotations.contains(areasNotation) - && line.contains(areasNotation)) { - line = line.replaceAll(areasNotation, LOCK_START - + areasNotation + LOCK_END); - usedAreaNotations.add(areasNotation); - } - } - } - // locking "THE" in "THE CITY OF MANASSAS", "...THE" in "...THE CITY", - // and "IS" or "CANCELLED" in "IS CANCELLED...". - line = extraTokensPattern.matcher(line).replaceAll( - LOCK_REPLACEMENT_TEXT); - } + usedAreaNotations.clear(); + // head line pattern + m = headlinePtrn.matcher(line); + if (m.find()) { + checkForMND = false; + headlineFound = true; + line = line.replace(m.group(2), LOCK_START + m.group(2) + + LOCK_END); + } + // CAN portion in a CANCON + if (cancelVtecLineFound) { + if (smwCan) { + // lock marine zone names + if (lockSmwCan) { + if (line.length() == 0) { + lockSmwCan = false; + } else + line = LOCK_START + line + LOCK_END; + } else { + m = smwHeadlinePtrn.matcher(line); + if (m.find()) + lockSmwCan = true; + } + } else { + for (String s : tokens) + if (line.contains(s)) + line = line.replace(s, LOCK_START + s + + LOCK_END); + for (AffectedAreas area : canceledAreas) { + String areaNotation = area.getAreaNotation(); + if (areaNotation != null) { + // areaNotation, e.g., COUNTY + if (areaNotation != null + && areaNotation.length() > 0 + && !usedAreaNotations + .contains(areaNotation) + && line.contains(areaNotation)) { + line = line.replaceAll(areaNotation, + LOCK_START + areaNotation + + LOCK_END); + usedAreaNotations.add(areaNotation); + } + // areasNotation, e.g., COUNTIES + String areasNotation = area + .getAreasNotation().toUpperCase(); + if (areasNotation != null + && areasNotation.length() > 0 + && !usedAreaNotations + .contains(areasNotation) + && line.contains(areasNotation)) { + line = line.replaceAll(areasNotation, + LOCK_START + areasNotation + + LOCK_END); + usedAreaNotations.add(areasNotation); + } + } + } + // locking "THE" in "THE CITY OF MANASSAS", "...THE" + // in "...THE CITY", + // and "IS" or "CANCELLED" in "IS CANCELLED...". + line = extraTokensPattern.matcher(line).replaceAll( + LOCK_REPLACEMENT_TEXT); + } - if (cancelVtecLineFound && isCancelledFound) - cancelVtecLineFound = false; + if (cancelVtecLineFound && isCancelledFound) + cancelVtecLineFound = false; - m = cancelOnlyPtrn.matcher(line); - if (m.find()) - cancelVtecLineFound = false; + m = cancelOnlyPtrn.matcher(line); + if (m.find()) + cancelVtecLineFound = false; - sb.append(line + "\n"); - continue; - } else { - // follow-ups other than CAN in a CANCON - if (headlineFound) { - usedAreaNotations.clear(); - if (areas != null && !marineProduct) { - for (AffectedAreas area : areas) { - if (area.getName() != null - && line.contains(area.getName() - .toUpperCase())) { - line = line.replaceFirst(area.getName() - .toUpperCase(), LOCK_START - + area.getName().toUpperCase() - + LOCK_END); - } + sb.append(line + "\n"); + continue; + } else { + // follow-ups other than CAN in a CANCON + if (headlineFound) { + usedAreaNotations.clear(); + if (areas != null && !marineProduct) { + for (AffectedAreas area : areas) { + if (area.getName() != null + && line.contains(area.getName() + .toUpperCase())) { + line = line.replaceFirst(area.getName() + .toUpperCase(), LOCK_START + + area.getName().toUpperCase() + + LOCK_END); + } - if (area.getAreaNotation() != null - && !usedAreaNotations.contains(area - .getAreaNotation() - .toUpperCase()) - && line.contains(area.getAreaNotation())) { - line = line.replaceAll(" " - + area.getAreaNotation() - .toUpperCase(), LOCK_START - + " " + area.getAreaNotation() - + LOCK_END); - usedAreaNotations.add(area - .getAreaNotation().toUpperCase()); - } - } - } + if (area.getAreaNotation() != null + && !usedAreaNotations.contains(area + .getAreaNotation() + .toUpperCase()) + && line.contains(area + .getAreaNotation())) { + line = line + .replaceAll( + " " + + area.getAreaNotation() + .toUpperCase(), + LOCK_START + + " " + + area.getAreaNotation() + + LOCK_END); + usedAreaNotations.add(area + .getAreaNotation() + .toUpperCase()); + } + } + } - m = cancelPtrn.matcher(line); - if (m.find()) { - line = line.replaceFirst(m.group(3), - LOCK_START + m.group(3) + LOCK_END); - if (canceledAreas != null) { - for (AffectedAreas canceledArea : canceledAreas) { - if (line.contains(canceledArea.getName() - .toUpperCase())) { - line = line.replaceFirst(canceledArea - .getName().toUpperCase(), - LOCK_START - + canceledArea - .getName() - .toUpperCase() - + LOCK_END); - } - } - } - headlineFound = false; - } + m = cancelPtrn.matcher(line); + if (m.find()) { + line = line.replaceFirst(m.group(3), LOCK_START + + m.group(3) + LOCK_END); + if (canceledAreas != null) { + for (AffectedAreas canceledArea : canceledAreas) { + if (line.contains(canceledArea + .getName().toUpperCase())) { + line = line + .replaceFirst( + canceledArea + .getName() + .toUpperCase(), + LOCK_START + + canceledArea + .getName() + .toUpperCase() + + LOCK_END); + } + } + } + headlineFound = false; + } - m = expirePtrn.matcher(line); - if (m.find()) { - line = line.replaceFirst(m.group(3), - LOCK_START + m.group(3) + LOCK_END); - headlineFound = false; - } + m = expirePtrn.matcher(line); + if (m.find()) { + line = line.replaceFirst(m.group(3), LOCK_START + + m.group(3) + LOCK_END); + headlineFound = false; + } - sb.append(line + "\n"); - continue; - } - } + sb.append(line + "\n"); + continue; + } + } } // Locking LAT...LON m = latLonPtrn.matcher(line); if (m.find()) { - sb.append(LOCK_START + line + "\n"); + sb.append(LOCK_START + line + "\n" + LOCK_END); insideLatLon = true; continue; } @@ -702,11 +730,10 @@ public class WarningTextHandler { if (insideLatLon) { m = subLatLonPtrn.matcher(line); if (m.find()) { - sb.append(line + "\n"); + sb.append(LOCK_START + line + "\n" + LOCK_END); continue; } else { insideLatLon = false; - sb.append(LOCK_END); } } @@ -719,7 +746,7 @@ public class WarningTextHandler { // Locking TIME...MOT..LOC m = tmlPtrn.matcher(line); if (m.find()) { - sb.append(LOCK_START + line + "\n"); + sb.append(LOCK_START + line + "\n" + LOCK_END); insideTML = true; continue; } @@ -727,33 +754,32 @@ public class WarningTextHandler { if (insideTML) { m = subTMLPtrn.matcher(line); if (m.matches()) { - sb.append(line + "\n"); + sb.append(LOCK_START + line + "\n" + LOCK_END); continue; } else { insideTML = false; - sb.append(LOCK_END); } } // Test lines if (line.equals(TEST_MSG3) - || line.equals(TEST_MSG1) - || (line.startsWith("TEST...") && line - .endsWith("...TEST"))) { - sb.append(LOCK_START + line + LOCK_END + "\n"); - continue; - } + || line.equals(TEST_MSG1) + || (line.startsWith("TEST...") && line + .endsWith("...TEST"))) { + sb.append(LOCK_START + line + LOCK_END + "\n"); + continue; + } m = testMessagePtrn.matcher(line); if (m.find()) { - line = line.replace(m.group(2), LOCK_START + m.group(2) - + LOCK_END); + line = line.replace(m.group(2), LOCK_START + m.group(2) + + LOCK_END); } } catch (Exception e) { - // If an exception is thrown, - // log the exception but continue locking text - statusHandler.handle(Priority.PROBLEM, "Error locking line: " - + line + "\n", e); + // If an exception is thrown, + // log the exception but continue locking text + statusHandler.handle(Priority.PROBLEM, "Error locking line: " + + line + "\n", e); } sb.append(line + "\n"); insideLatLon = false; @@ -849,31 +875,32 @@ public class WarningTextHandler { return sb.toString(); } - + private static String wrapLocations(String locationsLine) { StringBuffer sb = new StringBuffer(); - + String line = " "; String[] locations = locationsLine.split("\\.\\.\\."); - + for (int i = 0; i < locations.length; i++) { String location = locations[i]; - int size = (i == locations.length - 1)? location.length() : location.length() + 3; - + int size = (i == locations.length - 1) ? location.length() + : location.length() + 3; + if (line.length() + size >= MAX_WIDTH - 2) { sb.append(line + "\n"); line = " "; - } - + } + if (i == locations.length - 1) { line += location; } else { line += location + "..."; } } - + sb.append(line + "\n"); - + return sb.toString(); } diff --git a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/AbstractWarningResource.java b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/AbstractWarningResource.java index 792db841d0..c8bfe49884 100644 --- a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/AbstractWarningResource.java +++ b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/AbstractWarningResource.java @@ -3,6 +3,7 @@ package com.raytheon.viz.warnings.rsc; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -74,7 +75,8 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; * in a given display frame * Jun 04, 2012 DR14992 mgamazaychikov Reversed the textToPrint array to * plot the strings in correct order - * + * Aug 09, 2012 DR 15166 D.Friedman Plot only the most recent record for + * an event. * * * @author jsanchez @@ -532,77 +534,94 @@ public abstract class AbstractWarningResource extends AbstractWWAResource lastFrame = true; } synchronized (paintLock) { - for (String datauri : entryMap.keySet()) { - WarningEntry entry = entryMap.get(datauri); - AbstractWarningRecord record = entry.record; + HashMap candidates = + new HashMap(); + for (WarningEntry entry : entryMap.values()) { if (matchesFrame(entry, paintProps.getDataTime(), framePeriod, lastFrame)) { + String key = getEventKey(entry); + WarningEntry current = candidates.get(key); + + if (current == null || current.record.getIssueTime(). + before(entry.record.getIssueTime()) || + (current.record.getIssueTime().equals(entry.record.getIssueTime()) && + current.record.getInsertTime().before(entry.record.getInsertTime())) + ) + candidates.put(key, entry); + } + } + for (WarningEntry entry : candidates.values()) { + AbstractWarningRecord record = entry.record; - // check shapes - if (entry.project) { - initShape(target, entry.record); - entry.project = false; + // check shapes + if (entry.project) { + initShape(target, entry.record); + entry.project = false; + } + + if (entry != null && entry.wireframeShape != null) { + LineStyle lineStyle = (record.getProductClass() != null && record + .getProductClass().equals("T")) ? LineStyle.DASHED + : LineStyle.SOLID; + target.drawWireframeShape(entry.wireframeShape, + getCapability(ColorableCapability.class) + .getColor(), + getCapability(OutlineCapability.class) + .getOutlineWidth(), lineStyle); + } else if (entry != null && entry.shadedShape != null) { + target.drawShadedShape(entry.shadedShape, 1); + } + + if (record != null && record.getGeometry() != null) { + // Calculate the upper left portion of the polygon + Coordinate upperLeft = new Coordinate(180, -90); + + for (Coordinate c : record.getGeometry() + .getCoordinates()) { + if (c.y - c.x > upperLeft.y - upperLeft.x) { + upperLeft = c; + } } - if (entry != null && entry.wireframeShape != null) { - LineStyle lineStyle = (record.getProductClass() != null && record - .getProductClass().equals("T")) ? LineStyle.DASHED - : LineStyle.SOLID; - target.drawWireframeShape(entry.wireframeShape, - getCapability(ColorableCapability.class) - .getColor(), - getCapability(OutlineCapability.class) - .getOutlineWidth(), lineStyle); - } else if (entry != null && entry.shadedShape != null) { - target.drawShadedShape(entry.shadedShape, 1); - } - - if (record != null && record.getGeometry() != null) { - // Calculate the upper left portion of the polygon - Coordinate upperLeft = new Coordinate(180, -90); - - for (Coordinate c : record.getGeometry() - .getCoordinates()) { - if (c.y - c.x > upperLeft.y - upperLeft.x) { - upperLeft = c; - } - } - - double[] d = descriptor.worldToPixel(new double[] { - upperLeft.x, upperLeft.y }); - d[0] -= paintProps.getZoomLevel() * 100; - - double mapWidth = descriptor.getMapWidth() - * paintProps.getZoomLevel() / 1000; - String[] textToPrint = getText(record, mapWidth); - if (warningsFont == null) { - warningsFont = target.getDefaultFont() - .deriveWithSize(11); - } - // DR14992: reverse the textToPrint array to plot the strings in correct order - String [] textToPrintReversed = new String[textToPrint.length]; - for(int i = 0; i < textToPrint.length; i++) { - textToPrintReversed[i] = textToPrint[textToPrint.length - - i - 1]; - } - - DrawableString params = new DrawableString(textToPrintReversed, - color); - params.font = warningsFont; - params.setCoordinates(d[0], d[1]); - params.textStyle = TextStyle.NORMAL; - params.horizontalAlignment = HorizontalAlignment.RIGHT; - params.verticallAlignment = VerticalAlignment.BOTTOM; - params.magnification = getCapability( - MagnificationCapability.class) - .getMagnification(); - target.drawStrings(params); + double[] d = descriptor.worldToPixel(new double[] { + upperLeft.x, upperLeft.y }); + d[0] -= paintProps.getZoomLevel() * 100; + + double mapWidth = descriptor.getMapWidth() + * paintProps.getZoomLevel() / 1000; + String[] textToPrint = getText(record, mapWidth); + if (warningsFont == null) { + warningsFont = target.getDefaultFont() + .deriveWithSize(11); } + // DR14992: reverse the textToPrint array to plot the strings in correct order + String [] textToPrintReversed = new String[textToPrint.length]; + for(int i = 0; i < textToPrint.length; i++) { + textToPrintReversed[i] = textToPrint[textToPrint.length + - i - 1]; + } + + DrawableString params = new DrawableString(textToPrintReversed, + color); + params.font = warningsFont; + params.setCoordinates(d[0], d[1]); + params.textStyle = TextStyle.NORMAL; + params.horizontalAlignment = HorizontalAlignment.RIGHT; + params.verticallAlignment = VerticalAlignment.BOTTOM; + params.magnification = getCapability( + MagnificationCapability.class) + .getMagnification(); + target.drawStrings(params); } } } } + private static String getEventKey(WarningEntry entry) { + AbstractWarningRecord r = entry.record; + return r.getOfficeid() + '.' + r.getPhensig() + '.' + r.getEtn(); + } + protected boolean matchesFrame(WarningEntry entry, DataTime paintTime, TimeRange framePeriod, boolean lastFrame) { TimeRange recordPeriod = new TimeRange(entry.record.getStartTime() diff --git a/deltaScripts/future/relocateTextUtilities.py b/deltaScripts/future/relocateTextUtilities.py new file mode 100644 index 0000000000..cc636fb002 --- /dev/null +++ b/deltaScripts/future/relocateTextUtilities.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python + +## +# 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. +## + +import glob +import os +import shutil + + +def forceTextProdRegen(): + oldTextProds = glob.glob('/awips2/edex/data/utility/cave_static/configured/*/gfe/userPython/textProducts/*.py*') + for script in oldTextProds: + try: + os.remove(script) + except: + pass + oldTextUtils = glob.glob('/awips2/edex/data/utility/cave_static/configured/*/gfe/userPython/textUtilities/regular/*.py*') + for script in oldTextUtils: + try: + os.remove(script) + except: + pass + # touch shapefile and template file to force regen of textProducts and all textUtilities + shapeFile = glob.glob('/awips2/edex/data/utility/edex_static/base/shapefiles/*/*.shp')[0] + prodTemplate = glob.glob('/awips2/edex/data/utility/edex_static/base/textproducts/templates/product/*.py')[0] + # passing None as the second arg is equivalent to running touch + os.utime(shapeFile, None) + os.utime(prodTemplate, None) + +def relocateSiteLevelUtils(): + sitePaths = getSubDirs('/awips2/edex/data/utility/cave_static/site') + for site in sitePaths: + scripts = glob.glob(os.path.join(site, 'gfe/userPython/textProducts/*.py')) + for script in scripts: + if not isTextProduct(script): + moveToUtilities(script) + +def relocateUserLevelUtils(): + userPaths = getSubDirs('/awips2/edex/data/utility/cave_static/user') + for user in userPaths: + scripts = glob.glob(os.path.join(user, 'gfe/userPython/textProducts/*.py')) + for script in scripts: + if not isTextProduct(script): + moveToUtilities(script) + +def getSubDirs(path): + return [os.path.join(path, name) for name in os.listdir(path) + if os.path.isdir(os.path.join(path, name))] + +def isTextProduct(path): + retVal = False + with open(path, 'r') as f: + txt = f.read() + if "class TextProduct" in txt: + retVal = True + return retVal + +def moveToUtilities(srcPath): + destPath = srcPath.replace('textProducts', 'textUtilities/regular', 1) + if not os.path.isdir(os.path.dirname(destPath)): + os.makedirs(os.path.dirname(destPath)) + shutil.move(srcPath, destPath) + # make sure any .pyo, .pyc, and .md5 files are not left behind + garbageFiles = glob.glob(srcPath + "*") + for file in garbageFiles: + try: + os.remove(file) + except: + pass + +def main(): + forceTextProdRegen() + relocateSiteLevelUtils() + relocateUserLevelUtils() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/maps/hibernate.cfg.xml b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/maps/hibernate.cfg.xml index 6587a70f0f..79efc40e97 100644 --- a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/maps/hibernate.cfg.xml +++ b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/maps/hibernate.cfg.xml @@ -62,9 +62,9 @@ 1 60 300 - 10 - 10 1 + 20 + 20 diff --git a/edexOsgi/build.edex/esb/conf/log4j-ingest.xml b/edexOsgi/build.edex/esb/conf/log4j-ingest.xml index cacc2f651f..8485718a8b 100644 --- a/edexOsgi/build.edex/esb/conf/log4j-ingest.xml +++ b/edexOsgi/build.edex/esb/conf/log4j-ingest.xml @@ -8,6 +8,10 @@ + + + + @@ -141,8 +145,8 @@ - - + + diff --git a/edexOsgi/build.edex/esb/conf/log4j.xml b/edexOsgi/build.edex/esb/conf/log4j.xml index 20eae58b79..f28ba3d6c3 100644 --- a/edexOsgi/build.edex/esb/conf/log4j.xml +++ b/edexOsgi/build.edex/esb/conf/log4j.xml @@ -8,6 +8,10 @@ + + + + @@ -17,12 +21,36 @@ + + + + + + + + + + + + + + + + + + - + + + + + + + @@ -84,6 +112,6 @@ - + - + diff --git a/edexOsgi/build.edex/esb/conf/res/base/attributeNames.xml b/edexOsgi/build.edex/esb/conf/res/base/attributeNames.xml index dd29625b00..7e014fab4c 100644 --- a/edexOsgi/build.edex/esb/conf/res/base/attributeNames.xml +++ b/edexOsgi/build.edex/esb/conf/res/base/attributeNames.xml @@ -241,7 +241,5 @@ archiveDir svcBackupDir mhsData - requestTimeLogFilter - responseSizeLogFilter diff --git a/edexOsgi/build.edex/esb/conf/res/base/environment.xml b/edexOsgi/build.edex/esb/conf/res/base/environment.xml index f485f6a33f..38058b4d1e 100644 --- a/edexOsgi/build.edex/esb/conf/res/base/environment.xml +++ b/edexOsgi/build.edex/esb/conf/res/base/environment.xml @@ -47,8 +47,6 @@ false ${env:edex.home}/../GFESuite/ /data/fxa/mhs - 1000 - 8 diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/TimeRange.py b/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/TimeRange.py index 44bc649634..2cd383d2a3 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/TimeRange.py +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/TimeRange.py @@ -126,6 +126,18 @@ class TimeRange(JUtil.JavaWrapperClass): def __ne__(self, other): return not self == other + def __lt__(self, other): + return self.__tr.compareTo(other.toJavaObj()) < 0 + + def __le__(self, other): + return self.__tr.compareTo(other.toJavaObj()) <= 0 + + def __gt__(self, other): + return self.__tr.compareTo(other.toJavaObj()) > 0 + + def __ge__(self, other): + return self.__tr.compareTo(other.toJavaObj()) >= 0 + def __hash__(self): if not self.__hash: self.__hash = self.startTime().unixTime() ^ self.endTime().unixTime() @@ -134,6 +146,9 @@ class TimeRange(JUtil.JavaWrapperClass): def __str__(self): return str(self.__tr.toString()) + def __repr__(self): + return str(self.__tr.toString()) + def javaTimeRangeListToPyList(timeRanges): pylist = [] size = timeRanges.size() diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/VM_global_library.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/VM_global_library.vm index a6ab74429c..04ffc77be2 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/VM_global_library.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/VM_global_library.vm @@ -1,8 +1,8 @@ ##### UPDATED 3/2/12 12.2.1-4 BY EVAN BOOKBINDER ##### Qinglu Lin 04-04-2012 DR 14691. ##### Qinglu Lin 06-18-2012 DR 15043. Use duration in secondBullet. - -#* +##### Qinglu Lin 07-31-2012 DR 15217. Use roundAndPad for movement direction in DEG. +##### Qinglu Lin 08-13-2012 DR 14493. Use corToNewMarker and corEventtime. #################################################################################################### Mile Marker Test Code macro "mmarkers" use (called out of VM_global_library.vm): @@ -330,7 +330,7 @@ ${mathUtil.abs(${mathUtil.round($v100)})}## #macro( tml $time $motdir $motspd $timeFormat $eventlocation ) TIME...MOT...LOC ## ${dateUtil.format(${start}, ${timeFormat.time})}Z ## -${mathUtil.round(${motdir})}DEG ## +${mathUtil.roundAndPad(${motdir})}DEG ## ${mathUtil.round(${motspd})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## @@ -661,7 +661,11 @@ UNTIL ${dateUtil.format(${expire}, ${timeFormat.clock}, 15, ${localtimezone})}## #end #macro(thirdBullet $dateUtil $eventtime $timeFormat $localtimezone $secondtimezone) +#if(${corToNewMarker}) +AT ${corEventtime}## +#else AT ${dateUtil.format(${eventtime}, ${timeFormat.clock}, ${localtimezone})}## +#end #if(${secondtimezone}) /${dateUtil.format(${eventtime}, ${timeFormat.clock}, ${secondtimezone})}/## #end diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisory.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisory.xml index ab1c53e225..be7d050092 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisory.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisory.xml @@ -296,6 +296,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisoryFollowup.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisoryFollowup.xml index 134c25f2d8..18622249b8 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisoryFollowup.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisoryFollowup.xml @@ -256,6 +256,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisoryFollowup_Zones.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisoryFollowup_Zones.xml index 5fa4770733..01f9f0c8a7 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisoryFollowup_Zones.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisoryFollowup_Zones.xml @@ -290,6 +290,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisory_Zones.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisory_Zones.xml index 32ff00e343..a05ab96e23 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisory_Zones.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodAdvisory_Zones.xml @@ -336,6 +336,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarning.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarning.xml index 80a438edf9..7989ed5672 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarning.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarning.xml @@ -321,6 +321,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarningFollowup.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarningFollowup.xml index 1433fd1a7b..6f51d34850 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarningFollowup.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarningFollowup.xml @@ -267,6 +267,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarningFollowup_Zones.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarningFollowup_Zones.xml index ee0d6b7eec..ca49de4272 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarningFollowup_Zones.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarningFollowup_Zones.xml @@ -306,6 +306,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarning_Zones.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarning_Zones.xml index 1301279c46..38dd206ab2 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarning_Zones.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/arealFloodWarning_Zones.xml @@ -349,6 +349,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/customTemplate.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/customTemplate.vm index 05352d9182..a3323ebfad 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/customTemplate.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/customTemplate.vm @@ -1,6 +1,8 @@ -##################### +#################################################################### ## CUSTOM TEMPLATE ## -##################### +## History +## QINGLU LIN 8-14-2012 DR 14493 use corToNewMarker and TMLtime ## +#################################################################### ${WMOId} ${vtecOffice} 000000 CUSTOM ${ugcline} @@ -166,8 +168,12 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## +#if(${corToNewMarker}) +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## +#else ${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +#end +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarning.vm index 329120f96b..086593b64e 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarning.vm @@ -1,12 +1,13 @@ ################# -################################################################ -## EXTREME WIND WARNING TEMPLATE ## -## (SLIGHTLY) MODIFIED BY TOM BIRCHARD - WFO HFO ## +############################################################################ +## EXTREME WIND WARNING TEMPLATE ## +## (SLIGHTLY) MODIFIED BY TOM BIRCHARD - WFO HFO ## ## VERSION AWIPS II 1.0 -- 15-APRIL-2011 -## MODIFIED EVAN BOOKBINDER 09-16-2011 OB11.0.8-8 ## -## EVAN BOOKBINDER WFO EAX 11-04-2011 OB11.9-3 (DRs) ## -## ## -################################################################## +## MODIFIED EVAN BOOKBINDER 09-16-2011 OB11.0.8-8 ## +## EVAN BOOKBINDER WFO EAX 11-04-2011 OB11.9-3 (DRs) ## +## QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## +## QINGLU LIN 8-14-2012 DR 14493 use TMLtime ## +############################################################################ ## EWW PRODUCT ## ################# ## @@ -187,8 +188,8 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## -${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarningFollowup.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarningFollowup.vm index bf0bacf43d..ca65bb9b66 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarningFollowup.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarningFollowup.vm @@ -2,6 +2,7 @@ ## EWW SVS ## ## MODIFIED EVAN BOOKBINDER 09-16-2011 OB11.0.8-8 ## Evan Bookbinder 4-25-2012 for OB 12.3.1 (corText) +## QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ################################################ ## ### CREATE PHRASING DEPENDING ON WHETHER WE ISSUE EXP PRIOR TO EXPIRATION TIME OR NOT @@ -336,7 +337,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. TIME...MOT...LOC ## ${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## @@ -487,7 +488,7 @@ LAT...LON ## TIME...MOT...LOC ## ${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/ffwfaw.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/ffwfaw.xml index 7b9258cdb7..27e6a280ff 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/ffwfaw.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/ffwfaw.xml @@ -338,6 +338,7 @@ ALTHOUGH IT SERVES NO PURPOSE HERE, IT WILL CRASH WARNGEN IF REMOVED --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarning.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarning.xml index d27ccefda8..0571339759 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarning.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarning.xml @@ -311,6 +311,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarningFollowup.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarningFollowup.xml index 29ee6edb61..f51059ec30 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarningFollowup.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarningFollowup.xml @@ -269,6 +269,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarningFollowup_Zones.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarningFollowup_Zones.xml index 46917cccdd..3d6a93f1c0 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarningFollowup_Zones.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarningFollowup_Zones.xml @@ -275,6 +275,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarning_Zones.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarning_Zones.xml index bf0b1034e5..a47c03c630 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarning_Zones.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/flashFloodWarning_Zones.xml @@ -304,6 +304,7 @@ and place into this template --> ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereThunderstormWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereThunderstormWarning.vm index 628fb62734..cbd5151b14 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereThunderstormWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereThunderstormWarning.vm @@ -5,6 +5,8 @@ ## VERSION AWIPS II 1.0 -- 2-21-2012 OB12.1.1-1 ## ## VERSION AWIPS II 1.1 -- 2-29-2012 OB12.2.1-4 ## ## VERSION AWIPS II 1.2 -- 4-20-2012 ## +## BY QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## +## QINGLU LIN 8-14-2012 DR 14493 use TMLtime ## ################################################################ ## ##SET SOME INITIAL VARIABLES @@ -655,8 +657,8 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## -${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereWeatherStatement.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereWeatherStatement.vm index 2f9c2fa970..3aac4392af 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereWeatherStatement.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereWeatherStatement.vm @@ -5,6 +5,7 @@ ## VERSION AWIPS II 1.0 -- 2-21-2012 OB12.1.1-1 ## ## VERSION AWIPS II 1.1 -- 2-29-2012 OB12.2.1-4 ## ## VERSION AWIPS II 1.2 -- 4-20-2012 ## +## BY QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## ################################################################ ## ################################################################### @@ -302,7 +303,7 @@ REMEMBER...A TORNADO WARNING STILL REMAINS IN EFFECT FOR !** PORTION AND COUNTY TIME...MOT...LOC ## ${dateUtil.format(${now}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## @@ -1161,7 +1162,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. TIME...MOT...LOC ## ${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactTornadoWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactTornadoWarning.vm index 089e9782ba..4ca6ee4802 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactTornadoWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactTornadoWarning.vm @@ -5,6 +5,7 @@ ## VERSION AWIPS II 1.0 -- 2-21-2012 OB12.1.1-1 ## ## VERSION AWIPS II 1.1 -- 2-29-2012 OB12.2.1-4 ## ## VERSION AWIPS II 1.2 -- 4-20-2012 ## +## BY QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## ################################################################ ## ESTABLISH SOME INITIAL VARIABLES #set ($preAmble = "") @@ -627,7 +628,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. TIME...MOT...LOC ## ${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarning.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarning.xml index dbd0196b89..b3d382ae86 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarning.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarning.xml @@ -369,6 +369,7 @@ and place into this template ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarningFollowup.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarningFollowup.xml index ba06385b13..59a2dd4764 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarningFollowup.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarningFollowup.xml @@ -396,6 +396,7 @@ and place into this template ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarningFollowup_Zones.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarningFollowup_Zones.xml index 0ba5705ed8..8ea5cdf3a9 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarningFollowup_Zones.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarningFollowup_Zones.xml @@ -398,6 +398,7 @@ and place into this template ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarning_Zones.xml b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarning_Zones.xml index a34c4e7552..51c1cac32b 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarning_Zones.xml +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/nonConvectiveFlashFloodWarning_Zones.xml @@ -368,6 +368,7 @@ and place into this template ffmp_basins + 0.064 streamname diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeThunderstormWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeThunderstormWarning.vm index b94f780416..6baef876b6 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeThunderstormWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeThunderstormWarning.vm @@ -8,6 +8,8 @@ ## 11-04-2011 OB11.9-3 (DRs) ## ## 2-24-2012 OB12.2.1 CLEANUP ## ## BY QINGLU LIN 6-18-2012 DR 15043 use duration ## +## BY QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## +## BY QINGLU LIN 8-14-2012 DR 14493 use TMLtime ## ################################################################ ## ##SET SOME INITIAL VARIABLES @@ -474,8 +476,8 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## -${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeWeatherStatement.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeWeatherStatement.vm index 7446de8c4f..da9149404a 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeWeatherStatement.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeWeatherStatement.vm @@ -9,6 +9,7 @@ ## BY EVAN BOOKBINDER 2-24-2012 OB12.2.1 ## ## BY MIKE REGA 5-3-2012 DR 14885 MND blank line ## ## BY QINGLU LIN 6-18-2012 DR 15043 use duration ## +## BY QINGLU LIN 7-31-2012 DR 15217 use roundAndPad## ################################################################# ## ################################################################### @@ -277,7 +278,7 @@ REMEMBER...A TORNADO WARNING STILL REMAINS IN EFFECT FOR !** PORTION AND COUNTY TIME...MOT...LOC ## ${dateUtil.format(${now}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## @@ -859,7 +860,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. TIME...MOT...LOC ## ${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/significantWeatherAdvisory.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/significantWeatherAdvisory.vm index 16e1e0575b..d0ceee0fff 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/significantWeatherAdvisory.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/significantWeatherAdvisory.vm @@ -6,6 +6,7 @@ ## Edited by Mike Dangelo 02-27-2012 ## ## Edited by Phil Kurimski 3-01-2012 OB12.2.1-4 ## ## Evan Bookbinder 4-25-2012 for OB 12.3.1 (MND) +## QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## ###################################################### ## ##SET SOME INITIAL VARIABLES @@ -322,7 +323,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. TIME...MOT...LOC ## ${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarning.vm index c5e9d4286e..7642b1dcc5 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarning.vm @@ -9,7 +9,9 @@ ## VERSION AWIPS II 1.4 -- JAN 26 2012 OB12.1.1-1 ## ## Cleaned up wind coding for version 1.4 ## ## VERSION AWIPS II 1.5 -- MAR 2 2012 OB12.2.1-4 ## -##################################################### +## BY QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## +## BY QINGLU LIN 8-14-2012 DR 14493 use TMLtime ## +################################################################ ## Added Volcano Information in version 1.3 for sites where ## Volcanoes affect their marine zones. If sites wish to hide ## this information comment out the appropriate bullets in the @@ -393,8 +395,8 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## -${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarningFollowup.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarningFollowup.vm index 4f1e3eee88..0779831aa9 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarningFollowup.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarningFollowup.vm @@ -10,6 +10,7 @@ ## Cleaned up wind coding for version 1.4 ## ## VERSION AWIPS II 1.5 -- MAR 2 2012 OB12.2.1-4 ## ## BY MGAMAZAYCHIKOV -- JUL 20 2012 DR15006 ## +## BY QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## ##################################################### ## Added Volcano Information in version 1.3 for sites where ## Volcanoes affect their marine zones. If sites wish to hide @@ -563,7 +564,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. TIME...MOT...LOC ## ${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## @@ -976,7 +977,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. TIME...MOT...LOC ## ${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## @@ -1402,7 +1403,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. TIME...MOT...LOC ## ${dateUtil.format(${now}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/tornadoWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/tornadoWarning.vm index 0ae6165a8b..3c6b02794a 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/tornadoWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/tornadoWarning.vm @@ -11,6 +11,8 @@ ## EVAN BOOKBINDER WFO EAX 11-04-11 - OB11.9-3 (DRs) ## ## EVAN BOOKBINDER WFO EAX 2-24-12 - OB12.2.1 ## ## MIKE REGA 5-03-12 - DR 14885 MND blank line ## +## QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## +## QINGLU LIN 8-14-2012 DR 14493 use TMLtime ## ############################################################################### ## ESTABLISH SOME INITIAL VARIABLES #set($preAmble = "") @@ -420,8 +422,8 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## -${dateUtil.format(${event}, ${timeFormat.time})}Z ## -${mathUtil.round(${movementDirection})}DEG ## +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## +${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) #llFormat(${eventCoord.y}) #llFormat(${eventCoord.x}) ## diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/protectedFiles.txt b/edexOsgi/build.edex/esb/data/utility/edex_static/base/protectedFiles.txt index 5264d7a021..4c5422020d 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/protectedFiles.txt +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/protectedFiles.txt @@ -5,6 +5,9 @@ # A simple example would be # BASE:common_static/textdb/textCategoryClass.txt +#AvnFPS files +SITE:cave_static/aviation/avnwatch/aviationForecasterConfig.xml + #D2D files BASE:cave_static/derivedParameters/DerivedParameterInterface.py @@ -155,3 +158,6 @@ BASE:edex_static/smartInit/NamDNG5.py #gfeConfig files BASE:cave_static/gfe/userPython/gfeConfig/gfeConfig.py +# FFMP Files +SITE:common_static/purge/ffmpPurgeRules.xml +SITE:common_static/ffmp/FFMPTemplateConfig.xml \ No newline at end of file diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/smartinit/Init.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/smartinit/Init.py index 31ab9521ff..4db1571056 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/smartinit/Init.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/smartinit/Init.py @@ -23,6 +23,7 @@ # ------------ ---------- ----------- -------------------------- # 02/16/12 14439 jdynina modified haines thresholds # 02/16/12 13917 jdynina merged in changes from TRAC ticket 11391 +# 07/25/12 #957 dgilling implement edit areas as args to calc methods. # # ## @@ -36,7 +37,7 @@ pytime = time #-------------------------------------------------------------------------- #-------------------------------------------------------------------------- -# Definitiona for model database class. +# Definition for model database class. #-------------------------------------------------------------------------- class MDB: def __init__(self, dblist): @@ -336,11 +337,7 @@ class Forecaster(GridUtilities): # LogStream.logProblem("staticTopo not available, using topo") # self.__stopo = self.__topo - areas = self._client.getEditAreaNames() - areasize = areas.size() - self._editAreas = [] - for i in range(areasize): - self._editAreas.append(str(areas.get(i))) + self._editAreas = self._client.getEditAreaNames() self._empty = self.__topo * 0 self._minus = self._empty - 1 @@ -958,8 +955,8 @@ class Forecaster(GridUtilities): for arg in args: if arg in self._editAreas: if cache[arg][0] is None: - p = self.newdb()[we] - ea = p.getEditArea(arg) + p = self.newdb().getItem(we) + ea = p.getEditArea(arg).__numpy__[0] cache[arg] = (ea, (0, sys.maxint)) gargs.append(cache[arg][0]) continue diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/Generator.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/Generator.py index 8b43696fe2..7be3c78550 100755 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/Generator.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/Generator.py @@ -30,6 +30,8 @@ Date Ticket# Engineer Description Jun 23, 2008 1180 jelkins Initial creation Jul 08, 2008 1222 jelkins Modified for use within Java Jul 09, 2008 1222 jelkins Split command line loader from class +Jul 24, 2012 #944 dgilling Refactored to support separate + generation of products and utilities. @author: jelkins """ @@ -78,6 +80,20 @@ LOG = logging.getLogger("Generator") # List of protected files fileList = [] +#Installation information for product formatters. +#Directories to Process, src/dest +ProcessDirectories = [ + { + 'src': "textproducts/templates/product", + 'dest': "textProducts" + }, + { + 'src': "textproducts/templates/utility", + 'dest': "textUtilities/regular" + }, + ] + + class Generator(): """Generates site specific text products from base template files. @@ -86,11 +102,8 @@ class Generator(): def __init__(self): """Class constructor""" - - # self.setSiteId(siteId) - # self.setDestination(destinationDir) - - self.setTemplate(TEMPLATE_DIR) + self.__destination = None + self.__siteId = None def setSiteId(self,siteId): """Set the site ID @@ -107,25 +120,6 @@ class Generator(): else: raise LookupError, ' unknown WFO: ' + siteId - def setTemplate(self, value): - """Set this generator's source directory - - Verifies the directory exists and is readable - - @param value: this value should be a fully qualified path - @type value: string - - @raise IOError: when the directory is not found - """ - from os import access - from os import R_OK - - if access(value,R_OK): - self.__template = value - else: - LOG.debug("Attempted to use templates from: %s" % value) - raise IOError, 'directory not readable' - def setDestination(self, value): """Set this generator's output directory @@ -155,14 +149,6 @@ class Generator(): """ return self.__siteId - def getTemplate(self): - """The template directory location - - @return: the template directory location - @rtype: string - """ - return self.__template - def getDestination(self): """The directory into which the generated files are placed @@ -185,7 +171,10 @@ class Generator(): self.__delete() self.__createPilDictionary(self.__siteId) - created = self.__create() + + created = 0 + for dirInfo in ProcessDirectories: + created += self.__create(dirInfo['src'], dirInfo['dest']) LOG.info("%d text products created" % created) LOG.debug("Configuration of Text Products Finish") @@ -199,12 +188,12 @@ class Generator(): # ---- Delete Empty Directory ----------------------------------------- - try: - from os import rmdir - rmdir(self.getDestination()) - except OSError, description: - LOG.warn("unable to remove directory (%s)" % description) - pass + for dirInfo in ProcessDirectories: + try: + os.rmdir(os.path.join(self.getDestination(), dirInfo['dest'])) + except OSError, description: + LOG.warn("unable to remove directory (%s)" % description) + pass def info(self): """Text product information for this site""" @@ -311,23 +300,23 @@ class Generator(): from preferences.configureTextProducts import ProductToStandardMapping subDict = {} - subDict[''] = siteid - subDict[''] = SITE_INFO[siteid]['region'] - subDict[''] = SITE_INFO[siteid]['wfoCityState'] - subDict[''] = SITE_INFO[siteid]['wfoCity'] - subDict[''] = SITE_INFO[siteid]['fullStationID'] - subDict[''] = SITE_INFO[siteid]['state'] + subDict[''] = siteid.strip() + subDict[''] = SITE_INFO[siteid]['region'].strip() + subDict[''] = SITE_INFO[siteid]['wfoCityState'].strip() + subDict[''] = SITE_INFO[siteid]['wfoCity'].strip() + subDict[''] = SITE_INFO[siteid]['fullStationID'].strip() + subDict[''] = SITE_INFO[siteid]['state'].strip() if product is not None: - subDict[''] = product + subDict[''] = product.strip() if ProductToStandardMapping.has_key(product): - subDict[''] = ProductToStandardMapping[product] + subDict[''] = ProductToStandardMapping[product].strip() else: - subDict[''] = product + subDict[''] = product.strip() if pilInfo is not None: for k in pilInfo.keys(): - subDict['<' + k + '>'] = pilInfo[k] + subDict['<' + k + '>'] = pilInfo[k].strip() if pilInfo is not None and pilInfo.has_key("pil") and multiPilFlag: - subDict[''] = pilInfo["pil"][3:6]#pil=nnnxxx, want xxx + subDict[''] = pilInfo["pil"][3:6].strip() #pil=nnnxxx, want xxx else: subDict['_'] = "" #no multiple pils @@ -350,33 +339,27 @@ class Generator(): pilInfo = self.__pilInfo subDict = {} - subDict['Site'] = siteid - subDict['Region'] = SITE_INFO[siteid]['region'] + subDict['Site'] = siteid.strip() + subDict['Region'] = SITE_INFO[siteid]['region'].strip() if product is not None: - subDict['Product'] = product + subDict['Product'] = product.strip() if pilInfo is not None and pilInfo.has_key("pil") and multiPilFlag: - subDict['MultiPil'] = pilInfo["pil"][3:6] #xxx of nnnxxx + subDict['MultiPil'] = pilInfo["pil"][3:6].strip() #xxx of nnnxxx else: subDict['_MultiPil'] = "" #no pil information, remove entry return self.substituteKeywords(subDict,fileName) - def __getTemplateFiles(self): + def __getTemplateFiles(self, srcDir): """Get a list of all template files @return: a list of all template files @rtype: list """ + pathMgr = PathManagerFactory.getPathManager() edexStaticBase = pathMgr.getContext(LocalizationType.EDEX_STATIC, LocalizationLevel.BASE) - templateFiles = pathMgr.listFiles(edexStaticBase, "textproducts/templates", None, True, True) - -# templateFiles = [] -# -# from os import walk -# for root,dirs,files in walk(TEMPLATE_DIR): -# map(lambda fileName:templateFiles.append(join(root,fileName)),files) - + templateFiles = pathMgr.listFiles(edexStaticBase, srcDir, None, False, True) return templateFiles def __printPilDictionary(self, pillist): @@ -503,7 +486,7 @@ class Generator(): LOG.error("Unknown Product: %s" % regularNameBase) return None - def __create(self): + def __create(self, srcDir, destDir): """Build the formatters for this site Substitute the appropriate values into the templates. Name and place @@ -519,11 +502,11 @@ class Generator(): # ---- Gather a list of all template Files -------------------------- - templateFiles = self.__getTemplateFiles() + templateFiles = self.__getTemplateFiles(srcDir) # ---- Process the files --------------------------------------------- - import os, stat, string + import stat, string for lf in templateFiles: fileName = str(lf.getFile().getAbsolutePath()) @@ -604,7 +587,7 @@ class Generator(): # ---- Output to File ----------------------------------- - destFilename = join(self.getDestination(),destName)+regNameExt + destFilename = join(self.getDestination(), destDir, destName) + regNameExt LOG.debug(" ---> %s" % destFilename) try: @@ -679,60 +662,59 @@ class Generator(): allProducts.append(p) for p in templateProds: allProducts.append(p) + + for dirInfo in ProcessDirectories: + templateFiles = self.__getTemplateFiles(dirInfo['src']) - templateFiles = self.__getTemplateFiles() + #determine potential files, based on the template files + for lf in templateFiles: + tf = str(lf.getFile().getAbsolutePath()) - #determine potential files, based on the template files - for lf in templateFiles: - tf = str(lf.getFile().getAbsolutePath()) - - LOG.debug("Template= %s" % basename(tf)) - mname = basename(tf) - globExpressions = [] - - #wildcard the Site - mname = string.replace(mname, "Site", "???") #always 3 chars - - #wildcard the Region - mname = string.replace(mname, "Region", "??") #always 2 chars - - #wildcard the _MultiPil - wcards = [] - if string.find(mname, "_MultiPil") != -1: - wcards.append(string.replace(mname, "_MultiPil", "")) - wcards.append(string.replace(mname, "_MultiPil", "_?")) - wcards.append(string.replace(mname, "_MultiPil", "_??")) - wcards.append(string.replace(mname, "_MultiPil", "_???")) - else: - wcards.append(mname) - - #wildcard the Product - if string.find(mname, "Product") == 0: - for wc in wcards: - for prd in allProducts: - ge = prd + wc[7:] #Product is first 7 characters - globExpressions.append(ge) - - #simple case - Product does not need to be expanded - else: - for wc in wcards: - globExpressions.append(wc) - - for g in globExpressions: - - searchString = join(self.getDestination(),g) - - delfiles = glob.glob(searchString) - - for fn in delfiles: - #delete any existing file - try: - os.chmod(fn, 0644) - os.remove(fn) - LOG.debug(" DEL---> %s" % fn) - productsRemoved += 1 - except: - pass + LOG.debug("Template= %s" % basename(tf)) + mname = basename(tf) + globExpressions = [] + + #wildcard the Site + mname = string.replace(mname, "Site", "???") #always 3 chars + + #wildcard the Region + mname = string.replace(mname, "Region", "??") #always 2 chars + + #wildcard the _MultiPil + wcards = [] + if string.find(mname, "_MultiPil") != -1: + wcards.append(string.replace(mname, "_MultiPil", "")) + wcards.append(string.replace(mname, "_MultiPil", "_?")) + wcards.append(string.replace(mname, "_MultiPil", "_??")) + wcards.append(string.replace(mname, "_MultiPil", "_???")) + else: + wcards.append(mname) + + #wildcard the Product + if string.find(mname, "Product") == 0: + for wc in wcards: + for prd in allProducts: + ge = prd + wc[7:] #Product is first 7 characters + globExpressions.append(ge) + + #simple case - Product does not need to be expanded + else: + for wc in wcards: + globExpressions.append(wc) + + for g in globExpressions: + searchString = join(self.getDestination(), dirInfo['dest'], g) + delfiles = glob.glob(searchString) + + for fn in delfiles: + #delete any existing file + try: + os.chmod(fn, 0644) + os.remove(fn) + LOG.debug(" DEL---> %s" % fn) + productsRemoved += 1 + except: + pass LOG.debug(" Deleting Existing Baseline Templates Finished........") diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AFD.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AFD.py index e4ebc8d7cd..5b962f6821 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AFD.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AFD.py @@ -339,8 +339,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._longTermFcstrNumber = self._getForecasterNumber(self._longTermFcstrNumber) self._shortTermFcstrNumber = self._getForecasterNumber(self._shortTermFcstrNumber) self._aviationFcstrNumber = self._getForecasterNumber(self._aviationFcstrNumber) diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AreaFcst.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AreaFcst.py index 1df5a26ee7..84ff351107 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AreaFcst.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AreaFcst.py @@ -1093,8 +1093,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" #Tropical exceptions try: diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CCF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CCF.py index 9e3a8ff410..765d8cbfad 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CCF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CCF.py @@ -201,8 +201,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._forecasterNumber = self._getForecasterNumber(self._forecasterNumber) # Make argDict accessible diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF.py index fe128f9c4f..b5a022ea17 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF.py @@ -750,8 +750,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF_Pacific.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF_Pacific.py index 153f6a20de..a2845f646d 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF_Pacific.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF_Pacific.py @@ -1049,9 +1049,7 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): for key in varDict.keys(): if type(key) is types.TupleType: label, variable = key - exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" + exec "self._" + variable + "= varDict[key]" self._language = argDict["language"] diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg.py index 397b804196..7a45eadcfc 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg.py @@ -114,8 +114,6 @@ class TextProduct(GenericReport.TextProduct): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" return fcst def _preProcessArea(self, fcst, editArea, areaLabel, argDict): diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg_EQR_MultiPil_Local.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg_EQR_MultiPil_Local.py index 166c084c35..60c9dc521f 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg_EQR_MultiPil_Local.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg_EQR_MultiPil_Local.py @@ -80,8 +80,6 @@ class TextProduct(CivilEmerg.TextProduct): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" fcst = fcst + "AN EARTHQUAKE HAS BEEN FELT " + self._felt + " BY " +\ self._extent + " " + "IN THE |*enter area*| AREA. " + \ diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWF.py index 570e5fd4fc..887ff156da 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWF.py @@ -806,9 +806,7 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" - + self._language = argDict["language"] return None diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWFTable.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWFTable.py index efaf26895b..0a8471fc31 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWFTable.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWFTable.py @@ -539,8 +539,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" # Set up product-specific variables self._colWidth = 13 diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWM.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWM.py index 915b4d3efb..2a9ac96b03 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWM.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWM.py @@ -219,9 +219,7 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): for key in varDict.keys(): if type(key) is types.TupleType: label, variable = key - exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" + exec "self._" + variable + "= varDict[key]" # Calculate current times self._ddhhmmTime = self.getCurrentTime( diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GLF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GLF.py index cbebdd637b..6bbbc11106 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GLF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GLF.py @@ -693,8 +693,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericHazards.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericHazards.py index 551301d596..22bbc3898c 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericHazards.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericHazards.py @@ -250,8 +250,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis, if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericReport.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericReport.py index af1fa240a6..8874b5a2c4 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericReport.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericReport.py @@ -219,8 +219,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] return None diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/Hazard_HLS.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/Hazard_HLS.py index f703d6b209..2e4586340e 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/Hazard_HLS.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/Hazard_HLS.py @@ -5167,16 +5167,16 @@ READINESS ACTIONS AS RECOMMENDED."""), def _surge_Watch_Impact_stmt(self, info, segment): t="" water_dict = self._totalWaterLevel_dict(info, segment) - if info.surgeHtPlusTide > water_dict.get("Extreme", 7): + if info.surgeHtPlusTide >= water_dict.get("Extreme", 7): damage="WIDESPREAD MAJOR" - elif info.surgeHtPlusTide > water_dict.get("High", 5): + elif info.surgeHtPlusTide >= water_dict.get("High", 5): damage="AREAS OF MAJOR" - elif info.surgeHtPlusTide > water_dict.get("Moderate", 3): + elif info.surgeHtPlusTide >= water_dict.get("Moderate", 3): damage="AREAS OF MODERATE" - elif info.surgeHtPlusTide > water_dict.get("Low", 1): + elif info.surgeHtPlusTide >= water_dict.get("Low", 1): damage="AREAS OF MINOR" else: damage = None @@ -5189,16 +5189,16 @@ READINESS ACTIONS AS RECOMMENDED."""), def _surge_Impact_stmt(self, info, segment): t="" water_dict = self._totalWaterLevel_dict(info, segment) - if info.surgeHtPlusTide > water_dict.get("Extreme", 7): + if info.surgeHtPlusTide >= water_dict.get("Extreme", 7): damage= self._totalWaterLevel_Extreme_stmt(info, segment) - elif info.surgeHtPlusTide > water_dict.get("High", 5): + elif info.surgeHtPlusTide >= water_dict.get("High", 5): damage= self._totalWaterLevel_High_stmt(info, segment) - elif info.surgeHtPlusTide > water_dict.get("Moderate", 3): + elif info.surgeHtPlusTide >= water_dict.get("Moderate", 3): damage= self._totalWaterLevel_Moderate_stmt(info, segment) - elif info.surgeHtPlusTide > water_dict.get("Low", 1): + elif info.surgeHtPlusTide >= water_dict.get("Low", 1): damage= self._totalWaterLevel_Low_stmt(info, segment) else: damage ="MINOR COASTAL FLOOD DAMAGE" diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/MVF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/MVF.py index 2a9b23b1dd..cb9611957c 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/MVF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/MVF.py @@ -165,8 +165,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" try: if self._tropicalStorm == "YES": diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/NSH.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/NSH.py index 7a6cf9a5de..3ea2f77a4e 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/NSH.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/NSH.py @@ -530,8 +530,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._format = "Standard" self._extended = "Without Extended" diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/OFF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/OFF.py index 9c755059f3..49cca993bd 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/OFF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/OFF.py @@ -878,8 +878,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] return None diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/PFM.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/PFM.py index bfe9a175c7..e03206e273 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/PFM.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/PFM.py @@ -364,8 +364,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" try: if self._tropicalStorm == "YES": self._tropicalStorm = 1 diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SFT.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SFT.py index ed669b9bb3..a181bdfffb 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SFT.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SFT.py @@ -232,8 +232,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" # Make argDict accessible self.__argDict = argDict diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SRF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SRF.py index 77fbe89cf1..0122c88acc 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SRF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SRF.py @@ -811,8 +811,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] return None diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-request.xml b/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-request.xml index 2a0404d2cd..ecc5fa2616 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-request.xml +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-request.xml @@ -18,13 +18,6 @@ value="com.raytheon.uf.common.dataplugin.gfe.request.GetActiveTableRequest" /> - - - - - @@ -298,6 +291,13 @@ value="com.raytheon.uf.common.dataplugin.gfe.request.SaveCombinationsFileRequest" /> + + + + + diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/reference/ReferenceMgr.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/reference/ReferenceMgr.java new file mode 100644 index 0000000000..43b563038d --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/reference/ReferenceMgr.java @@ -0,0 +1,162 @@ +/** + * 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.reference; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.raytheon.edex.plugin.gfe.config.IFPServerConfig; +import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation; +import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData; +import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceID; +import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse; +import com.raytheon.uf.common.localization.IPathManager; +import com.raytheon.uf.common.localization.LocalizationFile; +import com.raytheon.uf.common.localization.LocalizationUtil; +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.util.FileUtil; + +/** + * Manages reference sets for the ifpServer. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 24, 2012            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class ReferenceMgr { + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(ReferenceMgr.class); + + private static final String EDIT_AREAS_DIR = FileUtil.join("gfe", + "editAreas"); + + IPathManager pathMgr; + + GridLocation dbGridLocation; + + public ReferenceMgr(final IFPServerConfig config) { + this.pathMgr = PathManagerFactory.getPathManager(); + this.dbGridLocation = config.dbDomain(); + } + + /** + * Returns the inventory of data on disk. + * + * @return ReferenceIDs for every defined edit area on disk. + */ + public ServerResponse> getInventory() { + List refIDs = new ArrayList(); + LocalizationFile[] contents = PathManagerFactory.getPathManager() + .listStaticFiles(EDIT_AREAS_DIR, new String[] { ".xml" }, + false, true); + if (contents != null) { + for (LocalizationFile lf : contents) { + String s = LocalizationUtil.extractName(lf.getName()); + String area = s.replace(".xml", ""); + refIDs.add(new ReferenceID(area, lf.isProtected(), lf + .getContext().getLocalizationLevel())); + } + } + + statusHandler.debug("ReferenceID inventory: " + refIDs); + + ServerResponse> sr = new ServerResponse>(); + sr.setPayload(refIDs); + return sr; + } + + /** + * Retrieves the specified ReferenceData, which is identified + * by ReferenceIDs, and returns it to the caller. + * + * @param ids + * ReferenceIDs of the data to retrieve. + * @return The requested ReferenceData. + */ + public ServerResponse> getData( + final List ids) { + ServerResponse> sr = new ServerResponse>(); + List data = new ArrayList(); + + // process each ReferenceID requested + for (ReferenceID id : ids) { + String path = FileUtil.join(EDIT_AREAS_DIR, id.getName() + ".xml"); + LocalizationFile lf = pathMgr.getStaticLocalizationFile(path); + + // does it exist? + if (lf == null) { + sr.addMessage("Unable to find reference data [" + id + "]"); + data = Collections.emptyList(); + sr.setPayload(data); + return sr; + } + + // open and read the file + ReferenceData refData = null; + try { + refData = (ReferenceData) SerializationUtil + .jaxbUnmarshalFromXmlFile(lf.getFile().getPath()); + } catch (Exception e) { + sr.addMessage("Unable to read reference data [" + id + "]"); + data = Collections.emptyList(); + sr.setPayload(data); + return sr; + } + + // assemble the actual ReferenceID, with the protect and access + // flags + ReferenceID referenceID = new ReferenceID(id.getName(), + lf.isProtected(), lf.getContext().getLocalizationLevel()); + + // assemble the ReferenceData + refData.setGloc(dbGridLocation); + refData.setId(referenceID); + data.add(refData); + } + + sr.setPayload(data); + return sr; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "ReferenceMgr [" + dbGridLocation.getSiteId() + "]"; + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetActiveSitesRequestHandler.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetActiveSitesRequestHandler.java deleted file mode 100644 index 94978dbb49..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetActiveSitesRequestHandler.java +++ /dev/null @@ -1,64 +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.gfe.server.handler; - -import java.util.Set; - -import com.raytheon.edex.plugin.gfe.config.GFESiteActivation; -import com.raytheon.uf.common.dataplugin.gfe.request.GetActiveSitesRequest; -import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse; -import com.raytheon.uf.common.serialization.comm.IRequestHandler; - -/** - * TODO Add Description - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jan 19, 2011            dgilling     Initial creation
- * 
- * 
- * - * @author dgilling - * @version 1.0 - */ - -public class GetActiveSitesRequestHandler implements - IRequestHandler { - - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest - * (com.raytheon.uf.common.serialization.comm.IServerRequest) - */ - @Override - public ServerResponse> handleRequest( - GetActiveSitesRequest request) throws Exception { - ServerResponse> sr = new ServerResponse>(); - sr.setPayload(GFESiteActivation.getInstance().getActiveSites()); - return sr; - } - -} diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetSelectTimeRangeHandler.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetSelectTimeRangeHandler.java new file mode 100644 index 0000000000..1436bf957f --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetSelectTimeRangeHandler.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.edex.plugin.gfe.server.handler; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.InputMismatchException; +import java.util.NoSuchElementException; +import java.util.Scanner; +import java.util.TimeZone; + +import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager; +import com.raytheon.uf.common.dataplugin.gfe.request.GetSelectTimeRangeRequest; +import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange.Mode; +import com.raytheon.uf.common.localization.IPathManager; +import com.raytheon.uf.common.localization.LocalizationContext; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +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.comm.IRequestHandler; +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.TimeRange; +import com.raytheon.uf.common.util.FileUtil; + +/** + * Request handler for GetSelectTimeRangeRequest. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 1, 2012             dgilling    Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class GetSelectTimeRangeHandler implements + IRequestHandler { + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(GetSelectTimeRangeHandler.class); + + private static final String FILE_EXT = ".SELECTTR"; + + private static final String FILE_PATH = FileUtil.join("gfe", "text", + "selecttr"); + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest + * (com.raytheon.uf.common.serialization.comm.IServerRequest) + */ + @Override + public ServerResponse handleRequest( + GetSelectTimeRangeRequest request) throws Exception { + ServerResponse retVal = new ServerResponse(); + + // So because EDEX has no concept of USER LocalizationLevel and the + // request type allows the user to specify the site id for the SITE + // localization level, we've got to build these contexts manually and + // parse through the results ourselves... + IPathManager pathMgr = PathManagerFactory.getPathManager(); + int numContexts = (request.getWorkstationID().getUserName() + .equals("SITE") ? 3 : 4); + LocalizationContext[] contexts = new LocalizationContext[numContexts]; + // building the array with the contexts in USER->SITE->...->BASE order + // allows the file we really want to appear sooner in the list of + // results + if (contexts.length == 4) { + contexts[0] = pathMgr.getContext(LocalizationType.COMMON_STATIC, + LocalizationLevel.USER); + contexts[0] + .setContextName(request.getWorkstationID().getUserName()); + } + contexts[numContexts - 3] = pathMgr.getContextForSite( + LocalizationType.COMMON_STATIC, request.getSiteID()); + contexts[numContexts - 2] = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.CONFIGURED); + contexts[numContexts - 2].setContextName(request.getSiteID()); + contexts[numContexts - 1] = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.BASE); + + LocalizationFile[] files = pathMgr.listFiles(contexts, FILE_PATH, + new String[] { FILE_EXT }, false, true); + LocalizationFile trFile = null; + for (LocalizationFile lf : files) { + String lfName = lf.getFile().getName(); + if (lfName.equals(request.getName() + FILE_EXT)) { + trFile = lf; + break; + } + } + + if (trFile != null) { + TimeZone localTZ = TimeZone + .getTimeZone(IFPServerConfigManager + .getServerConfig(request.getSiteID()) + .getTimeZones().get(0)); + SelectTimeRange selectTR = loadTimeRange(trFile, localTZ); + if (selectTR != null) { + TimeRange tr = selectTR.toTimeRange(); + retVal.setPayload(tr); + } else { + retVal.addMessage("Could not read SelectTimeRange " + + request.getName()); + } + } else { + retVal.addMessage("Could not find a SelectTimeRange named " + + request.getName()); + } + + return retVal; + } + + private SelectTimeRange loadTimeRange(LocalizationFile lf, TimeZone localTZ) { + File file = lf.getFile(); + + Scanner input = null; + try { + input = new Scanner(file); + + int start = input.nextInt(); + int end = input.nextInt(); + + Mode mode = Mode.LT; + if (input.hasNextInt()) { + mode = Mode.values()[input.nextInt()]; + } + + TimeZone timeZone = (mode == Mode.ZULU ? TimeZone + .getTimeZone("GMT") : localTZ); + + SelectTimeRange range = new SelectTimeRange(FileUtil.unmangle(file + .getName().replace(FILE_EXT, "")), start, end, mode, lf + .getContext().getLocalizationLevel(), timeZone); + return range; + } catch (FileNotFoundException fileNotFound) { + statusHandler.handle(Priority.PROBLEM, "Could not open SelectTR: " + + file.getAbsolutePath(), fileNotFound); + } catch (InputMismatchException inputMismatch) { + statusHandler.handle( + Priority.PROBLEM, + "Invalid value found within SelectTR: " + + file.getAbsolutePath(), inputMismatch); + } catch (NoSuchElementException noElement) { + statusHandler.handle( + Priority.PROBLEM, + "Prematurely reached end of SelectTR: " + + file.getAbsolutePath(), noElement); + } catch (Exception e) { + statusHandler.handle( + Priority.PROBLEM, + "Unhandled exception occurred reading SelectTR: " + + file.getAbsolutePath(), e); + } finally { + if (input != null) { + input.close(); + } + } + + return null; + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/IFPWE.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/IFPWE.java index bb5f791f50..f2354b8278 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/IFPWE.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/IFPWE.java @@ -20,12 +20,16 @@ package com.raytheon.edex.plugin.gfe.smartinit; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.TimeZone; +import com.raytheon.edex.plugin.gfe.config.IFPServerConfig; +import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager; +import com.raytheon.edex.plugin.gfe.reference.ReferenceMgr; import com.raytheon.edex.plugin.gfe.server.GridParmManager; import com.raytheon.edex.plugin.gfe.server.lock.LockManager; import com.raytheon.edex.plugin.gfe.util.SendNotifications; @@ -36,8 +40,12 @@ import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridParmInfo; import com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID; import com.raytheon.uf.common.dataplugin.gfe.discrete.DiscreteKey; import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException; +import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DBit; import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DByte; import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DFloat; +import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData; +import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData.RefType; +import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceID; import com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable; import com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable.LockMode; import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerMsg; @@ -62,10 +70,11 @@ import com.raytheon.uf.common.time.TimeRange; * *
  * SOFTWARE HISTORY
- * Date			Ticket#		Engineer	Description
- * ------------	----------	-----------	--------------------------
- * May 7, 2008				njensen	    Initial creation
- * Jan 22, 2010      4248   njensen      Better error msgs
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * May 7, 2008              njensen     Initial creation
+ * Jan 22, 2010  4248       njensen     Better error msgs
+ * Jul 25, 2012  #957       dgilling    Implement getEditArea().
  * 
  * 
* @@ -455,4 +464,30 @@ public class IFPWE { public ParmID getParmid() { return parmId; } + + public Grid2DBit getEditArea(String name) { + try { + IFPServerConfig config = IFPServerConfigManager + .getServerConfig(siteId); + ReferenceMgr refMgr = new ReferenceMgr(config); + + ServerResponse> sr = refMgr.getData(Arrays + .asList(new ReferenceID(name))); + if (sr.isOkay()) { + ReferenceData data = sr.getPayload().get(0); + if (data.refType() != RefType.POLYGON) { + throw new Exception("Edit area is not a polygon"); + } + return data.getGrid(); + } else { + statusHandler.error("Unable to retrieve edit area [" + name + + "]: " + sr.message()); + } + } catch (Exception e) { + statusHandler.error("Unable to retrieve edit area [" + name + "].", + e); + } + + return null; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/InitClient.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/InitClient.java index e9c91d3000..ce65ca3e28 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/InitClient.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/smartinit/InitClient.java @@ -22,10 +22,9 @@ package com.raytheon.edex.plugin.gfe.smartinit; import java.util.ArrayList; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - +import com.raytheon.edex.plugin.gfe.config.IFPServerConfig; import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager; +import com.raytheon.edex.plugin.gfe.reference.ReferenceMgr; import com.raytheon.edex.plugin.gfe.server.GridParmManager; import com.raytheon.edex.plugin.gfe.server.database.TopoDatabaseManager; import com.raytheon.edex.plugin.gfe.util.SendNotifications; @@ -33,14 +32,15 @@ import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord; import com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID; import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException; +import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceID; +import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse; import com.raytheon.uf.common.dataplugin.gfe.server.notify.UserMessageNotification; import com.raytheon.uf.common.dataplugin.gfe.server.request.GetGridRequest; import com.raytheon.uf.common.dataplugin.gfe.slice.IGridSlice; -import com.raytheon.uf.common.dataplugin.gfe.util.GfeUtil; +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.TimeRange; -import com.raytheon.uf.edex.core.EDEXUtil; -import com.raytheon.uf.edex.core.EdexException; /** * Init Client used by smart init for retrieving specific info @@ -50,6 +50,7 @@ import com.raytheon.uf.edex.core.EdexException; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 29, 2008 njensen Initial creation + * Jul 25, 2012 #957 dgilling Implement getEditAreaNames(). * * * @@ -59,7 +60,8 @@ import com.raytheon.uf.edex.core.EdexException; public class InitClient { - private static final Log logger = LogFactory.getLog(InitClient.class); + private static final transient IUFStatusHandler logger = UFStatus + .getHandler(InitClient.class); private DatabaseID destinationDB; @@ -109,10 +111,33 @@ public class InitClient { return list; } - public List getEditAreaNames() { - ArrayList list = new ArrayList(); - // TODO implement something here - return list; + // returning an array here instead of a List because arrays get converted to + // Python lists automatically by Jep + public String[] getEditAreaNames() { + try { + String siteId = destinationDB.getSiteId(); + IFPServerConfig config = IFPServerConfigManager + .getServerConfig(siteId); + ReferenceMgr refMgr = new ReferenceMgr(config); + + ServerResponse> sr = refMgr.getInventory(); + if (sr.isOkay()) { + List ids = sr.getPayload(); + String[] l = new String[ids.size()]; + for (int i = 0; i < ids.size(); i++) { + l[i] = ids.get(i).getName(); + } + + return l; + } else { + logger.error("Unable to retrieve edit area inventory: " + + sr.message()); + } + } catch (Exception e) { + logger.error("Unable to retrieve edit area inventory.", e); + } + + return new String[0]; } public IGridSlice getTopo() throws GfeException { diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/textproducts/Configurator.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/textproducts/Configurator.java index 98cbcbeb02..7fa29754f0 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/textproducts/Configurator.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/textproducts/Configurator.java @@ -57,9 +57,11 @@ import com.raytheon.uf.edex.database.cluster.ClusterTask; * *
  * SOFTWARE HISTORY
- * Date			Ticket#		Engineer	Description
- * ------------	----------	-----------	--------------------------
- * Jul 7, 2008	1222		jelkins	Initial creation
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * Jul 7, 2008  1222        jelkins     Initial creation
+ * Jul 24,2012  #944        dgilling    Fix text product template generation
+ *                                      to create textProducts and textUtilities.
  * 
  * 
* @@ -108,8 +110,7 @@ public class Configurator { try { destinationDirectory = pathMgr.getFile(caveStaticConfig, - FileUtil.join("gfe", "userPython", "textProducts")) - .getCanonicalPath(); + FileUtil.join("gfe", "userPython")).getCanonicalPath(); } catch (IOException e) { log.error("Unable to determine the destination directory", e); log.warn("Textproducts will not be configured."); 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 64e6eaca5a..7f74d2db32 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 @@ -21,13 +21,13 @@ import string, getopt, sys, time, gzip, os, LogStream, stat, traceback import numpy -import pupynere as NetCDF -#try: -# # dev environment -# from Scientific.IO import NetCDF -#except: -# # runtime we don't have the whole scientific package -# import NetCDF +#import pupynere as NetCDF +try: + # dev environment + from Scientific.IO import NetCDF +except: + # runtime we don't have the whole scientific package + import NetCDF import JUtil import iscUtil diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py index 1bf9b782f7..ab1691f06f 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py @@ -21,13 +21,13 @@ import os, stat, time, string, bisect, getopt, sys, traceback import LogStream, iscTime, iscUtil, mergeGrid -import pupynere as NetCDF -#try: -# # dev environment -# from Scientific.IO import NetCDF -#except: -# # runtime we don't have the whole scientific package -# import NetCDF +#import pupynere as NetCDF +try: + # dev environment + from Scientific.IO import NetCDF +except: + # runtime we don't have the whole scientific package + import NetCDF import numpy import JUtil diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject b/edexOsgi/com.raytheon.edex.plugin.grib/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject index 4105c55c03..d04ff31480 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject +++ b/edexOsgi/com.raytheon.edex.plugin.grib/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject @@ -11,3 +11,5 @@ com.raytheon.edex.plugin.grib.util.GribParamInfo com.raytheon.edex.plugin.grib.util.ParameterInfo com.raytheon.edex.plugin.grib.spatial.FileData com.raytheon.edex.plugin.grib.spatial.FileDataList +com.raytheon.edex.plugin.grib.decoderpostprocessors.PostProcessedModelSet +com.raytheon.edex.plugin.grib.decoderpostprocessors.PostProcessedModel diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GribPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GribPostProcessor.java index d94c5af917..627a0c36cb 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GribPostProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/GribPostProcessor.java @@ -20,23 +20,20 @@ package com.raytheon.edex.plugin.grib.decoderpostprocessors; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import com.raytheon.uf.common.dataplugin.grib.GribRecord; import com.raytheon.uf.common.dataplugin.grib.exception.GribException; -import com.raytheon.uf.common.localization.IPathManager; -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.dataplugin.grib.util.GribModelLookup; import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.serialization.SerializationException; +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; /** * An implementation to modify a grib record after the initial grid decoding if @@ -56,147 +53,162 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * @version 1 */ public class GribPostProcessor { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(GribPostProcessor.class); + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(GribPostProcessor.class); - /** The singleton instance */ - private static GribPostProcessor instance; + /** The singleton instance */ + private static GribPostProcessor instance; - /** The map containing the currently registered grib post processors */ - private static Map> processorMap = new HashMap>(); + /** The map containing the currently registered grib post processors */ + private static Map> processorMap = new HashMap>(); - /** - * Gets the singleton instance of GribPostProcessor - * - * @return The singleton instance of GribPostProcessor - */ - public static synchronized GribPostProcessor getInstance() { - if (instance == null) { - instance = new GribPostProcessor(); - } - return instance; - } + private static final String CLASS_PREFIX = "com.raytheon.edex.plugin.grib.decoderpostprocessors."; - /** - * Creates a new GribPostProcessor instance - */ - private GribPostProcessor() { - IPathManager pm = PathManagerFactory.getPathManager(); - String processorFile = pm.getFile( - pm.getContext(LocalizationType.EDEX_STATIC, - LocalizationLevel.BASE), - "/grib/postProcessModels/postProcessedModels.txt").getPath(); - BufferedReader in = null; - try { - in = new BufferedReader(new FileReader(processorFile)); - String line = null; - String[] tokens = null; - while ((line = in.readLine()) != null) { - if (line.startsWith("#") || line.trim().isEmpty()) { - continue; - } - tokens = line.split(":"); - String model = tokens[0].trim(); - IDecoderPostProcessor postProcessor = getPostProcessor( - tokens[0].trim(), tokens[1].trim()); - if (processorMap.containsKey(model)) { - processorMap.get(model).add(postProcessor); - } else { - ArrayList processors = new ArrayList(); - processors.add(postProcessor); - processorMap.put(model, processors); - } - } - in.close(); - } catch (IOException e) { - statusHandler.handle(Priority.PROBLEM, - "Error reading post processed model file", e); - } catch (GribException e) { - statusHandler.handle(Priority.PROBLEM, - "Error instantiating decoder post processor", e); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - statusHandler.handle(Priority.PROBLEM, - "Error closing post processed model file", e); - } - } - } - } + /** + * Gets the singleton instance of GribPostProcessor + * + * @return The singleton instance of GribPostProcessor + */ + public static synchronized GribPostProcessor getInstance() { + if (instance == null) { + instance = new GribPostProcessor(); + } + return instance; + } - /** - * Processes the GribRecords to determine if they need post processing - * - * @param records - * The records to examine - * @return The GribRecords including any new records created during the post - * processing - * @throws GribException - */ - public GribRecord[] process(GribRecord[] records) throws GribException { - List processors; - GribRecord[] results = null; - List additionalGrids = null; - for (int i = 0; i < records.length; i++) { - // Check the map to see if this grib record is part of a model for - // which post processing is necessary - processors = processorMap.get(records[i].getModelInfo() - .getModelName()); - if (processors != null) { - for (IDecoderPostProcessor processor : processors) { - // Post processing is not necessary, so we continue - if (processor == null) { - continue; - } - // Post processing is necessary - else { - results = processor.process(records[i]); - if (results.length == 0) { - return results; - } - records[i] = results[0]; - if (results.length > 1) { - if (additionalGrids == null) { - additionalGrids = new ArrayList(); - } - for (int j = 1; j < results.length; j++) { - additionalGrids.add(results[j]); - } - } - } - } - } - } - if (additionalGrids == null) { - return records; - } else { - for (int i = 0; i < records.length; i++) { - additionalGrids.add(records[i]); - } - return additionalGrids.toArray(new GribRecord[] {}); - } - } + /** + * Creates a new GribPostProcessor instance + */ + private GribPostProcessor() { + String processorFile = PathManagerFactory + .getPathManager() + .getStaticFile( + "/grib/postProcessModels/postProcessedModels.xml") + .getPath(); - private IDecoderPostProcessor getPostProcessor(String modelName, - String processorClassName) throws GribException { + try { + // Get the list of available model names + Set modelNames = GribModelLookup.getInstance() + .getModelNames(); - for (List processors : processorMap.values()) { - for (IDecoderPostProcessor processor : processors) { - if (processor.getClass().getCanonicalName() - .equals(processorClassName)) { - return processor; - } - } - } - try { - return (IDecoderPostProcessor) Class.forName(processorClassName) - .newInstance(); - } catch (Exception e) { - throw new GribException( - "Error instantiating decoder post processor for " - + modelName + " model.", e); - } - } + // Unmarshal the post processed model file + PostProcessedModelSet ppModelSet = (PostProcessedModelSet) SerializationUtil + .jaxbUnmarshalFromXmlFile(processorFile); + + /* + * Iterate over post processed models. Determine which models apply + * to each post processor if a regex is present + */ + for (PostProcessedModel ppModel : ppModelSet.getModels()) { + for (String modelName : modelNames) { + if (modelName.matches(ppModel.getModelName())) { + List processorInstances = processorMap + .get(modelName); + if (processorInstances == null) { + processorMap.put(modelName, + new ArrayList()); + processorInstances = processorMap.get(modelName); + } + + for (String processor : ppModel.getProcessors()) { + try { + processorInstances + .add((IDecoderPostProcessor) Class + .forName( + CLASS_PREFIX + + processor) + .newInstance()); + } catch (InstantiationException e) { + statusHandler + .fatal("Error instantiating grib post processor!", + e); + } catch (IllegalAccessException e) { + statusHandler + .fatal("Error instantiating grib post processor!", + e); + } catch (ClassNotFoundException e) { + statusHandler + .info("Class [" + + CLASS_PREFIX + + processor + + "] not found. Trying to load class: [" + + processor + "]"); + try { + processorInstances + .add((IDecoderPostProcessor) Class + .forName(processor) + .newInstance()); + } catch (Exception e1) { + statusHandler + .fatal("Error instantiating grib post processor!", + e1); + } + } + + } + + } + } + } + } catch (SerializationException e) { + statusHandler.fatal( + "Error unmarshalling post processed model list: "+processorFile, e); + } + + } + + /** + * Processes the GribRecords to determine if they need post processing + * + * @param records + * The records to examine + * @return The GribRecords including any new records created during the post + * processing + * @throws GribException + */ + public GribRecord[] process(GribRecord[] records) throws GribException { + List processors; + GribRecord[] results = null; + List additionalGrids = null; + for (int i = 0; i < records.length; i++) { + // Check the map to see if this grib record is part of a model for + // which post processing is necessary + processors = processorMap.get(records[i].getModelInfo() + .getModelName()); + if (processors != null) { + for (IDecoderPostProcessor processor : processors) { + // Post processing is not necessary, so we continue + if (processor == null) { + continue; + } + // Post processing is necessary + else { + results = processor.process(records[i]); + if (results.length == 0) { + continue; + } + records[i] = results[0]; + if (results.length > 1) { + if (additionalGrids == null) { + additionalGrids = new ArrayList(); + } + for (int j = 1; j < results.length; j++) { + additionalGrids.add(results[j]); + } + } + } + } + } + } + if (additionalGrids == null) { + return records; + } else { + GribRecord[] returnArray = new GribRecord[records.length+additionalGrids.size()]; + System.arraycopy(records, 0, returnArray, 0, records.length); + for (int i = records.length; i < returnArray.length; i++) { + returnArray[i] = additionalGrids.get(i-records.length); + } + return returnArray; + } + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/PostProcessedModel.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/PostProcessedModel.java new file mode 100644 index 0000000000..5e5fb9ff77 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/PostProcessedModel.java @@ -0,0 +1,100 @@ +/** + * 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.grib.decoderpostprocessors; + +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.serialization.ISerializableObject; + +/** + * A container class to hold which post processors apply to a grib model + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * 7/24/12      949         bphillip    Initial Creation
+ * 
+ * 
+ * + * @author bphillip + * @version 1 + */ +@XmlRootElement(name = "postProcessedModel") +@XmlAccessorType(XmlAccessType.NONE) +public class PostProcessedModel implements ISerializableObject { + + /** + * The model name to which the processors apply. May be a regular expression + */ + @XmlElement + private String modelName; + + /** + * The list of grib decoder post processors. The short class name may be + * used if the class is in the + * com.raytheon.edex.plugin.grib.decoderpostprocessors package. A fully + * qualified name may be used if the grib post processor is defined + * elsewhere + */ + @XmlElement(name = "processorName") + private List processors; + + public PostProcessedModel() { + + } + + public String getModelName() { + return modelName; + } + + public void setModelName(String modelName) { + this.modelName = modelName; + } + + public List getProcessors() { + if (processors == null) { + processors = new ArrayList(); + } + return processors; + } + + public void setProcessors(List processors) { + this.processors = processors; + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append(modelName).append("\n"); + for (String proc : processors) { + buf.append(proc).append("\n"); + } + return buf.toString(); + } + +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/PostProcessedModelSet.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/PostProcessedModelSet.java new file mode 100644 index 0000000000..62c3135951 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/PostProcessedModelSet.java @@ -0,0 +1,70 @@ +/** + * 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.grib.decoderpostprocessors; + +import java.util.ArrayList; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.common.serialization.ISerializableObject; + +/** + * A container class to hold the list of models needing to be post processed + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * 7/24/12      949         bphillip    Initial Creation
+ * 
+ * 
+ * + * @author bphillip + * @version 1 + */ +@XmlRootElement(name = "postProcessedModels") +@XmlAccessorType(XmlAccessType.NONE) +public class PostProcessedModelSet implements ISerializableObject{ + + /** + * List of post processed modesl + */ + @XmlElements({ @XmlElement(name = "postProcessedModel", type = PostProcessedModel.class) }) + private ArrayList models; + + public ArrayList getModels() { + if(models == null){ + models = new ArrayList(); + } + return models; + } + + public void setModels(ArrayList models) { + this.models = models; + } + +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/DefaultSubGridCenterPoint.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/DefaultSubGridCenterPoint.java new file mode 100644 index 0000000000..18d762a9fb --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/DefaultSubGridCenterPoint.java @@ -0,0 +1,79 @@ +/** + * 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.grib.spatial; + +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.geospatial.MapUtil; +import com.raytheon.uf.common.serialization.ISerializableObject; + +/** + * Default sub grid center point. If latitude/longitude may be null. This would + * show that the wfo center point should be looked up. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 25, 2012 977        rjpeter     Initial creation
+ * 
+ * 
+ * + * @author rjpeter + * @version 1.0 + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class DefaultSubGridCenterPoint implements ISerializableObject { + private Double centerLatitude; + + private Double centerLongitude; + + public Double getCenterLatitude() { + return centerLatitude; + } + + @XmlElement + public void setCenterLatitude(final Double centerLatitude) { + this.centerLatitude = centerLatitude; + if (this.centerLatitude != null) { + this.centerLatitude = new Double(MapUtil.correctLat(centerLatitude + .doubleValue())); + } + } + + public Double getCenterLongitude() { + return centerLongitude; + } + + @XmlElement + public void setCenterLongitude(final Double centerLongitude) { + this.centerLongitude = centerLongitude; + if (this.centerLongitude != null) { + this.centerLongitude = new Double( + MapUtil.correctLon(centerLongitude.doubleValue())); + } + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/GribSpatialCache.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/GribSpatialCache.java index ee199ae5dc..2b7bb6d8e0 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/GribSpatialCache.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/GribSpatialCache.java @@ -50,6 +50,7 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel 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.JAXBManager; import com.raytheon.uf.common.serialization.SerializationException; import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.edex.awipstools.GetWfoCenterHandler; @@ -74,7 +75,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 4/7/09 1994 bphillip Initial Creation - * + * Jul 25, 2012 977 rjpeter Add ability for sub grids to have a defined center point. * * * @author bphillip @@ -82,669 +83,727 @@ import com.vividsolutions.jts.geom.Coordinate; */ public class GribSpatialCache { - /** The logger */ - protected transient Log logger = LogFactory.getLog(getClass()); - - /** The singleton instance */ - private static GribSpatialCache instance = new GribSpatialCache(); - - /** - * Map containing the GridCoverages
- * The key for this map is the id field of the GridCoverage object stored as - * the value of the map - */ - private Map spatialMap; - - /** - * Map containing the GridCoverages
- * The key for this map is the name field of the GridCoverage object stored - * as the value of the map. This is only used internally for lookup of a - * coverage by name aka gridId. - */ - private Map spatialNameMap; - - /** - * Map containing the subGrid coverage based on a model name. - */ - private Map subGridCoverageMap; - - /** - * Map containing the subGrid definition based on a model name. - */ - private Map definedSubGridMap; - - /** - * Gets the singleton instance of GribSpatialCache - * - * @return The singleton instance of the GribSpatialCache - */ - public static GribSpatialCache getInstance() { - return instance; - } - - /** - * Creates a new GribSpatialCache - */ - private GribSpatialCache() { - spatialMap = new HashMap(); - spatialNameMap = new HashMap(); - definedSubGridMap = new HashMap(); - subGridCoverageMap = new HashMap(); - initializeGrids(); - } - - /** - * Retrieves a grid from the map. If the grid does not exist, null is - * returned - * - * @param id - * The id of the GridCoverage to retrieve - * @return The GridCoverage object, null if not present - * @throws GribException - * @throws DataAccessLayerException - */ - public GridCoverage getGrid(GridCoverage coverage) throws GribException { - GridCoverage retVal = spatialMap.get(coverage.getId()); - - if (retVal == null) { - /* - * Coverage not found in cache, but the values provided in the GDS - * may be slightly different than those for the grid in the cache. - * Check the database to be sure. - */ - try { - retVal = ((IGridCoverageDao) EDEXUtil.getESBComponent(coverage - .getProjectionType().replaceAll(" ", "") + "Dao")) - .checkGrid(coverage); - } catch (DataAccessLayerException e) { - throw new GribException("Error querying for grib coverage!", e); - } - - if (retVal != null) { - spatialMap.put(coverage.getId(), retVal); - spatialNameMap.put(coverage.getName(), retVal); - } - - } - - return retVal; - } - - public GridCoverage getGrid(int id) { - return spatialMap.get(id); - } - - public GridCoverage getGrid(String modelName) { - GridCoverage rval = null; - - if (modelName != null) { - if (subGridCoverageMap.containsKey(modelName)) { - rval = spatialMap.get(subGridCoverageMap.get(modelName)); - } else { - GridModel model = GribModelLookup.getInstance().getModelByName( - modelName); - if (model != null) { - rval = spatialNameMap.get(model.getGrid().toString()); - } - } - } - - return rval; - } - - public GridCoverage getGridByName(String name) { - return spatialNameMap.get(name); - } - - /** - * Puts a grid into the GribSpatialCache. - * - * @param grid - * The grid to store - * @param persistToDb - * True if this GridCoverage object is to be persisted to the - * database - * @throws GribException - * If problems occur while initializing the grid - */ - public void putGrid(GridCoverage grid, boolean initializeGrid, - boolean persistToDb) throws GribException { - if (initializeGrid) { - /* - * Prepare the grid to be stored into the cache. Initializes the - * geometry and crs objects and generates the id field - */ - grid.initialize(); - if (grid.getName() == null) { - grid.generateName(); - } - } - - // Persist to the database if desired - if (persistToDb) { - new CoreDao(DaoConfig.DEFAULT).saveOrUpdate(grid); - } - - spatialMap.put(grid.getId(), grid); - spatialNameMap.put(grid.getName(), grid); - } - - public SubGrid getSubGrid(String modelName) { - return definedSubGridMap.get(modelName); - } - - public GridCoverage getSubGridCoverage(String modelName) { - GridCoverage rval = null; - - if (subGridCoverageMap.containsKey(modelName)) { - rval = spatialMap.get(subGridCoverageMap.get(modelName)); - } - - return rval; - } - - /** - * Initializes the predefined set of grids. The grids are stored in xml - * format in the utility folder so the localization service has access to - * them.
- * GridCoverage are created from the xml via JaxB and placed in the cache - */ - private void initializeGrids() { - ClusterTask ct = null; - - do { - ct = ClusterLockUtils.lock("grib", "spatialCache", 120000, true); - } while (!LockState.SUCCESSFUL.equals(ct.getLockState())); - - try { - // pull all the coverage from the database - GridCoverageDao dao = new GridCoverageDao(); - FileDataList previousFdl = getPreviousFileDataList(); - FileDataList currentFdl = generateFileDataList(); - - if (isDefintionChanged(previousFdl, currentFdl)) { - processBaseGridsChanged(dao, currentFdl); - saveFileDataList(currentFdl); - } else { - List baseCoverages = dao - .loadBaseGrids(); - - if (baseCoverages != null && baseCoverages.size() > 0) { - for (Object obj : baseCoverages) { - try { - putGrid((GridCoverage) obj, false, false); - } catch (Exception e) { - // Log error but do not throw exception, technically - // is - // only from initialize which isn't being called - logger.error( - "Unable to load grid coverage into cache " - + obj, e); - } - } - } else { - // database wiped/plugin re-initialized need to repopulate - processBaseGridsChanged(dao, currentFdl); - saveFileDataList(currentFdl); - } - } - - processUnknownGrids(dao); - processSubGrids(dao, currentFdl); - } finally { - ClusterLockUtils.unlock(ct, false); - } - } - - /** - * A non subgridded definition has been added, deleted, or changed. - * Changed/delete both delete all records, models, and coverage defintion. - * Then Change/Add put in a new coverage definition. - * - * TODO: Post process Unknown definitions to see if they are now known. If - * now known delete definitions of unknown. - * - * @param dao - * @param currentFdl - */ - private void processBaseGridsChanged(GridCoverageDao dao, - FileDataList currentFdl) { - List baseCoverages = dao.loadBaseGrids(); - Map fileCoverageMap = loadGridDefinitionsFromDisk(currentFdl); - - // update needs to delete all hdf5 same as delete, so update is - // a delete and then an add to simplify logic and handle primary - // key changes. - List coveragesToDelete = new LinkedList(); - HashSet validDbCoverageNames = new HashSet( - (int) (baseCoverages.size() * 1.25) + 1); - - Iterator iter = baseCoverages.iterator(); - while (iter.hasNext()) { - GridCoverage dbCov = iter.next(); - GridCoverage fileCoverage = fileCoverageMap.get(dbCov.getName()); - if (!dbCov.equals(fileCoverage)) { - // coverage not in flat file or coverage has changed, - // delete coverage old coverage - coveragesToDelete.add(dbCov); - iter.remove(); - } else { - // current coverage still valid - validDbCoverageNames.add(dbCov.getName()); - } - } - - // delete grids, models, coverages, and hdf5 for namesToDelete. - for (GridCoverage cov : coveragesToDelete) { - logger.info("GridCoverage " + cov.getName() - + " has changed. Deleting out of date data"); - if (!dao.deleteCoverageAssociatedData(cov, true)) { - logger.warn("Failed to delete GridCoverage " + cov.getName() - + ". Manual intervention required."); - } else { - logger.info("GridCoverage successfully deleted"); - } - } - - // remove the valid db coverages from the map - fileCoverageMap.keySet().removeAll(validDbCoverageNames); - - // add new grids in bulk - for (GridCoverage cov : fileCoverageMap.values()) { - try { - putGrid(cov, true, false); - } catch (Exception e) { - logger.error( - "Failed to initialize grid definition " + cov.getName(), - e); - } - } - - // bulk persist the spatial maps - if (spatialMap.size() > 0) { - dao.persistAll(spatialMap.values()); - } - - for (GridCoverage cov : baseCoverages) { - try { - putGrid(cov, false, false); - } catch (Exception e) { - logger.error( - "Failed to initialize grid definition " + cov.getName(), - e); - } - } - } - - /** - * A non subGridd definition has been added, deleted, or changed. - * Changed/delete both delete all records, models, and coverage defintion. - * Then Change/Add put in a new coverage definition, and also delete any - * data associated with base model definition. - * - * @param dao - * @param currentFdl - */ - private void processSubGrids(GridCoverageDao dao, FileDataList currentFdl) { - List oldSubGridCoverages = dao.loadSubGrids(); - Map fileSubGridCoverageMap = loadSubGridDefinitionsFromDisk(currentFdl); - - // update needs to delete all hdf5 same as delete, so update is - // a delete and then an add to simplify logic and handle primary - // key changes. - List coveragesToDelete = new LinkedList(); - HashSet validDbCoverageNames = new HashSet( - (int) (oldSubGridCoverages.size() * 1.25) + 1); - - Iterator iter = oldSubGridCoverages.iterator(); - while (iter.hasNext()) { - GridCoverage dbCov = iter.next(); - GridCoverage fileCoverage = fileSubGridCoverageMap.get(dbCov - .getName()); - if (!dbCov.equals(fileCoverage)) { - // coverage not in flat file or coverage has changed, - // delete coverage - coveragesToDelete.add(dbCov); - iter.remove(); - } else { - // current coverage still valid - validDbCoverageNames.add(dbCov.getName()); - } - } - - // delete grids, models, coverages, and hdf5 for namesToDelete. - for (GridCoverage cov : coveragesToDelete) { - logger.info("Model " - + cov.getSubGridModel() - + " has changed subGrid definition, deleting out of date data"); - if (!dao.deleteCoverageAssociatedData(cov, true)) { - logger.warn("Failed to delete GridCoverage " + cov.getName() - + ". Manual intervention required."); - } else { - logger.info("GridModel successfully deleted"); - } - } - - // remove the valid db coverages from the map - fileSubGridCoverageMap.keySet().removeAll(validDbCoverageNames); - - // need to delete model information for new adds, as old grid may not - // have been subgridded - GribModelDao modelDao = new GribModelDao(); - for (GridCoverage cov : fileSubGridCoverageMap.values()) { - logger.info("Model " - + cov.getSubGridModel() - + " has changed subGrid definition, deleting out of date data"); - // look up parent - if (modelDao.deleteModelAndAssociatedData(cov.getSubGridModel()) < 0) { - logger.warn("Failed to delete SubGrid Model " - + cov.getSubGridModel() - + ". Manual intervention required."); - } else { - logger.info("GridModel successfully deleted"); - } - } - - // add new grids, persisting individually - for (GridCoverage cov : fileSubGridCoverageMap.values()) { - try { - putGrid(cov, true, true); - subGridCoverageMap.put(cov.getSubGridModel(), cov.getId()); - } catch (Exception e) { - logger.error( - "Failed to initialize grid definition " + cov.getName(), - e); - } - } - - // put database grids into map - for (GridCoverage cov : oldSubGridCoverages) { - try { - putGrid(cov, true, true); - subGridCoverageMap.put(cov.getSubGridModel(), cov.getId()); - } catch (Exception e) { - logger.error( - "Failed to initialize grid definition " + cov.getName(), - e); - } - } - } - - private void processUnknownGrids(GridCoverageDao dao) { - List unknownGrids = dao.loadUnknownGrids(); - for (GridCoverage cov : unknownGrids) { - try { - GridCoverage dbCov = getGrid(cov); - if (!cov.getName().equals(dbCov.getName())) { - logger.info("Unknown grid " + cov.getName() - + " is now mapped by " + dbCov.getName() - + ". Deleting unknown grid"); - dao.deleteCoverageAssociatedData(cov, true); - } - } catch (Exception e) { - logger.error("Erro occurred scanning unknown grids", e); - } - } - } - - private Map loadSubGridDefinitionsFromDisk( - FileDataList currentFdl) { - GribModelLookup gribModelLUT = GribModelLookup.getInstance(); - List subGridDefs = currentFdl.getSubGridFileList(); - Map subGrids = null; - - if (subGridDefs != null && subGridDefs.size() > 0) { - subGrids = new HashMap(subGridDefs.size() * 3); - Coordinate wfoCenterPoint = null; - String wfo = SiteUtil.getSite(); - GetWfoCenterPoint centerPointRequest = new GetWfoCenterPoint(wfo); - try { - wfoCenterPoint = new GetWfoCenterHandler() - .handleRequest(centerPointRequest); - } catch (Exception e) { - logger.error( - "Failed to generate sub grid definitions. Unable to lookup WFO Center Point", - e); - return new HashMap(0); - } - - for (FileData fd : subGridDefs) { - try { - SubGridDef subGridDef = loadSubGridDef(fd.getFilePath()); - - if (subGridDef != null) { - String referenceModel = subGridDef.getReferenceModel(); - - GridCoverage gridCoverage = getGrid(referenceModel); - - if (gridCoverage != null) { - Coordinate wfoCenter = MapUtil - .latLonToGridCoordinate(wfoCenterPoint, - PixelOrientation.CENTER, - gridCoverage); - - double xCenterPoint = wfoCenter.x; - double yCenterPoint = wfoCenter.y; - - double xDistance = subGridDef.getNx() / 2; - double yDistance = subGridDef.getNy() / 2; - Coordinate lowerLeftPosition = new Coordinate( - xCenterPoint - xDistance, yCenterPoint - + yDistance); - Coordinate upperRightPosition = new Coordinate( - xCenterPoint + xDistance, yCenterPoint - - yDistance); - - lowerLeftPosition = MapUtil.gridCoordinateToLatLon( - lowerLeftPosition, PixelOrientation.CENTER, - gridCoverage); - upperRightPosition = MapUtil - .gridCoordinateToLatLon(upperRightPosition, - PixelOrientation.CENTER, - gridCoverage); - - subGridDef.setLowerLeftLon(lowerLeftPosition.x); - subGridDef.setLowerLeftLat(lowerLeftPosition.y); - subGridDef.setUpperRightLon(upperRightPosition.x); - subGridDef.setUpperRightLat(upperRightPosition.y); - - // verify numbers in -180 -> 180 range - subGridDef.setLowerLeftLon(MapUtil - .correctLon(subGridDef.getLowerLeftLon())); - subGridDef.setUpperRightLon(MapUtil - .correctLon(subGridDef.getUpperRightLon())); - - // do a reverse lookup of the model name to get its - // associated grid id - - for (String modelName : subGridDef.getModelNames()) { - GridModel model = gribModelLUT - .getModelByName(modelName); - if (model != null) { - GridCoverage baseCoverage = spatialNameMap - .get(model.getGrid().toString()); - - if (baseCoverage != null) { - SubGrid subGrid = new SubGrid(); - subGrid.setModelName(modelName); - GridCoverage subGridCoverage = baseCoverage - .trim(subGridDef, subGrid); - if (subGridCoverage != null) { - subGrids.put( - subGridCoverage.getName(), - subGridCoverage); - definedSubGridMap.put(modelName, - subGrid); - } - } - } - } - } else { - logger.error("Failed to generate sub grid for " - + fd.getFilePath() - + ". Unable to determine coverage for referenceModel [" - + referenceModel + "]"); - } - } - } catch (Exception e) { - // Log error but do not throw exception - logger.error( - "Failed processing sub grid file: " - + fd.getFilePath(), e); - } - } - } else { - subGrids = new HashMap(0); - } - - return subGrids; - } - - /** - * Loads and validates subGridDef pointed to by filePath. If definition - * empty/invalid returns null. - * - * @param filePath - * @return - */ - private SubGridDef loadSubGridDef(String filePath) { - SubGridDef rval = null; - File f = new File(filePath); - - if (f.length() > 0) { - try { - rval = (SubGridDef) SerializationUtil - .jaxbUnmarshalFromXmlFile(f); - if (rval.getReferenceModel() == null - || rval.getModelNames() == null - || rval.getModelNames().size() == 0) { - // sub grid didn't have required definitions - rval = null; - } - } catch (SerializationException e) { - logger.error("Failed reading sub grid file: " + filePath, e); - } - } - - return rval; - } - - private static boolean isDefintionChanged(FileDataList previousFdl, - FileDataList currentFdl) { - boolean rval = true; - if (currentFdl != null) { - rval = !currentFdl.equals(previousFdl); - } else { - rval = previousFdl != null; - } - - return rval; - } - - private FileDataList generateFileDataList() { - /* - * Retrieve the list of files from the localization service - */ - IPathManager pm = PathManagerFactory.getPathManager(); - FileDataList fileList = new FileDataList(); - LocalizationContext[] contexts = pm - .getLocalSearchHierarchy(LocalizationType.EDEX_STATIC); - fileList.addCoverageFiles(pm.listFiles(contexts, "/grib/grids", - new String[] { "xml" }, true, true)); - fileList.addSubGridFiles(pm.listFiles(contexts, "/grib/subgrids", - new String[] { "xml" }, true, true)); - - return fileList; - } - - private FileDataList getPreviousFileDataList() { - IPathManager pm = PathManagerFactory.getPathManager(); - File previousFileData = pm.getFile(pm.getContext( - LocalizationType.EDEX_STATIC, LocalizationLevel.CONFIGURED), - "/grib/gridDefFileListing.xml"); - FileDataList rval = null; - - if (previousFileData.exists() && previousFileData.length() > 0) { - try { - Object obj = SerializationUtil - .jaxbUnmarshalFromXmlFile(previousFileData); - if (obj instanceof FileDataList) { - rval = (FileDataList) obj; - } else { - logger.error("Error occurred deserializing " - + previousFileData.getAbsolutePath() - + ", expected type " + FileDataList.class - + " received " + obj.getClass()); - } - } catch (Exception e) { - logger.error( - "Error occurred deserializing " - + previousFileData.getAbsolutePath(), e); - } - } - return rval; - } - - private Map loadGridDefinitionsFromDisk( - FileDataList currentFdl) { - List coverageFiles = currentFdl.getCoverageFileList(); - Map fileCoverageMap = new HashMap( - (int) (coverageFiles.size() * 1.25) + 1); - - /* - * Iterate over file list. Unmarshal to GridCoverage object - */ - for (FileData fd : coverageFiles) { - try { - GridCoverage grid = (GridCoverage) SerializationUtil - .jaxbUnmarshalFromXmlFile(fd.getFilePath()); - GridCoverage previousGrid = fileCoverageMap.put(grid.getName(), - grid); - if (previousGrid != null) { - for (FileData fd2 : coverageFiles) { - GridCoverage grid2 = (GridCoverage) SerializationUtil - .jaxbUnmarshalFromXmlFile(fd2.getFilePath()); - if (grid.getName().equals(grid2.getName())) { - logger.error("Grid " + grid.getName() - + " has already been defined. " - + fd.getFilePath() + " and " - + fd2.getFilePath() - + " have same name. Using " - + fd2.getFilePath()); - break; - } - } - } - } catch (Exception e) { - // Log error but do not throw exception - logger.error( - "Unable to read default grids file: " - + fd.getFilePath(), e); - } - } - - return fileCoverageMap; - } - - private void saveFileDataList(FileDataList fdl) { - try { - IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationFile lf = pm.getLocalizationFile( - pm.getContext(LocalizationType.EDEX_STATIC, - LocalizationLevel.CONFIGURED), - "/grib/gridDefFileListing.xml"); - SerializationUtil.jaxbMarshalToXmlFile(fdl, lf.getFile() - .getAbsolutePath()); - lf.save(); - } catch (Exception e) { - logger.error( - "Failed to save coverage file data list, coverages may be reloaded on next restart", - e); - } - } - - public static void reinitialize() { - GribSpatialCache newInstance = new GribSpatialCache(); - instance = newInstance; - } + /** The logger */ + protected Log logger = LogFactory.getLog(getClass()); + + /** The singleton instance */ + private static GribSpatialCache instance = new GribSpatialCache(); + + /** + * Map containing the GridCoverages
+ * The key for this map is the id field of the GridCoverage object stored as + * the value of the map + */ + private final Map spatialMap; + + /** + * Map containing the GridCoverages
+ * The key for this map is the name field of the GridCoverage object stored + * as the value of the map. This is only used internally for lookup of a + * coverage by name aka gridId. + */ + private final Map spatialNameMap; + + /** + * Map containing the subGrid coverage based on a model name. + */ + private final Map subGridCoverageMap; + + /** + * Map containing the subGrid definition based on a model name. + */ + private final Map definedSubGridMap; + + /** + * Gets the singleton instance of GribSpatialCache + * + * @return The singleton instance of the GribSpatialCache + */ + public static GribSpatialCache getInstance() { + return instance; + } + + /** + * Creates a new GribSpatialCache + */ + private GribSpatialCache() { + spatialMap = new HashMap(); + spatialNameMap = new HashMap(); + definedSubGridMap = new HashMap(); + subGridCoverageMap = new HashMap(); + initializeGrids(); + } + + /** + * Retrieves a grid from the map. If the grid does not exist, null is + * returned + * + * @param id + * The id of the GridCoverage to retrieve + * @return The GridCoverage object, null if not present + * @throws GribException + * @throws DataAccessLayerException + */ + public GridCoverage getGrid(final GridCoverage coverage) + throws GribException { + GridCoverage retVal = spatialMap.get(coverage.getId()); + + if (retVal == null) { + /* + * Coverage not found in cache, but the values provided in the GDS + * may be slightly different than those for the grid in the cache. + * Check the database to be sure. + */ + try { + retVal = ((IGridCoverageDao) EDEXUtil.getESBComponent(coverage + .getProjectionType().replaceAll(" ", "") + "Dao")) + .checkGrid(coverage); + } catch (DataAccessLayerException e) { + throw new GribException("Error querying for grib coverage!", e); + } + + if (retVal != null) { + spatialMap.put(coverage.getId(), retVal); + spatialNameMap.put(coverage.getName(), retVal); + } + + } + + return retVal; + } + + public GridCoverage getGrid(final int id) { + return spatialMap.get(id); + } + + public GridCoverage getGrid(final String modelName) { + GridCoverage rval = null; + + if (modelName != null) { + if (subGridCoverageMap.containsKey(modelName)) { + rval = spatialMap.get(subGridCoverageMap.get(modelName)); + } else { + GridModel model = GribModelLookup.getInstance().getModelByName( + modelName); + if (model != null) { + rval = spatialNameMap.get(model.getGrid().toString()); + } + } + } + + return rval; + } + + public GridCoverage getGridByName(final String name) { + return spatialNameMap.get(name); + } + + /** + * Puts a grid into the GribSpatialCache. + * + * @param grid + * The grid to store + * @param persistToDb + * True if this GridCoverage object is to be persisted to the + * database + * @throws GribException + * If problems occur while initializing the grid + */ + public void putGrid(final GridCoverage grid, final boolean initializeGrid, + final boolean persistToDb) throws GribException { + if (initializeGrid) { + /* + * Prepare the grid to be stored into the cache. Initializes the + * geometry and crs objects and generates the id field + */ + grid.initialize(); + if (grid.getName() == null) { + grid.generateName(); + } + } + + // Persist to the database if desired + if (persistToDb) { + new CoreDao(DaoConfig.DEFAULT).saveOrUpdate(grid); + } + + spatialMap.put(grid.getId(), grid); + spatialNameMap.put(grid.getName(), grid); + } + + public SubGrid getSubGrid(final String modelName) { + return definedSubGridMap.get(modelName); + } + + public GridCoverage getSubGridCoverage(final String modelName) { + GridCoverage rval = null; + + if (subGridCoverageMap.containsKey(modelName)) { + rval = spatialMap.get(subGridCoverageMap.get(modelName)); + } + + return rval; + } + + /** + * Initializes the predefined set of grids. The grids are stored in xml + * format in the utility folder so the localization service has access to + * them.
+ * GridCoverage are created from the xml via JaxB and placed in the cache + */ + private void initializeGrids() { + ClusterTask ct = null; + + do { + ct = ClusterLockUtils.lock("grib", "spatialCache", 120000, true); + } while (!LockState.SUCCESSFUL.equals(ct.getLockState())); + + try { + // pull all the coverage from the database + GridCoverageDao dao = new GridCoverageDao(); + FileDataList previousFdl = getPreviousFileDataList(); + FileDataList currentFdl = generateFileDataList(); + + if (isDefintionChanged(previousFdl, currentFdl)) { + processBaseGridsChanged(dao, currentFdl); + saveFileDataList(currentFdl); + } else { + List baseCoverages = dao + .loadBaseGrids(); + + if ((baseCoverages != null) && (baseCoverages.size() > 0)) { + for (Object obj : baseCoverages) { + try { + putGrid((GridCoverage) obj, false, false); + } catch (Exception e) { + // Log error but do not throw exception, technically + // is + // only from initialize which isn't being called + logger.error( + "Unable to load grid coverage into cache " + + obj, e); + } + } + } else { + // database wiped/plugin re-initialized need to repopulate + processBaseGridsChanged(dao, currentFdl); + saveFileDataList(currentFdl); + } + } + + processUnknownGrids(dao); + processSubGrids(dao, currentFdl); + } finally { + ClusterLockUtils.unlock(ct, false); + } + } + + /** + * A non subgridded definition has been added, deleted, or changed. + * Changed/delete both delete all records, models, and coverage defintion. + * Then Change/Add put in a new coverage definition. + * + * TODO: Post process Unknown definitions to see if they are now known. If + * now known delete definitions of unknown. + * + * @param dao + * @param currentFdl + */ + private void processBaseGridsChanged(final GridCoverageDao dao, + final FileDataList currentFdl) { + List baseCoverages = dao.loadBaseGrids(); + Map fileCoverageMap = loadGridDefinitionsFromDisk(currentFdl); + + // update needs to delete all hdf5 same as delete, so update is + // a delete and then an add to simplify logic and handle primary + // key changes. + List coveragesToDelete = new LinkedList(); + HashSet validDbCoverageNames = new HashSet( + (int) (baseCoverages.size() * 1.25) + 1); + + Iterator iter = baseCoverages.iterator(); + while (iter.hasNext()) { + GridCoverage dbCov = iter.next(); + GridCoverage fileCoverage = fileCoverageMap.get(dbCov.getName()); + if (!dbCov.equals(fileCoverage)) { + // coverage not in flat file or coverage has changed, + // delete coverage old coverage + coveragesToDelete.add(dbCov); + iter.remove(); + } else { + // current coverage still valid + validDbCoverageNames.add(dbCov.getName()); + } + } + + // delete grids, models, coverages, and hdf5 for namesToDelete. + for (GridCoverage cov : coveragesToDelete) { + logger.info("GridCoverage " + cov.getName() + + " has changed. Deleting out of date data"); + if (!dao.deleteCoverageAssociatedData(cov, true)) { + logger.warn("Failed to delete GridCoverage " + cov.getName() + + ". Manual intervention required."); + } else { + logger.info("GridCoverage successfully deleted"); + } + } + + // remove the valid db coverages from the map + fileCoverageMap.keySet().removeAll(validDbCoverageNames); + + // add new grids in bulk + for (GridCoverage cov : fileCoverageMap.values()) { + try { + putGrid(cov, true, false); + } catch (Exception e) { + logger.error( + "Failed to initialize grid definition " + cov.getName(), + e); + } + } + + // bulk persist the spatial maps + if (spatialMap.size() > 0) { + dao.persistAll(spatialMap.values()); + } + + for (GridCoverage cov : baseCoverages) { + try { + putGrid(cov, false, false); + } catch (Exception e) { + logger.error( + "Failed to initialize grid definition " + cov.getName(), + e); + } + } + } + + /** + * A non subGridd definition has been added, deleted, or changed. + * Changed/delete both delete all records, models, and coverage defintion. + * Then Change/Add put in a new coverage definition, and also delete any + * data associated with base model definition. + * + * @param dao + * @param currentFdl + */ + private void processSubGrids(final GridCoverageDao dao, + final FileDataList currentFdl) { + List oldSubGridCoverages = dao.loadSubGrids(); + Map fileSubGridCoverageMap = loadSubGridDefinitionsFromDisk(currentFdl); + + // update needs to delete all hdf5 same as delete, so update is + // a delete and then an add to simplify logic and handle primary + // key changes. + List coveragesToDelete = new LinkedList(); + HashSet validDbCoverageNames = new HashSet( + (int) (oldSubGridCoverages.size() * 1.25) + 1); + + Iterator iter = oldSubGridCoverages.iterator(); + while (iter.hasNext()) { + GridCoverage dbCov = iter.next(); + GridCoverage fileCoverage = fileSubGridCoverageMap.get(dbCov + .getName()); + if (!dbCov.equals(fileCoverage)) { + // coverage not in flat file or coverage has changed, + // delete coverage + coveragesToDelete.add(dbCov); + iter.remove(); + } else { + // current coverage still valid + validDbCoverageNames.add(dbCov.getName()); + } + } + + // delete grids, models, coverages, and hdf5 for namesToDelete. + for (GridCoverage cov : coveragesToDelete) { + logger.info("Model " + + cov.getSubGridModel() + + " has changed subGrid definition, deleting out of date data"); + if (!dao.deleteCoverageAssociatedData(cov, true)) { + logger.warn("Failed to delete GridCoverage " + cov.getName() + + ". Manual intervention required."); + } else { + logger.info("GridModel successfully deleted"); + } + } + + // remove the valid db coverages from the map + fileSubGridCoverageMap.keySet().removeAll(validDbCoverageNames); + + // need to delete model information for new adds, as old grid may not + // have been subgridded + GribModelDao modelDao = new GribModelDao(); + for (GridCoverage cov : fileSubGridCoverageMap.values()) { + logger.info("Model " + + cov.getSubGridModel() + + " has changed subGrid definition, deleting out of date data"); + // look up parent + if (modelDao.deleteModelAndAssociatedData(cov.getSubGridModel()) < 0) { + logger.warn("Failed to delete SubGrid Model " + + cov.getSubGridModel() + + ". Manual intervention required."); + } else { + logger.info("GridModel successfully deleted"); + } + } + + // add new grids, persisting individually + for (GridCoverage cov : fileSubGridCoverageMap.values()) { + try { + putGrid(cov, true, true); + subGridCoverageMap.put(cov.getSubGridModel(), cov.getId()); + } catch (Exception e) { + logger.error( + "Failed to initialize grid definition " + cov.getName(), + e); + } + } + + // put database grids into map + for (GridCoverage cov : oldSubGridCoverages) { + try { + putGrid(cov, true, true); + subGridCoverageMap.put(cov.getSubGridModel(), cov.getId()); + } catch (Exception e) { + logger.error( + "Failed to initialize grid definition " + cov.getName(), + e); + } + } + } + + private void processUnknownGrids(final GridCoverageDao dao) { + List unknownGrids = dao.loadUnknownGrids(); + for (GridCoverage cov : unknownGrids) { + try { + GridCoverage dbCov = getGrid(cov); + if (!cov.getName().equals(dbCov.getName())) { + logger.info("Unknown grid " + cov.getName() + + " is now mapped by " + dbCov.getName() + + ". Deleting unknown grid"); + dao.deleteCoverageAssociatedData(cov, true); + } + } catch (Exception e) { + logger.error("Erro occurred scanning unknown grids", e); + } + } + } + + private Map loadSubGridDefinitionsFromDisk( + final FileDataList currentFdl) { + GribModelLookup gribModelLUT = GribModelLookup.getInstance(); + List subGridDefs = currentFdl.getSubGridFileList(); + Map subGrids = null; + + if ((subGridDefs != null) && (subGridDefs.size() > 0)) { + subGrids = new HashMap(subGridDefs.size() * 3); + + Coordinate defaultCenterPoint = null; + + try { + defaultCenterPoint = getDefaultSubGridCenterPoint(); + } catch (Exception e) { + logger.error( + "Failed to generate sub grid definitions. Unable to lookup WFO Center Point", + e); + return new HashMap(0); + } + + for (FileData fd : subGridDefs) { + try { + SubGridDef subGridDef = loadSubGridDef(fd.getFilePath(), + defaultCenterPoint); + + if (subGridDef != null) { + String referenceModel = subGridDef.getReferenceModel(); + + GridCoverage gridCoverage = getGrid(referenceModel); + + if (gridCoverage != null) { + Coordinate subGridCenterLatLon = new Coordinate( + subGridDef.getCenterLongitude(), + subGridDef.getCenterLatitude()); + + Coordinate subGridCenterGridCoord = MapUtil + .latLonToGridCoordinate( + subGridCenterLatLon, + PixelOrientation.CENTER, + gridCoverage); + + double xCenterPoint = subGridCenterGridCoord.x; + double yCenterPoint = subGridCenterGridCoord.y; + + double xDistance = subGridDef.getNx() / 2; + double yDistance = subGridDef.getNy() / 2; + Coordinate lowerLeftPosition = new Coordinate( + xCenterPoint - xDistance, yCenterPoint + + yDistance); + Coordinate upperRightPosition = new Coordinate( + xCenterPoint + xDistance, yCenterPoint + - yDistance); + + lowerLeftPosition = MapUtil.gridCoordinateToLatLon( + lowerLeftPosition, PixelOrientation.CENTER, + gridCoverage); + upperRightPosition = MapUtil + .gridCoordinateToLatLon(upperRightPosition, + PixelOrientation.CENTER, + gridCoverage); + + subGridDef.setLowerLeftLon(lowerLeftPosition.x); + subGridDef.setLowerLeftLat(lowerLeftPosition.y); + subGridDef.setUpperRightLon(upperRightPosition.x); + subGridDef.setUpperRightLat(upperRightPosition.y); + + // verify numbers in -180 -> 180 range + subGridDef.setLowerLeftLon(MapUtil + .correctLon(subGridDef.getLowerLeftLon())); + subGridDef.setUpperRightLon(MapUtil + .correctLon(subGridDef.getUpperRightLon())); + + // do a reverse lookup of the model name to get its + // associated grid id + + for (String modelName : subGridDef.getModelNames()) { + GridModel model = gribModelLUT + .getModelByName(modelName); + if (model != null) { + GridCoverage baseCoverage = spatialNameMap + .get(model.getGrid().toString()); + + if (baseCoverage != null) { + SubGrid subGrid = new SubGrid(); + subGrid.setModelName(modelName); + GridCoverage subGridCoverage = baseCoverage + .trim(subGridDef, subGrid); + if (subGridCoverage != null) { + subGrids.put( + subGridCoverage.getName(), + subGridCoverage); + definedSubGridMap.put(modelName, + subGrid); + } + } + } + } + } else { + logger.error("Failed to generate sub grid for " + + fd.getFilePath() + + ". Unable to determine coverage for referenceModel [" + + referenceModel + "]"); + } + } + } catch (Exception e) { + // Log error but do not throw exception + logger.error( + "Failed processing sub grid file: " + + fd.getFilePath(), e); + } + } + } else { + subGrids = new HashMap(0); + } + + return subGrids; + } + + /** + * Loads and validates subGridDef pointed to by filePath. If definition + * empty/invalid returns null. + * + * @param filePath + * @return + */ + private SubGridDef loadSubGridDef(final String filePath, + final Coordinate defaultCenter) { + SubGridDef rval = null; + File f = new File(filePath); + + if (f.length() > 0) { + try { + rval = (SubGridDef) SerializationUtil + .jaxbUnmarshalFromXmlFile(f); + if ((rval.getReferenceModel() == null) + || (rval.getModelNames() == null) + || (rval.getModelNames().size() == 0)) { + // sub grid didn't have required definitions + rval = null; + } else { + if ((rval.getCenterLatitude() == null) + || (rval.getCenterLongitude() == null)) { + rval.setCenterLatitude(defaultCenter.y); + rval.setCenterLongitude(defaultCenter.x); + } + } + } catch (SerializationException e) { + logger.error("Failed reading sub grid file: " + filePath, e); + } + } + + return rval; + } + + private static boolean isDefintionChanged(final FileDataList previousFdl, + final FileDataList currentFdl) { + boolean rval = true; + if (currentFdl != null) { + rval = !currentFdl.equals(previousFdl); + } else { + rval = previousFdl != null; + } + + return rval; + } + + private FileDataList generateFileDataList() { + /* + * Retrieve the list of files from the localization service + */ + IPathManager pm = PathManagerFactory.getPathManager(); + FileDataList fileList = new FileDataList(); + LocalizationContext[] contexts = pm + .getLocalSearchHierarchy(LocalizationType.EDEX_STATIC); + fileList.addCoverageFiles(pm.listFiles(contexts, "/grib/grids", + new String[] { "xml" }, true, true)); + fileList.addSubGridFiles(pm.listFiles(contexts, "/grib/subgrids", + new String[] { "xml" }, true, true)); + + return fileList; + } + + private FileDataList getPreviousFileDataList() { + IPathManager pm = PathManagerFactory.getPathManager(); + File previousFileData = pm.getFile(pm.getContext( + LocalizationType.EDEX_STATIC, LocalizationLevel.CONFIGURED), + "/grib/gridDefFileListing.xml"); + FileDataList rval = null; + + if (previousFileData.exists() && (previousFileData.length() > 0)) { + try { + Object obj = SerializationUtil + .jaxbUnmarshalFromXmlFile(previousFileData); + if (obj instanceof FileDataList) { + rval = (FileDataList) obj; + } else { + logger.error("Error occurred deserializing " + + previousFileData.getAbsolutePath() + + ", expected type " + FileDataList.class + + " received " + obj.getClass()); + } + } catch (Exception e) { + logger.error( + "Error occurred deserializing " + + previousFileData.getAbsolutePath(), e); + } + } + return rval; + } + + private Map loadGridDefinitionsFromDisk( + final FileDataList currentFdl) { + List coverageFiles = currentFdl.getCoverageFileList(); + Map fileCoverageMap = new HashMap( + (int) (coverageFiles.size() * 1.25) + 1); + + /* + * Iterate over file list. Unmarshal to GridCoverage object + */ + for (FileData fd : coverageFiles) { + try { + GridCoverage grid = (GridCoverage) SerializationUtil + .jaxbUnmarshalFromXmlFile(fd.getFilePath()); + GridCoverage previousGrid = fileCoverageMap.put(grid.getName(), + grid); + if (previousGrid != null) { + for (FileData fd2 : coverageFiles) { + GridCoverage grid2 = (GridCoverage) SerializationUtil + .jaxbUnmarshalFromXmlFile(fd2.getFilePath()); + if (grid.getName().equals(grid2.getName())) { + logger.error("Grid " + grid.getName() + + " has already been defined. " + + fd.getFilePath() + " and " + + fd2.getFilePath() + + " have same name. Using " + + fd2.getFilePath()); + break; + } + } + } + } catch (Exception e) { + // Log error but do not throw exception + logger.error( + "Unable to read default grids file: " + + fd.getFilePath(), e); + } + } + + return fileCoverageMap; + } + + private void saveFileDataList(final FileDataList fdl) { + try { + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationFile lf = pm.getLocalizationFile( + pm.getContext(LocalizationType.EDEX_STATIC, + LocalizationLevel.CONFIGURED), + "/grib/gridDefFileListing.xml"); + SerializationUtil.jaxbMarshalToXmlFile(fdl, lf.getFile() + .getAbsolutePath()); + lf.save(); + } catch (Exception e) { + logger.error( + "Failed to save coverage file data list, coverages may be reloaded on next restart", + e); + } + } + + public static void reinitialize() { + GribSpatialCache newInstance = new GribSpatialCache(); + instance = newInstance; + } + + private Coordinate getDefaultSubGridCenterPoint() throws Exception { + Coordinate defaultCenterPoint = null; + IPathManager pm = PathManagerFactory.getPathManager(); + File defaultSubGridLocationFile = pm + .getStaticFile("/grib/defaultSubGridCenterPoint.xml"); + if ((defaultSubGridLocationFile != null) + && defaultSubGridLocationFile.exists()) { + try { + // only used here, just create own manager + JAXBManager mgr = new JAXBManager( + DefaultSubGridCenterPoint.class); + DefaultSubGridCenterPoint defaultSubGridLocation = (DefaultSubGridCenterPoint) mgr + .jaxbUnmarshalFromXmlFile(defaultSubGridLocationFile); + if ((defaultSubGridLocation != null) + && (defaultSubGridLocation.getCenterLatitude() != null) + && (defaultSubGridLocation.getCenterLongitude() != null)) { + defaultCenterPoint = new Coordinate( + defaultSubGridLocation.getCenterLongitude(), + defaultSubGridLocation.getCenterLatitude()); + logger.info("Default sub grid location is overriden as [" + + defaultCenterPoint.y + "/" + defaultCenterPoint.x + + "]"); + } + } catch (Exception e) { + logger.error( + "Unable to load default sub grid location from file: " + + defaultSubGridLocationFile.getAbsolutePath(), + e); + } + } + + if (defaultCenterPoint == null) { + // use wfo center point + String wfo = SiteUtil.getSite(); + GetWfoCenterPoint centerPointRequest = new GetWfoCenterPoint(wfo); + defaultCenterPoint = new GetWfoCenterHandler() + .handleRequest(centerPointRequest); + logger.info("Default sub grid location is wfo center point [" + + defaultCenterPoint.y + "/" + defaultCenterPoint.x + "]"); + } + + return defaultCenterPoint; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/grid/models/gribModels_NCEP-7.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/grid/models/gribModels_NCEP-7.xml index 7475a0936a..37aa32f136 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/grid/models/gribModels_NCEP-7.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/common_static/base/grid/models/gribModels_NCEP-7.xml @@ -1219,6 +1219,19 @@
1
+ + Aviation + Aviation +
7
+ 8 + 130 + + 105 + + +
1
+
+ AK-NamDNG5 AK-NamDNG5 diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/defaultSubGridCenterPoint.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/defaultSubGridCenterPoint.xml new file mode 100644 index 0000000000..4ad2509ec3 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/defaultSubGridCenterPoint.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.txt b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.txt deleted file mode 100644 index ae96f585d8..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.txt +++ /dev/null @@ -1,80 +0,0 @@ -# RUC130 PostProcessor -RUC130:com.raytheon.edex.plugin.grib.decoderpostprocessors.RUC130GribPostProcessor - -# Generate 6Hr Records Post Processor -ECMWF-HiRes:com.raytheon.edex.plugin.grib.decoderpostprocessors.ECMWFHiResProcessor -GFS213:com.raytheon.edex.plugin.grib.decoderpostprocessors.GFSProcessor - -# Post Processor For Lifted Index, if the ability to limit post processing to specific -# parameters is ever added this would be better done there -ETA:com.raytheon.edex.plugin.grib.decoderpostprocessors.Nam80PostProcessor -ETA218:com.raytheon.edex.plugin.grib.decoderpostprocessors.LiftedIndexPostProcessor -ETA242:com.raytheon.edex.plugin.grib.decoderpostprocessors.LiftedIndexPostProcessor -GFS212:com.raytheon.edex.plugin.grib.decoderpostprocessors.LiftedIndexPostProcessor -GFS213:com.raytheon.edex.plugin.grib.decoderpostprocessors.LiftedIndexPostProcessor - -# Ensemble Grids that need to be stitched together -AVN37:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -AVN38:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -AVN39:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -AVN40:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ECMF1:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ECMF2:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ECMF3:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ECMF4:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ECMF5:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ECMF6:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ECMF7:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ECMF8:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ENSEMBLE37:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ENSEMBLE38:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ENSEMBLE39:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -ENSEMBLE40:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -UKMET37:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -UKMET38:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -UKMET39:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler -UKMET40:com.raytheon.edex.plugin.grib.decoderpostprocessors.EnsembleGridAssembler - -# FFG grids -FFG-TIR:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-RSA:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-ORN:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-FWR:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-MSR:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-TUA:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-ALR:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-RHA:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-STR:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-KRF:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-ACR:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-PTR:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor -FFG-TAR:com.raytheon.edex.plugin.grib.decoderpostprocessors.FFGGribPostProcessor - -#RFCqpf grids -RFCqpf:com.raytheon.edex.plugin.grib.decoderpostprocessors.OverwriteGribPostProcessor -#MPE-Local grids -MPE-Local:com.raytheon.edex.plugin.grib.decoderpostprocessors.OverwriteGribPostProcessor -MPE-Mosaic:com.raytheon.edex.plugin.grib.decoderpostprocessors.OverwriteGribPostProcessor - -#RTMA grids -RTMA:com.raytheon.edex.plugin.grib.decoderpostprocessors.RTMAGribPostProcessor - -#LAPS grids -LAPS:com.raytheon.edex.plugin.grib.decoderpostprocessors.LapsPostProcessor - -#TPC grids -CPCoutlook211:com.raytheon.edex.plugin.grib.decoderpostprocessors.CPCoutlookGribPostProcessor - -#MSAS grids -MSAS:com.raytheon.edex.plugin.grib.decoderpostprocessors.MSASPostProcessor - -#HPCqpf grids -HPCqpf:com.raytheon.edex.plugin.grib.decoderpostprocessors.OverwriteGribPostProcessor -HPCqpfNDFD:com.raytheon.edex.plugin.grib.decoderpostprocessors.OverwriteGribPostProcessor - -#Canadian GEM grids -Canadian-Reg:com.raytheon.edex.plugin.grib.decoderpostprocessors.CanadianRegPostProcessor -Canadian-NH:com.raytheon.edex.plugin.grib.decoderpostprocessors.CanadianNHPostProcessor - -# RUC236 PostProcessor -RUC236:com.raytheon.edex.plugin.grib.decoderpostprocessors.RUC236GribPostProcessor \ No newline at end of file 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 new file mode 100644 index 0000000000..9f76ee1f23 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.xml @@ -0,0 +1,125 @@ + + + + + + UKMET[0-9]{2}|ECMF[0-9]{2}|ENSEMBLE[0-9]{2}|AVN[0-9]{2} + + EnsembleGridAssembler + + + + + HPCqpfNDFD + OverwriteGribPostProcessor + + + + RFCqpf + OverwriteGribPostProcessor + + + + HPCqpf + OverwriteGribPostProcessor + + + + MPE-.*|QPE-.* + OverwriteGribPostProcessor + + + + + FFG-[A-Z]{3} + FFGGribPostProcessor + + + + + ETA218 + LiftedIndexPostProcessor + + + + GFS212 + LiftedIndexPostProcessor + + + + GFS213 + GFSProcessor + LiftedIndexPostProcessor + + + + ETA242 + LiftedIndexPostProcessor + + + + + RTMA + RTMAGribPostProcessor + + + + + ECMWF-HiRes + ECMWFHiResProcessor + + + + + MSAS + MSASPostProcessor + + + + + ETA + Nam80PostProcessor + + + + + RUC236 + RUC236GribPostProcessor + + + + + CPCoutlook211 + CPCoutlookGribPostProcessor + + + + + Canadian-NH + CanadianNHPostProcessor + + + + Canadian-Reg + CanadianRegPostProcessor + + + + + LAPS + LapsPostProcessor + + + + + RUC130 + RUC130GribPostProcessor + + + + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HPCGuideClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HPCGuideClip.xml index c21da411d4..ab94f7dc86 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HPCGuideClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HPCGuideClip.xml @@ -23,4 +23,8 @@ HPCGuide 1000 689 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresEastClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresEastClip.xml index 82f91ed105..e7b2a4dcd4 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresEastClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresEastClip.xml @@ -23,4 +23,8 @@ HiResW-ARW-East 350 350 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresWestClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresWestClip.xml index 23e0015f63..4d6bc9c00b 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresWestClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresWestClip.xml @@ -23,4 +23,8 @@ HiResW-ARW-West 350 350 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/NamDng5Clip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/NamDng5Clip.xml index 2caa2abc3b..c99157b454 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/NamDng5Clip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/NamDng5Clip.xml @@ -23,4 +23,8 @@ NamDNG5 1000 689 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/RTMAClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/RTMAClip.xml index c4df1fae25..eb01326f9a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/RTMAClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/RTMAClip.xml @@ -23,4 +23,8 @@ RTMA 1000 689 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/TPCSurgeProbClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/TPCSurgeProbClip.xml index 4ea0ecc485..92e3392120 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/TPCSurgeProbClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/TPCSurgeProbClip.xml @@ -23,4 +23,8 @@ TPCSurgeProb 1300 1200 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/eta12Clip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/eta12Clip.xml index d5d24291e0..016e515cd7 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/eta12Clip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/eta12Clip.xml @@ -23,4 +23,8 @@ ETA218 175 175 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/lampClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/lampClip.xml index eb867ff980..0b10917a4a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/lampClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/lampClip.xml @@ -23,4 +23,8 @@ GFSLAMPTstorm 1000 689 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mEtaClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mEtaClip.xml index 00d0305989..731e71509f 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mEtaClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mEtaClip.xml @@ -23,4 +23,8 @@ mesoEta215 175 173 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip.xml index f7b13838f6..5eb5d17fab 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip.xml @@ -23,4 +23,8 @@ MOSGuide 350 350 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip_AK.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip_AK.xml index 7caec069b9..8406bef85a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip_AK.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip_AK.xml @@ -23,4 +23,8 @@ MOSGuide-AK 1649 1105 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/qpf218Clip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/qpf218Clip.xml index 0c9510408a..eec432b1f6 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/qpf218Clip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/qpf218Clip.xml @@ -23,4 +23,8 @@ RFCqpf 175 175 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/ruc13Clip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/ruc13Clip.xml index 366dcf955e..27fadd9eae 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/ruc13Clip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/ruc13Clip.xml @@ -23,4 +23,8 @@ RUC130 175 175 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/.classpath b/edexOsgi/com.raytheon.edex.plugin.pirep/.classpath index 1fa3e6803d..c83df31842 100644 --- a/edexOsgi/com.raytheon.edex.plugin.pirep/.classpath +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/.classpath @@ -3,5 +3,6 @@ + diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.edex.plugin.pirep/META-INF/MANIFEST.MF index 3a178e8193..b535f2431e 100644 --- a/edexOsgi/com.raytheon.edex.plugin.pirep/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/META-INF/MANIFEST.MF @@ -12,7 +12,8 @@ Require-Bundle: com.raytheon.edex.common, org.geotools, javax.measure, javax.persistence, - org.apache.camel;bundle-version="1.0.0";resolution:=optional + org.apache.camel;bundle-version="1.0.0";resolution:=optional, + org.junit;bundle-version="1.0.0" Export-Package: com.raytheon.edex.plugin.pirep, com.raytheon.edex.plugin.pirep.decoder Bundle-RequiredExecutionEnvironment: JavaSE-1.6 diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepParser.java b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepParser.java index 9ee5b4902d..5cb40aa13b 100644 --- a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepParser.java +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepParser.java @@ -58,6 +58,11 @@ import com.vividsolutions.jts.geom.Point; * Date PR# Engineer Description * ----------- ---------- ------------ -------------------------- * 20080116 798 jkorman Changed logging levels. + * ====================================== + * AWIPS2 DR Work + * 08/09/2012 1011 jkorman Changed parser to use TEIInfo to + * parse text elements properly. Removed test code to unit-test + * parse TEIs. * * * @author jkorman @@ -69,14 +74,6 @@ public class PirepParser { // Allowable future time in milliseconds (15 minutes). private static final int ALLOWABLE_TIME = 15; - private static final String[] RPIDS = { "UUA", "UA" }; - - /** - * Note that there are intentionally spaces after some of the teis. - */ - private static final String[] TEIS = { "/OV ", "/TM", "/FL", "/TP", "/SK ", - "/WX", "/TA", "/WV", "/TB", "/IC", "/RM" }; - private static final String SK_SKC = "SKC"; private static final String SK_CLR = "CLR"; @@ -171,12 +168,6 @@ public class PirepParser { // Was character non-alphanumeric but not whitespace? private static final int NONALPHANUMERIC = 3; - // The last search position when looking for TEIs - private int theSearchPos = -1; - - // Where was the Token found - private int theTokenPos; - private String reportData = null; private String theReportingStationId = null; @@ -219,6 +210,7 @@ public class PirepParser { private Headers headers; + private int reportType = IDecoderConstants.PIREP_NORMAL; /** * Construct a PirepParser from given String data. The report is completely * parsed and decoded upon success. @@ -256,7 +248,7 @@ public class PirepParser { } public Integer getReportType() { - return IDecoderConstants.PIREP_NORMAL; + return reportType; } /** @@ -397,114 +389,74 @@ public class PirepParser { * An error occurred within this method. */ protected void parse() { - int pirepIndex = 0; - - // Look for a 'UUA' or 'UA' indicator to denote the start of - // the report. - if (!nextString(reportData, pirepIndex, reportData.length(), RPIDS)) { - return; - } - // if failed to decode reporting station id, this must be Canadian pirep // TODO convert! - - // Find the first TEI within the report. - if (!nextString(reportData, pirepIndex, reportData.length(), TEIS)) { - return; - } - int pos1 = this.theSearchPos; - int tei1 = this.theTokenPos; - int teiIndex = pos1 + TEIS[tei1].length(); - int pos2, tei2; - - while (teiIndex < reportData.length()) { - // Find the end of the data for this TEI by finding the next - // TEI within the report. - int endTeiIndex; - boolean lastTei = !nextString(reportData, teiIndex, - reportData.length(), TEIS); - pos2 = this.theSearchPos; - tei2 = this.theTokenPos; - if (lastTei) { - // This is the last TEI within the report, so set the end - // of the data for this TEI equal to the end of the report. - endTeiIndex = reportData.length(); - } else { - endTeiIndex = pos2; - } - + + List positions = TEIInfo.findTEIs(reportData); + // Look for a 'UUA' or 'UA' indicator to denote the start of + // the report. + if ((positions.size() > 0) && (TEI.PIREP.equals(positions.get(0).getTei()))) { boolean success = false; - switch (tei1) { - case 0: - // Decode and store the "/OV" (i.e. location) data. - success = decodeLocationData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 1: - // Decode and store the "/TM" (i.e. time) data. - success = decodeTimeData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 2: - // Decode and store the "/FL" (i.e. flight level) data. - success = decodeFlightLevelData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 3: - // Decode and store the "/TP" (i.e. aircraft type) data. - success = decodeAircraftTypeData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 4: - // Decode and store the "/SK" (i.e. sky cover) data. - success = decodeSkyCoverData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 5: - // Decode and store the "/WX" (i.e. weather) data. - success = decodeWeatherData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 6: - // Decode and store the "/TA" (i.e. temperature) data. - success = decodeTemperatureData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 7: - // Decode and store the "/WV" (i.e. wind) data. - success = decodeWindData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 8: - // Decode and store the "/TB" (i.e. turbulence) data. - success = decodeTurbulenceData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 9: - // Decode and store the "/IC" (i.e. icing) data. - success = decodeIcingData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 10: - // Decode and store the "/RM" (i.e. remarks) data. - success = decodeRemarksData(reportData.substring(teiIndex, - endTeiIndex)); - break; - } // switch() + for (TEIInfo t : positions) { + switch (t.getTei()) { + case PIREP: { + // success = decodeReportingStationId(t.getTeiText()); + success = true; + break; + } + case OV: + // Decode and store the "/OV" (i.e. location) data. + success = decodeLocationData(t.getTeiText()); + break; + case TM: + // Decode and store the "/TM" (i.e. time) data. + success = decodeTimeData(t.getTeiText()); + break; + case FL: + // Decode and store the "/FL" (i.e. flight level) data. + success = decodeFlightLevelData(t.getTeiText()); + break; + case TP: + // Decode and store the "/TP" (i.e. aircraft type) data. + success = decodeAircraftTypeData(t.getTeiText()); + break; + case SK: + // Decode and store the "/SK" (i.e. sky cover) data. + success = decodeSkyCoverData(t.getTeiText()); + break; + case WX: + // Decode and store the "/WX" (i.e. weather) data. + success = decodeWeatherData(t.getTeiText()); + break; + case TA: + // Decode and store the "/TA" (i.e. temperature) data. + success = decodeTemperatureData(t.getTeiText()); + break; + case WV: + // Decode and store the "/WV" (i.e. wind) data. + success = decodeWindData(t.getTeiText()); + break; + case TB: + // Decode and store the "/TB" (i.e. turbulence) data. + success = decodeTurbulenceData(t.getTeiText()); + break; + case IC: + // Decode and store the "/IC" (i.e. icing) data. + success = decodeIcingData(t.getTeiText()); + break; + case RM: + // Decode and store the "/RM" (i.e. remarks) data. + success = decodeRemarksData(t.getTeiText()); + break; + default: { + logger.error(String.format("Invalid PIREP identifier [%s] found", t.getTeiText())); + break; + } + } // switch() + } // for + } else { - // discontinue if processing of any data fails - if (!success) { - // TODO: add logging - } - - if (lastTei) { - teiIndex = reportData.length(); - } else { - pos1 = pos2; - tei1 = tei2; - teiIndex = pos1 + TEIS[tei1].length(); - } - } // while() + } } // parse() /** @@ -1034,7 +986,7 @@ public class PirepParser { * A possible temperature to be decoded. * @return Was the temperature data decoded. * @throws DecodeException - * If a decode error occured. + * If a decode error occurred. */ protected boolean decodeTemperatureData(String aTemperature) { // Break up the input string into groups of "like-type" in order @@ -1495,54 +1447,6 @@ public class PirepParser { } } - /** - * The nextString method determines the position of the first occurrence of - * any of a list of substrings within the input string. This method provides - * equivalent functionality to the routine ST_NXTS in the ported code. The - * outputs are provided in member variables. - * - * @param str - * Input string - * @param firstPos - * First position to check - * @param lastPos - * Last position to check - * @param subStrings - * List of substrings - * @return success or failure - */ - protected boolean nextString(String str, int firstPos, int lastPos, - String subStrings[]) { - this.theTokenPos = -1; - String tstr = str.substring(0, lastPos); - for (int i = 0; i < subStrings.length; i++) { - if ((this.theSearchPos = tstr.indexOf(subStrings[i], firstPos)) != -1) { - this.theTokenPos = i; - return true; - } - } - - return false; - } - - /** - * This method finds a string in a string array and returns its index. - * - * @param str - * String to find - * @param strs - * Strings to compare - * @return index of matching string or -1 on failure - */ - protected int findString(String str, String[] strs) { - for (int i = 0; i < strs.length; i++) { - if (strs[i].equals(str)) { - return i; - } - } - return -1; - } // findString() - /** * This method groups "like-types" of characters to facilitate decoding. * This method provides equivalent functionality to the UT_BKGP subroutine @@ -1587,63 +1491,4 @@ public class PirepParser { return strs.toArray(new String[0]); } - - public static final void main(String[] args) { - - String[] latlons = { "0000N 00000W", "0000S 00000E", "9000S 00000W", - "9000N 00000W", "0000N 09000W", "9000S 09000W", "9000N 09000W", - - "0000N 09000W", "4500S 09000W", "9000N 09000W", - - "9000N 09959W", "0000N 10000W", - - "4500S 09000W", "9000N 09000W", - - "9000N 18000E", "9000S 18000E", "9000N 18000W", "9000S 18000W", - "9000N 17959W", "9000S 17959W", - - }; - - Pattern p = Pattern.compile(LATLON_PTRN); - - for (String s : latlons) { - Matcher m = p.matcher(s); - if (m.find()) { - BasePoint b = parseLatLon(m.group()); - if (b != null) { - System.out.println(String.format("%16s %10.6f %11.6f", s, - b.getLatitude(), b.getLongitude())); - } else { - System.out.println("Invalid parse " + s); - } - } else { - System.out.println("no match for " + s); - } - } - - String str = "123 123 123 \r SCT"; - - str = str.replaceAll("[\r\n]", " "); - str = str.replaceAll(" {2,}", " "); - - System.out.println("[" + str + "]"); - - p = Pattern.compile(bearingDistPattern); - Matcher m = p.matcher("OMA 080056"); - if(m.find()) { - System.out.println(m.group(1)); - System.out.println(m.group(2) + " " + m.group(3)); - } - m = p.matcher("OMA080056"); - if(m.find()) { - System.out.println(m.group(1)); - System.out.println(m.group(2) + " " + m.group(3)); - } - - - - - - } - } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepTools.java b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepTools.java index d88d009a59..b1421b4814 100644 --- a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepTools.java +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepTools.java @@ -20,16 +20,14 @@ package com.raytheon.edex.plugin.pirep.decoder; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import com.raytheon.uf.edex.decodertools.aircraft.AircraftFlightCondition; import com.raytheon.uf.edex.decodertools.aircraft.Entry; import com.raytheon.uf.edex.decodertools.aircraft.WordTranslator; /** - * TODO Add Description + * Perform decode on PIREP turbulence layers. * *
  * 
@@ -38,6 +36,9 @@ import com.raytheon.uf.edex.decodertools.aircraft.WordTranslator;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Jun 10, 2011            jkorman     Initial creation
+ * ======================================
+ * AWIPS2 DR Work
+ * 08/09/2012         1011 jkorman     Removed test code to unit test.
  * 
  * 
* @@ -50,7 +51,6 @@ public class PirepTools { private static final char SPACE = ' '; private static final char DASH = '-'; - private static final char SOLIDUS = '/'; @@ -164,13 +164,15 @@ public class PirepTools { TURBC_WORDS.enter("-", "-", false, TURBC_SYN_DASH, SYN_ID); } + // Data that may contain layer information. private String layerData; + // Layers decoded from layerData private List layers; /** - * - * @param data + * Construct zero or more layers from the supplied data. + * @param data A string that may contain layer information. */ public PirepTools(String data) { layerData = data; @@ -403,9 +405,9 @@ public class PirepTools { } /** - * If there are two intensity modifiers, reorder them so the the - * lower intensity occurs first. - * @param layer A layer that may contain intensity modifiers. + * If there are two heights, reorder them so the the + * lower height occurs first. + * @param layer A layer that may contain layer heights. */ private void reOrderHeight(AircraftFlightCondition layer) { if(layer != null) { @@ -440,57 +442,4 @@ public class PirepTools { return retValue; } // parseInteger() - /** - * @param args - */ - public static void main(String[] args) { - - // PirepTools tools = new - // PirepTools("OCNL LGT CHOP/MDT 100-150/LGT 150-200"); - - -// List list = tools.decodeTurbulenceData(); -// for (AircraftFlightCondition c : list) { -// System.out.println(c); -// } - - String [] data = { - "LGT 100-120", - "MOD TO SVR 100", - "SVR OCNL MOD 200-300", - "LGT CHOP 150 TO 110", - "LGT-MDT 120-150", - "MDT BLO\n 100", - "LIT-MOD CHOP ABOVE 120", - "CONTINOUS MOD 120-080"}; - for(String s : data) { - PirepTools tools = new PirepTools(s); - - List list = tools.decodeTurbulenceData(); - for(AircraftFlightCondition afc : list) { - String ss = afc.getFrequency(); - System.out.print((ss != null) ? ss : "----"); - System.out.print(" "); - ss = afc.getIntensity1(); - System.out.print((ss != null) ? ss : "----"); - System.out.print(" "); - ss = afc.getIntensity2(); - System.out.print((ss != null) ? ss : "----"); - System.out.print(" "); - ss = afc.getType(); - System.out.print((ss != null) ? ss : "----"); - System.out.print(" "); - Integer n = afc.getBaseHeight(); - System.out.print((n != null) ? n : "----"); - System.out.print(" "); - n = afc.getTopHeight(); - System.out.print((n != null) ? n : "----"); - System.out.println(); - - } - } - - - } - } diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEI.java b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEI.java new file mode 100644 index 0000000000..7547311a05 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEI.java @@ -0,0 +1,124 @@ +/** + * 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.pirep.decoder; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Enum that identifies the PIREP Text Element Indicators (TEIs). + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * AWIPS2 DR Work
+ * Aug 7, 2012        1011 jkorman     Initial creation
+ * 
+ * 
+ * + * @author jkorman + * @version 1.0 + */ + +public enum TEI implements Iterable { + // This TEI is used to identify the start of the PIREP, i.e. SSS [UA|UUA] + PIREP("PIREP"), OV("/OV "), TM("/TM "), FL("/FL"), TP("/TP"), SK("/SK "), WX( + "/WX"), TA("/TA"), WV("/WV"), TB("/TB"), IC("/IC"), RM("/RM"), + + NF("NF"); // These two don't go into the id map! + + // Map of valid TEIs. + private static Map ID_MAP = new HashMap(); + static { + ID_MAP.put(OV.id, OV); + ID_MAP.put(TM.id, TM); + ID_MAP.put(FL.id, FL); + ID_MAP.put(TP.id, TP); + ID_MAP.put(SK.id, SK); + ID_MAP.put(WX.id, WX); + ID_MAP.put(TA.id, TA); + ID_MAP.put(WV.id, WV); + ID_MAP.put(TB.id, TB); + ID_MAP.put(IC.id, IC); + ID_MAP.put(RM.id, RM); + } + + private String id; + + /** + * Construct a TEI with a specified identifier. + * + * @param id + * The identifier to assign. + */ + private TEI(String id) { + this.id = id; + } + + /** + * Get the identifier for this TEI. + * + * @return The TEI identifier. + */ + public String getId() { + return id; + } + + /** + * Get the string representation of this TEI. This returns the same as + * getId(). + * + * @return The TEI string representation. + */ + public String toString() { + return id; + } + + /** + * Get an iterator to the valid TEIs. This iterable iterator the TEI NF (not + * found). + * + * @return An iterator to the valid TEIs. + */ + @Override + public Iterator iterator() { + return ID_MAP.values().iterator(); + } + + /** + * Get a TEI based on its string identifier. Returns the TEI "NF" if the TEI + * identifier could not be found. + * + * @param id + * A candidate TEI identifier. + * @return The TEI found, or NF if not found. + */ + public static TEI getTEI(String id) { + TEI tei = NF; + if (ID_MAP.containsKey(id)) { + tei = ID_MAP.get(id); + } + return tei; + } +} \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEIInfo.java b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEIInfo.java new file mode 100644 index 0000000000..3b3d767171 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEIInfo.java @@ -0,0 +1,210 @@ +/** + * 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.pirep.decoder; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Parse Pilot Report (PIREP) Text Element Indicators (TEIs) from potential + * report text. This + * + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * AWIPS2 DR Work
+ * Aug 7, 2012        1011 jkorman     Initial creation
+ * 
+ * 
+ * + * @author jkorman + * @version 1.0 + */ + +public class TEIInfo implements Comparable { + // The start position of this TEI within the decoded data. + private int start; + + // The stop position of this TEI's text within the decoded data. + private int stop; + + // The TEI associated with the info. + private TEI tei; + + // The extracted text associated with this TEI. + private String teiText; + + /** + * Construct a TEIInfo instance with a given TEI, position, and index. + * + * @param tei + * @param position + * @param teiIndex + */ + private TEIInfo(TEI tei, int position) { + this.tei = tei; + start = position; + } + + /** + * + */ + @Override + public String toString() { + return String.format("%s:%d:%d:%d", tei, start, stop); + } + + /** + * Calculate the hashCode for this instance. + * + * @return The calculated hashCode. + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + start; + result = prime * result + ((tei == null) ? 0 : tei.hashCode()); + result = prime * result + ((teiText == null) ? 0 : teiText.hashCode()); + return result; + } + + /** + * Is this instance equal to another object instance. + * + * @return Is this instance equal to another object instance. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TEIInfo other = (TEIInfo) obj; + if (start != other.start) + return false; + if (tei != other.tei) + return false; + if (teiText == null) { + if (other.teiText != null) + return false; + } else if (!teiText.equals(other.teiText)) + return false; + return true; + } + + /** + * Override compareTo for TEIInfo. This method uses the start position of + * the TEI within the decoded data as the comparands. + */ + @Override + public int compareTo(TEIInfo t) { + return (t.start == start) ? 0 : (t.start < start) ? 1 : -1; + } + + /** + * Get the TEI that was decoded. + * + * @return The decoded TEI. + */ + public TEI getTei() { + return tei; + } + + /** + * Get the extracted text for the TEI. + * + * @return The TEI extracted text. + */ + public String getTeiText() { + return teiText; + } + + /** + * Extract the TEI information as well as the text data associated with that + * TEI into a collection of TEIInfo objects. Out of order data can be correctly + * parsed and returned. + * + * @param str + * Data containing a PIREP. + * @return Returns a list of TEIs found in the input data. Returns a zero + * length list if the input was null or no TEIs could be found. + */ + public static List findTEIs(String str) { + List positions = new ArrayList(); + if (str != null) { + int teiIndex = 0; + // loop over the valid TEIs + for (TEI tei : TEI.PIREP) { + int n = str.indexOf(tei.getId()); + if (n >= 0) { + TEIInfo info = new TEIInfo(tei, n); + positions.add(info); + } + teiIndex++; + } + Collections.sort(positions); + if (positions.size() > 0) { + TEIInfo tt = positions.get(0); + // Ensure that the PIREP is starting correctly! + if (TEI.OV.equals(tt.tei)) { + // Note that this will find both "UA" and "UUA" + if (str.substring(0, tt.start).indexOf("UA") > 0) { + // Insert the PIREP element at the 'head' of the list + positions.add(0, new TEIInfo(TEI.PIREP, 0)); + // Now iterate the list and fixup the stop positions + // of each TEI + TEIInfo previous = null; + for (TEIInfo t : positions) { + if (previous == null) { + previous = t; + } else { + previous.stop = t.start; + previous = t; + } + } + // Set the last TEI stop position to the end of the + // report. + previous.stop = str.length(); + } + } + } + // Now come in and extract the text associated with each TEI. + for (TEIInfo t : positions) { + if (TEI.PIREP.equals(t.getTei())) { + // Pick up the leading portion of the PIREP + t.teiText = str.substring(t.start, t.stop).trim(); + } else { + t.teiText = str.substring( + t.start + t.getTei().getId().length(), t.stop) + .trim(); + } + } + } + return positions; + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPParser.java b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPParser.java new file mode 100644 index 0000000000..53d3fb75bd --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPParser.java @@ -0,0 +1,167 @@ +/** + * 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 test.pirep; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Test; + +import com.raytheon.edex.plugin.pirep.decoder.PirepTools; +import com.raytheon.uf.edex.decodertools.core.BasePoint; + +import static org.junit.Assert.*; + + +/** + * Extracted methods tests from PirepParser. + * + *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 10, 2012            jkorman     Initial creation
+ *
+ * 
+ * + * @author jkorman + * @version 1.0 + */ + +public class TestPIREPParser { + + private static final String LATLON_PTRN = "((([0-8]\\d[0-5]\\d)|(9000))[NS] ((0\\d{2}[0-5]\\d)|([1][0-7]\\d[0-5]\\d)|(18000))[EW])"; + + private static BasePoint parseLatLon(String latlon) { + BasePoint point = null; + + // 012345678901 + // lldds llldds + + Integer lat_dd = PirepTools.parseInteger(latlon.substring(0, 2)); + Integer lat_mm = PirepTools.parseInteger(latlon.substring(2, 4)); + Integer lon_dd = PirepTools.parseInteger(latlon.substring(6, 9)); + Integer lon_mm = PirepTools.parseInteger(latlon.substring(9, 11)); + + if ((lat_dd != null) && (lat_mm) != null) { + if ((lon_dd != null) && (lon_mm) != null) { + + Double lat = lat_dd + (lat_mm / 60.0d); + Double lon = lon_dd + (lon_mm / 60.0d); + if (lat_dd.equals(0) && (lat_mm.equals(0))) { + lat = 0.0; + } else { + switch (latlon.charAt(4)) { + case 'N': { + break; + } + case 'S': { + lat = lat * -1; + break; + } + default: { + lat = null; + } + } + } + if (lon_dd.equals(0) && (lon_mm.equals(0))) { + lon = 0.0; + } else { + switch (latlon.charAt(11)) { + case 'E': { + break; + } + case 'W': { + lon = lon * -1; + break; + } + default: { + lon = null; + } + } + } + if (lat != null && lon != null) { + point = new BasePoint(lat, lon); + } + } + } + return point; + } + + @Test + public void testparseLatLon() { + String[] latlons = { "0000N 00000W", "0000S 00000E", "9000S 00000W", + "9000N 00000W", "0000N 09000W", "9000S 09000W", "9000N 09000W", + + "0000N 09000W", "4500S 09000W", "9000N 09000W", + + "9000N 09959W", "0000N 10000W", + + "4500S 09000W", "9000N 09000W", + + "9000N 18000E", "9000S 18000E", "9000N 18000W", "9000S 18000W", + "9000N 17959W", "9000S 17959W", + }; + + Pattern p = Pattern.compile(LATLON_PTRN); + + for (String s : latlons) { + Matcher m = p.matcher(s); + if (m.find()) { + BasePoint b = parseLatLon(m.group()); + if (b != null) { + System.out.println(String.format("%16s %10.6f %11.6f", s, + b.getLatitude(), b.getLongitude())); + } else { + fail("Invalid parse " + s); + } + } else { + fail("no match for " + s); + } + } + } + + @Test + public void testBearingDistancePattern() { + final String bearingDistPattern = "^([A-Z,0-9]{3,4})\\s*(\\d{3})(\\d{3})$"; + + String str = "123 123 123 \r SCT"; + + str = str.replaceAll("[\r\n]", " "); + str = str.replaceAll(" {2,}", " "); + + System.out.println("[" + str + "]"); + + Pattern p = Pattern.compile(bearingDistPattern); + Matcher m = p.matcher("OMA 080056"); + if(m.find()) { + System.out.println(m.group(1)); + System.out.println(m.group(2) + " " + m.group(3)); + } + m = p.matcher("OMA080056"); + if(m.find()) { + System.out.println(m.group(1)); + System.out.println(m.group(2) + " " + m.group(3)); + } + + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPRecord.java b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPRecord.java new file mode 100644 index 0000000000..70e1f7607a --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPRecord.java @@ -0,0 +1,233 @@ +/** + * 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 test.pirep; + +import java.util.List; + +import org.junit.Test; + +import com.raytheon.edex.plugin.pirep.decoder.PirepTools; +import com.raytheon.uf.common.dataplugin.pirep.PirepLayerData; +import com.raytheon.uf.common.dataplugin.pirep.PirepRecord; +import com.raytheon.uf.edex.decodertools.aircraft.AircraftFlightCondition; + +import static org.junit.Assert.*; + +/** + * Test various PIREP decoder components. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 8, 2012            jkorman     Initial creation
+ * 
+ * 
+ * + * @author jkorman + * @version 1.0 + */ + +public class TestPIREPRecord { + + /** + * Test that the getter for TBF (turbulence frequency) and TBI (turbulence + * intensity) get the data for the greatest intensity. + */ + @Test + public void testTurbulenceConstruction() { + + PirepRecord rec = new PirepRecord(); + + PirepLayerData layer = new PirepLayerData(rec); + layer.setLayerType(PirepLayerData.LAYER_TYP_TURBC); + layer.setFrequency("OCN"); + layer.setFirstValue("LGT"); + layer.setSecondValue("MOD"); + layer.setBaseLayerHeight(15000); + layer.setTopLayerHeight(20000); + rec.addLayer(layer); + + layer = new PirepLayerData(rec); + layer.setLayerType(PirepLayerData.LAYER_TYP_TURBC); + layer.setFrequency("CON"); + layer.setFirstValue("MOD"); + layer.setSecondValue("SEV"); + layer.setBaseLayerHeight(20000); + layer.setTopLayerHeight(22000); + rec.addLayer(layer); + + String[] data = rec.getStrings("TBF"); + assertNotNull(data); + assertTrue(data.length > 0); + assertEquals("CON", data[0]); + data = rec.getStrings("TBI"); + assertNotNull(data); + assertTrue(data.length > 0); + assertEquals("MODSEV", data[0]); + } + + /** + * Turbulence at one level, differing intensities. + */ + @Test + public void testPirepTurbc_1() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(10000); + expected.setTopHeight(null); + expected.setIntensity1("MOD"); + expected.setIntensity2("SEV"); + expected.setType(null); + expected.setFrequency(null); + + PirepTools t = new PirepTools("MOD TO SVR 100"); + checkLevel(t, 1); + checkData(expected, t.decodeTurbulenceData().get(0)); + } + + /** + * Turbulence between levels, differing intensities with frequency. + */ + @Test + public void testPirepTurbc_2() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(20000); + expected.setTopHeight(30000); + expected.setIntensity1("MOD"); + expected.setIntensity2("SEV"); + expected.setType(null); + expected.setFrequency("OCN"); + + PirepTools t = new PirepTools("SVR OCNL MOD 200-300"); + checkLevel(t, 1); + checkData(expected, t.decodeTurbulenceData().get(0)); + } + + /** + * Turbulence between levels, differing intensities. + */ + @Test + public void testPirepTurbc_3() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(12000); + expected.setTopHeight(15000); + expected.setIntensity1("LGT"); + expected.setIntensity2("MOD"); + expected.setType(null); + expected.setFrequency(null); + + PirepTools t = new PirepTools("LGT-MDT 120-150"); + checkLevel(t, 1); + checkData(expected, t.decodeTurbulenceData().get(0)); + } + + /** + * Turbulence below a level, single intensity. Embedded carriage control + * should be ignored. + */ + @Test + public void testPirepTurbc_4() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(-9999); + expected.setTopHeight(10000); + expected.setIntensity1("MOD"); + expected.setIntensity2(null); + expected.setType(null); + expected.setFrequency(null); + + PirepTools t = new PirepTools("MDT BLO\n 100"); + checkLevel(t, 1); + checkData(expected, t.decodeTurbulenceData().get(0)); + } + + /** + * Turbulence above a level, differing intensities. Light turbulence (LGT) + * is misspelled. Includes a turbulence type. + */ + @Test + public void testPirepTurbc_5() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(-9999); + expected.setTopHeight(12000); + expected.setIntensity1("LGT"); + expected.setIntensity2("MOD"); + expected.setType("CHOP"); + expected.setFrequency(null); + + PirepTools t = new PirepTools("LIT-MOD CHOP ABOVE 120"); + checkLevel(t, 1); + checkData(expected, t.decodeTurbulenceData().get(0)); + } + + /** + * Turbulence between two levels, show that levels are reordered. Includes a + * turbulence frequency, show that it is corrected. + */ + @Test + public void testPirepTurbc_6() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(8000); + expected.setTopHeight(12000); + expected.setIntensity1("MOD"); + expected.setIntensity2(null); + expected.setType(null); + expected.setFrequency("CON"); + + PirepTools t = new PirepTools("CONTINOUS MOD 120-080"); + checkLevel(t, 1); + List list = t.decodeTurbulenceData(); + checkData(expected, list.get(0)); + } + + /** + * Checks that the PirepTools has decoded data. + * + * @param tools + * The tools object that contains decoded data. + */ + private void checkLevel(PirepTools tools, int elements) { + assertNotNull(tools); + List list = tools.decodeTurbulenceData(); + assertNotNull(list); + assertEquals(elements, list.size()); + } + + /** + * Checks individual data elements. + * + * @param expected + * The expected flight conditions. + * @param actual + * The actual decoded flight conditions. + */ + private void checkData(AircraftFlightCondition expected, + AircraftFlightCondition actual) { + assertEquals(expected.getFrequency(), actual.getFrequency()); + assertEquals(expected.getIntensity1(), actual.getIntensity1()); + assertEquals(expected.getIntensity2(), actual.getIntensity2()); + assertEquals(expected.getType(), actual.getType()); + assertEquals(expected.getBaseHeight(), actual.getBaseHeight()); + assertEquals(expected.getTopHeight(), actual.getTopHeight()); + + } + +} diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestTEIInfo.java b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestTEIInfo.java new file mode 100644 index 0000000000..6431bbfe10 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestTEIInfo.java @@ -0,0 +1,118 @@ +/** + * 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 test.pirep; + +import java.util.List; + +import org.junit.Test; +import static org.junit.Assert.*; + +import com.raytheon.edex.plugin.pirep.decoder.TEI; +import com.raytheon.edex.plugin.pirep.decoder.TEIInfo; + +/** + * Various unit tests for the TEIInfo parser class. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 7, 2012            jkorman     Initial creation
+ * 
+ * 
+ * + * @author jkorman + * @version 1.0 + */ + +public class TestTEIInfo { + + /** + * Test that a legal PIREP is parsed correctly. + */ + @Test + public void testParseNormal() { + final String data = "LYH UA /OV LYH/TM 1226/FL210/TP P180/SK OVC100/WX FV99SM/TA 0/WV 27035KT/TB MDT/IC LGT RIME/RM CB W="; + + List parts = TEIInfo.findTEIs(data); + assertNotNull(parts); + assertEquals(12, parts.size()); + assertEquals(TEI.PIREP, parts.get(0).getTei()); + assertEquals(TEI.OV, parts.get(1).getTei()); + assertEquals(TEI.TM, parts.get(2).getTei()); + assertEquals(TEI.FL, parts.get(3).getTei()); + assertEquals(TEI.TP, parts.get(4).getTei()); + assertEquals(TEI.SK, parts.get(5).getTei()); + assertEquals(TEI.WX, parts.get(6).getTei()); + assertEquals(TEI.TA, parts.get(7).getTei()); + assertEquals(TEI.WV, parts.get(8).getTei()); + assertEquals(TEI.TB, parts.get(9).getTei()); + assertEquals(TEI.IC, parts.get(10).getTei()); + assertEquals(TEI.RM, parts.get(11).getTei()); + } + + /** + * Test that out of order elements are parsed correctly. + */ + @Test + public void testParseBadOrder() { + final String data = "LYH UA /OV LYH/TM 1226/FL210/SK OVC100/TP P180/WX FV99SM/TA 0/WV 27035KT/IC LGT RIME/TB MDT/RM CB W="; + + List parts = TEIInfo.findTEIs(data); + assertNotNull(parts); + assertEquals(12, parts.size()); + assertEquals(TEI.PIREP, parts.get(0).getTei()); + assertEquals(TEI.OV, parts.get(1).getTei()); + assertEquals(TEI.TM, parts.get(2).getTei()); + assertEquals(TEI.FL, parts.get(3).getTei()); + assertEquals(TEI.SK, parts.get(4).getTei()); + assertEquals(TEI.TP, parts.get(5).getTei()); + assertEquals(TEI.WX, parts.get(6).getTei()); + assertEquals(TEI.TA, parts.get(7).getTei()); + assertEquals(TEI.WV, parts.get(8).getTei()); + assertEquals(TEI.IC, parts.get(9).getTei()); + assertEquals(TEI.TB, parts.get(10).getTei()); + assertEquals(TEI.RM, parts.get(11).getTei()); + } + + /** + * Test that "/SKC" does not get confused with the "/SK" TEI. + */ + @Test + public void testSky() { + final String data = "LYH UA /OV LYH/TM 1226/FL210/SK OVC100/SKC/TA 0/WV 27035KT="; + final String skyData = "OVC100/SKC"; + + List parts = TEIInfo.findTEIs(data); + assertNotNull(parts); + assertEquals(7, parts.size()); + assertEquals(TEI.PIREP, parts.get(0).getTei()); + assertEquals(TEI.OV, parts.get(1).getTei()); + assertEquals(TEI.TM, parts.get(2).getTei()); + assertEquals(TEI.FL, parts.get(3).getTei()); + assertEquals(TEI.SK, parts.get(4).getTei()); + assertEquals(skyData, parts.get(4).getTeiText()); + assertEquals(TEI.TA, parts.get(5).getTei()); + assertEquals(TEI.WV, parts.get(6).getTei()); + } + +} diff --git a/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/impl/TextSeparatorFactory.java b/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/impl/TextSeparatorFactory.java index 446d8d820f..59e5854cf2 100644 --- a/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/impl/TextSeparatorFactory.java +++ b/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/impl/TextSeparatorFactory.java @@ -19,7 +19,6 @@ **/ package com.raytheon.edex.plugin.text.impl; -import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.Log; @@ -46,6 +45,10 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * Aug 12, 2008 jkorman Initial creation * Jul 10, 2009 2191 rjpeter Finished implementation. * 06/29/2012 15154 D. Friedman Fix detection of TAF collectives. + * ====================================== + * AWIPS2 DR Work + * 07/25/2012 959 jkorman Modified order of entry for determining + * the data type (standard or collective) for input data. * * * @author jkorman @@ -193,12 +196,15 @@ public class TextSeparatorFactory { String firstLine = WMOMessageSeparator.getLine(rawData, startIndex); int firstLineLen = firstLine.length(); - if (staticData.matchStdCollective(dataDes) != null) { + + // Maintain this order of entry so that Standard Text products + // are checked before collectives. + if ((stdAfosId = staticData.getProductId(ispanId)) != null) { + msgType = WMOMessageType.STD_TEXT; + } else if (staticData.matchStdCollective(dataDes) != null) { msgType = WMOMessageType.STD_COLLECTIVE; } else if (staticData.matchUACollective(dataDes) != null) { msgType = WMOMessageType.UA_COLLECTIVE; - } else if ((stdAfosId = staticData.getProductId(ispanId)) != null) { - msgType = WMOMessageType.STD_TEXT; } // dataDes/ispanId were not mapped, check hard coded diff --git a/edexOsgi/com.raytheon.uf.common.comm/src/com/raytheon/uf/common/comm/HttpClient.java b/edexOsgi/com.raytheon.uf.common.comm/src/com/raytheon/uf/common/comm/HttpClient.java index 05659ebf85..b169049c79 100644 --- a/edexOsgi/com.raytheon.uf.common.comm/src/com/raytheon/uf/common/comm/HttpClient.java +++ b/edexOsgi/com.raytheon.uf.common.comm/src/com/raytheon/uf/common/comm/HttpClient.java @@ -1,653 +1,654 @@ -/** - * 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.comm; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.zip.GZIPOutputStream; - -import org.apache.http.Header; -import org.apache.http.HeaderElement; -import org.apache.http.HttpEntity; -import org.apache.http.HttpException; -import org.apache.http.HttpRequest; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.HttpResponse; -import org.apache.http.HttpResponseInterceptor; -import org.apache.http.client.entity.GzipDecompressingEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.conn.ConnectionPoolTimeoutException; -import org.apache.http.entity.AbstractHttpEntity; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.AbstractHttpClient; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; -import org.apache.http.params.HttpConnectionParams; -import org.apache.http.protocol.HttpContext; -import org.apache.http.util.EntityUtils; - -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.util.ByteArrayOutputStreamPool; -import com.raytheon.uf.common.util.ByteArrayOutputStreamPool.ByteArrayOutputStream; - -/** - * - * Provides connectivity to the ESB server - * - *
- * 
- *    SOFTWARE HISTORY
- *   
- *    Date          Ticket#     Engineer    Description
- *    ------------  ----------  ----------- --------------------------
- *    7/1/06        #1088       chammack    Initial Creation.
- *    5/17/10      #5901       njensen        Moved to common
- *    03/02/11      #8045       rferrel     Add connect reestablished message.
- *    07/17/12    #911         njensen    Refactored significantly
- * 
- * 
- * - * @author chammack - * @version 1 - */ -public class HttpClient { - - public static class HttpClientResponse { - public final int code; - - public final byte[] data; - - private HttpClientResponse(int code, byte[] data) { - this.code = code; - this.data = data != null ? data : new byte[0]; - } - } - - private static final int SUCCESS_CODE = 200; - - private final org.apache.http.client.HttpClient client; - - private boolean previousConnectionFailed; - - private static HttpClient instance; - - /** - * Number of times to retry in the event of a connection exception. Default - * is 1. - */ - private int retryCount = 1; - - private static final IUFStatusHandler statusHandler = UFStatus.getHandler( - HttpClient.class, "DEFAULT"); - - private ThreadSafeClientConnManager connManager = null; - - private NetworkStatistics stats = new NetworkStatistics(); - - private boolean gzipRequests = false; - - /** number of requests currently in process by the application per host */ - private Map currentRequestsCount = new ConcurrentHashMap(); - - private HttpClient() { - connManager = new ThreadSafeClientConnManager(); - DefaultHttpClient client = new DefaultHttpClient(connManager); - client.addRequestInterceptor(new HttpRequestInterceptor() { - - public void process(final HttpRequest request, - final HttpContext context) throws HttpException, - IOException { - try { - stats.log( - Long.valueOf(request.getFirstHeader( - "Content-Length").getValue()), 0); - } catch (Throwable t) { - // Ignore any errors when logging - } - } - - }); - - client.addResponseInterceptor(new HttpResponseInterceptor() { - public void process(final HttpResponse response, - final HttpContext context) throws HttpException, - IOException { - try { - stats.log(0, response.getEntity().getContentLength()); - } catch (Throwable t) { - // Ignore any errors when logging - } - } - }); - this.client = client; - previousConnectionFailed = false; - } - - /** - * Enables gzip capabilities by advertising gzip is an accepted response - * encoding and decompressing responses if they arrived gzipped. This should - * only ever be called once per runtime. - */ - public void enableGzipResponseHandling() { - // Add gzip compression handlers - - // advertise we accept gzip - ((AbstractHttpClient) client) - .addRequestInterceptor(new HttpRequestInterceptor() { - - public void process(final HttpRequest request, - final HttpContext context) throws HttpException, - IOException { - if (!request.containsHeader("Accept-Encoding")) { - request.addHeader("Accept-Encoding", "gzip"); - } - } - - }); - - // handle gzip contents - ((AbstractHttpClient) client) - .addResponseInterceptor(new HttpResponseInterceptor() { - - public void process(final HttpResponse response, - final HttpContext context) throws HttpException, - IOException { - HttpEntity entity = response.getEntity(); - Header ceheader = entity.getContentEncoding(); - if (ceheader != null) { - HeaderElement[] codecs = ceheader.getElements(); - for (int i = 0; i < codecs.length; i++) { - if (codecs[i].getName() - .equalsIgnoreCase("gzip")) { - response.setEntity(new GzipDecompressingEntity( - response.getEntity())); - return; - } - } - } - } - - }); - } - - public void enableRequestCompression() { - gzipRequests = true; - } - - public static synchronized HttpClient getInstance() { - if (instance == null) { - instance = new HttpClient(); - } - - return instance; - } - - /** - * Post a message to an http address, and return the result as a string. - * - * - * @param address - * @param message - * @return - * @throws Exception - */ - public String post(String address, String message) throws Exception { - - String returnValue = new String(postByteResult(address, message)); - - return returnValue; - - } - - /** - * Post a message to an http address, and return the result as a byte array. - * - * - * @param address - * @param message - * @return - * @throws Exception - */ - public byte[] postByteResult(String address, String message) - throws Exception { - HttpPost put = new HttpPost(address); - put.setEntity(new StringEntity(message, "text/xml", "ISO-8859-1")); - - return executePostMethod(put); - } - - /** - * Sends the request to the server, checks the status code (in case of 404, - * 403, etc), and returns the response if there was no error code. - * - * @param put - * the request to send - * @return the response from the server - * @throws IOException - * @throws CommunicationException - */ - private HttpResponse postRequest(HttpUriRequest put) throws IOException, - CommunicationException { - HttpResponse resp = client.execute(put); - if (previousConnectionFailed) { - previousConnectionFailed = false; - statusHandler.handle(Priority.INFO, - "Connection with server reestablished."); - } - return resp; - } - - /** - * Posts the request to the server and passes the response stream to the - * handler callback. Will also retry the request if it fails due to a - * timeout or IO problem. - * - * @param put - * the request to post - * @param handlerCallback - * the handler to handle the response stream - * @return the http status code - * @throws CommunicationException - */ - private HttpClientResponse process(HttpUriRequest put, - IStreamHandler handlerCallback) throws CommunicationException { - int tries = 0; - boolean retry = true; - HttpResponse resp = null; - AtomicInteger ongoing = null; - - try { - String host = put.getURI().getHost(); - ongoing = currentRequestsCount.get(host); - if (ongoing == null) { - ongoing = new AtomicInteger(); - currentRequestsCount.put(host, ongoing); - } - int currentCount = ongoing.incrementAndGet(); - if (currentCount > getMaxConnectionsPerHost()) { - statusHandler.debug(currentCount + " ongoing http requests to " - + host - + ". Likely waiting for free connection from pool."); - } - while (retry) { - retry = false; - tries++; - - String errorMsg = null; - Exception exc = null; - try { - resp = postRequest(put); - } catch (ConnectionPoolTimeoutException e) { - errorMsg = "Timed out waiting for http connection from pool: " - + e.getMessage(); - errorMsg += ". Currently " + ongoing.get() - + " requests ongoing"; - exc = e; - } catch (IOException e) { - errorMsg = "Error occurred communicating with server: " - + e.getMessage(); - exc = e; - } - - if (errorMsg != null && exc != null) { - if (tries > retryCount) { - previousConnectionFailed = true; - // close/abort connection - if (put != null) { - put.abort(); - } - errorMsg += ". Hit retry limit, aborting connection."; - throw new CommunicationException(errorMsg, exc); - } else { - errorMsg += ". Retrying..."; - statusHandler.handle(Priority.INFO, errorMsg); - retry = true; - } - } - } - - // should only be able to get here if we didn't encounter the - // exceptions above on the most recent try - processResponse(resp, handlerCallback); - byte[] byteResult = null; - if (handlerCallback instanceof DefaultInternalStreamHandler) { - byteResult = ((DefaultInternalStreamHandler) handlerCallback).byteResult; - } - return new HttpClientResponse(resp.getStatusLine().getStatusCode(), - byteResult); - } finally { - if (ongoing != null) { - ongoing.decrementAndGet(); - } - } - } - - /** - * Streams the response content to the handler callback and closes the http - * connection once finished. - * - * @param resp - * the http response to stream - * @param handlerCallback - * the handler that should process the response stream - * @throws CommunicationException - */ - private void processResponse(HttpResponse resp, - IStreamHandler handlerCallback) throws CommunicationException { - InputStream is = null; - if (resp != null && resp.getEntity() != null) { - try { - is = resp.getEntity().getContent(); - handlerCallback.handleStream(is); - } catch (IOException e) { - throw new CommunicationException( - "IO error processing http response", e); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // ignore - } - } - - // Closes the stream if it's still open - try { - EntityUtils.consume(resp.getEntity()); - } catch (IOException e) { - // if there was an error reading the input stream, - // notify but continue - statusHandler.handle(Priority.EVENTB, - "Error reading InputStream, assuming closed", e); - } - } - } - } - - /** - * Posts the request and uses a DefaultInternalStreamHandler to - * automatically stream the response into a byte[]. - * - * @param put - * the post to send to the server - * @return the byte[] of the response - * @throws CommunicationException - */ - private byte[] executePostMethod(HttpPost put) - throws CommunicationException { - DefaultInternalStreamHandler handlerCallback = new DefaultInternalStreamHandler(); - HttpClientResponse resp = this.process(put, handlerCallback); - checkStatusCode(resp); - return resp.data; - } - - /** - * Post a message to an http address, and return the result as a byte array. - * - * - * @param address - * @param message - * @return - * @throws Exception - */ - public byte[] postBinary(String address, byte[] message) - throws CommunicationException, Exception { - - HttpPost put = new HttpPost(address); - if (gzipRequests) { - ByteArrayOutputStream byteStream = ByteArrayOutputStreamPool - .getInstance().getStream(message.length); - GZIPOutputStream gzipStream = new GZIPOutputStream(byteStream); - gzipStream.write(message); - gzipStream.finish(); - gzipStream.flush(); - byte[] gzipMessage = byteStream.toByteArray(); - gzipStream.close(); - if (message.length > gzipMessage.length) { - message = gzipMessage; - put.setHeader("Content-Encoding", "gzip"); - } - } - - put.setEntity(new ByteArrayEntity(message)); - - return executePostMethod(put); - } - - /** - * Post a string to an endpoint and stream the result back. - * - * The result should be handled inside of the handlerCallback - * - * @param address - * the http address - * @param message - * the message to send - * @param handlerCallback - * the handler callback - * @throws CommunicationException - * if an error occurred during transmission - */ - public void postStreamingByteArray(String address, byte[] message, - IStreamHandler handlerCallback) throws CommunicationException { - postStreamingEntity(address, new ByteArrayEntity(message), - handlerCallback); - } - - /** - * Executes an HttpUriRequest and returns a response with the byte[] and - * http status code. - * - * @param request - * the request to execute - * @return the result and status code - * @throws CommunicationException - */ - public HttpClientResponse executeRequest(HttpUriRequest request) - throws CommunicationException { - DefaultInternalStreamHandler streamHandler = new DefaultInternalStreamHandler(); - return process(request, streamHandler); - } - - /** - * Post a string to an endpoint and stream the result back. - * - * The result should be handled inside of the handlerCallback - * - * @param address - * the http address - * @param message - * the message to send - * @param handlerCallback - * the handler callback - * @throws UnsupportedEncodingException - * @throws CommunicationException - */ - @Deprecated - public void postStreamingString(String address, String message, - IStreamHandler handlerCallback) throws CommunicationException, - UnsupportedEncodingException { - postStreamingEntity(address, new StringEntity(message), handlerCallback); - } - - private void checkStatusCode(HttpClientResponse response) - throws CommunicationException { - if (response.code != SUCCESS_CODE) { - throw new CommunicationException( - "Error reading server response. Got error message: " - + response.data != null ? new String(response.data) - : null); - } - } - - /** - * Posts an entity to the address and stream the result back. - * - * @param address - * the http address to post to - * @param entity - * an entity containing the message to send - * @param handlerCallback - * the handler callback - * @throws CommunicationException - */ - private void postStreamingEntity(String address, AbstractHttpEntity entity, - IStreamHandler handlerCallback) throws CommunicationException { - HttpPost put = new HttpPost(address); - put.setEntity(entity); - HttpClientResponse resp = process(put, handlerCallback); - checkStatusCode(resp); - } - - public void setMaxConnectionsPerHost(int maxConnections) { - connManager.setDefaultMaxPerRoute(maxConnections); - } - - public int getMaxConnectionsPerHost() { - return connManager.getDefaultMaxPerRoute(); - } - - public void setSocketTimeout(int socketTimeout) { - HttpConnectionParams.setSoTimeout(client.getParams(), socketTimeout); - // client.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, - // socketTimeout); - } - - public void setConnectionTimeout(int connectionTimeout) { - HttpConnectionParams.setConnectionTimeout(client.getParams(), - connectionTimeout); - } - - /** - * Number of times to retry in the event of a socket exception. Default is - * 1. - */ - public int getRetryCount() { - return retryCount; - } - - /** - * Number of times to retry in the event of a socket exception. Default is - * 1. - * - * @param retryCount - */ - public void setRetryCount(int retryCount) { - this.retryCount = retryCount; - } - - /** - * Gets the network statistics for http traffic. - * - * @return - */ - public NetworkStatistics getStats() { - return stats; - } - - /** - * Provides a safe interface callback for implementing stream behavior with - * http - * - * The lifetime of the stream is only guaranteed inside the scope of the - * handleScope method. A user should not close the stream, it will be closed - * for them after the method completes. - * - * @author chammack - * @version 1.0 - */ - public static interface IStreamHandler { - - /** - * Implementation method for stream callbacks - * - * A user should NOT close the stream, it will be done for them after - * the method terminates. A user should NOT store off copies of the - * input stream for later use. - * - * @param is - * @throws VizException - */ - public abstract void handleStream(InputStream is) - throws CommunicationException; - } - - /** - * Automatically reads a stream into a byte array and stores the byte array - * in byteResult. Should only be used internally in HttpClient with - * convenience methods that do not take an IStreamHandler as an argument. - * - */ - private static class DefaultInternalStreamHandler implements IStreamHandler { - - private byte[] byteResult; - - @Override - public void handleStream(InputStream is) throws CommunicationException { - ByteArrayOutputStream baos = ByteArrayOutputStreamPool - .getInstance().getStream(); - try { - byte[] underlyingArray = baos.getUnderlyingArray(); - int read = 0; - int index = 0; - do { - try { - read = is.read(underlyingArray, index, - underlyingArray.length - index); - } catch (IOException e) { - throw new CommunicationException( - "Error reading byte response", e); - } - - if (read > 0) { - index += read; - if (index == underlyingArray.length) { - baos.setCapacity(underlyingArray.length << 1); - underlyingArray = baos.getUnderlyingArray(); - } - } - } while (read > 0); - - baos.setCount(index); - byteResult = new byte[index]; - System.arraycopy(underlyingArray, 0, byteResult, 0, index); - } finally { - if (baos != null) { - try { - baos.close(); - } catch (IOException e) { - // ignore - } - } - } - } - - } - -} +/** + * 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.comm; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.zip.GZIPOutputStream; + +import org.apache.http.Header; +import org.apache.http.HeaderElement; +import org.apache.http.HttpEntity; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpRequestInterceptor; +import org.apache.http.HttpResponse; +import org.apache.http.HttpResponseInterceptor; +import org.apache.http.client.entity.GzipDecompressingEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.conn.ConnectionPoolTimeoutException; +import org.apache.http.entity.AbstractHttpEntity; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.AbstractHttpClient; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; +import org.apache.http.params.HttpConnectionParams; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; + +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.util.ByteArrayOutputStreamPool; +import com.raytheon.uf.common.util.ByteArrayOutputStreamPool.ByteArrayOutputStream; + +/** + * + * Provides connectivity to the ESB server + * + *
+ * 
+ *    SOFTWARE HISTORY
+ *   
+ *    Date          Ticket#     Engineer    Description
+ *    ------------  ----------  ----------- --------------------------
+ *    7/1/06        #1088       chammack    Initial Creation.
+ *    5/17/10      #5901       njensen        Moved to common
+ *    03/02/11      #8045       rferrel     Add connect reestablished message.
+ *    07/17/12    #911         njensen    Refactored significantly
+ *    08/09/12     15307        snaples   Added putEntitiy in postStreamingEntity.
+ * 
+ * 
+ * + * @author chammack + * @version 1 + */ +public class HttpClient { + + public static class HttpClientResponse { + public final int code; + + public final byte[] data; + + private HttpClientResponse(int code, byte[] data) { + this.code = code; + this.data = data != null ? data : new byte[0]; + } + } + + private static final int SUCCESS_CODE = 200; + + private final org.apache.http.client.HttpClient client; + + private boolean previousConnectionFailed; + + private static HttpClient instance; + + /** + * Number of times to retry in the event of a connection exception. Default + * is 1. + */ + private int retryCount = 1; + + private static final IUFStatusHandler statusHandler = UFStatus.getHandler( + HttpClient.class, "DEFAULT"); + + private ThreadSafeClientConnManager connManager = null; + + private NetworkStatistics stats = new NetworkStatistics(); + + private boolean gzipRequests = false; + + /** number of requests currently in process by the application per host */ + private Map currentRequestsCount = new ConcurrentHashMap(); + + private HttpClient() { + connManager = new ThreadSafeClientConnManager(); + DefaultHttpClient client = new DefaultHttpClient(connManager); + client.addRequestInterceptor(new HttpRequestInterceptor() { + + public void process(final HttpRequest request, + final HttpContext context) throws HttpException, + IOException { + try { + stats.log( + Long.valueOf(request.getFirstHeader( + "Content-Length").getValue()), 0); + } catch (Throwable t) { + // Ignore any errors when logging + } + } + + }); + + client.addResponseInterceptor(new HttpResponseInterceptor() { + public void process(final HttpResponse response, + final HttpContext context) throws HttpException, + IOException { + try { + stats.log(0, response.getEntity().getContentLength()); + } catch (Throwable t) { + // Ignore any errors when logging + } + } + }); + this.client = client; + previousConnectionFailed = false; + } + + /** + * Enables gzip capabilities by advertising gzip is an accepted response + * encoding and decompressing responses if they arrived gzipped. This should + * only ever be called once per runtime. + */ + public void enableGzipResponseHandling() { + // Add gzip compression handlers + + // advertise we accept gzip + ((AbstractHttpClient) client) + .addRequestInterceptor(new HttpRequestInterceptor() { + + public void process(final HttpRequest request, + final HttpContext context) throws HttpException, + IOException { + if (!request.containsHeader("Accept-Encoding")) { + request.addHeader("Accept-Encoding", "gzip"); + } + } + + }); + + // handle gzip contents + ((AbstractHttpClient) client) + .addResponseInterceptor(new HttpResponseInterceptor() { + + public void process(final HttpResponse response, + final HttpContext context) throws HttpException, + IOException { + HttpEntity entity = response.getEntity(); + Header ceheader = entity.getContentEncoding(); + if (ceheader != null) { + HeaderElement[] codecs = ceheader.getElements(); + for (int i = 0; i < codecs.length; i++) { + if (codecs[i].getName() + .equalsIgnoreCase("gzip")) { + response.setEntity(new GzipDecompressingEntity( + response.getEntity())); + return; + } + } + } + } + + }); + } + + public void enableRequestCompression() { + gzipRequests = true; + } + + public static synchronized HttpClient getInstance() { + if (instance == null) { + instance = new HttpClient(); + } + + return instance; + } + + /** + * Post a message to an http address, and return the result as a string. + * + * + * @param address + * @param message + * @return + * @throws Exception + */ + public String post(String address, String message) throws Exception { + + String returnValue = new String(postByteResult(address, message)); + + return returnValue; + + } + + /** + * Post a message to an http address, and return the result as a byte array. + * + * + * @param address + * @param message + * @return + * @throws Exception + */ + public byte[] postByteResult(String address, String message) + throws Exception { + HttpPost put = new HttpPost(address); + put.setEntity(new StringEntity(message, "text/xml", "ISO-8859-1")); + + return executePostMethod(put); + } + + /** + * Sends the request to the server, checks the status code (in case of 404, + * 403, etc), and returns the response if there was no error code. + * + * @param put + * the request to send + * @return the response from the server + * @throws IOException + * @throws CommunicationException + */ + private HttpResponse postRequest(HttpUriRequest put) throws IOException, + CommunicationException { + HttpResponse resp = client.execute(put); + if (previousConnectionFailed) { + previousConnectionFailed = false; + statusHandler.handle(Priority.INFO, + "Connection with server reestablished."); + } + return resp; + } + + /** + * Posts the request to the server and passes the response stream to the + * handler callback. Will also retry the request if it fails due to a + * timeout or IO problem. + * + * @param put + * the request to post + * @param handlerCallback + * the handler to handle the response stream + * @return the http status code + * @throws CommunicationException + */ + private HttpClientResponse process(HttpUriRequest put, + IStreamHandler handlerCallback) throws CommunicationException { + int tries = 0; + boolean retry = true; + HttpResponse resp = null; + AtomicInteger ongoing = null; + + try { + String host = put.getURI().getHost(); + ongoing = currentRequestsCount.get(host); + if (ongoing == null) { + ongoing = new AtomicInteger(); + currentRequestsCount.put(host, ongoing); + } + int currentCount = ongoing.incrementAndGet(); + if (currentCount > getMaxConnectionsPerHost()) { + String msg = currentCount + " ongoing http requests to " + host + + ". Likely waiting for free connection from pool."; + statusHandler.debug(msg); + } + while (retry) { + retry = false; + tries++; + + String errorMsg = null; + Exception exc = null; + try { + resp = postRequest(put); + } catch (ConnectionPoolTimeoutException e) { + errorMsg = "Timed out waiting for http connection from pool: " + + e.getMessage(); + errorMsg += ". Currently " + ongoing.get() + + " requests ongoing"; + exc = e; + } catch (IOException e) { + errorMsg = "Error occurred communicating with server: " + + e.getMessage(); + exc = e; + } + + if (errorMsg != null && exc != null) { + if (tries > retryCount) { + previousConnectionFailed = true; + // close/abort connection + if (put != null) { + put.abort(); + } + errorMsg += ". Hit retry limit, aborting connection."; + throw new CommunicationException(errorMsg, exc); + } else { + errorMsg += ". Retrying..."; + statusHandler.handle(Priority.INFO, errorMsg); + retry = true; + } + } + } + + // should only be able to get here if we didn't encounter the + // exceptions above on the most recent try + processResponse(resp, handlerCallback); + byte[] byteResult = null; + if (handlerCallback instanceof DefaultInternalStreamHandler) { + byteResult = ((DefaultInternalStreamHandler) handlerCallback).byteResult; + } + return new HttpClientResponse(resp.getStatusLine().getStatusCode(), + byteResult); + } finally { + if (ongoing != null) { + ongoing.decrementAndGet(); + } + } + } + + /** + * Streams the response content to the handler callback and closes the http + * connection once finished. + * + * @param resp + * the http response to stream + * @param handlerCallback + * the handler that should process the response stream + * @throws CommunicationException + */ + private void processResponse(HttpResponse resp, + IStreamHandler handlerCallback) throws CommunicationException { + InputStream is = null; + if (resp != null && resp.getEntity() != null) { + try { + is = resp.getEntity().getContent(); + handlerCallback.handleStream(is); + } catch (IOException e) { + throw new CommunicationException( + "IO error processing http response", e); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + + // Closes the stream if it's still open + try { + EntityUtils.consume(resp.getEntity()); + } catch (IOException e) { + // if there was an error reading the input stream, + // notify but continue + statusHandler.handle(Priority.EVENTB, + "Error reading InputStream, assuming closed", e); + } + } + } + } + + /** + * Posts the request and uses a DefaultInternalStreamHandler to + * automatically stream the response into a byte[]. + * + * @param put + * the post to send to the server + * @return the byte[] of the response + * @throws CommunicationException + */ + private byte[] executePostMethod(HttpPost put) + throws CommunicationException { + DefaultInternalStreamHandler handlerCallback = new DefaultInternalStreamHandler(); + HttpClientResponse resp = this.process(put, handlerCallback); + checkStatusCode(resp); + return resp.data; + } + + /** + * Post a message to an http address, and return the result as a byte array. + * + * + * @param address + * @param message + * @return + * @throws Exception + */ + public byte[] postBinary(String address, byte[] message) + throws CommunicationException, Exception { + + HttpPost put = new HttpPost(address); + if (gzipRequests) { + ByteArrayOutputStream byteStream = ByteArrayOutputStreamPool + .getInstance().getStream(message.length); + GZIPOutputStream gzipStream = new GZIPOutputStream(byteStream); + gzipStream.write(message); + gzipStream.finish(); + gzipStream.flush(); + byte[] gzipMessage = byteStream.toByteArray(); + gzipStream.close(); + if (message.length > gzipMessage.length) { + message = gzipMessage; + put.setHeader("Content-Encoding", "gzip"); + } + } + + put.setEntity(new ByteArrayEntity(message)); + + return executePostMethod(put); + } + + /** + * Post a string to an endpoint and stream the result back. + * + * The result should be handled inside of the handlerCallback + * + * @param address + * the http address + * @param message + * the message to send + * @param handlerCallback + * the handler callback + * @throws CommunicationException + * if an error occurred during transmission + */ + public void postStreamingByteArray(String address, byte[] message, + IStreamHandler handlerCallback) throws CommunicationException { + postStreamingEntity(address, new ByteArrayEntity(message), + handlerCallback); + } + + /** + * Executes an HttpUriRequest and returns a response with the byte[] and + * http status code. + * + * @param request + * the request to execute + * @return the result and status code + * @throws CommunicationException + */ + public HttpClientResponse executeRequest(HttpUriRequest request) + throws CommunicationException { + DefaultInternalStreamHandler streamHandler = new DefaultInternalStreamHandler(); + return process(request, streamHandler); + } + + /** + * Post a string to an endpoint and stream the result back. + * + * The result should be handled inside of the handlerCallback + * + * @param address + * the http address + * @param message + * the message to send + * @param handlerCallback + * the handler callback + * @throws UnsupportedEncodingException + * @throws CommunicationException + */ + @Deprecated + public void postStreamingString(String address, String message, + IStreamHandler handlerCallback) throws CommunicationException, + UnsupportedEncodingException { + postStreamingEntity(address, new StringEntity(message), handlerCallback); + } + + private void checkStatusCode(HttpClientResponse response) + throws CommunicationException { + if (response.code != SUCCESS_CODE) { + throw new CommunicationException( + "Error reading server response. Got error message: " + + response.data != null ? new String(response.data) + : null); + } + } + + /** + * Posts an entity to the address and stream the result back. + * + * @param address + * the http address to post to + * @param entity + * an entity containing the message to send + * @param handlerCallback + * the handler callback + * @throws CommunicationException + */ + private void postStreamingEntity(String address, AbstractHttpEntity entity, + IStreamHandler handlerCallback) throws CommunicationException { + HttpPost put = new HttpPost(address); + put.setEntity(entity); + HttpClientResponse resp = process(put, handlerCallback); + checkStatusCode(resp); + } + + public void setMaxConnectionsPerHost(int maxConnections) { + connManager.setDefaultMaxPerRoute(maxConnections); + } + + public int getMaxConnectionsPerHost() { + return connManager.getDefaultMaxPerRoute(); + } + + public void setSocketTimeout(int socketTimeout) { + HttpConnectionParams.setSoTimeout(client.getParams(), socketTimeout); + // client.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, + // socketTimeout); + } + + public void setConnectionTimeout(int connectionTimeout) { + HttpConnectionParams.setConnectionTimeout(client.getParams(), + connectionTimeout); + } + + /** + * Number of times to retry in the event of a socket exception. Default is + * 1. + */ + public int getRetryCount() { + return retryCount; + } + + /** + * Number of times to retry in the event of a socket exception. Default is + * 1. + * + * @param retryCount + */ + public void setRetryCount(int retryCount) { + this.retryCount = retryCount; + } + + /** + * Gets the network statistics for http traffic. + * + * @return + */ + public NetworkStatistics getStats() { + return stats; + } + + /** + * Provides a safe interface callback for implementing stream behavior with + * http + * + * The lifetime of the stream is only guaranteed inside the scope of the + * handleScope method. A user should not close the stream, it will be closed + * for them after the method completes. + * + * @author chammack + * @version 1.0 + */ + public static interface IStreamHandler { + + /** + * Implementation method for stream callbacks + * + * A user should NOT close the stream, it will be done for them after + * the method terminates. A user should NOT store off copies of the + * input stream for later use. + * + * @param is + * @throws VizException + */ + public abstract void handleStream(InputStream is) + throws CommunicationException; + } + + /** + * Automatically reads a stream into a byte array and stores the byte array + * in byteResult. Should only be used internally in HttpClient with + * convenience methods that do not take an IStreamHandler as an argument. + * + */ + private static class DefaultInternalStreamHandler implements IStreamHandler { + + private byte[] byteResult; + + @Override + public void handleStream(InputStream is) throws CommunicationException { + ByteArrayOutputStream baos = ByteArrayOutputStreamPool + .getInstance().getStream(); + try { + byte[] underlyingArray = baos.getUnderlyingArray(); + int read = 0; + int index = 0; + do { + try { + read = is.read(underlyingArray, index, + underlyingArray.length - index); + } catch (IOException e) { + throw new CommunicationException( + "Error reading byte response", e); + } + + if (read > 0) { + index += read; + if (index == underlyingArray.length) { + baos.setCapacity(underlyingArray.length << 1); + underlyingArray = baos.getUnderlyingArray(); + } + } + } while (read > 0); + + baos.setCount(index); + byteResult = new byte[index]; + System.arraycopy(underlyingArray, 0, byteResult, 0, index); + } finally { + if (baos != null) { + try { + baos.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java index 41cc02bc04..51fdd5e2cf 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java @@ -31,7 +31,6 @@ import com.raytheon.uf.common.monitor.xml.SourceXML; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; - /** * FFTI Data Container * @@ -42,6 +41,7 @@ import com.raytheon.uf.common.status.UFStatus; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 03/31/11 5489 D. Hladky Initial release + * 07/31/12 578 D.Hladky finished it * * * @@ -50,14 +50,14 @@ import com.raytheon.uf.common.status.UFStatus; */ public class FFMPDataContainer { - - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(FFMPDataContainer.class); + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(FFMPDataContainer.class); private HashMap basinDataMap = new HashMap(); private String sourceName = null; - + private String filePath = null; public FFMPDataContainer() { @@ -88,11 +88,11 @@ public class FFMPDataContainer { * @return */ public FFMPBasinData getBasinData(String huc) { - if (basinDataMap.containsKey(huc)) { - return basinDataMap.get(huc); - } else { - return null; - } + if (basinDataMap.containsKey(huc)) { + return basinDataMap.get(huc); + } else { + return null; + } } /** @@ -142,160 +142,150 @@ public class FFMPDataContainer { if (source.getSourceType().equals(SOURCE_TYPE.GUIDANCE.getSourceType())) { guid = true; } - - FFMPBasinData currBasinData = getBasinData(huc); - if (currBasinData == null) { - setBasinData(huc, newBasinData); - } else { + FFMPBasinData currBasinData = getBasinData(huc); - for (Long key : newBasinData.getBasins().keySet()) { + if (currBasinData == null) { + setBasinData(huc, newBasinData); + } else { - if (guid) { + for (Long key : newBasinData.getBasins().keySet()) { - FFMPGuidanceBasin basin = null; + if (guid) { - if (currBasinData.get(key) instanceof FFMPGuidanceBasin) { - basin = (FFMPGuidanceBasin) currBasinData.get(key); - } + FFMPGuidanceBasin basin = null; - if (basin == null) { + if (currBasinData.get(key) instanceof FFMPGuidanceBasin) { + basin = (FFMPGuidanceBasin) currBasinData.get(key); + } - FFMPBasin newbasin = newBasinData.get(key); - basin = new FFMPGuidanceBasin(key, - newbasin.getAggregated()); + if (basin == null) { - if (newbasin instanceof FFMPGuidanceBasin) { + FFMPBasin newbasin = newBasinData.get(key); + basin = new FFMPGuidanceBasin(key, + newbasin.getAggregated()); - basin.setValue( - source.getSourceName(), - date, - ((FFMPGuidanceBasin) newbasin).getValue( - source.getSourceName(), - source.getExpirationMinutes(siteKey) * 60 * 1000)); - } else { - basin.setValue(source.getSourceName(), date, - newBasinData.get(key).getValue()); - } + if (newbasin instanceof FFMPGuidanceBasin) { - currBasinData.put(key, basin); + Float val = ((FFMPGuidanceBasin) newbasin).getValue(date, source.getSourceName()); + basin.setValue(source.getSourceName(), date, val); + } else { + Float val = newbasin.getValue(date); + basin.setValue(source.getSourceName(), date, val); + } - } else { + currBasinData.put(key, basin); - FFMPBasin newbasin = newBasinData.get(key); + } else { - if (newbasin instanceof FFMPGuidanceBasin) { + FFMPBasin newbasin = newBasinData.get(key); - if (basin.getValue(date, source.getSourceName()) != null - && (basin.getValue(date, - source.getSourceName()) >= 0.0f && !basin - .getValue(date, - source.getSourceName()) - .isNaN())) { + if (newbasin instanceof FFMPGuidanceBasin) { + + FFMPGuidanceBasin newGbasin = (FFMPGuidanceBasin)newBasinData.get(key); + Float basinVal = basin.getValue(date, source.getSourceName()); + Float newBasinVal = newGbasin.getValue(date, source.getSourceName()); - if (((FFMPGuidanceBasin) newbasin).getValue( - date, source.getSourceName()) >= 0.0f - && !((FFMPGuidanceBasin) newbasin) - .getValue(date, - source.getSourceName()) - .isNaN()) { + if (basinVal != null + && basinVal >= 0.0f + && !basinVal.isNaN() + && basinVal != FFMPUtils.MISSING) { - float val = (float) (basin.getValue(date, - source.getSourceName()) + ((FFMPGuidanceBasin) newbasin) - .getValue( - source.getSourceName(), - source.getExpirationMinutes(siteKey) * 60 * 1000) / 2.0); + if (newBasinVal != null + && newBasinVal >= 0.0f + && !newBasinVal.isNaN() + && newBasinVal != FFMPUtils.MISSING) { - basin.setValue(source.getSourceName(), - date, val); - } + float val = (float) ((basinVal + newBasinVal) / 2.0); + basin.setValue(source.getSourceName(), + date, val); + } + } else { + + if (newBasinVal.isNaN()) { + newBasinVal = FFMPUtils.MISSING; + } + + basin.setValue(source.getSourceName(), + date, newBasinVal); + } - } else { + } else { - if (!basin.containsKey(date, - source.getSourceName()) - && newbasin != null) { - basin.setValue(source.getSourceName(), - date, - ((FFMPGuidanceBasin) newbasin) - .getValue(date, source - .getSourceName())); - } - } + Float basinVal = basin.getValue(date, source.getSourceName()); + Float newBasinVal = newbasin.getValue(); + + if (basinVal != null + && basinVal >= 0.0f + && !basinVal.isNaN() + && basinVal != FFMPUtils.MISSING) { + + if (newBasinVal != null + && newBasinVal >= 0.0f + && !newBasinVal.isNaN() + && newBasinVal != FFMPUtils.MISSING) { - } else { - // meaning, it's a brand new file, we don't cast - // those out + float val = (float) ((basinVal + newBasinVal) / 2.0); + basin.setValue(source.getSourceName(), + date, val); + } + } else { + + if (newBasinVal.isNaN()) { + newBasinVal = FFMPUtils.MISSING; + } + + basin.setValue(source.getSourceName(), + date, newBasinVal); + } + } + } + + } else { - if (newbasin.getValue(date) != null - && newbasin.getValue(date) >= 0.0f - && !newbasin.getValue(date).isNaN() - && ((FFMPGuidanceBasin) basin).getValue( - date, source.getSourceName()) >= 0.0f - && !((FFMPGuidanceBasin) basin).getValue( - date, source.getSourceName()) - .isNaN()) { + FFMPBasin basin = currBasinData.get(key); + FFMPBasin newbasin = newBasinData.get(key); + Float val = 0.0f; - float val = (float) ((basin.getValue(date, - source.getSourceName()) + newbasin - .getValue()) / 2); + if (basin == null) { - basin.setValue(source.getSourceName(), date, - val); + basin = new FFMPBasin(key, newbasin.getAggregated()); + val = newbasin.getValue(date); - } else { + if (val.isNaN()) { + val = 0.0f; + } - basin.setValue(source.getSourceName(), date, - newbasin.getValue(date)); - } - } - } + basin.setValue(date, val); + currBasinData.put(key, basin); - } else { + } else { - FFMPBasin basin = currBasinData.get(key); - FFMPBasin newbasin = newBasinData.get(key); - Float val = 0.0f; + if (basin.getValue(date) != null + && !basin.getValue(date).isNaN() + && basin.getValue(date) != 0.0) { + if (newbasin.getValue(date) != null + && !newbasin.getValue(date).isNaN() + && newbasin.getValue(date) != 0.0) { - if (basin == null) { + val = (float) ((basin.getValue(date) + newbasin + .getValue(date)) / 2); + } - basin = new FFMPBasin(key, newbasin.getAggregated()); - val = newbasin.getValue(date); + } else { + val = newbasin.getValue(date); - if (val.isNaN()) { - val = 0.0f; - } + if (val.isNaN()) { + val = 0.0f; + } + } - basin.setValue(date, val); - currBasinData.put(key, basin); - - } else { - - if (basin.getValue(date) != null - && !basin.getValue(date).isNaN() - && basin.getValue(date) != 0.0) { - if (newbasin.getValue(date) != null - && !newbasin.getValue(date).isNaN() - && newbasin.getValue(date) != 0.0) { - - val = (float) ((basin.getValue(date) + newbasin - .getValue(date)) / 2); - } - - } else { - val = newbasin.getValue(date); - - if (val.isNaN()) { - val = 0.0f; - } - } - - basin.setValue(date, val); - } - } - } - } - } + basin.setValue(date, val); + } + } + } + } + } public void setSourceName(String sourceName) { this.sourceName = sourceName; @@ -322,8 +312,8 @@ public class FFMPDataContainer { } } } catch (Exception e) { - statusHandler.debug("No old times available..."+getSourceName()); - return null; + statusHandler.debug("No old times available..." + getSourceName()); + return null; } return null; } @@ -345,13 +335,14 @@ public class FFMPDataContainer { orderedTimes.add(time); } } - + Collections.reverse(orderedTimes); - + return orderedTimes; } } catch (Exception e) { - statusHandler.debug("No ordered times available..."+getSourceName()); + statusHandler.debug("No ordered times available..." + + getSourceName()); return null; } @@ -375,7 +366,7 @@ public class FFMPDataContainer { } } } catch (Exception e) { - statusHandler.debug("No new times available..."+getSourceName()); + statusHandler.debug("No new times available..." + getSourceName()); return null; } @@ -458,9 +449,9 @@ public class FFMPDataContainer { public double getMaxValue(ArrayList pfafs, Date backDate, Date currDate, long expirationTime, boolean rate) { - double val = getBasinData("ALL").getAccumMaxValue(pfafs, currDate, backDate, - expirationTime, rate); - + double val = getBasinData("ALL").getAccumMaxValue(pfafs, currDate, + backDate, expirationTime, rate); + return val; } @@ -473,12 +464,12 @@ public class FFMPDataContainer { } } - public void setFilePath(String filePath) { - this.filePath = filePath; - } + public void setFilePath(String filePath) { + this.filePath = filePath; + } - public String getFilePath() { - return filePath; - } + public String getFilePath() { + return filePath; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/MANIFEST.MF index c37d408810..a28562f5d1 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/MANIFEST.MF @@ -35,6 +35,7 @@ Export-Package: com.raytheon.uf.common.dataplugin.gfe, com.raytheon.uf.common.dataplugin.gfe.server.request, com.raytheon.uf.common.dataplugin.gfe.slice, com.raytheon.uf.common.dataplugin.gfe.textproduct, + com.raytheon.uf.common.dataplugin.gfe.time, com.raytheon.uf.common.dataplugin.gfe.util, com.raytheon.uf.common.dataplugin.gfe.weather, com.raytheon.uf.common.dataplugin.gfe.weatherelement diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.java deleted file mode 100644 index e03fb4c321..0000000000 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.java +++ /dev/null @@ -1,44 +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.common.dataplugin.gfe.request; - -import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; - -/** - * TODO Add Description - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jan 19, 2011            dgilling     Initial creation
- * 
- * 
- * - * @author dgilling - * @version 1.0 - */ - -@DynamicSerialize -public class GetActiveSitesRequest extends AbstractGfeRequest { - -} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.java new file mode 100644 index 0000000000..b87aa14c02 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.java @@ -0,0 +1,90 @@ +/** + * 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.dataplugin.gfe.request; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * Request that allows a defined selection time range to be retrieved by name. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 1, 2012             dgilling    Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ +@DynamicSerialize +public class GetSelectTimeRangeRequest extends AbstractGfeRequest { + + @DynamicSerializeElement + private String name; + + public GetSelectTimeRangeRequest() { + super(); + this.name = null; + } + + public GetSelectTimeRangeRequest(String name) { + super(); + this.name = name; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("GetSelectTimeRangeRequest [name="); + builder.append(name); + builder.append(", workstationID="); + if (workstationID == null) { + builder.append("null"); + } else { + builder.append(workstationID.toPrettyString()); + } + builder.append(", siteID="); + if (siteID == null) { + builder.append("null"); + } else { + builder.append(siteID); + } + builder.append("]"); + return builder.toString(); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/time/SelectTimeRange.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/time/SelectTimeRange.java similarity index 95% rename from cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/time/SelectTimeRange.java rename to edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/time/SelectTimeRange.java index b6017859a8..32d11e5605 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/time/SelectTimeRange.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/time/SelectTimeRange.java @@ -18,7 +18,7 @@ * further licensing information. **/ -package com.raytheon.viz.gfe.core.time; +package com.raytheon.uf.common.dataplugin.gfe.time; import java.util.Calendar; import java.util.Date; @@ -36,7 +36,8 @@ import com.raytheon.uf.common.time.TimeRange; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jun 24, 2008 mnash Initial creation + * Jun 24, 2008 mnash Initial creation + * Aug 01, 2012 #965 dgilling Moved to dataplugin.gfe project. * * * @@ -117,6 +118,7 @@ public class SelectTimeRange implements Comparable { /** * @see java.lang.Comparable#compareTo(java.lang.Object) */ + @Override public int compareTo(SelectTimeRange other) { if (start != other.start) { return start - other.start; diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/subgrid/SubGridDef.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/subgrid/SubGridDef.java index 60e07f2744..989fd6bf9e 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/subgrid/SubGridDef.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/subgrid/SubGridDef.java @@ -27,6 +27,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlList; import javax.xml.bind.annotation.XmlRootElement; +import com.raytheon.uf.common.geospatial.MapUtil; import com.raytheon.uf.common.serialization.ISerializableObject; /** @@ -38,7 +39,7 @@ import com.raytheon.uf.common.serialization.ISerializableObject; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 25, 2010 rjpeter Initial creation - * + * Jul 25, 2012 977 rjpeter Add optional centerLatitude/centerLongitude * * * @author rjpeter @@ -51,37 +52,39 @@ public class SubGridDef implements ISerializableObject { @XmlElement(required = true) @XmlList private List modelNames; - + @XmlElement(required = true) private String referenceModel; + @XmlElement(required = true) + private double nx; + + @XmlElement(required = true) + private double ny; + + // annotation on setter to enforce data constraints + private Double centerLatitude; + + // annotation on setter to enforce data constraints + private Double centerLongitude; + /** the lower left latitude */ - @XmlElement private double lowerLeftLat; /** the lower left longitude */ - @XmlElement private double lowerLeftLon; /** the upper right latitude */ - @XmlElement private double upperRightLat; /** the upper right longitude */ - @XmlElement private double upperRightLon; - - @XmlElement(required = true) - private double nx; - - @XmlElement(required = true) - private double ny; public List getModelNames() { return modelNames; } - public void setModelNames(List modelNames) { + public void setModelNames(final List modelNames) { this.modelNames = modelNames; } @@ -89,7 +92,7 @@ public class SubGridDef implements ISerializableObject { return lowerLeftLat; } - public void setLowerLeftLat(double lowerLeftLat) { + public void setLowerLeftLat(final double lowerLeftLat) { this.lowerLeftLat = lowerLeftLat; } @@ -97,7 +100,7 @@ public class SubGridDef implements ISerializableObject { return lowerLeftLon; } - public void setLowerLeftLon(double lowerLeftLon) { + public void setLowerLeftLon(final double lowerLeftLon) { this.lowerLeftLon = lowerLeftLon; } @@ -105,7 +108,7 @@ public class SubGridDef implements ISerializableObject { return upperRightLat; } - public void setUpperRightLat(double upperRightLat) { + public void setUpperRightLat(final double upperRightLat) { this.upperRightLat = upperRightLat; } @@ -113,7 +116,7 @@ public class SubGridDef implements ISerializableObject { return upperRightLon; } - public void setUpperRightLon(double upperRightLon) { + public void setUpperRightLon(final double upperRightLon) { this.upperRightLon = upperRightLon; } @@ -121,7 +124,7 @@ public class SubGridDef implements ISerializableObject { return nx; } - public void setNx(double nx) { + public void setNx(final double nx) { this.nx = nx; } @@ -129,7 +132,7 @@ public class SubGridDef implements ISerializableObject { return ny; } - public void setNy(double ny) { + public void setNy(final double ny) { this.ny = ny; } @@ -137,9 +140,33 @@ public class SubGridDef implements ISerializableObject { return referenceModel; } - public void setReferenceModel(String referenceModel) { + public void setReferenceModel(final String referenceModel) { this.referenceModel = referenceModel; } - - -} \ No newline at end of file + + public Double getCenterLatitude() { + return centerLatitude; + } + + @XmlElement + public void setCenterLatitude(final Double centerLatitude) { + this.centerLatitude = centerLatitude; + if (this.centerLatitude != null) { + this.centerLatitude = new Double(MapUtil.correctLat(centerLatitude + .doubleValue())); + } + } + + public Double getCenterLongitude() { + return centerLongitude; + } + + @XmlElement + public void setCenterLongitude(final Double centerLongitude) { + this.centerLongitude = centerLongitude; + if (this.centerLongitude != null) { + this.centerLongitude = new Double( + MapUtil.correctLon(centerLongitude.doubleValue())); + } + } +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/util/GribModelLookup.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/util/GribModelLookup.java index 44aac08506..c664b6a207 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/util/GribModelLookup.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/util/GribModelLookup.java @@ -21,6 +21,7 @@ package com.raytheon.uf.common.dataplugin.grib.util; import java.util.HashMap; import java.util.Map; +import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -126,6 +127,10 @@ public class GribModelLookup { } } } + + public Set getModelNames(){ + return modelsByName.keySet(); + } private String toKey(Integer center, Integer subcenter, String grid, Integer process) { 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 250453f3f0..6a0d595114 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 @@ -70,6 +70,12 @@ import com.vividsolutions.jts.geom.Geometry; * 20090408 952 jsanchez Updated getValue and getStrings methods. * Added getMessageData method. * 20090521 2338 jsanchez Changed the unit of the alititude. + * ====================================== + * 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. + * * * * @author jkorman @@ -138,7 +144,10 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, } @Transient - private PirepLayerData maxPirepLayerData = null; + private PirepLayerData maxTurbcLayerData = null; + + @Transient + private PirepLayerData maxIcingLayerData = null; @Transient private boolean display = true; @@ -591,32 +600,31 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, */ @Override public Amount getValue(String paramName) { + findMaxIcingLayer(); + findMaxTurbcLayer(); 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); - } 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); - } + 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); + } 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) { + a = new Amount(maxTurbcLayerData.getBaseLayerHeight().intValue(), + ALTITUDE_UNIT); } return a; } @@ -636,81 +644,85 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, @Override public String[] getStrings(String paramName) { - if ("ICI".matches(paramName)) { - int rank = -1; - String iceIntensity = null; - for (PirepLayerData layer : this.ancPirepData) { - String intensity = ""; - if (layer.getLayerType().equals(PirepLayerData.LAYER_TYP_ICING)) { - if (layer.getFirstValue() != null) { - intensity = layer.getFirstValue(); - } - if (layer.getSecondValue() != null) { - intensity += layer.getSecondValue(); - } + findMaxIcingLayer(); + findMaxTurbcLayer(); - if (ICING_MAP.get(intensity).intValue() > rank) { - rank = ICING_MAP.get(intensity).intValue(); - iceIntensity = intensity; - maxPirepLayerData = layer; - } + String[] retData = null; + if ("ICI".matches(paramName)) { + if (maxIcingLayerData != null) { + String intensity = getIntensity(maxIcingLayerData); + if (intensity != null) { + retData = new String[] { intensity }; } } - if (iceIntensity != null) { - String[] maxIntensity = { iceIntensity }; - return maxIntensity; - } else { - display = false; - } - } else if ("ICT".matches(paramName) && maxPirepLayerData != null) { - if (maxPirepLayerData == null) { - findMaxTurbcLayer(); - } - if (maxPirepLayerData != null) { - String type = maxPirepLayerData.getDataType(); + } else if ("ICT".matches(paramName) && maxIcingLayerData != null) { + if (maxIcingLayerData != null) { + String type = maxIcingLayerData.getDataType(); if (type != null) { - return new String[] { type, }; + retData = new String[] { type, }; } } } else if ("TBI".matches(paramName)) { - if (maxPirepLayerData == null) { - findMaxTurbcLayer(); - } - if (maxPirepLayerData != null) { - String intensity = getIntensity(maxPirepLayerData); + if (maxTurbcLayerData != null) { + String intensity = getIntensity(maxTurbcLayerData); if (intensity != null) { - return new String[] { intensity, }; + retData = new String[] { intensity }; } } } else if ("TBF".matches(paramName)) { - if (maxPirepLayerData == null) { - findMaxTurbcLayer(); - } - if (maxPirepLayerData != null) { - String freq = maxPirepLayerData.getFrequency(); + findMaxTurbcLayer(); + if (maxTurbcLayerData != null) { + String freq = maxTurbcLayerData.getFrequency(); if (freq != null) { - return new String[] { freq, }; + retData = new String[] { freq, }; } } } - return null; + return retData; + } + + private void findMaxIcingLayer() { + if (maxIcingLayerData == null) { + int rank = -1; + for (PirepLayerData layer : this.ancPirepData) { + if (layer.getLayerType().equals(PirepLayerData.LAYER_TYP_ICING)) { + String intensity = getIntensity(layer); + Integer n = ICING_MAP.get(intensity); + if ((n != null) && (n > rank)) { + rank = n; + maxIcingLayerData = layer; + } + } + } + if (maxIcingLayerData != null) { + display = (getIntensity(maxIcingLayerData) != null); + } else { + display = false; + } + } } /** * Find a turbulence layer with the greatest ordinal intensity. */ private void findMaxTurbcLayer() { - int rank = -1; - for (PirepLayerData layer : this.ancPirepData) { - if (PirepLayerData.LAYER_TYP_TURBC.equals(layer.getLayerType())) { - String intensity = getIntensity(layer); - if (TURB_MAP.containsKey(intensity)) { - if (TURB_MAP.get(intensity).intValue() > rank) { - rank = TURB_MAP.get(intensity).intValue(); - maxPirepLayerData = layer; + if (maxTurbcLayerData == null) { + int rank = -1; + for (PirepLayerData layer : this.ancPirepData) { + if (PirepLayerData.LAYER_TYP_TURBC.equals(layer.getLayerType())) { + String intensity = getIntensity(layer); + Integer n = TURB_MAP.get(intensity); + if ((n != null) && (n > rank)) { + rank = n; + maxTurbcLayerData = layer; } } } + if (maxTurbcLayerData != null) { + display = (getIntensity(maxTurbcLayerData) != null); + } else { + display = false; + } } } @@ -788,36 +800,4 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, return false; return true; } - - public static final void main(String[] args) { - - PirepRecord rec = new PirepRecord(); - - PirepLayerData layer = new PirepLayerData(rec); - layer.setLayerType(PirepLayerData.LAYER_TYP_TURBC); - layer.setFrequency("OCN"); - layer.setFirstValue("LGT"); - layer.setSecondValue("MOD"); - layer.setBaseLayerHeight(15000); - layer.setTopLayerHeight(20000); - rec.addLayer(layer); - - layer = new PirepLayerData(rec); - layer.setLayerType(PirepLayerData.LAYER_TYP_TURBC); - layer.setFrequency("CON"); - layer.setFirstValue("MOD"); - layer.setSecondValue("SEV"); - layer.setBaseLayerHeight(20000); - layer.setTopLayerHeight(22000); - rec.addLayer(layer); - - String[] data = rec.getStrings("TBF"); - if ((data != null) && (data.length > 0)) { - System.out.println(data[0]); - } - data = rec.getStrings("TBI"); - if ((data != null) && (data.length > 0)) { - System.out.println(data[0]); - } - } } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/GeospatialFactory.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/GeospatialFactory.java index 45c65a4930..0b614003f1 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/GeospatialFactory.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/GeospatialFactory.java @@ -60,7 +60,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; * AreaSourceConfiguration to areaFields List. * Apr 11, 2012 #14691 Qinglu Lin For marine warnings, getFeAreaField() returns null. * So, do not add the returned value of getFeAreaField() - * to areaFields. + * to areaFields. * * * @@ -116,7 +116,16 @@ public class GeospatialFactory { GeospatialData[] areas = dataSet.getAreas(); GeospatialData[] parentAreas = dataSet.getParentAreas(); - timezones = dataSet.getTimezones(); + GeospatialData[] myTimeZones = dataSet.getTimezones(); + if (myTimeZones != null && myTimeZones.length > 0) { + if (timezones == null) { + timezones = myTimeZones; + } + + for (GeospatialData tz : myTimeZones) { + tz.prepGeom = PreparedGeometryFactory.prepare(tz.geometry); + } + } Map> uniqueAreasMap = new HashMap>(); for (GeospatialData data : areas) { @@ -254,20 +263,20 @@ public class GeospatialFactory { AreaSourceConfiguration[] ascs = template.getAreaSources(); for (AreaSourceConfiguration asc : ascs) { - List areaFields = new ArrayList(); - String feAreaField = asc.getFeAreaField(); - String timeZoneField = asc.getTimeZoneField(); - areaFields.add(WarningConstants.GID); + List areaFields = new ArrayList(); + String feAreaField = asc.getFeAreaField(); + String timeZoneField = asc.getTimeZoneField(); + areaFields.add(WarningConstants.GID); areaFields.add(asc.getAreaField()); if (feAreaField != null) { - areaFields.add(feAreaField); - } - + areaFields.add(feAreaField); + } + if (timeZoneField != null) { areaFields.add(timeZoneField); } areaFields.add(asc.getFipsField()); - areaFields.add(asc.getAreaNotationField()); + areaFields.add(asc.getAreaNotationField()); GeospatialMetadata gmd = new GeospatialMetadata(); gmd.setAreaSource(asc.getAreaSource()); diff --git a/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/DestinationGeodeticCalculator.java b/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/DestinationGeodeticCalculator.java index 29fc9300d0..72582024e0 100644 --- a/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/DestinationGeodeticCalculator.java +++ b/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/DestinationGeodeticCalculator.java @@ -23,143 +23,144 @@ import org.geotools.referencing.GeodeticCalculator; * @version 1.0 */ public class DestinationGeodeticCalculator { - private static final double MAX_DIST = 20000000; + private static final double MAX_DIST = 20000000; - private double azimuth; + private double azimuth; - private double distance; + private double distance; - private double startLongitude; + private double startLongitude; - private double startLatitude; + private double startLatitude; - private double destLongitude; + private double destLongitude; - private double destLatitude; + private double destLatitude; - private boolean validDistance; + private boolean validDistance; - private boolean validDestination; + private boolean validDestination; - /** - * Set the azimuth and the distance. - * - * @param azimuth - * The azimuth in decimal degrees from -180° to 180°. - * @param distance - * The orthodromic distance in the same units as the ellipsoid - * axis. - * - */ - public void setDirection(double azimuth, double distance) - throws IllegalArgumentException { - this.azimuth = checkAzimuth(azimuth); - this.distance = distance; - validDistance = true; - validDestination = false; - } + private GeodeticCalculator gc = new GeodeticCalculator(); - /** - * Returns the orthodromic distance - */ - public double getOrthodromicDistance() { - if (!validDistance) { - GeodeticCalculator gc = new GeodeticCalculator(); - gc.setStartingGeographicPoint(startLongitude, startLatitude); - gc.setDestinationGeographicPoint(destLongitude, destLatitude); - distance = gc.getOrthodromicDistance(); - } - return distance; - } + /** + * Set the azimuth and the distance. + * + * @param azimuth + * The azimuth in decimal degrees from -180° to 180°. + * @param distance + * The orthodromic distance in the same units as the ellipsoid + * axis. + * + */ + public void setDirection(double azimuth, double distance) + throws IllegalArgumentException { + this.azimuth = checkAzimuth(azimuth); + this.distance = distance; + validDistance = true; + validDestination = false; + } - /** - * Sets starting point - */ - public void setStartingGeographicPoint(double lon, double lat) - throws IllegalArgumentException { - this.startLongitude = checkLongitude(lon); - this.startLatitude = checkLatitude(lat); - } + /** + * Returns the orthodromic distance + */ + public double getOrthodromicDistance() { + if (!validDistance) { + GeodeticCalculator gc = new GeodeticCalculator(); + gc.setStartingGeographicPoint(startLongitude, startLatitude); + gc.setDestinationGeographicPoint(destLongitude, destLatitude); + distance = gc.getOrthodromicDistance(); + } + return distance; + } - /** - * Sets starting point - */ - public void setStartingGeographicPoint(Point2D point) - throws IllegalArgumentException { - setStartingGeographicPoint(point.getX(), point.getY()); - } + /** + * Sets starting point + */ + public void setStartingGeographicPoint(double lon, double lat) + throws IllegalArgumentException { + this.startLongitude = checkLongitude(lon); + this.startLatitude = checkLatitude(lat); + } - /** - * Sets destination point - */ - public void setDestinationGeographicPoint(double lon, double lat) - throws IllegalArgumentException { - this.destLongitude = checkLongitude(lon); - this.destLatitude = checkLatitude(lat); - validDestination = true; - validDistance = false; - } + /** + * Sets starting point + */ + public void setStartingGeographicPoint(Point2D point) + throws IllegalArgumentException { + setStartingGeographicPoint(point.getX(), point.getY()); + } - /** - * Sets destination point - */ - public void setDestinationGeographicPoint(Point2D point) - throws IllegalArgumentException { - setStartingGeographicPoint(point.getX(), point.getY()); - } + /** + * Sets destination point + */ + public void setDestinationGeographicPoint(double lon, double lat) + throws IllegalArgumentException { + this.destLongitude = checkLongitude(lon); + this.destLatitude = checkLatitude(lat); + validDestination = true; + validDistance = false; + } - /** - * Returns the destination point. - */ - public Point2D getDestinationGeographicPoint() { - GeodeticCalculator gc = new GeodeticCalculator(); - gc.setStartingGeographicPoint(startLongitude, startLatitude); + /** + * Sets destination point + */ + public void setDestinationGeographicPoint(Point2D point) + throws IllegalArgumentException { + setStartingGeographicPoint(point.getX(), point.getY()); + } - if (validDestination) { - gc.setDestinationGeographicPoint(destLongitude, destLatitude); - return gc.getDestinationGeographicPoint(); - } + /** + * Returns the destination point. + */ + public Point2D getDestinationGeographicPoint() { + gc.setStartingGeographicPoint(startLongitude, startLatitude); - Point2D referenceGeographicPoint = gc.getStartingGeographicPoint(); - double dist = distance; - while (dist > MAX_DIST) { - gc.setStartingGeographicPoint(referenceGeographicPoint); - gc.setDirection(azimuth, MAX_DIST); - referenceGeographicPoint = gc.getDestinationGeographicPoint(); - dist -= MAX_DIST; - } + if (validDestination) { + gc.setDestinationGeographicPoint(destLongitude, destLatitude); + return gc.getDestinationGeographicPoint(); + } - gc.setStartingGeographicPoint(referenceGeographicPoint); - gc.setDirection(azimuth, dist); + Point2D referenceGeographicPoint = gc.getStartingGeographicPoint(); + double dist = distance; + while (dist > MAX_DIST) { + gc.setStartingGeographicPoint(referenceGeographicPoint); + gc.setDirection(azimuth, MAX_DIST); + referenceGeographicPoint = gc.getDestinationGeographicPoint(); + dist -= MAX_DIST; + } - return gc.getDestinationGeographicPoint(); - } + gc.setStartingGeographicPoint(referenceGeographicPoint); + gc.setDirection(azimuth, dist); - private static double checkLongitude(final double longitude) - throws IllegalArgumentException { - if (longitude >= -180 && longitude <= 180) { - return longitude; - } - throw new IllegalArgumentException("Longitude out of range: " - + longitude + ". Must be between -180 and 180"); - } + return gc.getDestinationGeographicPoint(); + } - private static double checkLatitude(final double latitude) - throws IllegalArgumentException { - if (latitude >= -90 && latitude <= 90) { - return latitude; - } - throw new IllegalArgumentException("Latitude out of range: " + latitude - + ". Must be between -90 and 90"); + private static double checkLongitude(final double longitude) + throws IllegalArgumentException { + if (longitude >= -180 && longitude <= 180) { + return longitude; + } + throw new IllegalArgumentException("Longitude out of range: " + + longitude + ". Must be between -180 and 180"); + } - } + private static double checkLatitude(final double latitude) + throws IllegalArgumentException { + if (latitude >= -90 && latitude <= 90) { + return latitude; + } + throw new IllegalArgumentException("Latitude out of range: " + latitude + + ". Must be between -90 and 90"); - private static double checkAzimuth(final double azimuth) - throws IllegalArgumentException { - if (azimuth >= -180.0 && azimuth <= 180.0) { - return azimuth; - } - throw new IllegalArgumentException("Azimuth out of range: " + azimuth - + ". Must be between -180 and 180"); - } + } + + private static double checkAzimuth(final double azimuth) + throws IllegalArgumentException { + if (azimuth >= -180.0 && azimuth <= 180.0) { + return azimuth; + } + throw new IllegalArgumentException("Azimuth out of range: " + azimuth + + ". Must be between -180 and 180"); + } } diff --git a/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/data/CommonTableConfig.java b/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/data/CommonTableConfig.java index 3bb19e0fee..02993b5dbb 100644 --- a/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/data/CommonTableConfig.java +++ b/edexOsgi/com.raytheon.uf.common.monitor/src/com/raytheon/uf/common/monitor/data/CommonTableConfig.java @@ -184,45 +184,48 @@ public class CommonTableConfig { * Available Observation History columns for SAFESEAS, Snow, Fog. */ public static enum obsHistCols { - Time, WindSpd, MaxWindSpd, WindGust, WindDir, Vis_mi, Vis_mn, P, PTend, SigWaveHgt, SwellHgt, SwellPer, SwellDir, T, Dewpt, SST, WaveSteep, RelHum, Ceiling, DewptDepr + Time, Lat, Lon, WindSpd, MaxWindSpd, WindGust, WindDir, Vis_mi, Vis_mn, P, PTend, SigWaveHgt, SwellHgt, SwellPer, SwellDir, T, Dewpt, SST, WaveSteep, RelHum, Ceiling, DewptDepr }; /** * SAFESEAS Maritime table columns. */ - private final String[] ssMaritimeTableCols = new String[] { - obsHistCols.Time.name(), obsHistCols.WindSpd.name(), - obsHistCols.MaxWindSpd.name(), obsHistCols.WindGust.name(), - obsHistCols.Vis_mn.name(), obsHistCols.P.name(), - obsHistCols.PTend.name(), obsHistCols.T.name(), - obsHistCols.Dewpt.name(), obsHistCols.SST.name(), - obsHistCols.SigWaveHgt.name(), obsHistCols.WaveSteep.name(), - obsHistCols.SwellHgt.name(), obsHistCols.SwellPer.name(), - obsHistCols.SwellDir.name() }; + private final String[] ssMaritimeTableCols = new String[] { + obsHistCols.Time.name(), obsHistCols.Lat.name(), + obsHistCols.Lon.name(), obsHistCols.WindSpd.name(), + obsHistCols.MaxWindSpd.name(), obsHistCols.WindGust.name(), + obsHistCols.Vis_mn.name(), obsHistCols.P.name(), + obsHistCols.PTend.name(), obsHistCols.T.name(), + obsHistCols.Dewpt.name(), obsHistCols.SST.name(), + obsHistCols.SigWaveHgt.name(), obsHistCols.WaveSteep.name(), + obsHistCols.SwellHgt.name(), obsHistCols.SwellPer.name(), + obsHistCols.SwellDir.name() }; - /** - * SAFESEAS METAR table columns. - */ - private final String[] ssMetarTableCols = new String[] { - obsHistCols.Time.name(), obsHistCols.WindDir.name(), - obsHistCols.WindSpd.name(), obsHistCols.WindGust.name(), - obsHistCols.P.name(), obsHistCols.T.name(), - obsHistCols.Dewpt.name(), obsHistCols.PTend.name() }; + /** + * SAFESEAS METAR table columns. + */ + private final String[] ssMetarTableCols = new String[] { + obsHistCols.Time.name(), obsHistCols.Lat.name(), + obsHistCols.Lon.name(), obsHistCols.WindDir.name(), + obsHistCols.WindSpd.name(), obsHistCols.WindGust.name(), + obsHistCols.P.name(), obsHistCols.T.name(), + obsHistCols.Dewpt.name(), obsHistCols.PTend.name() }; - /** - * Snow METAR table columns. - */ - private final String[] snowMetarTableCols = new String[] { - obsHistCols.Time.name(), obsHistCols.WindDir.name(), - obsHistCols.WindSpd.name(), obsHistCols.WindGust.name(), - obsHistCols.P.name(), obsHistCols.T.name(), - obsHistCols.Dewpt.name(), obsHistCols.PTend.name() }; + /** + * Snow METAR table columns. + */ + private final String[] snowMetarTableCols = new String[] { + obsHistCols.Time.name(), obsHistCols.Lat.name(), + obsHistCols.Lon.name(), obsHistCols.WindDir.name(), + obsHistCols.WindSpd.name(), obsHistCols.WindGust.name(), + obsHistCols.P.name(), obsHistCols.T.name(), + obsHistCols.Dewpt.name(), obsHistCols.PTend.name() }; /** * METAR configure names */ private final String[] metarConfigureNames = new String[] { - "Wind Dir (deg)", "Wind Spd (kt)", "Wind Gust (kt)", "P (in)", + "Lat (deg)", "Lon (deg)", "Wind Dir (deg)", "Wind Spd (kt)", "Wind Gust (kt)", "P (in)", "T (deg F)", "Dewpt (deg F)", "P Tendency (in)" }; /** @@ -230,7 +233,7 @@ public class CommonTableConfig { */ private final String[] metarFogConfigureNames = new String[] { - "Rel Hum (%)", "Vis (mi)", "Ceiling (ft x 100)", "Wind Dir (deg)", + "Lat (deg)", "Lon (deg)", "Rel Hum (%)", "Vis (mi)", "Ceiling (ft x 100)", "Wind Dir (deg)", "Wind Spd (kt)", "Wind Gust (kt)", "P (in)", "T (deg F)", "Dewpt (deg F)", "DewptDepr (deg F)", "P Tendency (in)" }; @@ -239,7 +242,7 @@ public class CommonTableConfig { */ private final String[] maritimeFogConfigureNames = new String[] { - "Wind Dir (deg)", "Wind Spd (kt)", "Wind Gust (kt)", "Vis (nm)", + "Lat (deg)", "Lon (deg)", "Wind Dir (deg)", "Wind Spd (kt)", "Wind Gust (kt)", "Vis (nm)", "P (in)", "P Tendency (in)", "T (deg F)", "Dewpt (deg F)", "SST (deg F)", "Significant Wave Hgt (ft)", "Wave Steep", "Swell Hgt (ft)", "Swell Per (sec)", "Swell Dir (deg)", @@ -250,7 +253,7 @@ public class CommonTableConfig { */ private final String[] maritimeSSConfigureNames = new String[] { - "Wind Spd (kt)", "MaxWindSpd (kt)", "Wind Gust (kt)", "Vis (nm)", + "Lat (deg)", "Lon (deg)", "Wind Spd (kt)", "MaxWindSpd (kt)", "Wind Gust (kt)", "Vis (nm)", "P (in)", "P Tendency (in)", "T (deg F)", "Dewpt (deg F)", "SST (deg F)", "Significant Wave Hgt (ft)", "Wave Steep", "Swell Hgt (ft)", "Swell Per (sec)", "Swell Dir (deg)" }; @@ -258,21 +261,23 @@ public class CommonTableConfig { /** * Fog Maritime table columns. */ - private final String[] fogMaritimeTableCols = new String[] { - obsHistCols.Time.name(), obsHistCols.WindSpd.name(), - obsHistCols.MaxWindSpd.name(), obsHistCols.WindGust.name(), - obsHistCols.Vis_mi.name(), obsHistCols.P.name(), - obsHistCols.PTend.name(), obsHistCols.T.name(), - obsHistCols.Dewpt.name(), obsHistCols.SST.name(), - obsHistCols.SigWaveHgt.name(), obsHistCols.WaveSteep.name(), - obsHistCols.SwellHgt.name(), obsHistCols.SwellPer.name(), - obsHistCols.SwellDir.name(), obsHistCols.RelHum.name() }; + private final String[] fogMaritimeTableCols = new String[] { + obsHistCols.Time.name(), obsHistCols.Lat.name(), + obsHistCols.Lon.name(), obsHistCols.WindSpd.name(), + obsHistCols.MaxWindSpd.name(), obsHistCols.WindGust.name(), + obsHistCols.Vis_mi.name(), obsHistCols.P.name(), + obsHistCols.PTend.name(), obsHistCols.T.name(), + obsHistCols.Dewpt.name(), obsHistCols.SST.name(), + obsHistCols.SigWaveHgt.name(), obsHistCols.WaveSteep.name(), + obsHistCols.SwellHgt.name(), obsHistCols.SwellPer.name(), + obsHistCols.SwellDir.name(), obsHistCols.RelHum.name() }; /** * Fog METAR table columns. */ private final String[] fogMetarTableCols = new String[] { - obsHistCols.Time.name(), obsHistCols.RelHum.name(), + obsHistCols.Time.name(), obsHistCols.Lat.name(), + obsHistCols.Lon.name(),obsHistCols.RelHum.name(), obsHistCols.Vis_mi.name(), obsHistCols.Ceiling.name(), obsHistCols.WindDir.name(), obsHistCols.WindSpd.name(), obsHistCols.WindGust.name(), obsHistCols.P.name(), @@ -493,56 +498,60 @@ public class CommonTableConfig { SortDirection.Decending, GraphType.None)); } - /** - * Create the Observation History column attributes. - */ - private void createObsHistoryColumnAttributes() { - obsHistColumnAttrMap.put(obsHistCols.Time.name(), new ColumnAttribData( - "Time (UTC)", "Time (UTC)")); - obsHistColumnAttrMap.put(obsHistCols.WindSpd.name(), - new ColumnAttribData("Wind Spd (kt)", "Wind Spd\n(kt)")); - obsHistColumnAttrMap - .put(obsHistCols.MaxWindSpd.name(), new ColumnAttribData( - "Max Wind Spd (kt)", "Max Wind\nSpd (kt)")); - obsHistColumnAttrMap.put(obsHistCols.WindGust.name(), - new ColumnAttribData("Wind Gust (kt)", "Wind Gust\n(kt)")); - obsHistColumnAttrMap.put(obsHistCols.WindDir.name(), - new ColumnAttribData("Wind Dir (deg)", "Wind Dir\n(deg)")); - obsHistColumnAttrMap.put(obsHistCols.Vis_mi.name(), - new ColumnAttribData("Vis (mi)", "Vis (mi)")); - obsHistColumnAttrMap.put(obsHistCols.Vis_mn.name(), - new ColumnAttribData("Vis (nm)", "Vis (nm)")); - obsHistColumnAttrMap.put(obsHistCols.P.name(), new ColumnAttribData( - "P (in)", "P (in)")); - obsHistColumnAttrMap.put(obsHistCols.PTend.name(), - new ColumnAttribData("P Tendency (in)", "P Tendency\n(in)")); - obsHistColumnAttrMap.put(obsHistCols.SigWaveHgt.name(), - new ColumnAttribData("Significant Wave Hgt (ft)", - "Significant\nWave Hgt (ft)")); - obsHistColumnAttrMap.put(obsHistCols.SwellHgt.name(), - new ColumnAttribData("Swell Hgt (ft)", "Swell Hgt\n(ft)")); - obsHistColumnAttrMap.put(obsHistCols.SwellPer.name(), - new ColumnAttribData("Swell Per (sec)", "Swell Per\n(sec)")); - obsHistColumnAttrMap.put(obsHistCols.SwellDir.name(), - new ColumnAttribData("Swell Dir (deg)", "Swell Dir\n(deg)")); - obsHistColumnAttrMap.put(obsHistCols.T.name(), new ColumnAttribData( - "T (deg F)", "T (deg F)")); - obsHistColumnAttrMap.put(obsHistCols.Dewpt.name(), - new ColumnAttribData("Dewpt (deg F)", "Dewpt\n(deg F)")); - obsHistColumnAttrMap.put(obsHistCols.SST.name(), new ColumnAttribData( - "SST (deg F)", "SST\n(deg F)")); - obsHistColumnAttrMap.put(obsHistCols.WaveSteep.name(), - new ColumnAttribData("Wave Steep", "Wave\nSteep")); - obsHistColumnAttrMap.put(obsHistCols.RelHum.name(), - new ColumnAttribData("Rel. Humid (%)", "Rel. Humid\n(%)")); - obsHistColumnAttrMap.put(obsHistCols.Ceiling.name(), - new ColumnAttribData("Ceiling (ft x 100)", - "Ceiling\n(ft x 100)")); - obsHistColumnAttrMap - .put(obsHistCols.DewptDepr.name(), new ColumnAttribData( - "DewptDepr (deg F)", "DewptDepr\n(deg F)")); + /** + * Create the Observation History column attributes. + */ + private void createObsHistoryColumnAttributes() { + obsHistColumnAttrMap.put(obsHistCols.Time.name(), new ColumnAttribData( + "Time (UTC)", "Time (UTC)")); + obsHistColumnAttrMap.put(obsHistCols.Lat.name(), new ColumnAttribData( + "Lat (deg)", "Lat (deg)")); + obsHistColumnAttrMap.put(obsHistCols.Lon.name(), new ColumnAttribData( + "Lon (deg)", "Lon (deg)")); + obsHistColumnAttrMap.put(obsHistCols.WindSpd.name(), + new ColumnAttribData("Wind Spd (kt)", "Wind Spd\n(kt)")); + obsHistColumnAttrMap + .put(obsHistCols.MaxWindSpd.name(), new ColumnAttribData( + "Max Wind Spd (kt)", "Max Wind\nSpd (kt)")); + obsHistColumnAttrMap.put(obsHistCols.WindGust.name(), + new ColumnAttribData("Wind Gust (kt)", "Wind Gust\n(kt)")); + obsHistColumnAttrMap.put(obsHistCols.WindDir.name(), + new ColumnAttribData("Wind Dir (deg)", "Wind Dir\n(deg)")); + obsHistColumnAttrMap.put(obsHistCols.Vis_mi.name(), + new ColumnAttribData("Vis (mi)", "Vis (mi)")); + obsHistColumnAttrMap.put(obsHistCols.Vis_mn.name(), + new ColumnAttribData("Vis (nm)", "Vis (nm)")); + obsHistColumnAttrMap.put(obsHistCols.P.name(), new ColumnAttribData( + "P (in)", "P (in)")); + obsHistColumnAttrMap.put(obsHistCols.PTend.name(), + new ColumnAttribData("P Tendency (in)", "P Tendency\n(in)")); + obsHistColumnAttrMap.put(obsHistCols.SigWaveHgt.name(), + new ColumnAttribData("Significant Wave Hgt (ft)", + "Significant\nWave Hgt (ft)")); + obsHistColumnAttrMap.put(obsHistCols.SwellHgt.name(), + new ColumnAttribData("Swell Hgt (ft)", "Swell Hgt\n(ft)")); + obsHistColumnAttrMap.put(obsHistCols.SwellPer.name(), + new ColumnAttribData("Swell Per (sec)", "Swell Per\n(sec)")); + obsHistColumnAttrMap.put(obsHistCols.SwellDir.name(), + new ColumnAttribData("Swell Dir (deg)", "Swell Dir\n(deg)")); + obsHistColumnAttrMap.put(obsHistCols.T.name(), new ColumnAttribData( + "T (deg F)", "T (deg F)")); + obsHistColumnAttrMap.put(obsHistCols.Dewpt.name(), + new ColumnAttribData("Dewpt (deg F)", "Dewpt\n(deg F)")); + obsHistColumnAttrMap.put(obsHistCols.SST.name(), new ColumnAttribData( + "SST (deg F)", "SST\n(deg F)")); + obsHistColumnAttrMap.put(obsHistCols.WaveSteep.name(), + new ColumnAttribData("Wave Steep", "Wave\nSteep")); + obsHistColumnAttrMap.put(obsHistCols.RelHum.name(), + new ColumnAttribData("Rel. Humid (%)", "Rel. Humid\n(%)")); + obsHistColumnAttrMap.put(obsHistCols.Ceiling.name(), + new ColumnAttribData("Ceiling (ft x 100)", + "Ceiling\n(ft x 100)")); + obsHistColumnAttrMap + .put(obsHistCols.DewptDepr.name(), new ColumnAttribData( + "DewptDepr (deg F)", "DewptDepr\n(deg F)")); - } + } /** * Get the Zone/Station column keys. diff --git a/edexOsgi/com.raytheon.uf.common.serialization.comm/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.serialization.comm/META-INF/MANIFEST.MF index 6902fed3de..4bdb30baf4 100644 --- a/edexOsgi/com.raytheon.uf.common.serialization.comm/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.serialization.comm/META-INF/MANIFEST.MF @@ -13,3 +13,4 @@ Export-Package: com.raytheon.uf.common.serialization.comm, Require-Bundle: com.raytheon.uf.common.serialization;bundle-version="1.11.12", net.sf.cglib;bundle-version="2.1.3", com.raytheon.uf.common.status +Import-Package: com.raytheon.uf.common.message diff --git a/edexOsgi/com.raytheon.uf.common.serialization.comm/src/com/raytheon/uf/common/serialization/comm/RequestWrapper.java b/edexOsgi/com.raytheon.uf.common.serialization.comm/src/com/raytheon/uf/common/serialization/comm/RequestWrapper.java new file mode 100644 index 0000000000..79c958486c --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.serialization.comm/src/com/raytheon/uf/common/serialization/comm/RequestWrapper.java @@ -0,0 +1,101 @@ +/** + * 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.serialization.comm; + +import com.raytheon.uf.common.message.WsId; +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * Wraps an IServerRequest so it can be tracked on both client applications and + * the server. Contains a unique identifier for this particular request and a + * workstation ID which has the network address and process id. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 24, 2012            njensen     Initial creation
+ * 
+ * 
+ * + * @author njensen + * @version 1.0 + */ + +@DynamicSerialize +public class RequestWrapper { + + @DynamicSerializeElement + private IServerRequest request; + + @DynamicSerializeElement + private WsId wsId; + + @DynamicSerializeElement + private String uniqueId; + + public RequestWrapper() { + + } + + public RequestWrapper(IServerRequest request, WsId workstationId, + String uniqueId) { + this.request = request; + this.wsId = workstationId; + this.uniqueId = uniqueId; + } + + public IServerRequest getRequest() { + return request; + } + + public void setRequest(IServerRequest request) { + this.request = request; + } + + public WsId getWsId() { + return wsId; + } + + public void setWsId(WsId wsId) { + this.wsId = wsId; + } + + public String getUniqueId() { + return uniqueId; + } + + public void setUniqueId(String uniqueId) { + this.uniqueId = uniqueId; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(125); + sb.append("Request[").append(wsId.toPrettyString()).append("][") + .append(uniqueId).append("] ") + .append(request.getClass().getSimpleName()); + return sb.toString(); + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/util/PythonFileGenerator.java b/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/util/PythonFileGenerator.java index 01808f374a..5b62498371 100644 --- a/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/util/PythonFileGenerator.java +++ b/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/util/PythonFileGenerator.java @@ -45,6 +45,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 14, 2010 njensen Initial creation + * Jul 31, 2012 #965 dgilling Fix path to file header. * * * @@ -319,7 +320,8 @@ public class PythonFileGenerator { } public static String getHeaderInfo() throws IOException { - File file = new File("../build.cave/tools/headup/AWIPS/awipsHeader.txt"); + File file = new File( + "../../cave/build/tools/headup/AWIPS/awipsHeader.txt"); if (!file.exists()) { System.out .println("Unable to determine header information, skipping header"); diff --git a/edexOsgi/com.raytheon.uf.common.site/src/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.java b/edexOsgi/com.raytheon.uf.common.site/src/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.java index ba45fcb234..ab56dbd594 100644 --- a/edexOsgi/com.raytheon.uf.common.site/src/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.java +++ b/edexOsgi/com.raytheon.uf.common.site/src/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.java @@ -20,7 +20,6 @@ package com.raytheon.uf.common.site.requests; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; -import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.comm.IServerRequest; /** @@ -32,7 +31,8 @@ import com.raytheon.uf.common.serialization.comm.IServerRequest; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Aug 5, 2011 randerso Initial creation + * Aug 05, 2011 randerso Initial creation + * Jul 31, 2012 #965 dgilling Remove unnecessary code. * * * @@ -42,25 +42,5 @@ import com.raytheon.uf.common.serialization.comm.IServerRequest; @DynamicSerialize public class GetActiveSitesRequest implements IServerRequest { - @DynamicSerializeElement - private String[] activeSites; - - public GetActiveSitesRequest() { - } - - /** - * @return the activeSites - */ - public String[] getActiveSites() { - return activeSites; - } - - /** - * @param activeSites - * the activeSites to set - */ - public void setActiveSites(String[] activeSites) { - this.activeSites = activeSites; - } - + // No fields needed } diff --git a/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/SizeUtil.java b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/SizeUtil.java new file mode 100644 index 0000000000..e0e7eeaa3b --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/SizeUtil.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.common.util; + +/** + * Utilities for calculating the size of objects + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 24, 2012            njensen     Initial creation
+ * 
+ * 
+ * + * @author njensen + * @version 1.0 + */ + +public class SizeUtil { + + private static final int BYTES_PER = 1024; + + private static final String[] REP_PREFIX = new String[] { "B", "kB", "MB", + "GB", "TB", "PB", "EB", "ZB", "YB" }; + + /** + * Transforms a number of bytes to a pretty string based on the total number + * of bytes, e.g. B, kB, MB, or GB as fitting. For example: 1000 -> 1000B, + * 10000 -> 9.7kB, 100000 -> 97.6kB, 1000000 -> 976.5kB, 10000000 -> 9.5MB + * + * @param numberOfBytes + * the number to transform to a pretty string + * @return the pretty String representation of the byte size + */ + public static String prettyByteSize(long numberOfBytes) { + float n = (float) numberOfBytes; + int reps = 0; + while (n > BYTES_PER && reps < REP_PREFIX.length - 1) { + reps++; + n /= BYTES_PER; + } + int tenth = ((int) (n * 10)) % 10; + StringBuilder sb = new StringBuilder(); + sb.append((int) n).append(".").append(tenth); + sb.append(REP_PREFIX[reps]); + return sb.toString(); + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.auth/src/com/raytheon/uf/edex/auth/RemoteRequestRouteWrapper.java b/edexOsgi/com.raytheon.uf.edex.auth/src/com/raytheon/uf/edex/auth/RemoteRequestRouteWrapper.java index a8464e8833..832be233f8 100644 --- a/edexOsgi/com.raytheon.uf.edex.auth/src/com/raytheon/uf/edex/auth/RemoteRequestRouteWrapper.java +++ b/edexOsgi/com.raytheon.uf.edex.auth/src/com/raytheon/uf/edex/auth/RemoteRequestRouteWrapper.java @@ -19,20 +19,17 @@ **/ package com.raytheon.uf.edex.auth; -import java.text.DecimalFormat; - import com.raytheon.uf.common.auth.AuthException; import com.raytheon.uf.common.auth.resp.AuthServerErrorResponse; import com.raytheon.uf.common.serialization.SerializationException; import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.common.serialization.comm.IServerRequest; +import com.raytheon.uf.common.serialization.comm.RequestWrapper; import com.raytheon.uf.common.serialization.comm.response.ServerErrorResponse; import com.raytheon.uf.common.serialization.comm.util.ExceptionWrapper; 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.props.EnvProperties; -import com.raytheon.uf.edex.core.props.PropertiesFactory; +import com.raytheon.uf.common.util.SizeUtil; /** * Wrapper for camel route so Serialization exceptions can be caught and @@ -44,6 +41,7 @@ import com.raytheon.uf.edex.core.props.PropertiesFactory; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Aug 10, 2009 mschenke Initial creation + * Jul 24, 2012 njensen Enhanced logging * * * @@ -52,62 +50,33 @@ import com.raytheon.uf.edex.core.props.PropertiesFactory; */ public class RemoteRequestRouteWrapper { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(RemoteRequestRouteWrapper.class); + + private static final IUFStatusHandler thriftSrvLogger = UFStatus + .getNamedHandler("ThriftSrvRequestLogger"); private RemoteRequestServer server; - private static final int MEGABYTE = 1024 * 1024; - - private static final int timeLogLevel; - - private static final long sizeLogLevel; - - static { - EnvProperties props = PropertiesFactory.getInstance() - .getEnvProperties(); - int tmp = 0; - String prop = props.getEnvValue("REQUEST_TIME_FILTER"); - if (prop != null) { - try { - tmp = Integer.parseInt(prop); - } catch (NumberFormatException e) { - - } - } - timeLogLevel = (tmp <= 0 ? Integer.MAX_VALUE : tmp); - - tmp = 0; - prop = props.getEnvValue("RESPONSE_SIZE_FILTER"); - if (prop != null) { - try { - tmp = Integer.parseInt(prop) * MEGABYTE; - } catch (NumberFormatException e) { - - } - } - sizeLogLevel = (tmp <= 0 ? Integer.MAX_VALUE : tmp); - } - public byte[] executeThrift(byte[] data) { try { long startTime = System.currentTimeMillis(); Object obj = SerializationUtil.transformFromThrift(data); - Object rvalObj = server.handleThriftRequest((IServerRequest) obj); + IServerRequest request = null; + if (obj instanceof RequestWrapper) { + request = ((RequestWrapper) obj).getRequest(); + } else { + request = (IServerRequest) obj; + } + Object rvalObj = server.handleThriftRequest(request); byte[] rval = SerializationUtil.transformToThrift(rvalObj); long endTime = System.currentTimeMillis(); - if (rval.length > sizeLogLevel - || (endTime - startTime) > timeLogLevel) { - DecimalFormat df = new DecimalFormat("0.##"); - statusHandler.handle( - Priority.INFO, - "Request " + obj + " took " + (endTime - startTime) - + "ms, request was size " - + df.format((double) data.length / 1024) - + "kb, and has response size " - + df.format(((double) rval.length / MEGABYTE)) - + "mb"); - } + StringBuilder sb = new StringBuilder(300); + sb.append("Handled ").append(obj.toString()).append(" in ") + .append((endTime - startTime)).append("ms, "); + sb.append("request was size ").append( + SizeUtil.prettyByteSize(data.length)); + sb.append(", response was size ").append( + SizeUtil.prettyByteSize(rval.length)); + thriftSrvLogger.info(sb.toString()); return rval; } catch (AuthException e) { AuthServerErrorResponse resp = new AuthServerErrorResponse(); diff --git a/edexOsgi/com.raytheon.uf.edex.auth/src/com/raytheon/uf/edex/auth/RemoteRequestServer.java b/edexOsgi/com.raytheon.uf.edex.auth/src/com/raytheon/uf/edex/auth/RemoteRequestServer.java index 0d3b4c0f25..d735acef38 100644 --- a/edexOsgi/com.raytheon.uf.edex.auth/src/com/raytheon/uf/edex/auth/RemoteRequestServer.java +++ b/edexOsgi/com.raytheon.uf.edex.auth/src/com/raytheon/uf/edex/auth/RemoteRequestServer.java @@ -44,6 +44,7 @@ import com.raytheon.uf.edex.auth.resp.ResponseFactory; * ------------ ---------- ----------- -------------------------- * Aug 3, 2009 mschenke Initial creation * + * * * * @author mschenke @@ -54,8 +55,6 @@ public class RemoteRequestServer { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(RemoteRequestServer.class); - private static final long LOG_TIME_THRESHOLD = 200; // milliseconds - private static final RemoteRequestServer instance = new RemoteRequestServer(); private HandlerRegistry registry; @@ -131,16 +130,7 @@ public class RemoteRequestServer { } } - long t0 = System.currentTimeMillis(); - String requestAsString = request.toString(); - Object response = handler.handleRequest(request); - long t1 = System.currentTimeMillis(); - long diff = t1 - t0; - if (diff > LOG_TIME_THRESHOLD) { - statusHandler.info("Handled " + requestAsString + " in " + diff - + "ms"); - } - return response; + return handler.handleRequest(request); } public void setRegistry(HandlerRegistry registry) { diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml index 278c919249..7e563040f4 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml @@ -8,13 +8,20 @@ - - + + + + + + + + @@ -35,9 +42,4 @@ - - - - \ No newline at end of file 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 53fabfb6bd..19f24a5ee3 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 @@ -103,6 +103,7 @@ import com.raytheon.uf.edex.plugin.ffmp.common.FFTIProcessor; * ------------ ---------- ----------- -------------------------- * 06/21/2009 2521 dhladky Initial Creation. * 02/03/2011 6500 cjeanbap Fixed NullPointerException. + * 07/31/2011 578 dhladky FFTI modifications * * * @author dhladky @@ -110,1491 +111,1805 @@ import com.raytheon.uf.edex.plugin.ffmp.common.FFTIProcessor; */ public class FFMPGenerator extends CompositeProductGenerator implements - MonitorConfigListener { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(FFMPGenerator.class); + MonitorConfigListener { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(FFMPGenerator.class); - /** - * Public constructor for FFMPGenerator - * - * @param name - * @param compositeProductType - */ - public FFMPGenerator(Executor executor) { + /** + * Public constructor for FFMPGenerator + * + * @param name + * @param compositeProductType + */ + public FFMPGenerator(Executor executor, Executor processexecutor) { - super(genName, productType, executor); - } + super(genName, productType, executor); + this.processexecutor = processexecutor; + } - /** writer thread executor **/ - public Executor writerExecutor = null; + private static final String genName = "FFMP"; - private static final String genName = "FFMP"; + private static final String templateTaskName = "FFMP Template"; - private static final String templateTaskName = "FFMP Template"; + private static final String productType = "ffmp"; - private static final String productType = "ffmp"; + /** ArrayList of domains to filter for */ + private ArrayList domains = null; - /** ArrayList of domains to filter for */ - private ArrayList domains = null; + /** template loader bool **/ + public boolean loaded = false; - /** template loader bool **/ - public boolean loaded = false; + /** check ffg first time you run **/ + public boolean ffgCheck = false; - /** check ffg first time you run **/ - public boolean ffgCheck = false; - - /** ffti finished processing **/ - public boolean fftiDone = true; - - /** products **/ - private ConcurrentHashMap products = null; - - /** Processes map **/ - private ConcurrentHashMap processes = null; - - /** array list of sources to evaluate **/ - public ArrayList fftiSources = new ArrayList(); - - /** run configuration manager **/ - public FFMPRunConfigurationManager frcm = null; - - /** source configuration manager **/ - public FFMPSourceConfigurationManager fscm = null; - - /** temp cache **/ - public ConcurrentHashMap ffmpData = new ConcurrentHashMap(); - - /** FFTI accum/ratio/diff cache **/ - public ConcurrentHashMap fftiData = new ConcurrentHashMap(); - - /** checks for initial load **/ - public ArrayList loadedData = new ArrayList(); - - /** template config manager **/ - public FFMPTemplateConfigurationManager tempConfig = null; - - /** FFMPConfig object **/ - public FFMPConfig config = null; - - /** template **/ - public FFMPTemplates template = null; - - private IPathManager pathManager; - - public static String sharePath = AppsDefaults.getInstance().getToken( - "apps_dir") - + File.separator + "ffmp" + File.separator; - - /** source bins used for finding basin to data correlations **/ - private HashMap sourceBins = new HashMap(); - - @Override - protected void configureFilters() { - - this.pathManager = PathManagerFactory.getPathManager(); - - statusHandler.handle(Priority.DEBUG, getGeneratorName() - + " process Filter Config..."); - domains = new ArrayList(); - boolean configValid = getRunConfig().isPopulated(); - - if (configValid) { - for (FFMPRunXML run : getRunConfig().getFFMPRunners()) { - domains = run.getDomains(); - } - } else { - - /** - * Don't have one, so create an EDEX generated default - */ - LocalizationContext commonStaticSite = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - - List sites = RadarsInUseUtil.getSite(null, - RadarsInUseUtil.LOCAL_CONSTANT); - - FFMPRunXML runner = new FFMPRunXML(); - ArrayList products = new ArrayList(); - // these two are always there in default setups - ProductRunXML hpeProduct = new ProductRunXML(); - hpeProduct.setProductName("DHRMOSAIC"); - hpeProduct.setProductKey("hpe"); - products.add(hpeProduct); - - ProductRunXML biasHpeProduct = new ProductRunXML(); - biasHpeProduct.setProductName("BDHRMOSAIC"); - biasHpeProduct.setProductKey("bhpe"); - products.add(biasHpeProduct); - - ArrayList rfc = new ArrayList(); - - if (sites.isEmpty()) { - RadarStationDao dao = new RadarStationDao(); - List stations = null; - try { - stations = dao.queryByWfo(PropertiesFactory.getInstance() - .getEnvProperties().getEnvValue("SITENAME")); - } catch (DataAccessLayerException e) { - statusHandler - .handle(Priority.ERROR, - "Unable to access data object for radar station table"); - } - - for (RadarStation station : stations) { - // this is just for a default - ProductRunXML dhrProduct = new ProductRunXML(); - dhrProduct.setProductName("DHR"); - dhrProduct.setProductKey(station.getRdaId().toLowerCase()); - products.add(dhrProduct); - - String newRfc = FFMPUtils - .getRFC(dhrProduct.getProductKey()); - if (!rfc.contains(newRfc)) { - rfc.add(newRfc); - } - - sites.add(station.getRdaId().toLowerCase()); - } - - } else { - for (String site : sites) { - // this is just for a default - ProductRunXML dhrProduct = new ProductRunXML(); - dhrProduct.setProductName("DHR"); - dhrProduct.setProductKey(site); - products.add(dhrProduct); - - String newRfc = FFMPUtils - .getRFC(dhrProduct.getProductKey()); - if (!rfc.contains(newRfc)) { - rfc.add(newRfc); - } - } - } - - runner.setProducts(products); - - // Apply site list to all QPE types - for (String source : getSourceConfig().getQPESources()) { - SourceXML qpeSource = getSourceConfig().getSource(source); - // Radar Derived sources use the primary source site keys for - // mosiac datakey - // Auto Config for any Radar derived sources - if (qpeSource.getDataType().equals( - DATA_TYPE.RADAR.getDataType())) { - SourceIngestConfigXML sicm = new SourceIngestConfigXML(); - sicm.setSourceName(qpeSource.getSourceName()); - sicm.setUriSubLocation(3); - - for (String siteid : sites) { - sicm.addDataKey(siteid); - } - - runner.addSourceIngest(sicm); - } - } - - // We have a list of available RFC's, now find mosaic - // Apply this to all RFCFFG sources - for (String source : getSourceConfig().getGuidances()) { - SourceXML guidSource = getSourceConfig().getSource(source); - - // Auto config for RFC sources - if (guidSource.isRfc()) { - // add a source mosaic config to the Run Config - SourceIngestConfigXML sicm = new SourceIngestConfigXML(); - sicm.setSourceName(guidSource.getSourceName()); - sicm.setUriSubLocation(3); - - for (String dataKey : rfc) { - sicm.addDataKey(dataKey); - } - - runner.addSourceIngest(sicm); - } - } - - // Apply site list to all SCANQPF default - for (String source : getSourceConfig().getQPFSources()) { - SourceXML qpfSource = getSourceConfig().getSource(source); - // Radar Derived sources use the primary source site keys for - // mosiac datakey - // Auto Config for any Radar derived sources (QPFSCAN) for - // example - if (qpfSource.getSourceName().equals("QPFSCAN")) { - SourceIngestConfigXML sicm = new SourceIngestConfigXML(); - sicm.setSourceName(qpfSource.getSourceName()); - sicm.setUriSubLocation(3); - - for (String siteid : sites) { - sicm.addDataKey(siteid); - } - - runner.addSourceIngest(sicm); - } - } - - DomainXML domain = new DomainXML(); - domain.setPrimary(true); - domain.setCwa(commonStaticSite.getContextName()); - runner.addDomain(domain); - - getRunConfig().addFFMPRunner(runner); - getRunConfig().saveConfigXml(); - getRunConfig().setPopulated(true); - - domains.add(domain); - } - - // kick off template generation - this.getExecutor().execute(new TemplateLoader(domains)); - } - - @Override - protected void createFilters() { - // do more here if you wish - - ArrayList runners = getRunConfig().getFFMPRunners(); - ArrayList tmp = new ArrayList( - runners.size()); - - for (FFMPRunXML runner : runners) { - DomainXML domain = runner.getPrimaryDomain(); - try { - tmp.add(new FFMPURIFilter(getSiteString(runner) + ":" - + getRFCString(runner) + ":" + domain.getCwa())); - - statusHandler.handle(Priority.INFO, "Created FFMP Filter.." - + " primary Domain: " + domain.getCwa()); - } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, - "Couldn't create FFMP Filter.." + " primary Domain: " - + domain.getCwa() - + " this RUNNER is not a viable FFMP config."); - e.printStackTrace(); - } - } - - filters = tmp.toArray(new URIFilter[tmp.size()]); - - } - - /** - * Slight difference in the way ffmp operates as opposed to the URIFilter in - * general. - */ - @Override - public void matchURIs(DataURINotificationMessage messages) { - - 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]; - - if (loaded) { - - synchronized (filter) { - - if (filter.isMatched(messages)) { - - if (!ffgCheck) { - - filter = getFFG(filter); - filter.setValidTime(filter - .getCurrentTime()); - ffgCheck = true; - } - - dispatch(filter); - } - } - } else { - statusHandler - .debug(getGeneratorName() - + ": templates not loaded yet. Skipping product"); - } - } - } - } - } - } - - @Override - public void generateProduct(URIGenerateMessage genMessage) { - if (loaded) { - try { - long time = System.currentTimeMillis(); - this.config = new FFMPConfig( - (FFMPURIGenerateMessage) genMessage, this); - products = new ConcurrentHashMap(); - processes = new ConcurrentHashMap(); - // read config updates, make sure we don't miss something - getRunConfig().readConfigXml(); - getSourceConfig().readConfigXml(); - - if (config.getSources() != null) { - for (String source : config.getSources().keySet()) { - processes.put(source, - getSourceConfig().getSource(source)); - } - } - - // start threads - - for (String source : processes.keySet()) { - this.getExecutor().execute( - new ProcessProduct(processes.get(source), this)); - } - - // count down latch - while (processes.size() > 0) { - // wait for all threads to finish before returning - try { - Thread.sleep(100); - statusHandler.handle(Priority.DEBUG, - "Checking status ..." + processes.size()); - for (String source : processes.keySet()) { - statusHandler.handle(Priority.DEBUG, - "Still processing ..." + source); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - if (products.size() > 0) { - - // Do the FFTI evaluation, if we have FFTI sources - if (fftiSources.size() > 0) { - this.getExecutor().execute(new FFTI(this)); - } - - ArrayList records = new ArrayList( - products.size()); - for (String source : products.keySet()) { - for (FFMPRecord rec : products.get(source)) { - records.add(rec); - } - } - - FFMPRecord[] recs = new FFMPRecord[records.size()]; - for (int i = 0; i < records.size(); i++) { - recs[i] = records.get(i); - } - - this.setPluginDataObjects(recs); - this.setPluginDao(new FFMPDao(getCompositeProductType(), - template, fscm, config.getCWA())); - - while (fftiSources.size() > 0) { - try { - Thread.sleep(100); - statusHandler.handle(Priority.DEBUG, - "Checking status ..." + fftiDone); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - statusHandler.handle( - Priority.INFO, - config.getCWA() + " finished, duration: " - + (System.currentTimeMillis() - time) - + " ms, wrote " + records.size() + " "); - - } else { - statusHandler.handle(Priority.INFO, config.getCWA() - + " no new products to produce."); - } - // dump data we don't need anymore - ffmpData.clear(); - - } catch (Throwable e) { - statusHandler.handle(Priority.ERROR, - "Unable to process FFMP Records."); - e.printStackTrace(); - } - } - } - - /** - * Get the list of domains - * - * @return - */ - public ArrayList getDomains() { - return domains; - } - - /** - * Add a filtering CWA - * - * @param domain - */ - public void addDomain(DomainXML domain) { - domains.add(domain); - } - - @Override - public boolean isRunning() { - return getConfigManager().getFFMPState(); - } - - /** - * Set list of CWA's - * - * @param cwas - */ - public void setDomains(ArrayList domains) { - this.domains = domains; - } - - /** - * Inner class to thread the ffmp processing - * - * @author dhladky - * - */ - private class ProcessProduct implements Runnable { - - SourceXML ffmpProduct; - - FFMPGenerator generator; - - @Override - public void run() { - try { - logger.debug("ProcessProduct: Starting thread " - + ffmpProduct.getSourceName()); - process(); - logger.debug("ProcessProduct: Finishing thread " - + ffmpProduct.getSourceName()); - } catch (Exception e) { - processes.remove(ffmpProduct.getSourceName()); - logger.error("ProcessProduct: removed " - + ffmpProduct.getSourceName()); - e.printStackTrace(); - } - } - - public ProcessProduct(SourceXML ffmpProduct, FFMPGenerator generator) { - this.ffmpProduct = ffmpProduct; - this.generator = generator; - } - - /** - * The actual work gets done here - */ - public void process() throws Exception { - - HashMap dataHash = config.getSourceData(ffmpProduct - .getSourceName()); - ArrayList ffmpRecords = new ArrayList( - dataHash.size()); - - FFMPRunXML runner = getRunConfig().getRunner(config.getCWA()); - - // process all of the dataKeys for this source - for (String dataKey : dataHash.keySet()) { - - ArrayList sites = new ArrayList(); - - // is it a mosaic? - if (ffmpProduct.isMosaic()) { - - // Take care of defaults, all in this case - for (ProductRunXML product : runner.getProducts()) { - // no duplicate keys! - if (!sites.contains(product.getProductKey())) { - sites.add(product.getProductKey()); - } - } - - // do filtering - for (ProductRunXML product : runner.getProducts()) { - // includes - if (product.hasIncludes()) { - for (String includeSourceName : product - .getIncludes()) { - if (ffmpProduct.getSourceName().equals( - includeSourceName)) { - // no duplicate keys! - if (!sites - .contains(product.getProductKey())) { - sites.add(product.getProductKey()); - } - } - } - } - // excludes - if (product.hasExcludes()) { - for (String excludeSourceName : product - .getExcludes()) { - if (ffmpProduct.getSourceName().equals( - excludeSourceName)) { - sites.remove(product.getProductKey()); - } - } - } - } - } else { - // No mosaic, just individual site run - String siteKey = dataKey; - - // special case for XMRG's - if (ffmpProduct.getDataType().equals( - FFMPSourceConfigurationManager.DATA_TYPE.XMRG - .getDataType())) { - - siteKey = null; - String primarySource = null; - - for (ProductXML product : getSourceConfig() - .getProducts()) { - if (product.containsSource(ffmpProduct - .getSourceName())) { - primarySource = product.getPrimarySource(); - break; - } - } - - for (ProductRunXML productRun : runner.getProducts()) { - if (productRun.getProductName().equals( - primarySource)) { - siteKey = productRun.getProductKey(); - break; - } - } - } - - sites.add(siteKey); - } - - for (String productKey : sites) { - - FFMPRecord ffmpRec = new FFMPRecord(); - ffmpRec.setSourceName(ffmpProduct.getSourceName()); - ffmpRec.setDataKey(dataKey); - ffmpRec.setSiteKey(productKey); - ffmpRec.setPluginName(getCompositeProductType()); - ffmpRec.setWfo(config.getCWA()); - FFMPProcessor ffmp = new FFMPProcessor(config, generator, - ffmpRec, template); - ffmpRec = ffmp.processFFMP(ffmpProduct); - ffmpRec.constructDataURI(); - - if (ffmpRec != null) { - - // Don't write loader buddy's on long duration - // sources. Not necessary 6*60 = 360 - if (getSourceConfig() - .getSource(ffmpRec.getSourceName()) - .getExpirationMinutes(productKey) < 360) { - - processDataContainer(ffmpRec); - } - - if (ffmp.isFFTI()) { - fftiDone = false; - if (!fftiSources.contains(ffmp.getFFTISource())) { - FFTIProcessor ffti = new FFTIProcessor( - generator, ffmpRec, - ffmp.getFFTISource()); - fftiSources.add(ffmp.getFFTISource()); - ffti.processFFTI(); - } - } - - ffmpRecords.add(ffmpRec); - } - } - } - - FFMPRecord[] recs = new FFMPRecord[ffmpRecords.size()]; - for (int i = 0; i < ffmpRecords.size(); i++) { - recs[i] = ffmpRecords.get(i); - } - products.put(ffmpProduct.getSourceName(), recs); - processes.remove(ffmpProduct.getSourceName()); - } - } - - /** - * Inner class to background template creation - * - * @author dhladky - * - */ - private class TemplateLoader implements Runnable { - - ArrayList templateDomains; - - DomainXML primaryDomain; - - @Override - public void run() { - statusHandler.handle(Priority.DEBUG, getGeneratorName() - + " Start loader "); - - for (DomainXML domain : templateDomains) { - if (domain.isPrimary()) { - primaryDomain = domain; - } - } - - // generate templates and unify geometries - loaded = load(); - statusHandler.handle(Priority.DEBUG, getGeneratorName() - + " Finishing loader "); - } - - public TemplateLoader(ArrayList templateDomains) { - this.templateDomains = templateDomains; - } - - /** - * - * @param domain - * @return - */ - public void createUnifiedGeometries(DomainXML domain) { - ArrayList hucsToGen = new ArrayList(); - hucsToGen.add("ALL"); - hucsToGen.add("COUNTY"); - - for (int i = template.getTotalHucLevels() - 1; i >= 0; i--) { - hucsToGen.add("HUC" + i); - } - - for (String huc : hucsToGen) { - template.verifyUnifiedGeometries(huc, domain.getCwa()); - } - } - - public boolean load() { - // load / create primary domain - ClusterTask task = null; - String lockDetails = getGeneratorName() + ":" - + primaryDomain.getCwa() + ":" + primaryDomain.getCwa(); - try { - do { - task = ClusterLockUtils.lock(templateTaskName, lockDetails, - 600 * 1000, true); - } while (task.getLockState() != LockState.SUCCESSFUL); - - template = FFMPTemplates.getInstance(primaryDomain, MODE.EDEX); - // setup the config - getTemplateConfig(); - createUnifiedGeometries(primaryDomain); - } finally { - if ((task != null) - && (task.getLockState() == LockState.SUCCESSFUL)) { - ClusterLockUtils.unlock(task, false); - } - } - - // load the secondary domains - List domainsToGen = new ArrayList( - templateDomains); - while (domainsToGen.size() > 0) { - Iterator iter = domainsToGen.iterator(); - boolean processedDomain = false; - while (iter.hasNext()) { - DomainXML domain = iter.next(); - lockDetails = getGeneratorName() + ":" - + primaryDomain.getCwa() + ":" + domain.getCwa(); - try { - task = ClusterLockUtils.lock(templateTaskName, - lockDetails, 300 * 1000, false); - - if (task.getLockState() == LockState.SUCCESSFUL) { - template.addDomain(domain); - createUnifiedGeometries(domain); - iter.remove(); - processedDomain = true; - } - } finally { - if ((task != null) - && (task.getLockState() == LockState.SUCCESSFUL)) { - ClusterLockUtils.unlock(task, false); - } - } - } - - if (!processedDomain) { - // Didn't process a domain, locked by another cluster - // member, sleep and try again - try { - Thread.sleep(100); - } catch (InterruptedException e) { - - } - } - } - - return template.done; - } - } - - /** - * Gets the string buffer for the RFC's - * - * @param run - * @return - */ - private String getRFCString(FFMPRunXML run) { - StringBuffer buf = new StringBuffer(); - - for (SourceIngestConfigXML ingest : run.getSourceIngests()) { - SourceXML source = FFMPSourceConfigurationManager.getInstance() - .getSource(ingest.getSourceName()); - if (source.isRfc()) { - int i = 0; - for (String dataKey : ingest.getDataKey()) { - if (i < ingest.getDataKey().size() - 1) { - buf.append(dataKey + ","); - } else { - buf.append(dataKey); - } - i++; - } - break; - } - } - return buf.toString(); - } - - /** - * Gets the string buffer for the sites, specific to RADAR type data - * - * @param run - * @return - */ - private String getSiteString(FFMPRunXML run) { - String sites = null; - StringBuffer buf = new StringBuffer(); - for (ProductRunXML product : run.getProducts()) { - SourceXML source = getSourceConfig().getSource( - product.getProductName()); - if (source.getDataType().equals(DATA_TYPE.RADAR.getDataType())) { - buf.append(product.getProductKey() + ","); - } - } - sites = buf.toString(); - if (sites.endsWith(",")) { - sites = sites.substring(0, sites.length() - 1); - } - return sites; - } - - /** - * Write your new SourceBins - * - * @param sourceList - */ - public void writeSourceBins(SourceBinList sourceList) { - - try { - LocalizationContext lc = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - - LocalizationFile lflist = pathManager.getLocalizationFile(lc, - getAbsoluteFileName(sourceList.getSourceId())); - - FileUtil.bytes2File( - SerializationUtil.transformToThrift(sourceList), - lflist.getFile(), true); - - lflist.save(); - - statusHandler.handle(Priority.INFO, "Wrote FFMP source Bin File: " - + sourceList.getSourceId()); - - } catch (SerializationException se) { - se.printStackTrace(); - } catch (FileNotFoundException fnfe) { - fnfe.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } catch (LocalizationOpFailedException e) { - e.printStackTrace(); - } - } - - /** - * Read out your SourceBins - * - * @param sourceId - * @return - */ - public SourceBinList readSourceBins(String sourceId) { - - SourceBinList sbl = null; - LocalizationContext lc = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - LocalizationFile f = pathManager.getLocalizationFile(lc, - getAbsoluteFileName(sourceId)); - - try { - sbl = (SourceBinList) SerializationUtil - .transformFromThrift(FileUtil.file2bytes(f.getFile(), true)); - } catch (FileNotFoundException fnfe) { - statusHandler.handle(Priority.ERROR, - "Unable to locate file " + f.getName()); - } catch (SerializationException se) { - statusHandler.handle(Priority.ERROR, - "Unable to read file " + f.getName()); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - - return sbl; - } - - /** - * Gets the completed filename - * - * @return - */ - public String getAbsoluteFileName(String sourceId) { - return "ffmp" + File.separator + "sources" + File.separator + sourceId - + ".bin"; - } - - /** - * See if you have one - * - * @param sourceId - * @return - */ - public boolean isExistingSourceBin(String sourceId) { - LocalizationContext lc = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - LocalizationFile f = pathManager.getLocalizationFile(lc, - getAbsoluteFileName(sourceId)); - return f.exists(); - } - - /** - * Gets the list of bins for that source - * - * @param sourceId - * @return - */ - public SourceBinList getSourceBinList(String sourceId) { - SourceBinList sbl = null; - if (!sourceBins.containsKey(sourceId)) { - sbl = readSourceBins(sourceId); - sourceBins.put(sourceId, sbl); - } else { - sbl = sourceBins.get(sourceId); - } - - return sbl; - } - - /** - * Sets the source bins, first time - * - * @param sbl - */ - public void setSourceBinList(SourceBinList sbl) { - sourceBins.put(sbl.getSourceId(), sbl); - writeSourceBins(sbl); - } - - /** - * Do pull strategy on FFG data - * - * @param filter - * @return - */ - private FFMPURIFilter getFFG(FFMPURIFilter filter) { - - ArrayList uris = new ArrayList(); - - for (String rfc : filter.getRFC()) { - // get a hash of the sources and their grib ids - HashMap sources = FFMPUtils.getFFGModelInfo(rfc); - if (sources != null) { - if (sources.size() > 0) { - for (String source : sources.keySet()) { - - SourceXML sourceXml = getSourceConfig().getSource( - source); - - if (sourceXml != null) { - - String plugin = getSourceConfig().getSource(source) - .getPlugin(); - uris.add(FFMPUtils.getFFGDataURI( - sources.get(source), plugin)); - } - } - } - } - } - // treat it like a regular uri in the filter. - if (uris.size() > 0) { - for (String dataUri : uris) { - // add your pattern checks to the key - for (Pattern pattern : filter.getMatchURIs().keySet()) { - statusHandler.handle(Priority.DEBUG, - "Pattern: " + pattern.toString() + " Key: " - + dataUri); - try { - if (pattern.matcher(dataUri).find()) { - // matches one of them, which one? - String matchKey = filter.getPatternName(pattern); - // put the sourceName:dataPath key into the sources - // array list - filter.getSources().put(matchKey, dataUri); - } - } catch (Exception e) { - statusHandler.handle( - Priority.ERROR, - "Unable to locate new FFG file. " - + pattern.toString()); - } - } - } - } - - return filter; - } - - /** - * get the FFMP data container for this source - * - * @param sourceName - * - * @return - */ - - public FFMPDataContainer getFFMPDataContainer(String siteSourceKey, ArrayList hucs, Date backDate) { - - FFMPDataContainer container = ffmpData.get(siteSourceKey); - - if (container == null) { - - String siteKey = null; - - String[] parts = siteSourceKey.split("-"); - - if (parts.length > 1) { - siteKey = parts[0]; - } - - container = loadFFMPDataContainer(siteSourceKey, - - hucs, siteKey, - - config.getCWA(), backDate); - - if (container != null) { - ffmpData.put(siteSourceKey, container); - } - } - - return container; - } - - /* - * Gets the FFTI sources to be run - */ - public ArrayList getFFTISources() { - return fftiSources; - } - - /** - * source config manager - * - * @return - */ - public FFMPSourceConfigurationManager getSourceConfig() { - if (fscm == null) { - fscm = FFMPSourceConfigurationManager.getInstance(); - fscm.addListener(this); - } - return fscm; - } - - /** - * run config manager - * - * @return - */ - public FFMPRunConfigurationManager getRunConfig() { - if (frcm == null) { - frcm = FFMPRunConfigurationManager.getInstance(); - frcm.addListener(this); - } - return frcm; - } - - /** - * Template config manager - * - * @return - */ - public FFMPTemplateConfigurationManager getTemplateConfig() { - if (tempConfig == null) { - tempConfig = FFMPTemplateConfigurationManager.getInstance(); - tempConfig.addListener(this); - } - return tempConfig; - } - - /** - * dispatch a filter for processing - * - * @param filter - */ - private void dispatch(FFMPURIFilter filter) { - - try { - EDEXUtil.getMessageProducer().sendAsync( - routeId, - SerializationUtil.transformToThrift(filter - .createGenerateMessage())); - } catch (Exception e) { - statusHandler.handle(Priority.ERROR, getGeneratorName() - + ": filter: " + filter.getName() - + ": failed to route filter to generator", e); - e.printStackTrace(); - } - - filter.setValidTime(new Date(System.currentTimeMillis())); - filter.reset(); - } - - /** - * FFMP buddy loader - * - * @param ffmpRec - * @param siteKey - */ - private void processDataContainer(FFMPRecord ffmpRec) { - - // write out the fast loader buddy file - SourceXML source = getSourceConfig().getSource(ffmpRec.getSourceName()); - String sourceName = null; - String dataKey = null; - - if (source.getSourceType().equals(SOURCE_TYPE.GUIDANCE.getSourceType())) { - sourceName = source.getDisplayName(); - dataKey = SOURCE_TYPE.GUIDANCE.getSourceType(); - } else { - sourceName = ffmpRec.getSourceName(); - dataKey = ffmpRec.getDataKey(); - } - - String sourceSiteDataKey = sourceName + "-" + ffmpRec.getSiteKey() - + "-" + dataKey; - - // Make a 6 hour "Buddy" loader file - Date backDate = new Date(ffmpRec.getDataTime().getRefTime().getTime() - - (3600 * 1000 * 6)); - - ArrayList hucs = template.getTemplateMgr().getHucLevels(); - - if (source.getSourceType().equals(SOURCE_TYPE.GAGE.getSourceType())) { - hucs.clear(); - hucs.add("ALL"); - } else { - hucs.remove("VIRTUAL"); - } - - // pull from disk if there - FFMPDataContainer fdc = loadFFMPDataContainer(sourceSiteDataKey, - hucs, ffmpRec.getSiteKey(), - ffmpRec.getWfo(), backDate); - - // brand new or initial load up - if (fdc == null || !loadedData.contains(sourceSiteDataKey)) { - - long time = System.currentTimeMillis(); - fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); - fdc = FFTIProcessor.populateDataContainer(fdc, template, hucs, backDate, ffmpRec.getDataTime() - .getRefTime(), ffmpRec.getWfo(), source, ffmpRec.getSiteKey()); - loadedData.add(sourceSiteDataKey); - long time2 = System.currentTimeMillis(); - statusHandler.handle(Priority.INFO, - "Populated new source: in " + (time2 - time) - + " ms: source: " + sourceSiteDataKey); - - } else { - // guidance sources are treated as a mosaic and are handled differently - // This is the main line sequence a source will take when updated. - if (!source.getSourceType().equals( - SOURCE_TYPE.GUIDANCE.getSourceType())) { - - long time = System.currentTimeMillis(); - Date newDate = fdc.getNewest(); - Date oldDate = fdc.getOldest(); - - if (newDate != null && oldDate != null) { - if ((ffmpRec.getDataTime().getRefTime().getTime() - newDate - .getTime()) >= (source.getExpirationMinutes(ffmpRec - .getSiteKey()) * 60 * 1000)) { - // force a re-query back to the newest time in - // existing source container, this will fill in gaps if - // they exist. - fdc = FFTIProcessor.populateDataContainer(fdc, - template, null, newDate, ffmpRec.getDataTime() - .getRefTime(), ffmpRec.getWfo(), - source, ffmpRec.getSiteKey()); - - } else if (oldDate.after(new Date( - backDate.getTime() - - (source.getExpirationMinutes(ffmpRec - .getSiteKey()) * 60 * 1000)))) { - // force a re-query back to barrierTime for - // existing source container, this happens if the - // ingest was turned off for some period of time. - fdc = FFTIProcessor.populateDataContainer(fdc, - template, null, backDate, oldDate, - ffmpRec.getWfo(), source, ffmpRec.getSiteKey()); - } - } - long time2 = System.currentTimeMillis(); - statusHandler.handle(Priority.INFO, - "Checked Source files: in " + (time2 - time) - + " ms: source: " + sourceSiteDataKey); - - // purge it up - fdc.purge(backDate); - } - } - - // add current record data - for (String huc : ffmpRec.getBasinsMap().keySet()) { - fdc.addFFMPEntry(ffmpRec.getDataTime().getRefTime(), source, - ffmpRec.getBasinData(huc), huc, ffmpRec.getSiteKey()); - } - - // set the name - fdc.setFilePath("" + sharePath + ffmpRec.getWfo() + "/"+ sourceSiteDataKey); - // cache it temporarily for FFTI use - ffmpData.put(sourceSiteDataKey, fdc); - // write it out - writeLoaderBuddyFiles(fdc); - } - - /** - * load existing container - * - * @param sourceSiteDataKey - * @param hucs - * @param siteKey - * @param wfo - * @return - */ - public FFMPDataContainer loadFFMPDataContainer(String sourceSiteDataKey, - ArrayList hucs, String siteKey, String wfo, Date backDate) { - - long time = System.currentTimeMillis(); - FFMPDataContainer fdc = null; - - for (String huc : hucs) { - - FFMPBasinData basinData = null; - - if (checkBuddyFile(sourceSiteDataKey, huc, wfo, backDate)) { - basinData = readLoaderBuddyFile(sourceSiteDataKey, huc, wfo, - backDate); - - if (fdc == null) { - fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); - } - } - - if (basinData != null) { - fdc.setBasinBuddyData(basinData, huc); - } - } - - if (fdc != null) { - long time2 = System.currentTimeMillis(); - statusHandler.handle(Priority.DEBUG, "Loaded Source files: in " - + (time2 - time) + " ms: source: " + sourceSiteDataKey); - } - - return fdc; - } - - /** - * Load existing buddy file - * - * @param sourceSiteDataKey - * @param huc - * @param wfo - * @return - */ - private FFMPBasinData readLoaderBuddyFile(String sourceSiteDataKey, - String huc, String wfo, Date backDate) { - - File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" - + huc + ".bin"); - FFMPBasinData basinData = null; - - try { - BufferedInputStream is = new BufferedInputStream( - new FileInputStream(file)); - DynamicSerializationManager dsm = DynamicSerializationManager - .getManager(SerializationType.Thrift); - basinData = (FFMPBasinData) dsm.deserialize(is); - is.close(); - } catch (SerializationException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return basinData; - - } - - /** - * Write buddy file - * - * @param sourceSiteDataKey - * @param huc - * @param wfo - * @return - */ - public void writeLoaderBuddyFiles(FFMPDataContainer fdc) { - - // Write all huc levels in separate files - File fileDir = new File("" + sharePath + config.getCWA()); - if (!fileDir.exists()) { - fileDir.mkdir(); - } - - WriteFiles writer = new WriteFiles(fdc); - writer.run(); - } - - /** - * Inner class to thread writing of BuddyFiles - * - * @author dhladky - * - */ - private class WriteFiles implements Runnable { - - private FFMPDataContainer fdc; - - public void run() { - try { - long time = System.currentTimeMillis(); - write(); - long time2 = System.currentTimeMillis(); - statusHandler.handle(Priority.DEBUG, - "Wrote loader files: in " + (time2 - time) - + " ms"); - } catch (Exception e) { - statusHandler.handle(Priority.ERROR, - "WriteFile: removed " + e.getMessage()); - } - } - - public WriteFiles(FFMPDataContainer fdc) { - this.fdc = fdc; - statusHandler.handle(Priority.DEBUG, "Created FileWriter"); - } - - /** - * The actual work gets done here - */ - public void write() throws Exception { - - try { - - String fileName = fdc.getFilePath(); - // lock for atomic write and read - HashMap fileNames = new HashMap(); - File lockfile = new File(fileName + ".lock"); - lockfile.createNewFile(); - - try { - - for (String huc : fdc.getKeys()) { - - FFMPBasinData fbd = fdc.getBasinData(huc); - - if (fbd.getBasins().size() > 0) { - - String tmpFilePath = fileName + "-" + huc + ".tmp"; - fileNames.put(tmpFilePath, fileName + "-" + huc - + ".bin"); - BufferedOutputStream os = null; - - try { - File file = new File(tmpFilePath); - os = new BufferedOutputStream( - new FileOutputStream(file)); - DynamicSerializationManager dsm = DynamicSerializationManager - .getManager(SerializationType.Thrift); - dsm.serialize(fbd, os); - } catch (SerializationException e) { - statusHandler.handle(Priority.ERROR, - "Serialization Error Writing buddy file: " - + e.getMessage()); - } catch (IOException e) { - statusHandler.handle( - Priority.ERROR, - "IO Error Writing buddy file: " - + e.getMessage()); - } finally { - if (os != null) { - os.close(); - } - } - } - } - } catch (Exception e) { - statusHandler - .handle(Priority.ERROR, - "Error writing Buddy File group: " - + e.getMessage()); - } finally { - // rename the files to real path - try { - for (String tmpName : fileNames.keySet()) { - File file = new File(tmpName); - file.renameTo(new File(fileNames.get(tmpName))); - } - - lockfile.delete(); - - } catch (Exception e) { - statusHandler.handle( - Priority.ERROR, - "IO Error Renaming buddy file: " - + e.getMessage()); - } - } - - } catch (Exception e) { - statusHandler.handle(Priority.ERROR, - "IO Error writing buddy files: " + e.getMessage()); - } - } - } - - /** - * Load existing buddy file - * - * @param sourceSiteDataKey - * @param huc - * @param wfo - * @return - */ - public boolean checkBuddyFile(String sourceSiteDataKey, String huc, - String wfo, Date backDate) { - - File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" - + huc + ".bin"); - - if (file.exists() && (file.lastModified() > backDate.getTime())) { - // System.out.println("File update and exists..."+sourceSiteDataKey); - return true; - } - - return false; - - } - - @Override - public synchronized void configChanged(MonitorConfigEvent fce) { - - boolean reload = false; - - if (fce.getSource() instanceof FFMPTemplateConfigurationManager) { - statusHandler - .handle(Priority.INFO, - "Re-configuring FFMP & URI filters...Template Config change"); - reload = true; - FFMPTemplateConfigurationManager ftcm = (FFMPTemplateConfigurationManager) fce - .getSource(); - if (ftcm.isRegenerate()) { - template.dumpTemplates(); - } - - tempConfig = null; - - } else if (fce.getSource() instanceof FFMPRunConfigurationManager) { - statusHandler.handle(Priority.INFO, - "Re-configuring FFMP & URI filters...Run Config change"); - reload = true; - frcm = null; - } - - else if (fce.getSource() instanceof FFMPSourceConfigurationManager) { - statusHandler.handle(Priority.INFO, - "Re-configuring FFMP & URI filters...Source Config change"); - reload = true; - fscm = null; - } - - if (reload) { - - ffgCheck = false; - resetFilters(); - - if (sourceBins != null) { - sourceBins.clear(); - } - - loadedData.clear(); - - DatMenuUtil dmu = new DatMenuUtil(); - dmu.setDatSite(PropertiesFactory.getInstance().getEnvProperties() - .getEnvValue("SITENAME")); - dmu.setOverride(true); - dmu.createMenus(); - } - } - - /** - * FFTI data cache - * @param ffti - */ - public void addFFTIData(String fftiName, FFTIData ffti) { - if (fftiData.containsKey(fftiName)) { - fftiData.replace(fftiName, ffti); - } else { - fftiData.put(fftiName, ffti); - } - } - - /** - * Get FFTI data cache - * @param fftiName - * @return - */ - public FFTIData getFFTIData(String fftiName) { - return fftiData.get(fftiName); - } - - /** - * Check existence - * @param fftiName - * @return - */ - public boolean isFFTI(String fftiName) { - return fftiData.containsKey(fftiName); - } - - /** - * get the whole container - * @return - */ - public ConcurrentHashMap getFFTIDataContainer() { - return fftiData; - } - -} \ No newline at end of file + /** ffti finished processing **/ + public boolean fftiDone = true; + + /** products **/ + private ConcurrentHashMap products = null; + + /** Processes map **/ + private ConcurrentHashMap processes = null; + + /** array list of sources to evaluate **/ + public ArrayList fftiSources = new ArrayList(); + + /** run configuration manager **/ + public FFMPRunConfigurationManager frcm = null; + + /** source configuration manager **/ + public FFMPSourceConfigurationManager fscm = null; + + /** temp cache **/ + public ConcurrentHashMap ffmpData = new ConcurrentHashMap(); + + /** FFTI accum/ratio/diff cache **/ + public ConcurrentHashMap fftiData = new ConcurrentHashMap(); + + /** checks for initial load **/ + public ArrayList loadedData = new ArrayList(); + + /** thread the productkeys **/ + public HashMap> productKeys = new HashMap>(); + + /** template config manager **/ + public FFMPTemplateConfigurationManager tempConfig = null; + + /** FFMPConfig object **/ + public FFMPConfig config = null; + + /** template **/ + public FFMPTemplates template = null; + + private IPathManager pathManager; + + public static String sharePath = AppsDefaults.getInstance().getToken( + "apps_dir") + + File.separator + "ffmp" + File.separator; + + /** source bins used for finding basin to data correlations **/ + private HashMap sourceBins = new HashMap(); + + /** thread executor **/ + public Executor processexecutor = null; + + @Override + protected void configureFilters() { + + this.pathManager = PathManagerFactory.getPathManager(); + + statusHandler.handle(Priority.DEBUG, getGeneratorName() + + " process Filter Config..."); + domains = new ArrayList(); + boolean configValid = getRunConfig().isPopulated(); + + if (configValid) { + for (FFMPRunXML run : getRunConfig().getFFMPRunners()) { + domains = run.getDomains(); + } + } else { + + /** + * Don't have one, so create an EDEX generated default + */ + LocalizationContext commonStaticSite = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + + List sites = RadarsInUseUtil.getSite(null, + RadarsInUseUtil.LOCAL_CONSTANT); + + FFMPRunXML runner = new FFMPRunXML(); + ArrayList products = new ArrayList(); + // these two are always there in default setups + ProductRunXML hpeProduct = new ProductRunXML(); + hpeProduct.setProductName("DHRMOSAIC"); + hpeProduct.setProductKey("hpe"); + products.add(hpeProduct); + + ProductRunXML biasHpeProduct = new ProductRunXML(); + biasHpeProduct.setProductName("BDHRMOSAIC"); + biasHpeProduct.setProductKey("bhpe"); + products.add(biasHpeProduct); + + ArrayList rfc = new ArrayList(); + + if (sites.isEmpty()) { + RadarStationDao dao = new RadarStationDao(); + List stations = null; + try { + stations = dao.queryByWfo(PropertiesFactory.getInstance() + .getEnvProperties().getEnvValue("SITENAME")); + } catch (DataAccessLayerException e) { + statusHandler + .handle(Priority.ERROR, + "Unable to access data object for radar station table"); + } + + for (RadarStation station : stations) { + // this is just for a default + ProductRunXML dhrProduct = new ProductRunXML(); + dhrProduct.setProductName("DHR"); + dhrProduct.setProductKey(station.getRdaId().toLowerCase()); + products.add(dhrProduct); + + String newRfc = FFMPUtils + .getRFC(dhrProduct.getProductKey()); + if (!rfc.contains(newRfc)) { + rfc.add(newRfc); + } + + sites.add(station.getRdaId().toLowerCase()); + } + + } else { + for (String site : sites) { + // this is just for a default + ProductRunXML dhrProduct = new ProductRunXML(); + dhrProduct.setProductName("DHR"); + dhrProduct.setProductKey(site); + products.add(dhrProduct); + + String newRfc = FFMPUtils + .getRFC(dhrProduct.getProductKey()); + if (!rfc.contains(newRfc)) { + rfc.add(newRfc); + } + } + } + + runner.setProducts(products); + + // Apply site list to all QPE types + for (String source : getSourceConfig().getQPESources()) { + SourceXML qpeSource = getSourceConfig().getSource(source); + // Radar Derived sources use the primary source site keys for + // mosiac datakey + // Auto Config for any Radar derived sources + if (qpeSource.getDataType().equals( + DATA_TYPE.RADAR.getDataType())) { + SourceIngestConfigXML sicm = new SourceIngestConfigXML(); + sicm.setSourceName(qpeSource.getSourceName()); + sicm.setUriSubLocation(3); + + for (String siteid : sites) { + sicm.addDataKey(siteid); + } + + runner.addSourceIngest(sicm); + } + } + + // We have a list of available RFC's, now find mosaic + // Apply this to all RFCFFG sources + for (String source : getSourceConfig().getGuidances()) { + SourceXML guidSource = getSourceConfig().getSource(source); + + // Auto config for RFC sources + if (guidSource.isRfc()) { + // add a source mosaic config to the Run Config + SourceIngestConfigXML sicm = new SourceIngestConfigXML(); + sicm.setSourceName(guidSource.getSourceName()); + sicm.setUriSubLocation(3); + + for (String dataKey : rfc) { + sicm.addDataKey(dataKey); + } + + runner.addSourceIngest(sicm); + } + } + + // Apply site list to all SCANQPF default + for (String source : getSourceConfig().getQPFSources()) { + SourceXML qpfSource = getSourceConfig().getSource(source); + // Radar Derived sources use the primary source site keys for + // mosiac datakey + // Auto Config for any Radar derived sources (QPFSCAN) for + // example + if (qpfSource.getSourceName().equals("QPFSCAN")) { + SourceIngestConfigXML sicm = new SourceIngestConfigXML(); + sicm.setSourceName(qpfSource.getSourceName()); + sicm.setUriSubLocation(3); + + for (String siteid : sites) { + sicm.addDataKey(siteid); + } + + runner.addSourceIngest(sicm); + } + } + + DomainXML domain = new DomainXML(); + domain.setPrimary(true); + domain.setCwa(commonStaticSite.getContextName()); + runner.addDomain(domain); + + getRunConfig().addFFMPRunner(runner); + getRunConfig().saveConfigXml(); + getRunConfig().setPopulated(true); + + domains.add(domain); + } + + // kick off template generation + this.getExecutor().execute(new TemplateLoader(domains)); + } + + @Override + protected void createFilters() { + // do more here if you wish + + ArrayList runners = getRunConfig().getFFMPRunners(); + ArrayList tmp = new ArrayList( + runners.size()); + + for (FFMPRunXML runner : runners) { + DomainXML domain = runner.getPrimaryDomain(); + try { + tmp.add(new FFMPURIFilter(getSiteString(runner) + ":" + + getRFCString(runner) + ":" + domain.getCwa())); + + statusHandler.handle(Priority.INFO, "Created FFMP Filter.." + + " primary Domain: " + domain.getCwa()); + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Couldn't create FFMP Filter.." + " primary Domain: " + + domain.getCwa() + + " this RUNNER is not a viable FFMP config."); + e.printStackTrace(); + } + } + + filters = tmp.toArray(new URIFilter[tmp.size()]); + + } + + /** + * Slight difference in the way ffmp operates as opposed to the URIFilter in + * general. + */ + @Override + public void matchURIs(DataURINotificationMessage messages) { + + 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]; + + if (loaded) { + + synchronized (filter) { + + if (filter.isMatched(messages)) { + + if (!ffgCheck) { + + filter = getFFG(filter); + filter.setValidTime(filter + .getCurrentTime()); + ffgCheck = true; + } + + dispatch(filter); + } + } + } else { + statusHandler + .debug(getGeneratorName() + + ": templates not loaded yet. Skipping product"); + } + } + } + } + } + } + + @Override + public void generateProduct(URIGenerateMessage genMessage) { + if (loaded) { + try { + long time = System.currentTimeMillis(); + this.config = new FFMPConfig( + (FFMPURIGenerateMessage) genMessage, this); + products = new ConcurrentHashMap(); + processes = new ConcurrentHashMap(); + // read config updates, make sure we don't miss something + getRunConfig().readConfigXml(); + getSourceConfig().readConfigXml(); + + if (config.getSources() != null) { + for (String source : config.getSources().keySet()) { + processes.put(source, + getSourceConfig().getSource(source)); + } + } + + // start threads + + for (String source : processes.keySet()) { + this.getExecutor().execute( + new ProcessProduct(processes.get(source), this)); + } + + // count down latch + while (processes.size() > 0) { + // wait for all threads to finish before returning + try { + Thread.sleep(100); + statusHandler.handle(Priority.DEBUG, + "Checking status ..." + processes.size()); + for (String source : processes.keySet()) { + statusHandler.handle(Priority.DEBUG, + "Still processing ..." + source); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + if (products.size() > 0) { + + // Do the FFTI evaluation, if we have FFTI sources + if (fftiSources.size() > 0) { + this.getExecutor().execute(new FFTI(this)); + } + + ArrayList records = new ArrayList( + products.size()); + for (String source : products.keySet()) { + for (FFMPRecord rec : products.get(source)) { + records.add(rec); + } + } + + FFMPRecord[] recs = new FFMPRecord[records.size()]; + for (int i = 0; i < records.size(); i++) { + recs[i] = records.get(i); + } + + this.setPluginDataObjects(recs); + this.setPluginDao(new FFMPDao(getCompositeProductType(), + template, fscm, config.getCWA())); + + while (fftiSources.size() > 0) { + try { + Thread.sleep(100); + statusHandler.handle(Priority.DEBUG, + "Checking status ..." + fftiDone); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + statusHandler.handle( + Priority.INFO, + config.getCWA() + " finished, duration: " + + (System.currentTimeMillis() - time) + + " ms, wrote " + records.size() + " "); + + } else { + statusHandler.handle(Priority.INFO, config.getCWA() + + " no new products to produce."); + } + // dump data we don't need anymore + ffmpData.clear(); + // suggest garbage collection + System.gc(); + + } catch (Throwable e) { + statusHandler.handle(Priority.ERROR, + "Unable to process FFMP Records."); + e.printStackTrace(); + } + } + } + + /** + * Get the list of domains + * + * @return + */ + public ArrayList getDomains() { + return domains; + } + + /** + * Add a filtering CWA + * + * @param domain + */ + public void addDomain(DomainXML domain) { + domains.add(domain); + } + + @Override + public boolean isRunning() { + return getConfigManager().getFFMPState(); + } + + /** + * Set list of CWA's + * + * @param cwas + */ + public void setDomains(ArrayList domains) { + this.domains = domains; + } + + /** + * Inner class to thread the ffmp processing + * + * @author dhladky + * + */ + private class ProcessProduct implements Runnable { + + SourceXML ffmpProduct; + + FFMPGenerator generator; + + @Override + public void run() { + try { + logger.debug("ProcessProduct: Starting thread " + + ffmpProduct.getSourceName()); + process(); + logger.debug("ProcessProduct: Finishing thread " + + ffmpProduct.getSourceName()); + } catch (Exception e) { + processes.remove(ffmpProduct.getSourceName()); + logger.error("ProcessProduct: removed " + + ffmpProduct.getSourceName()); + e.printStackTrace(); + } + } + + public ProcessProduct(SourceXML ffmpProduct, FFMPGenerator generator) { + this.ffmpProduct = ffmpProduct; + this.generator = generator; + } + + /** + * The actual work gets done here + */ + public void process() throws Exception { + + HashMap dataHash = config.getSourceData(ffmpProduct + .getSourceName()); + ArrayList ffmpRecords = new ArrayList( + dataHash.size()); + + FFMPRunXML runner = getRunConfig().getRunner(config.getCWA()); + + // process all of the dataKeys for this source + for (String dataKey : dataHash.keySet()) { + + ArrayList sites = new ArrayList(); + + // is it a mosaic? + if (ffmpProduct.isMosaic()) { + + // Take care of defaults, all in this case + for (ProductRunXML product : runner.getProducts()) { + // no duplicate keys! + if (!sites.contains(product.getProductKey())) { + sites.add(product.getProductKey()); + } + } + + // do filtering + for (ProductRunXML product : runner.getProducts()) { + // includes + if (product.hasIncludes()) { + for (String includeSourceName : product + .getIncludes()) { + if (ffmpProduct.getSourceName().equals( + includeSourceName)) { + // no duplicate keys! + if (!sites + .contains(product.getProductKey())) { + sites.add(product.getProductKey()); + } + } + } + } + // excludes + if (product.hasExcludes()) { + for (String excludeSourceName : product + .getExcludes()) { + if (ffmpProduct.getSourceName().equals( + excludeSourceName)) { + sites.remove(product.getProductKey()); + } + } + } + } + } else { + // No mosaic, just individual site run + String siteKey = dataKey; + + // special case for XMRG's + if (ffmpProduct.getDataType().equals( + FFMPSourceConfigurationManager.DATA_TYPE.XMRG + .getDataType())) { + + siteKey = null; + String primarySource = null; + + for (ProductXML product : getSourceConfig() + .getProducts()) { + if (product.containsSource(ffmpProduct + .getSourceName())) { + primarySource = product.getPrimarySource(); + break; + } + } + + for (ProductRunXML productRun : runner.getProducts()) { + if (productRun.getProductName().equals( + primarySource)) { + siteKey = productRun.getProductKey(); + break; + } + } + } + + sites.add(siteKey); + } + + int i = 0; + if (sites != null) { + // set the latch keys + ArrayList lsites = new ArrayList(); + for (String site: sites) { + lsites.add(site); + } + + productKeys.put(ffmpProduct.getSourceName(), lsites); + } + + for (String productKey : sites) { + + FFMPRecord ffmpRec = new FFMPRecord(); + ffmpRec.setSourceName(ffmpProduct.getSourceName()); + ffmpRec.setDataKey(dataKey); + ffmpRec.setSiteKey(productKey); + ffmpRec.setPluginName(getCompositeProductType()); + ffmpRec.setWfo(config.getCWA()); + FFMPProcessor ffmp = new FFMPProcessor(config, generator, + ffmpRec, template); + ffmpRec = ffmp.processFFMP(ffmpProduct); + ffmpRec.constructDataURI(); + + if (ffmpRec != null) { + + if (ffmp.isFFTI()) { + fftiDone = false; + if (!fftiSources.contains(ffmp.getFFTISource())) { + FFTIProcessor ffti = new FFTIProcessor( + generator, ffmpRec, + ffmp.getFFTISource()); + fftiSources.add(ffmp.getFFTISource()); + //System.out.println("Adding source to FFTISources!!!!!!!!!!!!"+ffmpRec.getSourceName()); + ffti.processFFTI(); + } + } + // this is a threaded process!!!!!!!!!!! + // Added this to speed the processing of mosaiced sources. + // Before all processing was in line to the source thread. + // This caused slowness in the overall processing. + // By allowing the mosaic components to be concurrently + // processed it has drastically sped up overall FFMP performance. + processDataContainer(ffmpRec, productKey); + ffmpRecords.add(ffmpRec); + } + i++; + } + + while (productKeys.size() > 0) { + // wait for all threads to finish before returning + try { + Thread.sleep(50); + statusHandler.handle(Priority.DEBUG, + "Checking status ..." + productKeys.size()); + for (String source : productKeys.keySet()) { + statusHandler.handle(Priority.DEBUG, + "Still processing ..." + source); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + FFMPRecord[] recs = new FFMPRecord[ffmpRecords.size()]; + for (int i = 0; i < ffmpRecords.size(); i++) { + recs[i] = ffmpRecords.get(i); + } + products.put(ffmpProduct.getSourceName(), recs); + processes.remove(ffmpProduct.getSourceName()); + } + } + + /** + * Inner class to background template creation + * + * @author dhladky + * + */ + private class TemplateLoader implements Runnable { + + ArrayList templateDomains; + + DomainXML primaryDomain; + + @Override + public void run() { + statusHandler.handle(Priority.DEBUG, getGeneratorName() + + " Start loader "); + + for (DomainXML domain : templateDomains) { + if (domain.isPrimary()) { + primaryDomain = domain; + } + } + + // generate templates and unify geometries + loaded = load(); + statusHandler.handle(Priority.DEBUG, getGeneratorName() + + " Finishing loader "); + } + + public TemplateLoader(ArrayList templateDomains) { + this.templateDomains = templateDomains; + } + + /** + * + * @param domain + * @return + */ + public void createUnifiedGeometries(DomainXML domain) { + ArrayList hucsToGen = new ArrayList(); + hucsToGen.add("ALL"); + hucsToGen.add("COUNTY"); + + for (int i = template.getTotalHucLevels() - 1; i >= 0; i--) { + hucsToGen.add("HUC" + i); + } + + for (String huc : hucsToGen) { + template.verifyUnifiedGeometries(huc, domain.getCwa()); + } + } + + public boolean load() { + // load / create primary domain + ClusterTask task = null; + String lockDetails = getGeneratorName() + ":" + + primaryDomain.getCwa() + ":" + primaryDomain.getCwa(); + try { + do { + task = ClusterLockUtils.lock(templateTaskName, lockDetails, + 600 * 1000, true); + } while (task.getLockState() != LockState.SUCCESSFUL); + + template = FFMPTemplates.getInstance(primaryDomain, MODE.EDEX); + // setup the config + getTemplateConfig(); + createUnifiedGeometries(primaryDomain); + } finally { + if ((task != null) + && (task.getLockState() == LockState.SUCCESSFUL)) { + ClusterLockUtils.unlock(task, false); + } + } + + // load the secondary domains + List domainsToGen = new ArrayList( + templateDomains); + while (domainsToGen.size() > 0) { + Iterator iter = domainsToGen.iterator(); + boolean processedDomain = false; + while (iter.hasNext()) { + DomainXML domain = iter.next(); + lockDetails = getGeneratorName() + ":" + + primaryDomain.getCwa() + ":" + domain.getCwa(); + try { + task = ClusterLockUtils.lock(templateTaskName, + lockDetails, 300 * 1000, false); + + if (task.getLockState() == LockState.SUCCESSFUL) { + template.addDomain(domain); + createUnifiedGeometries(domain); + iter.remove(); + processedDomain = true; + } + } finally { + if ((task != null) + && (task.getLockState() == LockState.SUCCESSFUL)) { + ClusterLockUtils.unlock(task, false); + } + } + } + + if (!processedDomain) { + // Didn't process a domain, locked by another cluster + // member, sleep and try again + try { + Thread.sleep(100); + } catch (InterruptedException e) { + + } + } + } + + return template.done; + } + } + + /** + * Gets the string buffer for the RFC's + * + * @param run + * @return + */ + private String getRFCString(FFMPRunXML run) { + StringBuffer buf = new StringBuffer(); + + for (SourceIngestConfigXML ingest : run.getSourceIngests()) { + SourceXML source = FFMPSourceConfigurationManager.getInstance() + .getSource(ingest.getSourceName()); + if (source.isRfc()) { + int i = 0; + for (String dataKey : ingest.getDataKey()) { + if (i < ingest.getDataKey().size() - 1) { + buf.append(dataKey + ","); + } else { + buf.append(dataKey); + } + i++; + } + break; + } + } + return buf.toString(); + } + + /** + * Gets the string buffer for the sites, specific to RADAR type data + * + * @param run + * @return + */ + private String getSiteString(FFMPRunXML run) { + String sites = null; + StringBuffer buf = new StringBuffer(); + for (ProductRunXML product : run.getProducts()) { + SourceXML source = getSourceConfig().getSource( + product.getProductName()); + if (source.getDataType().equals(DATA_TYPE.RADAR.getDataType())) { + buf.append(product.getProductKey() + ","); + } + } + sites = buf.toString(); + if (sites.endsWith(",")) { + sites = sites.substring(0, sites.length() - 1); + } + return sites; + } + + /** + * Write your new SourceBins + * + * @param sourceList + */ + public void writeSourceBins(SourceBinList sourceList) { + + try { + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + + LocalizationFile lflist = pathManager.getLocalizationFile(lc, + getAbsoluteSourceFileName(sourceList.getSourceId())); + + FileUtil.bytes2File( + SerializationUtil.transformToThrift(sourceList), + lflist.getFile(), true); + + lflist.save(); + + statusHandler.handle(Priority.INFO, "Wrote FFMP source Bin File: " + + sourceList.getSourceId()); + + } catch (SerializationException se) { + se.printStackTrace(); + } catch (FileNotFoundException fnfe) { + fnfe.printStackTrace(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } catch (LocalizationOpFailedException e) { + e.printStackTrace(); + } + } + + /** + * Read out your SourceBins + * + * @param sourceId + * @return + */ + public SourceBinList readSourceBins(String sourceId) { + + SourceBinList sbl = null; + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile f = pathManager.getLocalizationFile(lc, + getAbsoluteSourceFileName(sourceId)); + + try { + sbl = (SourceBinList) SerializationUtil + .transformFromThrift(FileUtil.file2bytes(f.getFile(), true)); + } catch (FileNotFoundException fnfe) { + statusHandler.handle(Priority.ERROR, + "Unable to locate file " + f.getName()); + } catch (SerializationException se) { + statusHandler.handle(Priority.ERROR, + "Unable to read file " + f.getName()); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + + return sbl; + } + + /** + * Gets the completed filename + * + * @return + */ + public String getAbsoluteSourceFileName(String sourceId) { + return "ffmp" + File.separator + "sources" + File.separator + sourceId + + ".bin"; + } + + /** + * See if you have one + * + * @param sourceId + * @return + */ + public boolean isExistingSourceBin(String sourceId) { + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile f = pathManager.getLocalizationFile(lc, + getAbsoluteSourceFileName(sourceId)); + return f.exists(); + } + + /** + * Gets the list of bins for that source + * + * @param sourceId + * @return + */ + public SourceBinList getSourceBinList(String sourceId) { + SourceBinList sbl = null; + if (!sourceBins.containsKey(sourceId)) { + sbl = readSourceBins(sourceId); + sourceBins.put(sourceId, sbl); + } else { + sbl = sourceBins.get(sourceId); + } + + return sbl; + } + + /** + * Sets the source bins, first time + * + * @param sbl + */ + public void setSourceBinList(SourceBinList sbl) { + sourceBins.put(sbl.getSourceId(), sbl); + writeSourceBins(sbl); + } + + /** + * Do pull strategy on FFG data + * + * @param filter + * @return + */ + private FFMPURIFilter getFFG(FFMPURIFilter filter) { + + ArrayList uris = new ArrayList(); + + for (String rfc : filter.getRFC()) { + // get a hash of the sources and their grib ids + HashMap sources = FFMPUtils.getFFGModelInfo(rfc); + if (sources != null) { + if (sources.size() > 0) { + for (String source : sources.keySet()) { + + SourceXML sourceXml = getSourceConfig().getSource( + source); + + if (sourceXml != null) { + + String plugin = getSourceConfig().getSource(source) + .getPlugin(); + uris.add(FFMPUtils.getFFGDataURI( + sources.get(source), plugin)); + } + } + } + } + } + // treat it like a regular uri in the filter. + if (uris.size() > 0) { + for (String dataUri : uris) { + // add your pattern checks to the key + for (Pattern pattern : filter.getMatchURIs().keySet()) { + statusHandler.handle(Priority.DEBUG, + "Pattern: " + pattern.toString() + " Key: " + + dataUri); + try { + if (pattern.matcher(dataUri).find()) { + // matches one of them, which one? + String matchKey = filter.getPatternName(pattern); + // put the sourceName:dataPath key into the sources + // array list + filter.getSources().put(matchKey, dataUri); + } + } catch (Exception e) { + statusHandler.handle( + Priority.ERROR, + "Unable to locate new FFG file. " + + pattern.toString()); + } + } + } + } + + return filter; + } + + /** + * get the FFMP data container for this source + * + * @param sourceName + * + * @return + */ + + public FFMPDataContainer getFFMPDataContainer(String siteSourceKey, + ArrayList hucs, Date backDate) { + + FFMPDataContainer container = ffmpData.get(siteSourceKey); + + if (container == null) { + + String siteKey = null; + + String[] parts = siteSourceKey.split("-"); + + if (parts.length > 1) { + siteKey = parts[0]; + } + + container = loadFFMPDataContainer(siteSourceKey, + + hucs, siteKey, + + config.getCWA(), backDate); + + if (container != null) { + ffmpData.put(siteSourceKey, container); + } + } + + return container; + } + + /* + * Gets the FFTI sources to be run + */ + public ArrayList getFFTISources() { + return fftiSources; + } + + /** + * source config manager + * + * @return + */ + public FFMPSourceConfigurationManager getSourceConfig() { + if (fscm == null) { + fscm = FFMPSourceConfigurationManager.getInstance(); + fscm.addListener(this); + } + return fscm; + } + + /** + * run config manager + * + * @return + */ + public FFMPRunConfigurationManager getRunConfig() { + if (frcm == null) { + frcm = FFMPRunConfigurationManager.getInstance(); + frcm.addListener(this); + } + return frcm; + } + + /** + * Template config manager + * + * @return + */ + public FFMPTemplateConfigurationManager getTemplateConfig() { + if (tempConfig == null) { + tempConfig = FFMPTemplateConfigurationManager.getInstance(); + tempConfig.addListener(this); + } + return tempConfig; + } + + /** + * dispatch a filter for processing + * + * @param filter + */ + private void dispatch(FFMPURIFilter filter) { + + try { + EDEXUtil.getMessageProducer().sendAsync( + routeId, + SerializationUtil.transformToThrift(filter + .createGenerateMessage())); + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, getGeneratorName() + + ": filter: " + filter.getName() + + ": failed to route filter to generator", e); + e.printStackTrace(); + } + + filter.setValidTime(new Date(System.currentTimeMillis())); + filter.reset(); + } + + /** + * Process this data container + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + */ + public void processDataContainer(FFMPRecord ffmpRec, String productKey) { + + this.getProcessExecutor().execute(new ProcessDataContainer(ffmpRec, productKey)); + } + + /** + * Inner class to thread writing of BuddyFiles + * + * @author dhladky + * + */ + private class ProcessDataContainer implements Runnable { + + private FFMPRecord ffmpRec; + private String productKey; + + public void run() { + try { + processDataContainer(ffmpRec, productKey); + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "ProcessDataContainer: removed " + e.getMessage()); + } + } + + public ProcessDataContainer(FFMPRecord ffmpRec, String productKey) { + this.ffmpRec = ffmpRec; + this.productKey = productKey; + } + + /** + * Process this data container + * + * @param ffmpRec + * @param write + */ + private void processDataContainer(FFMPRecord ffmpRec, String productKey) { + + String sourceName = null; + Date backDate = null; + String sourceSiteDataKey = null; + FFMPDataContainer fdc = null; + boolean write = true; + + try { + // write out the fast loader buddy file + + long ptime = System.currentTimeMillis(); + SourceXML source = getSourceConfig().getSource( + ffmpRec.getSourceName()); + String dataKey = ffmpRec.getDataKey(); + + if (source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + sourceName = source.getDisplayName(); + sourceSiteDataKey = sourceName; + // FFG is so infrequent go back a day + backDate = new Date(config.getDate().getTime() + - (3600 * 1000 * 24)); + } else { + sourceName = ffmpRec.getSourceName(); + sourceSiteDataKey = sourceName + "-" + ffmpRec.getSiteKey() + + "-" + dataKey; + backDate = new Date(ffmpRec.getDataTime().getRefTime() + .getTime() + - (3600 * 1000 * 6)); + } + + // deal with setting of needed HUCS + ArrayList hucs = template.getTemplateMgr() + .getHucLevels(); + + if (source.getSourceType().equals( + SOURCE_TYPE.GAGE.getSourceType()) + || source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + hucs.clear(); + hucs.add("ALL"); + } else { + hucs.remove("VIRTUAL"); + } + + // pull from disk if there + fdc = getFFMPDataContainer(sourceSiteDataKey, hucs, backDate); + + // brand new or initial load up + if (fdc == null || !loadedData.contains(sourceSiteDataKey)) { + + long time = System.currentTimeMillis(); + fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); + fdc = FFTIProcessor.populateDataContainer(fdc, template, + hucs, backDate, ffmpRec.getDataTime().getRefTime(), + ffmpRec.getWfo(), source, ffmpRec.getSiteKey()); + + if (!loadedData.contains(sourceSiteDataKey)) { + loadedData.add(sourceSiteDataKey); + } + + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.DEBUG, + "Populated new source: in " + (time2 - time) + + " ms: source: " + sourceSiteDataKey); + + } else { + + long time = System.currentTimeMillis(); + // guidance sources are treated as a mosaic and are handled + // differently. They are force read at startup. + // This is the main line sequence a source will take when + // updated. + if (!source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + + Date newDate = fdc.getNewest(); + Date oldDate = fdc.getOldest(); + + if (newDate != null && oldDate != null) { + if ((ffmpRec.getDataTime().getRefTime().getTime() - newDate + .getTime()) >= (source + .getExpirationMinutes(ffmpRec.getSiteKey()) * 60 * 1000)) { + // force a re-query back to the newest time in + // existing source container, this will fill in + // gaps + // if + // they exist. + fdc = FFTIProcessor.populateDataContainer(fdc, + template, null, newDate, ffmpRec + .getDataTime().getRefTime(), + ffmpRec.getWfo(), source, ffmpRec + .getSiteKey()); + + } else if (oldDate.after(new Date(backDate + .getTime() + - (source.getExpirationMinutes(ffmpRec + .getSiteKey()) * 60 * 1000)))) { + // force a re-query back to barrierTime for + // existing source container, this happens if + // the + // ingest was turned off for some period of + // time. + fdc = FFTIProcessor.populateDataContainer(fdc, + template, null, backDate, oldDate, + ffmpRec.getWfo(), source, + ffmpRec.getSiteKey()); + } + } + + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.DEBUG, + "Checked Source files: in " + (time2 - time) + + " ms: source: " + sourceSiteDataKey); + } + } + + // add current record data + for (String huc : hucs) { + fdc.addFFMPEntry(ffmpRec.getDataTime().getRefTime(), + source, ffmpRec.getBasinData(huc), huc, + ffmpRec.getSiteKey()); + } + // purge it up + fdc.purge(backDate); + // set the name + fdc.setFilePath("" + sharePath + ffmpRec.getWfo() + "/" + + sourceSiteDataKey); + + // cache it temporarily for FFTI use + if (source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + // only write last one + write = false; + + if (!ffmpData.containsKey(sourceSiteDataKey)) { + ffmpData.put(sourceSiteDataKey, fdc); + } else { + ffmpData.replace(sourceSiteDataKey, fdc); + } + } + + statusHandler.handle( + Priority.INFO, + "Processed FFMPDataContainer: in " + + (System.currentTimeMillis() - ptime) + + " ms: source: " + sourceSiteDataKey); + } catch (Exception e) { + statusHandler.handle(Priority.INFO, + "Failed Processing FFMPDataContainer" + e.getMessage()); + + } finally { + // moved writing here to remain safe from possible race condition between processing threads + if (productKeys != null) { + if (productKeys.containsKey(ffmpRec.getSourceName())) { + productKeys.get(ffmpRec.getSourceName()).remove(productKey); + //System.out.println("Removed productKey: "+productKey); + if (productKeys.get(ffmpRec.getSourceName()).size() == 0) { + //System.out.println("Removed source: "+ffmpRec.getSourceName()+" now writing"); + productKeys.remove(ffmpRec.getSourceName()); + // last one, allow write + write = true; + } + } + } + + if (write) { + // write it out + writeLoaderBuddyFiles(fdc); + } + } + } + } + + /** + * load existing container + * + * @param sourceSiteDataKey + * @param hucs + * @param siteKey + * @param wfo + * @return + */ + public FFMPDataContainer loadFFMPDataContainer(String sourceSiteDataKey, + ArrayList hucs, String siteKey, String wfo, Date backDate) { + + long time = System.currentTimeMillis(); + FFMPDataContainer fdc = null; + + synchronized (hucs) { + for (String huc : hucs) { + + FFMPBasinData basinData = null; + + if (checkBuddyFile(sourceSiteDataKey, huc, wfo, backDate)) { + try { + basinData = readLoaderBuddyFile(sourceSiteDataKey, huc, + wfo, backDate); + } catch (Exception e) { + statusHandler.handle( + Priority.ERROR, + "General Error Reading buddy file: " + + e.getMessage()); + } + + if (fdc == null) { + fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); + } + } + + if (basinData != null) { + fdc.setBasinBuddyData(basinData, huc); + } + } + } + + if (fdc != null) { + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.DEBUG, "Loaded Source files: in " + + (time2 - time) + " ms: source: " + sourceSiteDataKey); + } + + return fdc; + } + + /** + * Load existing buddy file + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + * @throws IOException + */ + private FFMPBasinData readLoaderBuddyFile(String sourceSiteDataKey, + String huc, String wfo, Date backDate) throws IOException { + + File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" + + huc + ".bin"); + FFMPBasinData basinData = null; + BufferedInputStream is = null; + + try { + is = new BufferedInputStream( + new FileInputStream(file)); + DynamicSerializationManager dsm = DynamicSerializationManager + .getManager(SerializationType.Thrift); + basinData = (FFMPBasinData) dsm.deserialize(is); + } catch (SerializationException e) { + statusHandler.handle(Priority.ERROR, + "Serialization Error Reading buddy file: " + + e.getMessage()); + } catch (IOException e) { + statusHandler.handle(Priority.ERROR, + "IO Error Reading buddy file: " + + e.getMessage()); + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "General Error Reading buddy file: " + + e.getMessage()); + } catch (Throwable t) { + statusHandler.handle(Priority.ERROR, + "Bogus Thrift Error Reading buddy file: " + + t.getMessage()); + } finally { + if (is != null) { + is.close(); + } + } + + return basinData; + + } + + /** + * Write buddy file + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + */ + public void writeLoaderBuddyFiles(FFMPDataContainer fdc) { + + // Write all huc levels in separate files + File fileDir = new File("" + sharePath + config.getCWA()); + if (!fileDir.exists()) { + fileDir.mkdir(); + } + + WriteFiles writer = new WriteFiles(fdc); + writer.run(); + } + + /** + * Inner class to thread writing of BuddyFiles + * + * @author dhladky + * + */ + private class WriteFiles implements Runnable { + + private FFMPDataContainer fdc; + + public void run() { + try { + long time = System.currentTimeMillis(); + write(); + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.DEBUG, "Wrote loader files: in " + + (time2 - time) + " ms :" + fdc.getFilePath()); + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "WriteFile: removed " + e.getMessage()); + } + } + + public WriteFiles(FFMPDataContainer fdc) { + this.fdc = fdc; + statusHandler.handle(Priority.DEBUG, "Created FileWriter"); + } + + /** + * The actual work gets done here + */ + public void write() throws Exception { + + try { + + String fileName = fdc.getFilePath(); + // lock for atomic write and read + HashMap fileNames = new HashMap(); + File lockfile = new File(fileName + ".lock"); + lockfile.createNewFile(); + + try { + + if (lockfile.canWrite()) { + // write the lock if we can even write to anything + synchronized (fdc.getKeys()) { + for (String huc : fdc.getKeys()) { + + FFMPBasinData fbd = fdc.getBasinData(huc); + + if (fbd.getBasins().size() > 0) { + + String tmpFilePath = fileName + "-" + huc + + ".tmp"; + BufferedOutputStream os = null; + + try { + File file = new File(tmpFilePath); + file.createNewFile(); + + if (file.canWrite()) { + os = new BufferedOutputStream( + new FileOutputStream(file)); + DynamicSerializationManager dsm = DynamicSerializationManager + .getManager(SerializationType.Thrift); + dsm.serialize(fbd, os); + fileNames.put(tmpFilePath, fileName + + "-" + huc + ".bin"); + } else { + statusHandler + .handle(Priority.WARN, + "Can not write buddy file: " + + file.getAbsolutePath()); + } + } catch (SerializationException e) { + statusHandler.handle(Priority.ERROR, + "Serialization Error Writing buddy file: " + + e.getMessage()); + } catch (IOException e) { + statusHandler.handle(Priority.ERROR, + "IO Error Writing buddy file: " + + e.getMessage()); + } finally { + if (os != null) { + os.close(); + } + } + } + } + } + } + } catch (Exception e) { + statusHandler + .handle(Priority.ERROR, + "Error writing Buddy File group: " + + e.getMessage()); + } finally { + // rename the files to real path + try { + for (String tmpName : fileNames.keySet()) { + File file = new File(tmpName); + file.renameTo(new File(fileNames.get(tmpName))); + } + + if (lockfile.exists()) { + lockfile.delete(); + } + + } catch (Exception e) { + statusHandler.handle( + Priority.ERROR, + "IO Error Renaming buddy file: " + + e.getMessage()); + } + } + + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "IO Error writing buddy files: " + e.getMessage()); + } + + } + } + + /** + * Load existing buddy file + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + */ + public boolean checkBuddyFile(String sourceSiteDataKey, String huc, + String wfo, Date backDate) { + + File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" + + huc + ".bin"); + + String sourceName = sourceSiteDataKey.split("-")[0]; + SourceXML source = getSourceConfig().getSourceByDisplayName(sourceName); + if (source != null) { + + if (source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + if (file.exists() && file.canRead() && file.canWrite()) { + return true; + } + } else { + if (file.exists() && file.canRead() && file.canWrite() + && (file.lastModified() > backDate.getTime())) { + // System.out.println("File update and exists..."+sourceSiteDataKey); + return true; + } + } + } + + return false; + + } + + @Override + public synchronized void configChanged(MonitorConfigEvent fce) { + + boolean reload = false; + + if (fce.getSource() instanceof FFMPTemplateConfigurationManager) { + statusHandler + .handle(Priority.INFO, + "Re-configuring FFMP & URI filters...Template Config change"); + reload = true; + FFMPTemplateConfigurationManager ftcm = (FFMPTemplateConfigurationManager) fce + .getSource(); + if (ftcm.isRegenerate()) { + template.dumpTemplates(); + } + + tempConfig = null; + + } else if (fce.getSource() instanceof FFMPRunConfigurationManager) { + statusHandler.handle(Priority.INFO, + "Re-configuring FFMP & URI filters...Run Config change"); + reload = true; + frcm = null; + } + + else if (fce.getSource() instanceof FFMPSourceConfigurationManager) { + statusHandler.handle(Priority.INFO, + "Re-configuring FFMP & URI filters...Source Config change"); + reload = true; + fscm = null; + } + + if (reload) { + + ffgCheck = false; + resetFilters(); + + if (sourceBins != null) { + sourceBins.clear(); + } + + loadedData.clear(); + + if (ffmpData != null) { + ffmpData.clear(); + } + if (fftiData != null) { + fftiData.clear(); + } + + DatMenuUtil dmu = new DatMenuUtil(); + dmu.setDatSite(PropertiesFactory.getInstance().getEnvProperties() + .getEnvValue("SITENAME")); + dmu.setOverride(true); + dmu.createMenus(); + } + } + + /** + * FFTI data cache + * + * @param ffti + */ + public void writeFFTIData(String fftiName, FFTIData ffti) { + if (fftiData.containsKey(fftiName)) { + fftiData.replace(fftiName, ffti); + } else { + fftiData.put(fftiName, ffti); + } + + writeFFTIFile(ffti, fftiName); + } + + /** + * Get FFTI data cache + * + * @param fftiName + * @return + */ + public FFTIData getFFTIData(String fftiName) { + // preserve the state of the reset value + boolean reset = true; + if (fftiData.containsKey(fftiName)) { + reset = fftiData.get(fftiName).isReset(); + } + + FFTIData ffti = readFFTIData(fftiName); + + if (fftiData != null) { + ffti.setReset(reset); + fftiData.put(fftiName, ffti); + } + return ffti; + } + + /** + * Write your FFTI Data files + * + * @param sourceList + */ + public void writeFFTIFile(FFTIData ffti, String fftiName) { + + try { + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + + LocalizationFile lflist = pathManager.getLocalizationFile(lc, + getAbsoluteFFTIFileName(fftiName)); + + FileUtil.bytes2File(SerializationUtil.transformToThrift(ffti), + lflist.getFile(), true); + + lflist.save(); + + statusHandler.handle(Priority.DEBUG, "Wrote FFMP FFTI file: " + + fftiName); + + } catch (SerializationException se) { + se.printStackTrace(); + } catch (FileNotFoundException fnfe) { + fnfe.printStackTrace(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } catch (LocalizationOpFailedException e) { + e.printStackTrace(); + } + } + + /** + * Read out your FFTI Files + * + * @param sourceId + * @return + */ + public FFTIData readFFTIData(String fftiName) { + + FFTIData ffti = null; + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile f = pathManager.getLocalizationFile(lc, + getAbsoluteFFTIFileName(fftiName)); + + try { + ffti = (FFTIData) SerializationUtil.transformFromThrift(FileUtil + .file2bytes(f.getFile(), true)); + } catch (FileNotFoundException fnfe) { + statusHandler.handle(Priority.ERROR, + "Unable to locate file " + f.getName()); + } catch (SerializationException se) { + statusHandler.handle(Priority.ERROR, + "Unable to read file " + f.getName()); + } catch (IOException ioe) { + statusHandler.handle(Priority.ERROR, + "Unable to read file " + f.getName()); + } + + return ffti; + } + + /** + * Gets the completed filename + * + * @return + */ + public String getAbsoluteFFTIFileName(String fftiName) { + return "ffmp" + File.separator + "ffti" + File.separator + fftiName + + ".bin"; + } + + /** + * See if you have one + * + * @param fftiName + * @return + */ + public boolean isFFTI(String fftiName) { + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile f = pathManager.getLocalizationFile(lc, + getAbsoluteFFTIFileName(fftiName)); + boolean exists = false; + if (f != null) { + exists = f.exists(); + } + + return exists; + } + + /** + * get the whole container + * + * @return + */ + public ConcurrentHashMap getFFTIDataContainer() { + return fftiData; + } + + /** + * the executor runner + * + * @return + */ + public Executor getProcessExecutor() { + return processexecutor; + } + + public void setProcessExecutor(Executor processexecutor) { + this.processexecutor = processexecutor; + } + +} \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java index e37efdc150..be051647fa 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java @@ -40,6 +40,7 @@ import com.raytheon.uf.edex.plugin.ffmp.FFMPGenerator; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 29 July, 2011 6772 dhladky Initial creation + * 29 July, 2012 578 dhladky memory work * * * @author dhladky @@ -92,14 +93,9 @@ public class FFMPInterpolatedGuidanceDelay { ArrayList hucs = new ArrayList(); hucs.add("ALL"); - // if (qpeSource.isMosaic()) { - // qpeContainer = generator.getFFMPDataContainer(qpeSource - // .getSourceName(), hucs, backDate); - // } else { qpeContainer = generator.getFFMPDataContainer(qpeSource.getSourceName() + "-" + siteKey + "-" + siteKey, hucs, backDate); - // } - + long expirationTime = qpeSource.getExpirationMinutes(siteKey) * 60 * 1000; // determine lag_time long lagTime = (currentRecord.getDataTime().getRefTime().getTime()) diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java index e17a1ad813..022f857a15 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java @@ -55,6 +55,7 @@ import com.raytheon.uf.edex.plugin.ffmp.FFMPGenerator; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 01, 2011 dhladky Initial creation + * July 13, 2012 dhladky Revamped to help memory * * * @@ -226,7 +227,7 @@ public class FFTI implements Runnable { for (String displayName : displayNames) { String[] fftiKeys = displayName.split("-"); - + // monolithic processing for mosaic sources if (fftiKeys.length == 1) { @@ -234,29 +235,29 @@ public class FFTI implements Runnable { displayName); ArrayList sites = getSites(source); ArrayList accums = new ArrayList(); - + // process all pieces of the mosaic - for (int i = 0; i < sites.size(); i++) { + for (int i = 0; i < sites.size(); i++) { - String dataKey = sites.get(i); + String dataKey = sites.get(i); - for (int j = 0; j < sites.size(); j++) { + for (int j = 0; j < sites.size(); j++) { - FFTIAccum faccum = getAccumulationForSite(displayName, - sites.get(j), dataKey, duration, - source.getUnit()); + FFTIAccum faccum = getAccumulationForSite(displayName, + sites.get(j), dataKey, duration, + source.getUnit()); - if (faccum != null) { - accums.add(faccum); - } - } - } + if (faccum != null) { + accums.add(faccum); + } + } + } // find the highest for the entire mosaic accum = new FFTIAccum(); accum.setAccumulation(0.0); - for (FFTIAccum faccum: accums) { + for (FFTIAccum faccum : accums) { if (accum.getAccumulation() <= faccum.getAccumulation()) { accum.setAccumulation(faccum.getAccumulation()); @@ -270,35 +271,35 @@ public class FFTI implements Runnable { accum.setUnit(faccum.getUnit()); } - statusHandler.handle( Priority.INFO, "FFTI mosaic ACCUM: " + source.getSourceName() + " " + accum.getAccumulation() + " gap: " + accum.getGap()); accumList.add(accum); - + } else { - + fftiSiteKey = fftiKeys[0]; fftiSourceKey = fftiKeys[1]; source = ffmpgen.getSourceConfig().getSourceByDisplayName( fftiSourceKey); - accum = getAccumulationForSite(fftiSourceKey, fftiSiteKey, fftiSiteKey, duration, source.getUnit()); - - if (accum != null) { - accum.setUnit(source.getUnit()); - statusHandler.handle( - Priority.INFO, - "FFTI ACCUM: " + source.getSourceName() + " " - + fftiSiteKey + " " - + accum.getAccumulation() + " gap: " - + accum.getGap()); + accum = getAccumulationForSite(fftiSourceKey, fftiSiteKey, + fftiSiteKey, duration, source.getUnit()); - accumList.add(accum); - } + if (accum != null) { + accum.setUnit(source.getUnit()); + statusHandler.handle( + Priority.INFO, + "FFTI ACCUM: " + source.getSourceName() + " " + + fftiSiteKey + " " + + accum.getAccumulation() + " gap: " + + accum.getGap()); + + accumList.add(accum); + } } } @@ -346,19 +347,19 @@ public class FFTI implements Runnable { .equals(FFTIAttributeXML.ATTRIBUTE.RATIO .getAttribute())) { - if (values.getGuids() != null - && values.getQpes() != null) { - tempVal = FFMPUtils.getMaxRatioValue( - values.getQpes(), values.getGuids()); - } - } else if (attribute.getAttributeName().equals( - FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) { + if (values.getGuids() != null + && values.getQpes() != null) { + tempVal = FFMPUtils.getMaxRatioValue( + values.getQpes(), values.getGuids()); + } + } else if (attribute.getAttributeName().equals( + FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) { - if (values.getGuids() != null - && values.getQpes() != null) { - tempVal = FFMPUtils.getMaxDiffValue( - values.getQpes(), values.getGuids()); - } + if (values.getGuids() != null + && values.getQpes() != null) { + tempVal = FFMPUtils.getMaxDiffValue( + values.getQpes(), values.getGuids()); + } } if ((tempVal != Float.NaN) @@ -405,20 +406,20 @@ public class FFTI implements Runnable { if (attribute.getAttributeName().equals( FFTIAttributeXML.ATTRIBUTE.RATIO.getAttribute())) { - if (values.getGuids() != null - && values.getQpes() != null) { - val = FFMPUtils.getMaxRatioValue(values.getQpes(), - values.getGuids()); - } - + if (values.getGuids() != null + && values.getQpes() != null) { + val = FFMPUtils.getMaxRatioValue(values.getQpes(), + values.getGuids()); + } + } else if (attribute.getAttributeName().equals( FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) { - if (values.getGuids() != null - && values.getQpes() != null) { - val = FFMPUtils.getMaxDiffValue(values.getQpes(), - values.getGuids()); - } + if (values.getGuids() != null + && values.getQpes() != null) { + val = FFMPUtils.getMaxDiffValue(values.getQpes(), + values.getGuids()); + } } gap = values.getGap(); @@ -459,74 +460,74 @@ public class FFTI implements Runnable { double red = attribute.getRedThrshld(); for (FFTIAccum accum : accumList) { - if (accum != null && accum.getName() != null) { - value = accum.getAccumulation(); - unit = accum.getUnit(); - displayName = accum.getName(); - gapVal = accum.getGap(); + if (accum != null && accum.getName() != null) { + value = accum.getAccumulation(); + unit = accum.getUnit(); + displayName = accum.getName(); + gapVal = accum.getGap(); - String sourceDisplayName = null; - if (displayName.contains("-")) { - sourceDisplayName = displayName.split("-")[1]; - } else { - sourceDisplayName = displayName; - } + String sourceDisplayName = null; + if (displayName.contains("-")) { + sourceDisplayName = displayName.split("-")[1]; + } else { + sourceDisplayName = displayName; + } - SourceXML source = FFMPSourceConfigurationManager - .getInstance().getSourceByDisplayName( - sourceDisplayName); + SourceXML source = FFMPSourceConfigurationManager + .getInstance().getSourceByDisplayName( + sourceDisplayName); - String sourceType = source.getSourceType(); + String sourceType = source.getSourceType(); - // Set up the alert data object - FFTIAlertData fad = new FFTIAlertData(); + // Set up the alert data object + FFTIAlertData fad = new FFTIAlertData(); - if (sourceType.equalsIgnoreCase(SOURCE_TYPE.QPE - .getSourceType())) { - fad.addSource(SOURCE_TYPE.QPE, displayName); - fad.addDuration(SOURCE_TYPE.QPE, setting.getQpeSource() - .getDurationHour()); - } else if (sourceType.equalsIgnoreCase(SOURCE_TYPE.QPF - .getSourceType())) { - fad.addSource(SOURCE_TYPE.QPF, displayName); - fad.addDuration(SOURCE_TYPE.QPF, setting.getQpfSource() - .getDurationHour()); - } + if (sourceType.equalsIgnoreCase(SOURCE_TYPE.QPE + .getSourceType())) { + fad.addSource(SOURCE_TYPE.QPE, displayName); + fad.addDuration(SOURCE_TYPE.QPE, setting.getQpeSource() + .getDurationHour()); + } else if (sourceType.equalsIgnoreCase(SOURCE_TYPE.QPF + .getSourceType())) { + fad.addSource(SOURCE_TYPE.QPF, displayName); + fad.addDuration(SOURCE_TYPE.QPF, setting.getQpfSource() + .getDurationHour()); + } - fad.setAttributeName(attribute.getAttributeName()); - fad.setDisplayName(displayName); - fad.setUnit(unit); - fad.setValue(formatter.format(value)); - fad.setGap(getGapString(gapVal)); + fad.setAttributeName(attribute.getAttributeName()); + fad.setDisplayName(displayName); + fad.setUnit(unit); + fad.setValue(formatter.format(value)); + fad.setGap(getGapString(gapVal)); - if ((value >= yellow) && (value < red)) { - fad.setPriority(String - .valueOf(UFStatus.Priority.PROBLEM.ordinal())); + if ((value >= yellow) && (value < red)) { + fad.setPriority(String + .valueOf(UFStatus.Priority.PROBLEM.ordinal())); - if (messagePriority.ordinal() > Priority.PROBLEM - .ordinal()) { - messagePriority = UFStatus.Priority.PROBLEM; - } - } else if (value >= red) { - fad.setPriority(String - .valueOf(UFStatus.Priority.SIGNIFICANT - .ordinal())); - if (messagePriority.ordinal() > UFStatus.Priority.SIGNIFICANT - .ordinal()) { - messagePriority = UFStatus.Priority.SIGNIFICANT; - } - } else { - fad.setPriority(String.valueOf(UFStatus.Priority.EVENTA - .ordinal())); - if (messagePriority.ordinal() > UFStatus.Priority.EVENTA - .ordinal()) { - messagePriority = UFStatus.Priority.EVENTA; - } - } + if (messagePriority.ordinal() > Priority.PROBLEM + .ordinal()) { + messagePriority = UFStatus.Priority.PROBLEM; + } + } else if (value >= red) { + fad.setPriority(String + .valueOf(UFStatus.Priority.SIGNIFICANT + .ordinal())); + if (messagePriority.ordinal() > UFStatus.Priority.SIGNIFICANT + .ordinal()) { + messagePriority = UFStatus.Priority.SIGNIFICANT; + } + } else { + fad.setPriority(String.valueOf(UFStatus.Priority.EVENTA + .ordinal())); + if (messagePriority.ordinal() > UFStatus.Priority.EVENTA + .ordinal()) { + messagePriority = UFStatus.Priority.EVENTA; + } + } - alertDataArray.add(fad); - } - } + alertDataArray.add(fad); + } + } } catch (Exception e) { e.printStackTrace(); statusHandler @@ -630,7 +631,16 @@ public class FFTI implements Runnable { fad.setAttributeName(attributeName); fad.setDisplayName(displayName); fad.setUnit(unit); - fad.setValue(formatter.format(value)); + + String displayStr = null; + if (attributeName.equals(FFTIAttributeXML.ATTRIBUTE.RATIO + .getAttribute())) { + displayStr = String.valueOf(Math.round(value)); + } else { + displayStr = String.format("%1.2f", value); + } + + fad.setValue(displayStr); fad.setGap(getGapString(gapVal)); fad.setPriority(new Integer(priority).toString()); fad.addDuration(SOURCE_TYPE.GUIDANCE, guidDuration); @@ -718,9 +728,6 @@ public class FFTI implements Runnable { + sourceLengths[1] + "s %-" + sourceLengths[2] + "s %6s %7s %-3s %-6s"; - // String headerFmt = typeFmt + " " + sourceFmt + " %5s " + unitFmt - // + " %8s %8s %s\n"; - String headerStr = String.format(lineFmt, "Type", "QPE", "QPF", "GUID ", "Value", "Unit", "Pri", "GAP"); @@ -793,82 +800,96 @@ public class FFTI implements Runnable { */ private FFTIAccum getAccumulationForSite(String fftiSourceKey, String fftiSiteKey, String fftiDataKey, double duration, String unit) { - + SourceXML ffmpSource = ffmpgen.getSourceConfig() .getSourceByDisplayName(fftiSourceKey); FFTIAccum accumulator = null; - String siteDataKey = ffmpSource.getDisplayName() + "-" + fftiSiteKey + "-"+ fftiDataKey; - + String siteDataKey = ffmpSource.getDisplayName() + "-" + fftiSiteKey + + "-" + fftiDataKey; + if (ffmpgen.isFFTI(siteDataKey)) { - accumulator = (FFTIAccum) ffmpgen.getFFTIData(siteDataKey); + accumulator = (FFTIAccum) ffmpgen.getFFTIData(siteDataKey); } else { - accumulator = new FFTIAccum(); + accumulator = new FFTIAccum(); } - + // 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); + accumulator.setDuration(duration); + accumulator.setUnit(unit); - if (ffmpSource.isMosaic()) { - accumulator.setName(ffmpSource.getDisplayName()); - } else { - accumulator.setName(fftiSiteKey + "-" + fftiSourceKey); - } - - long cur = config.getDate().getTime(); - long timeBack = (long) (duration * 3600 * 1000); - Date backDate = new Date(cur - timeBack); - long expirationTime = ffmpSource.getExpirationMinutes(fftiSiteKey) * 60 * 1000; + if (ffmpSource.isMosaic()) { + accumulator.setName(ffmpSource.getDisplayName()); + } else { + accumulator.setName(fftiSiteKey + "-" + fftiSourceKey); + } - FFMPDataContainer fdc = null; + long cur = config.getDate().getTime(); + long timeBack = (long) (duration * 3600 * 1000); + Date backDate = new Date(cur - timeBack); + long expirationTime = ffmpSource.getExpirationMinutes(fftiSiteKey) * 60 * 1000; - ArrayList hucs = new ArrayList(); - hucs.add("ALL"); + FFMPDataContainer fdc = null; - fdc = ffmpgen.getFFMPDataContainer(siteDataKey, hucs, backDate); + ArrayList hucs = new ArrayList(); + hucs.add("ALL"); - if (fdc != null) { + fdc = ffmpgen.getFFMPDataContainer(siteDataKey, hucs, backDate); - FFMPBasinData fbd = fdc.getBasinData("ALL"); + if (fdc != null) { - // go over the list of CWAs gathering the pfaf list - ArrayList pfafs = new ArrayList(); - ArrayList cwaList = fdm.getCwaList(); + FFMPBasinData fbd = fdc.getBasinData("ALL"); - Double gap = getGap(fdc, ffmpSource, duration, fftiSiteKey); + // go over the list of CWAs gathering the pfaf list + ArrayList pfafs = new ArrayList(); + ArrayList cwaList = fdm.getCwaList(); - if (gap != Double.NaN) { + Double gap = getGap(fdc, ffmpSource, duration, fftiSiteKey); - for (String cwa : cwaList) { - for (Long key : fbd.getBasins().keySet()) { + if (gap != Double.NaN) { + for (Long key : fbd.getBasins().keySet()) { + for (String cwa : cwaList) { - FFMPBasinMetaData basin = templates.getBasin(key); - if ((basin != null) && (basin.getCwa() != null)) { - if (basin.getCwa().equals(cwa)) { - if (!pfafs.contains(key)) { - pfafs.add(key); - } - } - } - } - } + boolean primary = false; + if (cwa.equals(config.getCWA())) { + primary = true; + } - double amount = fdc.getMaxValue(pfafs, backDate, - config.getDate(), expirationTime, - ffmpSource.isRate()); + FFMPBasinMetaData fmdb = templates.getBasin( + fftiSiteKey, key); - // max value for monitored area - accumulator.setAccumulation(amount); - accumulator.setGap(gap); - } - } - - // replace or insert it - accumulator.reset(false); - ffmpgen.addFFTIData(siteDataKey, accumulator); - } + if (fmdb == null) { + continue; + } + + // Gets buffer zones adjacent to CWA + if ((cwa.equals(fmdb.getCwa())) + || (primary && fmdb.isPrimaryCwa())) { + if (!pfafs.contains(key)) { + pfafs.add(key); + } + } + } + } + + double amount = fdc.getMaxValue(pfafs, backDate, + config.getDate(), expirationTime, + ffmpSource.isRate()); + + // max value for monitored area + accumulator.setAccumulation(amount); + accumulator.setGap(gap); + } + } + + // replace or insert it, memory management + if (ffmpgen.ffmpData.containsKey(siteDataKey)) { + ffmpgen.ffmpData.remove(siteDataKey); + } + accumulator.setReset(false); + ffmpgen.writeFFTIData(siteDataKey, accumulator); + } return accumulator; } @@ -882,119 +903,133 @@ public class FFTI implements Runnable { if (ffmpQSource == null) { ffmpQSource = ffmpgen.fscm.getSource(qSourceKey); } - - String siteDataKey = ffgType + "-" + ffmpQSource.getSourceName() + "-"+ qSiteKey; - + + String siteDataKey = ffgType + "-" + ffmpQSource.getSourceName() + "-" + + qSiteKey; + if (ffmpgen.isFFTI(siteDataKey)) { - values = (FFTIRatioDiff) ffmpgen.getFFTIData(siteDataKey); + values = (FFTIRatioDiff) ffmpgen.getFFTIData(siteDataKey); + if (values.getGuids() == null || values.getQpes() == null) { + values.setReset(true); + } } else { - values = new FFTIRatioDiff(); + values = new FFTIRatioDiff(); } - + // 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); - - long cur = config.getDate().getTime(); - long timeBack = (long) (duration * 3600 * 1000); - Date backDate = new Date(cur - timeBack); - long expirationTime = ffmpQSource.getExpirationMinutes(qSiteKey) * 60 * 1000; + values.setDuration(duration); + values.setUnit(unit); - // make sure we have data - Date ffgBackDate = new Date(config.getDate().getTime() - - (3600 * 1000 * 24)); + long cur = config.getDate().getTime(); + long timeBack = (long) (duration * 3600 * 1000); + Date backDate = new Date(cur - timeBack); + long expirationTime = ffmpQSource.getExpirationMinutes(qSiteKey) * 60 * 1000; - String primarySource = ffmpgen.fscm.getPrimarySource(ffmpQSource); - ProductXML product = ffmpgen.fscm.getProduct(primarySource); - ArrayList hucs = new ArrayList(); - hucs.add("ALL"); + // make sure we have data + Date ffgBackDate = new Date(config.getDate().getTime() + - (3600 * 1000 * 24)); - FFMPDataContainer guidContainer = ffmpgen.getFFMPDataContainer( - ffgType, hucs, ffgBackDate); - long guidSourceExpiration = 0l; + String primarySource = ffmpgen.fscm.getPrimarySource(ffmpQSource); + ProductXML product = ffmpgen.fscm.getProduct(primarySource); + ArrayList hucs = new ArrayList(); + hucs.add("ALL"); - if (guidContainer != null) { + FFMPDataContainer guidContainer = ffmpgen.getFFMPDataContainer( + ffgType, hucs, ffgBackDate); - for (SourceXML iguidSource : product - .getGuidanceSourcesByType(ffgType)) { + long guidSourceExpiration = 0l; - if (guidSourceExpiration == 0l) { - guidSourceExpiration = iguidSource - .getExpirationMinutes(qSiteKey) * 60 * 1000; - } + if (guidContainer == null) { + guidContainer = new FFMPDataContainer(ffgType, hucs); + } - if (!guidContainer.containsKey(iguidSource.getSourceName())) { + for (SourceXML iguidSource : product + .getGuidanceSourcesByType(ffgType)) { - guidContainer = FFTIProcessor.populateDataContainer( - guidContainer, templates, null, ffgBackDate, - config.getDate(), config.getCWA(), iguidSource, - qSiteKey); - } - } + if (guidSourceExpiration == 0l) { + guidSourceExpiration = iguidSource + .getExpirationMinutes(qSiteKey) * 60 * 1000; + break; + } + } - // if still nothing, punt! - if (guidContainer.size() == 0) { + // if still nothing, punt! + if (guidContainer.size() == 0) { - statusHandler.handle(Priority.PROBLEM, - "FFTI: No guidance sources available for " - + qSiteKey + " " + qSourceKey + " " - + " comparison."); - return null; - } + statusHandler.handle(Priority.PROBLEM, + "FFTI: No guidance sources available for " + qSiteKey + + " " + qSourceKey + " " + " comparison."); + return values; + } + + FFMPDataContainer qpeContainer = ffmpgen.getFFMPDataContainer( + ffmpQSource.getSourceName() + "-" + qSiteKey + "-" + + qSiteKey, hucs, backDate); - FFMPDataContainer qpeContainer = ffmpgen.getFFMPDataContainer( - ffmpQSource.getSourceName() + "-" + qSiteKey + "-" - + qSiteKey, hucs, backDate); + if (qpeContainer != null) { + // go over the list of CWAs gathering the pfaf list + ArrayList pfafs = new ArrayList(); + ArrayList cwaList = fdm.getCwaList(); + FFMPBasinData fbd = qpeContainer.getBasinData("ALL"); - if (qpeContainer != null) { - // go over the list of CWAs gathering the pfaf list - ArrayList pfafs = new ArrayList(); - ArrayList cwaList = fdm.getCwaList(); - for (String cwa : cwaList) { - for (Long key : qpeContainer.getBasinData("ALL") - .getBasins().keySet()) { - FFMPBasinMetaData basin = templates.getBasin(key); - if ((basin != null) && (basin.getCwa() != null)) { - if (basin.getCwa().equals(cwa)) { - pfafs.add(key); - } - } - } - } + for (Long key : fbd.getBasins().keySet()) { + for (String cwa : cwaList) { - Double gap = getGap(qpeContainer, ffmpQSource, duration, - qSiteKey); + boolean primary = false; + if (cwa.equals(config.getCWA())) { + primary = true; + } - if (gap != Double.NaN) { + FFMPBasinMetaData fmdb = templates.getBasin(qSiteKey, + key); - ArrayList qpes = qpeContainer - .getBasinData("ALL").getAccumValues(pfafs, - backDate, config.getDate(), - expirationTime, false); + if (fmdb == null) { + continue; + } - FFMPGuidanceInterpolation interpolator = new FFMPGuidanceInterpolation( - ffmpgen.fscm, product, ffmpgen.frcm.getRunner( - config.getCWA()).getProduct(qSiteKey), - primarySource, ffgType, qSiteKey); - interpolator.setInterpolationSources(duration); + // Gets buffer zones adjacent to CWA + if ((cwa.equals(fmdb.getCwa())) + || (primary && fmdb.isPrimaryCwa())) { + if (!pfafs.contains(key)) { + pfafs.add(key); + } + } + } + } - ArrayList guids = guidContainer.getBasinData( - "ALL").getGuidanceValues(pfafs, interpolator, - guidSourceExpiration); - - values.setQpes(qpes); - values.setGuids(guids); - values.setGap(gap); - } - } - } - - // replace or insert it - values.reset(false); - ffmpgen.addFFTIData(siteDataKey, values); - } + Double gap = getGap(qpeContainer, ffmpQSource, duration, + qSiteKey); + + if (gap != Double.NaN) { + + ArrayList qpes = qpeContainer.getBasinData("ALL") + .getAccumValues(pfafs, backDate, config.getDate(), + expirationTime, false); + + FFMPGuidanceInterpolation interpolator = new FFMPGuidanceInterpolation( + ffmpgen.fscm, product, ffmpgen.frcm.getRunner( + config.getCWA()).getProduct(qSiteKey), + primarySource, ffgType, qSiteKey); + interpolator.setInterpolationSources(duration); + + ArrayList guids = guidContainer.getBasinData("ALL") + .getGuidanceValues(pfafs, interpolator, + guidSourceExpiration); + + values.setQpes(qpes); + values.setGuids(guids); + values.setGap(gap); + } + } else { + return values; + } + + // replace or insert it + values.setReset(false); + ffmpgen.writeFFTIData(siteDataKey, values); + } return values; } @@ -1025,7 +1060,7 @@ public class FFTI implements Runnable { for (FFMPGap gap : gaps) { gapVal += gap.getGap(); } - + gapVal = gapVal / 60; } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java index c8b240798a..bd15a91443 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java @@ -19,6 +19,14 @@ **/ package com.raytheon.uf.edex.plugin.ffmp.common; +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.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + /** * FFTIAccum * @@ -34,11 +42,15 @@ package com.raytheon.uf.edex.plugin.ffmp.common; * @author dhladky * @version 1.0 */ - +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +@DynamicSerialize public class FFTIAccum extends FFTIData { + @DynamicSerializeElement + @XmlElement private Double accumulation = 0.0; - + public Double getAccumulation() { return accumulation; } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java index b91432139f..8ef8dcb43c 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java @@ -1,5 +1,14 @@ package com.raytheon.uf.edex.plugin.ffmp.common; +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.serialization.ISerializableObject; +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. @@ -36,19 +45,32 @@ package com.raytheon.uf.edex.plugin.ffmp.common; * @version 1.0 */ -public class FFTIData { - - private Double gap = 0.0; - - private Double duration = 0.0; - - private String name = null; - - private String unit = null; - - private boolean isReset = true; +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +@DynamicSerialize +public class FFTIData implements ISerializableObject { - /** + @DynamicSerializeElement + @XmlElement + private Double gap = 0.0; + + @DynamicSerializeElement + @XmlElement + private Double duration = 0.0; + + @DynamicSerializeElement + @XmlElement + private String name = null; + + @DynamicSerializeElement + @XmlElement + private String unit = null; + + @DynamicSerializeElement + @XmlElement + private boolean reset = true; + + /** * @param name * the name to set */ @@ -62,15 +84,15 @@ public class FFTIData { public String getName() { return name; } - - public Double getGap() { + + public Double getGap() { return gap; } public void setGap(Double gap) { this.gap = gap; } - + public Double getDuration() { return duration; } @@ -78,7 +100,7 @@ public class FFTIData { public void setDuration(Double duration) { this.duration = duration; } - + /** * @param unit * the unit to set @@ -93,21 +115,13 @@ public class FFTIData { public String getUnit() { return unit; } - - /** - * Change status - * @param isReset - */ - public void reset(boolean isReset) { - this.isReset = isReset; - } - - /** - * Check status - * @return - */ + public boolean isReset() { - return isReset; + return reset; + } + + public void setReset(boolean reset) { + this.reset = reset; } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java index 98bac0f5cc..d371da2ad1 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java @@ -35,7 +35,6 @@ import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager; import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager.SOURCE_TYPE; import com.raytheon.uf.common.monitor.xml.FFTISourceXML; -import com.raytheon.uf.common.monitor.xml.ProductXML; import com.raytheon.uf.common.monitor.xml.SourceXML; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -54,7 +53,7 @@ import com.raytheon.uf.edex.plugin.ffmp.FFMPGenerator; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 01, 2011 dhladky Initial creation - * + * July 11, 2012 dhladky Edited for FFTI work * * * @author dhladky @@ -71,18 +70,12 @@ public class FFTIProcessor { private FFMPGenerator ffmpgen = null; - private String wfo = null; - - private Date ffgBarrierTime = null; - - private FFMPDataContainer sourceContainer = null; - /** Pattern for dates in radar */ public static String datePattern = "yyyy-MM-dd HH:mm:ss"; - + /** 6 hour back time multiplier */ public static long backTime = 3600 * 1000 * 6; - + /** FFG back time multiplier */ public static long ffgbackTime = 3600 * 1000 * 24; @@ -100,321 +93,214 @@ public class FFTIProcessor { this.ffmpgen = ffmpgen; this.ffmpRec = ffmpRec; this.fftiSource = fftiSource; - this.wfo = ffmpRec.getWfo(); - long curr = ffmpRec.getDataTime().getRefTime().getTime(); - long fftiFFGBarrier = (long) (24.0 * 60.0 * 60.0 * 1000); - this.ffgBarrierTime = new Date(curr - fftiFFGBarrier); } /** * Process FFTI for this source */ public void processFFTI() { - ArrayList dispNameList = fftiSource.getDisplayNameList(); - for (String sourceNameString : dispNameList) { - - String iSiteKey = ffmpRec.getSiteKey(); - String iDataKey = ffmpRec.getDataKey(); - String sourceString = sourceNameString; - - String[] parts = sourceNameString.split("-"); - SourceXML source = null; - if (parts.length > 1) { - iSiteKey = parts[0]; - String sourceName = parts[1]; - source = FFMPSourceConfigurationManager.getInstance() - .getSource(sourceName); - } else { - // mosaic source - source = FFMPSourceConfigurationManager.getInstance() - .getSourceByDisplayName(sourceString); - } + ArrayList dispNameList = fftiSource.getDisplayNameList(); + String iSiteKey = ffmpRec.getSiteKey(); + String iDataKey = ffmpRec.getDataKey(); - if (source.getSourceType().equals( - FFMPSourceConfigurationManager.SOURCE_TYPE.GUIDANCE - .getSourceType())) { - - sourceString = source.getDisplayName(); - - // Mark all GUIDANCE related sources as dirty for FFTI - for (String fftiName: ffmpgen.getFFTIDataContainer().keySet()) { - if (fftiName.startsWith(sourceString)) { - System.out.println("Resetting FFTI source for processing!!!!! "+fftiName); - ffmpgen.getFFTIData(fftiName).reset(true); - } - } - - } else { - - sourceString = source.getDisplayName() + "-" + iSiteKey + "-"+ iDataKey; - - // Mark this source as dirty for FFTI - if (ffmpgen.isFFTI(sourceString)) { - //System.out.println("Resetting FFTI source for processing!!!!! "+sourceString); - ffmpgen.getFFTIData(sourceString).reset(true); - - // Mark associated sources as dirty for FFTI - for (String fftiName: ffmpgen.getFFTIDataContainer().keySet()) { - String[] name = fftiName.split("-"); - if (name.length == 3) { - if (name[1].equals(source.getDisplayName()) && name[2].equals(iDataKey)) { - //System.out.println("Resetting FFTI source for processing!!!!! "+fftiName); - ffmpgen.getFFTIData(fftiName).reset(true); - } - } - } - } - } - - Date backDate = new Date(ffmpRec.getDataTime().getRefTime().getTime() - - (backTime)); - ArrayList hucs = new ArrayList(); - hucs.add("ALL"); + for (String sourceNameString : dispNameList) { - sourceContainer = ffmpgen.getFFMPDataContainer(sourceString, hucs, backDate); + String sourceString = sourceNameString; - // we attempt to reload sources - // this is done to keep all of the clustered - // FFMP's in sync. otherwise one JVM would never - // be updated with what the other had processed. - if (sourceContainer == null) { - // first time being read - // check back this far for an existing file - boolean reload = false; + String[] parts = sourceNameString.split("-"); + SourceXML source = null; - if (source.getSourceType() - .equals(FFMPSourceConfigurationManager.SOURCE_TYPE.GUIDANCE - .getSourceType())) { - reload = true; - } + if (parts.length > 1) { + iSiteKey = parts[0]; + sourceString = parts[1]; + } - if (reload) { - sourceContainer = new FFMPDataContainer(sourceString); - } - } + source = FFMPSourceConfigurationManager.getInstance() + .getSourceByDisplayName(sourceString); - if (sourceContainer != null) { - - boolean write = false; - - if (source.getSourceType().equals( - SOURCE_TYPE.GUIDANCE.getSourceType())) { + // System.out.println("Source XML: "+source.getDisplayName()); - String primarySource = ffmpgen.fscm - .getPrimarySource(source); - ProductXML product = ffmpgen.fscm.getProduct(primarySource); - Date ffgBackDate = new Date(ffmpRec.getDataTime() - .getRefTime().getTime() - - (ffgbackTime)); + if (source != null) { - // try to load any missing one's, other than the new one - for (SourceXML guidSource : product - .getGuidanceSourcesByType(source.getDisplayName())) { - if (!sourceContainer.containsKey(guidSource - .getSourceName()) - && !source.getSourceName().equals( - guidSource.getSourceName())) { - - sourceContainer = populateDataContainer( - sourceContainer, ffmpgen.template, null, - ffgBackDate, ffmpRec.getDataTime() - .getRefTime(), wfo, source, - iSiteKey); - - sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); - write = true; - } - } + if (source.getSourceType().equals( + FFMPSourceConfigurationManager.SOURCE_TYPE.GUIDANCE + .getSourceType())) { - } /*else { + sourceString = source.getDisplayName(); - Date newDate = sourceContainer.getNewest(); - Date oldDate = sourceContainer.getOldest(); + // Mark all GUIDANCE related sources as dirty for FFTI + for (String fftiName : ffmpgen.getFFTIDataContainer() + .keySet()) { + if (fftiName.startsWith(sourceString)) { + // System.out + // .println("Resetting FFTI source for processing!!!!! " + // + fftiName); + ffmpgen.getFFTIData(fftiName).setReset(true); + } + } - if (newDate != null && oldDate != null) { - if ((ffmpRec.getDataTime().getRefTime().getTime() - newDate - .getTime()) >= (source - .getExpirationMinutes(iSiteKey) * 60 * 1000)) { - // force a re-query back to the newest time in - // existing source container - sourceContainer = populateDataContainer( - sourceContainer, ffmpgen.template, null, - newDate, - ffmpRec.getDataTime().getRefTime(), wfo, - source, iSiteKey); - - sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); - write = true; - - } else if (oldDate - .after(new Date( - barrierTime.getTime() - - (source - .getExpirationMinutes(iSiteKey) * 60 * 1000)))) { - // force a re-query back to barrierTime for - // existing source container - sourceContainer = populateDataContainer( - sourceContainer, ffmpgen.template, null, - barrierTime, oldDate, wfo, source, iSiteKey); - - sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); - write = true; - } - } else { - // COMPLETELY EMPTY SOURCE CONTAINER - // force a re-query back to barrierTime from current - // refTime - sourceContainer = populateDataContainer( - sourceContainer, ffmpgen.template, null, - barrierTime, - ffmpRec.getDataTime().getRefTime(), wfo, - source, iSiteKey); - - sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); - write = true; - } - } - - */ - - if (write) { - sourceContainer.purge(ffgBarrierTime); - //System.out.println("Writing from with in the FFTI Processor!!! "+sourceContainer.getFilePath()); - ffmpgen.writeLoaderBuddyFiles(sourceContainer); - } - } - } - } + } else { - /** - * Populates the FFTI Data back to the determined date - * - * @param sourceContainer - * @param template - * @param startDate - * @param endDate - * @param wfo - * @param source - * @return - */ - public static FFMPDataContainer populateDataContainer( - FFMPDataContainer sourceContainer, FFMPTemplates template, - ArrayList hucs, Date startDate, Date endDate, String wfo, - SourceXML source, String siteKey) { + sourceString = source.getDisplayName() + "-" + iSiteKey + + "-" + iDataKey; - ArrayList uris = getUris(startDate, endDate, wfo, source, - siteKey); - // System.out.println("Number of Records querried: " + siteKey + " : " - // + uris.size()); + // Mark this source as dirty for FFTI + if (ffmpgen.isFFTI(sourceString)) { + // System.out + // .println("Resetting FFTI source for processing!!!!! " + // + sourceString); + ffmpgen.getFFTIData(sourceString).setReset(true); - for (String uri : uris) { + // Mark associated sources as dirty for FFTI + for (String fftiName : ffmpgen.getFFTIDataContainer() + .keySet()) { + String[] name = fftiName.split("-"); + if (name.length == 3) { + if (name[1].equals(source.getDisplayName()) + && name[2].equals(iDataKey)) { + // System.out + // .println("Resetting FFTI source for processing!!!!! " + // + fftiName); + ffmpgen.getFFTIData(fftiName) + .setReset(true); + } + } + } + } + } + } + } + } - FFMPRecord rec = new FFMPRecord(uri); + /** + * Populates the FFTI Data back to the determined date + * + * @param sourceContainer + * @param template + * @param startDate + * @param endDate + * @param wfo + * @param source + * @return + */ + public static FFMPDataContainer populateDataContainer( + FFMPDataContainer sourceContainer, FFMPTemplates template, + ArrayList hucs, Date startDate, Date endDate, String wfo, + SourceXML source, String siteKey) { - boolean contains = false; + ArrayList uris = getUris(startDate, endDate, wfo, source, + siteKey); + // System.out.println("Number of Records querried: " + siteKey + " : " + // + uris.size()); - if (source.getSourceType().equals( - SOURCE_TYPE.GUIDANCE.getSourceType())) { - contains = sourceContainer.containsKey(source.getSourceName()); - // System.out.println("Processing FFG source!!!!!" - // + source.getSourceName()); - } else { - contains = sourceContainer.containsKey(rec.getDataTime() - .getRefTime()); - } + for (String uri : uris) { - if (!contains) { - try { - - if (hucs == null) { - hucs = new ArrayList(); - hucs.add("ALL"); - } - - for (String huc : hucs) { + FFMPRecord rec = new FFMPRecord(uri); - rec = populateRecord(rec, huc, template); - FFMPBasinData newData = rec.getBasinData(huc); - sourceContainer.addFFMPEntry(rec.getDataTime() - .getRefTime(), source, newData, huc, siteKey); + boolean contains = false; - } + if (source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + contains = sourceContainer.containsKey(source.getSourceName()); + // System.out.println("Processing FFG source!!!!!" + // + source.getSourceName()); + } else { + contains = sourceContainer.containsKey(rec.getDataTime() + .getRefTime()); + } - // System.out.println("Adding Time: " - // + rec.getDataTime().getRefTime()); + if (!contains) { + try { - } catch (PluginException e) { - e.printStackTrace(); - statusHandler.handle(Priority.ERROR, - "Source: " + source.getDisplayName() + " domain: " - + wfo - + " : failed to retrieve FFMP/FFTI Data "); - } - } - } + if (hucs == null) { + hucs = new ArrayList(); + hucs.add("ALL"); + } - return sourceContainer; - } + for (String huc : hucs) { - /** - * Get the uris for this FFTI source - * - * @param startDate - * @param endDate - * @param wfo - * @param source - * @return - */ - public static ArrayList getUris(Date startDate, Date endDate, - String wfo, SourceXML source, String siteKey) { + rec = populateRecord(rec, huc, template); + FFMPBasinData newData = rec.getBasinData(huc); + sourceContainer.addFFMPEntry(rec.getDataTime() + .getRefTime(), source, newData, huc, siteKey); - SimpleDateFormat datef = new SimpleDateFormat(datePattern); - datef.setTimeZone(TimeZone.getTimeZone("Zulu")); - StringBuilder query = new StringBuilder(200); + } - query.append("select datauri from ffmp where wfo = '"); - query.append(wfo); - query.append("' and sourcename = '"); - query.append(source.getSourceName()); - query.append("' and sitekey = '"); - query.append(siteKey); - if (!source.isMosaic()) { - query.append("' and datakey = '"); - query.append(siteKey); - } - query.append("' and reftime >= '"); - query.append(datef.format(startDate)); - query.append("' and reftime < '"); - query.append(datef.format(endDate)); + // System.out.println("Adding Time: " + // + rec.getDataTime().getRefTime()); - query.append("' order by reftime desc"); - // System.out.println("URI query: " + query.toString()); + } catch (PluginException e) { + e.printStackTrace(); + statusHandler.handle(Priority.ERROR, + "Source: " + source.getDisplayName() + " domain: " + + wfo + + " : failed to retrieve FFMP/FFTI Data "); + } + } + } - ArrayList uris = new ArrayList(); + return sourceContainer; + } - try { - CoreDao dao = new CoreDao(DaoConfig.forDatabase(FFMPUtils.META_DB)); - Object[] results = dao.executeSQLQuery(query.toString()); + /** + * Get the uris for this FFTI source + * + * @param startDate + * @param endDate + * @param wfo + * @param source + * @return + */ + public static ArrayList getUris(Date startDate, Date endDate, + String wfo, SourceXML source, String siteKey) { - if (results.length > 0) { - for (int i = 0; i < results.length; i++) { - Object result = results[i]; - if (result != null) { - /* - * System.out.println("Adding URI to FFTI list: " + - * (String) result); - */ - uris.add((String) result); - } - } - } + SimpleDateFormat datef = new SimpleDateFormat(datePattern); + datef.setTimeZone(TimeZone.getTimeZone("Zulu")); + StringBuilder query = new StringBuilder(200); - } catch (Exception e) { - statusHandler.handle(Priority.ERROR, - "Source: " + source.getSourceName() + " domain: " + wfo - + " : failed to query"); - } + query.append("select datauri from ffmp where wfo = '"); + query.append(wfo); + query.append("' and sourcename = '"); + query.append(source.getSourceName()); + query.append("' and sitekey = '"); + query.append(siteKey); + if (!source.isMosaic()) { + query.append("' and datakey = '"); + query.append(siteKey); + } + query.append("' and reftime >= '"); + query.append(datef.format(startDate)); + query.append("' and reftime < '"); + query.append(datef.format(endDate)); + + query.append("' order by reftime desc"); + // System.out.println("URI query: " + query.toString()); + + ArrayList uris = new ArrayList(); + + try { + CoreDao dao = new CoreDao(DaoConfig.forDatabase(FFMPUtils.META_DB)); + Object[] results = dao.executeSQLQuery(query.toString()); + + if (results.length > 0) { + for (int i = 0; i < results.length; i++) { + Object result = results[i]; + if (result != null) { + /* + * System.out.println("Adding URI to FFTI list: " + + * (String) result); + */ + uris.add((String) result); + } + } + } + + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "Source: " + source.getSourceName() + " domain: " + wfo + + " : failed to query"); + } return uris; } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java index 8f088bb4b4..e8c16cdffe 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java @@ -22,6 +22,15 @@ package com.raytheon.uf.edex.plugin.ffmp.common; import java.util.ArrayList; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + /** * FFTIRatioDiff * @@ -38,16 +47,23 @@ import java.util.ArrayList; * @version 1.0 */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +@DynamicSerialize public class FFTIRatioDiff extends FFTIData { + @DynamicSerializeElement + @XmlElements({ @XmlElement(name = "qpe", type = Float.class) }) private ArrayList qpes; + @DynamicSerializeElement + @XmlElements({ @XmlElement(name = "guid", type = Float.class) }) private ArrayList guids; - + public FFTIRatioDiff() { - + } - + public FFTIRatioDiff(ArrayList qpes, ArrayList guids, Double gap) { setQpes(qpes); @@ -70,5 +86,5 @@ public class FFTIRatioDiff extends FFTIData { public void setGuids(ArrayList guids) { this.guids = guids; } - + } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/edex_static/base/roles/userRoles.xml b/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/edex_static/base/roles/userRoles.xml index 910eab1ac4..c4a9488fad 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/edex_static/base/roles/userRoles.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/edex_static/base/roles/userRoles.xml @@ -133,6 +133,16 @@ + + diff --git a/edexOsgi/com.raytheon.uf.edex.site/src/com/raytheon/uf/edex/site/SiteAwareRegistry.java b/edexOsgi/com.raytheon.uf.edex.site/src/com/raytheon/uf/edex/site/SiteAwareRegistry.java index accf9abff2..d4a94c0b57 100644 --- a/edexOsgi/com.raytheon.uf.edex.site/src/com/raytheon/uf/edex/site/SiteAwareRegistry.java +++ b/edexOsgi/com.raytheon.uf.edex.site/src/com/raytheon/uf/edex/site/SiteAwareRegistry.java @@ -25,7 +25,7 @@ import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; @@ -58,6 +58,8 @@ import com.raytheon.uf.edex.site.SiteActivationMessage.Action; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 30, 2010 rjpeter Initial creation + * Jul 31, 2012 #965 dgilling Force ordering of sites in + * getActiveSites(). * * * @@ -136,7 +138,9 @@ public class SiteAwareRegistry { */ public String[] getActiveSites() { // make a set of the strings for each listener site - Set tmp = new HashSet(); + Set tmp = new LinkedHashSet(); + tmp.add(PropertiesFactory.getInstance().getEnvProperties() + .getEnvValue("SITENAME")); for (ISiteActivationListener sa : activationListeners) { tmp.addAll(sa.getActiveSites()); } @@ -160,8 +164,8 @@ public class SiteAwareRegistry { } return false; } - - public String validateConfig(String siteID){ + + public String validateConfig(String siteID) { StringBuffer retVal = new StringBuffer(); for (ISiteActivationListener sa : activationListeners) { retVal.append(sa.validateConfig(siteID)); diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/configuration/svcbu.properties b/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/configuration/svcbu.properties index d3d412f86f..2405687e6d 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/configuration/svcbu.properties +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite.servicebackup/svcBackup/ServiceBackup/configuration/svcbu.properties @@ -114,14 +114,14 @@ LOCK_DIR=${GFESUITE_HOME}/ServiceBackup/locks SCRIPTS_DIR=${GFESUITE_HOME}/ServiceBackup/scripts CAVE_LAUNCH_SCRIPT=${AWIPS_HOME}/cave/cave.sh -SVCBU_HOST=localhost +SVCBU_HOST=ec MSG_SEND_COMMAND=msg_send CDSPORT=9581 SVCBU_DB=Official SVCBU_TRIM_ELEMS=1 SVCBU_FAILED_SITE_PORT=98000001 SVCBU_GRIDAREA=ISC_Send_Area -SVCBU_ADDRESSEE=TNCF +SVCBU_ADDRESSEE="ANCF,BNCF" SVCBU_WMO_HEADER=SVCBKPIFP SVCBU_USER=0 SVCBU_USER_ID="" diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/publishGFE b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/publishGFE new file mode 100644 index 0000000000..bb65c312a4 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/publishGFE @@ -0,0 +1,50 @@ +#!/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. +## +############################################################################## +# TODO: ADD DESCRIPTION +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 07/26/12 #965 dgilling Initial Creation. +############################################################################## + +# this allows you to run this script from outside of ./bin +path_to_script=`readlink -f $0` +RUN_FROM_DIR=`dirname $path_to_script` + +BASE_AWIPS_DIR=`dirname $RUN_FROM_DIR` + +# get the base environment +source ${RUN_FROM_DIR}/setup.env + +# setup the environment needed to run the the Python +export LD_LIBRARY_PATH=${BASE_AWIPS_DIR}/src/lib:${PYTHON_INSTALL}/lib +export PYTHONPATH=${RUN_FROM_DIR}/src:$PYTHONPATH + +# execute the ifpInit Python module +_PYTHON="${PYTHON_INSTALL}/bin/python" +_MODULE="${RUN_FROM_DIR}/src/publishgfe/publishGFE.py" + +# quoting of '$@' is used to prevent command line interpretation +$_PYTHON $_MODULE -h ${DEFAULT_HOST} -r ${DEFAULT_PORT} "$@" + diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsyncGridsToCWF.sh b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsyncGridsToCWF.sh index eead9e0880..11c901cb0d 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsyncGridsToCWF.sh +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsyncGridsToCWF.sh @@ -204,13 +204,8 @@ remDirectory1="netcdf-wfo" # Directory where grids are stored on the mask=ISC_Send_Area # Parameter list for the netcdf file -parmlist1="-p MaxT -p MinT -p MaxRH -p MinRH -p T -p Td -p RH -p WindChill -p HeatIndex -p ApparentT" -parmlist2="-p PoP -p PoP12 -p Sky -p Wx -p Hazards -p SnowLevel -p QPF -p SnowAmt -p IceAccum -p Wind -p WindGust" -parmlist3="-p ClearIndex -p FreeWind -p LAL -p Haines -p MixHgt -p VentRate -p TransWind -p Wind20ft -p CLRIndx" -parmlist5="" -parmlist6="" -parmlist="$parmlist1 $parmlist2 $parmlist3 $parmlist4 $parmlist5 $parmlist6" -parmlist="" #uncomment to send all parameters +parmlist="" #send all parameters +. ${IFPS_DATA}/rsync_parms.${1} creationAttempts=3 # How many times do you want script to create and # quality control netcdf files if bad netcdf files @@ -237,11 +232,7 @@ FXA_BIN="/awips2/fxa/bin" CDSHOST="ec" CDSPORT="9581" -# It is possible that you may not have all of the parameters that your service backup sites -# need sent to the webfarms. So if script is run for a backup site, then send all parameters. -parmlist=" " - -# Setting up the infrastructure for a log file. +# set current data and log file name currdate=$(date -u +%Y%m%d) export LOG_FILE="${DXwrkDir}/log/${currdate}/netcdf_rsync.log" @@ -281,6 +272,12 @@ find ${WRKDIR}/. -mmin +60 -exec rm {} -f \; echo ...finished. >> $LOG_FILE echo " " >> $LOG_FILE +if [ "$parmlist" != "" ]; then + echo "Will trim elements to $parmlist" >> $LOG_FILE +else + echo "Will send all elements" >> $LOG_FILE +fi + # Determine the ifpnetCDF start and end times. start_time=$(date +%Y%m%d_%H00 -d "6 hours ago") end_time=$(date +%Y%m%d_%H00 -d "192 hours") diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsync_parms.ccc b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsync_parms.ccc new file mode 100644 index 0000000000..d4613a9b00 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsync_parms.ccc @@ -0,0 +1,8 @@ +# Parameter list for the netcdf file +# Example: parmlist1="-p ClearIndex -p MaxT" +parmlist1="" +parmlist2="" +parmlist3="" +parmlist5="" +parmlist6="" +parmlist="$parmlist1 $parmlist2 $parmlist3 $parmlist4 $parmlist5 $parmlist6" diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/ifpservertext/ifpServerText.py b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/ifpservertext/ifpServerText.py index d3924bae35..23a6e29aa5 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/ifpservertext/ifpServerText.py +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/ifpservertext/ifpServerText.py @@ -23,7 +23,6 @@ import sys, os, pwd, string, getopt, logging import numpy from dynamicserialize.dstypes.com.raytheon.uf.common.auth.resp import SuccessfulExecution -from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetActiveSitesRequest from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetSingletonDbIdsRequest from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetSiteTimeZoneInfoRequest from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GridLocRequest @@ -39,6 +38,7 @@ from dynamicserialize.dstypes.com.raytheon.uf.common.localization.stream import from dynamicserialize.dstypes.com.raytheon.uf.common.message import WsId from dynamicserialize.dstypes.com.raytheon.uf.common.plugin.nwsauth.user import User from dynamicserialize.dstypes.com.raytheon.uf.common.plugin.nwsauth.user import UserId +from dynamicserialize.dstypes.com.raytheon.uf.common.site.requests import GetActiveSitesRequest from ufpy import ThriftClient # @@ -72,26 +72,18 @@ class textInventoryRecord: return str(self.localCtx) + self.path + "/" + self.fileName ## Logging methods ## +logger = None def __initLogger(): - logger = logging.getLogger("ifpServerText.py") - logger.setLevel(logging.INFO) + global logger + logger = logging.getLogger("purgeAllModelData") + logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.INFO) + # Uncomment line below to enable debug-level logging + # ch.setLevel(logging.DEBUG) formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s", "%H:%M:%S") ch.setFormatter(formatter) logger.addHandler(ch) - -def logEvent(msg): - logging.getLogger("ifpServerText.py").info(msg) - -def logProblem(msg): - logging.getLogger("ifpServerText.py").error(msg) - -def logException(msg): - logging.getLogger("ifpServerText.py").exception(msg) - -def logVerbose(msg): - logging.getLogger("ifpServerText.py").debug(msg) class ifpServerText: @@ -110,7 +102,9 @@ class ifpServerText: "TextProduct": ".py", "TextUtility": ".py", "Utility": ".py", - "Combinations": ".py"} + "Combinations": ".py", + "ISCUtility": ".py" + } LOCALIZATION_DICT = {"Config": ("CAVE_STATIC", "gfe/userPython/gfeConfig"), "EditArea": ("COMMON_STATIC", "gfe/editAreas"), @@ -124,7 +118,9 @@ class ifpServerText: "TextProduct": ("CAVE_STATIC", "gfe/userPython/textProducts"), "TextUtility": ("CAVE_STATIC", "gfe/userPython/textUtilities/regular"), "Utility": ("CAVE_STATIC", "gfe/userPython/utilities"), - "Combinations": ("CAVE_STATIC", "gfe/combinations")} + "Combinations": ("CAVE_STATIC", "gfe/combinations"), + "ISCUtility": ("COMMON_STATIC", "isc/utilities") + } def __init__(self): self.__host = None @@ -237,7 +233,7 @@ class ifpServerText: options = ["Tool", "Procedure", "Utility", "TextUtility", "TextProduct", "Config", "EditArea", "SelectTR", "EditAreaGroup", "SampleSet", "WeatherElementGroup", - "ColorTable", "Combinations", "SmartTool"] + "ColorTable", "Combinations", "SmartTool", "ISCUtility"] if opt[1] not in options: self.__usage() s = "Error: Illegal class specified " + opt[1] @@ -254,7 +250,7 @@ class ifpServerText: "SelectTR": "SELECTTR", "Tool": "Tool", "Procedure": "Procedure", "TextProduct": "TextProduct", "TextUtility": "TextUtility", "Utility": "Utility", - "Combinations": "COMBINATIONS"} + "Combinations": "COMBINATIONS", "ISCUtility": "ISCUtility"} self.__textCategory = dic[self.__classType] elif opt[0] == '-s': if self.__mode is not None: @@ -501,7 +497,7 @@ Usage: ifpServerText -h hostname -p rpcPortNumber -o siteID [-u user] except Exception, e: raise RuntimeError("Could not send file to localization server: " + str(e)) - logEvent("Saved file " + self.__filename + " under " + self.__name) + logger.info("Saved file " + self.__filename + " under " + self.__name) def __deleteText(self): #Deletes a text file @@ -546,7 +542,7 @@ Usage: ifpServerText -h hostname -p rpcPortNumber -o siteID [-u user] except Exception, e: raise RuntimeError("Could not delete file from localization server: " + str(e)) - logEvent("Deleted " + self.__name) + logger.info("Deleted " + self.__name) def __getText(self): #Gets the text file @@ -591,7 +587,7 @@ Usage: ifpServerText -h hostname -p rpcPortNumber -o siteID [-u user] f = open(self.__filename, 'w', 0644) f.write(txt) f.close() - logEvent("Got " + self.__name + " --- written to " + self.__filename) + logger.info("Got " + self.__name + " --- written to " + self.__filename) def __inventoryText(self): #Returns the inventory @@ -704,19 +700,14 @@ Usage: ifpServerText -h hostname -p rpcPortNumber -o siteID [-u user] raise Exception, serverResponse.message() elif self.__metaInfo == "site": request = GetActiveSitesRequest() - request.setWorkstationID(wsId) - request.setSiteID("") try: serverResponse = self.__thrift.sendRequest(request) except Exception, e: raise RuntimeError, "Could not retrieve meta information: " + str(e) - if (serverResponse.isOkay()): - sites = serverResponse.getPayload() - for s in sites: - txt = txt + s + "\n" - else: - raise Exception, serverResponse.message() + for site in serverResponse: + txt = txt + site + "\n" + elif self.__metaInfo == "singleton": request = GetSingletonDbIdsRequest() request.setWorkstationID(wsId) @@ -759,21 +750,21 @@ Usage: ifpServerText -h hostname -p rpcPortNumber -o siteID [-u user] f = open(self.__filename, 'w', 0644) f.write(txt) f.close() - logEvent("Got MetaInfo " + self.__metaInfo + " --- written to " + self.__filename) + logger.info("Got MetaInfo " + self.__metaInfo + " --- written to " + self.__filename) def main(): __initLogger() - logEvent("ifpServerText Starting") + logger.info("ifpServerText Starting") try: obj = ifpServerText() obj.process() except Exception, e: - logException("Error encountered running ifpServerText:") + logger.exception("Error encountered running ifpServerText:") sys.exit(1) - logEvent("ifpServerText Finished") + logger.info("ifpServerText Finished") sys.exit(0) diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/publishgfe/publishGFE.py b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/publishgfe/publishGFE.py new file mode 100644 index 0000000000..f59911c365 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/publishgfe/publishGFE.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python + +## +# 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. +## + +import argparse +import logging +import sys + +from ufpy import UsageArgumentParser +from ufpy.gfe import IFPClient + +from dynamicserialize.dstypes.com.raytheon.uf.common.time import TimeRange +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.db.objects import DatabaseID +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.db.objects import ParmID +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.server.request import CommitGridRequest + + +logger = None +def __initLogger(): + global logger + logger = logging.getLogger("publishGFE") + logger.setLevel(logging.DEBUG) + ch = logging.StreamHandler() + ch.setLevel(logging.INFO) + # Uncomment line below to enable debug-level logging + # ch.setLevel(logging.DEBUG) + formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s", "%H:%M:%S") + ch.setFormatter(formatter) + logger.addHandler(ch) + +## Custom actions for ArgumentParser object ## +class StoreTimeAction(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + (isValid, dateTime) = DatabaseID.decodeDtg(values) + if isValid: + setattr(namespace, self.dest, dateTime) + else: + parser.error("Argument for option " + option_string + " not in yyyymmdd_hhmm format") + +class AppendParmNameAndLevelAction(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + tx = ParmID.parmNameAndLevel(values) + comp = tx[0] + '_' + tx[1] + if (hasattr(namespace, self.dest)) and \ + (getattr(namespace, self.dest) is not None): + currentValues = getattr(namespace, self.dest) + currentValues.append(comp) + setattr(namespace, self.dest, currentValues) + else: + setattr(namespace, self.dest, [comp]) + +def validateArgs(): + parser = UsageArgumentParser.UsageArgumentParser(prog='publishGFE', conflict_handler="resolve") + parser.add_argument("-h", action="store", dest="host", + help="where the ifpServer is running", + required=True, metavar="hostname") + parser.add_argument("-r", action="store", type=int, dest="port", + help="the port that ifpServer is serving", + required=True, metavar="portNumber") + parser.add_argument("-t", action="store", dest="definedTR", + help="(Optional) named time range, supersedes -s and -e", + default="", metavar="namedTR") + parser.add_argument("-s", action=StoreTimeAction, dest="sT", + help="(Optional) start time, format = yyyymmdd_hhmm", + metavar="startTime") + parser.add_argument("-e", action=StoreTimeAction, dest="eT", + help="(Optional) end time, format = yyyymmdd_hhmm", + metavar="endTime") + parser.add_argument("-u", action="store", dest="user", + help="(Optional) user, defaults to SITE", + default="SITE", metavar="user") + parser.add_argument("-o", action="store", dest="site", + help="(Optional) site to publish grids for, defaults to server's primary site", + metavar="site") + parser.add_argument("-p", action=AppendParmNameAndLevelAction, dest="parmNamesAndLevels", + help="(Optional) parm, can have multiple switches; if none, defaults to all parms.", + default=[], metavar="parm") + options = parser.parse_args() + + tr = TimeRange.allTimes() + if options.sT is not None: + tr.setStart(options.sT) + if options.eT is not None: + tr.setEnd(options.eT) + setattr(options, 'tr', tr) + + return options + +def expandToParmInv(inv, definedTR): + expandedTR = definedTR + for tr in inv: + if tr.overlaps(definedTR): + expandedTR = expandedTR.combineWith(tr) + + return expandedTR + +def main(): + __initLogger() + logger.info("Publish Fcst Data to Official") + + args = validateArgs() + logger.debug("Command-line arguments: " + str(args)) + + # build IFPClient object + db = IFPClient.IFPClient(args.host, args.port, args.user, args.site, "publishGFE") + + # get site id + siteID = args.site + if siteID is None or len(siteID) == 0: + sr = db.getSiteID() + if not sr.isOkay(): + logger.error("Unable to determine site id: " + sr.message()) + sys.exit(1) + siteID = sr.getPayload()[0] + + # calculate list of parms + dbid = DatabaseID(siteID + "_GRID__Fcst_00000000_0000") + sr = db.getParmList(dbid) + if not sr.isOkay(): + logger.error("Unable to determine parms: " + sr.message()) + sys.exit(1) + parmsInDb = sr.getPayload() + commitParmList = [] + if len(args.parmNamesAndLevels) == 0: + commitParmList = parmsInDb + else: + for parm in args.parmNamesAndLevels: + tx = ParmID.parmNameAndLevel(parm) + found = False + for dbParm in parmsInDb: + if dbParm.getParmName() == tx[0] and dbParm.getParmLevel() == tx[1]: + commitParmList.append(dbParm) + found = True + if not found: + logger.warning("Unable to find parm [" + str(parm) + "] in database [" + str(dbid) + "]") + + # calculate time ranges + tr = args.tr + if len(args.definedTR) > 0: + sr = db.getSelectTR(args.definedTR) + if not sr.isOkay(): + logger.error("Unable to find select tr definition: " + sr.message()) + sys.exit(1) + tr = sr.getPayload() + + # CommitGridRequest(parmid, commitTime) + requests = [] + for parm in commitParmList: + inv = [] + sr = db.getGridInventory(parm) + if not sr.isOkay(): + logger.error("Unable to get grid inventory: " + sr.message()) + sys.exit(1) + inv = sr.getPayload() + expandTR = expandToParmInv(inv, tr) + req = CommitGridRequest() + req.setParmId(parm) + req.setTimeRange(expandTR) + requests.append(req) + logger.debug(parm.getParmName() + ' ' + str(tr)) + + # commit grid + sr = db.commitGrid(requests) + if not sr.isOkay(): + logger.error("Unable to publish grids: " + sr.message()) + sys.exit(1) + else: + logger.info("Publish completed.") + + +if __name__ == '__main__': + main() diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/__init__.py index cae498053c..2c658821b8 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/__init__.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/__init__.py @@ -33,6 +33,7 @@ __all__ = [ 'pointdata', 'pypies', 'serialization', + 'site', 'time' ] diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmID.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmID.py index e5a9a48328..68d276abfa 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmID.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmID.py @@ -119,13 +119,25 @@ class ParmID(object): if not self.parmLevel.isalnum(): return False - return True - + return True @staticmethod def defaultLevel(): return "SFC" + @staticmethod + def parmNameAndLevel(composite): + retValue = [] + + pos = composite.find('_') + if pos != -1: + retValue.append(composite[:pos]) + retValue.append(composite[pos+1:]) + else: + retValue.append(composite) + retValue.append("SFC") + return retValue + def __str__(self): return self.__repr__() diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/CommitGridsRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/CommitGridsRequest.py new file mode 100644 index 0000000000..28d3d2b119 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/CommitGridsRequest.py @@ -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. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class CommitGridsRequest(object): + + def __init__(self): + self.commits = None + self.workstationID = None + self.siteID = None + + def getCommits(self): + return self.commits + + def setCommits(self, commits): + self.commits = commits + + def getWorkstationID(self): + return self.workstationID + + def setWorkstationID(self, workstationID): + self.workstationID = workstationID + + def getSiteID(self): + return self.siteID + + def setSiteID(self, siteID): + self.siteID = siteID + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetParmListRequest.py similarity index 87% rename from pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.py rename to pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetParmListRequest.py index 2e8732d9b7..ebb93968b8 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetParmListRequest.py @@ -20,12 +20,19 @@ # File auto-generated against equivalent DynamicSerialize Java class -class GetActiveSitesRequest(object): +class GetParmListRequest(object): def __init__(self): + self.dbIds = None self.workstationID = None self.siteID = None + def getDbIds(self): + return self.dbIds + + def setDbIds(self, dbIds): + self.dbIds = dbIds + def getWorkstationID(self): return self.workstationID diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.py new file mode 100644 index 0000000000..24910d1417 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.py @@ -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. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class GetSelectTimeRangeRequest(object): + + def __init__(self): + self.name = None + self.workstationID = None + self.siteID = None + + def getName(self): + return self.name + + def setName(self, name): + self.name = name + + def getWorkstationID(self): + return self.workstationID + + def setWorkstationID(self, workstationID): + self.workstationID = workstationID + + def getSiteID(self): + return self.siteID + + def setSiteID(self, siteID): + self.siteID = siteID + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/__init__.py index b9333b2865..c969f576df 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/__init__.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/__init__.py @@ -21,21 +21,25 @@ # File auto-generated by PythonFileGenerator __all__ = [ + 'CommitGridsRequest', 'ConfigureTextProductsRequest', 'CreateNetCDFGridRequest', 'ExecuteIscMosaicRequest', 'GetASCIIGridsRequest', - 'GetActiveSitesRequest', 'GetGridDataRequest', 'GetGridInventoryRequest', 'GetLockTablesRequest', - 'GetPythonGridDataRequest', 'GetOfficialDbNameRequest', + 'GetParmListRequest', + 'GetPythonGridDataRequest', + 'GetSelectTimeRangeRequest', 'GetSingletonDbIdsRequest', 'GetSiteTimeZoneInfoRequest', 'GridLocRequest', 'IscDataRecRequest', 'LockChangeRequest', + 'ProcessReceivedConfRequest', + 'ProcessReceivedDigitalDataRequest', 'PurgeGfeGridsRequest', 'SaveASCIIGridsRequest', 'SendGridsToNDFDRequest', @@ -43,21 +47,25 @@ __all__ = [ 'SmartInitRequest' ] +from CommitGridsRequest import CommitGridsRequest from ConfigureTextProductsRequest import ConfigureTextProductsRequest from CreateNetCDFGridRequest import CreateNetCDFGridRequest from ExecuteIscMosaicRequest import ExecuteIscMosaicRequest from GetASCIIGridsRequest import GetASCIIGridsRequest -from GetActiveSitesRequest import GetActiveSitesRequest from GetGridDataRequest import GetGridDataRequest from GetGridInventoryRequest import GetGridInventoryRequest from GetLockTablesRequest import GetLockTablesRequest -from GetPythonGridDataRequest import GetPythonGridDataRequest from GetOfficialDbNameRequest import GetOfficialDbNameRequest +from GetParmListRequest import GetParmListRequest +from GetPythonGridDataRequest import GetPythonGridDataRequest +from GetSelectTimeRangeRequest import GetSelectTimeRangeRequest from GetSingletonDbIdsRequest import GetSingletonDbIdsRequest from GetSiteTimeZoneInfoRequest import GetSiteTimeZoneInfoRequest from GridLocRequest import GridLocRequest from IscDataRecRequest import IscDataRecRequest from LockChangeRequest import LockChangeRequest +from ProcessReceivedConfRequest import ProcessReceivedConfRequest +from ProcessReceivedDigitalDataRequest import ProcessReceivedDigitalDataRequest from PurgeGfeGridsRequest import PurgeGfeGridsRequest from SaveASCIIGridsRequest import SaveASCIIGridsRequest from SendGridsToNDFDRequest import SendGridsToNDFDRequest diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/CommitGridRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/CommitGridRequest.py new file mode 100644 index 0000000000..8b42939a87 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/CommitGridRequest.py @@ -0,0 +1,54 @@ +## +# 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. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class CommitGridRequest(object): + + def __init__(self): + self.parmId = None + self.dbId = None + self.timeRange = None + self.clientSendStatus = False + + def getParmId(self): + return self.parmId + + def setParmId(self, parmId): + self.parmId = parmId + + def getDbId(self): + return self.dbId + + def setDbId(self, dbId): + self.dbId = dbId + + def getTimeRange(self): + return self.timeRange + + def setTimeRange(self, timeRange): + self.timeRange = timeRange + + def getClientSendStatus(self): + return self.clientSendStatus + + def setClientSendStatus(self, clientSendStatus): + self.clientSendStatus = bool(clientSendStatus) + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/__init__.py index a96cf2cb49..7c56d14258 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/__init__.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/__init__.py @@ -21,11 +21,13 @@ # File auto-generated by PythonFileGenerator __all__ = [ + 'CommitGridRequest', 'GetGridRequest', 'LockRequest', 'LockTableRequest' ] +from CommitGridRequest import CommitGridRequest from GetGridRequest import GetGridRequest from LockRequest import LockRequest from LockTableRequest import LockTableRequest diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/__init__.py new file mode 100644 index 0000000000..d9702fd5d7 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/__init__.py @@ -0,0 +1,27 @@ +## +# 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. +## + +# File auto-generated by PythonFileGenerator + +__all__ = [ + 'requests' + ] + + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.py new file mode 100644 index 0000000000..747ee0320c --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.py @@ -0,0 +1,27 @@ +## +# 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. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class GetActiveSitesRequest(object): + + def __init__(self): + super(GetActiveSitesRequest, self).__init__() + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/__init__.py new file mode 100644 index 0000000000..f3ddd21199 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/__init__.py @@ -0,0 +1,28 @@ +## +# 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. +## + +# File auto-generated by PythonFileGenerator + +__all__ = [ + 'GetActiveSitesRequest' + ] + +from GetActiveSitesRequest import GetActiveSitesRequest + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/time/TimeRange.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/time/TimeRange.py index c521efdba5..a30d4e0316 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/time/TimeRange.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/time/TimeRange.py @@ -27,9 +27,9 @@ import time MAX_TIME = 2147483647 class TimeRange(object): - def __init__(self): - self.start = None - self.end = None + def __init__(self, start=None, end=None): + self.start = self.__convertToDateTime(start) + self.end = self.__convertToDateTime(end) def __str__(self): return self.__repr__() @@ -42,6 +42,21 @@ class TimeRange(object): def __ne__(self, other): return (not self.__eq__(other)) + + def __convertToDateTime(self, timeArg): + if timeArg is None: + return None + if isinstance(timeArg, datetime.datetime): + return timeArg + elif isinstance(timeArg, time.struct_time): + return datetime.datetime(*timeArg[:6]) + else: + totalSecs = long(timeArg) + if totalSecs < MAX_TIME: + return datetime.datetime.utcfromtimestamp(totalSecs) + else: + extraTime = datetime.timedelta(seconds=(totalSecs - MAX_TIME)) + return datetime.datetime.utcfromtimestamp(MAX_TIME) + extraTime def getStart(self): return self.start.utctimetuple() @@ -50,17 +65,7 @@ class TimeRange(object): return long(calendar.timegm(self.getStart()) * 1000) def setStart(self, start): - if isinstance(start, datetime.datetime): - self.start = start - elif isinstance(start, time.struct_time): - self.start = datetime.datetime(*start[:6]) - else: - totalSecs = long(start) - if totalSecs < MAX_TIME: - self.start = datetime.datetime.utcfromtimestamp(totalSecs) - else: - extraTime = datetime.timedelta(seconds=(totalSecs - MAX_TIME)) - self.start = datetime.datetime.utcfromtimestamp(MAX_TIME) + extraTime + self.start = self.__convertToDateTime(start) def getEnd(self): return self.end.utctimetuple() @@ -69,24 +74,43 @@ class TimeRange(object): return long(calendar.timegm(self.getEnd()) * 1000) def setEnd(self, end): - if isinstance(end, datetime.datetime): - self.end = end - elif isinstance(end, time.struct_time): - self.end = datetime.datetime(*end[:6]) - else: - totalSecs = long(end) - if totalSecs < MAX_TIME: - self.end = datetime.datetime.utcfromtimestamp(totalSecs) - else: - extraTime = datetime.timedelta(seconds=(totalSecs - MAX_TIME)) - self.end = datetime.datetime.utcfromtimestamp(MAX_TIME) + extraTime + self.end = self.__convertToDateTime(end) + def duration(self): + delta = self.end - self.start + return long(delta.total_seconds()) + + def contains(self, timeArg): + if isinstance(timeArg, TimeRange): + if self.duration() == 0: + return self.__eq__(timeArg) + elif timeArg.duration() == 0: + return self.contains(timeArg.start) + return (timeArg.start >= self.start and timeArg.end <= self.end) + else: + convTime = self.__convertToDateTime(timeArg) + if type(convTime) is not datetime.datetime: + raise TypeError("Invalid type for argument time specified to TimeRange.contains().") + if self.duration() != 0: + return (convTime >= self.start and convTime < self.end) + return convTime == self.start + def isValid(self): return (self.start != self.end) + def overlaps(self, timeRange): + return (timeRange.contains(self.start) or self.contains(timeRange.start)) + + def combineWith(self, timeRange): + if self.isValid() and timeRange.isValid(): + newStart = min(self.start, timeRange.start) + newEnd = max(self.end, timeRange.end) + return TimeRange(newStart, newEnd) + elif self.isValid(): + return self + + return timeRange + @staticmethod def allTimes(): - tr = TimeRange() - tr.setStart(0) - tr.setEnd(MAX_TIME) - return tr + return TimeRange(0, MAX_TIME) diff --git a/pythonPackages/ufpy/gfe/IFPClient.py b/pythonPackages/ufpy/gfe/IFPClient.py new file mode 100644 index 0000000000..1288094df6 --- /dev/null +++ b/pythonPackages/ufpy/gfe/IFPClient.py @@ -0,0 +1,173 @@ +## +# 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. +## + +from ufpy import ThriftClient + +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.db.objects import DatabaseID +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.db.objects import ParmID +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import CommitGridsRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetGridInventoryRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetParmListRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetSelectTimeRangeRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.server.request import CommitGridRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.message import WsId +from dynamicserialize.dstypes.com.raytheon.uf.common.site.requests import GetActiveSitesRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.server.message import ServerResponse + + +# +# Provides a Python-based interface for executing GFE requests. +# +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 07/26/12 dgilling Initial Creation. +# +# +# + + +class IFPClient(object): + def __init__(self, host, port, user, site=None, progName=None): + self.__thrift = ThriftClient.ThriftClient(host, port) + self.__wsId = WsId(userName=user, progName=progName) + # retrieve default site + if site is None: + sr = self.getSiteID() + if len(sr.getPayload()) > 0: + site = sr.getPayload()[0] + self.__siteId = site + + def commitGrid(self, request): + if type(request) is CommitGridRequest: + return self.__commitGrid([request]) + elif self.__isHomogenousIterable(request, CommitGridRequest): + return self.__commitGrid([cgr for cgr in request]) + raise TypeError("Invalid type: " + str(type(request)) + " specified to commitGrid(). Only accepts CommitGridRequest or lists of CommitGridRequest.") + + def __commitGrid(self, requests): + ssr = ServerResponse() + request = CommitGridsRequest() + request.setCommits(requests) + sr = self.__makeRequest(request) + ssr.setMessages(sr.getMessages()) + return ssr + + def getParmList(self, id): + argType = type(id) + if argType is DatabaseID: + return self.__getParmList([id]) + elif self.__isHomogenousIterable(id, DatabaseID): + return self.__getParmList([dbid for dbid in id]) + raise TypeError("Invalid type: " + str(argType) + " specified to getParmList(). Only accepts DatabaseID or lists of DatabaseID.") + + def __getParmList(self, ids): + ssr = ServerResponse() + request = GetParmListRequest() + request.setDbIds(ids) + sr = self.__makeRequest(request) + ssr.setMessages(sr.getMessages()) + list = sr.getPayload() if sr.getPayload() is not None else [] + ssr.setPayload(list) + return ssr + + def __isHomogenousIterable(self, iterable, classType): + try: + iterator = iter(iterable) + for item in iterator: + if not isinstance(item, classType): + return False + except TypeError: + return False + return True + + def getGridInventory(self, parmID): + if type(parmID) is ParmID: + sr = self.__getGridInventory([parmID]) + list = [] + try: + list = sr.getPayload()[parmID] + except KeyError: + # no-op, we've already default the TimeRange list to empty + pass + sr.setPayload(list) + return sr + elif self.__isHomogenousIterable(parmID, ParmID): + return self.__getGridInventory([id for id in parmID]) + raise TypeError("Invalid type: " + str(type(parmID)) + " specified to getGridInventory(). Only accepts ParmID or lists of ParmID.") + + def __getGridInventory(self, parmIDs): + ssr = ServerResponse() + request = GetGridInventoryRequest() + request.setParmIds(parmIDs) + sr = self.__makeRequest(request) + ssr.setMessages(sr.getMessages()) + trs = sr.getPayload() if sr.getPayload() is not None else {} + ssr.setPayload(trs) + return ssr + + def getSelectTR(self, name): + request = GetSelectTimeRangeRequest() + request.setName(name) + sr = self.__makeRequest(request) + ssr = ServerResponse() + ssr.setMessages(sr.getMessages()) + ssr.setPayload(sr.getPayload()) + return ssr + + def getSiteID(self): + ssr = ServerResponse() + request = GetActiveSitesRequest() + sr = self.__makeRequest(request) + ssr.setMessages(sr.getMessages()) + ids = sr.getPayload() if sr.getPayload() is not None else [] + sr.setPayload(ids) + return sr + + def __makeRequest(self, request): + try: + request.setSiteID(self.__siteId) + except AttributeError: + pass + try: + request.setWorkstationID(self.__wsId) + except AttributeError: + pass + + sr = ServerResponse() + response = None + try: + response = self.__thrift.sendRequest(request) + except ThriftClient.ThriftRequestException as e: + sr.setMessages([str(e)]) + try: + sr.setPayload(response.getPayload()) + except AttributeError: + sr.setPayload(response) + try: + sr.setMessages(response.getMessages()) + except AttributeError: + # not a server response, nothing else to do + pass + + return sr diff --git a/pythonPackages/ufpy/gfe/__init__.py b/pythonPackages/ufpy/gfe/__init__.py new file mode 100644 index 0000000000..f2a16d5c47 --- /dev/null +++ b/pythonPackages/ufpy/gfe/__init__.py @@ -0,0 +1,37 @@ +## +# 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. +## + + +# +# __init__.py for ufpy.gfe package +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 07/26/12 dgilling Initial Creation. +# +# +# + + +__all__ = [ + ] diff --git a/rpms/awips2.core/Installer.version/component.spec b/rpms/awips2.core/Installer.version/component.spec index 3510cd1ed6..18a955da80 100644 --- a/rpms/awips2.core/Installer.version/component.spec +++ b/rpms/awips2.core/Installer.version/component.spec @@ -123,7 +123,7 @@ function updateCAVEVersion() export PATH=/awips2/java/bin:${PATH} export JAVA_HOME="/awips2/java/jre" - ./cave -application org.eclipse.ant.core.antRunner -nosplash \ + su awips -c './cave -application org.eclipse.ant.core.antRunner -nosplash' \ > /dev/null 2>&1 rm -f ${BUILD_XML} diff --git a/rpms/awips2.edex/deploy.builder/build.sh b/rpms/awips2.edex/deploy.builder/build.sh index f40de8f441..03ce6574b5 100644 --- a/rpms/awips2.edex/deploy.builder/build.sh +++ b/rpms/awips2.edex/deploy.builder/build.sh @@ -136,6 +136,7 @@ buildRPM "Installer.edex-configuration" buildRPM "Installer.edex-shapefiles" # For, now edex-native is always a 32-bit rpm. export TARGET_BUILD_ARCH="i386" +buildRPM "Installer.edex-ost" buildRPM "Installer.edex-native" # Reset the target architecture for the remaining rpms. setTargetArchitecture diff --git a/rpms/python.site-packages/Installer.qpid/component.spec b/rpms/python.site-packages/Installer.qpid/component.spec index 22913329c6..192444f96f 100644 --- a/rpms/python.site-packages/Installer.qpid/component.spec +++ b/rpms/python.site-packages/Installer.qpid/component.spec @@ -8,7 +8,7 @@ Name: awips2-python-qpid Summary: AWIPS II Python qpid Distribution Version: 0.6 -Release: 3 +Release: 4 Group: AWIPSII BuildRoot: %{_build_root} BuildArch: %{_build_arch}