From 5bb47b7931cdc1b0e80e7a360776c1cc6ad9759d Mon Sep 17 00:00:00 2001 From: Ron Anderson Date: Wed, 27 Mar 2013 09:29:55 -0500 Subject: [PATCH] Issue #1774 Fix D2D accumulative parameter time ranges Change-Id: I57b32881a30e89c999dae6db7753da83f9e949c1 Former-commit-id: aee839a85ec68c7eb80ef1e7236af6cb4666372b --- .../core/internal/AbstractParmManager.java | 30 +- .../gfe/core/internal/MockParmManager.java | 9 +- .../gfe/core/griddata/ScalarGridDataTest.java | 8 +- .../gfe/core/griddata/VectorGridDataTest.java | 12 +- .../raytheon/viz/gfe/core/parm/TestParm.java | 6 +- .../gfe/cache/d2dparms/D2DParmIdCache.java | 20 +- .../plugin/gfe/config/GFESiteActivation.java | 11 +- .../edex/plugin/gfe/db/dao/GFED2DDao.java | 419 ++++++++++ .../edex/plugin/gfe/db/dao/GFEDao.java | 493 +---------- .../plugin/gfe/paraminfo/GridParamInfo.java | 25 +- .../gfe/paraminfo/GridParamInfoLookup.java | 27 +- .../plugin/gfe/paraminfo/ParameterInfo.java | 30 + .../plugin/gfe/server/GridParmManager.java | 56 +- .../gfe/server/database/D2DGridDatabase.java | 777 ++++++++++++------ .../gfe/server/database/IFPGridDatabase.java | 137 +-- .../notify/GfeIngestNotificationFilter.java | 49 +- .../base/parameter/alias/gfeParamName.xml | 583 +++++++++---- .../base/grid/parameterInfo/hpcGuideNDFD.xml | 7 +- .../base/grid/parameterInfo/ruc130.xml | 9 + ...f.common.serialization.ISerializableObject | 2 - .../gfe/db/objects/GridParmInfo.java | 149 ++-- .../gfe/db/objects/TimeConstraints.java | 161 ++-- .../gfe/serialize/TimeConstraintsAdapter.java | 62 ++ .../raytheon/uf/common/time/TimeRange.java | 45 +- .../uf/common/time/util/TimeUtil.java | 7 +- .../adapters/TimeConstraintsAdapter.py | 46 ++ .../dynamicserialize/adapters/__init__.py | 6 +- .../gfe/db/objects/TimeConstraints.py | 56 +- 28 files changed, 1959 insertions(+), 1283 deletions(-) create mode 100644 edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFED2DDao.java create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/serialize/TimeConstraintsAdapter.java create mode 100644 pythonPackages/dynamicserialize/adapters/TimeConstraintsAdapter.py diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/AbstractParmManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/AbstractParmManager.java index 9510f79367..fd4eb09274 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/AbstractParmManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/AbstractParmManager.java @@ -100,6 +100,7 @@ import com.raytheon.viz.gfe.core.parm.vcparm.VCModuleJobPool; * use in PngWriter * 01/22/2013 #1515 dgilling Increase default size of VCModule thread pool * to decrease UI hang-ups waiting for results. + * 03/20/2013 #1774 randerso Code cleanup * * * @@ -243,7 +244,7 @@ public abstract class AbstractParmManager implements IParmManager { protected DatabaseID productDB; - protected List availableDatabases; + protected Set availableDatabases; protected final DatabaseID mutableDb; @@ -320,26 +321,16 @@ public abstract class AbstractParmManager implements IParmManager { dbCategories = Arrays.asList(prefs.getStringArray("dbTypes")); - this.availableDatabases = getDatabaseInventory(); + this.availableDatabases = new HashSet( + getDatabaseInventory()); this.dbInvChangeListener = new AbstractGFENotificationObserver( DBInvChangeNotification.class) { @Override public void notify(DBInvChangeNotification notificationMessage) { - - List newInventory; - List additions = new ArrayList(); - List deletions = new ArrayList(); - - newInventory = filterDbIds(notificationMessage.getInventory()); - additions.addAll(newInventory); - additions.removeAll(availableDatabases); - deletions.addAll(availableDatabases); - deletions.removeAll(newInventory); - availableDatabases = newInventory; - - updatedDatabaseList(availableDatabases, deletions, additions); + updatedDatabaseList(notificationMessage.getDeletions(), + notificationMessage.getAdditions()); } }; @@ -1862,15 +1853,16 @@ public abstract class AbstractParmManager implements IParmManager { * The list of available parms is updated based on the list of additions and * deletions. * - * @param newList - * The full inventory, including new additions and deletions * @param deletions * The items being removed from the inventory * @param additions * The items being added from the inventory */ - public void updatedDatabaseList(List newList, - List deletions, List additions) { + public void updatedDatabaseList(List deletions, + List additions) { + availableDatabases.addAll(additions); + availableDatabases.removeAll(deletions); + List toDelete = new ArrayList(); for (DatabaseID dbId : deletions) { diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/MockParmManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/MockParmManager.java index 85fdc80e50..42fa8ccb02 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/MockParmManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/MockParmManager.java @@ -60,6 +60,7 @@ import com.raytheon.uf.common.dataplugin.gfe.slice.VectorGridSlice; import com.raytheon.uf.common.dataplugin.gfe.slice.WeatherGridSlice; import com.raytheon.uf.common.dataplugin.gfe.weather.WeatherKey; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.viz.gfe.Activator; import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.griddata.DiscreteGridData; @@ -82,6 +83,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 02/04/2008 chammack Initial Creation + * 03/20/2013 #1774 randerso Use TimeUtil constants * * * @@ -106,10 +108,10 @@ public class MockParmManager extends AbstractParmManager { "CST6CDT"); private static final TimeConstraints TC1 = new TimeConstraints( - TimeConstraints.HOUR, TimeConstraints.HOUR, 0); + TimeUtil.SECONDS_PER_HOUR, TimeUtil.SECONDS_PER_HOUR, 0); private static final TimeConstraints TC2 = new TimeConstraints( - 13 * TimeConstraints.HOUR, TimeConstraints.DAY, 13); + 13 * TimeUtil.SECONDS_PER_HOUR, TimeUtil.SECONDS_PER_DAY, 13); protected Set fullParmSet; @@ -662,6 +664,7 @@ public class MockParmManager extends AbstractParmManager { return gloc; } + @Override public Parm getParmInExpr(final String exprName, boolean enableTopo) { return getParmInExpr(exprName, enableTopo, dataManager .getSpatialDisplayManager().getActivatedParm()); @@ -795,10 +798,12 @@ public class MockParmManager extends AbstractParmManager { } + @Override public List getIscDatabases() { return new ArrayList(); } + @Override public ParmID getISCParmID(ParmID pid) { return new ParmID(); } diff --git a/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/griddata/ScalarGridDataTest.java b/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/griddata/ScalarGridDataTest.java index a847a795ba..238fecfdcb 100644 --- a/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/griddata/ScalarGridDataTest.java +++ b/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/griddata/ScalarGridDataTest.java @@ -30,15 +30,16 @@ import org.junit.Test; import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory; import com.raytheon.uf.common.dataplugin.gfe.config.ProjectionData; import com.raytheon.uf.common.dataplugin.gfe.config.ProjectionData.ProjectionType; +import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation; 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.db.objects.TimeConstraints; -import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DBit; import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DFloat; import com.raytheon.uf.common.dataplugin.gfe.slice.ScalarGridSlice; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.viz.gfe.core.parm.MockParm; import com.raytheon.viz.gfe.core.wxvalue.ScalarWxValue; import com.vividsolutions.jts.geom.Coordinate; @@ -55,6 +56,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Mar 26, 2008 rbell Initial creation + * Mar 20, 2013 #1774 randerso Use TimeUtil constants * * * @@ -106,8 +108,8 @@ public class ScalarGridDataTest { new Point(4, 4), new Coordinate(45, 30), new Coordinate(9, 9), "CST6CDT"); - TimeConstraints testTC1 = new TimeConstraints(TimeConstraints.HOUR, - TimeConstraints.HOUR, 0); + TimeConstraints testTC1 = new TimeConstraints( + TimeUtil.SECONDS_PER_HOUR, TimeUtil.SECONDS_PER_HOUR, 0); GridParmInfo testGPI1 = new GridParmInfo(testPID1, testGL1, GridType.SCALAR, "F", "Temperature", -20f, 80f, 2, false, diff --git a/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/griddata/VectorGridDataTest.java b/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/griddata/VectorGridDataTest.java index bf041b06c4..401d5b4f16 100644 --- a/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/griddata/VectorGridDataTest.java +++ b/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/griddata/VectorGridDataTest.java @@ -29,15 +29,16 @@ import org.junit.Test; import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory; import com.raytheon.uf.common.dataplugin.gfe.config.ProjectionData; import com.raytheon.uf.common.dataplugin.gfe.config.ProjectionData.ProjectionType; +import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation; 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.db.objects.TimeConstraints; -import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DBit; import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DFloat; import com.raytheon.uf.common.dataplugin.gfe.slice.VectorGridSlice; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.viz.gfe.core.parm.MockParm; import com.raytheon.viz.gfe.core.wxvalue.VectorWxValue; import com.vividsolutions.jts.geom.Coordinate; @@ -53,7 +54,8 @@ import com.vividsolutions.jts.geom.Coordinate; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Mar 26, 2008 rbell Initial creation + * Mar 26, 2008 rbell Initial creation + * Mar 20, 2013 #1774 randerso Use TimeUtil constants * * * @@ -66,8 +68,8 @@ public class VectorGridDataTest { private final float testFA1[] = new float[145 * 145]; { for (int i = 0; i < 145 * 145; i++) { - this.testFA1[i] = (float) (i + (i / (Math.pow(10.0, (i + "") - .length())))); + this.testFA1[i] = (float) (i + (i / (Math.pow(10.0, + (i + "").length())))); } } @@ -104,7 +106,7 @@ public class VectorGridDataTest { "CST6CDT"); private final TimeConstraints testTC1 = new TimeConstraints( - TimeConstraints.HOUR, TimeConstraints.HOUR, 0); + TimeUtil.SECONDS_PER_HOUR, TimeUtil.SECONDS_PER_HOUR, 0); private final GridParmInfo testGPI1 = new GridParmInfo(this.testPID1, this.testGL1, GridType.VECTOR, "F", "Temperature", -20f, 80f, 2, diff --git a/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/parm/TestParm.java b/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/parm/TestParm.java index 33d0424e2a..dfbcaf8c68 100644 --- a/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/parm/TestParm.java +++ b/cave/com.raytheon.viz.gfe/tests/com/raytheon/viz/gfe/core/parm/TestParm.java @@ -42,6 +42,7 @@ import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DFloat; import com.raytheon.uf.common.dataplugin.gfe.slice.IGridSlice; import com.raytheon.uf.common.dataplugin.gfe.slice.ScalarGridSlice; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.viz.gfe.GFEOperationFailedException; import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.griddata.AbstractGridData; @@ -64,6 +65,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 02/21/2008 chammack Initial Creation + * 03/20/2013 #1774 randerso Use TimeUtil constants * * * @@ -84,7 +86,7 @@ public class TestParm { "CST6CDT"); private static final TimeConstraints TC1 = new TimeConstraints( - TimeConstraints.HOUR, TimeConstraints.HOUR, 0); + TimeUtil.SECONDS_PER_HOUR, TimeUtil.SECONDS_PER_HOUR, 0); private static GridParmInfo gpi; @@ -136,7 +138,7 @@ public class TestParm { "CST6CDT"); private final TimeConstraints testTC1 = new TimeConstraints( - TimeConstraints.HOUR, TimeConstraints.HOUR, 0); + TimeUtil.SECONDS_PER_HOUR, TimeUtil.SECONDS_PER_HOUR, 0); private final GridParmInfo testGPI1 = new GridParmInfo(this.testPID1, this.testGL1, GridType.SCALAR, "F", "Temperature", -20f, 80f, 2, diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/cache/d2dparms/D2DParmIdCache.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/cache/d2dparms/D2DParmIdCache.java index f45f28f45d..29bcce99fd 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/cache/d2dparms/D2DParmIdCache.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/cache/d2dparms/D2DParmIdCache.java @@ -34,7 +34,6 @@ import java.util.regex.Pattern; import com.raytheon.edex.plugin.gfe.config.IFPServerConfig; import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager; -import com.raytheon.edex.plugin.gfe.db.dao.GFEDao; import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException; import com.raytheon.edex.plugin.gfe.server.GridParmManager; import com.raytheon.edex.plugin.gfe.server.database.D2DGridDatabase; @@ -47,6 +46,7 @@ import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory; import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID; 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.server.message.ServerResponse; import com.raytheon.uf.common.dataplugin.gfe.server.notify.GridUpdateNotification; import com.raytheon.uf.common.message.WsId; import com.raytheon.uf.common.status.IUFStatusHandler; @@ -70,6 +70,8 @@ import com.raytheon.uf.edex.site.SiteAwareRegistry; * D2DParmIdCache toGfeIngestNotificationFilter. * Added code to match wind components and send * GridUpdateNotifications. + * Mar 20, 2013 #1774 randerso Changde to use GFDD2DDao + * * * * @author bphillip @@ -308,7 +310,6 @@ public class D2DParmIdCache { "Building D2DParmIdCache for " + siteID + "..."); IFPServerConfig config = IFPServerConfigManager .getServerConfig(siteID); - GFEDao dao = new GFEDao(); Set parmIds = new HashSet(); long start = System.currentTimeMillis(); List d2dModels = config.getD2dModels(); @@ -318,8 +319,8 @@ public class D2DParmIdCache { if ((d2dModelName != null) && (gfeModel != null)) { List dbIds = null; try { - dbIds = dao.getD2DDatabaseIdsFromDb(d2dModelName, - gfeModel, siteID); + dbIds = D2DGridDatabase.getD2DDatabaseIdsFromDb(config, + d2dModelName); } catch (DataAccessLayerException e) { throw new PluginException( "Unable to get D2D Database Ids from database!", @@ -333,9 +334,14 @@ public class D2DParmIdCache { for (int i = 0; i < versions; i++) { try { - parmIds.addAll(dao.getD2DParmIdsFromDb( - d2dModelName, dbIds.get(i))); - } catch (DataAccessLayerException e) { + D2DGridDatabase db = (D2DGridDatabase) GridParmManager + .getDb(dbIds.get(i)); + ServerResponse> sr = db + .getParmList(); + if (sr.isOkay()) { + parmIds.addAll(sr.getPayload()); + } + } catch (GfeException e) { throw new PluginException( "Error adding parmIds to D2DParmIdCache!!", e); diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java index ce9fdb0397..c4b7c3bee2 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GFESiteActivation.java @@ -34,13 +34,13 @@ import com.google.common.util.concurrent.MoreExecutors; import com.raytheon.edex.plugin.gfe.cache.d2dparms.D2DParmIdCache; import com.raytheon.edex.plugin.gfe.cache.gridlocations.GridLocationCache; import com.raytheon.edex.plugin.gfe.cache.ifpparms.IFPParmIdCache; -import com.raytheon.edex.plugin.gfe.db.dao.GFEDao; import com.raytheon.edex.plugin.gfe.db.dao.IscSendRecordDao; import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException; import com.raytheon.edex.plugin.gfe.exception.GfeMissingConfigurationException; import com.raytheon.edex.plugin.gfe.isc.IRTManager; import com.raytheon.edex.plugin.gfe.reference.MapManager; import com.raytheon.edex.plugin.gfe.server.GridParmManager; +import com.raytheon.edex.plugin.gfe.server.database.D2DGridDatabase; import com.raytheon.edex.plugin.gfe.server.database.D2DSatDatabaseManager; import com.raytheon.edex.plugin.gfe.server.database.GridDatabase; import com.raytheon.edex.plugin.gfe.server.database.NetCDFDatabaseManager; @@ -84,6 +84,7 @@ import com.raytheon.uf.edex.site.ISiteActivationListener; * missing configuration (no stack trace). * Feb 28, 2013 #1447 dgilling Enable active table fetching on site * activation. + * Mar 20, 2013 #1774 randerso Changed to use GFED2DDao * * * @@ -425,7 +426,6 @@ public class GFESiteActivation implements ISiteActivationListener { if (LockState.SUCCESSFUL.equals(ct.getLockState())) { boolean clearTime = false; try { - GFEDao dao = new GFEDao(); List d2dModels = configRef.getD2dModels(); List> idsByVersion = new ArrayList>( 5); @@ -440,10 +440,9 @@ public class GFESiteActivation implements ISiteActivationListener { .desiredDbVersions(new DatabaseID( siteID, DataType.GRID, "", gfeModel)); - List dbIds = dao - .getD2DDatabaseIdsFromDb( - d2dModelName, gfeModel, - siteID, versions); + List dbIds = D2DGridDatabase + .getD2DDatabaseIdsFromDb(configRef, + d2dModelName, versions); while (versions > idsByVersion.size()) { idsByVersion.add(new ArrayList( diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFED2DDao.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFED2DDao.java new file mode 100644 index 0000000000..5f3ae9bd82 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFED2DDao.java @@ -0,0 +1,419 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ + +package com.raytheon.edex.plugin.gfe.db.dao; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.hibernate.Query; +import org.hibernate.SQLQuery; +import org.hibernate.Session; + +import com.raytheon.edex.plugin.gfe.config.IFPServerConfig; +import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager; +import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException; +import com.raytheon.edex.plugin.gfe.util.GridTranslator; +import com.raytheon.uf.common.comm.CommunicationException; +import com.raytheon.uf.common.dataplugin.PluginException; +import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID; +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.grid.GridConstants; +import com.raytheon.uf.common.dataplugin.grid.GridInfoConstants; +import com.raytheon.uf.common.dataplugin.grid.GridRecord; +import com.raytheon.uf.common.dataplugin.level.Level; +import com.raytheon.uf.common.dataplugin.level.LevelFactory; +import com.raytheon.uf.common.parameter.mapping.ParameterMapper; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.util.mapping.MultipleMappingException; +import com.raytheon.uf.edex.database.DataAccessLayerException; +import com.raytheon.uf.edex.database.query.DatabaseQuery; +import com.raytheon.uf.edex.plugin.grid.dao.GridDao; + +/** + * Data access object for manipulating GFE Records + * + *
+ * SOFTWARE HISTORY
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * 03/20/13     #1774      randerso    Refactored out of GFEDao
+ * 
+ * 
+ * + * @author randerso + * @version 1.0 + */ + +// ********************************************************************** +// TODO: this was moved out of GFEDao and needs to be cleaned up to better +// use the inherited GridDao functionality and hibernate instead of +// SQL/HQL queries. Some parts of the queries could be pushed up to +// GridDao +// ********************************************************************** +public class GFED2DDao extends GridDao { + private static final String FCST_TIME = "dataTime.fcstTime"; + + private static final String REF_TIME = "dataTime.refTime"; + + // hibernate query to find grid info record for the given datasetId and + // parameter + private static final String SQL_D2D_GRID_PARM_QUERY = "select parameter_abbreviation, id " + + "FROM grid_info WHERE " + + GridInfoConstants.DATASET_ID + + " = :" + + GridInfoConstants.DATASET_ID + + " AND " + + "level_id = :level_id AND " + + "(lower(parameter_abbreviation) = :abbrev OR lower(parameter_abbreviation) like :hourAbbrev)"; + + // hibernate query to find the times for the GridRecord for the given + // info.id, id returned to allow easy lookup of the record associated with + // the time + private static final String HQL_D2D_GRID_TIME_QUERY = "select dataTime.fcstTime, id from GridRecord " + + "where " + + GridConstants.INFO_ID + + " = :info_id AND dataTime.refTime = :refTime order by dataTime.fcstTime"; + + private static final Pattern WIND_PATTERN = Pattern.compile("wind"); + + public GFED2DDao() throws PluginException { + super(); + } + + /** + * Retrieves a list of available forecast times + * + * @param dbId + * The database ID to get the times for + * @return The list of forecast times associated with the specified + * DatabaseID + * @throws DataAccessLayerException + * If errors occur while querying the metadata database + */ + public List getD2DForecastTimes(DatabaseID dbId) + throws DataAccessLayerException { + DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); + query.addDistinctParameter(FCST_TIME); + try { + IFPServerConfig config = IFPServerConfigManager + .getServerConfig(dbId.getSiteId()); + query.addQueryParam(GridConstants.DATASET_ID, + config.d2dModelNameMapping(dbId.getModelName())); + } catch (GfeConfigurationException e) { + throw new DataAccessLayerException( + "Error occurred looking up model name mapping", e); + } + query.addQueryParam(REF_TIME, dbId.getModelTimeAsDate()); + query.addOrder(FCST_TIME, true); + + @SuppressWarnings("unchecked") + List vals = (List) this.queryByCriteria(query); + return vals; + } + + /** + * Retrieves a GridRecord from the grib metadata database based on a ParmID, + * TimeRange, and GridParmInfo. + * + * @param id + * The parmID of the desired GridRecord + * @param forecastTime + * The foreCast time of the desired GridRecord, null for any + * record + * @param info + * The GridParmInfo for the requested d2d grid. + * @return The GridRecord from the grib metadata database + * @throws DataAccessLayerException + * If errors occur while querying the metadata database + */ + public GridRecord getD2DGrid(ParmID id, Integer forecastTime, + GridParmInfo info) throws DataAccessLayerException { + Session s = null; + + try { + s = getHibernateTemplate().getSessionFactory().openSession(); + // TODO: clean up so we only make one db query + SortedMap rawTimes = queryByD2DParmId(id, s); + + // if forecastTime is null just pick one, + // this is for static data since all times are the same + if (forecastTime == null) { + forecastTime = rawTimes.keySet().iterator().next(); + } + + GridRecord retVal = (GridRecord) s.get(GridRecord.class, + rawTimes.get(forecastTime)); + retVal.setPluginName(GridConstants.GRID); + return retVal; + + } finally { + if (s != null) { + try { + s.close(); + } catch (Exception e) { + statusHandler.error( + "Error occurred closing database session", e); + } + } + } + } + + /** + * Gets a SortedMap of DataTime and GridRecord ids from the grib metadata + * database which match the given ParmID. Session passed to allow reuse + * across multiple calls. + * + * @param id + * The ParmID to search with + * @param s + * The database session to use + * @return The list of GridRecords from the grib metadata database which + * match the given ParmID + * @throws DataAccessLayerException + * If errors occur while querying the metadata database + */ + public SortedMap queryByD2DParmId(ParmID id, Session s) + throws DataAccessLayerException { + String levelName = GridTranslator.getLevelName(id.getParmLevel()); + + double[] levelValues = GridTranslator.getLevelValue(id.getParmLevel()); + boolean levelOnePresent = (levelValues[0] != Level + .getInvalidLevelValue()); + boolean levelTwoPresent = (levelValues[1] != Level + .getInvalidLevelValue()); + Level level = null; + + // to have a level 2, must have a level one + try { + if (levelOnePresent && levelTwoPresent) { + level = LevelFactory.getInstance().getLevel(levelName, + levelValues[0], levelValues[1]); + } else if (levelOnePresent) { + level = LevelFactory.getInstance().getLevel(levelName, + levelValues[0]); + } else { + level = LevelFactory.getInstance().getLevel(levelName, 0.0); + } + } catch (CommunicationException e) { + logger.error(e.getLocalizedMessage(), e); + } + if (level == null) { + logger.warn("Unable to query D2D parms, ParmID " + id + + " does not map to a level"); + return new TreeMap(); + } + + SQLQuery modelQuery = s.createSQLQuery(SQL_D2D_GRID_PARM_QUERY); + modelQuery.setLong("level_id", level.getId()); + DatabaseID dbId = id.getDbId(); + + try { + IFPServerConfig config = IFPServerConfigManager + .getServerConfig(dbId.getSiteId()); + modelQuery.setString(GridInfoConstants.DATASET_ID, + config.d2dModelNameMapping(dbId.getModelName())); + } catch (GfeConfigurationException e) { + throw new DataAccessLayerException( + "Error occurred looking up model name mapping", e); + } + + String abbreviation = null; + try { + abbreviation = ParameterMapper.getInstance().lookupBaseName( + id.getParmName(), "gfeParamName"); + } catch (MultipleMappingException e) { + statusHandler.handle(Priority.WARN, e.getLocalizedMessage(), e); + abbreviation = e.getArbitraryMapping(); + } + + abbreviation = abbreviation.toLowerCase(); + modelQuery.setString("abbrev", abbreviation); + modelQuery.setString("hourAbbrev", abbreviation + "%hr"); + + @SuppressWarnings("unchecked") + List results = modelQuery.list(); + + Integer modelId = null; + if (results.size() == 0) { + return new TreeMap(); + } else if (results.size() > 1) { + // hours matched, take hour with least number that matches exact + // param + Pattern p = Pattern.compile("^" + abbreviation + "(\\d+)hr$"); + int lowestHr = -1; + for (Object[] rows : results) { + String param = ((String) rows[0]).toLowerCase(); + if (param.equals(abbreviation) && (lowestHr < 0)) { + modelId = (Integer) rows[1]; + } else { + Matcher matcher = p.matcher(param); + if (matcher.matches()) { + int hr = Integer.parseInt(matcher.group(1)); + if ((lowestHr < 0) || (hr < lowestHr)) { + modelId = (Integer) rows[1]; + lowestHr = hr; + } + } + } + } + } else { + modelId = (Integer) (results.get(0))[1]; + } + + Query timeQuery = s.createQuery(HQL_D2D_GRID_TIME_QUERY); + timeQuery.setInteger("info_id", modelId); + timeQuery.setParameter("refTime", dbId.getModelTimeAsDate()); + + @SuppressWarnings("unchecked") + List timeResults = timeQuery.list(); + + if (timeResults.isEmpty()) { + return new TreeMap(); + } + + SortedMap dataTimes = new TreeMap(); + for (Object[] rows : timeResults) { + dataTimes.put((Integer) rows[0], (Integer) rows[1]); + } + return dataTimes; + } + + /** + * Retrieve the available Forecast Hours by D2D parm id. + * + * @param id + * @return the list of forecast hours + * @throws DataAccessLayerException + */ + public List queryFcstHourByD2DParmId(ParmID id) + throws DataAccessLayerException { + List timeList = new ArrayList(); + Session s = null; + try { + s = getHibernateTemplate().getSessionFactory().openSession(); + + if (id.getParmName().equalsIgnoreCase("wind")) { + String idString = id.toString(); + Matcher idWindMatcher = WIND_PATTERN.matcher(idString); + + ParmID uWindId = new ParmID(idWindMatcher.replaceAll("uW")); + SortedMap results = queryByD2DParmId(uWindId, + s); + List uTimeList = new ArrayList(results.size()); + for (Integer o : results.keySet()) { + uTimeList.add(o); + } + + ParmID vWindId = new ParmID(idWindMatcher.replaceAll("vW")); + results = queryByD2DParmId(vWindId, s); + Set vTimeList = new HashSet(results.size(), 1); + for (Integer o : results.keySet()) { + vTimeList.add(o); + } + + for (Integer tr : uTimeList) { + if (vTimeList.contains(tr)) { + timeList.add(tr); + } + } + + if (!timeList.isEmpty()) { + return timeList; + } + + ParmID sWindId = new ParmID(idWindMatcher.replaceAll("ws")); + results = queryByD2DParmId(sWindId, s); + List sTimeList = new ArrayList(results.size()); + for (Integer o : results.keySet()) { + sTimeList.add(o); + } + + ParmID dWindId = new ParmID(idWindMatcher.replaceAll("wd")); + results = queryByD2DParmId(dWindId, s); + Set dTimeList = new HashSet(results.size(), 1); + for (Integer o : results.keySet()) { + dTimeList.add(o); + } + + for (Integer tr : sTimeList) { + if (dTimeList.contains(tr)) { + timeList.add(tr); + } + } + } else { + SortedMap results = queryByD2DParmId(id, s); + for (Integer o : results.keySet()) { + timeList.add(o); + } + } + } finally { + if (s != null) { + try { + s.close(); + } catch (Exception e) { + statusHandler.error( + "Error occurred closing database session", e); + } + } + } + + return timeList; + } + + /** + * Retrieves model run times for the n most recent model runs of a given + * d2dModelName + * + * @param d2dModelName + * @param maxRecords + * @return + * @throws DataAccessLayerException + */ + public List getD2DModelRunTimes(String d2dModelName, int maxRecords) + throws DataAccessLayerException { + DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); + query.addDistinctParameter(REF_TIME); + query.addQueryParam(GridConstants.DATASET_ID, d2dModelName); + query.addOrder(REF_TIME, false); + if (maxRecords > 0) { + query.setMaxResults(maxRecords); + } + List result = this.queryByCriteria(query); + + List inventory = new ArrayList(result.size()); + for (Object obj : result) { + // convert returned "Dates" (actually java.sql.TimeStamps) to actual + // java.util.Dates so equals comparisons work correctly + Date date = new Date(((Date) obj).getTime()); + inventory.add(date); + } + + return inventory; + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java index b5ad4e1fa8..b94ddba242 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java @@ -27,18 +27,13 @@ import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.regex.Matcher; import java.util.regex.Pattern; import org.hibernate.Query; -import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.DetachedCriteria; @@ -49,44 +44,27 @@ import org.springframework.transaction.support.TransactionCallbackWithoutResult; import com.raytheon.edex.db.dao.DefaultPluginDao; import com.raytheon.edex.plugin.gfe.config.GFESiteActivation; -import com.raytheon.edex.plugin.gfe.config.IFPServerConfig; -import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager; -import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException; import com.raytheon.edex.plugin.gfe.server.GridParmManager; -import com.raytheon.edex.plugin.gfe.server.database.D2DGridDatabase; import com.raytheon.edex.plugin.gfe.server.database.GridDatabase; -import com.raytheon.edex.plugin.gfe.util.GridTranslator; import com.raytheon.edex.plugin.gfe.util.SendNotifications; -import com.raytheon.uf.common.comm.CommunicationException; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory; import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID; -import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID.DataType; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord; -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.exception.GfeException; import com.raytheon.uf.common.dataplugin.gfe.server.notify.GridUpdateNotification; import com.raytheon.uf.common.dataplugin.gfe.server.notify.LockNotification; import com.raytheon.uf.common.dataplugin.gfe.type.Pair; import com.raytheon.uf.common.dataplugin.gfe.util.GfeUtil; -import com.raytheon.uf.common.dataplugin.grid.GridConstants; -import com.raytheon.uf.common.dataplugin.grid.GridInfoConstants; -import com.raytheon.uf.common.dataplugin.grid.GridRecord; -import com.raytheon.uf.common.dataplugin.level.Level; -import com.raytheon.uf.common.dataplugin.level.LevelFactory; import com.raytheon.uf.common.dataplugin.persist.IPersistable; import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; import com.raytheon.uf.common.dataquery.db.QueryResult; import com.raytheon.uf.common.datastorage.DataStoreFactory; import com.raytheon.uf.common.datastorage.IDataStore; -import com.raytheon.uf.common.parameter.mapping.ParameterMapper; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.DataTime; import com.raytheon.uf.common.time.TimeRange; -import com.raytheon.uf.common.time.util.TimeUtil; -import com.raytheon.uf.common.util.mapping.MultipleMappingException; import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.purge.PurgeLogger; import com.raytheon.uf.edex.database.query.DatabaseQuery; @@ -112,7 +90,8 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery; * 01/21/12 #1504 randerso Back ported change to use ParameterMapper into 13.1.2 * 02/10/13 #1603 randerso Eliminated unnecessary conversion from lists to arrays * 02/12/13 #1608 randerso Changed to use explicit deletes for groups and datasets - * 03/15/13 #1795 njensen Added updatePublishTime() + * 03/15/13 #1795 njensen Added updatePublishTime() + * 03/21/13 #1774 randerso Moved D2D routines into {@link com.raytheon.edex.plugin.gfe.db.dao.GFED2DDao} * * * @@ -120,25 +99,6 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery; * @version 1.0 */ public class GFEDao extends DefaultPluginDao { - // hibernate query to find grid info record for the given datasetId and - // parameter - private String SQL_D2D_GRID_PARM_QUERY = "select parameter_abbreviation, id " - + "FROM grid_info WHERE " - + GridInfoConstants.DATASET_ID - + " = :" - + GridInfoConstants.DATASET_ID - + " AND " - + "level_id = :level_id AND " - + "(lower(parameter_abbreviation) = :abbrev OR lower(parameter_abbreviation) like :hourAbbrev)"; - - // hibernate query to find the times for the GridRecord for the given - // info.id, id returned to allow easy lookup of the record associated with - // the time - private static final String HQL_D2D_GRID_TIME_QUERY = "select dataTime, id from GridRecord " - + "where " - + GridConstants.INFO_ID - + " = :info_id AND dataTime.refTime = :refTime order by dataTime.fcstTime"; - private static final Pattern WIND_PATTERN = Pattern.compile("wind"); public GFEDao() throws PluginException { @@ -596,348 +556,6 @@ public class GFEDao extends DefaultPluginDao { return history; } - /** - * Retrieves a list of valid times for a specified ParmID from the grib - * metadata database. The valid time is constructed by adding the forecast - * time to the reference time. - * - * @param id - * The parmID to get the times for - * @return The list of times associated with the specified ParmID - * @throws DataAccessLayerException - * If errors occur while querying the metadata database - */ - public List getD2DTimes(ParmID id) - throws DataAccessLayerException { - return queryTimeByD2DParmId(id); - } - - /** - * Retrieves a list of available forecast times - * - * @param dbId - * The database ID to get the times for - * @return The list of forecast times associated with the specified - * DatabaseID - * @throws DataAccessLayerException - * If errors occur while querying the metadata database - */ - @SuppressWarnings("unchecked") - public List getD2DForecastTimes(DatabaseID dbId) - throws DataAccessLayerException { - DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); - query.addDistinctParameter("dataTime.fcstTime"); - try { - IFPServerConfig config = IFPServerConfigManager - .getServerConfig(dbId.getSiteId()); - query.addQueryParam(GridConstants.DATASET_ID, - config.d2dModelNameMapping(dbId.getModelName())); - } catch (GfeConfigurationException e) { - throw new DataAccessLayerException( - "Error occurred looking up model name mapping", e); - } - query.addQueryParam("dataTime.refTime", dbId.getModelTimeAsDate()); - query.addOrder("dataTime.fcstTime", true); - List vals = this.queryByCriteria(query); - return (List) vals; - } - - /** - * Retrieves a GridRecord from the grib metadata database based on a ParmID, - * TimeRange, and GridParmInfo. - * - * @param id - * The parmID of the desired GridRecord - * @param timeRange - * The timeRange of the desired GridRecord - * @param info - * The GridParmInfo for the requested d2d grid. - * @return The GridRecord from the grib metadata database - * @throws DataAccessLayerException - * If errors occur while querying the metadata database - */ - public GridRecord getD2DGrid(ParmID id, TimeRange timeRange, - GridParmInfo info) throws DataAccessLayerException { - Session s = null; - - try { - s = getHibernateTemplate().getSessionFactory().openSession(); - // TODO: clean up so we only make one db query - SortedMap rawTimes = queryByD2DParmId(id, s); - List gribTimes = new ArrayList(); - for (DataTime dt : rawTimes.keySet()) { - gribTimes.add(dt.getValidPeriod()); - } - - try { - if (isMos(id)) { - for (Map.Entry timeEntry : rawTimes - .entrySet()) { - TimeRange gribTime = timeEntry.getKey() - .getValidPeriod(); - TimeRange time = info.getTimeConstraints() - .constraintTime(gribTime.getEnd()); - if (timeRange.getEnd().equals(time.getEnd()) - || !info.getTimeConstraints().anyConstraints()) { - GridRecord retVal = (GridRecord) s.get( - GridRecord.class, timeEntry.getValue()); - retVal.setPluginName(GridConstants.GRID); - return retVal; - } - } - } else if (D2DGridDatabase.isNonAccumDuration(id, gribTimes)) { - for (Map.Entry timeEntry : rawTimes - .entrySet()) { - TimeRange gribTime = timeEntry.getKey() - .getValidPeriod(); - if (timeRange.getStart().equals(gribTime.getEnd()) - || timeRange.equals(gribTime)) { - GridRecord retVal = (GridRecord) s.get( - GridRecord.class, timeEntry.getValue()); - retVal.setPluginName(GridConstants.GRID); - return retVal; - } - } - } else { - for (Map.Entry timeEntry : rawTimes - .entrySet()) { - TimeRange gribTime = timeEntry.getKey() - .getValidPeriod(); - TimeRange time = info.getTimeConstraints() - .constraintTime(gribTime.getStart()); - if ((timeRange.getStart().equals(time.getStart()) || !info - .getTimeConstraints().anyConstraints())) { - GridRecord retVal = (GridRecord) s.get( - GridRecord.class, timeEntry.getValue()); - retVal.setPluginName(GridConstants.GRID); - return retVal; - } - } - } - } catch (GfeConfigurationException e) { - throw new DataAccessLayerException( - "Error getting configuration for " - + id.getDbId().getSiteId(), e); - } - } finally { - if (s != null) { - try { - s.close(); - } catch (Exception e) { - statusHandler.error( - "Error occurred closing database session", e); - } - } - } - - return null; - } - - /** - * Gets a SortedMap of DataTime and GridRecord ids from the grib metadata - * database which match the given ParmID. Session passed to allow reuse - * across multiple calls. - * - * @param id - * The ParmID to search with - * @param s - * The database session to use - * @return The list of GridRecords from the grib metadata database which - * match the given ParmID - * @throws DataAccessLayerException - * If errors occur while querying the metadata database - */ - @SuppressWarnings("unchecked") - public SortedMap queryByD2DParmId(ParmID id, Session s) - throws DataAccessLayerException { - String levelName = GridTranslator.getLevelName(id.getParmLevel()); - - double[] levelValues = GridTranslator.getLevelValue(id.getParmLevel()); - boolean levelOnePresent = (levelValues[0] != Level - .getInvalidLevelValue()); - boolean levelTwoPresent = (levelValues[1] != Level - .getInvalidLevelValue()); - Level level = null; - - // to have a level 2, must have a level one - try { - if (levelOnePresent && levelTwoPresent) { - level = LevelFactory.getInstance().getLevel(levelName, - levelValues[0], levelValues[1]); - } else if (levelOnePresent) { - level = LevelFactory.getInstance().getLevel(levelName, - levelValues[0]); - } else { - level = LevelFactory.getInstance().getLevel(levelName, 0.0); - } - } catch (CommunicationException e) { - logger.error(e.getLocalizedMessage(), e); - } - if (level == null) { - logger.warn("Unable to query D2D parms, ParmID " + id - + " does not map to a level"); - return new TreeMap(); - } - - SQLQuery modelQuery = s.createSQLQuery(SQL_D2D_GRID_PARM_QUERY); - modelQuery.setLong("level_id", level.getId()); - DatabaseID dbId = id.getDbId(); - - try { - IFPServerConfig config = IFPServerConfigManager - .getServerConfig(dbId.getSiteId()); - modelQuery.setString(GridInfoConstants.DATASET_ID, - config.d2dModelNameMapping(dbId.getModelName())); - } catch (GfeConfigurationException e) { - throw new DataAccessLayerException( - "Error occurred looking up model name mapping", e); - } - - String abbreviation = null; - try { - abbreviation = ParameterMapper.getInstance().lookupBaseName( - id.getParmName(), "gfeParamName"); - } catch (MultipleMappingException e) { - statusHandler.handle(Priority.WARN, e.getLocalizedMessage(), e); - abbreviation = e.getArbitraryMapping(); - } - - abbreviation = abbreviation.toLowerCase(); - modelQuery.setString("abbrev", abbreviation); - modelQuery.setString("hourAbbrev", abbreviation + "%hr"); - List results = modelQuery.list(); - Integer modelId = null; - if (results.size() == 0) { - return new TreeMap(); - } else if (results.size() > 1) { - // hours matched, take hour with least number that matches exact - // param - Pattern p = Pattern.compile("^" + abbreviation + "(\\d+)hr$"); - int lowestHr = -1; - for (Object[] rows : (List) results) { - String param = ((String) rows[0]).toLowerCase(); - if (param.equals(abbreviation) && (lowestHr < 0)) { - modelId = (Integer) rows[1]; - } else { - Matcher matcher = p.matcher(param); - if (matcher.matches()) { - int hr = Integer.parseInt(matcher.group(1)); - if ((lowestHr < 0) || (hr < lowestHr)) { - modelId = (Integer) rows[1]; - lowestHr = hr; - } - } - } - } - } else { - modelId = (Integer) ((Object[]) results.get(0))[1]; - } - - Query timeQuery = s.createQuery(HQL_D2D_GRID_TIME_QUERY); - timeQuery.setInteger("info_id", modelId); - timeQuery.setParameter("refTime", dbId.getModelTimeAsDate()); - List timeResults = timeQuery.list(); - if (timeResults.isEmpty()) { - return new TreeMap(); - } - - SortedMap dataTimes = new TreeMap(); - for (Object[] rows : timeResults) { - dataTimes.put((DataTime) rows[0], (Integer) rows[1]); - } - return dataTimes; - } - - public List queryTimeByD2DParmId(ParmID id) - throws DataAccessLayerException { - List timeList = new ArrayList(); - Session s = null; - try { - s = getHibernateTemplate().getSessionFactory().openSession(); - - if (id.getParmName().equalsIgnoreCase("wind")) { - String idString = id.toString(); - Matcher idWindMatcher = WIND_PATTERN.matcher(idString); - - ParmID uWindId = new ParmID(idWindMatcher.replaceAll("uW")); - SortedMap results = queryByD2DParmId( - uWindId, s); - List uTimeList = new ArrayList( - results.size()); - for (DataTime o : results.keySet()) { - uTimeList.add(new TimeRange(o.getValidPeriod().getStart(), - 3600 * 1000)); - } - - ParmID vWindId = new ParmID(idWindMatcher.replaceAll("vW")); - results = queryByD2DParmId(vWindId, s); - Set vTimeList = new HashSet( - results.size(), 1); - for (DataTime o : results.keySet()) { - vTimeList.add(new TimeRange(o.getValidPeriod().getStart(), - 3600 * 1000)); - } - - for (TimeRange tr : uTimeList) { - if (vTimeList.contains(tr)) { - timeList.add(new TimeRange(tr.getStart(), tr.getStart())); - } - } - - if (!timeList.isEmpty()) { - return timeList; - } - - ParmID sWindId = new ParmID(idWindMatcher.replaceAll("ws")); - results = queryByD2DParmId(sWindId, s); - List sTimeList = new ArrayList( - results.size()); - for (DataTime o : results.keySet()) { - sTimeList.add(new TimeRange(o.getValidPeriod().getStart(), - 3600 * 1000)); - } - - ParmID dWindId = new ParmID(idWindMatcher.replaceAll("wd")); - results = queryByD2DParmId(dWindId, s); - Set dTimeList = new HashSet( - results.size(), 1); - for (DataTime o : results.keySet()) { - dTimeList.add(new TimeRange(o.getValidPeriod().getStart(), - 3600 * 1000)); - } - - for (TimeRange tr : sTimeList) { - if (dTimeList.contains(tr)) { - timeList.add(new TimeRange(tr.getStart(), tr.getStart())); - } - } - } else { - SortedMap results = queryByD2DParmId(id, s); - if (isMos(id)) { - for (DataTime o : results.keySet()) { - timeList.add(new TimeRange(o.getValidPeriod().getEnd(), - o.getValidPeriod().getDuration())); - } - } else { - for (DataTime o : results.keySet()) { - timeList.add(o.getValidPeriod()); - } - } - } - } finally { - if (s != null) { - try { - s.close(); - } catch (Exception e) { - statusHandler.error( - "Error occurred closing database session", e); - } - } - } - - return timeList; - } - public void purgeGFEGrids(final DatabaseID dbId) { txTemplate.execute(new TransactionCallbackWithoutResult() { @Override @@ -959,107 +577,6 @@ public class GFEDao extends DefaultPluginDao { }); } - public List getD2DDatabaseIdsFromDb(String d2dModelName, - String gfeModel, String siteID) throws DataAccessLayerException { - return getD2DDatabaseIdsFromDb(d2dModelName, gfeModel, siteID, -1); - } - - public List getD2DDatabaseIdsFromDb(String d2dModelName, - String gfeModel, String siteID, int maxRecords) - throws DataAccessLayerException { - List dbInventory = new ArrayList(); - - DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); - query.addDistinctParameter("dataTime.refTime"); - query.addQueryParam(GridConstants.DATASET_ID, d2dModelName); - query.addOrder("dataTime.refTime", false); - if (maxRecords > 0) { - query.setMaxResults(maxRecords); - } - List result = this.queryByCriteria(query); - - for (Object obj : result) { - DatabaseID dbId = null; - dbId = new DatabaseID(siteID, DataType.GRID, "D2D", gfeModel, - (Date) obj); - try { - GridDatabase db = GridParmManager.getDb(dbId); - if ((db != null) && !dbInventory.contains(dbId)) { - dbInventory.add(dbId); - } - } catch (GfeException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); - } - } - return dbInventory; - } - - /** - * Retrieves the latest (or newest) model run for the given site and model - * name. - * - * @param d2dModel - * A GridModel object that contains the D2D model name. - * @param gfeModel - * The GFE model name that corresponds to d2dModel. - * @param siteID - * The site to retrieve the data for. - * @return The DatabaseID of the newest D2D model, or null if no models can - * be found. - * @throws DataAccessLayerException - */ - public DatabaseID getLatestD2DDatabaseIdsFromDb(String d2dModelName, - String gfeModel, String siteID) throws DataAccessLayerException { - List dbIds = getD2DDatabaseIdsFromDb(d2dModelName, - gfeModel, siteID, 1); - if (!dbIds.isEmpty()) { - return dbIds.get(0); - } else { - return null; - } - } - - public Set getD2DParmIdsFromDb(String d2dModelName, DatabaseID dbId) - throws DataAccessLayerException { - - Set parmIds = new HashSet(); - - DatabaseQuery query = new DatabaseQuery(GridRecord.class.getName()); - query.addDistinctParameter(GridConstants.PARAMETER_ABBREVIATION); - query.addDistinctParameter(GridConstants.MASTER_LEVEL_NAME); - query.addDistinctParameter(GridConstants.LEVEL_ONE); - query.addDistinctParameter(GridConstants.LEVEL_TWO); - query.addQueryParam(GridConstants.DATASET_ID, d2dModelName); - query.addQueryParam( - "dataTime.refTime", - TimeUtil.formatDate(dbId.getModelTimeAsDate()).replaceAll("_", - " ")); - - List result = this.queryByCriteria(query); - - for (Object obj : result) { - Object[] objArr = (Object[]) obj; - String levelName = GridTranslator.getShortLevelName( - (String) objArr[1], (Double) objArr[2], (Double) objArr[3]); - if (!levelName.equals(LevelFactory.UNKNOWN_LEVEL)) { - String abbrev = (String) objArr[0]; - try { - abbrev = ParameterMapper.getInstance().lookupAlias(abbrev, - "gfeParamName"); - } catch (MultipleMappingException e) { - statusHandler.handle(Priority.WARN, - e.getLocalizedMessage(), e); - abbrev = e.getArbitraryMapping(); - } - ParmID newParmId = new ParmID(abbrev, dbId, levelName); - parmIds.add(newParmId); - } - - } - return parmIds; - } - /** * Removes GridParmInfo from the HDF5 file and any data associated with that * info @@ -1136,12 +653,6 @@ public class GFEDao extends DefaultPluginDao { } } - public static boolean isMos(ParmID id) { - return id.getDbId().getModelName().equals("MOSGuide") - && (id.getParmName().startsWith("mxt") || id.getParmName() - .startsWith("mnt")); - } - /** * Updates the publish times in the database of all provided * GridDataHistories. Does not alter the publish times in memory. diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/GridParamInfo.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/GridParamInfo.java index da2a2851db..8e0eb543dc 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/GridParamInfo.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/GridParamInfo.java @@ -20,8 +20,11 @@ package com.raytheon.edex.plugin.gfe.paraminfo; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @@ -31,6 +34,7 @@ import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlRootElement; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.common.time.util.TimeUtil; /** * @@ -41,7 +45,9 @@ import com.raytheon.uf.common.time.TimeRange; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jun 24, 2010 #6372 bphillip Initial creation + * Jun 24, 2010 #6372 bphillip Initial creation + * Mar 20, 2013 #1774 randerso Added getParmNames, + * changed getAvailableTimes to match A1 * * * @@ -108,12 +114,21 @@ public class GridParamInfo { } public List getAvailableTimes(Date refTime) { - List availTimes = new ArrayList(); - for (int i = 1; i < times.size(); i++) { - availTimes.add(new TimeRange(refTime.getTime() + times.get(i - 1) - * 1000, refTime.getTime() + times.get(i) * 1000)); + List availTimes = new ArrayList(times.size()); + for (Integer fcstHour : times) { + availTimes.add(new TimeRange(new Date(refTime.getTime() + fcstHour + * TimeUtil.MILLIS_PER_SECOND), TimeUtil.MILLIS_PER_HOUR)); } return availTimes; } + public Collection getParmNames() { + List paramInfoList = this.getGridParamInfo(); + Set parmNames = new HashSet(); + for (ParameterInfo info : paramInfoList) { + parmNames.add(info.getShort_name()); + } + + return parmNames; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/GridParamInfoLookup.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/GridParamInfoLookup.java index 1f7150bc76..1ea469c431 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/GridParamInfoLookup.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/GridParamInfoLookup.java @@ -56,8 +56,10 @@ import com.raytheon.uf.common.util.mapping.MultipleMappingException; * Jan 25, 2012 DR 14305 ryu Read site parameterInfo files * Sep 12, 2012 #1117 dgilling Implement method to retrieve all * parm names for a given model. - * Feb 15, 2013 1598 bsteffen Make GridParamInfoLookup filter on - * extension. + * Feb 15, 2013 1598 bsteffen Make GridParamInfoLookup filter on + * extension. + * Mar 20, 2013 #1774 randerso Added getModelInfo, + * added Dflt if no levels specified * * * @@ -94,7 +96,14 @@ public class GridParamInfoLookup { init(); } - private GridParamInfo getGridParamInfo(String mappedModel) { + /** + * Gets the model information based on the specified model + * + * @param mappedModel + * The model name + * @return The parameter information or null if none found + */ + public GridParamInfo getGridParamInfo(String mappedModel) { String paramInfoName = null; try { paramInfoName = DatasetIdMapper.getInstance().lookupAliasOrNull( @@ -211,5 +220,17 @@ public class GridParamInfoLookup { "Error unmarshalling grid parameter information", e); } } + + for (GridParamInfo gridParamInfo : modelParamMap.values()) { + for (String parmName : gridParamInfo.getParmNames()) { + ParameterInfo parameterInfo = gridParamInfo + .getParameterInfo(parmName); + + // add Dflt level if no other levels defined + if (parameterInfo.getLevels().isEmpty()) { + parameterInfo.getLevels().add("Dflt"); + } + } + } } } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/ParameterInfo.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/ParameterInfo.java index 5d98f98bf1..f87be858d4 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/ParameterInfo.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/paraminfo/ParameterInfo.java @@ -43,6 +43,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; * Jun 24, 2010 bphillip Initial creation * Sep 12, 2012 #1117 dgilling Create field to hold list of * valid levels for each parameter. + * Mar 20, 2013 #1774 randerso Added getMinVal and getMaxVal * * * @@ -53,6 +54,13 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlAccessorType(XmlAccessType.NONE) public class ParameterInfo { + // The netCDF convention is MINFLOAT to MAXFLOAT. + // But we can't use it or GFE will attempt to create + // billions and billions of contours. + public static final float MIN_VALUE = 0f; + + public static final float MAX_VALUE = 10000f; + @XmlElement @XmlJavaTypeAdapter(CollapsedStringAdapter.class) private String short_name; @@ -190,6 +198,28 @@ public class ParameterInfo { this.valid_range = valid_range; } + /** + * @return the minimum valid value + */ + public float getMinVal() { + float min = MIN_VALUE; + if (valid_range != null && valid_range.length == 2) { + min = valid_range[0]; + } + return min; + } + + /** + * @return the maximum valid value + */ + public float getMaxVal() { + float min = MAX_VALUE; + if (valid_range != null && valid_range.length == 2) { + min = valid_range[1]; + } + return min; + } + /** * @return the fillValue */ diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java index 5233f53657..5c447f51a7 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java @@ -91,6 +91,8 @@ import com.raytheon.uf.edex.database.purge.PurgeLogger; * smartInit hdf5 data * 03/07/13 #1773 njensen Logged commitGrid() times * 03/15/13 #1795 njensen Sped up commitGrid() + * 03/20/2013 #1774 randerso Removed dead method, changed to use new + * D2DGridDatabase constructor * * * @@ -356,48 +358,6 @@ public class GridParmManager { return sr; } - public static ServerResponse getD2DGridData( - List requests) { - - ServerResponse retVal = new ServerResponse(); - - // Get the grid data - ServerResponse> sr = getGridData(requests); - retVal.addMessages(sr); - if (!sr.isOkay()) { - return retVal; - } - - // // Now store it off in a temp location so the client can get to it - // for (IGridSlice slice : sr.getPayload()) { - // try { - // GridDatabase db = getDb(requests.get(0).getParmId().getDbId()); - // if (db instanceof D2DGridDatabase) { - // File tempDir = GfeUtil.getTempHDF5Dir( - // GridDatabase.gfeBaseDataDir, requests.get(0) - // .getParmId()); - // if (!tempDir.exists()) { - // tempDir.mkdirs(); - // } - // db.saveGridToHdf5(slice, GfeUtil.getTempHDF5File( - // GridDatabase.gfeBaseDataDir, requests.get(0) - // .getParmId()), GfeUtil.getHDF5Group( - // requests.get(0).getParmId(), slice.getValidTime())); - // } else { - // retVal - // .addMessage("Cannot save temp grids for non-D2D grid databases."); - // return retVal; - // } - // } catch (GfeException e) { - // sr.addMessage("Unable to get DB: " - // + requests.get(0).getParmId().getDbId()); - // return retVal; - // } - // } - return retVal; - - } - /** * * Request to commit data to the official database. The changes are * returned through the calling argument "changes". @@ -1197,7 +1157,12 @@ public class GridParmManager { IFPServerConfig serverConfig = IFPServerConfigManager .getServerConfig(siteId); try { - db = new D2DGridDatabase(serverConfig, dbId); + // this is still necessary on other JVMs from where + // ingested + String d2dModelName = serverConfig + .d2dModelNameMapping(modelName); + db = new D2DGridDatabase(serverConfig, d2dModelName, + dbId.getModelTimeAsDate()); } catch (Exception e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage()); @@ -1363,10 +1328,9 @@ public class GridParmManager { private static void createDbNotification(String siteID, List dbs, List additions, List deletions) { - DBInvChangeNotification notify = new DBInvChangeNotification(dbs, - additions, deletions, siteID); - if (!additions.isEmpty() || !deletions.isEmpty()) { + DBInvChangeNotification notify = new DBInvChangeNotification(dbs, + additions, deletions, siteID); SendNotifications.send(notify); } } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/D2DGridDatabase.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/D2DGridDatabase.java index e27107244c..9650c06cd1 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/D2DGridDatabase.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/D2DGridDatabase.java @@ -23,31 +23,34 @@ package com.raytheon.edex.plugin.gfe.server.database; import java.awt.Rectangle; import java.nio.FloatBuffer; import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.SortedSet; import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.measure.converter.UnitConverter; import javax.measure.unit.Unit; import com.raytheon.edex.plugin.gfe.config.IFPServerConfig; -import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager; -import com.raytheon.edex.plugin.gfe.db.dao.GFEDao; -import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException; +import com.raytheon.edex.plugin.gfe.db.dao.GFED2DDao; +import com.raytheon.edex.plugin.gfe.paraminfo.GridParamInfo; import com.raytheon.edex.plugin.gfe.paraminfo.GridParamInfoLookup; import com.raytheon.edex.plugin.gfe.paraminfo.ParameterInfo; -import com.raytheon.edex.util.Util; +import com.raytheon.edex.plugin.gfe.server.GridParmManager; +import com.raytheon.edex.plugin.gfe.util.GridTranslator; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory; import com.raytheon.uf.common.dataplugin.gfe.RemapGrid; import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID; +import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID.DataType; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridParmInfo; @@ -61,6 +64,7 @@ import com.raytheon.uf.common.dataplugin.gfe.slice.ScalarGridSlice; import com.raytheon.uf.common.dataplugin.gfe.slice.VectorGridSlice; import com.raytheon.uf.common.dataplugin.grid.GridPathProvider; import com.raytheon.uf.common.dataplugin.grid.GridRecord; +import com.raytheon.uf.common.dataplugin.level.Level; import com.raytheon.uf.common.datastorage.DataStoreFactory; import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.datastorage.Request; @@ -68,13 +72,16 @@ import com.raytheon.uf.common.datastorage.records.FloatDataRecord; import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.gridcoverage.GridCoverage; import com.raytheon.uf.common.message.WsId; +import com.raytheon.uf.common.parameter.mapping.ParameterMapper; +import com.raytheon.uf.common.status.IPerformanceStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.PerformanceStatus; 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.time.util.TimeUtil; +import com.raytheon.uf.common.util.mapping.MultipleMappingException; import com.raytheon.uf.edex.database.DataAccessLayerException; -import com.raytheon.uf.edex.database.plugin.PluginFactory; -import com.raytheon.uf.edex.plugin.grid.dao.GridDao; /** * Singleton that assists with grid data @@ -93,6 +100,7 @@ import com.raytheon.uf.edex.plugin.grid.dao.GridDao; * 10/10/12 #1260 randerso Changed to only retrieve slab containing overlapping * data instead of full grid. Added logging to support * GFE performance testing + * 03/19/2013 #1774 randerso Fix accumulative grid time ranges * * * @@ -103,19 +111,161 @@ public class D2DGridDatabase extends VGridDatabase { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(D2DGridDatabase.class); - // separate logger for GFE performance logging - private static final IUFStatusHandler gfePerformanceLogger = UFStatus - .getNamedHandler("GFEPerformanceLogger"); + /** + * Retrieve the gfe DatabaseID for a given d2d model run + * + * @param d2dModelName + * @param modelTime + * @param config + * @return + */ + public static DatabaseID getDbId(String d2dModelName, Date modelTime, + IFPServerConfig config) { + String gfeModelName = config.gfeModelNameMapping(d2dModelName); + if (gfeModelName == null || gfeModelName.isEmpty()) { + return null; + } + return new DatabaseID(getSiteID(config), DataType.GRID, "D2D", + gfeModelName, modelTime); + } + + /** + * Retrieves DatabaseIDs for all model runs of a given d2dModelName + * + * @param d2dModelName + * desired d2d model name + * @param gfeModel + * gfe model name to use + * @param siteID + * siteID to use in databaseId + * @param maxRecords + * max number of model runs to return + * @return + * @throws DataAccessLayerException + */ + public static List getD2DDatabaseIdsFromDb( + IFPServerConfig config, String d2dModelName) + throws DataAccessLayerException { + return getD2DDatabaseIdsFromDb(config, d2dModelName, -1); + } + + /** + * Retrieves DatabaseIDs for the n most recent model runs of a given + * d2dModelName + * + * @param d2dModelName + * desired d2d model name + * @param maxRecords + * max number of model runs to return + * @return + * @throws DataAccessLayerException + */ + public static List getD2DDatabaseIdsFromDb( + IFPServerConfig config, String d2dModelName, int maxRecords) + throws DataAccessLayerException { + + try { + GFED2DDao dao = new GFED2DDao(); + List result = dao.getD2DModelRunTimes(d2dModelName, + maxRecords); + + List dbInventory = new ArrayList(); + for (Date date : result) { + DatabaseID dbId = null; + dbId = getDbId(d2dModelName, date, config); + try { + GridDatabase db = GridParmManager.getDb(dbId); + if ((db != null) && !dbInventory.contains(dbId)) { + dbInventory.add(dbId); + } + } catch (GfeException e) { + statusHandler.handle(Priority.PROBLEM, + e.getLocalizedMessage(), e); + } + } + return dbInventory; + } catch (PluginException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + return Collections.emptyList(); + } + } + + // regex to match parmnnhr + private static final Pattern parmHrPattern = Pattern + .compile("(\\D+)\\d+hr"); + + private final IPerformanceStatusHandler perfLog = PerformanceStatus + .getHandler("GFE:"); + + private static class D2DParm { + private ParmID parmId; + + private GridParmInfo gpi; + + private Map fcstHrToTimeRange; + + private Map timeRangeToFcstHr; + + private String[] components; + + public D2DParm(ParmID parmId, GridParmInfo gpi, + Map fcstHrToTimeRange, String... components) { + this.parmId = parmId; + this.gpi = gpi; + this.fcstHrToTimeRange = fcstHrToTimeRange; + this.components = components; + + this.timeRangeToFcstHr = new HashMap( + fcstHrToTimeRange.size(), 1.0f); + + for (Entry entry : fcstHrToTimeRange.entrySet()) { + this.timeRangeToFcstHr.put(entry.getValue(), entry.getKey()); + } + } + + public ParmID getParmId() { + return parmId; + } + + public GridParmInfo getGpi() { + return gpi; + } + + public Map getFcstHrToTimeRange() { + return fcstHrToTimeRange; + } + + public Map getTimeRangeToFcstHr() { + return timeRangeToFcstHr; + } + + public String[] getComponents() { + return components; + } + + @Override + public String toString() { + return this.parmId.toString(); + } + } + + private String d2dModelName; + + private Date modelTime; + + private GridParamInfo modelInfo; + + private List availableTimes; /** The remap object used for resampling grids */ private final Map remap = new HashMap(); /** The destination GridLocation (The local GFE grid coverage) */ - private GridLocation outputLoc; + private GridLocation outputGloc; - private final List parms; + private Map gfeParms = new HashMap(); - public static final String GRID_LOCATION_CACHE_KEY = "GfeLocations"; + private Map d2dParms = new HashMap(); /** * Constructs a new D2DGridDatabase @@ -123,20 +273,39 @@ public class D2DGridDatabase extends VGridDatabase { * @param dbId * The database ID of this database */ - public D2DGridDatabase(IFPServerConfig config, DatabaseID dbId) - throws GfeException { + public D2DGridDatabase(IFPServerConfig config, String d2dModelName, + Date modelTime) throws GfeException { super(config); - this.dbId = dbId; - this.parms = new ArrayList(); - valid = this.dbId.isValid(); - if (valid) { + this.d2dModelName = d2dModelName; + this.modelTime = modelTime; + this.modelInfo = GridParamInfoLookup.getInstance().getGridParamInfo( + d2dModelName); + if (modelInfo == null) { + throw new GfeException("No model info for: " + d2dModelName); + } + this.availableTimes = modelInfo.getAvailableTimes(modelTime); + + // Get the database id for this database. + this.dbId = getDbId(this.d2dModelName, this.modelTime, this.config); + this.valid = this.dbId.isValid(); + + // get the output gloc' + if (this.valid) { + outputGloc = this.config.dbDomain(); + if (!outputGloc.isValid()) { + this.valid = false; + } + } + + // create the parms + if (this.valid) { loadParms(); - outputLoc = this.config.dbDomain(); } } - private RemapGrid getOrCreateRemap(GridCoverage awipsGrid) { + private RemapGrid getOrCreateRemap(GridCoverage awipsGrid) + throws GfeException { RemapGrid remap = this.remap.get(awipsGrid.getId()); if (remap == null) { String gfeModelName = dbId.getModelName(); @@ -144,19 +313,19 @@ public class D2DGridDatabase extends VGridDatabase { GridLocation inputLoc = new GridLocation(d2dModelName, awipsGrid); inputLoc.setSiteId(d2dModelName); Rectangle subdomain = NetCDFUtils.getSubGridDims(inputLoc, - this.outputLoc); + this.outputGloc); // fix up coordinates for 0,0 in upper left in A2 subdomain.y = inputLoc.gridSize().y - subdomain.y - subdomain.height; if (subdomain.isEmpty()) { - statusHandler.warn(this.dbId + throw new GfeException(this.dbId + ": GFE domain does not overlap dataset domain."); } else { GridLocation subGloc = new GridLocation(dbId.toString(), inputLoc, subdomain); - remap = new RemapGrid(subGloc, this.outputLoc); + remap = new RemapGrid(subGloc, this.outputGloc); this.remap.put(awipsGrid.getId(), remap); } @@ -169,80 +338,216 @@ public class D2DGridDatabase extends VGridDatabase { // no op } + /** + * Attempts to load the supplied ParmAtts using the given level. + * + * Certain weather elements are handled differently, if they are considered + * accumulative in nature, PoP, tp, cp are common examples. + * + * This method loads only Scalar parms + * + * @param atts + * @param level + */ + private void loadParm(ParameterInfo atts, String level) { + List accumParms = this.config.accumulativeD2DElements(this.dbId + .getModelName()); + boolean accParm = false; + if (accumParms.contains(atts.getShort_name())) { + accParm = true; + } + + ParmID pid = new ParmID(atts.getShort_name(), this.dbId, level); + if (!pid.isValid()) { + return; + } + + TimeConstraints tc = getTimeConstraints(availableTimes); + if (accParm) { + tc = new TimeConstraints(tc.getRepeatInterval(), + tc.getRepeatInterval(), tc.getStartTime()); + } + + float minV = atts.getMinVal(); + float maxV = atts.getMaxVal(); + int precision = calcPrecision(minV, maxV); + GridParmInfo gpi = new GridParmInfo(pid, this.outputGloc, + GridType.SCALAR, atts.getUnits(), atts.getLong_name(), minV, + maxV, precision, false, tc, accParm); + if (!gpi.isValid()) { + return; + } + + // get possible inventory times + HashMap possibleInventorySlots; + List forecastTimes = this.modelInfo.getTimes(); + possibleInventorySlots = new HashMap( + forecastTimes.size(), 1.0f); + if (accParm) { + long millisDur = tc.getDuration() * TimeUtil.MILLIS_PER_SECOND; + // adjust accumulative parms to have forecast hour + // at end of time range + for (int i = 0; i < forecastTimes.size(); i++) { + possibleInventorySlots.put(forecastTimes.get(i), new TimeRange( + new Date(availableTimes.get(i).getStart().getTime() + - millisDur), millisDur)); + } + } else if ((GridPathProvider.STATIC_PARAMETERS.contains(atts + .getShort_name())) && !availableTimes.isEmpty()) { + TimeRange ntr = availableTimes.get(0).combineWith( + availableTimes.get(availableTimes.size() - 1)); + // make static parms have a single time range that spans + // all availableTimes + for (int i = 0; i < forecastTimes.size(); i++) { + possibleInventorySlots.put(forecastTimes.get(i), ntr); + } + } else { + for (int i = 0; i < forecastTimes.size(); i++) { + possibleInventorySlots.put(forecastTimes.get(i), + availableTimes.get(i)); + } + } + + D2DParm d2dParm = new D2DParm(pid, gpi, possibleInventorySlots, + atts.getShort_name()); + this.gfeParms.put(pid, d2dParm); + this.d2dParms.put(compositeName(atts.getShort_name(), level), d2dParm); + } + + /** + * Loads a vector parm using the supplied u and v components at the + * specified level. + * + * Vectors are never rate-parms. + * + */ + private void loadParm(ParameterInfo uatts, ParameterInfo vatts, String level) { + ParmID pid = new ParmID("wind", dbId, level); + if (!pid.isValid()) { + return; + } + + TimeConstraints tc = getTimeConstraints(availableTimes); + + float maxV = uatts.getMaxVal(); + float minV = 0.0f; + int precision = calcPrecision(minV, maxV); + GridParmInfo gpi = new GridParmInfo(pid, outputGloc, GridType.VECTOR, + uatts.getUnits(), "wind", minV, maxV, precision, false, tc, + false); + + if (!gpi.isValid()) { + return; + } + + // get possible inventory times + List forecastTimes = this.modelInfo.getTimes(); + Map possibleInventorySlots = new HashMap( + forecastTimes.size(), 1.0f); + for (int i = 0; i < forecastTimes.size(); i++) { + possibleInventorySlots.put(forecastTimes.get(i), + availableTimes.get(i)); + } + + D2DParm d2dParm = new D2DParm(pid, gpi, possibleInventorySlots, + uatts.getShort_name(), vatts.getShort_name()); + this.gfeParms.put(pid, d2dParm); + this.d2dParms.put(compositeName(uatts.getShort_name(), level), d2dParm); + this.d2dParms.put(compositeName(vatts.getShort_name(), level), d2dParm); + } + /** * Loads all of the parms it can. */ private void loadParms() { - String gribModelName = config.d2dModelNameMapping(dbId.getModelName()); - Collection parmNames = new HashSet(GridParamInfoLookup - .getInstance().getParmNames(gribModelName)); + // NOTE: this is returned as a copy so we are not modifying the copy in + // modelInfo + Collection parmNames = modelInfo.getParmNames(); // first see if we can make wind... if ((parmNames.contains("uw")) && (parmNames.contains("vw"))) { - List uLevels = GridParamInfoLookup.getInstance() - .getParameterInfo(gribModelName, "uw").getLevels(); - List vLevels = GridParamInfoLookup.getInstance() - .getParameterInfo(gribModelName, "vw").getLevels(); - for (String level : uLevels) { - if (vLevels.contains(level)) { - parms.add(new ParmID("wind", dbId, level)); - } - } + // replace uw and vw with wind. + ParameterInfo uatts = this.modelInfo.getParameterInfo("uw"); + ParameterInfo vatts = this.modelInfo.getParameterInfo("vw"); + parmNames.remove("uw"); parmNames.remove("vw"); - } else if ((parmNames.contains("ws")) && (parmNames.contains("wd"))) { - List sLevels = GridParamInfoLookup.getInstance() - .getParameterInfo(gribModelName, "ws").getLevels(); - List dLevels = GridParamInfoLookup.getInstance() - .getParameterInfo(gribModelName, "wd").getLevels(); - for (String level : sLevels) { - if (dLevels.contains(level)) { - parms.add(new ParmID("wind", dbId, level)); - } + + for (String level : uatts.getLevels()) { + loadParm(uatts, vatts, level); } + + } else if ((parmNames.contains("ws")) && (parmNames.contains("wd"))) { + // replace ws and wd with wind. + ParameterInfo satts = this.modelInfo.getParameterInfo("ws"); + ParameterInfo datts = this.modelInfo.getParameterInfo("wd"); + parmNames.remove("ws"); parmNames.remove("wd"); + + for (String level : satts.getLevels()) { + loadParm(satts, datts, level); + } } // Now do all the scalars for (String parmName : parmNames) { - List levels = GridParamInfoLookup.getInstance() - .getParameterInfo(gribModelName, parmName).getLevels(); - if (levels.isEmpty()) { - levels = Arrays.asList("Dflt"); - } - for (String level : levels) { - parms.add(new ParmID(parmName, dbId, level)); + ParameterInfo atts = this.modelInfo.getParameterInfo(parmName); + + for (String level : atts.getLevels()) { + loadParm(atts, level); } } } @Override public ServerResponse> getGridInventory(ParmID id) { - List trs = new ArrayList(); ServerResponse> sr = new ServerResponse>(); - GFEDao dao = null; - try { - dao = (GFEDao) PluginFactory.getInstance().getPluginDao("gfe"); - } catch (PluginException e1) { - statusHandler - .handle(Priority.PROBLEM, "Unable to get GFE dao!", e1); - } - try { - List d2dTimes = dao.getD2DTimes(id); + List inventory; + D2DParm parm = this.gfeParms.get(id); + if (parm != null) { + // get database inventory + List dbInv = null; try { - trs = getTimeRange(id, d2dTimes); - } catch (IllegalArgumentException e) { - // Ignore + GFED2DDao dao = new GFED2DDao(); + + // get database inventory where all components are available + for (String component : parm.getComponents()) { + ParmID compPid = new ParmID(component, dbId, + id.getParmLevel()); + List compInv = dao + .queryFcstHourByD2DParmId(compPid); + + if (dbInv == null) { + dbInv = compInv; + } else { + dbInv.retainAll(compInv); + } + } + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Error retrieving inventory for " + id, e); + dbInv = Collections.emptyList(); } - sr.setPayload(trs); - return sr; - } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, - "Error retrieving D2D grid inventory from Database", e); - sr.addMessage("Error retrieving D2D grid inventory from Database"); - return sr; + + SortedSet invSet = new TreeSet(); + for (Integer forecastTime : dbInv) { + TimeRange tr = parm.getFcstHrToTimeRange().get(forecastTime); + if (tr != null) { + invSet.add(tr); + } else { + statusHandler.warn("No time range found for " + + parm.getParmId() + " at forecast time " + + forecastTime); + } + } + inventory = new ArrayList(invSet); + } else { + sr.addMessage("Unknown PID: " + id); + inventory = Collections.emptyList(); } + sr.setPayload(inventory); + return sr; } public boolean isParmInfoDefined(ParmID id) { @@ -278,7 +583,7 @@ public class D2DGridDatabase extends VGridDatabase { float minV = 0; float maxV = atts.getValid_range()[1]; int precision = calcPrecision(minV, maxV); - gpi = new GridParmInfo(id, this.outputLoc, GridType.VECTOR, + gpi = new GridParmInfo(id, this.outputGloc, GridType.VECTOR, atts.getUnits(), "wind", minV, maxV, precision, false, tc, false); sr.setPayload(gpi); @@ -291,9 +596,11 @@ public class D2DGridDatabase extends VGridDatabase { if (atts == null) { if (gpi == null) { - TimeConstraints tc = new TimeConstraints(3600, 3600, 0); - gpi = new GridParmInfo(id, this.outputLoc, GridType.SCALAR, "", - "", 0, 10000, 0, false, tc, false); + TimeConstraints tc = new TimeConstraints( + TimeUtil.SECONDS_PER_HOUR, TimeUtil.SECONDS_PER_HOUR, 0); + gpi = new GridParmInfo(id, this.outputGloc, GridType.SCALAR, + "", "", ParameterInfo.MIN_VALUE, + ParameterInfo.MAX_VALUE, 0, false, tc, false); } } else { @@ -332,9 +639,8 @@ public class D2DGridDatabase extends VGridDatabase { // max = MAXFLOAT; minV = 0; maxV = 10000; - if (!id.getParmName().equals("staticTopo") - && !id.getParmName().equals("staticSpacing") - && !id.getParmName().equals("staticCoriolis")) { + if (!GridPathProvider.STATIC_PARAMETERS.contains(id + .getParmName())) { statusHandler.handle(Priority.VERBOSE, "[valid_range] or [valid_min] or [valid_max] " + "not found for " + id.toString()); @@ -342,7 +648,7 @@ public class D2DGridDatabase extends VGridDatabase { } int precision = calcPrecision(minV, maxV); - gpi = new GridParmInfo(id, this.outputLoc, GridType.SCALAR, + gpi = new GridParmInfo(id, this.outputGloc, GridType.SCALAR, atts.getUnits(), atts.getLong_name(), minV, maxV, precision, false, tc, rateParm); } @@ -380,14 +686,15 @@ public class D2DGridDatabase extends VGridDatabase { @Override public ServerResponse> getParmList() { ServerResponse> sr = new ServerResponse>(); - List parmIds = new ArrayList(parms); + + List parmIds = new ArrayList(this.gfeParms.keySet()); sr.setPayload(parmIds); return sr; } @Override public String getProjectionId() { - return this.outputLoc.getProjection().getProjectionID(); + return this.outputGloc.getProjection().getProjectionID(); } @Override @@ -496,7 +803,7 @@ public class D2DGridDatabase extends VGridDatabase { * * @param parmId * The parmID of the data - * @param time + * @param timeRange * The time range of the data * @param gpi * The grid parm information associated with the data @@ -504,23 +811,33 @@ public class D2DGridDatabase extends VGridDatabase { * @throws GfeException * If the grid data cannot be retrieved */ - private Grid2DFloat getGrid(ParmID parmId, TimeRange time, + private Grid2DFloat getGrid(ParmID parmId, TimeRange timeRange, GridParmInfo gpi, boolean convertUnit) throws GfeException { Grid2DFloat bdata = null; GridRecord d2dRecord = null; long t0 = System.currentTimeMillis(); - GFEDao dao = null; + GFED2DDao dao = null; try { - dao = (GFEDao) PluginFactory.getInstance().getPluginDao("gfe"); + dao = new GFED2DDao(); } catch (PluginException e1) { throw new GfeException("Unable to get GFE dao!", e1); } try { // Gets the metadata from the grib metadata database - d2dRecord = dao.getD2DGrid(parmId, time, gpi); + Integer fcstHr = null; + if (!GridPathProvider.STATIC_PARAMETERS.contains(parmId + .getParmName())) { + D2DParm parm = this.gfeParms.get(parmId); + fcstHr = parm.getTimeRangeToFcstHr().get(timeRange); + if (fcstHr == null) { + throw new GfeException("Invalid time range " + timeRange + + " for " + parmId); + } + } + d2dRecord = dao.getD2DGrid(parmId, fcstHr, gpi); } catch (DataAccessLayerException e) { throw new GfeException( "Error retrieving D2D Grid record from database", e); @@ -529,7 +846,7 @@ public class D2DGridDatabase extends VGridDatabase { if (d2dRecord == null) { throw new GfeException("No data available for " + parmId - + " for time range " + time); + + " for time range " + timeRange); } // Gets the raw data from the D2D grib HDF5 file @@ -559,14 +876,10 @@ public class D2DGridDatabase extends VGridDatabase { } long t3 = System.currentTimeMillis(); - if (gfePerformanceLogger.isPriorityEnabled(Priority.DEBUG)) { - gfePerformanceLogger.handle(Priority.DEBUG, - "D2DGridDatabase.getGrid" + // - " metaData: " + (t1 - t0) + // - " hdf5: " + (t2 - t1) + // - " remap: " + (t3 - t2) + // - " total: " + (t3 - t0)); - } + perfLog.logDuration("D2DGridDatabase.getGrid metaData: ", (t1 - t0)); + perfLog.logDuration("D2DGridDatabase.getGrid hdf5: ", (t2 - t1)); + perfLog.logDuration("D2DGridDatabase.getGrid remap: ", (t3 - t2)); + perfLog.logDuration("D2DGridDatabase.getGrid total: ", (t3 - t0)); return retVal; @@ -612,7 +925,7 @@ public class D2DGridDatabase extends VGridDatabase { * * @param parmId * The parmID of the data - * @param time + * @param timeRange * The time range of the data * @param gpi * The grid parm info for the data @@ -623,73 +936,79 @@ public class D2DGridDatabase extends VGridDatabase { * @throws GfeException * The the wind grids cannot be constructed */ - private void getWindGrid(ParmID parmId, TimeRange time, GridParmInfo gpi, - Grid2DFloat mag, Grid2DFloat dir) throws GfeException { + private void getWindGrid(ParmID parmId, TimeRange timeRange, + GridParmInfo gpi, Grid2DFloat mag, Grid2DFloat dir) + throws GfeException { - GFEDao dao = null; + GFED2DDao dao = null; try { - dao = (GFEDao) PluginFactory.getInstance().getPluginDao("gfe"); + dao = new GFED2DDao(); } catch (PluginException e1) { throw new GfeException("Unable to get GFE dao!!", e1); } - GridRecord uRecord = null; - GridRecord vRecord = null; - GridRecord sRecord = null; - GridRecord dRecord = null; - try { - // Get the metadata from the grib metadata database - uRecord = dao.getD2DGrid( - new ParmID("uW", this.dbId, parmId.getParmLevel()), time, - gpi); - vRecord = dao.getD2DGrid( - new ParmID("vW", this.dbId, parmId.getParmLevel()), time, - gpi); - } catch (DataAccessLayerException e) { - throw new GfeException( - "Unable to retrieve wind grids from D2D database", e); + D2DParm windParm = this.gfeParms.get(parmId); + Integer fcstHr = windParm.getTimeRangeToFcstHr().get(timeRange); + if (fcstHr == null) { + throw new GfeException("Invalid time range " + timeRange + " for " + + parmId); } String mappedModel = config.d2dModelNameMapping(dbId.getModelName()); - if ((uRecord != null) && (vRecord != null)) { - // Gets the raw grid data from the D2D grib HDF5 files - Grid2DFloat uData = getRawGridData(uRecord); - Grid2DFloat vData = getRawGridData(vRecord); - - // Resample the data to fit the desired region - float fillV = Float.MAX_VALUE; - ParameterInfo pa = GridParamInfoLookup.getInstance() - .getParameterInfo(mappedModel, "uw"); - if (pa != null) { - fillV = pa.getFillValue(); - } - - try { - RemapGrid remap = getOrCreateRemap(uRecord.getLocation()); - remap.remapUV(uData, vData, fillV, gpi.getMaxValue(), - gpi.getMinValue(), gpi.getMinValue(), true, true, mag, - dir); - } catch (Exception e) { - throw new GfeException("Unable to remap UV wind grids", e); - } - return; - } else { + if (windParm.getComponents()[0].equals("uw")) { try { + GridRecord uRecord = null; + GridRecord vRecord = null; // Get the metadata from the grib metadata database - sRecord = dao.getD2DGrid( - new ParmID("ws", this.dbId, parmId.getParmLevel()), - time, gpi); - dRecord = dao.getD2DGrid( - new ParmID("wd", this.dbId, parmId.getParmLevel()), - time, gpi); + + uRecord = dao.getD2DGrid( + new ParmID("uw", this.dbId, parmId.getParmLevel()), + fcstHr, gpi); + vRecord = dao.getD2DGrid( + new ParmID("vw", this.dbId, parmId.getParmLevel()), + fcstHr, gpi); + + // Gets the raw grid data from the D2D grib HDF5 files + Grid2DFloat uData = getRawGridData(uRecord); + Grid2DFloat vData = getRawGridData(vRecord); + + // Resample the data to fit the desired region + float fillV = Float.MAX_VALUE; + ParameterInfo pa = GridParamInfoLookup.getInstance() + .getParameterInfo(mappedModel, "uw"); + if (pa != null) { + fillV = pa.getFillValue(); + } + + try { + RemapGrid remap = getOrCreateRemap(uRecord.getLocation()); + remap.remapUV(uData, vData, fillV, gpi.getMaxValue(), + gpi.getMinValue(), gpi.getMinValue(), true, true, + mag, dir); + } catch (Exception e) { + throw new GfeException("Unable to remap UV wind grids", e); + } + return; } catch (DataAccessLayerException e) { throw new GfeException( "Unable to retrieve wind grids from D2D database", e); } - if ((sRecord != null) && (dRecord != null)) { + } else { + try { + GridRecord sRecord = null; + GridRecord dRecord = null; + + // Get the metadata from the grib metadata database + sRecord = dao.getD2DGrid( + new ParmID("ws", this.dbId, parmId.getParmLevel()), + fcstHr, gpi); + dRecord = dao.getD2DGrid( + new ParmID("wd", this.dbId, parmId.getParmLevel()), + fcstHr, gpi); + // Gets the raw grid data from the D2D grib HDF5 files Grid2DFloat sData = getRawGridData(sRecord); Grid2DFloat dData = getRawGridData(dRecord); @@ -710,42 +1029,30 @@ public class D2DGridDatabase extends VGridDatabase { throw new GfeException("Unable to remap wind grids", e); } return; + } catch (DataAccessLayerException e) { + throw new GfeException( + "Unable to retrieve wind grids from D2D database", e); } } - - String message = "Wind record"; - if (uRecord == null) { - message += " uW"; - } - if (vRecord == null) { - message += " vW"; - } - if (sRecord == null) { - message += " ws"; - } - if (dRecord == null) { - message += " wd"; - } - message += " is null for db " + dbId.toString() + ", level " - + parmId.getParmLevel() + ", time " + time.toString(); - throw new GfeException(message); } /** * Gets the raw data from the D2D HDF5 repository * * @param d2dRecord - * The grib metadata + * The grid metadata * @return The raw data * @throws GfeException */ private Grid2DFloat getRawGridData(GridRecord d2dRecord) throws GfeException { try { - GridDao dao = new GridDao(); + GFED2DDao dao = new GFED2DDao(); + // TODO should we add subgrid support to GridDao or PluginDao + // reimplementing this call here with subgrid support // dao.getHDF5Data(d2dRecord, -1); - // TODO should we add subgrid support to GribDao or PluginDao + IDataStore dataStore = dao.getDataStore(d2dRecord); GridLocation gloc = getOrCreateRemap(d2dRecord.getLocation()) @@ -781,59 +1088,6 @@ public class D2DGridDatabase extends VGridDatabase { } } - /** - * Assigns the appropriate time range to the inventory - * - * @param parmName - * The parm name - * @param inventory - * The inventory of times to examine - * @return The inventory with corrected time ranges - * @throws GfeException - * If time ranges cannot be reassigned - */ - private List getTimeRange(ParmID id, List inventory) - throws GfeException { - String parmName = id.getParmName(); - List times = GridParamInfoLookup - .getInstance() - .getParameterTimes( - config.d2dModelNameMapping(id.getDbId().getModelName()), - id.getDbId().getModelDate()); - TimeConstraints tc = this.getTimeConstraints(times); - if (config.accumulativeD2DElements(dbId.getModelName()).contains( - parmName)) { - tc = new TimeConstraints(tc.getRepeatInterval(), - tc.getRepeatInterval(), tc.getStartTime()); - } - - if ((inventory.size() > 1) - && (parmName.equals("staticTopo") - || parmName.equals("staticSpacing") || parmName - .equals("staticCoriolis"))) { - TimeRange ntr = new TimeRange( - inventory.get(0).getStart().getTime(), inventory - .get(inventory.size() - 1).getEnd().getTime() - + Util.MILLI_PER_HOUR); - inventory.clear(); - inventory.add(ntr); - } else { - List newInventory = new ArrayList( - inventory.size()); - for (TimeRange tr : inventory) { - if (isNonAccumDuration(id, inventory) && tr.isValid() - && !GFEDao.isMos(id)) { - newInventory.add(tc.constraintTime(tr.getEnd())); - } else { - newInventory.add(tc.constraintTime(tr.getStart())); - } - } - inventory = newInventory; - } - - return inventory; - } - /** * Gets time constraints based on an ordered list of times * @@ -844,20 +1098,25 @@ public class D2DGridDatabase extends VGridDatabase { private TimeConstraints getTimeConstraints(List times) { if (times.size() <= 1) { - return new TimeConstraints(3600, 3600, 0); + return new TimeConstraints(TimeUtil.SECONDS_PER_HOUR, + TimeUtil.SECONDS_PER_HOUR, 0); } long repeat = (times.get(1).getStart().getTime() - times.get(0) - .getStart().getTime()) / 1000; - long start = (times.get(0).getStart().getTime() / 1000) % 86400; + .getStart().getTime()) + / TimeUtil.MILLIS_PER_SECOND; + long start = (times.get(0).getStart().getTime() / TimeUtil.MILLIS_PER_SECOND) + % TimeUtil.SECONDS_PER_DAY; for (int i = 1; i < times.size() - 1; i++) { if (((times.get(i + 1).getStart().getTime() - times.get(i) - .getStart().getTime()) / 1000) != repeat) { - return new TimeConstraints(3600, 3600, 0); + .getStart().getTime()) / TimeUtil.MILLIS_PER_SECOND) != repeat) { + return new TimeConstraints(TimeUtil.SECONDS_PER_HOUR, + TimeUtil.SECONDS_PER_HOUR, 0); } } - return new TimeConstraints(3600, (int) repeat, (int) start); + return new TimeConstraints(TimeUtil.SECONDS_PER_HOUR, (int) repeat, + (int) start); } private int calcPrecision(float minV, float maxV) { @@ -886,9 +1145,9 @@ public class D2DGridDatabase extends VGridDatabase { @Override public SortedSet getValidTimes() throws GfeException, DataAccessLayerException { - GFEDao dao = null; + GFED2DDao dao = null; try { - dao = (GFEDao) PluginFactory.getInstance().getPluginDao("gfe"); + dao = new GFED2DDao(); } catch (PluginException e) { throw new GfeException("Unable to get GFE dao!!", e); } @@ -915,30 +1174,54 @@ public class D2DGridDatabase extends VGridDatabase { // no-op } - public static boolean isNonAccumDuration(ParmID id, - Collection times) throws GfeConfigurationException { - boolean isAccum = false; - try { - isAccum = IFPServerConfigManager - .getServerConfig(id.getDbId().getSiteId()) - .accumulativeD2DElements(id.getDbId().getModelName()) - .contains(id.getParmName()); - } catch (GfeConfigurationException e) { - throw e; + public ParmID getParmId(String d2dParmName, Level level) { + String gfeParmName = getGfeParmName(d2dParmName); + + String levelName = GridTranslator.getShortLevelName(level + .getMasterLevel().getName(), level.getLevelonevalue(), level + .getLeveltwovalue()); + + D2DParm parm = d2dParms.get(compositeName(gfeParmName, levelName)); + if (parm != null) { + return parm.getParmId(); } - if (!isAccum) { - boolean isDuration = false; - for (TimeRange time : times) { - if (time.getDuration() > 0) { - isDuration = true; - break; - } + Matcher matcher = parmHrPattern.matcher(d2dParmName); + if (matcher.find()) { + String abbrev = matcher.group(1); + gfeParmName = getGfeParmName(abbrev); + parm = d2dParms.get(compositeName(gfeParmName, levelName)); + if (parm != null) { + return parm.getParmId(); } - return isDuration; } - return !isAccum; + return null; } + private String getGfeParmName(String d2dParmName) { + String gfeParmName = null; + try { + gfeParmName = ParameterMapper.getInstance().lookupAlias( + d2dParmName, "gfeParamName"); + } catch (MultipleMappingException e) { + statusHandler.handle(Priority.WARN, e.getLocalizedMessage(), e); + gfeParmName = e.getArbitraryMapping(); + } + return gfeParmName; + } + + public TimeRange getTimeRange(ParmID parmID, Integer fcstHour) { + D2DParm parm = this.gfeParms.get(parmID); + if (parm == null) { + statusHandler.warn("No D2D parameter found for " + parmID); + return null; + } + TimeRange tr = parm.getFcstHrToTimeRange().get(fcstHour); + return tr; + } + + private String compositeName(String parmName, String level) { + return parmName + "_" + level; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java index a25c00e1ec..d33b9c7d17 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java @@ -94,7 +94,6 @@ import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.plugin.PluginFactory; import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.io.WKTReader; /** * GFE Grid database containing IFP Grid data. @@ -115,6 +114,7 @@ import com.vividsolutions.jts.io.WKTReader; * 02/12/13 #1608 randerso Changed to explicitly call deleteGroups * 03/07/13 #1737 njensen Logged getGridData times * 03/15/13 #1795 njensen Added updatePublishTime() + * 03/20/13 #1774 randerso Cleanup code to use proper constructors * * * @@ -1191,6 +1191,7 @@ public class IFPGridDatabase extends GridDatabase { "Unable to update grid history!!", e); } return sr; + } /** @@ -1591,77 +1592,79 @@ public class IFPGridDatabase extends GridDatabase { protected GridParmInfo populateGpi(Map dataAttributes) throws Exception { - GridParmInfo gpi = new GridParmInfo(); - TimeConstraints tc = new TimeConstraints(); - GridLocation location = new GridLocation(); - ProjectionData pd = new ProjectionData(); - - pd.setProjectionID((String) dataAttributes - .get("gridLoc.projection.projectionID")); - pd.setProjectionType(ProjectionType.valueOf((String) dataAttributes - .get("gridLoc.projection.projectionType"))); - pd.setLatLonLL(new Coordinate((Float) dataAttributes - .get("gridLoc.projection.latLonLL.x"), (Float) dataAttributes - .get("gridLoc.projection.latLonLL.y"))); - pd.setLatLonUR(new Coordinate((Float) dataAttributes - .get("gridLoc.projection.latLonUR.x"), (Float) dataAttributes - .get("gridLoc.projection.latLonUR.y"))); - pd.setLatLonOrigin(new Coordinate((Float) dataAttributes - .get("gridLoc.projection.latLonOrigin.x"), - (Float) dataAttributes.get("gridLoc.projection.latLonOrigin.y"))); - pd.setStdParallelOne((Float) dataAttributes - .get("gridLoc.projection.stdParallelOne")); - pd.setStdParallelTwo((Float) dataAttributes - .get("gridLoc.projection.stdParallelTwo")); - pd.setGridPointLL(new Point((Integer) dataAttributes - .get("gridLoc.projection.gridPointLL.x"), + String projID = (String) dataAttributes + .get("gridLoc.projection.projectionID"); + ProjectionType projType = ProjectionType + .valueOf((String) dataAttributes + .get("gridLoc.projection.projectionType")); + Coordinate latLonLL = new Coordinate( + (Float) dataAttributes.get("gridLoc.projection.latLonLL.x"), + (Float) dataAttributes.get("gridLoc.projection.latLonLL.y")); + Coordinate latLonUR = new Coordinate( + (Float) dataAttributes.get("gridLoc.projection.latLonUR.x"), + (Float) dataAttributes.get("gridLoc.projection.latLonUR.y")); + Coordinate latLonOrig = new Coordinate( + (Float) dataAttributes.get("gridLoc.projection.latLonOrigin.x"), + (Float) dataAttributes.get("gridLoc.projection.latLonOrigin.y")); + Float stdPar1 = (Float) dataAttributes + .get("gridLoc.projection.stdParallelOne"); + Float stdPar2 = (Float) dataAttributes + .get("gridLoc.projection.stdParallelTwo"); + Point gridLL = new Point( (Integer) dataAttributes - .get("gridLoc.projection.gridPointLL.y"))); - pd.setGridPointUR(new Point((Integer) dataAttributes - .get("gridLoc.projection.gridPointUR.x"), + .get("gridLoc.projection.gridPointLL.x"), (Integer) dataAttributes - .get("gridLoc.projection.gridPointUR.y"))); - pd.setLatIntersect((Float) dataAttributes - .get("gridLoc.projection.latIntersect")); - pd.setLonCenter((Float) dataAttributes - .get("gridLoc.projection.lonCenter")); - pd.setLonOrigin((Float) dataAttributes - .get("gridLoc.projection.lonOrigin")); + .get("gridLoc.projection.gridPointLL.y")); + Point gridUR = new Point( + (Integer) dataAttributes + .get("gridLoc.projection.gridPointUR.x"), + (Integer) dataAttributes + .get("gridLoc.projection.gridPointUR.y")); + Float latInt = (Float) dataAttributes + .get("gridLoc.projection.latIntersect"); + Float lonCenter = (Float) dataAttributes + .get("gridLoc.projection.lonCenter"); + Float lonOrig = (Float) dataAttributes + .get("gridLoc.projection.lonOrigin"); + ProjectionData proj = new ProjectionData(projID, projType, latLonLL, + latLonUR, latLonOrig, stdPar1, stdPar2, gridLL, gridUR, latInt, + lonCenter, lonOrig); - location.setSiteId((String) dataAttributes.get("gridLoc.siteID")); - location.setNx((Integer) dataAttributes.get("gridLoc.nx")); - location.setNy((Integer) dataAttributes.get("gridLoc.ny")); - location.setTimeZone((String) dataAttributes.get("gridLoc.timeZone")); - location.setOrigin(new Coordinate((Float) dataAttributes - .get("gridLoc.origin.x"), (Float) dataAttributes - .get("gridLoc.origin.y"))); - location.setExtent(new Coordinate((Float) dataAttributes - .get("gridLoc.extent.x"), (Float) dataAttributes - .get("gridLoc.extent.y"))); - location.setGeometry(new WKTReader().read((String) dataAttributes - .get("gridLoc.geometry"))); - location.setCrsWKT((String) dataAttributes.get("gridLoc.crs")); - location.setProjection(pd); + String id = (String) dataAttributes.get("gridLoc.siteID"); + int nx = (Integer) dataAttributes.get("gridLoc.nx"); + int ny = (Integer) dataAttributes.get("gridLoc.ny"); + Coordinate domainOrigin = new Coordinate( + (Float) dataAttributes.get("gridLoc.origin.x"), + (Float) dataAttributes.get("gridLoc.origin.y")); + Coordinate domainExtent = new Coordinate( + (Float) dataAttributes.get("gridLoc.extent.x"), + (Float) dataAttributes.get("gridLoc.extent.y")); + String timeZone = (String) dataAttributes.get("gridLoc.timeZone"); + GridLocation gridLoc = new GridLocation(id, proj, new Point(nx, ny), + domainOrigin, domainExtent, timeZone); - tc.setDuration((Integer) dataAttributes.get("timeConstraints.duration")); - tc.setRepeatInterval((Integer) dataAttributes - .get("timeConstraints.repeatInterval")); - tc.setStartTime((Integer) dataAttributes - .get("timeConstraints.startTime")); + int duration = (Integer) dataAttributes.get("timeConstraints.duration"); + int repeatInterval = (Integer) dataAttributes + .get("timeConstraints.repeatInterval"); + int startTime = (Integer) dataAttributes + .get("timeConstraints.startTime"); + TimeConstraints timeConstraints = new TimeConstraints(duration, + repeatInterval, startTime); - gpi.setParmID(new ParmID((String) dataAttributes.get("parmID"))); - gpi.setGridType(GridType.valueOf((String) dataAttributes - .get("gridType"))); - gpi.setDescriptiveName((String) dataAttributes.get("descriptiveName")); - gpi.setUnitString((String) dataAttributes.get("unitString")); - gpi.setMaxValue((Float) dataAttributes.get("maxValue")); - gpi.setMinValue((Float) dataAttributes.get("minValue")); - gpi.setPrecision((Integer) dataAttributes.get("precision")); - gpi.setRateParm((Boolean) dataAttributes.get("rateParm")); - gpi.setTimeIndependentParm((Boolean) dataAttributes - .get("timeIndependentParm")); - gpi.setTimeConstraints(tc); - gpi.setGridLoc(location); + ParmID parmId = new ParmID((String) dataAttributes.get("parmID")); + GridType gridType = GridType.valueOf((String) dataAttributes + .get("gridType")); + String descriptiveName = (String) dataAttributes.get("descriptiveName"); + String unit = (String) dataAttributes.get("unitString"); + Float minValue = (Float) dataAttributes.get("minValue"); + Float maxValue = (Float) dataAttributes.get("maxValue"); + int precision = (Integer) dataAttributes.get("precision"); + boolean timeIndependentParm = (Boolean) dataAttributes + .get("timeIndependentParm"); + boolean rateParm = (Boolean) dataAttributes.get("rateParm"); + GridParmInfo gpi = new GridParmInfo(parmId, gridLoc, gridType, unit, + descriptiveName, minValue, maxValue, precision, + timeIndependentParm, timeConstraints, rateParm); return gpi; } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/notify/GfeIngestNotificationFilter.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/notify/GfeIngestNotificationFilter.java index 50c7ad17e2..c648026d6d 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/notify/GfeIngestNotificationFilter.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/notify/GfeIngestNotificationFilter.java @@ -36,34 +36,32 @@ import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager; import com.raytheon.edex.plugin.gfe.exception.GfeConfigurationException; import com.raytheon.edex.plugin.gfe.server.D2DSatParm; import com.raytheon.edex.plugin.gfe.server.GridParmManager; +import com.raytheon.edex.plugin.gfe.server.database.D2DGridDatabase; import com.raytheon.edex.plugin.gfe.server.database.D2DSatDatabase; import com.raytheon.edex.plugin.gfe.server.database.D2DSatDatabaseManager; import com.raytheon.edex.plugin.gfe.smartinit.SmartInitQueue; import com.raytheon.edex.plugin.gfe.smartinit.SmartInitRecord; import com.raytheon.edex.plugin.gfe.smartinit.SmartInitRecordPK; -import com.raytheon.edex.plugin.gfe.util.GridTranslator; import com.raytheon.edex.plugin.gfe.util.SendNotifications; import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory; import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID; -import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID.DataType; import com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID; import com.raytheon.uf.common.dataplugin.gfe.server.notify.DBInvChangeNotification; import com.raytheon.uf.common.dataplugin.gfe.server.notify.GfeNotification; import com.raytheon.uf.common.dataplugin.gfe.server.notify.GridUpdateNotification; import com.raytheon.uf.common.dataplugin.grid.GridRecord; +import com.raytheon.uf.common.dataplugin.level.Level; import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord; import com.raytheon.uf.common.message.WsId; -import com.raytheon.uf.common.parameter.mapping.ParameterMapper; import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; -import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.TimeRange; -import com.raytheon.uf.common.util.mapping.MultipleMappingException; import com.raytheon.uf.edex.core.EDEXUtil; /** - * TODO Add Description + * Filters data URI notifications and sends GridUpdate and DbInvChanged + * notifications for new D2D data * *
  * 
