diff --git a/cave/build/static/common/cave/etc/alertViz/configurations/Default.xml b/cave/build/static/common/cave/etc/alertViz/configurations/Default.xml index 4131bcff53..59e7066d04 100644 --- a/cave/build/static/common/cave/etc/alertViz/configurations/Default.xml +++ b/cave/build/static/common/cave/etc/alertViz/configurations/Default.xml @@ -1,4 +1,11 @@ + @@ -273,11 +280,11 @@ - + - - - + + + diff --git a/cave/build/static/common/cave/etc/gfe/userPython/utilities/SmartScript.py b/cave/build/static/common/cave/etc/gfe/userPython/utilities/SmartScript.py index cd8114b1d8..9cd6a4cd40 100644 --- a/cave/build/static/common/cave/etc/gfe/userPython/utilities/SmartScript.py +++ b/cave/build/static/common/cave/etc/gfe/userPython/utilities/SmartScript.py @@ -890,21 +890,15 @@ class SmartScript(BaseTool.BaseTool): else: timeRange = timeRange.toJavaObj() - from com.raytheon.viz.gfe.smarttool.script import SmartToolRequest, SmartToolFinishedListener, SmartToolJob from com.raytheon.viz.gfe.smarttool import SmartUtil - req = SmartUtil.callFromSmartScript(self.__dataMgr, toolName, elementName, editArea, + result = SmartUtil.callFromSmartScript(self.__dataMgr, toolName, elementName, editArea, timeRange, varDict, emptyEditAreaFlag, JUtil.pylistToJavaStringList(passErrors), missingDataMode, parm) - listener = SmartToolFinishedListener() - req.setListener(listener) - SmartToolJob.enqueue(self.__dataMgr, req) - while not listener.isDone(): - time.sleep(0.2) - if listener.getResult(): - raise Exceptions.EditActionError(errorType="Error", errorInfo=str(listener.getResult())) + if result: + raise Exceptions.EditActionError(errorType="Error", errorInfo=str(result)) return None def callProcedure(self, name, editArea=None, timeRange=None, varDict=None, @@ -919,20 +913,15 @@ class SmartScript(BaseTool.BaseTool): else: timeRange = timeRange.toJavaObj() - from com.raytheon.viz.gfe.procedures import ProcedureUtil, ProcedureRequest, ProcedureFinishedListener,ProcedureJob + from com.raytheon.viz.gfe.procedures import ProcedureUtil if varDict: varDict = str(varDict) - listener = ProcedureFinishedListener() - req = ProcedureUtil.callFromSmartScript(self.__dataMgr, name, editArea, timeRange, varDict) - req.setListener(listener) - - ProcedureJob.enqueue(self.__dataMgr, req) - while not listener.isDone(): - time.sleep(0.2) + + result = ProcedureUtil.callFromSmartScript(self.__dataMgr, name, editArea, timeRange, varDict) # callSmartTool raises the exception put here it is returned. - if listener.getResult(): - return Exceptions.EditActionError(errorType="Error", errorInfo=str(listener.getResult())) + if result: + return Exceptions.EditActionError(errorType="Error", errorInfo=str(result)) return None diff --git a/cave/build/static/common/cave/etc/menus/ncepHydro/cpc/baseCPC.xml b/cave/build/static/common/cave/etc/menus/ncepHydro/cpc/baseCPC.xml index 0b83352ae3..1e0eb6cc24 100644 --- a/cave/build/static/common/cave/etc/menus/ncepHydro/cpc/baseCPC.xml +++ b/cave/build/static/common/cave/etc/menus/ncepHydro/cpc/baseCPC.xml @@ -30,22 +30,41 @@ /redbook/%/PMNV88/% + + titleText="------ 3-7 Day Hazard Outlook ------" id="threeTo7DayHazardOutlook"/> - /redbook/%/PEIY50/% - + menuText="3-7 day Precipitation Fcst" id="threeTo7DayPrecipFcst"> + /redbook/%/PEIY97/% + - - /redbook/%/PTIY98/% - + + /redbook/%/PYIY97/% + - - /redbook/%/PYIY88/% - + + /redbook/%/PTIY97/% + + + + + + /redbook/%/PEIY96/% + + + + /redbook/%/PYIY96/% + + + + /redbook/%/PTIY96/% + + /redbook/%/PTAT90/% diff --git a/cave/build/static/common/cave/etc/redbook/redbookMapping.xml b/cave/build/static/common/cave/etc/redbook/redbookMapping.xml index 5ec936b5fd..8e6cf38330 100644 --- a/cave/build/static/common/cave/etc/redbook/redbookMapping.xml +++ b/cave/build/static/common/cave/etc/redbook/redbookMapping.xml @@ -163,11 +163,18 @@ PPKA01 gfs 00hr MSLP * - PEIK98 Day 3 QPF - Time Proj 60-72Hrs + + PEIY96 + 8-14 Day Precip Hazards + + + PEIY97 + 3-7 Day Precip Hazards + PLQI51 redbook graphic @@ -175,7 +182,7 @@ PEIY50 3-10 Day Threat Assess Precip - + PYMA70 700mb UA plot @@ -243,6 +250,14 @@ PTNR98 6-10 Day Maximum Heat Index Outlook + + + PTIY96 + 8-14 Temp/Wind Hazards + + + PTIY97 + 3-7 Day Temp/Wind Hazards PNWA68 @@ -264,7 +279,6 @@ PYAA98 Sfc Frontal Analysis - PTAT00 8-14 Day Heat Index >=95F @@ -277,13 +291,18 @@ PPAM89 96Hr North Atlantic Fronts/Pressure/Winds FCST - PYAA89 N Atlantic Surface Anal - - + + PYIY96 + 8-14 Day Soil/Wildfire Hazards + + + PYIY97 + 3-7 Day Soil/Wildfire Hazards + PSBD25 Day 3 Prob .25+" Ice @@ -342,7 +361,6 @@ PYMA25 250mb UA plot - POWA31 redbook graphic @@ -358,8 +376,7 @@ PEIW01,PEIW02,PEIW03,PEIW04,PEIW05,PEIW06,PEIW07,PEIW08,PEIW09,PEIW10,PEIW11,PEIW12,PEIW13 90 Day Seasonal Precip Outlook - - + PTIW01,PTIW02,PTIW03,PTIW04,PTIW05,PTIW06,PTIW07,PTIW08,PTIW09,PTIW10,PTIW11,PTIW12,PTIW13 90 Day Seasonal Temp Outlook diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/notification/jobs/NotificationManagerJob.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/notification/jobs/NotificationManagerJob.java index e97354137b..34ebe129a5 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/notification/jobs/NotificationManagerJob.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/notification/jobs/NotificationManagerJob.java @@ -21,7 +21,6 @@ package com.raytheon.uf.viz.core.notification.jobs; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Timer; @@ -119,23 +118,30 @@ public class NotificationManagerJob implements ExceptionListener, IDisposable { */ @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } ListenerKey other = (ListenerKey) obj; if (queryString == null) { - if (other.queryString != null) + if (other.queryString != null) { return false; - } else if (!queryString.equals(other.queryString)) + } + } else if (!queryString.equals(other.queryString)) { return false; + } if (topic == null) { - if (other.topic != null) + if (other.topic != null) { return false; - } else if (!topic.equals(other.topic)) + } + } else if (!topic.equals(other.topic)) { return false; + } return true; } } @@ -529,13 +535,13 @@ public class NotificationManagerJob implements ExceptionListener, IDisposable { sendToObserver(obs, msg); } - Iterator iterator = jobWrappers.values().iterator(); - while (iterator.hasNext()) { - JobWrapper wrapper = iterator.next(); - if (!wrapper.isEmpty() && wrapper.getState() != Job.RUNNING) { - wrapper.schedule(); - } - } + // Iterator iterator = jobWrappers.values().iterator(); + // while (iterator.hasNext()) { + // JobWrapper wrapper = iterator.next(); + // if (!wrapper.isEmpty() && wrapper.getState() != Job.RUNNING) { + // wrapper.schedule(); + // } + // } } public synchronized void addObserver(INotificationObserver obs) { @@ -656,6 +662,7 @@ public class NotificationManagerJob implements ExceptionListener, IDisposable { lastErrorPrintTime = System.currentTimeMillis(); } } + this.schedule(); } /** diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/TimeHeightDlg.java b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/TimeHeightDlg.java index e8ce68f5cd..00525b6dfe 100644 --- a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/TimeHeightDlg.java +++ b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/TimeHeightDlg.java @@ -20,6 +20,7 @@ package com.raytheon.uf.viz.monitor.scan.commondialogs; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.LinkedHashMap; import java.util.TreeMap; @@ -50,6 +51,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Mar 10, 2010 lvenable Initial creation + * Dec 23, 2011 13608 mgamazay Updated populateIdentCombo so the drop down menu + * shows the current feature ident instead of being blank. * * * @@ -291,11 +294,19 @@ public class TimeHeightDlg extends CaveSWTDialog implements ITimeHeightInfo { * Populate the ident combo control. */ private void populateIdentCombo() { - for (String str : identArray) { - identCbo.add(str); + + if ( Arrays.asList(identArray).contains(ident) ) { + for (String str : identArray) { + identCbo.add(str); + } + identCbo.select(identCbo.indexOf(ident)); } - - identCbo.select(identCbo.indexOf(ident)); + + else { + identCbo.add(ident); + identCbo.select(identCbo.indexOf(ident)); + } + } /** diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/TimeHeightMsgBox.java b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/TimeHeightMsgBox.java index 5e720a93b3..9a26bbc10f 100644 --- a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/TimeHeightMsgBox.java +++ b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/TimeHeightMsgBox.java @@ -43,6 +43,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 25, 2011 mpduff Initial creation + * Dec 23, 2011 13608 mgamazay Added initialization of ident to the constructor * * * @@ -65,6 +66,7 @@ public class TimeHeightMsgBox extends CaveSWTDialog implements protected TimeHeightMsgBox(Shell parentShell, String ident) { super(parentShell, SWT.DIALOG_TRIM | SWT.MODELESS); setText("Unavailable T-H Trend"); + this.ident = ident; } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java index 0bd77847ea..7fa89145fa 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java @@ -506,6 +506,7 @@ public class DataManager { private void dispose() { selectTimeRangeManager.dispose(); refManager.dispose(); + parmManager.dispose(); autoSaveJob.dispose(); autoSaveJob = null; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/IParmManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/IParmManager.java index 39f0a1a9be..5cfcbef830 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/IParmManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/IParmManager.java @@ -27,6 +27,7 @@ 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.slice.IGridSlice; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.viz.core.jobs.JobPool; import com.raytheon.viz.gfe.GFEOperationFailedException; import com.raytheon.viz.gfe.core.msgs.IAvailableSourcesChangedListener; import com.raytheon.viz.gfe.core.msgs.IDisplayedParmListChangedListener; @@ -567,4 +568,6 @@ public interface IParmManager extends IParmInventoryChangedListener, * @return */ public ParmID fromExpression(String parmName); + + public JobPool getNotificationPool(); } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISCParmInitJob.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISCParmInitJob.java index 56e886bc82..e0cbe2d7fa 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISCParmInitJob.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISCParmInitJob.java @@ -69,12 +69,13 @@ public class ISCParmInitJob extends Job { protected IStatus run(IProgressMonitor monitor) { IISCDataAccess iscAccess = dataMgr.getIscDataAccess(); for (Parm parm : parms) { - // if (parm != null) { - iscAccess.getISCParm(parm); - // } + if (!monitor.isCanceled()) { + iscAccess.getISCParm(parm); + } else { + return Status.CANCEL_STATUS; + } } return Status.OK_STATUS; } - } 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 7a0dd90274..afdffed569 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 @@ -34,6 +34,8 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.eclipse.core.runtime.ListenerList; + 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; @@ -53,6 +55,7 @@ import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.TimeRange; import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.common.util.RWLArrayList; +import com.raytheon.uf.viz.core.jobs.JobPool; import com.raytheon.viz.core.mode.CAVEMode; import com.raytheon.viz.gfe.Activator; import com.raytheon.viz.gfe.GFEServerException; @@ -71,7 +74,7 @@ import com.raytheon.viz.gfe.core.msgs.Message; import com.raytheon.viz.gfe.core.msgs.ShowISCGridsMsg; import com.raytheon.viz.gfe.core.parm.ABVParmID; import com.raytheon.viz.gfe.core.parm.Parm; -import com.raytheon.viz.gfe.core.parm.VCModule; +import com.raytheon.viz.gfe.core.parm.vcparm.VCModule; /** * Implements common parm manager functionality shared between concrete and mock @@ -90,6 +93,8 @@ import com.raytheon.viz.gfe.core.parm.VCModule; */ public abstract class AbstractParmManager implements IParmManager { + private static final int NOTIFICATION_THREADS = 4; + protected class ParmIDVis { private ParmID pid; @@ -196,17 +201,17 @@ public abstract class AbstractParmManager implements IParmManager { // virtual parm definitions (modulename = key) protected List vcModules; - protected List availableSourcesListeners; + protected ListenerList availableSourcesListeners; - protected List displayedParmListListeners; + protected ListenerList displayedParmListListeners; - protected List newModelListeners; + protected ListenerList newModelListeners; - protected List parmIdChangedListeners; + protected ListenerList parmIdChangedListeners; - protected List parmListChangedListeners; + protected ListenerList parmListChangedListeners; - protected List systemTimeRangeChangedListeners; + protected ListenerList systemTimeRangeChangedListeners; protected TimeRange systemTimeRange; @@ -230,15 +235,19 @@ public abstract class AbstractParmManager implements IParmManager { private AbstractGFENotificationObserver siteActivationListener; + private ISCParmInitJob iscInit; + + private JobPool notificationPool; + protected AbstractParmManager(final DataManager dataManager) { this.dataManager = dataManager; this.parms = new RWLArrayList(); - this.displayedParmListListeners = new ArrayList(); - this.parmListChangedListeners = new ArrayList(); - this.systemTimeRangeChangedListeners = new ArrayList(); - this.availableSourcesListeners = new ArrayList(); - this.newModelListeners = new ArrayList(); - this.parmIdChangedListeners = new ArrayList(); + this.displayedParmListListeners = new ListenerList(); + this.parmListChangedListeners = new ListenerList(); + this.systemTimeRangeChangedListeners = new ListenerList(); + this.availableSourcesListeners = new ListenerList(); + this.newModelListeners = new ListenerList(); + this.parmIdChangedListeners = new ListenerList(); // Get virtual parm definitions vcModules = initVirtualCalcParmDefinitions(); @@ -364,6 +373,9 @@ public abstract class AbstractParmManager implements IParmManager { dataManager.getNotificationRouter().addObserver( this.siteActivationListener); + notificationPool = new JobPool("Parm Manager notification job", + NOTIFICATION_THREADS, true); + } /* @@ -384,6 +396,16 @@ public abstract class AbstractParmManager implements IParmManager { dataManager.getNotificationRouter().removeObserver( this.siteActivationListener); + + for (VCModule module : vcModules) { + module.dispose(); + } + + if (iscInit != null) { + iscInit.cancel(); + } + + notificationPool.cancel(); } protected DatabaseID decodeDbString(final String string) { @@ -1126,8 +1148,10 @@ public abstract class AbstractParmManager implements IParmManager { } setParms(addParms, deletions); - ISCParmInitJob iscInit = new ISCParmInitJob(dataManager, - getDisplayedParms()); + if (iscInit != null) { + iscInit.cancel(); + } + iscInit = new ISCParmInitJob(dataManager, getDisplayedParms()); iscInit.schedule(); return; @@ -1390,10 +1414,20 @@ public abstract class AbstractParmManager implements IParmManager { * @param deletes * parms that were deleted */ - protected void fireDisplayedParmListChanged(Parm[] parms, Parm[] adds, - Parm[] deletes) { - for (IDisplayedParmListChangedListener listener : this.displayedParmListListeners) { - listener.displayedParmListChanged(parms, deletes, adds); + protected void fireDisplayedParmListChanged(final Parm[] parms, + final Parm[] adds, final Parm[] deletes) { + for (Object listener : this.displayedParmListListeners.getListeners()) { + final IDisplayedParmListChangedListener casted = (IDisplayedParmListChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.displayedParmListChanged(parms, deletes, adds); + } + }; + + notificationPool.schedule(notTask); } } @@ -1405,9 +1439,18 @@ public abstract class AbstractParmManager implements IParmManager { * @param newParmId * The new ParmID associated with parm. */ - protected void fireParmIDChanged(Parm parm, ParmID newParmId) { - for (IParmIDChangedListener listener : this.parmIdChangedListeners) { - listener.parmIDChanged(parm, newParmId); + protected void fireParmIDChanged(final Parm parm, final ParmID newParmId) { + for (Object listener : this.parmIdChangedListeners.getListeners()) { + final IParmIDChangedListener casted = (IParmIDChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.parmIDChanged(parm, newParmId); + } + }; + notificationPool.schedule(notTask); } } @@ -1421,9 +1464,19 @@ public abstract class AbstractParmManager implements IParmManager { * @param deletes * parms that were deleted */ - protected void fireParmListChanged(Parm[] parms, Parm[] adds, Parm[] deletes) { - for (IParmListChangedListener listener : this.parmListChangedListeners) { - listener.parmListChanged(parms, deletes, adds); + protected void fireParmListChanged(final Parm[] parms, final Parm[] adds, + final Parm[] deletes) { + for (Object listener : this.parmListChangedListeners.getListeners()) { + final IParmListChangedListener casted = (IParmListChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.parmListChanged(parms, deletes, adds); + } + }; + notificationPool.schedule(notTask); } } @@ -1433,9 +1486,19 @@ public abstract class AbstractParmManager implements IParmManager { * @param systemTimeRange * new system time range */ - protected void fireSystemTimeRangeChanged(TimeRange systemTimeRange) { - for (ISystemTimeRangeChangedListener listener : this.systemTimeRangeChangedListeners) { - listener.systemTimeRangeChanged(systemTimeRange); + protected void fireSystemTimeRangeChanged(final TimeRange systemTimeRange) { + for (Object listener : this.systemTimeRangeChangedListeners + .getListeners()) { + final ISystemTimeRangeChangedListener casted = (ISystemTimeRangeChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.systemTimeRangeChanged(systemTimeRange); + } + }; + notificationPool.schedule(notTask); } } @@ -1449,10 +1512,22 @@ public abstract class AbstractParmManager implements IParmManager { * @param additions * The items added to the inventory */ - protected void fireAvailableSourcesChanged(List inventory, - List deletions, List additions) { - for (IAvailableSourcesChangedListener listener : this.availableSourcesListeners) { - listener.availableSourcesChanged(inventory, deletions, additions); + protected void fireAvailableSourcesChanged( + final List inventory, final List deletions, + final List additions) { + for (Object listener : this.availableSourcesListeners.getListeners()) { + final IAvailableSourcesChangedListener casted = (IAvailableSourcesChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.availableSourcesChanged(inventory, deletions, + additions); + } + }; + + notificationPool.schedule(notTask); } } @@ -1462,9 +1537,18 @@ public abstract class AbstractParmManager implements IParmManager { * @param additions * The DatabaseID of the newly-available model */ - protected void fireNewModelAvailable(DatabaseID newModel) { - for (INewModelAvailableListener listener : this.newModelListeners) { - listener.newModelAvailable(newModel); + protected void fireNewModelAvailable(final DatabaseID newModel) { + for (Object listener : this.newModelListeners.getListeners()) { + final INewModelAvailableListener casted = (INewModelAvailableListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.newModelAvailable(newModel); + } + }; + notificationPool.schedule(notTask); } } @@ -1862,6 +1946,7 @@ public abstract class AbstractParmManager implements IParmManager { deleteParm(tempParms.toArray(new Parm[tempParms.size()])); } + @Override public ParmID fromExpression(String expression) { return new ABVParmID(this).parse(expression); } @@ -1918,4 +2003,9 @@ public abstract class AbstractParmManager implements IParmManager { return -1; } + + @Override + public JobPool getNotificationPool() { + return notificationPool; + } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java index fd145ee224..b7a6d41ddb 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java @@ -51,7 +51,7 @@ import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.parm.DbParm; import com.raytheon.viz.gfe.core.parm.Parm; import com.raytheon.viz.gfe.core.parm.ParmDisplayAttributes.VisMode; -import com.raytheon.viz.gfe.core.parm.VCModule; +import com.raytheon.viz.gfe.core.parm.vcparm.VCModule; import com.raytheon.viz.gfe.core.parm.VCParm; import com.raytheon.viz.gfe.core.parm.VParm; import com.raytheon.viz.gfe.types.MutableInteger; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/Parm.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/Parm.java index 45701a5dc4..35201ab0f0 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/Parm.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/Parm.java @@ -326,7 +326,8 @@ public abstract class Parm implements Comparable { this.parmState = new ParmState(this); this.displayAttributes = new ParmDisplayAttributes(displayable, this); - this.parmListeners = new ParmListeners(); + this.parmListeners = new ParmListeners(this.dataManager + .getParmManager().getNotificationPool()); // Construct an empty lock table // Subclasses who utilize locks will override this diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/ParmListeners.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/ParmListeners.java index 2092321a48..5164b5e514 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/ParmListeners.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/ParmListeners.java @@ -25,6 +25,7 @@ import org.eclipse.core.runtime.ListenerList; import com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID; import com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.viz.core.jobs.JobPool; import com.raytheon.viz.gfe.core.msgs.GridDataChangedMsg; import com.raytheon.viz.gfe.core.msgs.IColorTableModifiedListener; import com.raytheon.viz.gfe.core.msgs.ICombineModeChangedListener; @@ -83,7 +84,9 @@ public class ParmListeners { private final ListenerList lockTableChangedListeners; - protected ParmListeners() { + private final JobPool notificationPool; + + protected ParmListeners(JobPool pool) { this.gridChangedListeners = new ListenerList(); this.parmInventoryChangedListeners = new ListenerList(); this.parmIDChangedListeners = new ListenerList(); @@ -94,81 +97,171 @@ public class ParmListeners { this.pickupValueChangedListeners = new ListenerList(); this.colorTableModifiedListeners = new ListenerList(); this.lockTableChangedListeners = new ListenerList(); + this.notificationPool = pool; } - public void fireGridChangedListener(ParmID parmID, TimeRange validTime) { + public void fireGridChangedListener(final ParmID parmID, + final TimeRange validTime) { for (Object listener : this.gridChangedListeners.getListeners()) { - ((IGridDataChangedListener) listener).gridDataChanged(parmID, - validTime); - } + final IGridDataChangedListener casted = (IGridDataChangedListener) listener; + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.gridDataChanged(parmID, validTime); + } + }; + + notificationPool.schedule(notTask); + } new GridDataChangedMsg(parmID, validTime).send(); } - protected void fireParmInventoryChangedListener(Parm parm, - TimeRange validTime) { + protected void fireParmInventoryChangedListener(final Parm parm, + final TimeRange validTime) { for (Object listener : this.parmInventoryChangedListeners .getListeners()) { - ((IParmInventoryChangedListener) listener).parmInventoryChanged( - parm, validTime); + final IParmInventoryChangedListener casted = (IParmInventoryChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.parmInventoryChanged(parm, validTime); + } + }; + + notificationPool.schedule(notTask); } } - protected void fireParmIDChangedListener(Parm parm, ParmID newParmID) { + protected void fireParmIDChangedListener(final Parm parm, + final ParmID newParmID) { for (Object listener : this.parmIDChangedListeners.getListeners()) { - ((IParmIDChangedListener) listener).parmIDChanged(parm, newParmID); + final IParmIDChangedListener casted = (IParmIDChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.parmIDChanged(parm, newParmID); + } + }; + notificationPool.schedule(notTask); } } - public void fireSelectionTimeRangeChanged(Parm parm, - TimeRange selectionTimeRange) { + public void fireSelectionTimeRangeChanged(final Parm parm, + final TimeRange selectionTimeRange) { for (Object listener : this.selectionTimeRangeChangedListeners .getListeners()) { - ((ISelectionTimeRangeChangedListener) listener) - .selectionTimeRangeChanged(parm, selectionTimeRange); + final ISelectionTimeRangeChangedListener casted = (ISelectionTimeRangeChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.selectionTimeRangeChanged(parm, selectionTimeRange); + } + }; + + notificationPool.schedule(notTask); } } - public void fireParameterSelectionChangedListener(Parm parm, - boolean selected) { + public void fireParameterSelectionChangedListener(final Parm parm, + final boolean selected) { for (Object listener : this.parameterSelectionChangedListeners .getListeners()) { - ((IParameterSelectionChangedListener) listener) - .parameterSelectionChanged(parm, selected); + final IParameterSelectionChangedListener casted = (IParameterSelectionChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.parameterSelectionChanged(parm, selected); + } + }; + notificationPool.schedule(notTask); } } - public void fireCombineModeChangedListener(Parm parm, CombineMode mode) { + public void fireCombineModeChangedListener(final Parm parm, + final CombineMode mode) { for (Object listener : this.combineModeChangedListeners.getListeners()) { - ((ICombineModeChangedListener) listener).combineModeChanged(parm, - mode); + final ICombineModeChangedListener casted = (ICombineModeChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.combineModeChanged(parm, mode); + } + }; + notificationPool.schedule(notTask); } } - public void fireVectorModeChangedListener(Parm parm, VectorMode mode) { + public void fireVectorModeChangedListener(final Parm parm, + final VectorMode mode) { for (Object listener : this.vectorModeChangedListeners.getListeners()) { - ((IVectorModeChangedListener) listener).vectorModeChanged(parm, - mode); + final IVectorModeChangedListener casted = (IVectorModeChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.vectorModeChanged(parm, mode); + } + }; + notificationPool.schedule(notTask); } } - public void firePickupValueChangedListener(Parm parm, WxValue pickupValue) { + public void firePickupValueChangedListener(final Parm parm, + final WxValue pickupValue) { for (Object listener : this.pickupValueChangedListeners.getListeners()) { - ((IPickupValueChangedListener) listener).pickupValueChanged(parm, - pickupValue); + final IPickupValueChangedListener casted = (IPickupValueChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.pickupValueChanged(parm, pickupValue); + } + }; + notificationPool.schedule(notTask); } } - public void fireColorTableModified(Parm parm) { + public void fireColorTableModified(final Parm parm) { for (Object listener : this.colorTableModifiedListeners.getListeners()) { - ((IColorTableModifiedListener) listener).colorTableModified(parm); + final IColorTableModifiedListener casted = (IColorTableModifiedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.colorTableModified(parm); + } + }; + notificationPool.schedule(notTask); } } - public void fireLockTableChanged(Parm parm, LockTable lockTable) { + public void fireLockTableChanged(final Parm parm, final LockTable lockTable) { for (Object listener : this.lockTableChangedListeners.getListeners()) { - ((ILockTableChangedListener) listener).lockTableChanged(parm, - lockTable); + final ILockTableChangedListener casted = (ILockTableChangedListener) listener; + + Runnable notTask = new Runnable() { + + @Override + public void run() { + casted.lockTableChanged(parm, lockTable); + } + }; + notificationPool.schedule(notTask); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCModule.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCModule.java deleted file mode 100644 index a93ce550a5..0000000000 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCModule.java +++ /dev/null @@ -1,662 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.viz.gfe.core.parm; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import jep.JepException; - -import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory; -import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory.OriginType; -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.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.discrete.DiscreteKey; -import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DBit; -import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DByte; -import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DFloat; -import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil; -import com.raytheon.uf.common.dataplugin.gfe.slice.DiscreteGridSlice; -import com.raytheon.uf.common.dataplugin.gfe.slice.IGridSlice; -import com.raytheon.uf.common.dataplugin.gfe.slice.ScalarGridSlice; -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.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.viz.core.VizApp; -import com.raytheon.viz.gfe.GFEException; -import com.raytheon.viz.gfe.core.DataManager; -import com.raytheon.viz.gfe.core.IParmManager; -import com.raytheon.viz.gfe.core.griddata.IGridData; - -/** - * Virtual Calculated Module. Serves as interface between the VCParm and the - * actual python algorithms. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Oct 17, 2011            dgilling     Initial creation
- * 
- * 
- * - * @author dgilling - * @version 1.0 - */ - -public class VCModule { - - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(VCModule.class); - - public class DepParmInv { - - private ParmID parmID; - - private List times; - - public DepParmInv(ParmID pid, List trs) { - this.parmID = pid; - this.times = trs; - } - - public ParmID getParmID() { - return parmID; - } - - public List getTimes() { - return times; - } - - @Override - public String toString() { - StringBuilder tmp = new StringBuilder(); - tmp.append("(pid="); - tmp.append(parmID.toString()); - tmp.append(",times="); - tmp.append(times.toString()); - tmp.append(')'); - - return tmp.toString(); - } - } - - public class VCInventory { - - private TimeRange gridTimeRange; - - private List depParmInv; - - public VCInventory(TimeRange gridTimeRange, List depParmInv) { - this.gridTimeRange = gridTimeRange; - this.depParmInv = depParmInv; - } - - public TimeRange getGridTimeRange() { - return gridTimeRange; - } - - public List getDepParmInv() { - return depParmInv; - } - - @Override - public String toString() { - StringBuilder tmp = new StringBuilder(); - tmp.append("gtr="); - tmp.append(gridTimeRange.toString()); - tmp.append(",dpi="); - tmp.append(depParmInv.toString()); - - return tmp.toString(); - } - } - - protected class GetInventoryArg { - public List trs; - - public GetInventoryArg(List trs) { - this.trs = new ArrayList(trs); - } - } - - protected class CalcHistoryArg { - // simulates the AWIPS1 tuple used, which contained an encoded time - // range (long[]) and the list of GridDataHistory entries that - // correspond to that grid time range (List). - public List histEntries; - - public CalcHistoryArg(List histEntries) { - this.histEntries = new ArrayList(histEntries); - } - } - - protected class CalcGridArg { - // simulates the AWIPS1 tuple used, which contained an encoded time - // range (long[]), the grid data (IGridData), and a bit mask of valid - // points in the grid data (Grid2DBit). - public List argTuples; - - public CalcGridArg(List argTuples) { - this.argTuples = new ArrayList(argTuples); - } - } - - private VCModuleScript module; - - private Throwable error; - - private GridParmInfo gpi; - - private Collection depParms; - - private DataManager dataMgr; - - private IParmManager parmMgr; - - @SuppressWarnings("unused") - private String id; - - // To prevent invalid thread access errors from Jep all public interface - // functions run within a VizApp.runSync(). This is not a desirable - // long-term solution and would be faster if they could run on some other - // common thread. - // FIXME: Restructure this class to work from a common thread that is - // not the UI thread. - public VCModule(DataManager dataMgr, IParmManager parmMgr, final File module) { - this.dataMgr = dataMgr; - this.parmMgr = parmMgr; - this.id = module.getName(); - - // Let's do something unfortunately hacky here--we're going to force - // creation of the module object to be on the UI thread. Thus, any of - // the notifications received by VCParm can call methods within this - // class from a VizApp.runAsync and not receive invalid thread errors. - VizApp.runSync(new Runnable() { - - @Override - public void run() { - try { - VCModule.this.module = new VCModuleScript(module - .getAbsolutePath(), GfePyIncludeUtil - .getCommonPythonIncludePath(), VCModule.this - .getClass().getClassLoader()); - } catch (JepException e) { - VCModule.this.error = e; - } - } - }); - } - - public boolean isValid() { - return (this.error == null); - } - - public Throwable getErrorString() { - Throwable rVal = error; - error = null; - return rVal; - } - - private List getMethodArgs(String method) throws JepException { - // statusHandler.debug("getMethodArgs: " + id); - return module.getArgumentNames(method); - } - - public Collection dependentParms() { - if (this.depParms != null) { - return this.depParms; - } - - final Collection parameters = new ArrayList(); - VizApp.runSync(new Runnable() { - - @Override - public void run() { - try { - parameters.addAll(getMethodArgs("getInventory")); - } catch (JepException e) { - error = e; - // statusHandler.handle(Priority.DEBUG, "dependentParms: " + - // id - // + " error", e); - VCModule.this.depParms = Collections.emptyList(); - } - } - }); - - if (this.depParms == null) { - Collection rval = new ArrayList(); - - for (String parmName : parameters) { - ParmID pid = parmMgr.fromExpression(parmName); - if (pid.isValid()) { - rval.add(pid); - } else { - error = new IllegalArgumentException( - "Can't find Weather Element for " + parmName); - this.depParms = Collections.emptyList(); - } - } - - this.depParms = rval; - } - - return this.depParms; - } - - private long[] encodeTR(final TimeRange tr) { - long[] ptime = { tr.getStart().getTime(), tr.getEnd().getTime() }; - return ptime; - } - - private List pyInventory(Parm p) { - IGridData[] gridInv = p.getGridInventory(); - List inv = new ArrayList(gridInv.length); - for (IGridData gd : gridInv) { - inv.add(encodeTR(gd.getGridTime())); - } - - return inv; - } - - private Object[] encodeGD(IGridData gd) { - Object[] item = new Object[3]; - item[0] = encodeTR(gd.getGridTime()); - - // since we have to go through a bunch of hoops in VCModuleScript to get - // the IGridData in python-useable format, no need doing anything here - // but storing the data - item[1] = gd; - - // add a mask indicating the set of valid points. Note for all data - // other than ISC data, the mask is all points. ISC data values depend - // upon the masking of the Grid Data History. - Grid2DBit validBits; - if (gd.getParm().isIscParm()) { - List hs = gd.getHistorySites(); - validBits = dataMgr.getRefManager().siteGridpoints(hs, true); - } else { - validBits = dataMgr.getRefManager().fullRefSet().getGrid(); - } - item[2] = validBits; - - return item; - } - - @SuppressWarnings("unchecked") - private IGridSlice decodeGD(Object o, VCInventory invEntry) - throws GFEException, JepException { - TimeRange tr = invEntry.getGridTimeRange(); - List gdh = calcHistory(invEntry); - if (!isValid()) { - throw new GFEException(getErrorString()); - } - - GridParmInfo gpi = getGpi(); - switch (gpi.getGridType()) { - case SCALAR: - return new ScalarGridSlice(tr, gpi, gdh, (Grid2DFloat) o); - case VECTOR: - Grid2DFloat[] s = (Grid2DFloat[]) o; - return new VectorGridSlice(tr, gpi, gdh, s[0], s[1]); - case WEATHER: - Object[] wxGrid = (Object[]) o; - List key = new ArrayList(); - List pkey = (List) wxGrid[1]; - for (String wKey : pkey) { - key.add(new WeatherKey(gpi.getParmID().getDbId().getSiteId(), - wKey)); - } - return new WeatherGridSlice(tr, gpi, gdh, (Grid2DByte) wxGrid[0], - key); - case DISCRETE: - Object[] discGrid = (Object[]) o; - List keys = new ArrayList(); - List pkeys = (List) discGrid[1]; - for (String dKey : pkeys) { - keys.add(new DiscreteKey(gpi.getParmID().getDbId().getSiteId(), - dKey, gpi.getParmID())); - } - return new DiscreteGridSlice(tr, gpi, gdh, - (Grid2DByte) discGrid[0], keys); - default: - statusHandler.handle(Priority.EVENTB, "Unknown parm type: " - + gpi.getGridType().toString()); - break; - } - - return null; - } - - @SuppressWarnings("unchecked") - private TimeRange decodeTR(Object o) { - List ptr = (List) o; - return new TimeRange(ptr.get(0), ptr.get(1)); - } - - @SuppressWarnings("unchecked") - public List getInventory() { - // statusHandler.debug("getInventory: " + id); - final List rval = new ArrayList(); - - VizApp.runSync(new Runnable() { - - @Override - public void run() { - try { - List args = getMethodArgs("getInventory"); - Map cargs = new HashMap( - args.size()); - List pargs = new ArrayList(args.size()); - - for (String arg : args) { - ParmID pid = parmMgr.fromExpression(arg); - Parm tp = parmMgr.getParm(pid); - if (tp == null) { - throw new IllegalArgumentException( - "Can't locate Weather Element: " + arg); - } - cargs.put(arg, new GetInventoryArg(pyInventory(tp))); - pargs.add(tp); - } - - // what's returned from the script here is a list of tuples. - // Each tuple contains: - // 1. A TimeRange. - // 2. A list of TimeRanges that correspond to the Fcst grids - // that should be used for that time - // 3. A list of TimeRanges that correspond to the ISC grids - // that should be used for that time - List> result = (List>) module - .execute("getInventory", cargs); - for (List item : result) { - List dpi = new ArrayList(); - for (int i = 1; i < item.size(); i++) { - List ditem = (List) item.get(i); - List trs = new ArrayList( - ditem.size()); - for (Object tr : ditem) { - trs.add(decodeTR(tr)); - } - dpi.add(new DepParmInv( - pargs.get(i - 1).getParmID(), trs)); - } - rval.add(new VCInventory(decodeTR(item.get(0)), dpi)); - } - - } catch (Throwable t) { - error = t; - } - } - }); - - return rval; - } - - private List encodeGDH(final List gdh) { - List l = new ArrayList(gdh.size()); - for (GridDataHistory hist : gdh) { - l.add(hist.getCodedString()); - } - - return l; - } - - @SuppressWarnings("unchecked") - private List decodeGDH(final Object o) { - List s = (List) o; - List rval = new ArrayList(s.size()); - - for (String entry : s) { - GridDataHistory gdh = new GridDataHistory(entry); - rval.add(gdh); - } - - return rval; - } - - @SuppressWarnings("unchecked") - public List calcHistory(final VCInventory invEntry) { - // statusHandler.debug("calcHistory: " + id + " " + - // invEntry.toString()); - - final List result = new ArrayList(); - VizApp.runSync(new Runnable() { - - @Override - public void run() { - boolean hasattr = false; - try { - hasattr = module.hasAttr("calcHistory"); - } catch (JepException e) { - // swallow exception and move on - statusHandler.handle(Priority.EVENTB, - "Could not retrieve calcHistory attribute", e); - } - - if (hasattr) { - try { - final List dpi = invEntry.getDepParmInv(); - List args = getMethodArgs("calcHistory"); - Map cargs = new HashMap( - args.size()); - - for (String arg : args) { - Parm tp = parmMgr.getParm(parmMgr - .fromExpression(arg)); - if (tp != null) { - List l = new ArrayList(); - for (DepParmInv dpiEntry : dpi) { - if (dpiEntry.getParmID().equals( - tp.getParmID())) { - for (TimeRange tr : dpiEntry.getTimes()) { - IGridData gd = tp - .overlappingGrid(tr - .getStart()); - if (gd == null) { - throw new IllegalArgumentException( - "Unable to retrieve overlapping grid for parm: " - + tp.getParmID() - .toString() - + " for time: " - + tr.toString()); - } - - Object[] tl = new Object[2]; - tl[0] = encodeTR(gd.getGridTime()); - tl[1] = encodeGDH(Arrays.asList(gd - .getHistory())); - l.add(tl); - } - } - } - - cargs.put(arg, new CalcHistoryArg(l)); - } else { - throw new IllegalArgumentException( - "Unable to find parm " + arg); - } - } - - result.addAll((List) module.execute( - "calcHistory", cargs)); - } catch (Throwable t) { - error = t; - } - } - } - }); - - if (error == null) { - return decodeGDH(result); - } else { - // the default - return Arrays.asList(new GridDataHistory(OriginType.CALCULATED, - getGpi().getParmID(), invEntry.getGridTimeRange())); - } - } - - public IGridSlice calcGrid(VCInventory invEntry) { - // statusHandler.debug("calcGrid: " + id + " " + invEntry.toString()); - final List dpi = invEntry.getDepParmInv(); - - final List holder = new ArrayList(1); - VizApp.runSync(new Runnable() { - - @Override - public void run() { - try { - List args = getMethodArgs("calcGrid"); - Map cargs = new HashMap( - args.size()); - - for (String arg : args) { - ParmID id = parmMgr.fromExpression(arg); - Parm tp = parmMgr.getParm(id); - if (tp != null) { - List l = new ArrayList(); - - for (DepParmInv dpiEntry : dpi) { - if (dpiEntry.getParmID().equals(tp.getParmID())) { - for (TimeRange tr : dpiEntry.getTimes()) { - IGridData gd = tp.overlappingGrid(tr - .getStart()); - if (gd == null) { - throw new IllegalArgumentException( - "Unable to retrieve overlapping grid for parm: " - + tp.getParmID() - .toString() - + " for time: " - + tr.toString()); - } - - l.add(encodeGD(gd)); - } - } - } - - cargs.put(arg, new CalcGridArg(l)); - } else { - throw new IllegalArgumentException( - "Unable to find parm " + arg); - } - } - - Object result = module.executeCalcGrid(cargs, getGpi() - .getGridType()); - holder.add(result); - - } catch (Throwable t) { - error = t; - } - } - }); - - if (error == null) { - try { - return decodeGD(holder.get(0), invEntry); - } catch (Throwable t) { - error = t; - return null; - } - } else { - return null; - } - } - - @SuppressWarnings("unchecked") - public GridParmInfo getGpi() { - if (this.gpi != null) { - return this.gpi; - } - // statusHandler.debug("getGpi(): " + id); - - try { - final List> result = new ArrayList>(); - VizApp.runSync(new Runnable() { - - @Override - public void run() { - try { - result.addAll((List>) VCModule.this.module - .execute("getWEInfo", null)); - } catch (JepException e) { - VCModule.this.error = e; - } - } - }); - if (error != null) { - return null; - } - - List s = result.get(1); - String site = parmMgr.getMutableDatabase().getSiteId(); - DatabaseID dbid = new DatabaseID(site, DataType.GRID, s.get(1) - .toString(), s.get(0).toString(), DatabaseID.NO_MODEL_TIME); - - s = result.get(2); - TimeConstraints tc = new TimeConstraints((Integer) s.get(0), - (Integer) s.get(1), (Integer) s.get(2)); - - s = result.get(0); - ParmID pid = new ParmID(s.get(0).toString(), dbid); - GridType type = GridType.NONE; - try { - type = GridType.valueOf(s.get(1).toString().toUpperCase()); - } catch (IllegalArgumentException e) { - // just want to swallow the exception here as we've already - // defaulted type to NONE - statusHandler - .handle(Priority.EVENTB, "Invalid GridType specified: " - + s.get(1).toString(), e); - } - - // Double check for all the various valid parm lengths from - // serverConfig - GridParmInfo gpi = new GridParmInfo(pid, - parmMgr.compositeGridLocation(), type, s.get(2).toString(), - s.get(3).toString(), (Float) s.get(5), (Float) s.get(4), - (Integer) s.get(6), false, tc, (Boolean) s.get(7)); - this.gpi = gpi; - - } catch (Exception e) { - error = e; - } - - return this.gpi; - } -} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCModuleScript.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCModuleScript.java deleted file mode 100644 index 8ab1d32564..0000000000 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCModuleScript.java +++ /dev/null @@ -1,402 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.viz.gfe.core.parm; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import jep.JepException; - -import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; -import com.raytheon.uf.common.dataplugin.gfe.discrete.DiscreteKey; -import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DBit; -import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DByte; -import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DFloat; -import com.raytheon.uf.common.dataplugin.gfe.weather.WeatherKey; -import com.raytheon.uf.common.python.PyUtil; -import com.raytheon.uf.common.python.PythonScript; -import com.raytheon.viz.gfe.core.griddata.DiscreteGridData; -import com.raytheon.viz.gfe.core.griddata.IGridData; -import com.raytheon.viz.gfe.core.griddata.ScalarGridData; -import com.raytheon.viz.gfe.core.griddata.VectorGridData; -import com.raytheon.viz.gfe.core.griddata.WeatherGridData; -import com.raytheon.viz.gfe.core.parm.VCModule.CalcGridArg; -import com.raytheon.viz.gfe.core.parm.VCModule.CalcHistoryArg; -import com.raytheon.viz.gfe.core.parm.VCModule.GetInventoryArg; - -/** - * A PythonScript subclass that replaces the Python/C++ interface that was - * available to AWIPS1's VCModule class. Primarily used for - * Python->Java data type conversions. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Nov 17, 2011            dgilling     Initial creation
- * 
- * 
- * - * @author dgilling - * @version 1.0 - */ - -public class VCModuleScript extends PythonScript { - - private static final String INSTANCE_NAME = "instance"; - - private List tempGridNames; - - /** - * Constructor. - * - * @param aFilePath - * the path to the python script - * @param anIncludePath - * the python include path, with multiple directories being - * separated by ":" - * @param aClassLoader - * the Java classloader to use for importing Java classes inside - * python - * @throws JepException - */ - public VCModuleScript(String aFilePath, String anIncludePath, - ClassLoader aClassLoader) throws JepException { - super(aFilePath, anIncludePath, aClassLoader, Arrays.asList( - "import JUtil", "import numpy")); - instantiatePythonClass(INSTANCE_NAME, "VCParm", null); - this.tempGridNames = new ArrayList(); - } - - /** - * Retrieves a list of argument names for the specified Python method. - * - * @param method - * The name of the method. - * @return List of argument names for the specified Python method, except - * for "self". - * @throws JepException - */ - public List getArgumentNames(String method) throws JepException { - String[] argNames = getArgumentNames(method, INSTANCE_NAME); - List retVal = new ArrayList(argNames.length); - for (String arg : argNames) { - if (!arg.equals("self")) { - retVal.add(arg); - } - } - - return retVal; - } - - /** - * Executes the calcGrid() method. - * - * @param methodArgs - * A Map containing argument names and values. - * @param type - * The GridType of the grid being calculated. - * @return The virtual grid. For SCALARs, this will be a - * Grid2DFloat. For VECTORs, this will be an array - * containing 2 Grid2DFloat objects (mag, dir). For - * WEATHER and DISCRETE, this will be an array containing a - * Grid2DByte and a list of keys. - * @throws JepException - */ - public Object executeCalcGrid(Map methodArgs, GridType type) - throws JepException { - internalExecute("calcGrid", INSTANCE_NAME, methodArgs); - Object obj = decodeGD(type); - jep.eval(RESULT + " = None"); - return obj; - } - - /* - * (non-Javadoc) - * - * @see com.raytheon.uf.common.python.PythonScript#execute(java.lang.String, - * java.util.Map) - */ - @Override - public Object execute(String methodName, Map args) - throws JepException { - internalExecute(methodName, INSTANCE_NAME, args); - jep.eval(RESULT + " = JUtil.pyValToJavaObj(" + RESULT + ")"); - Object obj = jep.getValue(RESULT); - jep.eval(RESULT + " = None"); - return obj; - } - - /** - * Override of the evaluateArgument() method which handles the custom - * argument structures defined in VCModule. Important so that - * we can convert the Java datatypes to Python native objects (and numpy - * arrays for the grids). - * - * @param argName - * The argument name. - * @param argValue - * the value of the argument - * - * @see com.raytheon.uf.common.python.PythonInterpreter#evaluateArgument(java - * .lang.String, java.lang.Object) - */ - @SuppressWarnings("unchecked") - @Override - protected void evaluateArgument(String argName, Object argValue) - throws JepException { - if (argValue instanceof GetInventoryArg) { - GetInventoryArg arg = (GetInventoryArg) argValue; - StringBuilder sb = new StringBuilder(512); - sb.append(argName + " = ["); - for (int i = 0; i < arg.trs.size(); i++) { - long[] tuple = arg.trs.get(i); - sb.append('('); - sb.append(tuple[0]); - sb.append(", "); - sb.append(tuple[1]); - sb.append(')'); - if (i < arg.trs.size() - 1) { - sb.append(','); - } - } - sb.append(']'); - jep.eval(sb.toString()); - } else if (argValue instanceof CalcHistoryArg) { - CalcHistoryArg castedArg = (CalcHistoryArg) argValue; - - StringBuilder sb = new StringBuilder(1024); - sb.append(argName + " = ["); - for (int i = 0; i < castedArg.histEntries.size(); i++) { - Object[] timeAndHistList = castedArg.histEntries.get(i); - long[] tr = (long[]) timeAndHistList[0]; - List hist = (List) timeAndHistList[1]; - - sb.append("(("); - sb.append(tr[0]); - sb.append(", "); - sb.append(tr[1]); - sb.append("), ["); - for (int j = 0; j < hist.size(); j++) { - sb.append("\"" + hist.get(j) + "\""); - if (j < hist.size() - 1) { - sb.append(','); - } - } - sb.append("])"); - if (i < castedArg.histEntries.size() - 1) { - sb.append(','); - } - } - sb.append(']'); - jep.eval(sb.toString()); - } else if (argValue instanceof CalcGridArg) { - CalcGridArg castedArg = (CalcGridArg) argValue; - - StringBuilder sb = new StringBuilder(768); - sb.append(argName + " = ["); - - for (int i = 0; i < castedArg.argTuples.size(); i++) { - Object[] tuple = castedArg.argTuples.get(i); - long[] tr = (long[]) tuple[0]; - IGridData gd = (IGridData) tuple[1]; - Grid2DBit mask = (Grid2DBit) tuple[2]; - - sb.append("(("); - sb.append(tr[0]); - sb.append(", "); - sb.append(tr[1]); - sb.append("), "); - sb.append(encodeGridAndMask(gd, mask, i)); - sb.append(')'); - - if (i < castedArg.argTuples.size() - 1) { - sb.append(','); - } - } - sb.append(']'); - jep.eval(sb.toString()); - - } else { - super.evaluateArgument(argName, argValue); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.python.PythonScript#cleanupArgs(java.util.List) - */ - @Override - protected void cleanupArgs(List args) throws JepException { - super.cleanupArgs(args); - for (String gridName : tempGridNames) { - jep.eval(gridName + " = None"); - } - tempGridNames.clear(); - } - - private String encodeGridAndMask(IGridData gd, Grid2DBit mask, int offset) - throws JepException { - StringBuilder jepString = new StringBuilder(256); - String prefix = gd.getParm().getParmID().getParmName() - + Integer.toHexString(gd.getParm().getParmID().hashCode()) - + "_" + offset + "_"; - - if (gd instanceof ScalarGridData) { - ScalarGridData grid = (ScalarGridData) gd; - Grid2DFloat f = (grid.getScalarSlice()).getScalarGrid(); - String name = prefix + "grid"; - jep.setNumeric(name, f.getFloats(), f.getXdim(), f.getYdim()); - jepString.append(name); - jepString.append(", "); - tempGridNames.add(name); - } else if (gd instanceof VectorGridData) { - VectorGridData grid = (VectorGridData) gd; - Grid2DFloat mag = (grid.getVectorSlice()).getMagGrid(); - Grid2DFloat dir = (grid.getVectorSlice()).getDirGrid(); - String magName = prefix + "Mag"; - String dirName = prefix + "Dir"; - jep.setNumeric(magName, mag.getFloats(), mag.getXdim(), - mag.getYdim()); - jep.setNumeric(dirName, dir.getFloats(), dir.getXdim(), - dir.getYdim()); - jepString.append('('); - jepString.append(magName); - jepString.append(','); - jepString.append(dirName); - jepString.append("), "); - tempGridNames.add(magName); - tempGridNames.add(dirName); - } else if (gd instanceof WeatherGridData) { - WeatherGridData grid = (WeatherGridData) gd; - Grid2DByte bytes = grid.getWeatherSlice().getWeatherGrid(); - String name = prefix + "grid"; - jep.setNumeric(name, bytes.getBytes(), bytes.getXdim(), - bytes.getYdim()); - jepString.append('('); - jepString.append(name); - jepString.append(','); - WeatherKey[] keys = grid.getWeatherSlice().getKeys(); - ArrayList stringKeys = new ArrayList(keys.length); - for (WeatherKey k : keys) { - stringKeys.add(k.toString()); - } - jepString.append(PyUtil.listToTuple(stringKeys)); - jepString.append("), "); - tempGridNames.add(name); - } else if (gd instanceof DiscreteGridData) { - DiscreteGridData grid = (DiscreteGridData) gd; - Grid2DByte bytes = grid.getDiscreteSlice().getDiscreteGrid(); - String name = prefix + "grid"; - jep.setNumeric(name, bytes.getBytes(), bytes.getXdim(), - bytes.getYdim()); - jepString.append('('); - jepString.append(name); - jepString.append(','); - DiscreteKey[] keys = grid.getDiscreteSlice().getKey(); - ArrayList stringKeys = new ArrayList(keys.length); - for (DiscreteKey k : keys) { - stringKeys.add(k.toString()); - } - jepString.append(PyUtil.listToTuple(stringKeys)); - jepString.append("), "); - tempGridNames.add(name); - } - - String maskName = prefix + "mask"; - jep.setNumeric(maskName, mask.getBytes(), mask.getXdim(), - mask.getYdim()); - jepString.append(maskName); - tempGridNames.add(maskName); - - return jepString.toString(); - } - - private Object decodeGD(GridType type) throws JepException { - Object result = null; - boolean resultFound = (Boolean) jep.getValue(RESULT + " is not None"); - - if (resultFound) { - int xDim, yDim = 0; - switch (type) { - case SCALAR: - float[] scalarData = (float[]) jep.getValue(RESULT - + ".astype(numpy.float32)"); - xDim = (Integer) jep.getValue(RESULT + ".shape[1]"); - yDim = (Integer) jep.getValue(RESULT + ".shape[0]"); - result = new Grid2DFloat(xDim, yDim, scalarData); - break; - case VECTOR: - float[] mag = (float[]) jep.getValue(RESULT - + "[0].astype(numpy.float32)"); - float[] dir = (float[]) jep.getValue(RESULT - + "[1].astype(numpy.float32)"); - xDim = (Integer) jep.getValue(RESULT + "[0].shape[1]"); - yDim = (Integer) jep.getValue(RESULT + "[0].shape[0]"); - - Grid2DFloat magGrid = new Grid2DFloat(xDim, yDim, mag); - Grid2DFloat dirGrid = new Grid2DFloat(xDim, yDim, dir); - result = new Grid2DFloat[] { magGrid, dirGrid }; - break; - case WEATHER: - case DISCRETE: - byte[] bytes = (byte[]) jep.getValue(RESULT - + "[0].astype(numpy.int8)"); - String[] keys = (String[]) jep.getValue(RESULT + "[1]"); - xDim = (Integer) jep.getValue(RESULT + "[0].shape[1]"); - yDim = (Integer) jep.getValue(RESULT + "[0].shape[0]"); - - Grid2DByte grid = new Grid2DByte(xDim, yDim, bytes); - List keysList = new ArrayList(); - Collections.addAll(keysList, keys); - - result = new Object[] { grid, keysList }; - break; - } - } - - return result; - } - - /** - * Calls hasattr() against the VCModule instance and returns - * whether or not the specified attribute exists. - * - * @param attribute - * Attribute name. - * @return Whether or not the specified attribute exists. - * @throws JepException - */ - public boolean hasAttr(String attribute) throws JepException { - jep.eval(RESULT + " = hasattr(" + INSTANCE_NAME + ", \"" + attribute - + "\")"); - boolean result = ((Boolean) jep.getValue(RESULT)).booleanValue(); - jep.eval(RESULT + " = None"); - return result; - } - -} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java index d52b44638a..de9b275cda 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java @@ -38,15 +38,15 @@ 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.viz.core.VizApp; import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.griddata.AbstractGridData; import com.raytheon.viz.gfe.core.griddata.IGridData; import com.raytheon.viz.gfe.core.msgs.IGridDataChangedListener; import com.raytheon.viz.gfe.core.msgs.IParmInventoryChangedListener; import com.raytheon.viz.gfe.core.msgs.IParmListChangedListener; -import com.raytheon.viz.gfe.core.parm.VCModule.DepParmInv; -import com.raytheon.viz.gfe.core.parm.VCModule.VCInventory; +import com.raytheon.viz.gfe.core.parm.vcparm.VCModule; +import com.raytheon.viz.gfe.core.parm.vcparm.VCModule.DepParmInv; +import com.raytheon.viz.gfe.core.parm.vcparm.VCModule.VCInventory; /** * A VC (virtual calculated) parm is virtual (non-database ifpServer) and is @@ -145,39 +145,32 @@ public class VCParm extends VParm implements IParmListChangedListener, // statusHandler.handle(Priority.DEBUG, "gridDataChanged for: " + parmId // + " " + validTime); - VizApp.runAsync(new Runnable() { - - @Override - public void run() { - for (VCInventory inv : VCParm.this.vcInventory) { - for (DepParmInv dpi : inv.getDepParmInv()) { - if (dpi.getParmID().equals(parmId)) { - for (TimeRange tr : dpi.getTimes()) { - if (tr.getStart().equals(validTime.getStart())) { - VCParm.this.grids.acquireReadLock(); - try { - for (IGridData grid : VCParm.this.grids) { - if (inv.getGridTimeRange().equals( - grid.getGridTime())) { - grid.depopulate(); - gridDataHasChanged( - grid, - getDisplayAttributes() - .getDisplayMask(), - false); - return; - } - } - } finally { - VCParm.this.grids.releaseReadLock(); + for (VCInventory inv : this.vcInventory) { + for (DepParmInv dpi : inv.getDepParmInv()) { + if (dpi.getParmID().equals(parmId)) { + for (TimeRange tr : dpi.getTimes()) { + if (tr.getStart().equals(validTime.getStart())) { + this.grids.acquireReadLock(); + try { + for (IGridData grid : this.grids) { + if (inv.getGridTimeRange().equals( + grid.getGridTime())) { + grid.depopulate(); + gridDataHasChanged(grid, + getDisplayAttributes() + .getDisplayMask(), + false); + return; } } + } finally { + this.grids.releaseReadLock(); } } } } } - }); + } } @@ -196,13 +189,8 @@ public class VCParm extends VParm implements IParmListChangedListener, // statusHandler.handle(Priority.DEBUG, // "ParmListChangedMsg received: "); - VizApp.runAsync(new Runnable() { + registerParmClients(parms, true); - @Override - public void run() { - registerParmClients(parms, true); - } - }); } /* @@ -222,13 +210,8 @@ public class VCParm extends VParm implements IParmListChangedListener, // approach. // statusHandler.debug("ParmInventoryChanged notification for: " // + getParmID().toString()); - VizApp.runAsync(new Runnable() { - @Override - public void run() { - recalcInventory(true); - } - }); + recalcInventory(true); } /* @@ -366,7 +349,7 @@ public class VCParm extends VParm implements IParmListChangedListener, // If there is an error in calcHistory() it // will still give us one to use. So, we can just logProblem if (!mod.isValid()) { - statusHandler.handle(Priority.PROBLEM, + statusHandler.handle(Priority.EVENTB, "Error in history calculation for " + getParmID().toString(), mod.getErrorString()); } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/CalcVcModGridArg.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/CalcVcModGridArg.java new file mode 100644 index 0000000000..461e689170 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/CalcVcModGridArg.java @@ -0,0 +1,187 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.core.parm.vcparm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import jep.Jep; +import jep.JepException; + +import com.raytheon.uf.common.dataplugin.gfe.discrete.DiscreteKey; +import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DBit; +import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DByte; +import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DFloat; +import com.raytheon.uf.common.dataplugin.gfe.weather.WeatherKey; +import com.raytheon.uf.common.python.PyUtil; +import com.raytheon.viz.gfe.core.griddata.DiscreteGridData; +import com.raytheon.viz.gfe.core.griddata.IGridData; +import com.raytheon.viz.gfe.core.griddata.ScalarGridData; +import com.raytheon.viz.gfe.core.griddata.VectorGridData; +import com.raytheon.viz.gfe.core.griddata.WeatherGridData; + +/** + * TODO Add Description + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 12, 2012            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class CalcVcModGridArg implements IVcModuleArgument { + + // simulates the AWIPS1 tuple used, which contained an encoded time + // range (long[]), the grid data (IGridData), and a bit mask of valid + // points in the grid data (Grid2DBit). + private List argTuples; + + public CalcVcModGridArg(List argTuples) { + this.argTuples = new ArrayList(argTuples); + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.gfe.core.parm.vcparm.IVcModuleArgument#evaluateArgument + * (jep.Jep) + */ + @Override + public Collection evaluateArgument(final Jep instance, + String argName) throws JepException { + StringBuilder sb = new StringBuilder(768); + Collection tempNames = new ArrayList( + (argTuples.size() * 2)); + + sb.append(argName + " = ["); + for (int i = 0; i < argTuples.size(); i++) { + Object[] tuple = argTuples.get(i); + long[] tr = (long[]) tuple[0]; + IGridData gd = (IGridData) tuple[1]; + Grid2DBit mask = (Grid2DBit) tuple[2]; + + sb.append("(("); + sb.append(tr[0]); + sb.append("L, "); + sb.append(tr[1]); + sb.append("L), "); + tempNames.addAll(encodeGridAndMask(gd, mask, i, sb, instance)); + sb.append(')'); + + if (i < argTuples.size() - 1) { + sb.append(','); + } + } + sb.append(']'); + instance.eval(sb.toString()); + + return tempNames; + } + + private Collection encodeGridAndMask(IGridData gd, Grid2DBit mask, + int offset, StringBuilder sb, Jep jep) throws JepException { + StringBuilder jepString = new StringBuilder(256); + String prefix = gd.getParm().getParmID().getParmName() + + Integer.toHexString(gd.getParm().getParmID().hashCode()) + + "_" + offset + "_"; + Collection tempGridNames = new ArrayList(2); + + if (gd instanceof ScalarGridData) { + ScalarGridData grid = (ScalarGridData) gd; + Grid2DFloat f = (grid.getScalarSlice()).getScalarGrid(); + String name = prefix + "grid"; + jep.setNumeric(name, f.getFloats(), f.getXdim(), f.getYdim()); + jepString.append(name); + jepString.append(", "); + tempGridNames.add(name); + } else if (gd instanceof VectorGridData) { + VectorGridData grid = (VectorGridData) gd; + Grid2DFloat mag = (grid.getVectorSlice()).getMagGrid(); + Grid2DFloat dir = (grid.getVectorSlice()).getDirGrid(); + String magName = prefix + "Mag"; + String dirName = prefix + "Dir"; + jep.setNumeric(magName, mag.getFloats(), mag.getXdim(), + mag.getYdim()); + jep.setNumeric(dirName, dir.getFloats(), dir.getXdim(), + dir.getYdim()); + jepString.append('('); + jepString.append(magName); + jepString.append(','); + jepString.append(dirName); + jepString.append("), "); + tempGridNames.add(magName); + tempGridNames.add(dirName); + } else if (gd instanceof WeatherGridData) { + WeatherGridData grid = (WeatherGridData) gd; + Grid2DByte bytes = grid.getWeatherSlice().getWeatherGrid(); + String name = prefix + "grid"; + jep.setNumeric(name, bytes.getBytes(), bytes.getXdim(), + bytes.getYdim()); + jepString.append('('); + jepString.append(name); + jepString.append(','); + WeatherKey[] keys = grid.getWeatherSlice().getKeys(); + ArrayList stringKeys = new ArrayList(keys.length); + for (WeatherKey k : keys) { + stringKeys.add(k.toString()); + } + jepString.append(PyUtil.listToTuple(stringKeys)); + jepString.append("), "); + tempGridNames.add(name); + } else if (gd instanceof DiscreteGridData) { + DiscreteGridData grid = (DiscreteGridData) gd; + Grid2DByte bytes = grid.getDiscreteSlice().getDiscreteGrid(); + String name = prefix + "grid"; + jep.setNumeric(name, bytes.getBytes(), bytes.getXdim(), + bytes.getYdim()); + jepString.append('('); + jepString.append(name); + jepString.append(','); + DiscreteKey[] keys = grid.getDiscreteSlice().getKey(); + ArrayList stringKeys = new ArrayList(keys.length); + for (DiscreteKey k : keys) { + stringKeys.add(k.toString()); + } + jepString.append(PyUtil.listToTuple(stringKeys)); + jepString.append("), "); + tempGridNames.add(name); + } + + String maskName = prefix + "mask"; + jep.setNumeric(maskName, mask.getBytes(), mask.getXdim(), + mask.getYdim()); + jepString.append(maskName); + sb.append(jepString); + tempGridNames.add(maskName); + + return tempGridNames; + } + +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/CalcVcModHistoryArg.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/CalcVcModHistoryArg.java new file mode 100644 index 0000000000..94ebb029d3 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/CalcVcModHistoryArg.java @@ -0,0 +1,99 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.core.parm.vcparm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import jep.Jep; +import jep.JepException; + +/** + * TODO Add Description + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 12, 2012            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class CalcVcModHistoryArg implements IVcModuleArgument { + + // simulates the AWIPS1 tuple used, which contained an encoded time + // range (long[]) and the list of GridDataHistory entries that + // correspond to that grid time range (List). + private List histEntries; + + public CalcVcModHistoryArg(List histEntries) { + this.histEntries = new ArrayList(histEntries); + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.gfe.core.parm.vcparm.IVcModuleArgument#evaluateArgument + * (jep.Jep) + */ + @Override + public Collection evaluateArgument(final Jep instance, + String argName) throws JepException { + StringBuilder sb = new StringBuilder(1024); + + sb.append(argName + " = ["); + for (int i = 0; i < histEntries.size(); i++) { + Object[] timeAndHistList = histEntries.get(i); + long[] tr = (long[]) timeAndHistList[0]; + @SuppressWarnings("unchecked") + List hist = (List) timeAndHistList[1]; + + sb.append("(("); + sb.append(tr[0]); + sb.append("L, "); + sb.append(tr[1]); + sb.append("L), ["); + for (int j = 0; j < hist.size(); j++) { + sb.append("\"" + hist.get(j) + "\""); + if (j < hist.size() - 1) { + sb.append(','); + } + } + sb.append("])"); + if (i < histEntries.size() - 1) { + sb.append(','); + } + } + sb.append(']'); + instance.eval(sb.toString()); + + return Collections.emptyList(); + } + +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/GetVcModInventoryArg.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/GetVcModInventoryArg.java new file mode 100644 index 0000000000..36ba08d84b --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/GetVcModInventoryArg.java @@ -0,0 +1,85 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.core.parm.vcparm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import jep.Jep; +import jep.JepException; + +/** + * TODO Add Description + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 12, 2012            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class GetVcModInventoryArg implements IVcModuleArgument { + + public List trs; + + public GetVcModInventoryArg(List trs) { + this.trs = new ArrayList(trs); + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.gfe.core.parm.vcparm.IVcModuleArgument#evaluateArgument + * (jep.Jep, java.lang.String) + */ + @Override + public Collection evaluateArgument(final Jep instance, + String argName) throws JepException { + StringBuilder sb = new StringBuilder(512); + + sb.append(argName + " = ["); + for (int i = 0; i < trs.size(); i++) { + long[] tuple = trs.get(i); + sb.append('('); + sb.append(tuple[0]); + sb.append("L, "); + sb.append(tuple[1]); + sb.append("L)"); + if (i < trs.size() - 1) { + sb.append(','); + } + } + sb.append(']'); + instance.eval(sb.toString()); + + return Collections.emptyList(); + } + +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureFinishedListener.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/IVcModuleArgument.java similarity index 63% rename from cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureFinishedListener.java rename to cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/IVcModuleArgument.java index e1c396fc1a..70deaae63c 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureFinishedListener.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/IVcModuleArgument.java @@ -17,9 +17,12 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.viz.gfe.procedures; +package com.raytheon.viz.gfe.core.parm.vcparm; -import com.raytheon.uf.viz.core.jobs.IRequestCompleteListener; +import java.util.Collection; + +import jep.Jep; +import jep.JepException; /** * TODO Add Description @@ -27,34 +30,19 @@ import com.raytheon.uf.viz.core.jobs.IRequestCompleteListener; *
  * 
  * SOFTWARE HISTORY
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * Nov 30, 2011            rferrel     Initial creation
+ * Jan 12, 2012            dgilling     Initial creation
  * 
  * 
* - * @author rferrel + * @author dgilling * @version 1.0 */ -public class ProcedureFinishedListener implements - IRequestCompleteListener { +public interface IVcModuleArgument { - private boolean done = false; + public Collection evaluateArgument(final Jep instance, String argName) throws JepException; - private Object result; - - @Override - public void requestComplete(Object result) { - done = true; - this.result = result; - } - - public boolean isDone() { - return done; - } - - public Object getResult() { - return result; - } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModule.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModule.java new file mode 100644 index 0000000000..3919ae81cf --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModule.java @@ -0,0 +1,564 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.core.parm.vcparm; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jep.JepException; + +import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory; +import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory.OriginType; +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.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.discrete.DiscreteKey; +import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DBit; +import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DByte; +import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DFloat; +import com.raytheon.uf.common.dataplugin.gfe.slice.DiscreteGridSlice; +import com.raytheon.uf.common.dataplugin.gfe.slice.IGridSlice; +import com.raytheon.uf.common.dataplugin.gfe.slice.ScalarGridSlice; +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.python.PyConstants; +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.viz.gfe.GFEException; +import com.raytheon.viz.gfe.core.DataManager; +import com.raytheon.viz.gfe.core.IParmManager; +import com.raytheon.viz.gfe.core.griddata.IGridData; +import com.raytheon.viz.gfe.core.parm.Parm; + +/** + * Virtual Calculated Module. Serves as interface between the VCParm and the + * actual python algorithms. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Oct 17, 2011            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class VCModule { + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(VCModule.class); + + public class DepParmInv { + + private ParmID parmID; + + private List times; + + public DepParmInv(ParmID pid, List trs) { + this.parmID = pid; + this.times = trs; + } + + public ParmID getParmID() { + return parmID; + } + + public List getTimes() { + return times; + } + + @Override + public String toString() { + StringBuilder tmp = new StringBuilder(); + tmp.append("(pid="); + tmp.append(parmID.toString()); + tmp.append(",times="); + tmp.append(times.toString()); + tmp.append(')'); + + return tmp.toString(); + } + } + + public class VCInventory { + + private TimeRange gridTimeRange; + + private List depParmInv; + + public VCInventory(TimeRange gridTimeRange, List depParmInv) { + this.gridTimeRange = gridTimeRange; + this.depParmInv = depParmInv; + } + + public TimeRange getGridTimeRange() { + return gridTimeRange; + } + + public List getDepParmInv() { + return depParmInv; + } + + @Override + public String toString() { + StringBuilder tmp = new StringBuilder(); + tmp.append("gtr="); + tmp.append(gridTimeRange.toString()); + tmp.append(",dpi="); + tmp.append(depParmInv.toString()); + + return tmp.toString(); + } + } + + private Throwable error; + + private GridParmInfo gpi; + + private VCModuleJob python; + + private DataManager dataMgr; + + private IParmManager parmMgr; + + private String id; + + public VCModule(DataManager dataMgr, IParmManager parmMgr, final File module) { + this.dataMgr = dataMgr; + this.parmMgr = parmMgr; + this.id = module.getName().split("\\.(?=[^\\.]+$)")[0]; + this.python = new VCModuleJob(this.dataMgr); + this.python.schedule(); + } + + public void dispose() { + this.python.cancel(); + } + + public boolean isValid() { + return (this.error == null); + } + + public Throwable getErrorString() { + Throwable rVal = error; + error = null; + return rVal; + } + + private List getMethodArgs(String method) throws Throwable { + // statusHandler.debug("getMethodArgs: " + id); + + Map args = new HashMap(); + args.put(PyConstants.METHOD_NAME, method); + VCModuleRequest req = new VCModuleRequest(id, "getMethodArgs", args); + python.enqueue(req); + + Object result = req.getResult(); + String[] argNames = (String[]) result; + return Arrays.asList(argNames); + } + + public Collection dependentParms() { + Collection rval = new ArrayList(); + + try { + Collection parameters = getMethodArgs("getInventory"); + for (String parmName : parameters) { + ParmID pid = parmMgr.fromExpression(parmName); + if (pid.isValid()) { + rval.add(pid); + } else { + throw new IllegalArgumentException( + "Can't find Weather Element for " + parmName); + } + } + } catch (Throwable t) { + error = t; + // statusHandler.handle(Priority.DEBUG, "dependentParms: " + id + // + " error", t); + return Collections.emptyList(); + } + + return rval; + } + + private long[] encodeTR(final TimeRange tr) { + long[] ptime = { tr.getStart().getTime(), tr.getEnd().getTime() }; + return ptime; + } + + private List pyInventory(Parm p) { + IGridData[] gridInv = p.getGridInventory(); + List inv = new ArrayList(gridInv.length); + for (IGridData gd : gridInv) { + inv.add(encodeTR(gd.getGridTime())); + } + + return inv; + } + + private Object[] encodeGD(IGridData gd) { + Object[] item = new Object[3]; + item[0] = encodeTR(gd.getGridTime()); + + // since we have to go through a bunch of hoops in VCModuleScript to get + // the IGridData in python-useable format, no need doing anything here + // but storing the data + item[1] = gd; + + // add a mask indicating the set of valid points. Note for all data + // other than ISC data, the mask is all points. ISC data values depend + // upon the masking of the Grid Data History. + Grid2DBit validBits; + if (gd.getParm().isIscParm()) { + List hs = gd.getHistorySites(); + validBits = dataMgr.getRefManager().siteGridpoints(hs, true); + } else { + validBits = dataMgr.getRefManager().fullRefSet().getGrid(); + } + item[2] = validBits; + + return item; + } + + @SuppressWarnings("unchecked") + private IGridSlice decodeGD(Object o, VCInventory invEntry) + throws GFEException, JepException { + TimeRange tr = invEntry.getGridTimeRange(); + List gdh = calcHistory(invEntry); + if (!isValid()) { + throw new GFEException(getErrorString()); + } + + GridParmInfo gpi = getGpi(); + switch (gpi.getGridType()) { + case SCALAR: + return new ScalarGridSlice(tr, gpi, gdh, (Grid2DFloat) o); + case VECTOR: + Grid2DFloat[] s = (Grid2DFloat[]) o; + return new VectorGridSlice(tr, gpi, gdh, s[0], s[1]); + case WEATHER: + Object[] wxGrid = (Object[]) o; + List key = new ArrayList(); + List pkey = (List) wxGrid[1]; + for (String wKey : pkey) { + key.add(new WeatherKey(gpi.getParmID().getDbId().getSiteId(), + wKey)); + } + return new WeatherGridSlice(tr, gpi, gdh, (Grid2DByte) wxGrid[0], + key); + case DISCRETE: + Object[] discGrid = (Object[]) o; + List keys = new ArrayList(); + List pkeys = (List) discGrid[1]; + for (String dKey : pkeys) { + keys.add(new DiscreteKey(gpi.getParmID().getDbId().getSiteId(), + dKey, gpi.getParmID())); + } + return new DiscreteGridSlice(tr, gpi, gdh, + (Grid2DByte) discGrid[0], keys); + default: + statusHandler.handle(Priority.EVENTB, "Unknown parm type: " + + gpi.getGridType().toString()); + break; + } + + return null; + } + + @SuppressWarnings("unchecked") + private TimeRange decodeTR(Object o) { + List ptr = (List) o; + return new TimeRange(ptr.get(0), ptr.get(1)); + } + + @SuppressWarnings("unchecked") + public List getInventory() { + // statusHandler.debug("getInventory: " + id); + final List rval = new ArrayList(); + + try { + List args = getMethodArgs("getInventory"); + Map cargs = new HashMap(args.size()); + List pargs = new ArrayList(args.size()); + + for (String arg : args) { + ParmID pid = parmMgr.fromExpression(arg); + Parm tp = parmMgr.getParm(pid); + if (tp == null) { + throw new IllegalArgumentException( + "Can't locate Weather Element: " + arg); + } + cargs.put(arg, new GetVcModInventoryArg(pyInventory(tp))); + pargs.add(tp); + } + + VCModuleRequest req = new VCModuleRequest(id, "getInventory", cargs); + python.enqueue(req); + Object reqResult = req.getResult(); + + // what's returned from the script here is a list of tuples. + // Each tuple contains: + // 1. A TimeRange. + // 2. A list of TimeRanges that correspond to the Fcst grids that + // should be used for that time + // 3. A list of TimeRanges that correspond to the ISC grids that + // should be used for that time + List> result = (List>) reqResult; + for (List item : result) { + List dpi = new ArrayList(); + for (int i = 1; i < item.size(); i++) { + List ditem = (List) item.get(i); + List trs = new ArrayList(ditem.size()); + for (Object tr : ditem) { + trs.add(decodeTR(tr)); + } + dpi.add(new DepParmInv(pargs.get(i - 1).getParmID(), trs)); + } + rval.add(new VCInventory(decodeTR(item.get(0)), dpi)); + } + + } catch (Throwable t) { + error = t; + } + + return rval; + } + + private List encodeGDH(final List gdh) { + List l = new ArrayList(gdh.size()); + for (GridDataHistory hist : gdh) { + l.add(hist.getCodedString()); + } + + return l; + } + + @SuppressWarnings("unchecked") + private List decodeGDH(final Object o) { + List s = (List) o; + List rval = new ArrayList(s.size()); + + for (String entry : s) { + GridDataHistory gdh = new GridDataHistory(entry); + rval.add(gdh); + } + + return rval; + } + + @SuppressWarnings("unchecked") + public List calcHistory(final VCInventory invEntry) { + // statusHandler.debug("calcHistory: " + id + " " + + // invEntry.toString()); + + // commenting out this python call because it is completely + // superfluous--all the baseline VCMODULE files have a calcHistory + // method so there's no point in checking and it saves a call into the + // VCModuleJob queue. If at some point there's a desire to support + // user/site-defined modules, this check should probably return. + // TODO: Reimplement using a call to BaseGfePyController.hasMethod(). + + // boolean hasattr = false; + // try { + // hasattr = module.hasAttr("calcHistory"); + // } catch (JepException e) { + // // swallow exception and move on + // statusHandler.handle(Priority.EVENTB, + // "Could not retrieve calcHistory attribute", e); + // } + + // if (hasattr) { + try { + final List dpi = invEntry.getDepParmInv(); + List args = getMethodArgs("calcHistory"); + Map cargs = new HashMap(args.size()); + + for (String arg : args) { + Parm tp = parmMgr.getParm(parmMgr.fromExpression(arg)); + if (tp != null) { + List l = new ArrayList(); + for (DepParmInv dpiEntry : dpi) { + if (dpiEntry.getParmID().equals(tp.getParmID())) { + for (TimeRange tr : dpiEntry.getTimes()) { + IGridData gd = tp + .overlappingGrid(tr.getStart()); + if (gd == null) { + throw new IllegalArgumentException( + "Unable to retrieve overlapping grid for parm: " + + tp.getParmID().toString() + + " for time: " + + tr.toString()); + } + + Object[] tl = new Object[2]; + tl[0] = encodeTR(gd.getGridTime()); + tl[1] = encodeGDH(Arrays + .asList(gd.getHistory())); + l.add(tl); + } + } + } + + cargs.put(arg, new CalcVcModHistoryArg(l)); + } else { + throw new IllegalArgumentException("Unable to find parm " + + arg); + } + } + + VCModuleRequest req = new VCModuleRequest(id, "calcHistory", cargs); + python.enqueue(req); + Object reqResult = req.getResult(); + + List result = (List) reqResult; + return decodeGDH(result); + + } catch (Throwable t) { + error = t; + } + // } + + // the default + return Arrays.asList(new GridDataHistory(OriginType.CALCULATED, + getGpi().getParmID(), invEntry.getGridTimeRange())); + } + + public IGridSlice calcGrid(VCInventory invEntry) { + // statusHandler.debug("calcGrid: " + id + " " + invEntry.toString()); + + final List dpi = invEntry.getDepParmInv(); + + try { + List args = getMethodArgs("calcGrid"); + Map cargs = new HashMap(args.size()); + + for (String arg : args) { + ParmID id = parmMgr.fromExpression(arg); + Parm tp = parmMgr.getParm(id); + if (tp != null) { + List l = new ArrayList(); + + for (DepParmInv dpiEntry : dpi) { + if (dpiEntry.getParmID().equals(tp.getParmID())) { + for (TimeRange tr : dpiEntry.getTimes()) { + IGridData gd = tp + .overlappingGrid(tr.getStart()); + if (gd == null) { + throw new IllegalArgumentException( + "Unable to retrieve overlapping grid for parm: " + + tp.getParmID().toString() + + " for time: " + + tr.toString()); + } + + l.add(encodeGD(gd)); + } + } + } + + cargs.put(arg, new CalcVcModGridArg(l)); + } else { + throw new IllegalArgumentException("Unable to find parm " + + arg); + } + } + + VCModuleRequest req = new VCModuleRequest(id, "calcGrid", cargs, + getGpi().getGridType()); + python.enqueue(req); + Object reqResult = req.getResult(); + + return decodeGD(reqResult, invEntry); + + } catch (Throwable t) { + error = t; + } + + return null; + } + + @SuppressWarnings("unchecked") + public GridParmInfo getGpi() { + if (this.gpi != null) { + return this.gpi; + } + // statusHandler.debug("getGpi(): " + id); + + try { + VCModuleRequest req = new VCModuleRequest(id, "getWEInfo", null); + python.enqueue(req); + Object reqResult = req.getResult(); + + List> result = (List>) reqResult; + + List s = result.get(1); + String site = parmMgr.getMutableDatabase().getSiteId(); + DatabaseID dbid = new DatabaseID(site, DataType.GRID, s.get(1) + .toString(), s.get(0).toString(), DatabaseID.NO_MODEL_TIME); + + s = result.get(2); + TimeConstraints tc = new TimeConstraints((Integer) s.get(0), + (Integer) s.get(1), (Integer) s.get(2)); + + s = result.get(0); + ParmID pid = new ParmID(s.get(0).toString(), dbid); + GridType type = GridType.NONE; + try { + type = GridType.valueOf(s.get(1).toString().toUpperCase()); + } catch (IllegalArgumentException e) { + // just want to swallow the exception here as we've already + // defaulted type to NONE + statusHandler.handle(Priority.EVENTB, + "Invalid GridType specified: " + s.get(1).toString()); + } + + // Double check for all the various valid parm lengths from + // serverConfig + GridParmInfo gpi = new GridParmInfo(pid, + parmMgr.compositeGridLocation(), type, s.get(2).toString(), + s.get(3).toString(), (Float) s.get(5), (Float) s.get(4), + (Integer) s.get(6), false, tc, (Boolean) s.get(7)); + this.gpi = gpi; + + } catch (Throwable t) { + error = t; + } + + return this.gpi; + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleController.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleController.java new file mode 100644 index 0000000000..2a45629928 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleController.java @@ -0,0 +1,234 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.core.parm.vcparm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import jep.JepException; + +import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; +import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DByte; +import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DFloat; +import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil; +import com.raytheon.uf.common.python.PyConstants; +import com.raytheon.viz.gfe.BaseGfePyController; +import com.raytheon.viz.gfe.core.DataManager; + +/** + * A PythonScript subclass that replaces the Python/C++ interface that was + * available to AWIPS1's VCModule class. Primarily used for + * Python->Java data type conversions. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Nov 17, 2011            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class VCModuleController extends BaseGfePyController { + + private static final String CLASS_NAME = "VCParm"; + + private List tempGridNames; + + /** + * Constructor. + * + * @param aFilePath + * the path to the python script + * @param anIncludePath + * the python include path, with multiple directories being + * separated by ":" + * @param aClassLoader + * the Java classloader to use for importing Java classes inside + * python + * @param dataMgr + * TODO + * @throws JepException + */ + protected VCModuleController(String aFilePath, String anIncludePath, + ClassLoader aClassLoader, DataManager dataMgr) throws JepException { + super(aFilePath, anIncludePath, aClassLoader, dataMgr, CLASS_NAME); + this.tempGridNames = new ArrayList(); + + String scriptPath = GfePyIncludeUtil.getVCModulesIncludePath(); + jep.eval(INTERFACE + " = VCModuleInterface('" + scriptPath + "')"); + } + + /** + * Retrieves a list of argument names for the specified Python method. + * + * @param moduleName + * TODO + * @param method + * The name of the method. + * @return List of argument names for the specified Python method, except + * for "self". + * @throws JepException + */ + public List getMethodArgs(String moduleName, String method) + throws JepException { + String[] argNames = getMethodArguments(moduleName, method); + List retVal = new ArrayList(argNames.length); + for (String arg : argNames) { + if (!arg.equals("self")) { + retVal.add(arg); + } + } + + return retVal; + } + + public Object executeMethod(String moduleName, String methodName, + Map args, GridType type) throws JepException { + if (!isInstantiated(moduleName)) { + instantiatePythonTool(moduleName); + } + + args.put(PyConstants.METHOD_NAME, methodName); + args.put(PyConstants.MODULE_NAME, moduleName); + args.put(PyConstants.CLASS_NAME, pythonClassName); + + internalExecute("runMethod", INTERFACE, args); + Object obj = null; + if (!methodName.equals("calcGrid")) { + jep.eval(RESULT + " = JUtil.pyValToJavaObj(" + RESULT + ")"); + obj = jep.getValue(RESULT); + } else { + obj = decodeGD(type); + } + jep.eval(RESULT + " = None"); + + return obj; + } + + /** + * Override of the evaluateArgument method which handles the + * custom argument structures defined in VCModule. Important so + * that we can convert the Java datatypes to Python native objects (and + * numpy arrays for the grids). + * + * @param argName + * The argument name. + * @param argValue + * the value of the argument + * + * @see com.raytheon.uf.common.python.PythonInterpreter#evaluateArgument(java + * .lang.String, java.lang.Object) + */ + @Override + protected void evaluateArgument(String argName, Object argValue) + throws JepException { + if (argValue instanceof IVcModuleArgument) { + IVcModuleArgument castedArg = (IVcModuleArgument) argValue; + Collection tempGrids = castedArg.evaluateArgument(jep, + argName); + tempGridNames.addAll(tempGrids); + } else { + super.evaluateArgument(argName, argValue); + } + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.python.PythonScript#cleanupArgs(java.util.List) + */ + @Override + protected void cleanupArgs(List args) throws JepException { + super.cleanupArgs(args); + for (String gridName : tempGridNames) { + jep.eval("del " + gridName); + } + tempGridNames.clear(); + } + + private Object decodeGD(GridType type) throws JepException { + Object result = null; + boolean resultFound = (Boolean) jep.getValue(RESULT + " is not None"); + + if (resultFound) { + int xDim, yDim = 0; + switch (type) { + case SCALAR: + float[] scalarData = (float[]) jep.getValue(RESULT + + ".astype(numpy.float32)"); + xDim = (Integer) jep.getValue(RESULT + ".shape[1]"); + yDim = (Integer) jep.getValue(RESULT + ".shape[0]"); + result = new Grid2DFloat(xDim, yDim, scalarData); + break; + case VECTOR: + float[] mag = (float[]) jep.getValue(RESULT + + "[0].astype(numpy.float32)"); + float[] dir = (float[]) jep.getValue(RESULT + + "[1].astype(numpy.float32)"); + xDim = (Integer) jep.getValue(RESULT + "[0].shape[1]"); + yDim = (Integer) jep.getValue(RESULT + "[0].shape[0]"); + + Grid2DFloat magGrid = new Grid2DFloat(xDim, yDim, mag); + Grid2DFloat dirGrid = new Grid2DFloat(xDim, yDim, dir); + result = new Grid2DFloat[] { magGrid, dirGrid }; + break; + case WEATHER: + case DISCRETE: + byte[] bytes = (byte[]) jep.getValue(RESULT + + "[0].astype(numpy.int8)"); + String[] keys = (String[]) jep.getValue(RESULT + "[1]"); + xDim = (Integer) jep.getValue(RESULT + "[0].shape[1]"); + yDim = (Integer) jep.getValue(RESULT + "[0].shape[0]"); + + Grid2DByte grid = new Grid2DByte(xDim, yDim, bytes); + List keysList = new ArrayList(); + Collections.addAll(keysList, keys); + + result = new Object[] { grid, keysList }; + break; + } + } + + return result; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.gfe.BaseGfePyController#instantiatePythonTool(java.lang + * .String) + */ + @Override + public void instantiatePythonTool(String moduleName) throws JepException { + Map instanceMap = getStarterMap(moduleName); + execute("instantiate", INTERFACE, instanceMap); + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleControllerFactory.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleControllerFactory.java new file mode 100644 index 0000000000..67bccdc1d3 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleControllerFactory.java @@ -0,0 +1,80 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.core.parm.vcparm; + +import jep.JepException; + +import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil; +import com.raytheon.uf.common.localization.LocalizationContext; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.python.PyUtil; +import com.raytheon.uf.common.util.FileUtil; +import com.raytheon.viz.gfe.core.DataManager; + +/** + * Factory for the VCModuleController class. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 20, 2011            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class VCModuleControllerFactory { + + /** + * A private constructor so that Java does not attempt to create one for us. + * As this class should not be instantiated, do not attempt to ever call + * this constructor; it will simply throw an AssertionError. + */ + private VCModuleControllerFactory() { + throw new AssertionError(); + } + + private static String getScriptPath() { + LocalizationContext baseCtx = PathManagerFactory.getPathManager() + .getContext(LocalizationType.COMMON_STATIC, + LocalizationLevel.BASE); + String scriptPath = GfePyIncludeUtil.getVCModUtilsLF(baseCtx).getFile() + .getPath(); + return FileUtil.join(scriptPath, "VCModuleInterface.py"); + } + + public static VCModuleController buildInstance(DataManager dataMgr) + throws JepException { + String includePath = PyUtil.buildJepIncludePath( + GfePyIncludeUtil.getVCModUtilsIncludePath(), + GfePyIncludeUtil.getVCModulesIncludePath(), + GfePyIncludeUtil.getCommonPythonIncludePath()); + + return new VCModuleController(getScriptPath(), includePath, + VCModuleControllerFactory.class.getClassLoader(), dataMgr); + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleJob.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleJob.java new file mode 100644 index 0000000000..d7a588d031 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleJob.java @@ -0,0 +1,134 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.core.parm.vcparm; + +import java.util.concurrent.TimeUnit; + +import jep.JepException; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +import com.raytheon.uf.common.dataplugin.gfe.StatusConstants; +import com.raytheon.uf.common.python.PyConstants; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.viz.core.jobs.AbstractQueueJob; +import com.raytheon.viz.gfe.core.DataManager; + +/** + * Job which allows VCModule python calls to run off a + * common thread. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 20, 2011            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class VCModuleJob extends AbstractQueueJob { + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(VCModuleJob.class); + + private VCModuleController python = null; + + private DataManager dataMgr; + + public VCModuleJob(DataManager dataMgr) { + super("GFE Virtual ISC Python executor"); + setSystem(true); + this.dataMgr = dataMgr; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime. + * IProgressMonitor) + */ + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + try { + python = VCModuleControllerFactory.buildInstance(dataMgr); + } catch (JepException e) { + return new Status(IStatus.ERROR, StatusConstants.PLUGIN_ID, + "Error initializing VCModule python object", e); + } + + while (!monitor.isCanceled()) { + VCModuleRequest request = null; + try { + request = queue.poll(1000L, TimeUnit.MILLISECONDS); + if (request != null) { + processRequest(request); + } + + // TODO: Reinstate this call, if we ever want to support + // dynamic editing of VCMODULE files through the + // Localization perspective. + // python.processFileUpdates(); + } catch (InterruptedException e) { + statusHandler.handle(Priority.PROBLEM, + "VC Module python thread interrupted.", e); + break; + } catch (Throwable t) { + // statusHandler.handle(Priority.DEBUG, + // "Error running VCModule method.", t); + request.setResult(t); + } + } + } finally { + + if (python != null) { + python.dispose(); + python = null; + } + } + + return Status.OK_STATUS; + } + + private void processRequest(VCModuleRequest request) throws JepException { + Object result = null; + + if (request.getMethodName().equals("getMethodArgs")) { + result = python.getMethodArguments(request.getModuleName(), + (String) request.getArgMap().get(PyConstants.METHOD_NAME)); + } else { + result = python.executeMethod(request.getModuleName(), + request.getMethodName(), request.getJepArgs(), + request.getType()); + } + + request.setResult(result); + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleRequest.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleRequest.java new file mode 100644 index 0000000000..252ce5bcab --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/vcparm/VCModuleRequest.java @@ -0,0 +1,134 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.core.parm.vcparm; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Semaphore; + +import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; +import com.raytheon.uf.viz.core.jobs.QueueJobRequest; + +/** + * TODO Add Description + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 20, 2011            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class VCModuleRequest extends QueueJobRequest { + + private String moduleName; + + private String methodName; + + private Map argMap; + + private GridType type; + + private Object result; + + private Semaphore completionMutex; + + public VCModuleRequest(String moduleName, String method, + Map argMap) { + this(moduleName, method, argMap, null); + } + + public VCModuleRequest(String moduleName, String method, + Map argMap, GridType type) { + this.moduleName = moduleName; + this.methodName = method; + this.argMap = argMap; + this.type = type; + this.completionMutex = new Semaphore(1); + // always leave the mutex locked until we're ready to return a result + try { + this.completionMutex.acquire(); + } catch (InterruptedException e) { + // don't care + } + } + + public String getModuleName() { + return moduleName; + } + + public String getMethodName() { + return methodName; + } + + public Map getArgMap() { + return argMap; + } + + public Map getJepArgs() { + if (argMap != null) { + return new HashMap(argMap); + } else { + return new HashMap(); + } + } + + public GridType getType() { + return type; + } + + /** + * Returns the result from executing this request. Because + * VCModuleRequests are executed asynchronously, this method + * blocks until the VCModule method has completed execution. + * + * @return The result of executing the request. + * @throws Throwable + * If an exception occurred while processing the request. + */ + public Object getResult() throws Throwable { + try { + // because we initially locked the mutex in the constructor, this + // will block until something has called setResult + completionMutex.acquire(); + if (!(result instanceof Throwable)) { + return result; + } else { + throw (Throwable) result; + } + } catch (InterruptedException e) { + throw e; + } finally { + completionMutex.release(); + } + } + + public void setResult(Object result) { + this.result = result; + completionMutex.release(); + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java index 5af32b1297..b88e275a96 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java @@ -51,7 +51,6 @@ import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.TimeRange; import com.raytheon.uf.viz.core.RGBColors; -import com.raytheon.uf.viz.core.VizApp; import com.raytheon.uf.viz.core.drawables.FillPatterns; import com.raytheon.viz.gfe.Activator; import com.raytheon.viz.gfe.GFEPreference; @@ -96,7 +95,7 @@ public class GridBar implements IMessageClient, IParmInventoryChangedListener, IGridVisibilityChangedListener, IActivatedParmChangedListener, IGridDataChangedListener, ISelectionTimeRangeChangedListener, IParameterSelectionChangedListener, ILockTableChangedListener, - IParmIDChangedListener, DisposeListener, Runnable + IParmIDChangedListener, DisposeListener { private static final transient IUFStatusHandler statusHandler = UFStatus @@ -309,6 +308,7 @@ public class GridBar implements IMessageClient, IParmInventoryChangedListener, this.canvas.addDisposeListener(this); } + @Override public void widgetDisposed(DisposeEvent e) { this.dispose(); } @@ -1339,20 +1339,7 @@ public class GridBar implements IMessageClient, IParmInventoryChangedListener, } public void redraw() { - if (this.display.getThread() == Thread.currentThread()) { - run(); - } else { - VizApp.runAsync(this); - } - } - - @Override - public void run() { - if (!canvas.isDisposed()) { - Rectangle bounds = getBounds(); - canvas.redraw(bounds.x, bounds.y, bounds.width, bounds.height, true); - // this.redrawCount++; - } + canvas.markDirty(getBounds()); } /** diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridCanvas.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridCanvas.java index 0262f5a0a5..f5aa2ab9d4 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridCanvas.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridCanvas.java @@ -31,7 +31,6 @@ import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.swt.SWT; @@ -51,6 +50,7 @@ import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.progress.UIJob; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; import com.raytheon.uf.common.dataplugin.gfe.db.objects.TimeConstraints; @@ -125,7 +125,7 @@ public class GridCanvas extends Canvas implements IMessageClient { private static Color SEPARATOR_COLOR = new Color(Display.getDefault(), RGBColors.getRGBColor("CornflowerBlue")); - private class ScrollJob extends Job { + private class ScrollJob extends UIJob { private int increment = 0; /** @@ -138,34 +138,72 @@ public class GridCanvas extends Canvas implements IMessageClient { public ScrollJob() { super("GridCanvasScrollJob"); + setSystem(true); } @Override - protected IStatus run(IProgressMonitor monitor) { - VizApp.runSync(new Runnable() { + public IStatus runInUIThread(IProgressMonitor monitor) { + Point p = scrolledComp.getOrigin(); + if ((increment < 0 && p.y > 0) + || (increment > 0 && p.y < (getSize().y - scrolledComp + .getClientArea().height))) { + p.y += increment; + scrolledComp.setOrigin(p); - @Override - public void run() { - Point p = scrolledComp.getOrigin(); - if ((increment < 0 && p.y > 0) - || (increment > 0 && p.y < (getSize().y - scrolledComp - .getClientArea().height))) { - p.y += increment; - scrolledComp.setOrigin(p); + if (increment < 0) { + selection.y += increment; + } + selection.height += Math.abs(increment); + setSelection(selection); - if (increment < 0) { - selection.y += increment; - } - selection.height += Math.abs(increment); - setSelection(selection); + schedule(100); + } else { + cancel(); + } + return Status.OK_STATUS; + } + } - schedule(100); - } else { - cancel(); - } + private class RepaintJob extends UIJob { + private Rectangle dirtyRect; + + public RepaintJob() { + super("GridCanvasRepaintJob"); + setSystem(true); + } + + public void markDirty(Rectangle rect) { + synchronized (this) { + if (this.dirtyRect != null) { + this.dirtyRect = this.dirtyRect.union(rect); + } else { + this.dirtyRect = rect; + } + } + this.schedule(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime + * .IProgressMonitor) + */ + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + + if (!GridCanvas.this.isDisposed() && dirtyRect != null) { + Rectangle rect; + synchronized (this) { + rect = dirtyRect; + dirtyRect = null; } - }); + GridCanvas.this.redraw(rect.x, rect.y, rect.width, rect.height, + true); + } + return Status.OK_STATUS; } @@ -198,6 +236,8 @@ public class GridCanvas extends Canvas implements IMessageClient { private ScrollJob scrollJob = new ScrollJob(); + private RepaintJob repaintJob = new RepaintJob(); + private ScrolledComposite scrolledComp; private Point stretchStart = new Point(0, 0); @@ -1120,4 +1160,8 @@ public class GridCanvas extends Canvas implements IMessageClient { } } } + + public void markDirty(Rectangle rect) { + this.repaintJob.markDirty(rect); + } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridManager.java index a43e2e57a3..1daf497a0d 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridManager.java @@ -44,6 +44,7 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Slider; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.progress.UIJob; import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.TimeRange; @@ -140,7 +141,7 @@ public class GridManager implements IGridManager { /** * Job to update the time display */ - private static class UpdateJob extends Job { + private static class UpdateJob extends UIJob { public UpdateJob() { super("GridManagerUpdate"); @@ -154,22 +155,15 @@ public class GridManager implements IGridManager { * IProgressMonitor) */ @Override - protected IStatus run(IProgressMonitor monitor) { + public IStatus runInUIThread(IProgressMonitor monitor) { // if any displays are active - if (activeList.size() > 0) { + if (!activeList.isEmpty()) { // update the state of all active displays - Display.getDefault().syncExec(new Runnable() { - - @Override - public void run() { - for (GridManager gm : activeList) { - gm.redraw(); - } - } - - }); - - this.schedule(60000); + for (GridManager gm : activeList) { + gm.redraw(); + } + long t = System.currentTimeMillis() % 60000; + this.schedule(60000 - t); } return Status.OK_STATUS; @@ -347,6 +341,7 @@ public class GridManager implements IGridManager { return widthIncrement; } + @Override public void expandTimeScale() { if (widthIncrement < GridManagerUtil.SECONDS_PER_PIXEL.length - 1) { widthIncrement++; @@ -355,6 +350,7 @@ public class GridManager implements IGridManager { } } + @Override public void contractTimeScale() { if (widthIncrement > 0) { widthIncrement--; @@ -642,6 +638,7 @@ public class GridManager implements IGridManager { * * @see com.raytheon.viz.gfe.gridmanager2.IGridManager#redraw() */ + @Override public void redraw() { if (!parent.isDisposed()) { timeScale.redraw(); @@ -793,6 +790,7 @@ public class GridManager implements IGridManager { /** * @return the lockSelectionTRtoTimeStep */ + @Override public boolean isLockSelectionTRtoTimeStep() { return lockSelectionTRtoTimeStep; } @@ -801,6 +799,7 @@ public class GridManager implements IGridManager { * @param lockSelectionTRtoTimeStep * the lockSelectionTRtoTimeStep to set */ + @Override public void setLockSelectionTRtoTimeStep(boolean lockSelectionTRtoTimeStep) { this.lockSelectionTRtoTimeStep = lockSelectionTRtoTimeStep; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/TimeScale.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/TimeScale.java index c1d26f9be3..fcb85f735f 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/TimeScale.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/TimeScale.java @@ -26,6 +26,9 @@ import java.util.Calendar; import java.util.Date; import java.util.TimeZone; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; @@ -48,11 +51,11 @@ import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.menus.CommandContributionItem; import org.eclipse.ui.menus.CommandContributionItemParameter; +import org.eclipse.ui.progress.UIJob; import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.TimeRange; import com.raytheon.uf.viz.core.RGBColors; -import com.raytheon.uf.viz.core.VizApp; import com.raytheon.viz.gfe.Activator; import com.raytheon.viz.gfe.GFEPreference; import com.raytheon.viz.gfe.GFEServerException; @@ -79,7 +82,7 @@ import com.raytheon.viz.gfe.ui.SelectTRMenu; * @version 1.0 */ -public class TimeScale extends Canvas implements IMessageClient, Runnable { +public class TimeScale extends Canvas implements IMessageClient { private static final int MINOR_TICK = 5; private static final int MAJOR_TICK = 10; @@ -107,6 +110,32 @@ public class TimeScale extends Canvas implements IMessageClient, Runnable { } } + private class RepaintJob extends UIJob { + + public RepaintJob() { + super("TimeScaleRepaintJob"); + setSystem(true); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime + * .IProgressMonitor) + */ + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + + if (!TimeScale.this.isDisposed()) { + TimeScale.this.redraw(); + } + + return Status.OK_STATUS; + } + + } + private final GridManager gridManager; private String[] displayedPeriods; @@ -125,10 +154,13 @@ public class TimeScale extends Canvas implements IMessageClient, Runnable { private MenuManager menuMgr; + private RepaintJob repaintJob; + @SuppressWarnings("unchecked") TimeScale(final Composite aParent, final GridManager aGridManager) { super(aParent, SWT.NONE); gridManager = aGridManager; + repaintJob = new RepaintJob(); displayedPeriods = TimeScaleDisplayedPeriodsPreference .getTimeScaleDisplayedPeriods(); @@ -513,18 +545,7 @@ public class TimeScale extends Canvas implements IMessageClient, Runnable { * */ private void refresh() { - if (this.getDisplay().getThread() == Thread.currentThread()) { - run(); - } else { - VizApp.runAsync(this); - } - } - - @Override - public void run() { - if (!isDisposed()) { - redraw(); - } + this.repaintJob.schedule(); } @Override diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJob.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJob.java index c32ac30365..ab3d246e95 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJob.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJob.java @@ -146,8 +146,8 @@ public class ProcedureJob extends AbstractQueueJob { if (request != null) { python.processFileUpdates(); processRequest(request); - if (request.getListener() != null) { - request.getListener().requestComplete(null); + if (request != null) { + request.requestComplete(null); } } else if (expireJob && ((instanceMap.get(dataMgr).size() > maxJobs) || (System @@ -158,8 +158,8 @@ public class ProcedureJob extends AbstractQueueJob { } catch (Throwable t) { statusHandler.handle(Priority.PROBLEM, "Error running tool ", t); - if (request != null && request.getListener() != null) { - request.getListener().requestComplete(t); + if (request != null) { + request.requestComplete(t); } } finally { request = null; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureRequest.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureRequest.java index b524a5a0b1..38ffa8adbb 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureRequest.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureRequest.java @@ -19,6 +19,8 @@ **/ package com.raytheon.viz.gfe.procedures; +import java.util.concurrent.Semaphore; + import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData; import com.raytheon.uf.common.time.TimeRange; import com.raytheon.uf.viz.core.jobs.QueueJobRequest; @@ -52,6 +54,21 @@ public class ProcedureRequest extends QueueJobRequest { private PreviewInfo preview; + private Semaphore completedSemaphore; + + private Object result; + + public ProcedureRequest() { + super(); + + completedSemaphore = new Semaphore(1); + try { + completedSemaphore.acquire(); + } catch (InterruptedException e) { + // don't care + } + } + public String getProcedureName() { return procedureName; } @@ -92,4 +109,20 @@ public class ProcedureRequest extends QueueJobRequest { this.preview = preview; } + public void requestComplete(Object result) { + this.result = result; + completedSemaphore.release(); + } + + public Object getResult() { + try { + completedSemaphore.acquire(); + return result; + } catch (InterruptedException e) { + return e; + } finally { + completedSemaphore.release(); + + } + } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureUtil.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureUtil.java index 3dba875fa8..5d93e61105 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureUtil.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureUtil.java @@ -75,7 +75,7 @@ public class ProcedureUtil { return pi; } - public static ProcedureRequest callFromSmartScript(final DataManager dm, + public static Object callFromSmartScript(final DataManager dm, final String procName, ReferenceData editArea, TimeRange timeRange, String varDict) { PreviewInfo pi = dm.getEditActionProcessor().prepareExecute( @@ -122,6 +122,7 @@ public class ProcedureUtil { }); } - return req; + ProcedureJob.enqueue(dm, req); + return req.getResult(); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/SmartUtil.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/SmartUtil.java index 6ddc9f7e29..64c0b9f65b 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/SmartUtil.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/SmartUtil.java @@ -128,7 +128,7 @@ public class SmartUtil { return pi; } - public static SmartToolRequest callFromSmartScript(final DataManager dm, + public static Object callFromSmartScript(final DataManager dm, final String toolName, final String elementName, ReferenceData editArea, TimeRange timeRange, String varDict, boolean emptyEditAreaFlag, List passErrors, @@ -176,6 +176,7 @@ public class SmartUtil { }); } - return req; + SmartToolJob.enqueue(dm, req); + return req.getResult(); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolFinishedListener.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolFinishedListener.java deleted file mode 100644 index 17b43261a0..0000000000 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolFinishedListener.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.viz.gfe.smarttool.script; - -import com.raytheon.uf.viz.core.jobs.IRequestCompleteListener; - -/** - * TODO Add Description - * - *
- * 
- * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Feb 23, 2010            njensen     Initial creation
- * 
- * 
- * - * @author njensen - * @version 1.0 - */ - -public class SmartToolFinishedListener implements - IRequestCompleteListener { - - private boolean done = false; - - private Object result; - - @Override - public void requestComplete(Object result) { - done = true; - this.result = result; - } - - public boolean isDone() { - return done; - } - - public Object getResult() { - return result; - } - -} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJob.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJob.java index 78459af599..05dcae6f9f 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJob.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJob.java @@ -155,9 +155,7 @@ public class SmartToolJob extends AbstractQueueJob { ea.getRefSet(), ea.getTimeRange(), request.getVarDict(), ea .getMissingDataMode(), monitor); - if (request.getListener() != null) { - request.getListener().requestComplete(null); - } + request.requestComplete(null); pjResult = Status.OK_STATUS; } catch (SmartToolException e) { @@ -184,14 +182,14 @@ public class SmartToolJob extends AbstractQueueJob { } catch (SmartToolException e) { statusHandler.handle(Priority.PROBLEM, "Error running tool ", e); - if (req != null && req.getListener() != null) { - req.getListener().requestComplete(e); + if (req != null) { + req.requestComplete(e); } } catch (Throwable t) { statusHandler.handle(Priority.PROBLEM, "Error running tool ", t); - if (req != null && req.getListener() != null) { - req.getListener().requestComplete(t); + if (req != null) { + req.requestComplete(t); } } finally { if (req != null && req.getPreview() != null) { diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolRequest.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolRequest.java index 9d1ca20583..ec73eaead4 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolRequest.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolRequest.java @@ -19,6 +19,8 @@ **/ package com.raytheon.viz.gfe.smarttool.script; +import java.util.concurrent.Semaphore; + import com.raytheon.uf.viz.core.jobs.QueueJobRequest; import com.raytheon.viz.gfe.core.parm.Parm; import com.raytheon.viz.gfe.smarttool.PreviewInfo; @@ -45,10 +47,23 @@ public class SmartToolRequest extends QueueJobRequest { private String varDict; - private SmartToolFinishedListener listener; - private PreviewInfo preview; + private Semaphore completedSemaphore; + + private Object result; + + public SmartToolRequest() { + super(); + + completedSemaphore = new Semaphore(1); + try { + completedSemaphore.acquire(); + } catch (InterruptedException e) { + // don't care + } + } + public Parm getInputParm() { return inputParm; } @@ -65,14 +80,6 @@ public class SmartToolRequest extends QueueJobRequest { this.varDict = varDict; } - public SmartToolFinishedListener getListener() { - return listener; - } - - public void setListener(SmartToolFinishedListener listener) { - this.listener = listener; - } - public PreviewInfo getPreview() { return preview; } @@ -81,4 +88,20 @@ public class SmartToolRequest extends QueueJobRequest { this.preview = preview; } + public void requestComplete(Object result) { + this.result = result; + completedSemaphore.release(); + } + + public Object getResult() { + try { + completedSemaphore.acquire(); + return result; + } catch (InterruptedException e) { + return e; + } finally { + completedSemaphore.release(); + + } + } } diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayCanvas.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayCanvas.java index aa9f98012d..41f25ba2a0 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayCanvas.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDisplayCanvas.java @@ -721,6 +721,8 @@ public class TimeSeriesDisplayCanvas extends TimeSeriesGraphCanvas implements gc.setBackground(this.white); } gc.drawString(NO_DATA_AVAILABLE, tmpX, tmpY); + gc.drawString(siteLabel +" fs=" + floodStage, GRAPHBORDER, + GRAPHBORDER - fontHeight * 2); this.dialog.getParentDialog().enableGraphButton(); this.dialog.getParentDialog().enableBothButton(); @@ -2624,4 +2626,4 @@ public class TimeSeriesDisplayCanvas extends TimeSeriesGraphCanvas implements public ArrayList getTraceArray() { return traceArray; } -} \ No newline at end of file +} diff --git a/cave/com.raytheon.viz.satellite/localization/menus/satellite/baseDerivedProductsImagery.xml b/cave/com.raytheon.viz.satellite/localization/menus/satellite/baseDerivedProductsImagery.xml index bd8dc025ff..1944a9e3d6 100644 --- a/cave/com.raytheon.viz.satellite/localization/menus/satellite/baseDerivedProductsImagery.xml +++ b/cave/com.raytheon.viz.satellite/localization/menus/satellite/baseDerivedProductsImagery.xml @@ -96,7 +96,7 @@ + titleText="------ AMSU and SSM/I + GPS ------" id="blendedofAMSUAndSSMIDataLine"/> /satellite/%/NESDIS/Miscellaneous/Supernational/Sounder_Based_Derived_Precipitable_Water_(PW) diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AWIPSHeaderBlockDlg.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AWIPSHeaderBlockDlg.java index 8be682c253..0d74cb925e 100755 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AWIPSHeaderBlockDlg.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/AWIPSHeaderBlockDlg.java @@ -84,6 +84,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * 04/14/2010 4734 mhuang Corrected StdTextProduct import * dependency * 06/28/2010 4639 cjeanbap Allow user to create a new text product. + * + * 01/26/2012 14468 D.Friedman Fix initial BBB field selection. * * * @author lvenable @@ -258,32 +260,10 @@ public class AWIPSHeaderBlockDlg extends CaveSWTDialog implements // Create the message/indicator group combo box. gd = new GridData(70, SWT.DEFAULT); - bbbCboBx = new Combo(wmoIdComp, SWT.DROP_DOWN); + bbbCboBx = new Combo(wmoIdComp, SWT.DROP_DOWN|SWT.READ_ONLY); bbbCboBx.setItems(BBB_LIST); bbbCboBx.select(3); bbbCboBx.setLayoutData(gd); - bbbCboBx.addVerifyListener(new VerifyListener() { - - @Override - public void verifyText(VerifyEvent e) { - if (e.text.length() == 3) { - if (e.start != 0 || e.end != 0) { - e.doit = false; - } else { - e.doit = false; - for (String s : BBB_LIST) { - if (s.equalsIgnoreCase(e.text)) { - e.doit = true; - e.text = s; - break; - } - } - } - } else if (e.text.length() != 0) { - e.doit = false; - } - } - }); bbbCboBx.addFocusListener(new FocusListener() { @@ -304,32 +284,11 @@ public class AWIPSHeaderBlockDlg extends CaveSWTDialog implements // Create the message/indicator version group combo box. gd = new GridData(70, SWT.DEFAULT); - bbbVerCboBx = new Combo(wmoIdComp, SWT.DROP_DOWN); + bbbVerCboBx = new Combo(wmoIdComp, SWT.DROP_DOWN|SWT.READ_ONLY); bbbVerCboBx.setItems(CHAR_LIST); bbbVerCboBx.select(0); bbbVerCboBx.setLayoutData(gd); - bbbVerCboBx.addVerifyListener(new VerifyListener() { - - @Override - public void verifyText(VerifyEvent e) { - e.text = e.text.trim().toUpperCase(); - if (e.text.length() > 1) { - e.doit = false; - } else if (e.text.length() == 1 && (e.start != 0 || e.end != 0)) { - e.doit = false; - } else if (e.text.length() == 1) { - e.doit = false; - for (String s : CHAR_LIST) { - if (s.equals(e.text)) { - e.doit = true; - break; - } - } - } - } - }); - bbbVerCboBx.addFocusListener(new FocusListener() { @Override diff --git a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/statusline/TimeDisplay.java b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/statusline/TimeDisplay.java index adadedaf05..1127a0d4c4 100644 --- a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/statusline/TimeDisplay.java +++ b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/statusline/TimeDisplay.java @@ -40,6 +40,7 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.progress.UIJob; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -74,7 +75,7 @@ public class TimeDisplay extends ContributionItem { /** * Job to update the time display */ - private static class TimeUpdateJob extends Job { + private static class TimeUpdateJob extends UIJob { /** * @param name @@ -91,22 +92,16 @@ public class TimeDisplay extends ContributionItem { * IProgressMonitor) */ @Override - protected IStatus run(IProgressMonitor monitor) { + public IStatus runInUIThread(IProgressMonitor monitor) { // if any displays are active - if (activeList.size() > 0) { + if (!activeList.isEmpty()) { // update the state of all active displays - Display.getDefault().syncExec(new Runnable() { + for (TimeDisplay td : activeList) { + td.update(); + } - @Override - public void run() { - for (TimeDisplay td : activeList) { - td.update(); - } - } - - }); - - this.schedule(1000); + long t = System.currentTimeMillis() % 60000; + this.schedule(60000 - t); } return Status.OK_STATUS; diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/BulletListManager.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/BulletListManager.java index ff0032b560..d6f25e9212 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/BulletListManager.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/BulletListManager.java @@ -31,6 +31,9 @@ import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration; * ------------ ---------- ----------- -------------------------- * Oct 5, 2011 jsanchez Initial creation * + * 01/26/2012 14466 D.Friedman Fix parseString processing. + * 01/26/2012 14469 D.Friedman Fix followup bullet processing + * * * * @author jsanchez @@ -145,24 +148,36 @@ public class BulletListManager { return; } - String warningText = record.getRawmessage().replaceAll("\n", " ") - .replaceAll(" ", " ").replaceAll(" ", " ") - .replaceAll(" ", " "); + String warningText = record.getRawmessage().replaceAll("\\s+", " "); /* Test 'showString' to determine if the bullet is to be hidden */ - ArrayList displayedBullets = new ArrayList(); - for (Bullet b : configuration.getBullets()) { - if (b != null - && (b.getShowString() == null || warningText.contains(b - .getShowString()))) { - displayedBullets.add(b); - } + ArrayList displayedBullets = null; + ArrayList displayedDamInfoBullets = null; + + for (int pass = 0; pass < 2; ++pass) { + Bullet[] sourceList = pass == 0 ? + configuration.getBullets() : + configuration.getDamInfoBullets(); + ArrayList resultList = new ArrayList(); + if (sourceList != null) { + for (Bullet b : sourceList) { + if (b != null + && (b.getShowString() == null || + selectBulletFromFollowup(b.getShowString(), warningText))) { + resultList.add(b); + } + } + } + if (pass == 0) + displayedBullets = resultList; + else + displayedDamInfoBullets = resultList; } /* Sets up the appropriate bullet groups */ recreateBullets( displayedBullets.toArray(new Bullet[displayedBullets.size()]), - configuration.getDamInfoBullets()); + displayedDamInfoBullets.toArray(new DamInfoBullet[displayedDamInfoBullets.size()])); if (configuration.getLockedGroupsOnFollowup() != null) { for (String lockedGroup : configuration.getLockedGroupsOnFollowup() @@ -177,13 +192,13 @@ public class BulletListManager { for (int i = 0; i < bullets.length; i++) { Bullet bullet = bullets[i]; if (selectBulletFromFollowup(bullet.getParseString(), warningText)) { - updateSelectedIndices(i, false); + updateSelectedIndices(i, false, true); } if (bullet.getFloodSeverity() != null && bullet.getFloodSeverity().equals( record.getFloodSeverity())) { - updateSelectedIndices(i, false); + updateSelectedIndices(i, false, true); } } } @@ -206,6 +221,20 @@ public class BulletListManager { * @param isFollowup */ public void updateSelectedIndices(int selectionIndex, boolean isFollowup) { + updateSelectedIndices(selectionIndex, isFollowup, false); + } + + /** + * Updates the list of selected of indices by including or removing indices + * depending on if the bullet is already selected or is a part of a group of + * bullets. If selectUnconditionally is true, sets (instead of toggles) + * bullets. + * + * @param selectionIndex + * @param isFollowup + * @param selectUnconditionally + */ + public void updateSelectedIndices(int selectionIndex, boolean isFollowup, boolean selectUnconditionally) { if (selectionIndex < 0 || selectionIndex >= bullets.length || titleGroup.contains(selectionIndex)) { return; @@ -214,14 +243,20 @@ public class BulletListManager { Bullet bullet = bullets[selectionIndex]; String group = bullet.getBulletGroup(); - if (group == null) { - if (selectedIndices.contains(selectionIndex)) { - selectedIndices.remove(selectionIndex); - } else { - selectedIndices.add(selectionIndex); - } - return; - } + if (group == null) { + if (selectUnconditionally) { + if (!selectedIndices.contains(selectionIndex)) + selectedIndices.add(selectionIndex); + } else { + // toggle + if (selectedIndices.contains(selectionIndex)) { + selectedIndices.remove(selectionIndex); + } else { + selectedIndices.add(selectionIndex); + } + } + return; + } /* Can't change selection when a part of a locked group on a follow up */ if (isFollowup && lockedGroups.contains(group.toLowerCase())) { @@ -262,19 +297,30 @@ public class BulletListManager { } List groupIndices = bulletGroups.get(group); - for (Integer index : groupIndices) { - /* - * Unselect items in a group except for the latest selection in the - * group - */ - if (!selectedIndices.contains(selectionIndex) - && index.equals(selectionIndex)) { - selectedIndices.add(index); - } else { - selectedIndices.remove(index); - clearScenarios(index); - } - } + for (Integer index : groupIndices) { + /* + * Unselect items in a group except for the latest selection in the + * group + */ + if (selectUnconditionally) { + if (index.equals(selectionIndex)) { + if (!selectedIndices.contains(selectionIndex)) + selectedIndices.add(index); + } else { + selectedIndices.remove(index); + clearScenarios(index); + } + } else { + // toggles off if selected + if (!selectedIndices.contains(selectionIndex) + && index.equals(selectionIndex)) { + selectedIndices.add(index); + } else { + selectedIndices.remove(index); + clearScenarios(index); + } + } + } } /** @@ -373,7 +419,7 @@ public class BulletListManager { } boolean selectBullet = true; - for (String p : parseString.toUpperCase().replaceAll(" ", " ") + for (String p : parseString.toUpperCase().replaceAll("\\s+", " ") .split("\",")) { p = p.replace("\"", ""); if ((p.startsWith("-") && warningText.contains(p.substring(1))) diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/gfe/vcmodule/utility/VCModuleInterface.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/gfe/vcmodule/utility/VCModuleInterface.py new file mode 100644 index 0000000000..8d0b12b487 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/gfe/vcmodule/utility/VCModuleInterface.py @@ -0,0 +1,59 @@ +## +# 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. +## + +# +# Globally import and sets up instances of the smart tool scripts. +# Designed to be used as a master controller for inspecting and running +# smart tools from Java. +# +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 10/21/08 njensen Initial Creation. +# +# +# + +import numpy +import sys + +import JUtil +import MasterInterface + + +class VCModuleInterface(MasterInterface.MasterInterface): + + def __init__(self, scriptPath): + MasterInterface.MasterInterface.__init__(self) + self.importModules(scriptPath) + + def getMethodArgNames(self, moduleName, className, methodName): + from java.util import ArrayList + args = self.getMethodArgs(moduleName, className, methodName) + argList = ArrayList() + for a in args: + argList.add(a) + return argList + + def getMethodArgs(self, moduleName, className, methodName): + return MasterInterface.MasterInterface.getMethodArgs(self, moduleName, className, methodName)[1:] \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianNHPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianNHPostProcessor.java new file mode 100644 index 0000000000..4a7a50b210 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianNHPostProcessor.java @@ -0,0 +1,182 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ + +package com.raytheon.edex.plugin.grib.decoderpostprocessors; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.raytheon.edex.plugin.grib.dao.GribDao; +import com.raytheon.uf.common.dataplugin.PluginException; +import com.raytheon.uf.common.dataplugin.grib.GribRecord; +import com.raytheon.uf.common.dataplugin.grib.exception.GribException; +import com.raytheon.uf.edex.database.DataAccessLayerException; +import com.raytheon.uf.edex.database.query.DatabaseQuery; + +/** + * Grib post processor implementation to generate 6-hr precipitation grids from + * run accumulated total precipitation + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * 1/18/2012                porricel    Initial Creation
+ * 
+ * 
+ * + * @author bphillip + * @version 1 + */ +public class CanadianNHPostProcessor extends SixHrPrecipGridProcessor { + + @Override + public GribRecord[] process(GribRecord record) throws GribException { + // Post process the data if this is a Total Precipitation grid + if (record.getModelInfo().getParameterAbbreviation().equals("TPrun")) { + return super.process(record); + } + return new GribRecord[] { record }; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + protected List getPrecipInventory(Date refTime) + throws GribException { + GribDao dao = null; + try { + dao = new GribDao(); + } catch (PluginException e) { + throw new GribException("Error instantiating grib dao!", e); + } + DatabaseQuery query = new DatabaseQuery(GribRecord.class); + query.addQueryParam("modelInfo.parameterAbbreviation", "TPrun"); + query.addQueryParam("modelInfo.modelName", "Canadian-NH"); + query.addQueryParam("dataTime.refTime", refTime); + query.addOrder("dataTime.fcstTime", true); + try { + return (List) dao.queryByCriteria(query); + } catch (DataAccessLayerException e) { + throw new GribException( + "Error getting Precip inventory for Canadian-NH!", e); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + protected List getPrecip6hrInventory(Date refTime) + throws GribException { + GribDao dao = null; + try { + dao = new GribDao(); + } catch (PluginException e) { + throw new GribException("Error instantiating grib dao!", e); + } + DatabaseQuery query = new DatabaseQuery(GribRecord.class); + query.addQueryParam("modelInfo.parameterAbbreviation", "TP6hr"); + query.addQueryParam("modelInfo.modelName", "Canadian-NH"); + query.addQueryParam("dataTime.refTime", refTime); + query.addReturnedField("dataTime.fcstTime"); + try { + return (List) dao.queryByCriteria(query); + } catch (DataAccessLayerException e) { + throw new GribException( + "Error getting Precip inventory for Canadian-NH!", e); + } + } + + /** + * Generates the 6 hour accumulated grid from the run accumulated + * precipitation grids. This function will look in the inventory and + * generate any 6 hr grids that can be generated. + * + * @param record + * The grib record for which to generate the 6 hour accumulated + * precipitation grid + * @return The generated 6-hr precipitation grids + * @throws GribException + */ + protected synchronized GribRecord[] generate6hrPrecipGrids(GribRecord record) + throws GribException { + + // The current run accumulated precipitation grid inventory in the + // database + List precipInventory = getPrecipInventory(record + .getDataTime().getRefTime()); + + // The current 6-hr precipitation grid inventory in the database + List precip6hrInventory = getPrecip6hrInventory(record + .getDataTime().getRefTime()); + + // Adds the current record to the precip inventory + float[] currentData = (float[]) record.getMessageData(); + record.setMessageData(currentData); + precipInventory.add(record); + + // Examine each grid in the inventory and generate the 6hr precipitation + // grid if possible + List generatedRecords = new ArrayList(); + for (int i = 0; i < precipInventory.size(); i++) { + // Check if the 6hr precipitation grid has already been produced + if (!precip6hrInventory.contains(precipInventory.get(i) + .getDataTime().getFcstTime())) { + // If the precipitation grid has not been produced, generate it + List generated6hrPrecips = generate6hrPrecip( + precipInventory.get(i), precipInventory, + precip6hrInventory); + for (GribRecord newRecord : generated6hrPrecips) { + // Add the generated grid to the current inventory + if (newRecord != null) { + precip6hrInventory.add(newRecord.getDataTime() + .getFcstTime()); + generatedRecords.add(newRecord); + } + } + } + } + + return generatedRecords.toArray(new GribRecord[] {}); + } + + /** + * Calculates the new data by subtracting the previous inventory data from + * the current data + * + * @param inventoryData + * The data from the previous precipitation record + * @param newData + * The data from the current precipitation record + */ + protected void calculatePrecipValues(float[] inventoryData, float[] newData) { + for (int i = 0; i < inventoryData.length; i++) { + newData[i] = newData[i] - inventoryData[i]; + if (newData[i] < 0) { + newData[i] = 0; + } + } + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianRegPostProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianRegPostProcessor.java new file mode 100644 index 0000000000..7d1db0db4e --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/CanadianRegPostProcessor.java @@ -0,0 +1,182 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ + +package com.raytheon.edex.plugin.grib.decoderpostprocessors; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.raytheon.edex.plugin.grib.dao.GribDao; +import com.raytheon.uf.common.dataplugin.PluginException; +import com.raytheon.uf.common.dataplugin.grib.GribRecord; +import com.raytheon.uf.common.dataplugin.grib.exception.GribException; +import com.raytheon.uf.edex.database.DataAccessLayerException; +import com.raytheon.uf.edex.database.query.DatabaseQuery; + +/** + * Grib post processor implementation to generate 3-hr precipitation grids from + * run accumulated total precipitation + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#     Engineer    Description
+ * ------------ ----------  ----------- --------------------------
+ * 1/18/2012                porricel    Initial Creation
+ * 
+ * 
+ * + * @author bphillip + * @version 1 + */ +public class CanadianRegPostProcessor extends ThreeHrPrecipGridProcessor { + + @Override + public GribRecord[] process(GribRecord record) throws GribException { + // Post process the data if this is a Total Precipitation grid + if (record.getModelInfo().getParameterAbbreviation().equals("TPrun")) { + return super.process(record); + } + return new GribRecord[] { record }; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + protected List getPrecipInventory(Date refTime) + throws GribException { + GribDao dao = null; + try { + dao = new GribDao(); + } catch (PluginException e) { + throw new GribException("Error instantiating grib dao!", e); + } + DatabaseQuery query = new DatabaseQuery(GribRecord.class); + query.addQueryParam("modelInfo.parameterAbbreviation", "TPrun"); + query.addQueryParam("modelInfo.modelName", "Canadian-Reg"); + query.addQueryParam("dataTime.refTime", refTime); + query.addOrder("dataTime.fcstTime", true); + try { + return (List) dao.queryByCriteria(query); + } catch (DataAccessLayerException e) { + throw new GribException( + "Error getting Precip inventory for Canadian-Reg!", e); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + protected List getPrecip3hrInventory(Date refTime) + throws GribException { + GribDao dao = null; + try { + dao = new GribDao(); + } catch (PluginException e) { + throw new GribException("Error instantiating grib dao!", e); + } + DatabaseQuery query = new DatabaseQuery(GribRecord.class); + query.addQueryParam("modelInfo.parameterAbbreviation", "TP3hr"); + query.addQueryParam("modelInfo.modelName", "Canadian-Reg"); + query.addQueryParam("dataTime.refTime", refTime); + query.addReturnedField("dataTime.fcstTime"); + try { + return (List) dao.queryByCriteria(query); + } catch (DataAccessLayerException e) { + throw new GribException( + "Error getting Precip inventory for Canadian-Reg!", e); + } + } + + /** + * Generates the 3 hour accumulated grid from the run accumulated + * precipitation grids. This function will look in the inventory and + * generate any 3 hr grids that can be generated. + * + * @param record + * The grib record for which to generate the 3 hour accumulated + * precipitation grid + * @return The generated 3-hr precipitation grids + * @throws GribException + */ + protected synchronized GribRecord[] generate3hrPrecipGrids(GribRecord record) + throws GribException { + + // The current run accumulated precipitation grid inventory in the + // database + List precipInventory = getPrecipInventory(record + .getDataTime().getRefTime()); + + // The current 3-hr precipitation grid inventory in the database + List precip3hrInventory = getPrecip3hrInventory(record + .getDataTime().getRefTime()); + + // Adds the current record to the precip inventory + float[] currentData = (float[]) record.getMessageData(); + record.setMessageData(currentData); + precipInventory.add(record); + + // Examine each grid in the inventory and generate the 3hr precipitation + // grid if possible + List generatedRecords = new ArrayList(); + for (int i = 0; i < precipInventory.size(); i++) { + // Check if the 3hr precipitation grid has already been produced + if (!precip3hrInventory.contains(precipInventory.get(i) + .getDataTime().getFcstTime())) { + // If the precipitation grid has not been produced, generate it + List generated3hrPrecips = generate3hrPrecip( + precipInventory.get(i), precipInventory, + precip3hrInventory); + for (GribRecord newRecord : generated3hrPrecips) { + // Add the generated grid to the current inventory + if (newRecord != null) { + precip3hrInventory.add(newRecord.getDataTime() + .getFcstTime()); + generatedRecords.add(newRecord); + } + } + } + } + + return generatedRecords.toArray(new GribRecord[] {}); + } + + /** + * Calculates the new data by subtracting the previous inventory data from + * the current data + * + * @param inventoryData + * The data from the previous precipitation record + * @param newData + * The data from the current precipitation record + */ + protected void calculatePrecipValues(float[] inventoryData, float[] newData) { + for (int i = 0; i < inventoryData.length; i++) { + newData[i] = newData[i] - inventoryData[i]; + if (newData[i] < 0) { + newData[i] = 0; + } + } + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java new file mode 100644 index 0000000000..d918004d47 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/decoderpostprocessors/ThreeHrPrecipGridProcessor.java @@ -0,0 +1,236 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ + +package com.raytheon.edex.plugin.grib.decoderpostprocessors; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import com.raytheon.edex.plugin.grib.dao.GribDao; +import com.raytheon.edex.plugin.grib.util.GribModelCache; +import com.raytheon.uf.common.dataplugin.PluginException; +import com.raytheon.uf.common.dataplugin.grib.GribModel; +import com.raytheon.uf.common.dataplugin.grib.GribRecord; +import com.raytheon.uf.common.dataplugin.grib.exception.GribException; +import com.raytheon.uf.common.datastorage.records.FloatDataRecord; +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.DataTime; +import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.edex.database.DataAccessLayerException; + +/** + * Abstract class to generate 3hr records + * + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date           Ticket#    Engineer          Description
+ * ------------   ---------- -----------       --------------------------
+ * Jan 24, 2012   DR 14299   M. Porricelli     Initial creation
+ * 
+ * 
+ * + * @author porricel + * @version 1.0 + */ +public abstract class ThreeHrPrecipGridProcessor implements IDecoderPostProcessor { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(ThreeHrPrecipGridProcessor.class); + + /** The number of seconds in 3 hours */ + protected static final int SECONDS_IN_3_HRS = 10800; + + @Override + public GribRecord[] process(GribRecord record) throws GribException { + + // Post process the data if this is a Total Precipitation grid + + GribRecord[] newRecords = generate3hrPrecipGrids(record); + GribRecord[] retVal = new GribRecord[newRecords.length + 1]; + retVal[0] = record; + for (int i = 1; i < retVal.length; i++) { + retVal[i] = newRecords[i - 1]; + } + return retVal; + + } + + protected abstract GribRecord[] generate3hrPrecipGrids(GribRecord record) + throws GribException; + + /** + * Generates the 3hr precipitation grid + * + * @param record + * The current record to clone and modify to produce the new 3hr + * grid + * @param precipInventory + * The current run accumulated grid inventory + * @param precip3hrInventory + * The current 3hr precipitation inventory + * @return The generated 3hr precipitation grid + * @throws GribException + */ + protected List generate3hrPrecip(GribRecord record, + List precipInventory, List precip3hrInventory) + throws GribException { + List tp3hrRecords = new ArrayList(); + int currentFcstTime = record.getDataTime().getFcstTime(); + + // If this is the first grid (the 3 hr grid), the 3hr precip + // accumulation is the same as the 3hr run accumulated grid + if (currentFcstTime == SECONDS_IN_3_HRS) { + tp3hrRecords.add(calculate3hrPrecip(null, record)); + } + // If this is not the first grid, generate the new grid using the + // previous grid + else { + for (GribRecord rec : precipInventory) { + if (rec.getDataTime().getFcstTime() == currentFcstTime + - SECONDS_IN_3_HRS) { + tp3hrRecords.add(calculate3hrPrecip(rec, record)); + } + } + } + return tp3hrRecords; + } + + /** + * Generates the 3hr precipitation grid from the current grid and the + * previous grid + * + * @param inventoryRecord + * The previous grid from the inventory + * @param currentRecord + * The current grid + * @return The generated 3hr precipitation grid + * @throws GribException + */ + protected GribRecord calculate3hrPrecip(GribRecord inventoryRecord, + GribRecord currentRecord) throws GribException { + + // Clone the current record and set the ID to 0 so Hibernate will + // recognize it as a new record + GribRecord tp3hrRecord = new GribRecord(currentRecord); + tp3hrRecord.setId(0); + if (currentRecord.getMessageData() == null) { + GribDao dao = null; + try { + dao = new GribDao(); + currentRecord.setMessageData(((FloatDataRecord) dao + .getHDF5Data(currentRecord, 0)[0]).getFloatData()); + } catch (PluginException e) { + throw new GribException("Error populating grib data!", e); + } + } + + // Copy the data to the new record so the data from the original record + // does not get modified + float[] currentData = (float[]) currentRecord.getMessageData(); + currentRecord.setMessageData(currentData); + float[] newData = new float[currentData.length]; + System.arraycopy(currentData, 0, newData, 0, currentData.length); + tp3hrRecord.setMessageData(newData); + + // Assign the new parameter abbreviation and cache it if necessary + tp3hrRecord.getModelInfo().setParameterAbbreviation("TP3hr"); + tp3hrRecord.getModelInfo().generateId(); + try { + GribModel model = GribModelCache.getInstance().getModel( + tp3hrRecord.getModelInfo()); + tp3hrRecord.setModelInfo(model); + } catch (DataAccessLayerException e) { + throw new GribException("Unable to get model info from the cache!", + e); + } + + // Change the data time to include the 3-hr time range + modifyDataTime(tp3hrRecord); + + // Calculate the new data values + if (inventoryRecord != null) { + if (inventoryRecord.getMessageData() == null) { + GribDao dao = null; + try { + dao = new GribDao(); + inventoryRecord + .setMessageData(((FloatDataRecord) dao.getHDF5Data( + inventoryRecord, 0)[0]).getFloatData()); + } catch (PluginException e) { + throw new GribException("Error populating grib data!", e); + } + } + calculatePrecipValues((float[]) inventoryRecord.getMessageData(), + (float[]) tp3hrRecord.getMessageData()); + } + return tp3hrRecord; + } + + /** + * Calculates the new data by subtracting the previous inventory data from + * the current data + * + * @param inventoryData + * The data from the previous precipitation record + * @param newData + * The data from the current precipitation record + */ + protected abstract void calculatePrecipValues(float[] messageData, + float[] messageData2); + + /** + * Modifies the DataTime of the provided record to include a 3hr time range + * + * @param record + * The record to modify the datatime for + */ + protected void modifyDataTime(GribRecord record) { + + Calendar refTime = record.getDataTime().getRefTimeAsCalendar(); + int fcstTime = record.getDataTime().getFcstTime(); + + // Calculate the start time by subtracting 3 hours from the reference + // time + forecast time + Calendar startTime = (Calendar) refTime.clone(); + startTime.add(Calendar.SECOND, fcstTime - SECONDS_IN_3_HRS); + + // Calculate the end time by adding the reference time + forecast time + Calendar endTime = (Calendar) refTime.clone(); + endTime.add(Calendar.SECOND, fcstTime); + TimeRange validPeriod = new TimeRange(startTime, endTime); + DataTime newDataTime = new DataTime(refTime, fcstTime, validPeriod); + + // Reset the datauri since the datauri contains the DataTime + record.setDataTime(newDataTime); + record.setDataURI(null); + try { + record.setPluginName("grib"); + record.constructDataURI(); + } catch (PluginException e) { + statusHandler.handle(Priority.PROBLEM, + "Error constructing dataURI!", e); + } + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/parameterInfo/ecmwf.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/parameterInfo/ecmwf.xml index cc272bde47..5816f68730 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/parameterInfo/ecmwf.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/parameterInfo/ecmwf.xml @@ -2,26 +2,8 @@ 0 + 21600 43200 - 86400 - 129600 - 172800 - 216000 - 259200 - 302400 - 345600 - 388800 - 432000 - 475200 - 518400 - 561600 - 604800 - 648000 - 691200 - 734400 - 777600 - 820800 - 864000 diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.txt b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.txt index 56aa8a758f..cc415567a9 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.txt +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/postProcessModels/postProcessedModels.txt @@ -79,3 +79,7 @@ TPCSurgeProb:com.raytheon.edex.plugin.grib.decoderpostprocessors.TPCSurgeProbPos #SREF grids SREF212:com.raytheon.edex.plugin.grib.decoderpostprocessors.SREFProbPostProcessor SREF243:com.raytheon.edex.plugin.grib.decoderpostprocessors.SREFProbPostProcessor + +#Canadian GEM grids +Canadian-Reg:com.raytheon.edex.plugin.grib.decoderpostprocessors.CanadianRegPostProcessor +Canadian-NH:com.raytheon.edex.plugin.grib.decoderpostprocessors.CanadianNHPostProcessor \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.redbook/utility/common_static/base/purge/redbookPurgeRules.xml b/edexOsgi/com.raytheon.edex.plugin.redbook/utility/common_static/base/purge/redbookPurgeRules.xml index 33ebd6411e..5df0ce6846 100644 --- a/edexOsgi/com.raytheon.edex.plugin.redbook/utility/common_static/base/purge/redbookPurgeRules.xml +++ b/edexOsgi/com.raytheon.edex.plugin.redbook/utility/common_static/base/purge/redbookPurgeRules.xml @@ -686,6 +686,48 @@ 2 + + + redbook + wmoTTAAii=PEIY97 + + 2 + + + + redbook + wmoTTAAii=PTIY97 + + 2 + + + + redbook + wmoTTAAii=PYIY97 + + 2 + + + + redbook + wmoTTAAii=PEIY96 + + 2 + + + + redbook + wmoTTAAii=PTIY96 + + 2 + + + + redbook + wmoTTAAii=PYIY96 + + 2 + redbook diff --git a/edexOsgi/com.raytheon.edex.plugin.redbook/utility/edex_static/base/redbook/redbookFcstMap.xml b/edexOsgi/com.raytheon.edex.plugin.redbook/utility/edex_static/base/redbook/redbookFcstMap.xml index 3d237127bc..c6a51f14a8 100644 --- a/edexOsgi/com.raytheon.edex.plugin.redbook/utility/edex_static/base/redbook/redbookFcstMap.xml +++ b/edexOsgi/com.raytheon.edex.plugin.redbook/utility/edex_static/base/redbook/redbookFcstMap.xml @@ -407,6 +407,42 @@ 240 + + PEIY96 + + 336 + + + + PEIY97 + + 168 + + + + PTIY96 + + 336 + + + + PTIY97 + + 168 + + + + PYIY96 + + 336 + + + + PYIY97 + + 168 + + PEIK98 diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/python/GfePyIncludeUtil.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/python/GfePyIncludeUtil.java index 07948fefe4..66bbcca86d 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/python/GfePyIncludeUtil.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/python/GfePyIncludeUtil.java @@ -93,6 +93,11 @@ public class GfePyIncludeUtil { public static final String GFE_CONFIG = FileUtil.join("config", GFE); + public static final String VCMODULES = FileUtil.join(GFE, "vcmodule"); + + public static final String VCMOD_UTILS = FileUtil + .join(VCMODULES, "utility"); + private static final IPathManager PATH_MANAGER = PathManagerFactory .getPathManager(); @@ -177,6 +182,10 @@ public class GfePyIncludeUtil { return PATH_MANAGER.getLocalizationFile(ctx, TESTS); } + public static LocalizationFile getVCModUtilsLF(LocalizationContext ctx) { + return PATH_MANAGER.getLocalizationFile(ctx, VCMOD_UTILS); + } + // Include Path getters public static String getCommonPythonIncludePath() { @@ -386,4 +395,13 @@ public class GfePyIncludeUtil { LocalizationType.EDEX_STATIC, siteId), GFE_CONFIG); } + public static String getVCModulesIncludePath() { + return getPath(PATH_MANAGER.getContext(LocalizationType.COMMON_STATIC, + LocalizationLevel.BASE), VCMODULES); + } + + public static String getVCModUtilsIncludePath() { + return getPath(PATH_MANAGER.getContext(LocalizationType.COMMON_STATIC, + LocalizationLevel.BASE), VCMOD_UTILS); + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.radar/src/com/raytheon/uf/common/dataplugin/radar/util/RadarRecordUtil.java b/edexOsgi/com.raytheon.uf.common.dataplugin.radar/src/com/raytheon/uf/common/dataplugin/radar/util/RadarRecordUtil.java index 6bd8e99ec7..78515c09a5 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.radar/src/com/raytheon/uf/common/dataplugin/radar/util/RadarRecordUtil.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.radar/src/com/raytheon/uf/common/dataplugin/radar/util/RadarRecordUtil.java @@ -54,6 +54,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Aug 11, 2010 mnash Initial creation + * Dec 28, 2011 11705 gzhang Fix SCAN missing Rows error * * * @@ -82,8 +83,9 @@ public class RadarRecordUtil { .getTheText())) { Map map = new HashMap(); Matcher m = RadarConstants.graphic_block_pattern - .matcher(((TextSymbolPacket) packets[j]) - .getTheText()); + .matcher( + getNormalizedGBText( ((TextSymbolPacket) packets[j]).getTheText() ) + ); if (m.find()) { String storm_id = m.group(1).trim(); map.put(GraphicBlockValues.AZIMUTH, m @@ -526,5 +528,41 @@ public class RadarRecordUtil { else return Double.parseDouble(s); } - + + /** + * DR#11705: SCAN missing row(s) comparing to radar Comb Att Table. + * + * Error cause: RadarConstants.GRAPHIC_BLOCK as a Regular Expression + * pattern can not match some variations in Graphic Block Texts with + * "<" and ">" having spaces between them and their associated numbers + * ( MXHAILSIZE and TOP ). + * + * Fix: replace all "<" and ">" with space: " " + * + * @param : Graphic Block Text that may contain ">" and/or "<". + * @return: String with ">" and/or "<" replaced by space. + */ + private static String getNormalizedGBText(String text){ + + if(text == null || text.isEmpty() || ( (! text.contains(">")) && (! text.contains("<")) ) ) + return text; + + /* + * contains only ">" + */ + if( ! text.contains("<") ) + return text.replaceAll(">", " "); + + /* + * contains only "<" + */ + if( ! text.contains(">") ) + return text.replaceAll("<", " "); + + /* + * contains both "<" and ">" + */ + return text.replaceAll(">"," ").replaceAll("<", " "); + + } } diff --git a/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/JmsPooledSession.java b/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/JmsPooledSession.java index 71bdd82284..6a66f95125 100644 --- a/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/JmsPooledSession.java +++ b/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/JmsPooledSession.java @@ -453,18 +453,20 @@ public class JmsPooledSession { "Trapped internal exception", trappedExc); } + closePooledConsumersProducers(); + + // need to close down all wrappers + for (JmsSessionWrapper wrapper : references) { + wrapper.closeInternal(); + } + + references.clear(); + + conn.removeSession(this); + // synchronize on the connection to avoid deadlock conditions in // qpid synchronized (conn) { - closePooledConsumersProducers(); - - // need to close down all wrappers - for (JmsSessionWrapper wrapper : references) { - wrapper.closeInternal(); - } - - references.clear(); - try { sess.close(); } catch (Exception e) { diff --git a/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/wrapper/JmsConnectionWrapper.java b/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/wrapper/JmsConnectionWrapper.java index ed81ef01c9..754b753a2e 100644 --- a/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/wrapper/JmsConnectionWrapper.java +++ b/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/wrapper/JmsConnectionWrapper.java @@ -109,14 +109,12 @@ public class JmsConnectionWrapper implements Connection { */ @Override public void close() throws JMSException { - synchronized (this) { - if (closeInternal()) { - // remove this wrapper from the manager - mgr.removeReference(this); + if (closeInternal()) { + // remove this wrapper from the manager + mgr.removeReference(this); - if (exceptionOccurred) { - mgr.close(); - } + if (exceptionOccurred) { + mgr.close(); } } } diff --git a/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/wrapper/JmsSessionWrapper.java b/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/wrapper/JmsSessionWrapper.java index 5c235b7c52..5ffe5f2295 100644 --- a/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/wrapper/JmsSessionWrapper.java +++ b/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/wrapper/JmsSessionWrapper.java @@ -132,15 +132,14 @@ public class JmsSessionWrapper implements Session { */ @Override public void close() throws JMSException { - synchronized (this) { - if (closeInternal()) { - // remove this wrapper from the manager - mgr.removeReference(this); + if (closeInternal()) { + // remove this wrapper from the manager + mgr.removeReference(this); - if (exceptionOccurred) { - mgr.close(); - } + if (exceptionOccurred) { + mgr.close(); } + } }