@@ -77,6 +75,7 @@ import com.raytheon.uf.edex.core.EDEXUtil;
  *                                      D2DParmIdCache to GfeIngestNotificationFilter
  * Mar 25, 2013       1823 dgilling     Trigger SAT smart init based only on record's
  *                                      SectorId and PhysicalElement.
+ * Mar 20, 2013      #1774 randerso     Refactor to use grid durations from D2DGridDatabase
  * 
  * 
* @@ -124,7 +123,6 @@ public class GfeIngestNotificationFilter { Map inits = new HashMap(); // Loop through each record received and construct a ParmID Map> gridInv = new HashMap>(); - List guns = new ArrayList(); Set newDbs = new HashSet(); IFPServerConfig config = null; @@ -138,12 +136,11 @@ public class GfeIngestNotificationFilter { for (GridRecord grid : gridRecords) { String gfeModel = config.gfeModelNameMapping(grid .getDatasetId()); + DatabaseID dbId = D2DGridDatabase.getDbId(grid.getDatasetId(), + grid.getDataTime().getRefTime(), config); // ignore if no mapping - if (gfeModel != null && gfeModel.length() > 0) { - DatabaseID dbId = new DatabaseID(site, DataType.GRID, - "D2D", gfeModel, grid.getDataTime().getRefTime()); - + if (dbId != null) { if ((!D2DParmIdCache.getInstance().getDatabaseIDs() .contains(dbId)) && (!newDbs.contains(dbId))) { @@ -158,33 +155,22 @@ public class GfeIngestNotificationFilter { } String abbrev = grid.getParameter().getAbbreviation(); - String gfeParmName = null; - try { - gfeParmName = ParameterMapper.getInstance() - .lookupAlias(abbrev, "gfeParamName"); - } catch (MultipleMappingException e) { - statusHandler.handle(Priority.WARN, - e.getLocalizedMessage(), e); - gfeParmName = e.getArbitraryMapping(); - } + Level level = grid.getLevel(); - String level = GridTranslator.getShortLevelName(grid - .getLevel().getMasterLevel().getName(), grid - .getLevel().getLevelonevalue(), grid.getLevel() - .getLeveltwovalue()); - ParmID parmID = new ParmID(gfeParmName, dbId, level); + D2DGridDatabase db = (D2DGridDatabase) GridParmManager + .getDb(dbId); + ParmID parmID = db.getParmId(abbrev, level); List trs = gridInv.get(parmID); if (trs == null) { trs = new ArrayList(); gridInv.put(parmID, trs); } - TimeRange validPeriod = grid.getDataTime().getValidPeriod(); - if (validPeriod.getDuration() > 0) { - trs.add(validPeriod); - } else { - trs.add(new TimeRange(grid.getDataTime() - .getValidPeriod().getStart(), 3600 * 1000)); + + Integer fcstHour = grid.getDataTime().getFcstTime(); + TimeRange tr = db.getTimeRange(parmID, fcstHour); + if (tr != null) { + trs.add(tr); } List siteInitModules = config.initModels(gfeModel); @@ -215,6 +201,7 @@ public class GfeIngestNotificationFilter { } // DR 15442 - move last for loop out of the for loop at line 110 + List guns = new ArrayList(); for (ParmID parmId : gridInv.keySet()) { try { List trs = gridInv.get(parmId); diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/parameter/alias/gfeParamName.xml b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/parameter/alias/gfeParamName.xml index 48b70d36fb..0641151bfb 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/parameter/alias/gfeParamName.xml +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/parameter/alias/gfeParamName.xml @@ -1,152 +1,437 @@ + - wgh - av - crain - cfrzr - cicep - csnow - cape - cin - cp - cp3hr - dpd - dpt - wvdir - swdir - ept - geh - gh - hidx - lgsp - lgsp3hr - lhf - mnt - wvper - swper - mxt - pli - pot - p - pmsl - emsp - mmsp - dirpw - perpw - htsgw - pr - cpofp - cpozp - pw - rh - shf - dirsw - persw - wvhgt - swell - scp - snd - sh - heli - sli - bli - t - tcc - thp - tp - tp3hr - tp6hr - tp12hr - tp24hr - tp48hr - ustm - vstm - uw - vw - vapp - pvv - vis - vpt - weasd - wd - ws - wgs - msg - svv - gvv - ki - tke - - ccpc - pt3 - ww - tp_HPC - tp_ACR - tp_ALR - tp_FWR - tp_KRF - tp_MSR - tp_ORN - tp_PTR - tp_RHA - tp_RSA - tp_STR - tp_TAR - tp_TIR - tp_TUA - tpmean3 - tpmean6 - tpmean12 - tpmean24 - snolmean12 - tpsprd3 - tpsprd6 - tpsprd12 - tpsprd24 - snolsprd12 - qpe1 - qpe6 - Surge10Pct - PSurge10Ft - PSurge9Ft - PSurge8Ft - PSurge7Ft - PSurge6Ft - PSurge5Ft - PSurge4Ft - PSurge3Ft - PSurge2Ft - sld - maxRH3hr - maxRH12hr - minRH3hr - minRH12hr - SloshSurge - Surge20Pct - Surge30Pct - Surge40Pct - Surge50Pct - Surge60Pct - Surge70Pct - Surge80Pct - Surge90Pct - PSurge11Ft - PSurge12Ft - PSurge13Ft - PSurge14Ft - PSurge15Ft - PSurge16Ft - PSurge17Ft - PSurge18Ft - PSurge19Ft - PSurge20Ft - PSurge21Ft - PSurge22Ft - PSurge23Ft - PSurge24Ft - PSurge25Ft + av + cape + cfrzr + cicep + cin + cp3hr + cp + cpofp + cpozp + crain + csnow + dirpw + dirsw + dpd + dpt + emsp + ept + geh + gh + gvv + heli + hidx + htsgw + ki + lgsp3hr + lgsp + lhf + mmsp + mnt + msg + mxt + perpw + persw + pli + pmsl + pot + p + pr + pvv + pw + rh + scp + shf + sh + sli + snd + svv + swdir + swell + swper + tcc + thp + tke + tp12hr + tp24hr + tp3hr + tp48hr + tp6hr + tp + t + ustm + uw + vapp + vis + vpt + vstm + vw + wd + weasd + wgh + wgs + ws + wvdir + wvhgt + wvper + + adimc + alti + bh + bli + bpvv + bwu + bwv + capec1 + capec2 + capec3 + capec4 + capec5 + cb + cc + ccov + ccpc + cfrzrc1 + cfrzrmean + cfrzrsprd + cice + cicepc1 + cicepmean + cicepsprd + cigc1 + cigc2 + cigc3 + cp2hr + cpvv + crainc1 + crainmean + crainsprd + csnowc1 + csnowmean + csnowsprd + cssi + ctop + ctstm + ctyp + cw + cxr + dpterranl + dptmean + dptsprd + elon + fd + fznp + ghmean + ghsprd + hyc + icec + iceg + icng + icprb + icsev + iidx + ilw + ip + lgsp2hr + llip + llr + lzfpc + lzfsc + lztwc + madv + maxRH12hr + maxRH3hr + mcdd + mcon + minRH12hr + minRH3hr + mnt12hr + mnt3hr + mnt6hr + mret + mslp + mwu + mwv + mxt12hr + mxt3hr + mxt6hr + nbe + nlat + nlrs + otim + pacc + pbe + pt3 + pc + perranl + pice + plixc1 + plixc2 + plixc3 + plixc4 + plixc5 + pmslmean + pmslsprd + pop12hr + pop3hr + pop6hr + pop + ppam + ppan + ppas + ppbm + ppbn + ppbs + ppffg + ppnn + prcp12hr + prcp3hr + prcp6hr + prob34 + prob50 + prob64 + ptam + ptan + pta + ptas + ptbm + ptbn + ptbs + ptnn + ptor + pt + ptt + ptyp + pwmean + pws34 + pws50 + pws64 + pwsprd + qpe1 + qpe6 + qpe24 + rain + refc + refd + rhmean + rhsprd + routed_flow_c + routed_flow_h + routed_flow_m + routed_flow + rr + rrv + s1hr + sacc + sherranl + shwlt + sld + si + smc + snol12c10 + snol12c1 + snol12c2 + snol12c3 + snol12c4 + snol12c5 + snol12c6 + snol12c7 + snol12c8 + snol12c9 + snolmean12 + snolsprd12 + snowd3hr + snowd6hr + snow + spt + stot + stpa + st + tadv + tc1 + terranl + thp12hr + thp3hr + thp6hr + tmean + totsn + tp120hr + tp12c1 + tp12c2 + tp12c3 + tp12c4 + tp12c5 + tp12c6 + tp12c7 + tp12c8 + tpmean12 + tpsprd12 + tp24c1 + tp24c2 + tp24c3 + tp24c4 + tp24c5 + tp24c6 + tp24c7 + tp24c8 + tpmean24 + tpsprd24 + tp3c1 + tp3c2 + tp3c3 + tp3c4 + tp3c5 + tp3c6 + tp3c7 + tp3c8 + tpmean3 + tpsprd3 + tp6c1 + tp6c2 + tp6c3 + tp6c4 + tp6c5 + tp6c6 + tp6c7 + tp6c8 + tpmean6 + tpsprd6 + tp_ACR + tp_ACR + tp_ALR + tp_ALR + PSurge4Ft + PSurge4Ft + PSurge5Ft + PSurge5Ft + PSurge6Ft + PSurge6Ft + Surge20Pct + Surge20Pct + PSurge7Ft + PSurge7Ft + PSurge8Ft + PSurge8Ft + PSurge9Ft + PSurge9Ft + PSurge10Ft + PSurge10Ft + Surge30Pct + Surge30Pct + PSurge11Ft + PSurge11Ft + PSurge12Ft + PSurge12Ft + PSurge13Ft + PSurge13Ft + Surge40Pct + Surge40Pct + PSurge14Ft + PSurge14Ft + PSurge15Ft + PSurge15Ft + PSurge16Ft + PSurge16Ft + Surge50Pct + Surge50Pct + PSurge17Ft + PSurge17Ft + PSurge18Ft + PSurge18Ft + PSurge19Ft + PSurge19Ft + Surge60Pct + Surge60Pct + PSurge20Ft + PSurge20Ft + PSurge2Ft + PSurge2Ft + PSurge21Ft + PSurge21Ft + PSurge22Ft + PSurge22Ft + PSurge23Ft + PSurge23Ft + Surge70Pct + Surge70Pct + PSurge24Ft + PSurge24Ft + PSurge25Ft + PSurge25Ft + Surge80Pct + Surge80Pct + Surge90Pct + Surge90Pct + PSurge3Ft + PSurge3Ft + SloshSurge + SloshSurge + Surge10Pct + tp_ecmwf + tp_FWR + tp_FWR + tp_HPC + tp_HPC + tp_KRF + tp_KRF + tp_MSR + tp_MSR + tp_ORN + tp_ORN + tp_PTR + tp_PTR + tp_RHA + tp_RHA + tp_RSA + tp_RSA + tp_STR + tp_STR + tp_TAR + tp_TAR + tp_TIR + tp_TIR + tp_TUA + tp_TUA + tpw + tsprd + ttot + turb + uwerranl + uwmean + uwsprd + uzfwc + uztwc + visc1 + visc2 + vmcc + vss + ww + vwerranl + vwmean + vwsprd + water_depth + wderranl + wgd + wom + wsc1 + wsc2 + wsc3 + wsc4 + wserranl + wsmean + wsp1 + wsp2 + wsp3 + wssprd + wx + zagl diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/hpcGuideNDFD.xml b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/hpcGuideNDFD.xml index 963841f792..a2d5d454fb 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/hpcGuideNDFD.xml +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/hpcGuideNDFD.xml @@ -1,4 +1,7 @@ + 302400 @@ -124,13 +127,13 @@ - wxType + wx Weather Weather 0.0 - 12.0 + 10.0 -99999.0 0 SFC diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/ruc130.xml b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/ruc130.xml index fe27b63219..0dd80bdcdc 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/ruc130.xml +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/ruc130.xml @@ -1,4 +1,7 @@ + 0 @@ -14,6 +17,12 @@ 36000 39600 43200 + 46800 + 50400 + 54000 + 57600 + 61200 + 64800 weasd diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject index ab8c87a563..087b58f697 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject @@ -2,9 +2,7 @@ com.raytheon.uf.common.dataplugin.gfe.config.ProjectionData com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation -com.raytheon.uf.common.dataplugin.gfe.db.objects.GridParmInfo com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID -com.raytheon.uf.common.dataplugin.gfe.db.objects.TimeConstraints com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData com.raytheon.uf.common.dataplugin.gfe.sample.SampleData diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridParmInfo.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridParmInfo.java index 01786c640c..e445e4b373 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridParmInfo.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/GridParmInfo.java @@ -28,10 +28,6 @@ import javax.measure.unit.NonSI; import javax.measure.unit.SI; import javax.measure.unit.Unit; import javax.measure.unit.UnitFormat; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; import com.raytheon.uf.common.dataplugin.gfe.discrete.DiscreteKey; @@ -53,6 +49,8 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * ------------ ---------- ----------- -------------------------- * 02/05/2008 chammack Separated static attributes from GFERecord * 02/27/2008 879 rbell Added constructors and equals(Object) + * 03/20/2013 #1774 randerso Removed unnecessary XML annotations, + * added isValid method to match A1 * * * @@ -60,7 +58,6 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * @version 1.0 */ -@XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize public class GridParmInfo implements Cloneable, ISerializableObject { private static final transient IUFStatusHandler statusHandler = UFStatus @@ -91,105 +88,51 @@ public class GridParmInfo implements Cloneable, ISerializableObject { } /** The parm id associated with this grid parm info */ - @XmlElement @DynamicSerializeElement private ParmID parmID; /** The grid location associated with this grid parm info */ - @XmlElement @DynamicSerializeElement private GridLocation gridLoc; /** The grid type */ - @XmlAttribute @DynamicSerializeElement private GridType gridType; /** The parameter descriptive name */ - @XmlAttribute @DynamicSerializeElement private String descriptiveName; /** The units associated with the parameter */ - @XmlAttribute @DynamicSerializeElement private String unitString; private Unit unitObject; /** The minimum allowed value */ - @XmlAttribute @DynamicSerializeElement private float minValue; /** The maximum allowed value */ - @XmlAttribute @DynamicSerializeElement private float maxValue; /** The precision of the value */ - @XmlAttribute @DynamicSerializeElement private int precision; /** Is value a rate parameter */ - @XmlAttribute @DynamicSerializeElement private boolean rateParm; /** Time Constraints */ - @XmlElement @DynamicSerializeElement private TimeConstraints timeConstraints; - @XmlAttribute @DynamicSerializeElement private boolean timeIndependentParm; - private void validCheck() { - if (!parmID.isValid()) { - throw new IllegalArgumentException( - "GridParmInfo.ParmID is not valid [" + parmID + ']'); - } - - if (timeConstraints == null) { - throw new IllegalArgumentException( - "GridParmInfo.TimeConstraints are null"); - } - - if (gridLoc == null) { - throw new IllegalArgumentException( - "GridParmInfo.GridLocation is null"); - } - - if (timeIndependentParm && timeConstraints.anyConstraints()) { - throw new IllegalArgumentException( - "GridParmInfo is invalid. There are time constraints " - + " for a time independent parm. Constraints: " - + timeConstraints); - } - - // units defined - if (unitString == null) { - throw new IllegalArgumentException( - "GridParmInfo.Units are not defined."); - } - - // max/min/precision checks - if (maxValue < minValue) { - throw new IllegalArgumentException( - "GridParmInfo is invalid. Max 5) { + sb.append("GridParmInfo is invalid. Precision out of limits. "); + sb.append(" Precision is: "); + sb.append(precision); + sb.append(". Must be betwwen -2 and 5\n"); + } + + this.errorMessage = sb.toString(); + if (errorMessage.isEmpty()) { + return true; + } else { + return false; + } + } + + /** + * @return true if valid + */ + public boolean isValid() { + return errorMessage.isEmpty(); + } + /** * @return the gridType */ diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/TimeConstraints.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/TimeConstraints.java index c7f6f15cf7..399c0b1f66 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/TimeConstraints.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/TimeConstraints.java @@ -23,14 +23,15 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; - +import com.raytheon.uf.common.dataplugin.gfe.serialize.TimeConstraintsAdapter; import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeTypeAdapter; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.common.time.util.TimeUtil; /** * A TimeConstraint represents a parm's quantum and time block alignments. @@ -40,6 +41,8 @@ import com.raytheon.uf.common.time.TimeRange; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 2/19/2008 chammack Ported from AWIPS I + * 03/20/2013 #1774 randerso Added isValid method, use TimeUtil constants, + * added serialization adapter, removed setters. * * * @@ -47,26 +50,22 @@ import com.raytheon.uf.common.time.TimeRange; * @version 1.0 */ -@XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize +@DynamicSerializeTypeAdapter(factory = TimeConstraintsAdapter.class) public class TimeConstraints implements ISerializableObject { - public static final int HOUR = 3600; + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(TimeConstraints.class); - public static final int DAY = 24 * HOUR; - - @XmlAttribute @DynamicSerializeElement private int duration; - @XmlAttribute @DynamicSerializeElement private int repeatInterval; - @XmlAttribute @DynamicSerializeElement private int startTime; - private static final int MilliSecInDay = (DAY * 1000); + boolean valid; /** * Default Constructor @@ -75,23 +74,35 @@ public class TimeConstraints implements ISerializableObject { duration = 0; repeatInterval = 0; startTime = 0; + valid = false; } public TimeConstraints(int duration, int repeatInterval, int startTime) { - - if (duration == 0 && repeatInterval == 0 && startTime == 0) { - // all zeroes is OK - } else if (repeatInterval <= 0 || repeatInterval > DAY - || DAY % repeatInterval != 0 || repeatInterval < duration - || startTime < 0 || startTime > DAY || duration < 0 - || duration > DAY) { - throw new IllegalArgumentException( - "Bad init values for timeConstraints"); - } - this.duration = duration; this.repeatInterval = repeatInterval; this.startTime = startTime; + + if (this.duration == 0 && this.repeatInterval == 0 + && this.startTime == 0) { + valid = true; + } else { + if (repeatInterval <= 0 + || repeatInterval > TimeUtil.SECONDS_PER_DAY + || TimeUtil.SECONDS_PER_DAY % repeatInterval != 0 + || repeatInterval < duration || startTime < 0 + || startTime > TimeUtil.SECONDS_PER_DAY || duration < 0 + || duration > TimeUtil.SECONDS_PER_DAY) { + statusHandler.warn("Bad init values for TimeConstraints: " + + this); + valid = false; + this.duration = 0; + this.repeatInterval = 0; + this.startTime = 0; + } else { + valid = true; + } + } + } /** @@ -103,14 +114,16 @@ public class TimeConstraints implements ISerializableObject { * the time that the range should contain */ public TimeRange constraintTime(Date absTime) { - - if (!anyConstraints()) { + if (!valid) { + return new TimeRange(); + } else if (!anyConstraints()) { return TimeRange.allTimes(); } - long secSinceMidnight = absTime.getTime() % MilliSecInDay; + long secSinceMidnight = absTime.getTime() % TimeUtil.MILLIS_PER_DAY; - long midnight = (absTime.getTime() / MilliSecInDay) * MilliSecInDay; + long midnight = (absTime.getTime() / TimeUtil.MILLIS_PER_DAY) + * TimeUtil.MILLIS_PER_DAY; int tStart = startTime - repeatInterval; @@ -119,12 +132,12 @@ public class TimeConstraints implements ISerializableObject { tStart -= repeatInterval; // keep going until below 0 } - while (tStart < DAY) { + while (tStart < TimeUtil.SECONDS_PER_DAY) { int tEnd = tStart + duration; - if ((tStart * 1000) <= secSinceMidnight - && secSinceMidnight < (tEnd * 1000)) { - return new TimeRange(midnight + 1000 * tStart, midnight + 1000 - * tEnd); + if ((tStart * TimeUtil.MILLIS_PER_SECOND) <= secSinceMidnight + && secSinceMidnight < (tEnd * TimeUtil.MILLIS_PER_SECOND)) { + return new TimeRange(midnight + TimeUtil.MILLIS_PER_SECOND + * tStart, midnight + TimeUtil.MILLIS_PER_SECOND * tEnd); } tStart += repeatInterval; } @@ -150,17 +163,6 @@ public class TimeConstraints implements ISerializableObject { return duration; } - /** - * @param duration - * the duration to set - */ - public void setDuration(int duration) { - if (duration < 0 || duration > DAY) { - throw new IllegalArgumentException("Bad duration"); - } - this.duration = duration; - } - /** * @return the repeatInterval */ @@ -168,20 +170,6 @@ public class TimeConstraints implements ISerializableObject { return repeatInterval; } - /** - * @param repeatInterval - * the repeatInterval to set - */ - public void setRepeatInterval(int repeatInterval) { - if (repeatInterval < 0 || repeatInterval > DAY - || (repeatInterval != 0 && DAY % repeatInterval != 0) - || repeatInterval < duration) { - throw new IllegalArgumentException("Bad repeatInterval"); - } - - this.repeatInterval = repeatInterval; - } - /** * @return the startTime */ @@ -190,14 +178,10 @@ public class TimeConstraints implements ISerializableObject { } /** - * @param startTime - * the startTime to set + * @return true if valid */ - public void setStartTime(int startTime) { - if (startTime < 0 || startTime > DAY) { - throw new IllegalArgumentException("Bad startTime"); - } - this.startTime = startTime; + public boolean isValid() { + return valid; } /* @@ -213,7 +197,7 @@ public class TimeConstraints implements ISerializableObject { TimeConstraints rhs = (TimeConstraints) obj; - return (duration == rhs.duration + return (valid == rhs.valid && duration == rhs.duration && repeatInterval == rhs.repeatInterval && startTime == rhs.startTime); } @@ -232,7 +216,8 @@ public class TimeConstraints implements ISerializableObject { // get the constraint times for the given time range TimeRange tr1 = constraintTime(tr.getStart()); - TimeRange tr2 = constraintTime(new Date(tr.getEnd().getTime() - 1000)); + TimeRange tr2 = constraintTime(new Date(tr.getEnd().getTime() + - TimeUtil.MILLIS_PER_SECOND)); // checking if (!tr1.isValid() || !tr2.isValid()) { @@ -255,7 +240,7 @@ public class TimeConstraints implements ISerializableObject { * @return possible time ranges */ public TimeRange[] constraintTimes(final TimeRange timeRange) { - if (!timeRange.isValid()) { + if (!valid || !timeRange.isValid()) { return new TimeRange[0]; // return empty sequence } else if (!anyConstraints()) { TimeRange maxTR = TimeRange.allTimes(); @@ -266,7 +251,8 @@ public class TimeConstraints implements ISerializableObject { // is beyond the time range given List sbs = new ArrayList(); // returned value TimeRange tr = firstSB(timeRange.getStart()); - while (timeRange.getEnd().getTime() + (duration * 1000) > tr.getEnd() + while (timeRange.getEnd().getTime() + + (duration * TimeUtil.MILLIS_PER_SECOND) > tr.getEnd() .getTime()) { if (tr.overlaps(timeRange)) { sbs.add(tr); @@ -286,8 +272,9 @@ public class TimeConstraints implements ISerializableObject { */ private TimeRange nextSB(final TimeRange timeRange) { long nextStart = timeRange.getStart().getTime() - + (repeatInterval * 1000); - long nextEnd = timeRange.getEnd().getTime() + (repeatInterval * 1000); + + (repeatInterval * TimeUtil.MILLIS_PER_SECOND); + long nextEnd = timeRange.getEnd().getTime() + + (repeatInterval * TimeUtil.MILLIS_PER_SECOND); return new TimeRange(nextStart, nextEnd); } @@ -300,15 +287,17 @@ public class TimeConstraints implements ISerializableObject { * @return first time constraint */ private TimeRange firstSB(Date searchTime) { - long midnightMilliSeconds = (searchTime.getTime() / MilliSecInDay) - * MilliSecInDay; + long midnightMilliSeconds = (searchTime.getTime() / TimeUtil.MILLIS_PER_DAY) + * TimeUtil.MILLIS_PER_DAY; - long ystdMidnight = midnightMilliSeconds - MilliSecInDay; // to catch - // overlap + // to catch overlap + long ystdMidnight = midnightMilliSeconds - TimeUtil.MILLIS_PER_DAY; // calculate the first time range - Date startT = new Date(ystdMidnight + (startTime * 1000)); - Date endT = new Date(startT.getTime() + (duration * 1000)); + Date startT = new Date(ystdMidnight + + (startTime * TimeUtil.MILLIS_PER_SECOND)); + Date endT = new Date(startT.getTime() + + (duration * TimeUtil.MILLIS_PER_SECOND)); return new TimeRange(startT, endT); } @@ -319,11 +308,21 @@ public class TimeConstraints implements ISerializableObject { */ @Override public String toString() { - if (!anyConstraints()) { + if (!valid) { + return ""; + } else if (!anyConstraints()) { return ""; } else { - return "[s=" + startTime / 3600 + "h" + ",i=" + repeatInterval - / 3600 + "h" + ",d=" + duration / 3600 + "h]"; + StringBuilder sb = new StringBuilder(); + sb.append("[s="); + sb.append(startTime / TimeUtil.SECONDS_PER_HOUR); + sb.append("h, i="); + sb.append(repeatInterval / TimeUtil.SECONDS_PER_HOUR); + sb.append("h, d="); + sb.append(duration / TimeUtil.SECONDS_PER_HOUR); + sb.append("h]"); + + return sb.toString(); } } @@ -338,7 +337,7 @@ public class TimeConstraints implements ISerializableObject { */ public TimeRange expandTRToQuantum(final TimeRange timeRange) { - if (!timeRange.isValid()) { + if (!valid || !timeRange.isValid()) { return new TimeRange(); } @@ -353,7 +352,7 @@ public class TimeConstraints implements ISerializableObject { // <=) TimeRange tr1 = constraintTime(timeRange.getStart()); TimeRange tr2 = constraintTime(new Date(timeRange.getEnd() - .getTime() - 1000)); + .getTime() - TimeUtil.MILLIS_PER_SECOND)); if (!tr1.isValid() || !tr2.isValid()) { return new TimeRange(); } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/serialize/TimeConstraintsAdapter.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/serialize/TimeConstraintsAdapter.java new file mode 100644 index 0000000000..1b90e0b816 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/serialize/TimeConstraintsAdapter.java @@ -0,0 +1,62 @@ +/** + * 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.serialize; + +import com.raytheon.uf.common.dataplugin.gfe.db.objects.TimeConstraints; +import com.raytheon.uf.common.serialization.IDeserializationContext; +import com.raytheon.uf.common.serialization.ISerializationContext; +import com.raytheon.uf.common.serialization.ISerializationTypeAdapter; +import com.raytheon.uf.common.serialization.SerializationException; + +/** + * Thrift serialization adapter for TimeConstraints + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Mar 11, 2013     #1774  randerso    Initial creation
+ * 
+ * 
+ * + * @author randerso + * @version 1.0 + */ + +public class TimeConstraintsAdapter implements + ISerializationTypeAdapter { + + @Override + public void serialize(ISerializationContext serializer, + TimeConstraints object) throws SerializationException { + serializer.writeI32(object.getDuration()); + serializer.writeI32(object.getRepeatInterval()); + serializer.writeI32(object.getStartTime()); + } + + @Override + public TimeConstraints deserialize(IDeserializationContext deserializer) + throws SerializationException { + return new TimeConstraints(deserializer.readI32(), + deserializer.readI32(), deserializer.readI32()); + } +} diff --git a/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/TimeRange.java b/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/TimeRange.java index ae848536fc..5da7b72323 100644 --- a/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/TimeRange.java +++ b/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/TimeRange.java @@ -40,6 +40,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeTypeAdapter; import com.raytheon.uf.common.time.adapter.TimeRangeTypeAdapter; +import com.raytheon.uf.common.time.util.TimeUtil; /** * @@ -51,6 +52,8 @@ import com.raytheon.uf.common.time.adapter.TimeRangeTypeAdapter; * ------------ ---------- ----------- -------------------------- * Jun 19, 2007 chammack Port from AWIPS Common * 02/27/2008 879 rbell Added compareTo(TimeRange) + * 03/20/2013 #1774 randerso Changed toString to display times even when + * duration is 0, use TimeUtil constants. * * * @@ -100,15 +103,10 @@ import com.raytheon.uf.common.time.adapter.TimeRangeTypeAdapter; public class TimeRange implements Serializable, Comparable, ISerializableObject, Cloneable { - private static final int SEC_PER_MIN = 60; - - private static final int SEC_PER_HOUR = 3600; - - private static final long SEC_PER_DAY = SEC_PER_HOUR * 24; - // This constant gives a value similar to GFEs AbsTime.MaxFutureValue() // and doesn't break Calendar like Long.MAX_VALUE does - private static final long MAX_TIME = (long) Integer.MAX_VALUE * 1000; + private static final long MAX_TIME = Integer.MAX_VALUE + * TimeUtil.MILLIS_PER_SECOND; /** * @@ -245,15 +243,15 @@ public class TimeRange implements Serializable, Comparable, */ public String durationAsPrettyString() { long dur = getDuration(); - long days = dur / SEC_PER_DAY; + long days = dur / TimeUtil.SECONDS_PER_DAY; - dur -= days * SEC_PER_DAY; - long hours = dur / SEC_PER_HOUR; + dur -= days * TimeUtil.SECONDS_PER_DAY; + long hours = dur / TimeUtil.SECONDS_PER_HOUR; - dur -= hours * SEC_PER_HOUR; - long min = dur / SEC_PER_MIN; + dur -= hours * TimeUtil.SECONDS_PER_HOUR; + long min = dur / TimeUtil.SECONDS_PER_MINUTE; - long sec = dur - min * SEC_PER_MIN; + long sec = dur - min * TimeUtil.SECONDS_PER_MINUTE; StringBuilder sb = new StringBuilder(); @@ -534,17 +532,20 @@ public class TimeRange implements Serializable, Comparable, */ @Override public String toString() { - if (isValid()) { - final DateFormat GMTFormat = new SimpleDateFormat( - "MMM dd yy HH:mm:ss zzz"); - GMTFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + final DateFormat GMTFormat = new SimpleDateFormat( + "MMM dd yy HH:mm:ss zzz"); + GMTFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - return "(" + GMTFormat.format(getStart()) + ", " - + GMTFormat.format(getEnd()) + ")"; - } else { - return "(Invalid)"; + StringBuilder sb = new StringBuilder(); + sb.append("("); + sb.append(GMTFormat.format(getStart())); + sb.append(", "); + sb.append(GMTFormat.format(getEnd())); + if (!isValid()) { + sb.append(", Invalid"); } - + sb.append(")"); + return sb.toString(); } /* diff --git a/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java b/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java index 11e45ec039..e2b6dec413 100644 --- a/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java +++ b/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java @@ -48,7 +48,8 @@ import com.raytheon.uf.common.time.domain.api.ITimePoint; * Jan 22, 2013 1484 mpduff Add HOURS_PER_WEEK. * Jan 22, 2013 1519 djohnson Add MINUTES_PER_DAY. * Feb 26, 2013 1597 randerso Add SECONDS_PER_HOUR. - * + * Mar 20, 2013 1774 randerso Add SECONDS_PER_DAY, changed SECONDS_PER_HOUR to int. + * * * * @author njensen @@ -97,11 +98,13 @@ public final class TimeUtil { public static final int MINUTES_PER_HOUR = 60; - public static final long SECONDS_PER_HOUR = SECONDS_PER_MINUTE + public static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR; public static final int HOURS_PER_DAY = 24; + public static final int SECONDS_PER_DAY = HOURS_PER_DAY * SECONDS_PER_HOUR; + public static final int HOURS_PER_HALF_DAY = HOURS_PER_DAY / 2; public static final int HOURS_PER_QUARTER_DAY = HOURS_PER_HALF_DAY / 2; diff --git a/pythonPackages/dynamicserialize/adapters/TimeConstraintsAdapter.py b/pythonPackages/dynamicserialize/adapters/TimeConstraintsAdapter.py new file mode 100644 index 0000000000..74b1a5cb82 --- /dev/null +++ b/pythonPackages/dynamicserialize/adapters/TimeConstraintsAdapter.py @@ -0,0 +1,46 @@ +## +# 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. +## + + +# +# Adapter for com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 03/20/13 #1774 randerso Initial Creation. +# +# +# + +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.db.objects import TimeConstraints + +ClassAdapter = 'com.raytheon.uf.common.dataplugin.gfe.db.objects.TimeConstraints' + +def serialize(context, timeConstraints): + context.writeI32(timeConstraints.getDuration()); + context.writeI32(timeConstraints.getRepeatInterval()); + context.writeI32(timeConstraints.getStartTime()); + +def deserialize(context): + result = TimeConstraints(context.readI32(), context.readI32(), context.readI32()) + return result \ No newline at end of file diff --git a/pythonPackages/dynamicserialize/adapters/__init__.py b/pythonPackages/dynamicserialize/adapters/__init__.py index 1c9fc9ebe9..69b558e738 100644 --- a/pythonPackages/dynamicserialize/adapters/__init__.py +++ b/pythonPackages/dynamicserialize/adapters/__init__.py @@ -28,6 +28,7 @@ # Date Ticket# Engineer Description # ------------ ---------- ----------- -------------------------- # 08/31/10 njensen Initial Creation. +# 03/20/13 #1774 randerso Added TimeConstraintsAdapter # # # @@ -50,8 +51,9 @@ __all__ = [ 'TimestampAdapter', 'EnumSetAdapter', 'FloatBufferAdapter', - 'ByteBufferAdapter' -# 'GridDataHistoryAdapter' + 'ByteBufferAdapter', + 'TimeConstraintsAdapter', +# 'GridDataHistoryAdapter', ] classAdapterRegistry = {} diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/TimeConstraints.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/TimeConstraints.py index c2ce0ea1ed..ba5756559e 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/TimeConstraints.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/TimeConstraints.py @@ -19,8 +19,11 @@ ## # File auto-generated against equivalent DynamicSerialize Java class +# +# 03/20/2013 #1774 randerso Removed setters, added isValid. +import logging HOUR = 3600; DAY = 24 * HOUR; @@ -31,13 +34,24 @@ class TimeConstraints(object): duration = int(duration) repeatInterval = int(repeatInterval) startTime = int(startTime) - - if duration != 0 or repeatInterval != 0 or startTime != 0: - if (repeatInterval <= 0 or repeatInterval > DAY) or \ - (DAY % repeatInterval != 0 or repeatInterval < duration) or \ - (startTime < 0 or startTime > DAY) or \ - (duration < 0 or duration > DAY): - raise ValueError("Bad init values for TimeConstraints.") + + self.valid = False; + if duration == 0 and repeatInterval == 0 and startTime == 0: + self.valid = True; + else: + if repeatInterval <= 0 or repeatInterval > DAY \ + or DAY % repeatInterval != 0 \ + or repeatInterval < duration \ + or startTime < 0 or startTime > DAY \ + or duration < 0 or duration > DAY: + + logging.warning("Bad init values for TimeConstraints: ", self); + self.valid = False; + duration = 0; + repeatInterval = 0; + startTime = 0; + else: + self.valid = True; self.duration = duration self.repeatInterval = repeatInterval @@ -47,12 +61,14 @@ class TimeConstraints(object): return self.__repr__() def __repr__(self): - if not self.anyConstraints(): + if not self.isValid(): + return "" + elif not self.anyConstraints(): return "" else: - return "[s=" + str(self.startTime / HOUR) + "h,i=" + \ - str(self.repeatInterval / HOUR) + "h,d=" + \ - str(self.duration / 3600) + "h]" + return "[s=" + str(self.startTime / HOUR) + "h, i=" + \ + str(self.repeatInterval / HOUR) + "h, d=" + \ + str(self.duration / HOUR) + "h]" def __eq__(self, other): if not isinstance(other, TimeConstraints): @@ -72,29 +88,13 @@ class TimeConstraints(object): return (self.duration != 0) def isValid(self): - if self.duration != 0 or self.repeatInterval != 0 or self.startTime != 0: - if (self.repeatInterval <= 0 or self.repeatInterval > DAY) or \ - (DAY % self.repeatInterval != 0 or self.repeatInterval < self.duration) or \ - (self.startTime < 0 or self.startTime > DAY) or \ - (self.duration < 0 or self.duration > DAY): - return False - return True + return self.valid def getDuration(self): return self.duration - def setDuration(self, duration): - self.duration = duration - def getRepeatInterval(self): return self.repeatInterval - def setRepeatInterval(self, repeatInterval): - self.repeatInterval = repeatInterval - def getStartTime(self): return self.startTime - - def setStartTime(self, startTime): - self.startTime = startTime -