diff --git a/RadarServer/build.rcm/cfgbits/data/config/drop-ins/cronOTRs.xml b/RadarServer/build.rcm/cfgbits/data/config/drop-ins/cronOTRs.xml index 0c532c4fb2..e3b1fec4cd 100644 --- a/RadarServer/build.rcm/cfgbits/data/config/drop-ins/cronOTRs.xml +++ b/RadarServer/build.rcm/cfgbits/data/config/drop-ins/cronOTRs.xml @@ -30,6 +30,6 @@ 34 16 34 32 - - + + \ No newline at end of file diff --git a/cave/build/p2-build.xml b/cave/build/p2-build.xml index dd00a25f0e..7acd223efc 100644 --- a/cave/build/p2-build.xml +++ b/cave/build/p2-build.xml @@ -178,10 +178,6 @@ - - - diff --git a/cave/build/static/common/cave/etc/aviation/python/CigVisTrend.py b/cave/build/static/common/cave/etc/aviation/python/CigVisTrend.py index d075571611..6ed8e9d677 100644 --- a/cave/build/static/common/cave/etc/aviation/python/CigVisTrend.py +++ b/cave/build/static/common/cave/etc/aviation/python/CigVisTrend.py @@ -26,6 +26,10 @@ # DELIVERED # # History: +# Revision 17 +# Created: 10-AUG-2012 15:00:00 GZHANG +# DR 14702: Added fix for PyTables in Gui().trend() +# # Revision 16 (DELIVERED) # Created: 06-MAR-2008 17:01:20 OBERFIEL # Added fix for leap-years. @@ -661,7 +665,7 @@ class Gui(): n1 = max(0, n-2*int((t-t1)//3600.0)-1) # small enough n2 = n1 + 5*self.MaxHours # big enough data = [(row['date_time'], row['cig'], row['vis']) for row in \ - table.where('(t1<=date_time) & (date_time - - com.raytheon.uf.viz.alertviz.localization.feature - - - - - - org.eclipse.pde.FeatureBuilder - - - - - - org.eclipse.pde.FeatureNature - - diff --git a/cave/com.raytheon.uf.viz.alertviz.localization.feature/build.properties b/cave/com.raytheon.uf.viz.alertviz.localization.feature/build.properties deleted file mode 100644 index 64f93a9f0b..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization.feature/build.properties +++ /dev/null @@ -1 +0,0 @@ -bin.includes = feature.xml diff --git a/cave/com.raytheon.uf.viz.alertviz.localization.feature/com.raytheon.uf.viz.alertviz.localization.feature.ecl b/cave/com.raytheon.uf.viz.alertviz.localization.feature/com.raytheon.uf.viz.alertviz.localization.feature.ecl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cave/com.raytheon.uf.viz.alertviz.localization.feature/feature.xml b/cave/com.raytheon.uf.viz.alertviz.localization.feature/feature.xml deleted file mode 100644 index af5b04e473..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization.feature/feature.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - [Enter Feature Description here.] - - - - [Enter Copyright Description here.] - - - - [Enter License Description here.] - - - - - - - - - - - diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/.classpath b/cave/com.raytheon.uf.viz.alertviz.localization/.classpath deleted file mode 100644 index 751c8f2e50..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/.project b/cave/com.raytheon.uf.viz.alertviz.localization/.project deleted file mode 100644 index 1fcbe82ecd..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - com.raytheon.uf.viz.alertviz.localization - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - - diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/.settings/org.eclipse.jdt.core.prefs b/cave/com.raytheon.uf.viz.alertviz.localization/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index c56eb27ffa..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,7 +0,0 @@ -#Mon Apr 04 17:11:52 CDT 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/META-INF/MANIFEST.MF b/cave/com.raytheon.uf.viz.alertviz.localization/META-INF/MANIFEST.MF deleted file mode 100644 index 8aaa5e3ec4..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/META-INF/MANIFEST.MF +++ /dev/null @@ -1,25 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Ui Plug-in -Bundle-SymbolicName: com.raytheon.uf.viz.alertviz.localization;singleton:=true -Bundle-Version: 1.12.1174.qualifier -Bundle-Activator: com.raytheon.uf.viz.alertviz.Activator -Bundle-Vendor: Raytheon -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - com.raytheon.uf.common.localization, - com.raytheon.uf.common.message;bundle-version="1.11.11", - com.raytheon.uf.viz.alertviz;bundle-version="1.11.11" -Bundle-ActivationPolicy: lazy -Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization -Export-Package: com.raytheon.uf.viz.alertviz.localization, - com.raytheon.uf.viz.alertviz.localization.actions -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Import-Package: com.raytheon.uf.common.alertmonitor, - com.raytheon.uf.common.util, - com.raytheon.uf.viz.localization, - com.raytheon.uf.viz.localization.adapter, - com.raytheon.uf.viz.localization.filetreeview, - com.raytheon.uf.viz.localization.service, - com.raytheon.viz.ui, - com.raytheon.viz.ui.dialogs diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/build.properties b/cave/com.raytheon.uf.viz.alertviz.localization/build.properties deleted file mode 100644 index e9863e281e..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/build.properties +++ /dev/null @@ -1,5 +0,0 @@ -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - plugin.xml diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/com.raytheon.uf.viz.alertviz.localization.ecl b/cave/com.raytheon.uf.viz.alertviz.localization/com.raytheon.uf.viz.alertviz.localization.ecl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/plugin.xml b/cave/com.raytheon.uf.viz.alertviz.localization/plugin.xml deleted file mode 100644 index d9f64b49b6..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/plugin.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/AlertVizLocalizationAdapter.java b/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/AlertVizLocalizationAdapter.java deleted file mode 100644 index 2a019cab00..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/AlertVizLocalizationAdapter.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.uf.viz.alertviz.localization; - -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.jface.action.IMenuManager; - -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; -import com.raytheon.uf.viz.alertviz.localization.actions.AlertVizFileImportAction; -import com.raytheon.uf.viz.localization.adapter.LocalizationPerspectiveAdapter; -import com.raytheon.uf.viz.localization.filetreeview.FileTreeEntryData; - -/** - * Localization perspective adapter for AlertViz. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Apr 04, 2011  5853       bgonzale    Initial creation
- * 
- * 
- * - * @author bgonzale - * @version 1.0 - */ - -public class AlertVizLocalizationAdapter extends LocalizationPerspectiveAdapter { - - private static final Map localizationMap = getLocalizationMap(); - - @Override - public boolean addContextMenuItems(IMenuManager menuMgr, - FileTreeEntryData[] selectedData) { - if (selectedData.length == 1) { - FileTreeEntryData selected = selectedData[0]; - - if (selected.getClass() == FileTreeEntryData.class) { - LocalizationLevel level = localizationMap.get(selected - .getName()); - menuMgr.add(new AlertVizFileImportAction( - (FileTreeEntryData) selected, level)); - return true; - } - } - return false; - } - - private static Map getLocalizationMap() { - Map map = new HashMap(); - map.put("Audio", LocalizationLevel.SITE); - map.put("Configurations", LocalizationLevel.USER); - map.put("Scripts", LocalizationLevel.SITE); - map.put("Python", LocalizationLevel.SITE); - return map; - } -} diff --git a/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/actions/AlertVizFileImportAction.java b/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/actions/AlertVizFileImportAction.java deleted file mode 100644 index 103ab383f1..0000000000 --- a/cave/com.raytheon.uf.viz.alertviz.localization/src/com/raytheon/uf/viz/alertviz/localization/actions/AlertVizFileImportAction.java +++ /dev/null @@ -1,161 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.uf.viz.alertviz.localization.actions; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import org.eclipse.jface.action.Action; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.FileDialog; -import org.eclipse.swt.widgets.Shell; - -import com.raytheon.uf.common.localization.IPathManager; -import com.raytheon.uf.common.localization.LocalizationContext; -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; -import com.raytheon.uf.common.localization.LocalizationFile; -import com.raytheon.uf.common.localization.PathManagerFactory; -import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException; -import com.raytheon.uf.common.status.IUFStatusHandler; -import com.raytheon.uf.common.status.UFStatus; -import com.raytheon.uf.common.status.UFStatus.Priority; -import com.raytheon.uf.viz.localization.filetreeview.FileTreeEntryData; -import com.raytheon.viz.ui.VizWorkbenchManager; - -/** - * Opens a file dialog for importing files. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Apr 04, 2011  5853       bgonzale    Initial creation
- * 
- * 
- * - * @author bgonzale - * @version 1.0 - */ - -public class AlertVizFileImportAction extends Action { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(AlertVizFileImportAction.class, "GDN_ADMIN", - "GDN_ADMIN"); - - private static final String PLUGIN_ID = "com.raytheon.uf.viz.alertviz.ui"; - - private static final String ASTERISK = "*"; - - private static final String ALL_FILES = "*.*"; - - private LocalizationLevel level; - - private String[] extensions; - - private String path; - - /** - * @param fileEntry - * - */ - public AlertVizFileImportAction(FileTreeEntryData fileEntry) { - this(fileEntry, LocalizationLevel.USER); - } - - /** - * @param fileEntry - * @param level - * - */ - public AlertVizFileImportAction(FileTreeEntryData fileEntry, - LocalizationLevel level) { - super("Import"); - this.level = level == null ? LocalizationLevel.USER : level; - this.path = fileEntry.getPath(); - String[] fileEntryExtensions = fileEntry.getPathData().getFilter(); - this.extensions = new String[fileEntryExtensions.length + 1]; - for (int i = 0; i < fileEntryExtensions.length; ++i) { - this.extensions[i] = ASTERISK + fileEntryExtensions[i]; - } - this.extensions[this.extensions.length - 1] = ALL_FILES; - } - - @Override - public void run() { - Shell shell = VizWorkbenchManager.getInstance().getCurrentWindow() - .getShell(); - FileDialog fd = new FileDialog(shell, SWT.OPEN | SWT.MULTI); - - fd.setText("Import " + level + " File"); - fd.setFilterExtensions(extensions); - fd.setFilterPath(System.getProperty("user.home")); - - String fileName = fd.open(); - - if (fileName != null) { - File file = new File(fileName); - - if (file.exists() && file.isFile()) { - IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationContext ctx = pm.getContext( - LocalizationType.CAVE_STATIC, level); - LocalizationFile locFile = pm.getLocalizationFile(ctx, path - + File.separator + file.getName()); - - try { - saveToLocalizationFile(file, locFile); - } catch (FileNotFoundException e) { - statusHandler.handle(Priority.PROBLEM, - e.getLocalizedMessage(), e); - } catch (IOException e) { - statusHandler.handle(Priority.PROBLEM, - e.getLocalizedMessage(), e); - } catch (LocalizationOpFailedException e) { - statusHandler.handle(Priority.CRITICAL, - "Error Importing file " + fileName, e); - } - } - } - } - - private void saveToLocalizationFile(File file, LocalizationFile locFile) - throws IOException, LocalizationOpFailedException { - File newFile = locFile.getFile(); - InputStream in = new FileInputStream(file); - OutputStream out = new FileOutputStream(newFile); - byte[] buff = new byte[1024]; - int len; - - while ((len = in.read(buff)) > 0) { - out.write(buff, 0, len); - } - in.close(); - out.close(); - locFile.save(); - } -} diff --git a/cave/com.raytheon.uf.viz.alertviz.ui/src/com/raytheon/uf/viz/alertviz/ui/dialogs/FileSelectDlg.java b/cave/com.raytheon.uf.viz.alertviz.ui/src/com/raytheon/uf/viz/alertviz/ui/dialogs/FileSelectDlg.java index 1583162020..d6ca0ce033 100644 --- a/cave/com.raytheon.uf.viz.alertviz.ui/src/com/raytheon/uf/viz/alertviz/ui/dialogs/FileSelectDlg.java +++ b/cave/com.raytheon.uf.viz.alertviz.ui/src/com/raytheon/uf/viz/alertviz/ui/dialogs/FileSelectDlg.java @@ -341,7 +341,7 @@ public class FileSelectDlg extends Dialog { importNewBtn1.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { FileDialog newFileDlg = new FileDialog(shell, SWT.OPEN - | SWT.MULTI); + | SWT.SINGLE); newFileDlg.setFilterExtensions(fileExtensions); String newFileName = newFileDlg.open(); if (newFileName != null) { diff --git a/cave/com.raytheon.uf.viz.alertviz/plugin.xml b/cave/com.raytheon.uf.viz.alertviz/plugin.xml index 4e5ec8901c..2cac8a257e 100644 --- a/cave/com.raytheon.uf.viz.alertviz/plugin.xml +++ b/cave/com.raytheon.uf.viz.alertviz/plugin.xml @@ -27,5 +27,79 @@ id="com.raytheon.viz.notification.statusHandler"> - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/FileTreeView.java b/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/FileTreeView.java index 6d66dbc462..d9b598edac 100644 --- a/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/FileTreeView.java +++ b/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/FileTreeView.java @@ -819,7 +819,7 @@ public class FileTreeView extends ViewPart implements IPartListener2, // We can import into true directories, not group datas mgr.add(new Separator()); mgr.add(new ImportFileAction(fdata.getPathData().getType(), - fdata.getPath())); + fdata.getPath(), fdata.getPathData().getFilter())); } } } diff --git a/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/actions/ImportFileAction.java b/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/actions/ImportFileAction.java index c597c8fdf4..f3d9d62c50 100644 --- a/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/actions/ImportFileAction.java +++ b/cave/com.raytheon.uf.viz.localization.perspective/src/com/raytheon/uf/viz/localization/perspective/view/actions/ImportFileAction.java @@ -67,17 +67,36 @@ public class ImportFileAction extends Action { private static final String FORMAT_STRING = "The file '%s' already exists at the %s level and " + "will be deleted. Proceed?"; + private static final String ASTERISK = "*"; + private String directoryPath; private LocalizationType contextType; + private String[] fileExtensionFilterArr; + public ImportFileAction(LocalizationType contextType, String directoryPath) { super("Import File..."); this.contextType = contextType; this.directoryPath = directoryPath; } - /* + public ImportFileAction(LocalizationType contextType, String directoryPath, String[] filter) { + this(contextType, directoryPath); + if (filter != null) { + this.fileExtensionFilterArr = new String[filter.length]; + for (int i = 0; i < filter.length; ++i) { + if (filter[i] != null && filter[i].startsWith(".")) { + // prepend an asterisk as required by FileDialog. + this.fileExtensionFilterArr[i] = ASTERISK + filter[i]; + } else { + this.fileExtensionFilterArr[i] = filter[i]; + } + } + } + } + + /* * (non-Javadoc) * * @see org.eclipse.jface.action.Action#run() @@ -87,6 +106,9 @@ public class ImportFileAction extends Action { Shell parent = VizWorkbenchManager.getInstance().getCurrentWindow() .getShell(); FileDialog dialog = new FileDialog(parent); + if (fileExtensionFilterArr != null) { + dialog.setFilterExtensions(fileExtensionFilterArr); + } String fileToImport = dialog.open(); if (fileToImport != null) { File importFile = new File(fileToImport); diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java index b4acf0afe6..6e967c627b 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/FFMPMonitor.java @@ -820,20 +820,15 @@ public class FFMPMonitor extends ResourceMonitor { populateFFMPRecord(product, siteKey, dataKey, sourceName, ptime, phuc, retrieveNew); } - } else { - // special case where FFG is the primary source - // check for special case with dual stand alone and table - // display loaded - SourceXML sourcexml = getSourceConfig().getSource(sourceName); + } else { + // special case where FFG is the primary source + // check for special case with dual stand alone and table + // display loaded - if (sourcexml.getSourceType().equals( - SOURCE_TYPE.GUIDANCE.getSourceType())) { - sourceName = sourcexml.getDisplayName(); - } else { - populateFFMPRecord(product, siteKey, dataKey, sourceName, - ptime, phuc, retrieveNew); - } - } + populateFFMPRecord(product, siteKey, dataKey, sourceName, + ptime, phuc, retrieveNew); + + } record = ffmpData.get(siteKey).get(sourceName); } @@ -1109,6 +1104,8 @@ public class FFMPMonitor extends ResourceMonitor { } resourceListeners.remove(listener); + // clean up if we can + System.gc(); } public ArrayList getResourceListenerList() { diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/FFTIControlDlg.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/FFTIControlDlg.java index c6833d5cfb..9ee15a3950 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/FFTIControlDlg.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/FFTIControlDlg.java @@ -279,8 +279,11 @@ public class FFTIControlDlg extends Dialog { && (thisItem.getQpeDurHr() == nextItem.getQpeDurHr()) && (thisItem.getGuidDurHr() == nextItem.getGuidDurHr()) && (thisItem.getQpfDurHr() == nextItem.getQpfDurHr()) - && (thisItem.getTotalDurHr() == nextItem.getTotalDurHr())) { - + && (thisItem.getTotalDurHr() == nextItem.getTotalDurHr()) + && (thisItem.getQpeSrc().length > 0 && nextItem.getQpeSrc().length > 0 && thisItem.getQpeSrc()[0].equals(nextItem.getQpeSrc()[0])) + && (thisItem.getQpfSrc().length > 0 && nextItem.getQpfSrc().length > 0 && thisItem.getQpfSrc()[0].equals(nextItem.getQpfSrc()[0])) + && (thisItem.getGuidSrc().length > 0 && nextItem.getGuidSrc().length > 0 && thisItem.getGuidSrc()[0].equals(nextItem.getGuidSrc()[0]))) { + duplicateLst.add(i + 1); duplicateLst.add(j + 1); } @@ -295,8 +298,14 @@ public class FFTIControlDlg extends Dialog { HashSet duplicates = getDuplicates(); if (duplicates.size() > 0) { String setsStr = ""; - for (Integer setIndex : duplicates) - setsStr += setIndex + "/"; + int i = 0; + for (Integer setIndex : duplicates) { + setsStr += setIndex; + if (i != duplicates.size()-1) { + setsStr = setsStr + "/"; + } + i++; + } MessageBox messageBox = new MessageBox(shell, SWT.OK); messageBox.setText("Warning: Duplicate Setting(s)!"); messageBox diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/SettingComp.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/SettingComp.java index d66d03f65e..23009cd527 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/SettingComp.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ffti/SettingComp.java @@ -20,6 +20,7 @@ package com.raytheon.uf.viz.monitor.ffmp.ffti; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import org.eclipse.swt.SWT; @@ -45,6 +46,17 @@ import com.raytheon.uf.common.monitor.xml.ProductRunXML; import com.raytheon.uf.common.monitor.xml.ProductXML; import com.raytheon.uf.common.monitor.xml.SourceXML; +/** + * FFTI Setting Composite. + * + *
+ * SOFTWARE HISTORY
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * 08/07/2012   578        mpduff      FFTI now only a single selection and populates
+ *                                     correctly.
+ * 
+ */ public class SettingComp extends Composite implements DurationInterface { /** * Parent tab folder. @@ -102,6 +114,8 @@ public class SettingComp extends Composite implements DurationInterface { // temporary storage for qpf private String selectedQpfVal = "0"; + + private FFTISettingXML fftiSetting; public SettingComp(TabFolder parent) { super(parent, 0); @@ -115,7 +129,8 @@ public class SettingComp extends Composite implements DurationInterface { super(parent, 0); this.parent = parent; - + this.fftiSetting = fftiSetting; + init(); // set the attributes @@ -217,6 +232,8 @@ public class SettingComp extends Composite implements DurationInterface { accumRdo.setEnabled(true); accumAction(accumAttrib); + + setSettings(); } private void createAttributeControls() { @@ -318,7 +335,7 @@ public class SettingComp extends Composite implements DurationInterface { gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false); gd.widthHint = listWidth; gd.heightHint = listHeight; - qpeList = new List(precipSrcComp, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); + qpeList = new List(precipSrcComp, SWT.BORDER | SWT.V_SCROLL); qpeList.setLayoutData(gd); fillQpeList(); @@ -327,8 +344,7 @@ public class SettingComp extends Composite implements DurationInterface { gd.horizontalSpan = 2; gd.widthHint = listWidth - 75; gd.heightHint = listHeight; - guidList = new List(precipSrcComp, SWT.BORDER | SWT.MULTI - | SWT.V_SCROLL); + guidList = new List(precipSrcComp, SWT.BORDER | SWT.V_SCROLL); guidList.setLayoutData(gd); fillGuidList(); @@ -337,7 +353,7 @@ public class SettingComp extends Composite implements DurationInterface { gd.horizontalSpan = 2; gd.widthHint = listWidth; gd.heightHint = listHeight; - qpfList = new List(precipSrcComp, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); + qpfList = new List(precipSrcComp, SWT.BORDER | SWT.V_SCROLL); qpfList.setLayoutData(gd); fillQpfList(); @@ -393,9 +409,6 @@ public class SettingComp extends Composite implements DurationInterface { guidSet.add(sourceName); guidList.add(sourceName); } - if (guidList.getItemCount() > 0) { - guidList.setSelection(0); - } guidList.addSelectionListener(new SelectionListener() { @@ -438,9 +451,10 @@ public class SettingComp extends Composite implements DurationInterface { if (source.isMosaic()) { if (!qpeSet.contains(product.getProductKey())) { - if (!qpeSet.contains(source.getDisplayName())) { - qpeSet.add(source.getDisplayName()); - qpeList.add(source.getDisplayName()); + String displayName = source.getDisplayName(); + if (!qpeSet.contains(displayName)) { + qpeSet.add(displayName); + qpeList.add(displayName); } break; } @@ -460,10 +474,6 @@ public class SettingComp extends Composite implements DurationInterface { } } } - - if (qpeList.getItemCount() > 0) { - qpeList.setSelection(0); - } } /** @@ -516,10 +526,6 @@ public class SettingComp extends Composite implements DurationInterface { } } } - - if (qpfList.getItemCount() > 0) { - qpfList.setSelection(0); - } } /** @@ -598,6 +604,55 @@ public class SettingComp extends Composite implements DurationInterface { SWT.COLOR_WHITE)); attrLbl.setLayoutData(gd); } + + /** + * Set the dialog to reflect the saved configuration. + */ + private void setSettings() { + // Select the configured items, otherwise select the first + + if (this.fftiSetting != null) { + // QPE + if (fftiSetting.getQpeSource().getDisplayNameList() == null || + fftiSetting.getQpeSource().getDisplayNameList().isEmpty()) { + qpeList.setSelection(0); + } else { + // Only using the first one in the list to match A1 + java.util.List items = Arrays.asList(qpeList.getItems()); + String name = fftiSetting.getQpeSource().getDisplayNameList().get(0); + int idx = items.indexOf(name); + qpeList.select(idx); + qpeList.showSelection(); + } + + // GUID + if (fftiSetting.getGuidSource().getDisplayNameList() == null || + fftiSetting.getGuidSource().getDisplayNameList().isEmpty()) { + guidList.setSelection(0); + } else { + // Only using the first one in the list to match A1 + java.util.List items = Arrays.asList(guidList.getItems()); + String name = fftiSetting.getGuidSource().getDisplayNameList().get(0); + int idx = items.indexOf(name); + guidList.select(idx); + guidList.showSelection(); + } + + // QPF + if (fftiSetting.getQpfSource().getDisplayNameList() == null || + fftiSetting.getQpfSource().getDisplayNameList().isEmpty()) { + qpfList.setSelection(0); + } else { + // Only using the first one in the list to match A1 + java.util.List items = Arrays.asList(qpfList.getItems()); + String name = fftiSetting.getQpfSource().getDisplayNameList().get(0); + int idx = items.indexOf(name); + qpfList.select(idx); + qpfList.showSelection(); + } + + } + } private void accumAction(FFTIAttribute attribVal) { // change attribute values diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPConfig.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPConfig.java index dd17900eb3..04d9846250 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPConfig.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPConfig.java @@ -45,6 +45,22 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData.COLUMN_NA import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPConfigBasinXML; import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPTableColumnXML; +/** + * FFMP GUI Config Object. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 01, 2012 14168      mpduff       Add convenience methods for 
+ *                                      getting ColorCell and ReverseFilter
+ * 
+ * 
+ * + * @author lvenable + * @version 1.0 + */ public class FFMPConfig { private static FFMPConfig classInstance = new FFMPConfig(); @@ -97,9 +113,9 @@ public class FFMPConfig { private HashMap threshMgrMap; private HashMap thresholdLookup; - + private AttributesDlgData attrData = null; - + private boolean reReadAttrData = false; private FFMPConfig() { @@ -357,7 +373,7 @@ public class FFMPConfig { return null; } - + public void createAttributesDlgData(String siteKey) { ArrayList columnData = ffmpCfgBasin .getTableColumnData(); @@ -371,7 +387,7 @@ public class FFMPConfig { for (int i = 0; i < columns.length; i++) { String column = columns[i]; String displayName = null; - + for (FFMPTableColumnXML tcXML : columnData) { if (column.contains("_")) { String[] parts = column.split("_"); @@ -380,10 +396,14 @@ public class FFMPConfig { } if (column.equalsIgnoreCase(tcXML.getColumnName())) { boolean includedInTable = false; - if (column.equalsIgnoreCase(COLUMN_NAME.GUID.getColumnName()) || - column.equalsIgnoreCase(COLUMN_NAME.RATIO.getColumnName()) || - column.equalsIgnoreCase(COLUMN_NAME.DIFF.getColumnName())) { - if (ffmpCfgBasin.getIncludedGuids().contains(displayName)) { + if (column.equalsIgnoreCase(COLUMN_NAME.GUID + .getColumnName()) + || column.equalsIgnoreCase(COLUMN_NAME.RATIO + .getColumnName()) + || column.equalsIgnoreCase(COLUMN_NAME.DIFF + .getColumnName())) { + if (ffmpCfgBasin.getIncludedGuids().contains( + displayName)) { includedInTable = true; attrData.setGuidColumnIncluded(displayName, includedInTable); @@ -397,8 +417,9 @@ public class FFMPConfig { } } } - - public AttributesDlgData getVisibleColumns(String siteKey, boolean reReadAttrData) { + + public AttributesDlgData getVisibleColumns(String siteKey, + boolean reReadAttrData) { this.reReadAttrData = reReadAttrData; return getVisibleColumns(siteKey); } @@ -413,33 +434,46 @@ public class FFMPConfig { public void setVisibleColumns(AttributesDlgData attrData) { this.attrData = attrData; - + ArrayList columnData = ffmpCfgBasin .getTableColumnData(); - for (FFMPTableColumnXML tcXML : columnData) { - if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.RATE.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.RATE.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.NAME.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.NAME.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.QPE.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.QPE.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.QPF.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.QPF.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.GUID.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.GUID.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.RATIO.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.RATIO.getColumnName())); - } else if (tcXML.getColumnName().equalsIgnoreCase(COLUMN_NAME.DIFF.getColumnName())) { - tcXML.setDisplayedInTable(attrData.isColumnVisible(COLUMN_NAME.DIFF.getColumnName())); + if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.RATE.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.RATE.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.NAME.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.NAME.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.QPE.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.QPE.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.QPF.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.QPF.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.GUID.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.GUID.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.RATIO.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.RATIO.getColumnName())); + } else if (tcXML.getColumnName().equalsIgnoreCase( + COLUMN_NAME.DIFF.getColumnName())) { + tcXML.setDisplayedInTable(attrData + .isColumnVisible(COLUMN_NAME.DIFF.getColumnName())); } } - + HashMap guidanceMap = attrData.getGuidanceList(); String list = ""; boolean first = true; - for (String key: guidanceMap.keySet()) { + for (String key : guidanceMap.keySet()) { if (first == false) { list.concat(","); } @@ -496,7 +530,8 @@ public class FFMPConfig { * starts. If the column is not visible then default the sort column to be * the name column. * - * @param siteKey The siteKey being used + * @param siteKey + * The siteKey being used * @return Column index. */ public int getStartSortIndex(String siteKey) { @@ -506,7 +541,7 @@ public class FFMPConfig { FfmpTableConfig tableCfg = FfmpTableConfig.getInstance(); FFMPSourceConfigurationManager sourceConfigManager = FFMPSourceConfigurationManager .getInstance(); - + FFMPRunXML runner = configManager.getRunner(monitor.getWfo()); ProductRunXML prodRunXml = runner.getProduct(siteKey); String name = prodRunXml.getProductName(); @@ -514,7 +549,7 @@ public class FFMPConfig { ProductXML productXml = sourceConfigManager.getProduct(name); ArrayList guidTypes = productXml.getAvailableGuidanceTypes(); - + String guidRankSource = null; if (guidTypes.size() > 1) { String colSorted = ffmpCfgBasin.getColumnSorted(); @@ -523,7 +558,7 @@ public class FFMPConfig { guidRankSource = parts[1]; } } - + FfmpTableConfigData tableCfgData = tableCfg.getTableConfigData(siteKey); String[] tableColumns = tableCfgData.getTableColumnKeys(); String sortedColName = ffmpCfgBasin.getColumnSorted(); @@ -539,7 +574,7 @@ public class FFMPConfig { column = parts[1]; guidType = parts[0]; } - + if (column.equalsIgnoreCase(sortedColName)) { if ((guidType != null) && (guidRankSource != null)) { if (guidType.equalsIgnoreCase(guidRankSource)) { @@ -554,7 +589,7 @@ public class FFMPConfig { } } } - + return 0; } @@ -562,10 +597,16 @@ public class FFMPConfig { if (columnName.contains("_")) { return true; } - + return false; } - + + /** + * Get the filter value for this column. + * + * @param threshColName + * @return The filter value + */ public double getFilterValue(ThreshColNames threshColName) { ArrayList columnData = ffmpCfgBasin .getTableColumnData(); @@ -575,6 +616,36 @@ public class FFMPConfig { return data.getFilter(); } + /** + * Get the ColorCell value for this column. + * + * @param threshColName + * @return The ColorCell value + */ + public boolean isColorCell(ThreshColNames threshColName) { + ArrayList columnData = ffmpCfgBasin + .getTableColumnData(); + + FFMPTableColumnXML data = columnData.get(threshColName.getColIndex()); + + return data.getColorCell(); + } + + /** + * Get the reverse filter value for this column. + * + * @param threshColName + * @return The Reverse Filter value + */ + public boolean isReverseFilter(ThreshColNames threshColName) { + ArrayList columnData = ffmpCfgBasin + .getTableColumnData(); + + FFMPTableColumnXML data = columnData.get(threshColName.getColIndex()); + + return data.getReverseFilter(); + } + /** * @return the attrData */ @@ -583,7 +654,8 @@ public class FFMPConfig { } /** - * @param attrData the attrData to set + * @param attrData + * the attrData to set */ public void setAttrData(AttributesDlgData attrData) { this.attrData = attrData; @@ -597,12 +669,13 @@ public class FFMPConfig { } /** - * @param reReadAttrData the reReadAttrData to set + * @param reReadAttrData + * the reReadAttrData to set */ public void setReReadAttrData(boolean reReadAttrData) { this.reReadAttrData = reReadAttrData; } - + public String getIncludedGuids() { return ffmpCfgBasin.getIncludedGuids(); } diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java index 62a18c9fc8..00e9c2d972 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FFMPTable.java @@ -52,6 +52,7 @@ import com.raytheon.uf.common.monitor.data.CommonConfig; import com.raytheon.uf.common.monitor.data.CommonConfig.AppName; import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPConfig.ThreshColNames; import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData.COLUMN_NAME; +import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPConfigBasinXML; import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPTableColumnXML; /** @@ -67,17 +68,20 @@ import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPTableColumnXML; * Apr 7, 2009 lvenable Initial creation * Mar 15,2012 DR 14406 gzhang Fixing QPF Column Title Missing * Mar 20,2012 DR 14250 gzhang Eliminating column Missing values + * Aug 01, 2012 14168 mpduff Only allow filtering if ColorCell is true * + * * @author lvenable * @version 1.0 */ public abstract class FFMPTable extends Composite { /** Default column width */ - protected static final int DEFAULT_COLUMN_WIDTH = 95;//DR14406: old value: 75 too small + protected static final int DEFAULT_COLUMN_WIDTH = 95;// DR14406: old value: + // 75 too small - /** DR14406: For columns with more words */ + /** DR14406: For columns with more words */ protected static final int EXTRA_COLUMN_WIDTH = 28; - + protected String currentPfaf = null; /** @@ -326,10 +330,10 @@ public abstract class FFMPTable extends Composite { cols[j].setImage(null); cols[j].setWidth(defaultColWidth); } - + // reset the tableIndex tableIndex = -1; - + /* * Check of the column is sortable. */ @@ -377,17 +381,36 @@ public abstract class FFMPTable extends Composite { int sortColIndex = table.indexOf(sortedTableColumn); boolean isAFilterCol = false; ThreshColNames sortedThreshCol = null; + boolean reverseFilter = false; double filterNum = Double.NaN; - String columnName = getColumnKeys()[sortColIndex]; + String sortedColumnName = getColumnKeys()[sortColIndex]; + + FFMPConfigBasinXML ffmpCfgBasin = FFMPConfig.getInstance() + .getFFMPConfigData(); + + ArrayList ffmpTableCols = ffmpCfgBasin + .getTableColumnData(); + + for (ThreshColNames threshColName : ThreshColNames.values()) { + if (sortedColumnName.contains(threshColName.name())) { + sortedThreshCol = threshColName; + break; + } + } + // Check if the sorted column is a column that will contain a filter. - if (!columnName.equalsIgnoreCase("NAME")) { - isAFilterCol = true; - for (ThreshColNames threshColName : ThreshColNames.values()) { - if (columnName.contains(threshColName.name())) { - sortedThreshCol = threshColName; - filterNum = ffmpConfig.getFilterValue(threshColName); + // Check the gui config to see if colorCell is true. If false then do + // not apply filter + for (FFMPTableColumnXML xml : ffmpTableCols) { + if (xml.getColumnName().contains(sortedThreshCol.name())) { + if (ffmpConfig.isColorCell(sortedThreshCol)) { + // Only filter if colorCell is true + isAFilterCol = true; + filterNum = ffmpConfig.getFilterValue(sortedThreshCol); + reverseFilter = ffmpConfig.isReverseFilter(sortedThreshCol); } + break; } } @@ -414,38 +437,16 @@ public abstract class FFMPTable extends Composite { extent.x); /* - * Check if the sorted column is a filter column. + * Check if the data value is Not A Number. */ - if (isAFilterCol == true) { - /* - * Check if the data value is Not A Number. - */ - float dataVal = cellData[sortColIndex] - .getValueAsFloat(); - //DR 14250 fix: any value not a number will be omitted - if (/*sortedThreshCol.name().equalsIgnoreCase("RATIO") &&*/ Float.isNaN(dataVal)) { - continue; - } - - // if (sortedThreshCol.name().equalsIgnoreCase("RATIO") == false) { - - // If the data value is less/more than the filter value - // continue - // so we don't put the data in the table. Less for normal - // filtering, - // more for reverse filtering - ArrayList tcList = ffmpConfig - .getFFMPConfigData().getTableColumnData(); - boolean reverseFilter = false; - for (FFMPTableColumnXML tc : tcList) { - if (tc.getColumnName().equalsIgnoreCase( - sortedThreshCol.name())) { - reverseFilter = tc.getReverseFilter(); - break; - } - } - // } + float dataVal = cellData[sortColIndex].getValueAsFloat(); + // DR 14250 fix: any value not a number will be omitted + if (/* sortedThreshCol.name().equalsIgnoreCase("RATIO") && */Float + .isNaN(dataVal)) { + continue; + } + if (isAFilterCol) { if (reverseFilter) { if (dataVal > filterNum) { continue; @@ -458,7 +459,7 @@ public abstract class FFMPTable extends Composite { } indexArray.add(t); - + // Check to see if this is the selected row if (rowData.getPfaf().equals(currentPfaf)) { tableIndex = indexArray.indexOf(t); @@ -667,7 +668,10 @@ public abstract class FFMPTable extends Composite { } } - imageWidth = maxTextLength * textWidth + EXTRA_COLUMN_WIDTH;//DR14406: old value 6 too small + imageWidth = maxTextLength * textWidth + EXTRA_COLUMN_WIDTH;// DR14406: + // old value + // 6 too + // small imageHeight = textHeight * 2; gc.dispose(); @@ -722,25 +726,34 @@ public abstract class FFMPTable extends Composite { String[] tmpArray = colName.split("\n"); for (int j = 0; j < tmpArray.length; j++) { -// if (tmpArray[j].length() > maxTextLen) { -// maxTextLen = tmpArray[j].length(); -// } -// } + // if (tmpArray[j].length() > maxTextLen) { + // maxTextLen = tmpArray[j].length(); + // } + // } - xCoord = Math.round((imageWidth / 2)- (tmpArray[j].length() /*DR14406: old value: maxTextLen*/* textWidth / 2)); - yCoord = j*(textHeight+1);//DR14406: old value 0 is only for the 1st line - gc.drawText(tmpArray[j], xCoord, yCoord, true);//DR14406: draw each line separately + xCoord = Math.round((imageWidth / 2) + - (tmpArray[j].length() /* + * DR14406: old value: + * maxTextLen + */* textWidth / 2)); + yCoord = j * (textHeight + 1);// DR14406: old value 0 is + // only for the 1st line + gc.drawText(tmpArray[j], xCoord, yCoord, true);// DR14406: + // draw each + // line + // separately } } else { xCoord = Math.round((imageWidth / 2) - (colName.length() * textWidth / 2)); yCoord = imageHeight / 2 - textHeight / 2 - 1; - gc.drawText(colName, xCoord, yCoord, true);//DR14406: draw text with a single line + gc.drawText(colName, xCoord, yCoord, true);// DR14406: draw text + // with a single line } -// System.out.println("Column name = " + colName); - //DR14406: move the below text drawing code into the if-else blocks - //gc.drawText(colName, xCoord, yCoord, true); + // System.out.println("Column name = " + colName); + // DR14406: move the below text drawing code into the if-else blocks + // gc.drawText(colName, xCoord, yCoord, true); gc.dispose(); tc.setImage(img); @@ -794,9 +807,10 @@ public abstract class FFMPTable extends Composite { tCols[i].setWidth(table.getColumn(i).getWidth()); } else { tCols[i].setWidth(defaultColWidth); - } - - setQPFColName(tCols[i], col);//DR14406: set QPF title with quicker response + } + + setQPFColName(tCols[i], col);// DR14406: set QPF title with + // quicker response } else { tCols[i].setWidth(0); } @@ -876,27 +890,24 @@ public abstract class FFMPTable extends Composite { */ protected abstract int getColumnIndex(String sortCol); - - - - /** - * DR14406 code: QPF column's name should be re-set - * when a user choose another type of QPF from the - * Attributes... button. + * DR14406 code: QPF column's name should be re-set when a user choose + * another type of QPF from the Attributes... button. * * See FfmpTableConfigData.setQpfType() with ColumnAttribData * - * @param tCols: TableColumn - * @param col: Column name + * @param tCols + * : TableColumn + * @param col + * : Column name */ - private void setQPFColName(TableColumn tCols, String col){ - - if(COLUMN_NAME.QPF.getColumnName().equalsIgnoreCase(col)){ - - setColumnImages(); - tCols.setWidth(defaultColWidth+EXTRA_COLUMN_WIDTH);//38); - - } + private void setQPFColName(TableColumn tCols, String col) { + + if (COLUMN_NAME.QPF.getColumnName().equalsIgnoreCase(col)) { + + setColumnImages(); + tCols.setWidth(defaultColWidth + EXTRA_COLUMN_WIDTH);// 38); + + } } } \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java index 83b2f6ab01..0501df28d1 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/dialogs/FfmpBasinTableDlg.java @@ -84,6 +84,8 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPLoaderStatus; import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPResource; import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPTableDataLoader; import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPTableDataUpdate; +import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPConfigBasinXML; +import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPTableColumnXML; import com.raytheon.uf.viz.monitor.listeners.IMonitorListener; import com.raytheon.viz.ui.dialogs.CaveSWTDialog; @@ -96,6 +98,10 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Sep 30, 2009 lvenable Initial creation + * Jul 31, 2012 14517 mpduff Fix map blanking on updates and table updates + * for rapid slider changes. + * Aug 01, 2012 14168 mpduff Only allow items into the Thresholds menu if + * ColorCell is true. * * * @@ -110,7 +116,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements .getHandler(FfmpBasinTableDlg.class); private List retrievalQueue = new ArrayList(); - + private MenuItem linkToFrameMI; private MenuItem worstCaseMI; @@ -220,7 +226,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements private Composite tableComp; private FFMPTableDataLoader dataRetrieveThread = null; - + private boolean sweet = true; public FfmpBasinTableDlg(Shell parent, FFMPTableData tData, @@ -496,10 +502,11 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements mi.setSelection(true); break; } - } + } } else { sourceMenuItems.get(0).setSelection(true); - ffmpConfig.getFFMPConfigData().setGuidSrc(sourceMenuItems.get(0).getText()); + ffmpConfig.getFFMPConfigData().setGuidSrc( + sourceMenuItems.get(0).getText()); } fireFieldChangedEvent(FFMPRecord.FIELDS.RATIO, false); @@ -561,7 +568,8 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements for (int i = 0; i < sourceMenuItems.size(); i++) { String rdo = sourceMenuItems.get(i).getText(); if (rdo.equals(guidSrc)) { - ffmpConfig.getFFMPConfigData().setGuidSrc(guidSrc); + ffmpConfig.getFFMPConfigData().setGuidSrc( + guidSrc); fireConfigUpdateEvent(); break; } @@ -1023,18 +1031,21 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements // Loop over enum from config singleton to create menu items for (ThreshColNames colName : ThreshColNames.values()) { - MenuItem mi = new MenuItem(popupMenu, SWT.NONE); - mi.setText(colName.name()); - mi.setData(colName); - mi.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - MenuItem mi = (MenuItem) e.getSource(); - ThreshColNames colName = (ThreshColNames) mi.getData(); + if (ffmpConfig.isColorCell(colName)) { + // only add a menu item if colorCell is true + MenuItem mi = new MenuItem(popupMenu, SWT.NONE); + mi.setText(colName.name()); + mi.setData(colName); + mi.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + MenuItem mi = (MenuItem) e.getSource(); + ThreshColNames colName = (ThreshColNames) mi.getData(); - displayThresholdsDialog(colName); - } - }); + displayThresholdsDialog(colName); + } + }); + } } // Set the pop-up menu as the pop-up for the shell @@ -1267,27 +1278,27 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements this.ffmpConfig.setAttrData(attrData); this.ffmpTable.showHideTableColumns(); boolean changeSplit = false; - + if (timeDurScale.split != ffmpConfig.isSplit()) { - changeSplit = true; + changeSplit = true; } timeDurScale.setSplit(ffmpConfig.isSplit()); updateTimeDurationLabel(timeDurScale.getSelectedHoursValue(), ffmpConfig.isSplit()); - if (updateData) { + if (updateData) { - if (changeSplit) { - fireTimeChangedEvent(timeDurScale.getSelectedHoursValue(), - ffmpConfig.isSplit(), true); - } - resource.clearTables(); - resource.getDrawable(resource.getPaintTime()).setDirty(true); - FFMPMonitor.getInstance().fireMonitorEvent( - this.getClass().getName()); + if (changeSplit) { + fireTimeChangedEvent(timeDurScale.getSelectedHoursValue(), + ffmpConfig.isSplit(), true); + } + resource.clearTables(); + resource.getDrawable(resource.getPaintTime()).setDirty(true); + FFMPMonitor.getInstance().fireMonitorEvent( + this.getClass().getName()); - } + } ffmpTable.calculateTableSize(); shell.pack(); @@ -1330,7 +1341,8 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements ffmpListeners.remove(fl); } - public void fireTimeChangedEvent(double newTime, boolean split, boolean override) { + public void fireTimeChangedEvent(double newTime, boolean split, + boolean override) { FFMPRecord.FIELDS field = FFMPRecord.FIELDS.QPE; @@ -1381,7 +1393,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements if (waitCursor == true) { shell.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); } - + FFMPFieldChangeEvent ffce = new FFMPFieldChangeEvent(field); Iterator iter = ffmpListeners.iterator(); @@ -1420,9 +1432,9 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements if (!selected) { cwas.remove(cwa); } else { - if (!cwas.contains(cwa)) { - cwas.add(cwa); - } + if (!cwas.contains(cwa)) { + cwas.add(cwa); + } } FFMPCWAChangeEvent fcce = new FFMPCWAChangeEvent(cwas); @@ -1659,23 +1671,22 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements * @param tData */ public void resetData(FFMPTableData tData) { - if (!ffmpTable.isDisposed()) { this.mainTableData = tData; - //System.out.println("---" + tData.getTableRows().size()); + // System.out.println("---" + tData.getTableRows().size()); ffmpTable.clearTableSelection(); - //long time = System.currentTimeMillis(); + // long time = System.currentTimeMillis(); ffmpTable .setCenteredAggregationKey(resource.centeredAggregationKey); ffmpTable.setTableData(mainTableData); - //long time1 = System.currentTimeMillis(); + // long time1 = System.currentTimeMillis(); resetCursor(); shell.pack(); shell.redraw(); - //System.out - // .println("Time to load Data into table " + (time1 - time)); + // System.out + // .println("Time to load Data into table " + (time1 - time)); } } @@ -1689,7 +1700,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements || allOnlySmallBasinsMI.getSelection()) { groupLbl.setText(name); } - + shell.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); fireScreenRecenterEvent(pfaf, 1); } @@ -1776,7 +1787,8 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements */ timeDurScale.setTimeDurationAndUpdate(ffmpConfig.getFFMPConfigData() .getTimeFrame()); - fireTimeChangedEvent(ffmpConfig.getFFMPConfigData().getTimeFrame(), false, false); + fireTimeChangedEvent(ffmpConfig.getFFMPConfigData().getTimeFrame(), + false, false); /* * Layer @@ -1847,7 +1859,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements } fireAutoRefreshEvent(false); - + /* * CWAs * @@ -2039,7 +2051,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements resource, basinTrendDlg, allowNewTableUpdate, sourceUpdate, date, this); - synchronized (retrievalQueue) { + synchronized (retrievalQueue) { if (dataRetrieveThread == null || dataRetrieveThread.isDone()) { retrievalQueue.clear(); dataRetrieveThread = tableLoader; @@ -2050,7 +2062,7 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements } } } - + /** * Get the latest TableDataLoader and clear all previous loaders * @@ -2058,7 +2070,8 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements */ private FFMPTableDataLoader getLoader() { synchronized (retrievalQueue) { - FFMPTableDataLoader loader = retrievalQueue.get(retrievalQueue.size() - 1); + FFMPTableDataLoader loader = retrievalQueue.get(retrievalQueue + .size() - 1); retrievalQueue.clear(); return loader; } @@ -2091,46 +2104,54 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements public void tableDataUpdateComplete(FFMPTableDataUpdate updateData) { final FFMPTableDataUpdate fupdateData = updateData; - + if (!this.isDisposed()) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { - allowNewTableUpdate = fupdateData.isAllowNewTableUpdate(); - sourceUpdate = fupdateData.isSourceUpdate(); - - if (fupdateData.getTableData() != null && sweet) { - resetData(fupdateData.getTableData()); - } - - if (fupdateData.isFireGraph()) { - fireGraphDataEvent(fupdateData.getGraphPfaf(), false, - fupdateData.getGraphTime()); - } - - setValidTime(fupdateData.getValidTime()); - updateGapValueLabel(fupdateData.getGapValueLabel()); - - resetCursor(); - sweet = true; - - if (retrievalQueue.size() > 0) { - dataRetrieveThread = getLoader(); - dataRetrieveThread.start(); - } + processUpdate(fupdateData); } }); - } + } } - + /** - * used to blank the group label when channging HUC - * while in an aggregate. + * Process the update + */ + private void processUpdate(FFMPTableDataUpdate fupdateData) { + allowNewTableUpdate = fupdateData.isAllowNewTableUpdate(); + sourceUpdate = fupdateData.isSourceUpdate(); + + if (retrievalQueue.size() > 0) { + dataRetrieveThread = getLoader(); + dataRetrieveThread.start(); + return; + } else { + } + + if (fupdateData.getTableData() != null && sweet) { + resetData(fupdateData.getTableData()); + } + + if (fupdateData.isFireGraph()) { + fireGraphDataEvent(fupdateData.getGraphPfaf(), false, + fupdateData.getGraphTime()); + } + + setValidTime(fupdateData.getValidTime()); + updateGapValueLabel(fupdateData.getGapValueLabel()); + + resetCursor(); + sweet = true; + } + + /** + * used to blank the group label when channging HUC while in an aggregate. */ public void blankGroupLabel() { - if (groupLbl != null) { - groupLbl.setText(""); - } + if (groupLbl != null) { + groupLbl.setText(""); + } } } diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java index e5e565d4c3..0a0dd588bb 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPResource.java @@ -149,6 +149,8 @@ import com.vividsolutions.jts.geom.Point; * ------------ ---------- ----------- -------------------------- * 29 June, 2009 2521 dhladky Initial creation * 11 Apr. 2012 DR 14522 gzhang Fixing invalid thread error. + * 31 July 2012 14517 mpduff Fix for blanking map on update. + * * * @author dhladky * @version 1.0 @@ -376,6 +378,9 @@ public class FFMPResource extends /** force utility **/ private FFFGForceUtil forceUtil = null; + /** Restore Table flag */ + private boolean restoreTable = false; + /** * FFMP resource * @@ -2441,7 +2446,8 @@ public class FFMPResource extends } if ((cwaBasins.size() == 0) || !req.extent.equals(drawable.getExt()) - || !phuc.equals(drawable.getHuc())) { + || !phuc.equals(drawable.getHuc()) + || restoreTable) { Envelope env = null; try { Envelope e = req.descriptor.pixelToWorld(req.extent, @@ -2466,7 +2472,7 @@ public class FFMPResource extends templates, getSiteKey(), cwa, phuc); for (Entry entry : envMap.entrySet()) { - if (env.intersects(entry.getValue())) { + if (env.intersects(entry.getValue()) || env.contains(entry.getValue())) { // add the individual basins cwaBasins.add(entry.getKey()); } @@ -2766,6 +2772,10 @@ public class FFMPResource extends } } + if (restoreTable) { + restoreTable = false; + } + drawable.setTime(req.time); if (lowestCenter != ZOOM.BASIN) { drawable.setCenterAggrKey(centeredAggregationKey); @@ -3189,7 +3199,8 @@ public class FFMPResource extends public void restoreTable() { centeredAggregationKey = null; centeredAggregatePfafList = null; - + restoreTable = true; + lowestCenter = FFMPRecord.ZOOM.WFO; getDescriptor().getRenderableDisplay().getExtent().reset(); zoom(1.0f); diff --git a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java index 1d80cf92f8..7a62a2bff9 100644 --- a/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java +++ b/cave/com.raytheon.uf.viz.monitor.ffmp/src/com/raytheon/uf/viz/monitor/ffmp/ui/rsc/FFMPTableDataLoader.java @@ -41,7 +41,8 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpBasinTableDlg; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Oct 13, 2011 dhladky Initial creation + * Oct 13, 2011 dhladky Initial creation. + * Jul 31, 2012 14517 mpduff Fix for Rapid slider changes * * * @@ -142,11 +143,13 @@ public class FFMPTableDataLoader extends Thread { // System.out // .println(" Cache MISSSSSSSSSSSS!!!!!"); + + double origDrawTime = resource.getTime(); FFMPDataGenerator dg = new FFMPDataGenerator( ffmp, resource); tData = dg.generateFFMPData(); drawable.setTableData(iHuc, tData); - drawable.setDrawTime(resource.getTime()); + drawable.setDrawTime(origDrawTime); } } } catch (Exception e) { diff --git a/cave/com.raytheon.uf.viz.profiler/src/com/raytheon/uf/viz/profiler/ProfilerResource.java b/cave/com.raytheon.uf.viz.profiler/src/com/raytheon/uf/viz/profiler/ProfilerResource.java index e1b43413f6..f75fd316c8 100644 --- a/cave/com.raytheon.uf.viz.profiler/src/com/raytheon/uf/viz/profiler/ProfilerResource.java +++ b/cave/com.raytheon.uf.viz.profiler/src/com/raytheon/uf/viz/profiler/ProfilerResource.java @@ -67,9 +67,12 @@ import com.vividsolutions.jts.geom.Coordinate; * replaced deprecated function calls * replaced deprecated function calls * Feb 10, 2011 8030 bkowal access to the plots ArrayList is now synchronized - * Feb 15, 2011 8036 bkowal magnification only affects the x-axis, wind bards, and + * Feb 15, 2011 8036 bkowal magnification only affects the x-axis, wind barbs, and * the color bar. - * + * ====================================== + * AWIPS2 DR Work + * 08/10/2012 1035 jkorman Changed number of 'staffs' from 12 to 13 and changed time + * display to match AWIPS I. * * * @author dhladky @@ -81,6 +84,8 @@ public class ProfilerResource extends private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(ProfilerResource.class); + private static final int NUM_PROFILE_STAFFS = 13; + /* Graphic target */ private IGraphicsTarget target = null; @@ -137,7 +142,7 @@ public class ProfilerResource extends protected void initInternal(IGraphicsTarget target) throws VizException { this.target = target; dataTimes = new ArrayList(); - incX = (ProfilerUtils.profilerRectangle.width / 12); + incX = (ProfilerUtils.profilerRectangle.width / NUM_PROFILE_STAFFS); incYheight = ProfilerUtils.profilerRectangle.height / maxY; @@ -222,7 +227,7 @@ public class ProfilerResource extends earliestTime = Math.min(earliestTime, validTime); latestTime = Math.max(latestTime, validTime); } - long earliestRequestTime = earliestTime - 12 * 3600000; + long earliestRequestTime = earliestTime - NUM_PROFILE_STAFFS * 3600000; List requestTimes = new ArrayList(); for (DataTime time : resourceData.getAvailableTimes()) { long validTime = time.getValidTime().getTimeInMillis(); @@ -343,7 +348,7 @@ public class ProfilerResource extends if (x < 0) { continue; } - if (x >= 12) { + if (x >= NUM_PROFILE_STAFFS) { continue; } ArrayList plots = entry.getValue(); @@ -463,9 +468,10 @@ public class ProfilerResource extends } Calendar c = paintProps.getDataTime().getValidTime(); - for (int i = 0; i < 12; i++) { + for (int i = 0; i < NUM_PROFILE_STAFFS; i++) { - String d = String.format("%1$tH:%1$tM", c); +// String d = String.format("%1$tH:%1$tM", c); + String d = String.format("%1$tH", c); parameters.setText(d, ProfilerUtils.GRAPH_COLOR); parameters.basics.x = ProfilerUtils.profilerRectangle.x + (i * incX) + (incX / 2); diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java index 247f812f67..527abe027c 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/editor/TafViewerEditorDlg.java @@ -213,6 +213,7 @@ import com.raytheon.viz.texteditor.msgs.IAviationObserver; * 08/12/2011 10612 rferrel saveFile will now always push file back to the server. * 11/29/2011 11612 rferrel Added getViewerTabList. * 20JUL2012 14570 gzhang/zhao Highlight correct time groups in TAF Viewer + * 08AGU2012 15613 zhao Modified highlightTAF() * * * @@ -3674,8 +3675,11 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, } ResourceConfigMgr configMgr = ResourceConfigMgr.getInstance(); - String taf = tafViewerStTxt.getText(); + String taf = tafViewerStTxt.getText(); int offset = taf.indexOf("TAF"); + if ( showHeadersChk.getSelection() ) { + offset = taf.indexOf("TAF", offset + 3); + } try { int end = taf.indexOf("TAF", offset + 3); if (end > 0) { @@ -3705,7 +3709,7 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, for (String alertKey : tempoMap.keySet()) { //System.out.println("2___alertKey: "+ alertKey); for (String value : tempoMap.get(alertKey)) { - System.out.println("3___value: "+ value); + //System.out.println("3___value: "+ value); str.setLength(1); str.append(value); int len = str.length(); @@ -3745,6 +3749,11 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, str.setLength(len); str.append("\n"); startIndex = taf.indexOf(str.toString()); + if (startIndex < 0) { + str.setLength(len); + str.append("="); + startIndex = taf.indexOf(str.toString()); + } } if (startIndex >= 0 /*within the same line*/&& startIndex < endIndex) { @@ -3983,11 +3992,11 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, // Only load the latest TAF, and assume it is the first one in // the Viewer. sb.append(TafUtil.safeFormatTaf(tafsInViewer[0], false)); - String bbb = ""; + String originalBbb = ""; String[] header = tafsInViewer[0].getWmoHeader().split(" "); if (header.length > 3) { - bbb = header[3]; + originalBbb = header[3]; } ITafSiteConfig config = TafSiteConfigFactory.getInstance(); @@ -3997,6 +4006,7 @@ public class TafViewerEditorDlg extends Dialog implements ITafSettable, String stationId = siteData.wmo.split(" ")[1]; String issueTime = header[2]; + String bbb = ""; if (type == null) { // Do nothing } else if (type == TafSettings.OPEN_AMD) { diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java index ab01929c16..bbd0b85599 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/guidance/MetarViewer.java @@ -63,7 +63,7 @@ import com.raytheon.viz.aviation.resource.ResourceConfigMgr.ResourceTag; * and set default value for check hours. * 04/28/2011 8065 rferrel Add flag to indicate display is current * and implement data caching - * 20JUL2012 14570 gzhang/zhao Added "tempo" to alertMap + * 31JUL2012 14570 zhao Highlight Metar alert for case of 'cat' * * * @@ -127,6 +127,7 @@ public class MetarViewer extends ViewerTab implements */ private static final HashMap alertMap = new HashMap(); static { + //alertMap.put("cat", new String[] { "", "", "", "" }); // 14570 alertMap.put("tempo", new String[] { "", "", "", "", "", "", "", "" }); // 14570 alertMap.put("vsby", new String[] { "", "" }); alertMap.put("wind", new String[] { "", "" }); @@ -410,7 +411,12 @@ public class MetarViewer extends ViewerTab implements if (alertMap != null && alertMap.size() > 0) { for (String key : alertMap.keySet()) { - colorViewerAlert(key, configMgr); + if ( key.equals("cat") ) { // "cat" involves "visibility" and "sky condition" + colorViewerAlert("vsby", configMgr); + colorViewerAlert("sky", configMgr); + } else { + colorViewerAlert(key, configMgr); + } } } } diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java index ad6f475855..aefc1f5df2 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/SiteMonitor.java @@ -63,7 +63,7 @@ import com.raytheon.viz.aviation.xml.MonitorCfg; * May 13, 2011 8611 rferrel Added type to help determine blink state. * Apr 30, 2012 14717 zhao Indicators turn gray when Metar is outdated * 20JUL2012 14570 gzhang/zhao Modified for highlighting correct time groups in TAF Viewer - * + * 11AUG2012 14570 zhao Added 'cat' to alert_key_map * * * @author lvenable @@ -126,7 +126,8 @@ public class SiteMonitor implements IRequestCompleteListener> { */ private static final Map ALERT_KEY_MAP = new HashMap(); { - ALERT_KEY_MAP.put("tempo", new String[] { "wind", "vsby", "pcp", "obv", "vcnty", "sky" } ); // 14570 + ALERT_KEY_MAP.put("cat", new String[] { "vsby", "sky" }); // 14570 + //ALERT_KEY_MAP.put("tempo", new String[] { "wind", "vsby", "pcp", "obv", "vcnty", "sky" } ); // 14570 ALERT_KEY_MAP.put("vsby", new String[] { "vsby" }); ALERT_KEY_MAP.put("wind", new String[] { "wind" }); ALERT_KEY_MAP.put("wx", new String[] { "pcp", "obv", "vcnty" }); diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafUtil.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafUtil.java index b17b58b198..556459afad 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafUtil.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/monitor/TafUtil.java @@ -49,6 +49,7 @@ import com.raytheon.uf.viz.core.exception.VizException; * Jul 6, 2010 5792 rferrel getLatestTafs now returns tafs * sorted by issue date newest at * the start of the array. + * 08AUG2012 15613 zhao Modified safeFormatTaf() * * * @@ -161,12 +162,13 @@ public class TafUtil { */ public static String safeFormatTaf(TafRecord t, boolean includeHeader) { StringBuilder sb = new StringBuilder(); - if (includeHeader) { - sb.append(t.getWmoHeader()); - sb.append(LINE_BREAK); - } if (t != null) { String[] text = t.getTafText().split("[\r\n]"); + if (includeHeader) { + sb.append(t.getWmoHeader()); + sb.append(LINE_BREAK); + sb.append("TAF").append(t.getStationId().substring(1,4)).append(LINE_BREAK); + } String firstLine = text[0]; if (firstLine.startsWith("TAF AMD") || firstLine.startsWith("TAF COR")) { @@ -191,6 +193,7 @@ public class TafUtil { sb.append(LINE_BREAK); } } + sb.append(LINE_BREAK); } return sb.toString(); } diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/SendDialog.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/SendDialog.java index 1f643714eb..4866319bec 100755 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/SendDialog.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/observer/SendDialog.java @@ -68,6 +68,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * 28 FEB 2008 938 lvenable Initial creation. * 4/15/2009 1982 grichard Provide feedback when saving a working TAF. * 12/08/2011 11745 rferrel Updated header time to transmission time. + * 08AUG2012 15613 zhao Determine proper BBB for transmission * * * @@ -364,7 +365,7 @@ public class SendDialog extends CaveSWTDialog { String siteWmoId = tabComp.getWmoId(); // WMO Site String siteNode = null; - java.util.List stationIds = new ArrayList(); + //java.util.List stationIds = new ArrayList(); ArrayList tafs = new ArrayList(); ArrayList updatedTafs = new ArrayList(); @@ -402,6 +403,16 @@ public class SendDialog extends CaveSWTDialog { // Site ID String siteId = fourLetterId.substring(1); + /* + * If "AAX" or "CCX" or "RRX", determine BBB for transmission + */ + String xmitBbb = bbb; + if ( bbb.equals("AAX") || bbb.equals("CCX") || bbb.equals("RRX") ) { + String type = bbb.substring(0, 2); + xmitBbb = getXmitBbb( type, siteId); + } + + // Update Header Time to transmission time. tafText = TIMESTAMP_PATTERN.matcher(tafText).replaceFirst( xmitTimestamp); @@ -418,7 +429,7 @@ public class SendDialog extends CaveSWTDialog { } TafQueueRecord record = new TafQueueRecord(forecasterId, - xmitTime.getTime(), tafText, bbb, siteId, siteWmoId, + xmitTime.getTime(), tafText, xmitBbb, siteId, siteWmoId, siteNode, xmitTime.getTime()); records.add(record); } @@ -455,4 +466,41 @@ public class SendDialog extends CaveSWTDialog { tabComp.setTafSent(tafsQeueued); shell.dispose(); } + + @SuppressWarnings("unchecked") + private String getXmitBbb(String type, String siteId) { + + try { + TafQueueRequest request = new TafQueueRequest(); + request.setType(Type.GET_LIST); + request.setState(TafQueueRecord.TafQueueState.SENT); + ServerResponse> response = (ServerResponse>) ThriftClient.sendRequest(request); + java.util.List payload = response.getPayload(); + String [] records = (String []) payload.toArray(new String[0]); + int numRecords = records.length; + for ( int i = numRecords-1; i >=0; i-- ) { + if ( records[i].contains(siteId) ) { + String [] texts = records[i].split("-"); + String bbb = texts[texts.length-2]; + if ( bbb.equals(" ") ) { + return type+"A"; + } + if ( bbb.subSequence(0, 2).equals(type) ) { + char[] newX = new char[] { bbb.charAt(2) }; + if ( newX[0] == 'X' ) { + newX[0] = 'A'; + } else { + newX[0]++; + } + return type + new String( newX ); + } + } + } + } catch (VizException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return type + "A"; + } } diff --git a/cave/com.raytheon.viz.feature.awips.developer/feature.xml b/cave/com.raytheon.viz.feature.awips.developer/feature.xml index b89071fd0e..4ff9da71be 100644 --- a/cave/com.raytheon.viz.feature.awips.developer/feature.xml +++ b/cave/com.raytheon.viz.feature.awips.developer/feature.xml @@ -50,10 +50,6 @@ id="com.raytheon.uf.viz.d2d.core.feature" version="0.0.0"/> - - diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/PythonPreferenceStore.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/PythonPreferenceStore.java index bd2a643dc7..5015cb67da 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/PythonPreferenceStore.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/PythonPreferenceStore.java @@ -34,6 +34,7 @@ import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.SafeRunnable; +import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil; import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; @@ -76,7 +77,6 @@ public class PythonPreferenceStore implements IPreferenceStore, private String configName; - @SuppressWarnings("unchecked") public PythonPreferenceStore(String configName) { this.propertyChangeListeners = new ArrayList(); this.configurationChangeListeners = new ArrayList(); @@ -84,7 +84,8 @@ public class PythonPreferenceStore implements IPreferenceStore, this.loadConfiguration(configName); } - public void loadConfiguration(String configName) { + @SuppressWarnings("unchecked") + public void loadConfiguration(String configName) { IPathManager pathMgr = PathManagerFactory.getPathManager(); String utilityDir = pathMgr.getFile( pathMgr.getContext(LocalizationType.CAVE_STATIC, @@ -92,23 +93,14 @@ public class PythonPreferenceStore implements IPreferenceStore, com.raytheon.uf.common.util.FileUtil.join("gfe", "utility")) .getPath(); - String configDir = com.raytheon.uf.common.util.FileUtil.join("gfe", - "userPython", "gfeConfig"); - String baseDir = pathMgr.getFile( - pathMgr.getContext(LocalizationType.CAVE_STATIC, - LocalizationLevel.BASE), configDir).getPath(); - String siteDir = pathMgr.getFile( - pathMgr.getContext(LocalizationType.CAVE_STATIC, - LocalizationLevel.SITE), configDir).getPath(); - String userDir = pathMgr.getFile( - pathMgr.getContext(LocalizationType.CAVE_STATIC, - LocalizationLevel.USER), configDir).getPath(); + String configPath = GfePyIncludeUtil.getConfigIncludePath(); + String vtecPath = GfePyIncludeUtil.getVtecIncludePath(); PythonScript py = null; try { py = new PythonScript( utilityDir + File.separator + "loadConfig.py", - PyUtil.buildJepIncludePath(userDir, siteDir, baseDir)); + PyUtil.buildJepIncludePath(configPath, vtecPath)); } catch (JepException e) { statusHandler.handle(Priority.CRITICAL, "Unable to load GFE config", e); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/config/ConfigCatalog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/config/ConfigCatalog.java index 83a05ff985..fb440bd456 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/config/ConfigCatalog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/config/ConfigCatalog.java @@ -121,10 +121,11 @@ public class ConfigCatalog extends AbstractScriptCatalog { // Look for HideConfigFile = True in the file PythonScript pscript = null; try { - String includePath = PyUtil - .buildJepIncludePath(GfePyIncludeUtil - .getConfigIncludePath()); - pscript = new PythonScript(file.getAbsolutePath(), includePath, + String configPath = GfePyIncludeUtil.getConfigIncludePath(); + String vtecPath = GfePyIncludeUtil.getVtecIncludePath(); + + pscript = new PythonScript(file.getAbsolutePath(), + PyUtil.buildJepIncludePath(configPath, vtecPath), getClass().getClassLoader(), preEvals); Boolean scriptValue = (Boolean) pscript.execute( "checkHideConfigFile", null); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISelectTimeRangeManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISelectTimeRangeManager.java index 173551c912..9beaf6d463 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISelectTimeRangeManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISelectTimeRangeManager.java @@ -19,8 +19,8 @@ **/ package com.raytheon.viz.gfe.core; -import com.raytheon.viz.gfe.core.time.SelectTimeRange; -import com.raytheon.viz.gfe.core.time.SelectTimeRange.Mode; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange.Mode; /** * TODO Add Description @@ -31,6 +31,7 @@ import com.raytheon.viz.gfe.core.time.SelectTimeRange.Mode; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Dec 3, 2009 randerso Initial creation + * Aug 1, 2012 #965 dgilling Change location of SelectTimeRange. * * * diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/AbstractGridData.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/AbstractGridData.java index 50df7c16a5..c9650039c1 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/AbstractGridData.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/AbstractGridData.java @@ -79,12 +79,12 @@ public abstract class AbstractGridData implements IGridData { protected boolean iscCapable = true; - protected Date lastAccessTime; + protected long lastAccessTime; protected Grid2DBit changedPoints; protected AbstractGridData(Parm aParm, IGridSlice aSlice) { - this.lastAccessTime = SimulatedTime.getSystemTime().getTime(); + this.lastAccessTime = System.currentTimeMillis(); this.parm = aParm; this.gridSlice = aSlice; // this.gridSlice.setUseCache(true); @@ -135,7 +135,7 @@ public abstract class AbstractGridData implements IGridData { } @Override - public Date getLastAccessTime() { + public long getLastAccessTime() { return this.lastAccessTime; } @@ -184,7 +184,7 @@ public abstract class AbstractGridData implements IGridData { } } - this.lastAccessTime = SimulatedTime.getSystemTime().getTime(); + this.lastAccessTime = System.currentTimeMillis(); } @Override @@ -458,7 +458,7 @@ public abstract class AbstractGridData implements IGridData { public boolean applyDelta(Date time, float delta, boolean taper, Grid2DBit pointsToChange) { if (delta == 0.0) { - return false; // nothing to change + return true; // nothing to change } populate(); checkOkayForEdit(); @@ -863,12 +863,12 @@ public abstract class AbstractGridData implements IGridData { if (!this.isPopulated()) { return; } - String msg = "Depopulating " + getParm().getParmID() + " tr=" - + getGridTime(); - statusHandler.handle(Priority.DEBUG, msg, new Exception("Debug: " - + msg)); + // String msg = "Depopulating " + getParm().getParmID() + " tr=" + // + getGridTime(); + // statusHandler.handle(Priority.DEBUG, msg, new Exception("Debug: " + // + msg)); - this.lastAccessTime = SimulatedTime.getSystemTime().getTime(); + this.lastAccessTime = 0; setGridSliceDataToNull(); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/IGridData.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/IGridData.java index bbc4e48220..ffb59f56c4 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/IGridData.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/griddata/IGridData.java @@ -158,7 +158,7 @@ public interface IGridData extends Comparable { * * @return time the grid was last accessed */ - public Date getLastAccessTime(); + public long getLastAccessTime(); /** * Returns the time range associated with this grid. diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java index d55affa041..2b2f10887d 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java @@ -32,6 +32,8 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange.Mode; import com.raytheon.uf.common.localization.FileUpdatedMessage; import com.raytheon.uf.common.localization.ILocalizationFileObserver; import com.raytheon.uf.common.localization.IPathManager; @@ -47,8 +49,6 @@ import com.raytheon.viz.gfe.GFEServerException; import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.ISelectTimeRangeManager; import com.raytheon.viz.gfe.core.msgs.SelectTimeRangesChangedMsg; -import com.raytheon.viz.gfe.core.time.SelectTimeRange; -import com.raytheon.viz.gfe.core.time.SelectTimeRange.Mode; /** * Class which manages the selection time range definitions that are stored on @@ -60,6 +60,7 @@ import com.raytheon.viz.gfe.core.time.SelectTimeRange.Mode; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Dec 3, 2009 #3135 randerso Initial creation + * Aug 1, 2012 #965 dgilling Change location of SelectTimeRange. * * * diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/DbParm.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/DbParm.java index 508e57c809..3553992d13 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/DbParm.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/DbParm.java @@ -708,10 +708,7 @@ public class DbParm extends Parm { continue; // grid overlaps spatial editor time -- skip it } - long lastAccess = 0; - if (grid.getLastAccessTime() != null) { - lastAccess = grid.getLastAccessTime().getTime(); - } + long lastAccess = grid.getLastAccessTime(); long delta = now - lastAccess; if (delta < milliseconds) { @@ -725,9 +722,10 @@ public class DbParm extends Parm { // only deallocate unlocked grids if (!locked) { - String msg = "Deallocating " + getParmID() + " tr=" + gTime; - statusHandler.handle(Priority.DEBUG, msg, new Exception( - "Debug: " + msg)); + // String msg = "Deallocating " + getParmID() + " tr=" + + // gTime; + // statusHandler.handle(Priority.DEBUG, msg, new Exception( + // "Debug: " + msg)); grid.depopulate(); } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java index 71cf6c9270..d9f70456a5 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/VCParm.java @@ -304,10 +304,7 @@ public class VCParm extends VParm implements IParmListChangedListener, continue; } // grid overlaps spatial editor time -- skip it - long lastAccess = 0; - if (grid.getLastAccessTime() != null) { - lastAccess = grid.getLastAccessTime().getTime(); - } + long lastAccess = grid.getLastAccessTime(); long delta = now - lastAccess; if (delta < milliseconds) { diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AbstractSaveParameterDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AbstractSaveParameterDialog.java index a11e9be7e0..857d4da0af 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AbstractSaveParameterDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AbstractSaveParameterDialog.java @@ -158,77 +158,84 @@ public abstract class AbstractSaveParameterDialog extends CaveJFACEDialog @Override protected IStatus run(IProgressMonitor monitor) { long t0 = System.currentTimeMillis(); - final CountDownLatch latch = new CountDownLatch( - MAX_CONCURRENT_SAVES); final AtomicBoolean allSuccessful = new AtomicBoolean(true); - - // spawn separate jobs top save parms - for (int i = 0; i < MAX_CONCURRENT_SAVES; i++) { - new Job("Saving Parms") { - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - Parm parm = null; - while ((parm = parms.poll()) != null) { - String parmString = parm.getParmID() - .toString(); - try { - // save data - if (statusHandler - .isPriorityEnabled(Priority.DEBUG)) { - statusHandler.handle( - Priority.DEBUG, "Save: " - + parmString); - } - if (!parm.saveParameter(true)) { - allSuccessful.set(false); - } - } catch (Exception e) { - allSuccessful.set(false); - statusHandler.handle(Priority.ERROR, - "Error occurred saving parm " - + parmString, e); - } - } - } finally { - latch.countDown(); - } - - return Status.OK_STATUS; - } - }.schedule(); - } - try { - latch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + final CountDownLatch latch = new CountDownLatch( + MAX_CONCURRENT_SAVES); - if (!allSuccessful.get()) { - statusHandler.handle(Priority.PROBLEM, - "Some grids were not saved. See log for details."); - } else { - statusHandler.handle(Priority.DEBUG, "Save Complete"); - } + // spawn separate jobs top save parms + for (int i = 0; i < MAX_CONCURRENT_SAVES; i++) { + new Job("Saving Parms") { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + Parm parm = null; + while ((parm = parms.poll()) != null) { + String parmString = parm.getParmID() + .toString(); + try { + // save data + if (statusHandler + .isPriorityEnabled(Priority.DEBUG)) { + statusHandler.handle( + Priority.DEBUG, + "Save: " + parmString); + } + if (!parm.saveParameter(true)) { + allSuccessful.set(false); + } + } catch (Throwable e) { + allSuccessful.set(false); + statusHandler.handle( + Priority.ERROR, + "Error occurred saving parm " + + parmString, e); + } + } + } catch (Throwable e) { + allSuccessful.set(false); + statusHandler.handle(Priority.ERROR, + e.getLocalizedMessage(), e); + } finally { + latch.countDown(); + } - VizApp.runAsync(new Runnable() { - - @Override - public void run() { - AbstractSaveParameterDialog.this.getShell().setCursor( - origCursor); - AbstractSaveParameterDialog.this - .saveFinished(allSuccessful.get()); + return Status.OK_STATUS; + } + }.schedule(); } - }); - long t1 = System.currentTimeMillis(); - System.out.println("GFE Save Forecast took: " + (t1 - t0) - + " ms"); + latch.await(); + } catch (Throwable e) { + allSuccessful.set(false); + statusHandler.handle(Priority.PROBLEM, + e.getLocalizedMessage(), e); + } finally { + if (!allSuccessful.get()) { + statusHandler + .handle(Priority.PROBLEM, + "Some grids were not saved. See log for details."); + } else { + statusHandler.handle(Priority.DEBUG, "Save Complete"); + } + + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + AbstractSaveParameterDialog.this.getShell() + .setCursor(origCursor); + AbstractSaveParameterDialog.this + .saveFinished(allSuccessful.get()); + } + }); + + long t1 = System.currentTimeMillis(); + System.out.println("GFE Save Forecast took: " + (t1 - t0) + + " ms"); + } return Status.OK_STATUS; } - }; saveJob.setSystem(true); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/DefineRefSetDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/DefineRefSetDialog.java index 7e19625468..4324498a8d 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/DefineRefSetDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/DefineRefSetDialog.java @@ -811,7 +811,13 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements @Override public void referenceSetChanged(ReferenceData refSet, ArrayList domains) { - activeChanged(); + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + activeChanged(); + } + }); } /* @@ -822,7 +828,13 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements */ @Override public void referenceSetIDChanged(ReferenceID refID) { - activeChanged(); + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + activeChanged(); + } + }); } /* @@ -838,7 +850,13 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements java.util.List deletions, java.util.List changes) { - this.refreshRefsets(); + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + refreshRefsets(); + } + }); } /* @@ -849,7 +867,13 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements */ @Override public void editAreaGroupInvChanged() { - this.refreshRefsets(); + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + refreshRefsets(); + } + }); } /* @@ -863,36 +887,35 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements @Override public void displayedParmListChanged(Parm[] parms, Parm[] deletions, Parm[] additions) { - refreshParms(); - } - - private void activeChanged() { VizApp.runAsync(new Runnable() { @Override public void run() { - // Update display when active refset changes - ReferenceData refData = refSetMgr.getActiveRefSet(); - - // Fix active refset display - if (!activeDisplay.isDisposed()) { - activeDisplay.setText(getActiveRefDesc(refData)); - } - - // Enable/Disable Undo button - if (!undoButton.isDisposed()) { - undoButton.setEnabled(!refData.refType().equals( - RefType.NONE)); - } - - // Enable/Disable Convert to Location button - if (!convertButton.isDisposed()) { - convertButton.setEnabled(refData.isQuery()); - } + refreshParms(); } }); } + private void activeChanged() { + // Update display when active refset changes + ReferenceData refData = refSetMgr.getActiveRefSet(); + + // Fix active refset display + if (!activeDisplay.isDisposed()) { + activeDisplay.setText(getActiveRefDesc(refData)); + } + + // Enable/Disable Undo button + if (!undoButton.isDisposed()) { + undoButton.setEnabled(!refData.refType().equals(RefType.NONE)); + } + + // Enable/Disable Convert to Location button + if (!convertButton.isDisposed()) { + convertButton.setEnabled(refData.isQuery()); + } + } + private String getActiveRefDesc(ReferenceData refData) { String s = ""; @@ -947,37 +970,29 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements } private void refreshRefsets() { - VizApp.runAsync(new Runnable() { + if (groupList.isDisposed() || editAreasList.isDisposed()) { + return; + } - @Override - public void run() { - if (groupList.isDisposed() || editAreasList.isDisposed()) { - return; - } + String[] groups = groupList.getSelection(); - String[] groups = groupList.getSelection(); + // Refresh the Group and Areas lists + java.util.List availGroups = refSetMgr.getGroupInventory(); + availGroups.add("Misc"); + groupList.setItems(availGroups.toArray(new String[availGroups.size()])); - // Refresh the Group and Areas lists - java.util.List availGroups = refSetMgr - .getGroupInventory(); - availGroups.add("Misc"); - groupList.setItems(availGroups.toArray(new String[availGroups - .size()])); - - // update selection - groupList.deselectAll(); - for (String group : groups) { - int index = groupList.indexOf(group); - if (index >= 0) { - groupList.select(index); - } - } - - groups = groupList.getSelection(); - String[] areaNames = getAreaNames(groups); - editAreasList.setItems(areaNames); + // update selection + groupList.deselectAll(); + for (String group : groups) { + int index = groupList.indexOf(group); + if (index >= 0) { + groupList.select(index); } - }); + } + + groups = groupList.getSelection(); + String[] areaNames = getAreaNames(groups); + editAreasList.setItems(areaNames); } private void refreshParms() { diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/SaveDeleteSelectTRDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/SaveDeleteSelectTRDialog.java index a36f733657..72a83422b2 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/SaveDeleteSelectTRDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/SaveDeleteSelectTRDialog.java @@ -41,17 +41,15 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange.Mode; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.SimulatedTime; -import com.raytheon.viz.gfe.Activator; import com.raytheon.viz.gfe.GFEServerException; -import com.raytheon.viz.gfe.constants.StatusConstants; import com.raytheon.viz.gfe.core.DataManager; -import com.raytheon.viz.gfe.core.time.SelectTimeRange; -import com.raytheon.viz.gfe.core.time.SelectTimeRange.Mode; import com.raytheon.viz.ui.dialogs.CaveJFACEDialog; import com.raytheon.viz.ui.widgets.SpinScale; @@ -64,6 +62,7 @@ import com.raytheon.viz.ui.widgets.SpinScale; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Dec 7, 2009 randerso Initial creation + * Aug 1, 2012 #965 dgilling Change location of SelectTimeRange. * * * @@ -72,7 +71,8 @@ import com.raytheon.viz.ui.widgets.SpinScale; */ public class SaveDeleteSelectTRDialog extends CaveJFACEDialog { - private static final transient IUFStatusHandler statusHandler = UFStatus.getHandler(SaveDeleteSelectTRDialog.class); + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(SaveDeleteSelectTRDialog.class); private DataManager dataManager; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java index b8f43e364d..aa25309507 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/edittool/contour/ContourTool.java @@ -115,6 +115,8 @@ import com.vividsolutions.jts.geom.LineString; * Jul 29, 2009 randerso Initial creation * Jul 02, 2010 6285 mpduff Fixed contours to update after * drawing and calculating new grid. + * Aug 08, 2012 #621 dgilling Fix ConcurrentModificationException + * in handling of renderables field. * * * @@ -323,6 +325,9 @@ public class ContourTool extends AbstractFreeformTool implements */ private void replaceCLines(List contours) { clearRenderables(); + + List renderables = new ArrayList( + this.renderables); renderables.add(freeformRenderable); if (currentGrid != null) { @@ -353,26 +358,34 @@ public class ContourTool extends AbstractFreeformTool implements } } renderables.add(renderable); - refresh(); } + + this.renderables = renderables; + refresh(); } private void disposeRenderables() { + List renderables = new ArrayList( + this.renderables); for (IRenderable renderable : renderables) { if (renderable instanceof JTSRenderable) { ((JTSRenderable) renderable).dispose(); } } renderables.clear(); + this.renderables = renderables; } private void clearRenderables() { + List renderables = new ArrayList( + this.renderables); for (IRenderable renderable : renderables) { if (renderable instanceof JTSRenderable) { ((JTSRenderable) renderable).clear(); } } renderables.clear(); + this.renderables = renderables; } private void initializeContourData(IGridData grid) { diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java index 4151787349..558e5f1cbb 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/gridmanager/GridBar.java @@ -647,13 +647,14 @@ public class GridBar implements IMessageClient, IParmInventoryChangedListener, Rectangle rect = computeRect(dataTR); gc.setFont(timeBlockSourceFont); + gc.setTextAntialias(SWT.OFF); String s = truncateLabelToFit(gc, text, rect.width); Point textSize = gc.stringExtent(s); if (textSize.x < rect.width + DATA_BLOCK_HORIZONTAL_MARGIN) { int xOffset = (rect.width - textSize.x) / 2; int yOffset = (rect.height - textSize.y) / 2; - gc.drawString(s, rect.x + xOffset, rect.y + yOffset, false); + gc.drawString(s, rect.x + xOffset, rect.y + yOffset, true); } } diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/resource/MultiPointResource.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/resource/MultiPointResource.java index 76f871ad7c..cb1c51a659 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/resource/MultiPointResource.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/resource/MultiPointResource.java @@ -305,9 +305,13 @@ public class MultiPointResource extends newDataMap.put(gage.getLid(), gage); /* Create a small envelope around the point */ - Coordinate p1 = new Coordinate(gage.getLon() + .03, gage.getLat() + .05); - Coordinate p2 = new Coordinate(gage.getLon() - .03, gage.getLat() - .05); - Envelope env = new Envelope(p1, p2); + double shiftHeightValue = getShiftHeight(gage); + double shiftWidthValue = getShiftWidth(gage); + + PixelExtent pe = getPixelExtent(gage, shiftWidthValue, + shiftHeightValue); + + Envelope env = this.descriptor.pixelToWorld(pe); ArrayList data = new ArrayList(); data.add(xy); data.add("GAGE: " + gage.getName() + " VALUE: " + gage.getGageValue()); @@ -776,13 +780,11 @@ public class MultiPointResource extends /** * Get the x direction shift value. * - * @param props - * The PaintProperties object * @param gage * The GageData object * @return The number of pixels to shift in the x direction */ - private double getShiftWidth(PaintProperties props, GageData gage) { + private double getShiftWidth(GageData gage) { double shiftWidthValue = (gage.getX_shift() / 2.0) / screenToWorldWidthRatio; @@ -792,13 +794,11 @@ public class MultiPointResource extends /** * Get the y direction shift value. * - * @param props - * The PaintProperties object * @param gage * The GageData object * @return The number of pixels to shift in the y direction */ - private double getShiftHeight(PaintProperties props, GageData gage) { + private double getShiftHeight(GageData gage) { double shiftHeightValue = (gage.getY_shift() / 2.0) / screenToWorldHeightRatio; @@ -886,8 +886,8 @@ public class MultiPointResource extends Coordinate c = gageData.getCoordinate(); double[] pixel = descriptor.worldToPixel(new double[] { c.x, c.y }); - double shiftHeightValue = getShiftHeight(paintProps, gageData); - double shiftWidthValue = getShiftWidth(paintProps, gageData); + double shiftHeightValue = getShiftHeight(gageData); + double shiftWidthValue = getShiftWidth(gageData); if (pixel != null) { if (paintProps.getView().getExtent().contains(pixel)) { @@ -918,9 +918,8 @@ public class MultiPointResource extends if (currentData != null) { List siteList = pdcManager.getObsReportList(); if ((siteList != null) && siteList.contains(currentData)) { - double shiftHeightValue = getShiftHeight(paintProps, - currentData); - double shiftWidthValue = getShiftWidth(paintProps, currentData); + double shiftHeightValue = getShiftHeight(currentData); + double shiftWidthValue = getShiftWidth(currentData); PixelExtent pe = getPixelExtent(currentData, shiftWidthValue, shiftHeightValue); diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDlg.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDlg.java index 27ca9dc4d4..9500bea336 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDlg.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/TimeSeriesDlg.java @@ -112,7 +112,10 @@ import com.raytheon.viz.hydrocommon.util.StnClassSyncUtil; * without starting CAVE. * 01 June 2011 9499 djingtao update openGraph() * 23 Jul 2012 15180 mpduff Auto select the first group in the predefined group list - * 23 Jul 2012 15195 mpduff Fix Group graphing to use the date widgets. + * 23 Jul 2012 15195 mpduff Fix Group graphing to use the date widgets. + * 08 Aug 2012 570 mpduff Fix a Ctrl-F in Station list causing IndexOutOfBounds error. + * 08 Aug 2012 657 mpduff Fix error when selecting a TS while no selection has been made + * in the Station List. * * * @author lvenable @@ -1161,10 +1164,12 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog { tsOrderCbo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - String line = topDataList.getItem(topDataList - .getSelectionIndex()); - String selectedLid = line.substring(0, line.indexOf(" ")); - populateBottomList(selectedLid, tsOrderCbo.getSelectionIndex()); + if (topDataList.getSelectionIndex() != -1) { + String line = topDataList.getItem(topDataList + .getSelectionIndex()); + String selectedLid = line.substring(0, line.indexOf(" ")); + populateBottomList(selectedLid, tsOrderCbo.getSelectionIndex()); + } } }); tsOrderCbo.select(1); @@ -1207,9 +1212,11 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog { topDataList.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - populateBottomList( - lidList.get(topDataList.getSelectionIndex()), - tsOrderCbo.getSelectionIndex()); + if (topDataList.getSelectionIndex() != -1) { + populateBottomList( + lidList.get(topDataList.getSelectionIndex()), + tsOrderCbo.getSelectionIndex()); + } } }); } diff --git a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/graph/TimeSeriesGraphCanvas.java b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/graph/TimeSeriesGraphCanvas.java index 7461fd3279..d2bc279daf 100644 --- a/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/graph/TimeSeriesGraphCanvas.java +++ b/cave/com.raytheon.viz.hydro/src/com/raytheon/viz/hydro/timeseries/graph/TimeSeriesGraphCanvas.java @@ -62,7 +62,8 @@ import com.raytheon.viz.hydrocommon.HydroConstants; * Apr 18, 2011 8963 jpiatt Removed Left Scale call to scale manager. * July 12 2011 9709 djingtao draw right Y axis for showPP is true. add new * function adjust_pcymax() - * Aug. 10, 2011 10457 djingtao allow the red rubberband box to be drawn for setMissing in Edit + * Aug. 10, 2011 10457 djingtao allow the red rubberband box to be drawn for setMissing in Edit + * Jul. 24, 2012 15195 mpduff Fix x axis scales. * * * @@ -492,7 +493,7 @@ public class TimeSeriesGraphCanvas extends Canvas { } // Check canvas width. if small then need to skip extra days - if (this.canvasWidth < 600) { + if (this.canvasWidth < 500) { daysSkip++; } @@ -537,8 +538,8 @@ public class TimeSeriesGraphCanvas extends Canvas { /* ******************** */ /* Hour annotation */ /* ******************** */ - dy = 10; - if (ndays < 4) { + dy = 10; + if (ndays < 8 && this.canvasWidth > 450) { if (hour < 10) { gc.drawText("0" + hour, x + leftBorder - dx, bottomBorder + 22); } else { diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/IRatingCurveSort.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/IRatingCurveSort.java deleted file mode 100644 index e4d299537c..0000000000 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/IRatingCurveSort.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.viz.hydrocommon.ratingcurve; - -/** - * Interface for getting the sort type for the rating curve data. - * - *
- *
- * SOFTWARE HISTORY
- *
- * Date        Ticket#     Engineer Description
- * ------------   ----------  ----------- --------------------------
- *24 Nov, 2008    1628      dhladky  Initial creation
- * 
- * 
- * - * @author dhladky - * @version 1.0 - */ -public interface IRatingCurveSort -{ - /** - * Get the sort type. - * @return The sort type. - */ - String getSortType(); -} \ No newline at end of file diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveData.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveData.java index 3ec557f301..d917f3a8e9 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveData.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveData.java @@ -167,4 +167,44 @@ public class RatingCurveData implements Comparable return ret; } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(discharge); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(stage); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RatingCurveData other = (RatingCurveData) obj; + if (Double.doubleToLongBits(discharge) != Double + .doubleToLongBits(other.discharge)) + return false; + if (Double.doubleToLongBits(stage) != Double + .doubleToLongBits(other.stage)) + return false; + return true; + } } diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveDlg.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveDlg.java index 1fbe6264bc..12f37e144c 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveDlg.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveDlg.java @@ -38,12 +38,12 @@ import org.eclipse.core.runtime.Status; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Layout; @@ -77,7 +77,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * @author lvenable * @version 1.0 */ -public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { +public class RatingCurveDlg extends CaveSWTDialog { /** * Control font. @@ -229,18 +229,6 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { */ private Button saveBtn; - /** - * Sort by enumeration. - */ - private enum sortBy { - Stage, Discharge - }; - - /** - * Sort by - */ - private sortBy sortKey; - /** * Dialog lid information. */ @@ -285,11 +273,6 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { */ private RatingCurveShiftData selectedRatingShift = null; - /** - * The current selected rating point - */ - private RatingCurveData selectedRatingPoint = null; - /** * Shift amount */ @@ -488,91 +471,6 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { df.setMaximumFractionDigits(2); df.setMaximumIntegerDigits(3); - shiftDataList.addSelectionListener(new SelectionListener() { - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - int index = 0; // default - RatingCurveShiftData rcsd = shiftData.get(index); - - shiftValueTF.setText(df.format(rcsd.getValue())); - shiftDateTF.setText(sdf.format(rcsd.getDate().getTime())); - shiftActiveChk.setSelection(rcsd.isActive()); - generateShiftList(rcsd); - setSelectedShift(rcsd); - - if (shiftActiveChk.getSelection()) { - // redraw the canvas with shifted data - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } - } - - @Override - public void widgetSelected(SelectionEvent e) { - int index = shiftDataList.getSelectionIndex(); - setSelectedShift(shiftData.get(index)); - RatingCurveShiftData rcsd = shiftData.get(index); - - shiftValueTF.setText(df.format(rcsd.getValue())); - shiftDateTF.setText(sdf.format(rcsd.getDate().getTime())); - shiftActiveChk.setSelection(rcsd.isActive()); - - if (shiftActiveChk.getSelection()) { - // redraw the canvas with shifted data - generateShiftList(getEditingShiftData()); - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } - } - - }); - - shiftActiveChk.addSelectionListener(new SelectionListener() { - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - // redraw the canvas with shifted data - if ((shiftData.size() > 0) && (shiftDataList != null)) { - int index = 0; - RatingCurveShiftData rcsd = shiftData.get(index); - if (rcsd.isActive()) { - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); - shiftActiveChk.setSelection(rcsd.isActive()); - } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } - } - } - - @Override - public void widgetSelected(SelectionEvent e) { - // redraw the canvas with shifted data - if ((shiftData.size() > 0) - && (shiftDataList.getSelectionIndex() != -1)) { - RatingCurveShiftData rcsd = shiftData.get(shiftDataList - .getSelectionIndex()); - generateShiftList(rcsd); - if (rcsd.isActive()) { - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } - } - } - - }); - // -------------------------------------------------------- // Create the Shift Remove & Update/Insert buttons // -------------------------------------------------------- @@ -589,25 +487,7 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { shftRemoveBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - if (getEditingShiftData() != null) { - int index = shiftDataList.getSelectionIndex(); - removedCurveShifts.add(getEditingShiftData()); - shiftData.remove(index); - selectedRatingShift = null; - - shiftDataList.removeAll(); - for (RatingCurveShiftData rcsd : shiftData) { - shiftDataList.add(getShiftListString(rcsd)); - } - shiftDataList.redraw(); - - shiftValueTF.setText(""); - shiftDateTF.setText(""); - shiftActiveChk.setSelection(false); - // default without shifting - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } + removeShift(); } }); @@ -656,25 +536,31 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { curveClearAllBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - // get rid of every point - removedPoints = noShiftCurveArray; - noShiftCurveArray.clear(); - noShiftCurveDataList.removeAll(); - noShiftCurveDataList.redraw(); + MessageBox messageDialog = new MessageBox(shell, SWT.OK | SWT.CANCEL); + messageDialog.setText("Clear Confirmation"); + messageDialog.setMessage("This will clear the list for " + lid + "."); + int response = messageDialog.open(); - if (shiftCurveArray != null) { - shiftCurveArray.clear(); - shiftCurveDataList.removeAll(); - shiftCurveDataList.redraw(); + if (response == SWT.OK) { + // get rid of every point + removedPoints = noShiftCurveArray; + noShiftCurveArray.clear(); + noShiftCurveDataList.removeAll(); + noShiftCurveDataList.redraw(); + + if (shiftCurveArray != null) { + shiftCurveArray.clear(); + } + shiftCurveDataList.removeAll(); + shiftCurveDataList.redraw(); + + stageTF.setText(""); + dischargeTF.setText(""); + selectedRatingShift = null; + + ratingCurveCanvas.updateCurveData(noShiftCurveArray, floodDbl, + recordDbl, shiftAmount); } - - stageTF.setText(""); - dischargeTF.setText(""); - selectedRatingShift = null; - selectedRatingPoint = null; - - ratingCurveCanvas.updateCurveData(noShiftCurveArray, floodDbl, - recordDbl, shiftAmount); } }); @@ -686,20 +572,28 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { @Override public void widgetSelected(SelectionEvent event) { if (noShiftCurveDataList.getSelectionIndex() != -1) { - // get rid of this point - int index = noShiftCurveDataList.getSelectionIndex(); - removedPoints.add(noShiftCurveArray.remove(index)); - remakeRatingCurveDataList(); + MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION + | SWT.OK | SWT.CANCEL); + mb.setText("Remove Base Rating Point Confirmation"); + mb.setMessage("This will remove the highlighted pair."); + int response = mb.open(); - stageTF.setText(""); - dischargeTF.setText(""); + if (response == SWT.OK) { + // get rid of this point + int index = noShiftCurveDataList.getSelectionIndex(); + removedPoints.add(noShiftCurveArray.remove(index)); + remakeRatingCurveDataList(); - if (getEditingShiftData() != null) { - generateShiftList(getEditingShiftData()); - } + stageTF.setText(""); + dischargeTF.setText(""); - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); + if (getEditingShiftData() != null) { + generateShiftList(getEditingShiftData()); + } + + ratingCurveCanvas.updateCurveData(noShiftCurveArray, + floodDbl, recordDbl, shiftAmount); + } } } }); @@ -712,47 +606,10 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { @Override public void widgetSelected(SelectionEvent event) { if (verifyDouble(stageTF) && verifyInt(dischargeTF)) { - RatingCurveData rcd = new RatingCurveData(new Double( stageTF.getText().trim()), new Double(dischargeTF .getText().trim())); - - if (noShiftCurveDataList != null) { - if (getEditingCurveData() != null) { - int index = noShiftCurveDataList - .getSelectionIndex(); - if (index > -1) { - noShiftCurveArray.remove(index); - noShiftCurveDataList.remove(index); - } - } - } - - if (!addedPoints.contains(rcd)) { - addedPoints.add(rcd); - } else { - addedPoints.remove(rcd); - addedPoints.add(rcd); - } - - noShiftCurveArray.add(rcd); - remakeRatingCurveDataList(); - - if (getEditingShiftData() != null) { - if (getEditingShiftData().isActive()) { - int index = shiftDataList.getSelectionIndex(); - generateShiftList(shiftData.get(index)); - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } else { - ratingCurveCanvas.updateCurveData( - noShiftCurveArray, floodDbl, recordDbl, - shiftAmount); - } - } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); - } + insertBaseCurvePoint(rcd); } } }); @@ -769,6 +626,49 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { shiftValueTF.setEditable(true); } } + + private void insertBaseCurvePoint(RatingCurveData rcd) { + if (!noShiftCurveArray.contains(rcd)) { + // Check for a matching stage value + RatingCurveData data = null; + for (RatingCurveData d: noShiftCurveArray) { + if (d.getStage() == rcd.getStage()) { + data = d; + break; + } + } + + if (data != null) { + noShiftCurveArray.remove(data); + } + + noShiftCurveArray.add(rcd); + if (!addedPoints.contains(rcd)) { + addedPoints.add(rcd); + } else { + addedPoints.remove(rcd); + addedPoints.add(rcd); + } + + remakeRatingCurveDataList(); + + if (getEditingShiftData() != null) { + if (getEditingShiftData().isActive()) { + int index = shiftDataList.getSelectionIndex(); + generateShiftList(shiftData.get(index)); + ratingCurveCanvas.updateCurveData(shiftCurveArray, + floodDbl, recordDbl, shiftAmount); + } else { + ratingCurveCanvas.updateCurveData( + noShiftCurveArray, floodDbl, recordDbl, + shiftAmount); + } + } else { + ratingCurveCanvas.updateCurveData(noShiftCurveArray, + floodDbl, recordDbl, shiftAmount); + } + } + } /** * Create the controls on the right side of the dialog. @@ -789,10 +689,17 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { createStageDischargeLabels(rightComp); gd = new GridData(220, 400); - shiftCurveDataList = new List(rightComp, SWT.BORDER | SWT.SINGLE - | SWT.V_SCROLL); + shiftCurveDataList = new List(rightComp, SWT.BORDER | SWT.V_SCROLL); shiftCurveDataList.setFont(controlFont); shiftCurveDataList.setLayoutData(gd); + shiftCurveDataList.deselectAll(); + shiftCurveDataList.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GRAY)); + shiftCurveDataList.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + shiftCurveDataList.deselectAll(); + } + }); gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false); ratingLbl = new Label(rightComp, SWT.CENTER); @@ -804,17 +711,6 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { | SWT.V_SCROLL); noShiftCurveDataList.setFont(controlFont); noShiftCurveDataList.setLayoutData(gd); - - if (noShiftCurveArray != null) { - // populate the list - for (RatingCurveData curve : noShiftCurveArray) { - noShiftCurveDataList.add(curve.toString()); - } - noShiftCurveDataList.setEnabled(true); - } else { - noShiftCurveDataList.setEnabled(false); - } - noShiftCurveDataList.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -823,10 +719,27 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { stageTF.setText(String.format("%7.2f", data.getStage())); dischargeTF .setText(String.format("%7.1f", data.getDischarge())); - setSelectedCurveData(data); } }); + if (noShiftCurveArray != null) { + // populate the list + RatingCurveShiftData currentShift = null; + if (shiftData != null && shiftData.size() > 0) { + if (shiftData.get(0).isActive()) { + currentShift = shiftData.get(0); + } + } + + for (RatingCurveData curve : noShiftCurveArray) { + noShiftCurveDataList.add(curve.toString()); + } + if (noShiftCurveDataList.getItemCount() > 0) { + noShiftCurveDataList.select(0); + generateShiftList(currentShift); + } + } + createStageDischargeTextFields(rightComp); } @@ -987,7 +900,12 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { if (label != null) { ratingLbl.setText(label); } - + + if (noShiftCurveArray.size() > 0) { + RatingCurveData rcd = noShiftCurveArray.get(0); + this.stageTF.setText(String.valueOf(rcd.getStage())); + this.dischargeTF.setText(String.valueOf(rcd.getDischarge())); + } } /** @@ -1052,10 +970,10 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { * @param rcsd */ public void generateShiftList(RatingCurveShiftData rcsd) { + shiftCurveDataList.removeAll(); if (rcsd != null) { shiftAmount = rcsd.getValue(); - shiftCurveDataList.removeAll(); shiftCurveArray = new ArrayList(); // remake the rating curve with shift data @@ -1067,38 +985,14 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { } // redraw for the full effect shiftCurveDataList.redraw(); + } else { + // make the rating curve with no shift data + for (RatingCurveData curve : noShiftCurveArray) { + shiftCurveDataList.add(curve.toString()); + } } } - @Override - public String getSortType() { - // TODO Auto-generated method stub - return "Stage"; - } - - /** - * Sort the crest data by stage value. - */ - public void sortByStage() { - sortKey = sortBy.Stage; - sortCurveData(); - } - - /** - * Sort the crest data by flow value. - */ - public void sortByDischarge() { - sortKey = sortBy.Discharge; - sortCurveData(); - } - - /** - * Sort the curve data. - */ - private void sortCurveData() { - Collections.sort(noShiftCurveArray); - } - /** * Imports a rating curve * @@ -1268,51 +1162,101 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { RatingCurveShiftData rcsd = new RatingCurveShiftData(lid, cal, new Double(shiftValueTF.getText()), shiftActiveChk .getSelection()); - // remove old - if (shiftDataList != null) { - int index = shiftDataList.getSelectionIndex(); - if (index != -1) { - if (rcsd.getDate().getTime().equals( - shiftData.get(index).getDate().getTime())) { - shiftDataList.remove(index); - shiftData.remove(index); - } - } else { - for (int i = 0; i < shiftData.size(); i++) { - RatingCurveShiftData data = shiftData.get(i); - if (data.getDate().getTime().equals(cal.getTime())) { - shiftData.remove(i); - shiftDataList.remove(i); - i--; - } - } - } + + if (shiftData.size() > 0 && shiftData.contains(rcsd)) { + for (RatingCurveShiftData sd: shiftData) { + if (rcsd.toString().equals(sd.toString())) { + sd.setActive(rcsd.isActive()); + sd.setDate(rcsd.getDate()); + sd.setLid(rcsd.getLid()); + sd.setValue(rcsd.getValue()); + break; + } + } + } else { + shiftData.add(rcsd); } - + if (!addedCurveShifts.contains(rcsd)) { - addedCurveShifts.add(rcsd); + addedCurveShifts.add(rcsd); } else { - addedCurveShifts.remove(rcsd); - addedCurveShifts.add(rcsd); + addedCurveShifts.remove(rcsd); + addedCurveShifts.add(rcsd); } - shiftData.add(rcsd); - shiftDataList.add(getShiftListString(rcsd)); - shiftDataList.redraw(); + shiftDataList.removeAll(); + Collections.sort(shiftData); - if (shiftActiveChk.getSelection()) { - generateShiftList(rcsd); - ratingCurveCanvas.updateCurveData(shiftCurveArray, - floodDbl, recordDbl, shiftAmount); + for (RatingCurveShiftData sd: shiftData) { + shiftDataList.add(getShiftListString(sd)); + } + + // Display the latest shift + RatingCurveShiftData currentShift = shiftData.get(0); + if (currentShift.isActive()) { + generateShiftList(currentShift); + ratingCurveCanvas.updateCurveData(shiftCurveArray, + floodDbl, recordDbl, currentShift.getValue()); } else { - ratingCurveCanvas.updateCurveData(noShiftCurveArray, - floodDbl, recordDbl, shiftAmount); + ratingCurveCanvas.updateCurveData(noShiftCurveArray, + floodDbl, recordDbl, 0); } } + + shiftValueTF.setText(""); + shiftDateTF.setText(""); + shiftActiveChk.setSelection(false); } catch (Exception e) { e.printStackTrace(); } } + + private void removeShift() { + if (shiftDataList.getItemCount() > 0 && shiftDataList.getSelectionCount() > 0) { + MessageBox messageDialog = new MessageBox(shell, SWT.OK | SWT.CANCEL); + messageDialog.setText("Shift Remove Confirmation"); + messageDialog.setMessage("This will remove the highlighted shift."); + int response = messageDialog.open(); + + if (response == SWT.OK) { + String selection = shiftDataList.getItem(shiftDataList.getSelectionIndex()); + for (RatingCurveShiftData sd: shiftData) { + if (getShiftListString(sd).equals(selection)) { + removedCurveShifts.add(sd); + break; + } + } + + shiftData.removeAll(removedCurveShifts); + shiftDataList.removeAll(); + Collections.sort(shiftData); + for (RatingCurveShiftData rcsd : shiftData) { + shiftDataList.add(getShiftListString(rcsd)); + } + shiftDataList.redraw(); + + if (shiftData.size() > 0) { + shiftAmount = shiftData.get(0).getValue(); + } else { + shiftAmount = 0; + } + + ratingCurveCanvas.updateCurveData(noShiftCurveArray, + floodDbl, recordDbl, shiftAmount); + + if (shiftData.size() > 0) { + RatingCurveShiftData currentShift = shiftData.get(0); + if (currentShift.isActive()) { + generateShiftList(currentShift); + } else { + generateShiftList(null); + } + } else { + generateShiftList(null); + } + } + } + } /** * Verify validity of input @@ -1371,44 +1315,40 @@ public class RatingCurveDlg extends CaveSWTDialog implements IRatingCurveSort { return selectedRatingShift; } - /** - * set the current curve shift - * - * @param selectedRatingShift - */ - private void setSelectedShift(RatingCurveShiftData selectedRatingShift) { - this.selectedRatingShift = selectedRatingShift; - } - - /** - * Get the editing curve data - * - * @return - */ - private RatingCurveData getEditingCurveData() { - return selectedRatingPoint; - } - - /** - * Sets the selected curve data - * - * @param selectedRatingPoint - */ - private void setSelectedCurveData(RatingCurveData selectedRatingPoint) { - this.selectedRatingPoint = selectedRatingPoint; - } - /** * update the noShiftCurveDataList */ private void remakeRatingCurveDataList() { - - sortCurveData(); + Collections.sort(noShiftCurveArray); + int index = noShiftCurveDataList.getSelectionIndex(); noShiftCurveDataList.removeAll(); + shiftCurveDataList.removeAll(); for (RatingCurveData rcd : noShiftCurveArray) { noShiftCurveDataList.add(rcd.toString()); } - noShiftCurveDataList.redraw(); + + if (shiftData.size() > 0) { + RatingCurveShiftData currentShift = shiftData.get(0); + if (currentShift.isActive()) { + generateShiftList(currentShift); + } else { + remakeRatingCurveDataList(); + } + } else { + remakeRatingCurveDataList(); + } + + if (noShiftCurveDataList.getItemCount() > 0) { + if (index >= noShiftCurveDataList.getItemCount()) { + noShiftCurveDataList.select(noShiftCurveDataList.getItemCount() - 1); + } else if (index >= 0 && index < noShiftCurveArray.size()) { + noShiftCurveDataList.select(index); + } else { + noShiftCurveDataList.select(0); + } + noShiftCurveDataList.showSelection(); + + } } /** diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveShiftData.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveShiftData.java index 564b6474d3..756993d02f 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveShiftData.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/ratingcurve/RatingCurveShiftData.java @@ -40,7 +40,7 @@ import java.util.TimeZone; * @version 1.0 */ -public class RatingCurveShiftData { +public class RatingCurveShiftData implements Comparable { private String lid = null; @@ -90,18 +90,34 @@ public class RatingCurveShiftData { public String getLid() { return lid; } + + public void setLid(String lid) { + this.lid = lid; + } public Calendar getDate() { return date; } + + public void setDate(Calendar date) { + this.date = date; + } public double getValue() { return value; } + public void setValue(double value) { + this.value = value; + } + public boolean isActive() { return active; } + + public void setActive(boolean active) { + this.active = active; + } /** * Get the date in a MM/DD/YYYY format. @@ -125,4 +141,16 @@ public class RatingCurveShiftData { return sb.toString(); } + + @Override + public int compareTo(RatingCurveShiftData o) { + if (this.date.getTime().equals(o.getDate().getTime())) { + return 0; + } else if (this.date.getTime().before(o.getDate().getTime())) { + return 1; + } else if (this.date.getTime().after(o.getDate().getTime())) { + return -1; + } + return 0; + } } diff --git a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/whfslib/GagePPWrite.java b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/whfslib/GagePPWrite.java index 0b00304560..40267ea053 100644 --- a/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/whfslib/GagePPWrite.java +++ b/cave/com.raytheon.viz.hydrocommon/src/com/raytheon/viz/hydrocommon/whfslib/GagePPWrite.java @@ -54,6 +54,7 @@ import com.raytheon.viz.hydrocommon.whfslib.GagePPOptions.upd_action; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 5, 2008 1649 snaples Initial creation + * Aug 8, 2012 15271 snaples Updated hourly slot * * * @@ -140,12 +141,6 @@ public final class GagePPWrite { String obstime = sdf.format(dto); GagePPOptions opts = options; int hr = dt.get(Calendar.HOUR_OF_DAY); - if (hr == 0) { - hr = 24; - dt.add(Calendar.HOUR_OF_DAY, -1); - obstime = sdf.format(dt); - dto = dt.getTime(); - } int min = dt.get(Calendar.MINUTE); char sixhroffset = get_offset_code(min); char sixhrqc = 'M'; @@ -212,7 +207,7 @@ public final class GagePPWrite { pHourpp.setSixhroffset(String.valueOf(sixhr_offset)); pHourpp.setSixhrqc(String.valueOf(sixhr_qc)); set_hour_slot_value(pHourpp, hr, new_hourly_value); - set_6hour_slot_value(pHourpp, six + 1, pp_value); + set_6hour_slot_value(pHourpp, six, pp_value); update_gage_rec(pHourpp); } @@ -283,7 +278,7 @@ public final class GagePPWrite { if (hpp.getSixhrqc() != null) { old_six_qc = hpp.getSixhrqc().toCharArray(); } - Short sixval = get_6hour_slot_value(hpp, six + 1); + Short sixval = get_6hour_slot_value(hpp, six); prev_sixhroff = old_sixhroffset[six]; prev_sixqc = old_six_qc[six]; @@ -363,7 +358,7 @@ public final class GagePPWrite { pHourpp.setSixhroffset(String.valueOf(sixhr_offset)); pHourpp.setSixhrqc(String.valueOf(six_hr_qc)); set_hour_slot_value(pHourpp, hr, hr_value); - set_6hour_slot_value(pHourpp, six + 1, six_hr_slot_val); + set_6hour_slot_value(pHourpp, six, six_hr_slot_val); update_gage_rec(pHourpp); } } @@ -733,22 +728,22 @@ public final class GagePPWrite { * the HourPC structure. */ switch (hour) { - case 1: /* 00z - 06z */ + case 0: /* 00z - 06z */ precip_value = pHourlyPP.getSixhr06(); break; - case 2: /* 06z - 12z */ + case 1: /* 06z - 12z */ precip_value = pHourlyPP.getSixhr12(); break; - case 3: /* 12z - 18z */ + case 2: /* 12z - 18z */ precip_value = pHourlyPP.getSixhr18(); break; - case 4: /* 18z - 00z */ + case 3: /* 18z - 00z */ precip_value = pHourlyPP.getSixhr24(); break; @@ -773,25 +768,25 @@ public final class GagePPWrite { * the HourPC structure. */ switch (hour) { - case 1: /* 00z - 06z */ + case 0: /* 00z - 06z */ precip_value = new Short((short) val); pHourlyPP.setSixhr06(precip_value); break; - case 2: /* 06z - 12z */ + case 1: /* 06z - 12z */ precip_value = new Short((short) val); pHourlyPP.setSixhr12(precip_value); break; - case 3: /* 12z - 18z */ + case 2: /* 12z - 18z */ precip_value = new Short((short) val); pHourlyPP.setSixhr18(precip_value); break; - case 4: /* 18z - 00z */ + case 3: /* 18z - 00z */ precip_value = new Short((short) val); pHourlyPP.setSixhr24(precip_value); @@ -927,7 +922,7 @@ public final class GagePPWrite { precip_value = pHourlyPP.getHour23(); break; - case 24: + case 0: precip_value = pHourlyPP.getHour24(); break; @@ -1068,12 +1063,13 @@ public final class GagePPWrite { pHourly.setHour23(precip_value); break; - case 24: + case 0: precip_value = new Short((short) val); pHourly.setHour24(precip_value); break; default: + precip_value = new Short((short) MISSING_PRECIP); break; } diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEDisplayManager.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEDisplayManager.java index 4c06832a89..7c51dc064c 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEDisplayManager.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/MPEDisplayManager.java @@ -104,6 +104,7 @@ import com.raytheon.viz.ui.editor.IMultiPaneEditor; * Dec 1, 2008 1748 snaples Added enum for Gage Color * Aug 11, 2010 5733 jwang Removed Polygon Edit and Gages * legend from MPE perspective + * Aug 8, 2012 15271 snaples Updated hourly slot * * * @author randerso @@ -536,7 +537,7 @@ public class MPEDisplayManager { clearMPEData(); try { dm.readRadarData(newDate); - dm.readGageData(newDate); + dm.readGageData(newDate, newDate); if (gageTableDlg != null) { gageTableDlg.updateDate(newDate); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java index ff0c179eca..4e76573654 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/rsc/MPEGageResource.java @@ -90,6 +90,7 @@ import com.vividsolutions.jts.index.strtree.STRtree; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Feb 8, 2011 mschenke Initial creation + * Aug 8, 2012 15271 snaples Updated hourly slot * * * @@ -160,7 +161,7 @@ public class MPEGageResource extends AbstractMPEInputResource { .getRenderableDisplay()); loadColors(); lastDate = displayMgr.getCurrentDate(); - addPoints(MPEDataManager.getInstance().readGageData(lastDate)); + addPoints(MPEDataManager.getInstance().readGageData(lastDate, lastDate)); } @Override @@ -215,7 +216,7 @@ public class MPEGageResource extends AbstractMPEInputResource { synchronized (mutex) { if (curDate != null && curDate.equals(lastDate) == false) { lastDate = curDate; - addPoints(MPEDataManager.getInstance().readGageData(lastDate)); + addPoints(MPEDataManager.getInstance().readGageData(lastDate, lastDate)); } } diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/RegenHrFlds.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/RegenHrFlds.java index e5838698b4..e8cdad8fc6 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/RegenHrFlds.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/core/RegenHrFlds.java @@ -54,6 +54,7 @@ import com.raytheon.viz.mpe.core.MPEDataManager.MPEGageData; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 30, 2008 snaples Initial creation + * Aug 8, 2012 15271 snaples Updated hourly slot * * * @author snaples @@ -301,7 +302,7 @@ public class RegenHrFlds { e.printStackTrace(); } - MPEDataManager.getInstance().readGageData(datetime); + MPEDataManager.getInstance().readGageData(datetime, datetime); /* Read radar data */ MPEDataManager.getInstance().readRadarData(datetime); MPEDataManager.getInstance().clearEditGages(); diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java index d0feff35d4..fa0e6bccf3 100644 --- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java +++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java @@ -85,6 +85,9 @@ import com.vividsolutions.jts.geom.Envelope; * 04/13/2009 2251 jsanchez Plot profilers. * 05/12/2009 2338 jsanchez Updated resourceChanged. Registered units. * 06/08/2009 2450 jsanchez Updated inpsect method to find closest plot. + * ====================================== + * AWIPS2 DR Work + * 08/09/2012 1011 jkorman Added screenToWorldRatio calc to paintInternal. * * * @@ -230,6 +233,8 @@ public class PlotResource extends if (this.stationsToParse.size() > 0) { this.updateRecords(); } + this.screenToWorldRatio = paintProps.getCanvasBounds().width + / paintProps.getView().getExtent().getWidth(); boolean delayLoop = false; DataTime thisFrameTime = this.displayedObsTime; if (thisFrameTime != null) { @@ -847,14 +852,18 @@ public class PlotResource extends ArrayList availableCoord) { double x1 = latlon.x; double y1 = latlon.y; - double minDistance = MAX_SAMPLE_DISANCE; +// double minDistance = MAX_SAMPLE_DISANCE; + double minDistance = MAX_SAMPLE_DISANCE * MAX_SAMPLE_DISANCE; int minIndex = -1; for (int i = 0; i < availableCoord.size(); i++) { Coordinate coord = availableCoord.get(i); double x2 = coord.x; double y2 = coord.y; - double d = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); +// double d = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); + double dx = x2 - x1; + double dy = y2 - y1; + double d = (dx * dx) + (dy * dy); if (d < minDistance) { minDistance = d; diff --git a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminal4Panel.xml b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminal4Panel.xml index 969d6942df..b6a428a02d 100644 --- a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminal4Panel.xml +++ b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminal4Panel.xml @@ -24,8 +24,8 @@ @@ -38,17 +38,17 @@ - - - - + + + + @@ -61,10 +61,10 @@ - - - - + + + + - \ No newline at end of file + diff --git a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflVel.xml b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflVel.xml index 149cf60dc8..a4158266f6 100644 --- a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflVel.xml +++ b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflVel.xml @@ -29,17 +29,7 @@ - - - - - - - - - - + @@ -289,20 +279,10 @@ - + - - - - - - - - - @@ -552,7 +532,7 @@ - + - \ No newline at end of file + diff --git a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflectivityMotion.xml b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflectivityMotion.xml index 6c36c917d4..d98f3891e1 100644 --- a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflectivityMotion.xml +++ b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalReflectivityMotion.xml @@ -21,22 +21,6 @@ - - - - - - - - - - - - - - @@ -443,22 +427,6 @@ - - - - - - - - - - - - - - @@ -862,4 +830,4 @@ - \ No newline at end of file + diff --git a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalSRMSpecWidth.xml b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalSRMSpecWidth.xml index c000445c52..bc2752d053 100644 --- a/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalSRMSpecWidth.xml +++ b/cave/com.raytheon.viz.radar/localization/menus/radar/baseTerminalSRMSpecWidth.xml @@ -21,16 +21,6 @@ - - - - - - - - - @@ -284,12 +274,6 @@ - - - - - @@ -435,4 +419,4 @@ - \ No newline at end of file + diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java index 2579dc0a69..4a1a450838 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java @@ -281,6 +281,7 @@ import com.raytheon.viz.ui.dialogs.SWTMessageBox; * 06/19/2012 14975 D.Friedman Prevent zeroed-out WMO header times. * 18JUL2012 14457 rferrel Add mouse listener to clear site's update obs when clicked on. * 25JUL2012 14459 rferrel Strip WMH headers when getting all METARs. + * 13AUG2012 14613 M.Gamazaychikov Ensured the WMO and MND header times are the same. * * * @author lvenable @@ -4603,10 +4604,16 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, } boolean successful = false; - // Convert the text in the text editor to uppercase - String currentDate = getCurrentDate(); + /* + * DR14613 - string currectDate is derived from Date now + * ensuring the same time in WMO heading and in the + * MND heading. + */ + Date now = SimulatedTime.getSystemTime().getTime(); + String currentDate = getCurrentDate(now); TextDisplayModel tdmInst = TextDisplayModel.getInstance(); + // Convert the text in the text editor to uppercase if (!isAutoSave) { if (!verifyRequiredFields()) { return false; @@ -4642,14 +4649,13 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, VtecObject vtecObj = VtecUtil.parseMessage(productText); if (warnGenFlag) { - // TODO: Pass in some flavor of currentDate to use to set - // the - // times. Currently roll over to the next minute between - // getting - // currentDate and getting the times in this method will - // cause - // them to be different. - productText = updateVtecTimes(productText, vtecObj); + /* + * DR14613 - string currectDate is derived from Date now + * ensuring the same time in WMO heading and in the + * MND heading. + */ + productText = updateVtecTimes(productText, vtecObj, now); + productText = updateHeaderTimes(productText, now); // Update editor so the proper send times are displayed. String[] b = productText.split("\n"); StringBuilder body = new StringBuilder(); @@ -5110,19 +5116,28 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, headerTF.setText(""); } - private String getCurrentDate() { - Date now = SimulatedTime.getSystemTime().getTime(); + private String getCurrentDate(Date now) { + /* + * DR14613 - pass the Date now as an argument + */ SimpleDateFormat formatter = new SimpleDateFormat("ddHHmm"); formatter.setTimeZone(TimeZone.getTimeZone("GMT")); return (formatter.format(now)); } - private String updateVtecTimes(String product, VtecObject vtecObj) { + /** + * Update the VTEC time using the Date now. + * + * @param product + * @param vtecObj + * @param now + * @return + */ + private String updateVtecTimes(String product, VtecObject vtecObj, Date now) { if (vtecObj == null || vtecObj.getAction().equals("COR")) { return product; } - Date now = SimulatedTime.getSystemTime().getTime(); // Update the vtec start time if (vtecObj.getAction().equals("NEW")) { SimpleDateFormat vtecFormatter = new SimpleDateFormat( @@ -5131,9 +5146,20 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, product = product.replace( vtecFormatter.format(vtecObj.getStartTime().getTime()), vtecFormatter.format(now)); - } + } - // Update the header time + return product; + } + + /** + * Update the MND header time using the Date now. + * + * @param product + * @param now + * @return + */ + private String updateHeaderTimes(String product, Date now) { + // Update the header time Matcher m = datePtrn.matcher(product); if (m.find()) { SimpleDateFormat headerFormat = new SimpleDateFormat( @@ -5144,9 +5170,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, product = product.replace(m.group(1), headerFormat.format(now) .toUpperCase()); } - - return product; + return product; } + public void setCurrentWmoId(String wmoId) { TextDisplayModel.getInstance().setWmoId(token, wmoId); diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java index d043a14cad..245fbd8fde 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java @@ -1234,7 +1234,7 @@ public class WarngenLayer extends AbstractStormTrackResource { ((oldWarningPolygon.intersection(warningPolygon) .getArea() / oldWarningArea.getArea()) * 100)) .intValue(); - if (oldWarningPolygon.intersects(warningPolygon) == false + if (GeometryUtil.intersects(oldWarningPolygon, warningPolygon) == false && !state.isMarked()) { // Snap back to polygon state.setWarningPolygon(localToLatLon((Polygon) oldWarningPolygon)); @@ -1873,7 +1873,7 @@ public class WarngenLayer extends AbstractStormTrackResource { IDisplayPaneContainer container = getResourceContainer(); Coordinate[] coords = warningPolygon.getExteriorRing().getCoordinates(); - if (vertexId >= coords.length) { + if (vertexId >= coords.length || vertexId < 0) { return vertexId; } int rval = vertexId; diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java index 8b9b324bff..c7684911d7 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java @@ -126,7 +126,6 @@ public class WarngenUIManager extends InputAdapter { @Override public boolean handleMouseDown(int x, int y, int button) { warngenLayer.showDialog(true); - menuMove = false; lastMouseX = x; lastMouseY = y; if (!handleInput || warngenLayer.isBoxEditable() == false) { @@ -135,7 +134,7 @@ public class WarngenUIManager extends InputAdapter { boolean rval = false; if (button == 1 && moveType != null) { return true; - } else if (button == 2) { + } else if (button == 2 && menuMove == false) { /** Try to add vertex */ new AddVertexAction().run(); if (pointCreated) { @@ -202,8 +201,7 @@ public class WarngenUIManager extends InputAdapter { return super.handleMouseUp(x, y, mouseButton); } - - if (mouseButton == 3) { + if (mouseButton == 3 && menuMove == false) { Coordinate c = container.translateClick(x, y); WarngenUIState state = warngenLayer.getWarngenState(); boolean geomsEqual = true; @@ -245,13 +243,14 @@ public class WarngenUIManager extends InputAdapter { boolean rval = false; - if (moveType != null || pointDeleted || pointCreated) { + if (moveType != null || pointDeleted || pointCreated || menuMove) { try { if (moveType == MoveType.ALL_POINTS) { WarngenUIState state = warngenLayer.getWarngenState(); - Coordinate[] coordinates = state.getWarningPolygon().getCoordinates(); + Coordinate[] coordinates = state.getWarningPolygon() + .getCoordinates(); PolygonUtil.truncate(coordinates, 2); - + GeometryFactory gf = new GeometryFactory(); LinearRing lr = gf.createLinearRing(coordinates); state.setWarningPolygon(gf.createPolygon(lr, null)); @@ -265,15 +264,13 @@ public class WarngenUIManager extends InputAdapter { } pointDeleted = false; pointCreated = false; + menuMove = false; return rval; } @Override public boolean handleMouseMove(int x, int y) { if (menuMove) { - movePointIndex = StormTrackUIManager.getCoordinateIndex( - warngenLayer, warngenLayer.getPolygon().getCoordinates(), - new Coordinate(lastMouseX, lastMouseY)); move(x, y); warngenLayer.getWarngenState().geometryChanged = true; return true; @@ -426,7 +423,8 @@ public class WarngenUIManager extends InputAdapter { for (int i = 0; i < coords.length; ++i) { Coordinate toAdd = (Coordinate) coords[i].clone(); - if (!toAdd.equals(toRemove) || alreadyRemoved.contains(toAdd)) { + if (!toAdd.equals(toRemove) + || alreadyRemoved.contains(toAdd)) { coordList.add(toAdd); } else { alreadyRemoved.add(toAdd); @@ -441,11 +439,11 @@ public class WarngenUIManager extends InputAdapter { LinearRing lr = gf.createLinearRing(coordList .toArray(new Coordinate[coordList.size()])); Polygon newPoly = gf.createPolygon(lr, null); - + if (newPoly.isValid() == false) { return; } - + warngenLayer.getWarngenState().setWarningPolygon(newPoly); try { warngenLayer.updateWarnedAreas(true, true); @@ -498,6 +496,9 @@ public class WarngenUIManager extends InputAdapter { @Override public void run() { moveType = MoveType.SINGLE_POINT; + movePointIndex = StormTrackUIManager.getCoordinateIndex( + warngenLayer, warngenLayer.getPolygon().getCoordinates(), + new Coordinate(lastMouseX, lastMouseY)); menuMove = true; } @@ -511,6 +512,9 @@ public class WarngenUIManager extends InputAdapter { @Override public void run() { moveType = MoveType.ALL_POINTS; + movePointIndex = StormTrackUIManager.getCoordinateIndex( + warngenLayer, warngenLayer.getPolygon().getCoordinates(), + new Coordinate(lastMouseX, lastMouseY)); menuMove = true; } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java index 66434de188..eb82daa896 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java @@ -29,14 +29,15 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.HashMap; import java.util.Properties; import java.util.Set; +import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -100,7 +101,6 @@ import com.raytheon.viz.warngen.util.WeatherAdvisoryWatch; import com.raytheon.viz.warnings.DateUtil; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.prep.PreparedGeometry; import com.vividsolutions.jts.io.WKTReader; @@ -122,6 +122,7 @@ import com.vividsolutions.jts.io.WKTReader; * Jun 15, 2012 15043 Qinglu Lin Added duration to context. * Jul 16, 2012 15091 Qinglu Lin Compute intersection area, which is used for prevent 2nd timezone * from appearing in 2nd and 3rd bullets when not necessary. + * Aug 13, 2012 14493 Qinglu Lin Handled MND time, event time, and TML time specially for COR to NEW. * * * @@ -181,6 +182,7 @@ public class TemplateRunner { .getFrameTimes(); Date eventTime = datatimes != null && datatimes.length > 0 ? datatimes[datatimes.length - 1] .getRefTimeAsCalendar().getTime() : startTime; + Date simulatedTime = SimulatedTime.getSystemTime().getTime(); WarngenConfiguration config = warngenLayer.getConfiguration(); StormTrackState stormTrackState = warngenLayer.getStormTrackState(); @@ -236,6 +238,8 @@ public class TemplateRunner { AffectedAreas[] areas = null; AffectedAreas[] cancelareas = null; Map intersectAreas = null; + Wx wx = null; + long wwaMNDTime = 0l; try { t0 = System.currentTimeMillis(); areas = Area.findAffectedAreas(config, warnPolygon, warningArea, @@ -260,71 +264,92 @@ public class TemplateRunner { Set timeZones = new HashSet(); for (AffectedAreas area : areas) { if (area.getTimezone() != null) { - // Handles counties that span two time zones + // Handles counties that span two time zones String oneLetterTimeZones = area.getTimezone().trim(); oneLetterTZ = new String[oneLetterTimeZones.length()]; if (oneLetterTimeZones.length() == 1) { timeZones.add(String.valueOf(oneLetterTimeZones .charAt(0))); } else { - // Determine if one letter timezone is going to be put into timeZones. - Polygon[] poly1, poly2; - int n1, n2; - double size, totalSize; + // Determine if one letter timezone is going to be + // put into timeZones. + Polygon[] poly1, poly2; + int n1, n2; + double size, totalSize; for (int i = 0; i < oneLetterTimeZones.length(); i++) { - oneLetterTZ[i] = String.valueOf(oneLetterTimeZones.charAt(i)); - Geometry timezoneGeom = warngenLayer.getTimezoneGeom(oneLetterTZ[i]); - t0 = System.currentTimeMillis(); - poly1 = null; poly2 = null; - n1 = 0; n2 = 0; - size = 0.0d; totalSize = 0.0d; - if (timezoneGeom != null && warningArea!= null) { - if (intersectSize.get(oneLetterTZ[i]) != null) continue; - poly1 = new Polygon[warningArea.getNumGeometries()]; - n1 = warningArea.getNumGeometries(); - for (int j = 0; j < n1; j++) { - poly1[j] = (Polygon)warningArea.getGeometryN(j); - } - poly2 = new Polygon[timezoneGeom.getNumGeometries()]; - n2 = timezoneGeom.getNumGeometries(); - for (int j = 0; j < n2; j++) { - poly2[j] = (Polygon)timezoneGeom.getGeometryN(j); - } - // Calculate the total size of intersection - for (Polygon p1: poly1) { - for (Polygon p2: poly2) { - size = p1.intersection(p2).getArea(); - if (size > 0.0) - totalSize += size; - } - if (totalSize > minSize) break; //save time when the size of poly1 or poly2 is large - } - intersectSize.put(oneLetterTZ[i],totalSize); - } else - throw new VizException("Either timezoneGeom or/and warningArea is null. " + - "Timezone cannot be determined."); - System.out.println("Time to do size computation = " - + (System.currentTimeMillis() - t0)); - if (totalSize > minSize) { - timeZones.add(oneLetterTZ[i]); + oneLetterTZ[i] = String + .valueOf(oneLetterTimeZones.charAt(i)); + Geometry timezoneGeom = warngenLayer + .getTimezoneGeom(oneLetterTZ[i]); + t0 = System.currentTimeMillis(); + poly1 = null; + poly2 = null; + n1 = 0; + n2 = 0; + size = 0.0d; + totalSize = 0.0d; + if (timezoneGeom != null && warningArea != null) { + if (intersectSize.get(oneLetterTZ[i]) != null) + continue; + poly1 = new Polygon[warningArea + .getNumGeometries()]; + n1 = warningArea.getNumGeometries(); + for (int j = 0; j < n1; j++) { + poly1[j] = (Polygon) warningArea + .getGeometryN(j); + } + poly2 = new Polygon[timezoneGeom + .getNumGeometries()]; + n2 = timezoneGeom.getNumGeometries(); + for (int j = 0; j < n2; j++) { + poly2[j] = (Polygon) timezoneGeom + .getGeometryN(j); + } + // Calculate the total size of intersection + for (Polygon p1 : poly1) { + for (Polygon p2 : poly2) { + size = p1.intersection(p2) + .getArea(); + if (size > 0.0) + totalSize += size; + } + if (totalSize > minSize) + break; // save time when the size of + // poly1 or poly2 is large + } + intersectSize + .put(oneLetterTZ[i], totalSize); + } else + throw new VizException( + "Either timezoneGeom or/and warningArea is null. " + + "Timezone cannot be determined."); + System.out + .println("Time to do size computation = " + + (System.currentTimeMillis() - t0)); + if (totalSize > minSize) { + timeZones.add(oneLetterTZ[i]); } } - // If timeZones has nothing in it when the hatched area is very small, - // use the timezone of larger intersection size. - if (timeZones.size() == 0 ) { - if (intersectSize.size() > 1) - if (intersectSize.get(oneLetterTZ[0]) > intersectSize.get(oneLetterTZ[1])) { - timeZones.add(oneLetterTZ[0]); - } else { - timeZones.add(oneLetterTZ[1]); - } - else - throw new VizException("The size of intersectSize is less than 1, " + - "timezone cannot be determined."); - } + // If timeZones has nothing in it when the hatched + // area is very small, + // use the timezone of larger intersection size. + if (timeZones.size() == 0) { + if (intersectSize.size() > 1) + if (intersectSize.get(oneLetterTZ[0]) > intersectSize + .get(oneLetterTZ[1])) { + timeZones.add(oneLetterTZ[0]); + } else { + timeZones.add(oneLetterTZ[1]); + } + else + throw new VizException( + "The size of intersectSize is less than 1, " + + "timezone cannot be determined."); + } } } else { - throw new VizException("Calling to area.getTimezone() returns null."); + throw new VizException( + "Calling to area.getTimezone() returns null."); } } @@ -342,12 +367,16 @@ public class TemplateRunner { if (!(selectedAction == WarningAction.CAN || selectedAction == WarningAction.EXP)) { Coordinate[] stormLocs = warngenLayer .getStormLocations(stormTrackState); - Wx wx = new Wx(config, stormTrackState, + wx = new Wx(config, stormTrackState, warngenLayer.getStormLocations(stormTrackState), startTime.getTime(), DateUtil.roundDateTo15(endTime) .getTime(), warnPolygon); - context.put("now", SimulatedTime.getSystemTime().getTime()); - context.put("start", wx.getStartTime()); + if (selectedAction == WarningAction.COR) { + wwaMNDTime = wx.getStartTime().getTime(); + } else { + context.put("now", simulatedTime); + context.put("start", wx.getStartTime()); + } context.put( "expire", DateUtil.roundDateTo15(selectedAction == WarningAction.EXT ? endTime @@ -359,6 +388,7 @@ public class TemplateRunner { context.put("duration", duration); context.put("event", eventTime); + context.put("TMLtime", eventTime); context.put("ugcline", FipsUtil.getUgcLine(areas, wx.getEndTime(), 15)); context.put("areaPoly", GisUtil.convertCoords(warngenLayer @@ -382,7 +412,7 @@ public class TemplateRunner { StormTrackData std = ToolsDataManager.getInstance() .getStormTrackData(); - std.setDate(SimulatedTime.getSystemTime().getTime()); + std.setDate(simulatedTime); std.setMotionDirection((int) wx.getMovementDirection()); std.setMotionSpeed((int) Math.round(wx.getMovementSpeed("kn"))); @@ -418,11 +448,12 @@ public class TemplateRunner { // Example: s[0-5] = T.CON-KLWX.SV.W.0123 AbstractWarningRecord oldWarn = CurrentWarnings.getInstance( threeLetterSiteId).getNewestByTracking(etn, phenSig); - context.put("now", SimulatedTime.getSystemTime().getTime()); + context.put("now", simulatedTime); context.put("event", eventTime); context.put("start", oldWarn.getStartTime().getTime()); context.put("expire", oldWarn.getEndTime().getTime()); Calendar canOrExpCal = Calendar.getInstance(); + canOrExpCal.setTimeZone(TimeZone.getTimeZone("GMT")); canOrExpCal.add(Calendar.MINUTE, 10); canOrExpCal.add(Calendar.MILLISECOND, 1); context.put( @@ -452,7 +483,7 @@ public class TemplateRunner { StormTrackData std = ToolsDataManager.getInstance() .getStormTrackData(); - std.setDate(SimulatedTime.getSystemTime().getTime()); + std.setDate(simulatedTime); std.setMotionDirection(oldWarn.getMotdir()); std.setMotionSpeed(oldWarn.getMotspd()); t0 = System.currentTimeMillis(); @@ -515,8 +546,68 @@ public class TemplateRunner { } context.put("etn", etn); context.put("start", oldWarn.getIssueTime().getTime()); - context.put("now", SimulatedTime.getSystemTime().getTime()); + if (oldWarn.getAct().equals("NEW")) { + context.put("now", new Date(wwaMNDTime)); + } else + context.put("now", simulatedTime); context.put("event", oldWarn.getIssueTime().getTime()); + + String message = oldWarn.getRawmessage(); + if (!stormTrackState.originalTrack) { + context.put("TMLtime", oldWarn.getStartTime().getTime()); + } else { + int hour = 0; + int minute = 0; + int tmlIndex = message.indexOf("TIME...MOT...LOC"); + int zIndex = -1; + if (tmlIndex > 0) { + zIndex = message.indexOf("Z", tmlIndex); + if (zIndex > 0) { + int startIndex = tmlIndex+16+1; + String tmlTime = null; + tmlTime = message.substring(startIndex,startIndex+4); + if (tmlTime.length() == 4) { + hour = Integer.parseInt(tmlTime.substring(0,2)); + minute = Integer.parseInt(tmlTime.substring(2,4)); + } else if (tmlTime.length() == 3) { + hour = Integer.parseInt(tmlTime.substring(0,1)); + minute = Integer.parseInt(tmlTime.substring(1,3)); + } else { + throw new VizException("The length of hour and minute for TML time is neither 3 nor 4."); + } + Calendar c = Calendar.getInstance(); + c.set(Calendar.HOUR_OF_DAY,hour); + c.set(Calendar.MINUTE, minute); + context.put("TMLtime", c.getTime()); + } else { + throw new VizException("Z, therefore hour and minute, cannot be found in TIME...MOT...LOC line."); + } + } else { + // To prevent errors resulting from undefined context("TMLtime") + context.put("TMLtime", oldWarn.getIssueTime().getTime()); + } + } + + // corEventtime for "COR to NEW", not for "COR to CON, CAN, or CANCON" + if (oldWarn.getAct().equals("NEW")) { + int untilIndex = message.indexOf("UNTIL"); + int atIndex = -1; + int elipsisIndex = -1; + if (untilIndex > 0) { + atIndex = message.indexOf("AT", untilIndex); + if (atIndex > 0) { + int hhmmIndex = atIndex+3; + elipsisIndex = message.indexOf("...", hhmmIndex); + if (elipsisIndex > 0) { + context.put("corToNewMarker","cortonewmarker"); + context.put("corEventtime",message.substring(hhmmIndex,elipsisIndex)); + } + } + } + if (untilIndex < 0 || atIndex < 0 || elipsisIndex < 0) + throw new VizException("Cannot find * AT line."); + } + Calendar cal = oldWarn.getEndTime(); cal.add(Calendar.MILLISECOND, 1); context.put("expire", cal.getTime()); @@ -547,7 +638,9 @@ public class TemplateRunner { context.put("expire", oldWarn.getEndTime().getTime()); context.put("ugcline", FipsUtil.getUgcLine(areas, oldWarn .getEndTime().getTime(), 15)); - Calendar cancelTime = (Calendar) oldWarn.getEndTime().clone(); + Calendar cancelTime = Calendar.getInstance(); + cancelTime.setTime(simulatedTime); + cancelTime.setTimeZone(TimeZone.getTimeZone("GMT")); cancelTime.add(Calendar.MINUTE, 10); String[] tmp = compareGeomsForFollowUp(oldWarn, warnPolygon, areas, cancelTime.getTime(), config); diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java index c9d961d6a6..42fd0764bd 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/util/WarningTextHandler.java @@ -63,8 +63,7 @@ import com.raytheon.viz.warngen.gis.AffectedAreasComparator; * c)Locking does not work for areal flood advisory followup; * d)NullointException/locking does not work for special marine warning * and locking beyond first paragragh. - * Jul 17, 2012 14989 Qinglu Lin Removed locks, and , for county names in pathcast line. - * Aug 6, 2012 15219 Qinglu Lin For tmlPtrn, changed d{1,3}DEG to d{3}DEG. + * Jul 17, 2012 14989 Qinglu Lin Removed locks, and , for county names in pathcast line. * * * @@ -134,10 +133,14 @@ public class WarningTextHandler { .compile("(\\.\\.\\.((A|THE)\\s(.*)\\s(WARNING|ADVISORY))\\s(FOR|(REMAINS IN EFFECT (|(UNTIL\\s\\d{3,4}\\s(AM|PM)\\s\\w{3})))))(|(.*))"); private static final Pattern canVtecPtrn = Pattern.compile("(\\.CAN\\.)"); + private static final Pattern smwCanPtrn = Pattern.compile("(\\.MA\\.W\\.)"); + private static final Pattern afaCanPtrn = Pattern.compile("(\\.FA\\.Y\\.)"); - private static final Pattern smwHeadlinePtrn = Pattern.compile("(THE AFFECTED AREAS WERE)"); - + + private static final Pattern smwHeadlinePtrn = Pattern + .compile("(THE AFFECTED AREAS WERE)"); + private static Pattern immediateCausePtrn = null; /** ex. SARPY NE-DOUGLAS NE-WASHINGTON NE- */ @@ -155,19 +158,22 @@ public class WarningTextHandler { private static final Pattern subLatLonPtrn = Pattern .compile("^((?!TIME...MOT... LOC))\\s{1,}\\d{3,4}\\s\\d{3,5}(|(\\s\\d{3,4}\\s\\d{3,5}){1,})"); - + private static final Pattern tmlPtrn = Pattern - .compile("TIME...MOT...LOC \\d{3,4}Z\\s\\d{3}DEG\\s\\d{1,3}KT((\\s\\d{3,4}\\s\\d{3,5}){1,})"); + .compile("TIME...MOT...LOC \\d{3,4}Z\\s\\d{3}DEG\\s\\d{1,3}KT((\\s\\d{3,4}\\s\\d{3,5}){1,})"); private static final Pattern subTMLPtrn = Pattern .compile("(\\d{3,5}\\s){1,}"); private static final Pattern lockedBlankLinesPattern = Pattern.compile( "(\\s*+)", Pattern.MULTILINE); - - private static final String LOCK_REPLACEMENT_TEXT = LOCK_START + "$0" + LOCK_END; - private static final Pattern extraTokensPattern = Pattern.compile("\\b(?:THE|IS|CANCELLED)\\b"); - + + private static final String LOCK_REPLACEMENT_TEXT = LOCK_START + "$0" + + LOCK_END; + + private static final Pattern extraTokensPattern = Pattern + .compile("\\b(?:THE|IS|CANCELLED)\\b"); + static { String pattern = ""; @@ -177,7 +183,7 @@ public class WarningTextHandler { pattern = "(.*)(A DAM BREAK"; for (String ic : immediateCause.split("\n")) { String[] parts = ic.split("\\\\"); - pattern += "|" + parts[1].trim(); + pattern += "| " + parts[1].trim(); } pattern += ")(.*)"; immediateCausePtrn = Pattern.compile(pattern); @@ -190,8 +196,8 @@ public class WarningTextHandler { } public static String handle(String originalMessage, AffectedAreas[] areas, - AffectedAreas[] canceledAreas, WarningAction action, WarningAction action2, - boolean autoLock) { + AffectedAreas[] canceledAreas, WarningAction action, + WarningAction action2, boolean autoLock) { long t0 = System.currentTimeMillis(); if (action == WarningAction.NEW) { try { @@ -294,9 +300,10 @@ public class WarningTextHandler { boolean startLines = true; - // Set before to false if the line is beyond "THE NATIONAL WEATHER SERVICE IN" line. + // Set before to false if the line is beyond + // "THE NATIONAL WEATHER SERVICE IN" line. boolean before = true; - + boolean isCancelledFound = false; // for CAN of CANCON of Special Marine Warning @@ -305,56 +312,57 @@ public class WarningTextHandler { // for CAN of CANCON of Areal Flood Advisory boolean afaCan = false; - int afaCanBlankline = 0; + int afaCanBlankline = 0; String[] tokens = null; if (canceledAreas != null) { - String areaNames = ""; - for (AffectedAreas area : canceledAreas) { - String areaName = area.getName(); - if (areaName != null && areaName.length()>0) { - areaName = areaName.toUpperCase(); - areaNames += areaName + " "; - } - } - areaNames = areaNames.trim(); - HashSet areaNameSet = new HashSet(); - String[] tokens0 = areaNames.split(" "); - int tokensLength = tokens0.length; - for (int i=0;i s0.length()) { - s1 = s0; - s0 = tokens[j]; - tokens[j] = s1; - } - } - tokens[i] = s0; - } + String areaNames = ""; + for (AffectedAreas area : canceledAreas) { + String areaName = area.getName(); + if (areaName != null && areaName.length() > 0) { + areaName = areaName.toUpperCase(); + areaNames += areaName + " "; + } + } + areaNames = areaNames.trim(); + HashSet areaNameSet = new HashSet(); + String[] tokens0 = areaNames.split(" "); + int tokensLength = tokens0.length; + for (int i = 0; i < tokensLength; i++) { + areaNameSet.add(tokens0[i]); + } + + tokens = (String[]) areaNameSet.toArray(new String[areaNameSet + .size()]); + String s0; + for (int i = 0; i < areaNameSet.size() - 1; i++) { + s0 = tokens[i]; + String s1; + for (int j = i; j < areaNameSet.size(); j++) { + if (tokens[j].length() > s0.length()) { + s1 = s0; + s0 = tokens[j]; + tokens[j] = s1; + } + } + tokens[i] = s0; + } } - boolean ruralFound=false, ruralReplace=false; + boolean ruralFound = false, ruralReplace = false; ArrayList usedAreaNotations = new ArrayList(); for (int lineIndex = 0; lineIndex < seperatedLines.length; ++lineIndex) { String line = seperatedLines[lineIndex]; - if (line.contains("THE NATIONAL WEATHER SERVICE IN") || line.contains("OTHER LOCATIONS IMPACTED")) { + if (line.contains("THE NATIONAL WEATHER SERVICE IN") + || line.contains("OTHER LOCATIONS IMPACTED")) { before = false; } - + if (!ruralFound && line.contains("MAINLY RURAL AREAS")) { - ruralFound = true; + ruralFound = true; } - + // This prevents blank line(s) after the header from being locked. if (startLines && lineIndex > 1) { startLines = line.trim().length() == 0; @@ -394,10 +402,10 @@ public class WarningTextHandler { cancelVtecLineFound = true; m = smwCanPtrn.matcher(line); if (m.find()) - smwCan = true; + smwCan = true; m = afaCanPtrn.matcher(line); if (m.find()) - afaCan = true; + afaCan = true; } continue; } @@ -410,13 +418,14 @@ public class WarningTextHandler { } if (before) { - m = listOfAreaNamePtrn.matcher(line); - if (m.find()) { - if (!(line.contains("!**") || line.contains("**!") || line.contains("OTHER LOCATIONS"))) { - sb.append(LOCK_START + line + "\n" + LOCK_END); - continue; - } - } + m = listOfAreaNamePtrn.matcher(line); + if (m.matches()) { + if (!(line.contains("!**") || line.contains("**!") || line + .contains("OTHER LOCATIONS"))) { + sb.append(LOCK_START + line + "\n" + LOCK_END); + continue; + } + } } // Locking Date in the MND header @@ -427,35 +436,34 @@ public class WarningTextHandler { } if (ruralFound) - if (!ruralReplace) - ruralReplace = true; - else - if (ruralReplace) { - if (line.trim().length() == 0) - ruralFound = false; - else { - line = line.replace("",""); - line = line.replace("",""); - sb.append(line + "\n"); - continue; - } - } + if (!ruralReplace) + ruralReplace = true; + else if (ruralReplace) { + if (line.trim().length() == 0) + ruralFound = false; + else { + line = line.replace("", ""); + line = line.replace("", ""); + sb.append(line + "\n"); + continue; + } + } if (line.trim().length() == 0) { insideTML = false; insideLatLon = false; headlineFound = false; if (smwCan) { - if (lockSmwCan) - cancelVtecLineFound = false; - lockSmwCan = false; + if (lockSmwCan) + cancelVtecLineFound = false; + lockSmwCan = false; } if (afaCan) { - afaCanBlankline += 1; - if (afaCanBlankline > 1) { - afaCan = false; - cancelVtecLineFound = false; - } + afaCanBlankline += 1; + if (afaCanBlankline > 1) { + afaCan = false; + cancelVtecLineFound = false; + } } if (startLines) { // Don't lock blank line after header @@ -564,134 +572,151 @@ public class WarningTextHandler { continue; } } else { - usedAreaNotations.clear(); - // head line pattern - m = headlinePtrn.matcher(line); - if (m.find()) { - checkForMND = false; - headlineFound = true; - line = line.replace(m.group(2), LOCK_START + m.group(2) - + LOCK_END); - } - // CAN portion in a CANCON - if (cancelVtecLineFound) { - if (smwCan) { - // lock marine zone names - if (lockSmwCan) { - if (line.length()==0) { - lockSmwCan = false; - } else - line = LOCK_START + line + LOCK_END; - } else { - m = smwHeadlinePtrn.matcher(line); - if (m.find()) - lockSmwCan = true; - } - } else { - for (String s: tokens) - if (line.contains(s)) - line = line.replace(s, LOCK_START - + s + LOCK_END); - for (AffectedAreas area : canceledAreas) { - String areaNotation = area.getAreaNotation(); - if (areaNotation != null) { - // areaNotation, e.g., COUNTY - if (areaNotation != null && areaNotation.length()>0 - && !usedAreaNotations.contains(areaNotation) - && line.contains(areaNotation)) { - line = line.replaceAll(areaNotation, LOCK_START - + areaNotation + LOCK_END); - usedAreaNotations.add(areaNotation); - } - // areasNotation, e.g., COUNTIES - String areasNotation = area.getAreasNotation().toUpperCase(); - if (areasNotation != null && areasNotation.length()>0 - && !usedAreaNotations.contains(areasNotation) - && line.contains(areasNotation)) { - line = line.replaceAll(areasNotation, LOCK_START - + areasNotation + LOCK_END); - usedAreaNotations.add(areasNotation); - } - } - } - // locking "THE" in "THE CITY OF MANASSAS", "...THE" in "...THE CITY", - // and "IS" or "CANCELLED" in "IS CANCELLED...". - line = extraTokensPattern.matcher(line).replaceAll( - LOCK_REPLACEMENT_TEXT); - } + usedAreaNotations.clear(); + // head line pattern + m = headlinePtrn.matcher(line); + if (m.find()) { + checkForMND = false; + headlineFound = true; + line = line.replace(m.group(2), LOCK_START + m.group(2) + + LOCK_END); + } + // CAN portion in a CANCON + if (cancelVtecLineFound) { + if (smwCan) { + // lock marine zone names + if (lockSmwCan) { + if (line.length() == 0) { + lockSmwCan = false; + } else + line = LOCK_START + line + LOCK_END; + } else { + m = smwHeadlinePtrn.matcher(line); + if (m.find()) + lockSmwCan = true; + } + } else { + for (String s : tokens) + if (line.contains(s)) + line = line.replace(s, LOCK_START + s + + LOCK_END); + for (AffectedAreas area : canceledAreas) { + String areaNotation = area.getAreaNotation(); + if (areaNotation != null) { + // areaNotation, e.g., COUNTY + if (areaNotation != null + && areaNotation.length() > 0 + && !usedAreaNotations + .contains(areaNotation) + && line.contains(areaNotation)) { + line = line.replaceAll(areaNotation, + LOCK_START + areaNotation + + LOCK_END); + usedAreaNotations.add(areaNotation); + } + // areasNotation, e.g., COUNTIES + String areasNotation = area + .getAreasNotation().toUpperCase(); + if (areasNotation != null + && areasNotation.length() > 0 + && !usedAreaNotations + .contains(areasNotation) + && line.contains(areasNotation)) { + line = line.replaceAll(areasNotation, + LOCK_START + areasNotation + + LOCK_END); + usedAreaNotations.add(areasNotation); + } + } + } + // locking "THE" in "THE CITY OF MANASSAS", "...THE" + // in "...THE CITY", + // and "IS" or "CANCELLED" in "IS CANCELLED...". + line = extraTokensPattern.matcher(line).replaceAll( + LOCK_REPLACEMENT_TEXT); + } - if (cancelVtecLineFound && isCancelledFound) - cancelVtecLineFound = false; + if (cancelVtecLineFound && isCancelledFound) + cancelVtecLineFound = false; - m = cancelOnlyPtrn.matcher(line); - if (m.find()) - cancelVtecLineFound = false; + m = cancelOnlyPtrn.matcher(line); + if (m.find()) + cancelVtecLineFound = false; - sb.append(line + "\n"); - continue; - } else { - // follow-ups other than CAN in a CANCON - if (headlineFound) { - usedAreaNotations.clear(); - if (areas != null && !marineProduct) { - for (AffectedAreas area : areas) { - if (area.getName() != null - && line.contains(area.getName() - .toUpperCase())) { - line = line.replaceFirst(area.getName() - .toUpperCase(), LOCK_START - + area.getName().toUpperCase() - + LOCK_END); - } + sb.append(line + "\n"); + continue; + } else { + // follow-ups other than CAN in a CANCON + if (headlineFound) { + usedAreaNotations.clear(); + if (areas != null && !marineProduct) { + for (AffectedAreas area : areas) { + if (area.getName() != null + && line.contains(area.getName() + .toUpperCase())) { + line = line.replaceFirst(area.getName() + .toUpperCase(), LOCK_START + + area.getName().toUpperCase() + + LOCK_END); + } - if (area.getAreaNotation() != null - && !usedAreaNotations.contains(area - .getAreaNotation() - .toUpperCase()) - && line.contains(area.getAreaNotation())) { - line = line.replaceAll(" " - + area.getAreaNotation() - .toUpperCase(), LOCK_START - + " " + area.getAreaNotation() - + LOCK_END); - usedAreaNotations.add(area - .getAreaNotation().toUpperCase()); - } - } - } + if (area.getAreaNotation() != null + && !usedAreaNotations.contains(area + .getAreaNotation() + .toUpperCase()) + && line.contains(area + .getAreaNotation())) { + line = line + .replaceAll( + " " + + area.getAreaNotation() + .toUpperCase(), + LOCK_START + + " " + + area.getAreaNotation() + + LOCK_END); + usedAreaNotations.add(area + .getAreaNotation() + .toUpperCase()); + } + } + } - m = cancelPtrn.matcher(line); - if (m.find()) { - line = line.replaceFirst(m.group(3), - LOCK_START + m.group(3) + LOCK_END); - if (canceledAreas != null) { - for (AffectedAreas canceledArea : canceledAreas) { - if (line.contains(canceledArea.getName() - .toUpperCase())) { - line = line.replaceFirst(canceledArea - .getName().toUpperCase(), - LOCK_START - + canceledArea - .getName() - .toUpperCase() - + LOCK_END); - } - } - } - headlineFound = false; - } + m = cancelPtrn.matcher(line); + if (m.find()) { + line = line.replaceFirst(m.group(3), LOCK_START + + m.group(3) + LOCK_END); + if (canceledAreas != null) { + for (AffectedAreas canceledArea : canceledAreas) { + if (line.contains(canceledArea + .getName().toUpperCase())) { + line = line + .replaceFirst( + canceledArea + .getName() + .toUpperCase(), + LOCK_START + + canceledArea + .getName() + .toUpperCase() + + LOCK_END); + } + } + } + headlineFound = false; + } - m = expirePtrn.matcher(line); - if (m.find()) { - line = line.replaceFirst(m.group(3), - LOCK_START + m.group(3) + LOCK_END); - headlineFound = false; - } + m = expirePtrn.matcher(line); + if (m.find()) { + line = line.replaceFirst(m.group(3), LOCK_START + + m.group(3) + LOCK_END); + headlineFound = false; + } - sb.append(line + "\n"); - continue; - } - } + sb.append(line + "\n"); + continue; + } + } } // Locking LAT...LON @@ -705,7 +730,7 @@ public class WarningTextHandler { if (insideLatLon) { m = subLatLonPtrn.matcher(line); if (m.find()) { - sb.append(LOCK_START +line + "\n" + LOCK_END); + sb.append(LOCK_START + line + "\n" + LOCK_END); continue; } else { insideLatLon = false; @@ -721,7 +746,7 @@ public class WarningTextHandler { // Locking TIME...MOT..LOC m = tmlPtrn.matcher(line); if (m.find()) { - sb.append(LOCK_START + line + "\n"+ LOCK_END); + sb.append(LOCK_START + line + "\n" + LOCK_END); insideTML = true; continue; } @@ -739,22 +764,22 @@ public class WarningTextHandler { // Test lines if (line.equals(TEST_MSG3) - || line.equals(TEST_MSG1) - || (line.startsWith("TEST...") && line - .endsWith("...TEST"))) { - sb.append(LOCK_START + line + LOCK_END + "\n"); - continue; - } + || line.equals(TEST_MSG1) + || (line.startsWith("TEST...") && line + .endsWith("...TEST"))) { + sb.append(LOCK_START + line + LOCK_END + "\n"); + continue; + } m = testMessagePtrn.matcher(line); if (m.find()) { - line = line.replace(m.group(2), LOCK_START + m.group(2) - + LOCK_END); + line = line.replace(m.group(2), LOCK_START + m.group(2) + + LOCK_END); } } catch (Exception e) { - // If an exception is thrown, - // log the exception but continue locking text - statusHandler.handle(Priority.PROBLEM, "Error locking line: " - + line + "\n", e); + // If an exception is thrown, + // log the exception but continue locking text + statusHandler.handle(Priority.PROBLEM, "Error locking line: " + + line + "\n", e); } sb.append(line + "\n"); insideLatLon = false; @@ -850,31 +875,32 @@ public class WarningTextHandler { return sb.toString(); } - + private static String wrapLocations(String locationsLine) { StringBuffer sb = new StringBuffer(); - + String line = " "; String[] locations = locationsLine.split("\\.\\.\\."); - + for (int i = 0; i < locations.length; i++) { String location = locations[i]; - int size = (i == locations.length - 1)? location.length() : location.length() + 3; - + int size = (i == locations.length - 1) ? location.length() + : location.length() + 3; + if (line.length() + size >= MAX_WIDTH - 2) { sb.append(line + "\n"); line = " "; - } - + } + if (i == locations.length - 1) { line += location; } else { line += location + "..."; } } - + sb.append(line + "\n"); - + return sb.toString(); } diff --git a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/AbstractWarningResource.java b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/AbstractWarningResource.java index 01c2c12ded..5b656e505e 100644 --- a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/AbstractWarningResource.java +++ b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/AbstractWarningResource.java @@ -3,6 +3,7 @@ package com.raytheon.viz.warnings.rsc; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -74,7 +75,8 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; * in a given display frame * Jun 04, 2012 DR14992 mgamazaychikov Reversed the textToPrint array to * plot the strings in correct order - * + * Aug 09, 2012 DR 15166 D.Friedman Plot only the most recent record for + * an event. * * * @author jsanchez @@ -530,77 +532,94 @@ public abstract class AbstractWarningResource extends AbstractWWAResource lastFrame = true; } synchronized (paintLock) { - for (String datauri : entryMap.keySet()) { - WarningEntry entry = entryMap.get(datauri); - AbstractWarningRecord record = entry.record; + HashMap candidates = + new HashMap(); + for (WarningEntry entry : entryMap.values()) { if (matchesFrame(entry, paintProps.getDataTime(), framePeriod, lastFrame)) { + String key = getEventKey(entry); + WarningEntry current = candidates.get(key); + + if (current == null || current.record.getIssueTime(). + before(entry.record.getIssueTime()) || + (current.record.getIssueTime().equals(entry.record.getIssueTime()) && + current.record.getInsertTime().before(entry.record.getInsertTime())) + ) + candidates.put(key, entry); + } + } + for (WarningEntry entry : candidates.values()) { + AbstractWarningRecord record = entry.record; - // check shapes - if (entry.project) { - initShape(target, entry.record); - entry.project = false; - } + // check shapes + if (entry.project) { + initShape(target, entry.record); + entry.project = false; + } - if (entry != null && entry.wireframeShape != null) { - LineStyle lineStyle = (record.getProductClass() != null && record - .getProductClass().equals("T")) ? LineStyle.DASHED - : LineStyle.SOLID; - target.drawWireframeShape(entry.wireframeShape, - getCapability(ColorableCapability.class) - .getColor(), - getCapability(OutlineCapability.class) - .getOutlineWidth(), lineStyle); - } else if (entry != null && entry.shadedShape != null) { - target.drawShadedShape(entry.shadedShape, 1); - } + if (entry != null && entry.wireframeShape != null) { + LineStyle lineStyle = (record.getProductClass() != null && record + .getProductClass().equals("T")) ? LineStyle.DASHED + : LineStyle.SOLID; + target.drawWireframeShape(entry.wireframeShape, + getCapability(ColorableCapability.class) + .getColor(), + getCapability(OutlineCapability.class) + .getOutlineWidth(), lineStyle); + } else if (entry != null && entry.shadedShape != null) { + target.drawShadedShape(entry.shadedShape, 1); + } - if (record != null && record.getGeometry() != null) { - // Calculate the upper left portion of the polygon - Coordinate upperLeft = new Coordinate(180, -90); + if (record != null && record.getGeometry() != null) { + // Calculate the upper left portion of the polygon + Coordinate upperLeft = new Coordinate(180, -90); - for (Coordinate c : record.getGeometry() - .getCoordinates()) { - if (c.y - c.x > upperLeft.y - upperLeft.x) { - upperLeft = c; - } + for (Coordinate c : record.getGeometry() + .getCoordinates()) { + if (c.y - c.x > upperLeft.y - upperLeft.x) { + upperLeft = c; } - - double[] d = descriptor.worldToPixel(new double[] { - upperLeft.x, upperLeft.y }); - d[0] -= paintProps.getZoomLevel() * 100; - - double mapWidth = descriptor.getMapWidth() - * paintProps.getZoomLevel() / 1000; - String[] textToPrint = getText(record, mapWidth); - if (warningsFont == null) { - warningsFont = target.getDefaultFont() - .deriveWithSize(11); - } - // DR14992: reverse the textToPrint array to plot the strings in correct order - String [] textToPrintReversed = new String[textToPrint.length]; - for(int i = 0; i < textToPrint.length; i++) { - textToPrintReversed[i] = textToPrint[textToPrint.length - - i - 1]; - } - - DrawableString params = new DrawableString(textToPrintReversed, - color); - params.font = warningsFont; - params.setCoordinates(d[0], d[1]); - params.textStyle = TextStyle.NORMAL; - params.horizontalAlignment = HorizontalAlignment.RIGHT; - params.verticallAlignment = VerticalAlignment.BOTTOM; - params.magnification = getCapability( - MagnificationCapability.class) - .getMagnification(); - target.drawStrings(params); } + + double[] d = descriptor.worldToPixel(new double[] { + upperLeft.x, upperLeft.y }); + d[0] -= paintProps.getZoomLevel() * 100; + + double mapWidth = descriptor.getMapWidth() + * paintProps.getZoomLevel() / 1000; + String[] textToPrint = getText(record, mapWidth); + if (warningsFont == null) { + warningsFont = target.getDefaultFont() + .deriveWithSize(11); + } + // DR14992: reverse the textToPrint array to plot the strings in correct order + String [] textToPrintReversed = new String[textToPrint.length]; + for(int i = 0; i < textToPrint.length; i++) { + textToPrintReversed[i] = textToPrint[textToPrint.length + - i - 1]; + } + + DrawableString params = new DrawableString(textToPrintReversed, + color); + params.font = warningsFont; + params.setCoordinates(d[0], d[1]); + params.textStyle = TextStyle.NORMAL; + params.horizontalAlignment = HorizontalAlignment.RIGHT; + params.verticallAlignment = VerticalAlignment.BOTTOM; + params.magnification = getCapability( + MagnificationCapability.class) + .getMagnification(); + target.drawStrings(params); } } } } + private static String getEventKey(WarningEntry entry) { + AbstractWarningRecord r = entry.record; + return r.getOfficeid() + '.' + r.getPhensig() + '.' + r.getEtn(); + } + protected boolean matchesFrame(WarningEntry entry, DataTime paintTime, TimeRange framePeriod, boolean lastFrame) { TimeRange recordPeriod = new TimeRange(entry.record.getStartTime() diff --git a/edexOsgi/build.edex/esb/conf/log4j-ingest.xml b/edexOsgi/build.edex/esb/conf/log4j-ingest.xml index e0bfcfe222..ac6f7fb20a 100644 --- a/edexOsgi/build.edex/esb/conf/log4j-ingest.xml +++ b/edexOsgi/build.edex/esb/conf/log4j-ingest.xml @@ -8,6 +8,10 @@ + + + + @@ -130,8 +134,8 @@ - - + + diff --git a/edexOsgi/build.edex/esb/conf/log4j.xml b/edexOsgi/build.edex/esb/conf/log4j.xml index 2ee48f8aa3..f28ba3d6c3 100644 --- a/edexOsgi/build.edex/esb/conf/log4j.xml +++ b/edexOsgi/build.edex/esb/conf/log4j.xml @@ -8,6 +8,10 @@ + + + + @@ -19,6 +23,10 @@ + + + + @@ -28,14 +36,14 @@ - + - + - + @@ -104,6 +112,6 @@ - + - + diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/TimeRange.py b/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/TimeRange.py index 44bc649634..2cd383d2a3 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/TimeRange.py +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/TimeRange.py @@ -126,6 +126,18 @@ class TimeRange(JUtil.JavaWrapperClass): def __ne__(self, other): return not self == other + def __lt__(self, other): + return self.__tr.compareTo(other.toJavaObj()) < 0 + + def __le__(self, other): + return self.__tr.compareTo(other.toJavaObj()) <= 0 + + def __gt__(self, other): + return self.__tr.compareTo(other.toJavaObj()) > 0 + + def __ge__(self, other): + return self.__tr.compareTo(other.toJavaObj()) >= 0 + def __hash__(self): if not self.__hash: self.__hash = self.startTime().unixTime() ^ self.endTime().unixTime() @@ -134,6 +146,9 @@ class TimeRange(JUtil.JavaWrapperClass): def __str__(self): return str(self.__tr.toString()) + def __repr__(self): + return str(self.__tr.toString()) + def javaTimeRangeListToPyList(timeRanges): pylist = [] size = timeRanges.size() diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/VM_global_library.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/VM_global_library.vm index 25017c4ad7..04ffc77be2 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/VM_global_library.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/VM_global_library.vm @@ -2,6 +2,7 @@ ##### Qinglu Lin 04-04-2012 DR 14691. ##### Qinglu Lin 06-18-2012 DR 15043. Use duration in secondBullet. ##### Qinglu Lin 07-31-2012 DR 15217. Use roundAndPad for movement direction in DEG. +##### Qinglu Lin 08-13-2012 DR 14493. Use corToNewMarker and corEventtime. #################################################################################################### Mile Marker Test Code macro "mmarkers" use (called out of VM_global_library.vm): @@ -660,7 +661,11 @@ UNTIL ${dateUtil.format(${expire}, ${timeFormat.clock}, 15, ${localtimezone})}## #end #macro(thirdBullet $dateUtil $eventtime $timeFormat $localtimezone $secondtimezone) +#if(${corToNewMarker}) +AT ${corEventtime}## +#else AT ${dateUtil.format(${eventtime}, ${timeFormat.clock}, ${localtimezone})}## +#end #if(${secondtimezone}) /${dateUtil.format(${eventtime}, ${timeFormat.clock}, ${secondtimezone})}/## #end diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/customTemplate.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/customTemplate.vm index 1bfd43192f..a3323ebfad 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/customTemplate.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/customTemplate.vm @@ -1,6 +1,8 @@ -##################### +#################################################################### ## CUSTOM TEMPLATE ## -##################### +## History +## QINGLU LIN 8-14-2012 DR 14493 use corToNewMarker and TMLtime ## +#################################################################### ${WMOId} ${vtecOffice} 000000 CUSTOM ${ugcline} @@ -166,7 +168,11 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## +#if(${corToNewMarker}) +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## +#else ${dateUtil.format(${event}, ${timeFormat.time})}Z ## +#end ${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarning.vm index 959034f936..086593b64e 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/extremeWindWarning.vm @@ -6,7 +6,7 @@ ## MODIFIED EVAN BOOKBINDER 09-16-2011 OB11.0.8-8 ## ## EVAN BOOKBINDER WFO EAX 11-04-2011 OB11.9-3 (DRs) ## ## QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## -## ## +## QINGLU LIN 8-14-2012 DR 14493 use TMLtime ## ############################################################################ ## EWW PRODUCT ## ################# @@ -188,7 +188,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## -${dateUtil.format(${event}, ${timeFormat.time})}Z ## +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## ${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereThunderstormWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereThunderstormWarning.vm index 95a654b2ab..cbd5151b14 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereThunderstormWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/impactSevereThunderstormWarning.vm @@ -6,6 +6,7 @@ ## VERSION AWIPS II 1.1 -- 2-29-2012 OB12.2.1-4 ## ## VERSION AWIPS II 1.2 -- 4-20-2012 ## ## BY QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## +## QINGLU LIN 8-14-2012 DR 14493 use TMLtime ## ################################################################ ## ##SET SOME INITIAL VARIABLES @@ -656,7 +657,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## -${dateUtil.format(${event}, ${timeFormat.time})}Z ## +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## ${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeThunderstormWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeThunderstormWarning.vm index 27384c25ae..6baef876b6 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeThunderstormWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/severeThunderstormWarning.vm @@ -9,6 +9,7 @@ ## 2-24-2012 OB12.2.1 CLEANUP ## ## BY QINGLU LIN 6-18-2012 DR 15043 use duration ## ## BY QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## +## BY QINGLU LIN 8-14-2012 DR 14493 use TMLtime ## ################################################################ ## ##SET SOME INITIAL VARIABLES @@ -475,7 +476,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## -${dateUtil.format(${event}, ${timeFormat.time})}Z ## +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## ${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarning.vm index 2f97773b33..7642b1dcc5 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/specialMarineWarning.vm @@ -10,7 +10,8 @@ ## Cleaned up wind coding for version 1.4 ## ## VERSION AWIPS II 1.5 -- MAR 2 2012 OB12.2.1-4 ## ## BY QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## -##################################################### +## BY QINGLU LIN 8-14-2012 DR 14493 use TMLtime ## +################################################################ ## Added Volcano Information in version 1.3 for sites where ## Volcanoes affect their marine zones. If sites wish to hide ## this information comment out the appropriate bullets in the @@ -394,7 +395,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## -${dateUtil.format(${event}, ${timeFormat.time})}Z ## +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## ${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/tornadoWarning.vm b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/tornadoWarning.vm index 86e1177ea2..3c6b02794a 100644 --- a/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/tornadoWarning.vm +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/warngen/tornadoWarning.vm @@ -12,6 +12,7 @@ ## EVAN BOOKBINDER WFO EAX 2-24-12 - OB12.2.1 ## ## MIKE REGA 5-03-12 - DR 14885 MND blank line ## ## QINGLU LIN 7-31-2012 DR 15217 use roundAndPad ## +## QINGLU LIN 8-14-2012 DR 14493 use TMLtime ## ############################################################################### ## ESTABLISH SOME INITIAL VARIABLES #set($preAmble = "") @@ -421,7 +422,7 @@ THIS IS A TEST MESSAGE. DO NOT TAKE ACTION BASED ON THIS MESSAGE. #printcoords(${areaPoly}, ${list}) TIME...MOT...LOC ## -${dateUtil.format(${event}, ${timeFormat.time})}Z ## +${dateUtil.format(${TMLtime}, ${timeFormat.time})}Z ## ${mathUtil.roundAndPad(${movementDirection})}DEG ## ${mathUtil.round(${movementInKnots})}KT ## #foreach(${eventCoord} in ${eventLocation}) diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/protectedFiles.txt b/edexOsgi/build.edex/esb/data/utility/edex_static/base/protectedFiles.txt index 5264d7a021..4c5422020d 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/protectedFiles.txt +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/protectedFiles.txt @@ -5,6 +5,9 @@ # A simple example would be # BASE:common_static/textdb/textCategoryClass.txt +#AvnFPS files +SITE:cave_static/aviation/avnwatch/aviationForecasterConfig.xml + #D2D files BASE:cave_static/derivedParameters/DerivedParameterInterface.py @@ -155,3 +158,6 @@ BASE:edex_static/smartInit/NamDNG5.py #gfeConfig files BASE:cave_static/gfe/userPython/gfeConfig/gfeConfig.py +# FFMP Files +SITE:common_static/purge/ffmpPurgeRules.xml +SITE:common_static/ffmp/FFMPTemplateConfig.xml \ No newline at end of file diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AFD.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AFD.py index e4ebc8d7cd..5b962f6821 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AFD.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AFD.py @@ -339,8 +339,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._longTermFcstrNumber = self._getForecasterNumber(self._longTermFcstrNumber) self._shortTermFcstrNumber = self._getForecasterNumber(self._shortTermFcstrNumber) self._aviationFcstrNumber = self._getForecasterNumber(self._aviationFcstrNumber) diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AreaFcst.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AreaFcst.py index 1df5a26ee7..84ff351107 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AreaFcst.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/AreaFcst.py @@ -1093,8 +1093,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" #Tropical exceptions try: diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CCF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CCF.py index 9e3a8ff410..765d8cbfad 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CCF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CCF.py @@ -201,8 +201,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._forecasterNumber = self._getForecasterNumber(self._forecasterNumber) # Make argDict accessible diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF.py index fe128f9c4f..b5a022ea17 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF.py @@ -750,8 +750,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF_Pacific.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF_Pacific.py index 153f6a20de..a2845f646d 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF_Pacific.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CWF_Pacific.py @@ -1049,9 +1049,7 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): for key in varDict.keys(): if type(key) is types.TupleType: label, variable = key - exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" + exec "self._" + variable + "= varDict[key]" self._language = argDict["language"] diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg.py index 397b804196..7a45eadcfc 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg.py @@ -114,8 +114,6 @@ class TextProduct(GenericReport.TextProduct): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" return fcst def _preProcessArea(self, fcst, editArea, areaLabel, argDict): diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg_EQR_MultiPil_Local.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg_EQR_MultiPil_Local.py index 166c084c35..60c9dc521f 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg_EQR_MultiPil_Local.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/CivilEmerg_EQR_MultiPil_Local.py @@ -80,8 +80,6 @@ class TextProduct(CivilEmerg.TextProduct): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" fcst = fcst + "AN EARTHQUAKE HAS BEEN FELT " + self._felt + " BY " +\ self._extent + " " + "IN THE |*enter area*| AREA. " + \ diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWF.py index 570e5fd4fc..887ff156da 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWF.py @@ -806,9 +806,7 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" - + self._language = argDict["language"] return None diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWFTable.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWFTable.py index efaf26895b..0a8471fc31 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWFTable.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWFTable.py @@ -539,8 +539,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" # Set up product-specific variables self._colWidth = 13 diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWM.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWM.py index 915b4d3efb..2a9ac96b03 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWM.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/FWM.py @@ -219,9 +219,7 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): for key in varDict.keys(): if type(key) is types.TupleType: label, variable = key - exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" + exec "self._" + variable + "= varDict[key]" # Calculate current times self._ddhhmmTime = self.getCurrentTime( diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GLF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GLF.py index cbebdd637b..6bbbc11106 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GLF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GLF.py @@ -693,8 +693,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericHazards.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericHazards.py index 551301d596..22bbc3898c 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericHazards.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericHazards.py @@ -250,8 +250,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis, if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericReport.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericReport.py index af1fa240a6..8874b5a2c4 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericReport.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/GenericReport.py @@ -219,8 +219,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] return None diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/MVF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/MVF.py index 2a9b23b1dd..cb9611957c 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/MVF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/MVF.py @@ -165,8 +165,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" try: if self._tropicalStorm == "YES": diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/NSH.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/NSH.py index 7a6cf9a5de..3ea2f77a4e 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/NSH.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/NSH.py @@ -530,8 +530,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._format = "Standard" self._extended = "Without Extended" diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/OFF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/OFF.py index 9c755059f3..49cca993bd 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/OFF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/OFF.py @@ -878,8 +878,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] return None diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/PFM.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/PFM.py index bfe9a175c7..e03206e273 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/PFM.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/PFM.py @@ -364,8 +364,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" try: if self._tropicalStorm == "YES": self._tropicalStorm = 1 diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SFT.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SFT.py index ed669b9bb3..a181bdfffb 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SFT.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SFT.py @@ -232,8 +232,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" # Make argDict accessible self.__argDict = argDict diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SRF.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SRF.py index 77fbe89cf1..0122c88acc 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SRF.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/textproducts/templates/product/SRF.py @@ -811,8 +811,6 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis): if type(key) is types.TupleType: label, variable = key exec "self._" + variable + "= varDict[key]" - else: - exec "self._" + key + "= varDict[key]" self._language = argDict["language"] return None diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-request.xml b/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-request.xml index 2a0404d2cd..ecc5fa2616 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-request.xml +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-request.xml @@ -18,13 +18,6 @@ value="com.raytheon.uf.common.dataplugin.gfe.request.GetActiveTableRequest" /> - - - - - @@ -298,6 +291,13 @@ value="com.raytheon.uf.common.dataplugin.gfe.request.SaveCombinationsFileRequest" /> + + + + + diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetActiveSitesRequestHandler.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetActiveSitesRequestHandler.java deleted file mode 100644 index 94978dbb49..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetActiveSitesRequestHandler.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.edex.plugin.gfe.server.handler; - -import java.util.Set; - -import com.raytheon.edex.plugin.gfe.config.GFESiteActivation; -import com.raytheon.uf.common.dataplugin.gfe.request.GetActiveSitesRequest; -import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse; -import com.raytheon.uf.common.serialization.comm.IRequestHandler; - -/** - * TODO Add Description - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jan 19, 2011            dgilling     Initial creation
- * 
- * 
- * - * @author dgilling - * @version 1.0 - */ - -public class GetActiveSitesRequestHandler implements - IRequestHandler { - - /* - * (non-Javadoc) - * - * @see - * com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest - * (com.raytheon.uf.common.serialization.comm.IServerRequest) - */ - @Override - public ServerResponse> handleRequest( - GetActiveSitesRequest request) throws Exception { - ServerResponse> sr = new ServerResponse>(); - sr.setPayload(GFESiteActivation.getInstance().getActiveSites()); - return sr; - } - -} diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetSelectTimeRangeHandler.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetSelectTimeRangeHandler.java new file mode 100644 index 0000000000..1436bf957f --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/handler/GetSelectTimeRangeHandler.java @@ -0,0 +1,192 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.edex.plugin.gfe.server.handler; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.InputMismatchException; +import java.util.NoSuchElementException; +import java.util.Scanner; +import java.util.TimeZone; + +import com.raytheon.edex.plugin.gfe.config.IFPServerConfigManager; +import com.raytheon.uf.common.dataplugin.gfe.request.GetSelectTimeRangeRequest; +import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange; +import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange.Mode; +import com.raytheon.uf.common.localization.IPathManager; +import com.raytheon.uf.common.localization.LocalizationContext; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.localization.LocalizationFile; +import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.serialization.comm.IRequestHandler; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.common.util.FileUtil; + +/** + * Request handler for GetSelectTimeRangeRequest. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 1, 2012             dgilling    Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class GetSelectTimeRangeHandler implements + IRequestHandler { + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(GetSelectTimeRangeHandler.class); + + private static final String FILE_EXT = ".SELECTTR"; + + private static final String FILE_PATH = FileUtil.join("gfe", "text", + "selecttr"); + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest + * (com.raytheon.uf.common.serialization.comm.IServerRequest) + */ + @Override + public ServerResponse handleRequest( + GetSelectTimeRangeRequest request) throws Exception { + ServerResponse retVal = new ServerResponse(); + + // So because EDEX has no concept of USER LocalizationLevel and the + // request type allows the user to specify the site id for the SITE + // localization level, we've got to build these contexts manually and + // parse through the results ourselves... + IPathManager pathMgr = PathManagerFactory.getPathManager(); + int numContexts = (request.getWorkstationID().getUserName() + .equals("SITE") ? 3 : 4); + LocalizationContext[] contexts = new LocalizationContext[numContexts]; + // building the array with the contexts in USER->SITE->...->BASE order + // allows the file we really want to appear sooner in the list of + // results + if (contexts.length == 4) { + contexts[0] = pathMgr.getContext(LocalizationType.COMMON_STATIC, + LocalizationLevel.USER); + contexts[0] + .setContextName(request.getWorkstationID().getUserName()); + } + contexts[numContexts - 3] = pathMgr.getContextForSite( + LocalizationType.COMMON_STATIC, request.getSiteID()); + contexts[numContexts - 2] = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.CONFIGURED); + contexts[numContexts - 2].setContextName(request.getSiteID()); + contexts[numContexts - 1] = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.BASE); + + LocalizationFile[] files = pathMgr.listFiles(contexts, FILE_PATH, + new String[] { FILE_EXT }, false, true); + LocalizationFile trFile = null; + for (LocalizationFile lf : files) { + String lfName = lf.getFile().getName(); + if (lfName.equals(request.getName() + FILE_EXT)) { + trFile = lf; + break; + } + } + + if (trFile != null) { + TimeZone localTZ = TimeZone + .getTimeZone(IFPServerConfigManager + .getServerConfig(request.getSiteID()) + .getTimeZones().get(0)); + SelectTimeRange selectTR = loadTimeRange(trFile, localTZ); + if (selectTR != null) { + TimeRange tr = selectTR.toTimeRange(); + retVal.setPayload(tr); + } else { + retVal.addMessage("Could not read SelectTimeRange " + + request.getName()); + } + } else { + retVal.addMessage("Could not find a SelectTimeRange named " + + request.getName()); + } + + return retVal; + } + + private SelectTimeRange loadTimeRange(LocalizationFile lf, TimeZone localTZ) { + File file = lf.getFile(); + + Scanner input = null; + try { + input = new Scanner(file); + + int start = input.nextInt(); + int end = input.nextInt(); + + Mode mode = Mode.LT; + if (input.hasNextInt()) { + mode = Mode.values()[input.nextInt()]; + } + + TimeZone timeZone = (mode == Mode.ZULU ? TimeZone + .getTimeZone("GMT") : localTZ); + + SelectTimeRange range = new SelectTimeRange(FileUtil.unmangle(file + .getName().replace(FILE_EXT, "")), start, end, mode, lf + .getContext().getLocalizationLevel(), timeZone); + return range; + } catch (FileNotFoundException fileNotFound) { + statusHandler.handle(Priority.PROBLEM, "Could not open SelectTR: " + + file.getAbsolutePath(), fileNotFound); + } catch (InputMismatchException inputMismatch) { + statusHandler.handle( + Priority.PROBLEM, + "Invalid value found within SelectTR: " + + file.getAbsolutePath(), inputMismatch); + } catch (NoSuchElementException noElement) { + statusHandler.handle( + Priority.PROBLEM, + "Prematurely reached end of SelectTR: " + + file.getAbsolutePath(), noElement); + } catch (Exception e) { + statusHandler.handle( + Priority.PROBLEM, + "Unhandled exception occurred reading SelectTR: " + + file.getAbsolutePath(), e); + } finally { + if (input != null) { + input.close(); + } + } + + return null; + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py index 64e6eaca5a..7f74d2db32 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py @@ -21,13 +21,13 @@ import string, getopt, sys, time, gzip, os, LogStream, stat, traceback import numpy -import pupynere as NetCDF -#try: -# # dev environment -# from Scientific.IO import NetCDF -#except: -# # runtime we don't have the whole scientific package -# import NetCDF +#import pupynere as NetCDF +try: + # dev environment + from Scientific.IO import NetCDF +except: + # runtime we don't have the whole scientific package + import NetCDF import JUtil import iscUtil diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py index 1bf9b782f7..ab1691f06f 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py @@ -21,13 +21,13 @@ import os, stat, time, string, bisect, getopt, sys, traceback import LogStream, iscTime, iscUtil, mergeGrid -import pupynere as NetCDF -#try: -# # dev environment -# from Scientific.IO import NetCDF -#except: -# # runtime we don't have the whole scientific package -# import NetCDF +#import pupynere as NetCDF +try: + # dev environment + from Scientific.IO import NetCDF +except: + # runtime we don't have the whole scientific package + import NetCDF import numpy import JUtil diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/DefaultSubGridCenterPoint.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/DefaultSubGridCenterPoint.java new file mode 100644 index 0000000000..18d762a9fb --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/DefaultSubGridCenterPoint.java @@ -0,0 +1,79 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.edex.plugin.grib.spatial; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.common.geospatial.MapUtil; +import com.raytheon.uf.common.serialization.ISerializableObject; + +/** + * Default sub grid center point. If latitude/longitude may be null. This would + * show that the wfo center point should be looked up. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 25, 2012 977        rjpeter     Initial creation
+ * 
+ * 
+ * + * @author rjpeter + * @version 1.0 + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class DefaultSubGridCenterPoint implements ISerializableObject { + private Double centerLatitude; + + private Double centerLongitude; + + public Double getCenterLatitude() { + return centerLatitude; + } + + @XmlElement + public void setCenterLatitude(final Double centerLatitude) { + this.centerLatitude = centerLatitude; + if (this.centerLatitude != null) { + this.centerLatitude = new Double(MapUtil.correctLat(centerLatitude + .doubleValue())); + } + } + + public Double getCenterLongitude() { + return centerLongitude; + } + + @XmlElement + public void setCenterLongitude(final Double centerLongitude) { + this.centerLongitude = centerLongitude; + if (this.centerLongitude != null) { + this.centerLongitude = new Double( + MapUtil.correctLon(centerLongitude.doubleValue())); + } + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/GribSpatialCache.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/GribSpatialCache.java index ee199ae5dc..2b7bb6d8e0 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/GribSpatialCache.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/spatial/GribSpatialCache.java @@ -50,6 +50,7 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.serialization.JAXBManager; import com.raytheon.uf.common.serialization.SerializationException; import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.edex.awipstools.GetWfoCenterHandler; @@ -74,7 +75,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 4/7/09 1994 bphillip Initial Creation - * + * Jul 25, 2012 977 rjpeter Add ability for sub grids to have a defined center point. * * * @author bphillip @@ -82,669 +83,727 @@ import com.vividsolutions.jts.geom.Coordinate; */ public class GribSpatialCache { - /** The logger */ - protected transient Log logger = LogFactory.getLog(getClass()); - - /** The singleton instance */ - private static GribSpatialCache instance = new GribSpatialCache(); - - /** - * Map containing the GridCoverages
- * The key for this map is the id field of the GridCoverage object stored as - * the value of the map - */ - private Map spatialMap; - - /** - * Map containing the GridCoverages
- * The key for this map is the name field of the GridCoverage object stored - * as the value of the map. This is only used internally for lookup of a - * coverage by name aka gridId. - */ - private Map spatialNameMap; - - /** - * Map containing the subGrid coverage based on a model name. - */ - private Map subGridCoverageMap; - - /** - * Map containing the subGrid definition based on a model name. - */ - private Map definedSubGridMap; - - /** - * Gets the singleton instance of GribSpatialCache - * - * @return The singleton instance of the GribSpatialCache - */ - public static GribSpatialCache getInstance() { - return instance; - } - - /** - * Creates a new GribSpatialCache - */ - private GribSpatialCache() { - spatialMap = new HashMap(); - spatialNameMap = new HashMap(); - definedSubGridMap = new HashMap(); - subGridCoverageMap = new HashMap(); - initializeGrids(); - } - - /** - * Retrieves a grid from the map. If the grid does not exist, null is - * returned - * - * @param id - * The id of the GridCoverage to retrieve - * @return The GridCoverage object, null if not present - * @throws GribException - * @throws DataAccessLayerException - */ - public GridCoverage getGrid(GridCoverage coverage) throws GribException { - GridCoverage retVal = spatialMap.get(coverage.getId()); - - if (retVal == null) { - /* - * Coverage not found in cache, but the values provided in the GDS - * may be slightly different than those for the grid in the cache. - * Check the database to be sure. - */ - try { - retVal = ((IGridCoverageDao) EDEXUtil.getESBComponent(coverage - .getProjectionType().replaceAll(" ", "") + "Dao")) - .checkGrid(coverage); - } catch (DataAccessLayerException e) { - throw new GribException("Error querying for grib coverage!", e); - } - - if (retVal != null) { - spatialMap.put(coverage.getId(), retVal); - spatialNameMap.put(coverage.getName(), retVal); - } - - } - - return retVal; - } - - public GridCoverage getGrid(int id) { - return spatialMap.get(id); - } - - public GridCoverage getGrid(String modelName) { - GridCoverage rval = null; - - if (modelName != null) { - if (subGridCoverageMap.containsKey(modelName)) { - rval = spatialMap.get(subGridCoverageMap.get(modelName)); - } else { - GridModel model = GribModelLookup.getInstance().getModelByName( - modelName); - if (model != null) { - rval = spatialNameMap.get(model.getGrid().toString()); - } - } - } - - return rval; - } - - public GridCoverage getGridByName(String name) { - return spatialNameMap.get(name); - } - - /** - * Puts a grid into the GribSpatialCache. - * - * @param grid - * The grid to store - * @param persistToDb - * True if this GridCoverage object is to be persisted to the - * database - * @throws GribException - * If problems occur while initializing the grid - */ - public void putGrid(GridCoverage grid, boolean initializeGrid, - boolean persistToDb) throws GribException { - if (initializeGrid) { - /* - * Prepare the grid to be stored into the cache. Initializes the - * geometry and crs objects and generates the id field - */ - grid.initialize(); - if (grid.getName() == null) { - grid.generateName(); - } - } - - // Persist to the database if desired - if (persistToDb) { - new CoreDao(DaoConfig.DEFAULT).saveOrUpdate(grid); - } - - spatialMap.put(grid.getId(), grid); - spatialNameMap.put(grid.getName(), grid); - } - - public SubGrid getSubGrid(String modelName) { - return definedSubGridMap.get(modelName); - } - - public GridCoverage getSubGridCoverage(String modelName) { - GridCoverage rval = null; - - if (subGridCoverageMap.containsKey(modelName)) { - rval = spatialMap.get(subGridCoverageMap.get(modelName)); - } - - return rval; - } - - /** - * Initializes the predefined set of grids. The grids are stored in xml - * format in the utility folder so the localization service has access to - * them.
- * GridCoverage are created from the xml via JaxB and placed in the cache - */ - private void initializeGrids() { - ClusterTask ct = null; - - do { - ct = ClusterLockUtils.lock("grib", "spatialCache", 120000, true); - } while (!LockState.SUCCESSFUL.equals(ct.getLockState())); - - try { - // pull all the coverage from the database - GridCoverageDao dao = new GridCoverageDao(); - FileDataList previousFdl = getPreviousFileDataList(); - FileDataList currentFdl = generateFileDataList(); - - if (isDefintionChanged(previousFdl, currentFdl)) { - processBaseGridsChanged(dao, currentFdl); - saveFileDataList(currentFdl); - } else { - List baseCoverages = dao - .loadBaseGrids(); - - if (baseCoverages != null && baseCoverages.size() > 0) { - for (Object obj : baseCoverages) { - try { - putGrid((GridCoverage) obj, false, false); - } catch (Exception e) { - // Log error but do not throw exception, technically - // is - // only from initialize which isn't being called - logger.error( - "Unable to load grid coverage into cache " - + obj, e); - } - } - } else { - // database wiped/plugin re-initialized need to repopulate - processBaseGridsChanged(dao, currentFdl); - saveFileDataList(currentFdl); - } - } - - processUnknownGrids(dao); - processSubGrids(dao, currentFdl); - } finally { - ClusterLockUtils.unlock(ct, false); - } - } - - /** - * A non subgridded definition has been added, deleted, or changed. - * Changed/delete both delete all records, models, and coverage defintion. - * Then Change/Add put in a new coverage definition. - * - * TODO: Post process Unknown definitions to see if they are now known. If - * now known delete definitions of unknown. - * - * @param dao - * @param currentFdl - */ - private void processBaseGridsChanged(GridCoverageDao dao, - FileDataList currentFdl) { - List baseCoverages = dao.loadBaseGrids(); - Map fileCoverageMap = loadGridDefinitionsFromDisk(currentFdl); - - // update needs to delete all hdf5 same as delete, so update is - // a delete and then an add to simplify logic and handle primary - // key changes. - List coveragesToDelete = new LinkedList(); - HashSet validDbCoverageNames = new HashSet( - (int) (baseCoverages.size() * 1.25) + 1); - - Iterator iter = baseCoverages.iterator(); - while (iter.hasNext()) { - GridCoverage dbCov = iter.next(); - GridCoverage fileCoverage = fileCoverageMap.get(dbCov.getName()); - if (!dbCov.equals(fileCoverage)) { - // coverage not in flat file or coverage has changed, - // delete coverage old coverage - coveragesToDelete.add(dbCov); - iter.remove(); - } else { - // current coverage still valid - validDbCoverageNames.add(dbCov.getName()); - } - } - - // delete grids, models, coverages, and hdf5 for namesToDelete. - for (GridCoverage cov : coveragesToDelete) { - logger.info("GridCoverage " + cov.getName() - + " has changed. Deleting out of date data"); - if (!dao.deleteCoverageAssociatedData(cov, true)) { - logger.warn("Failed to delete GridCoverage " + cov.getName() - + ". Manual intervention required."); - } else { - logger.info("GridCoverage successfully deleted"); - } - } - - // remove the valid db coverages from the map - fileCoverageMap.keySet().removeAll(validDbCoverageNames); - - // add new grids in bulk - for (GridCoverage cov : fileCoverageMap.values()) { - try { - putGrid(cov, true, false); - } catch (Exception e) { - logger.error( - "Failed to initialize grid definition " + cov.getName(), - e); - } - } - - // bulk persist the spatial maps - if (spatialMap.size() > 0) { - dao.persistAll(spatialMap.values()); - } - - for (GridCoverage cov : baseCoverages) { - try { - putGrid(cov, false, false); - } catch (Exception e) { - logger.error( - "Failed to initialize grid definition " + cov.getName(), - e); - } - } - } - - /** - * A non subGridd definition has been added, deleted, or changed. - * Changed/delete both delete all records, models, and coverage defintion. - * Then Change/Add put in a new coverage definition, and also delete any - * data associated with base model definition. - * - * @param dao - * @param currentFdl - */ - private void processSubGrids(GridCoverageDao dao, FileDataList currentFdl) { - List oldSubGridCoverages = dao.loadSubGrids(); - Map fileSubGridCoverageMap = loadSubGridDefinitionsFromDisk(currentFdl); - - // update needs to delete all hdf5 same as delete, so update is - // a delete and then an add to simplify logic and handle primary - // key changes. - List coveragesToDelete = new LinkedList(); - HashSet validDbCoverageNames = new HashSet( - (int) (oldSubGridCoverages.size() * 1.25) + 1); - - Iterator iter = oldSubGridCoverages.iterator(); - while (iter.hasNext()) { - GridCoverage dbCov = iter.next(); - GridCoverage fileCoverage = fileSubGridCoverageMap.get(dbCov - .getName()); - if (!dbCov.equals(fileCoverage)) { - // coverage not in flat file or coverage has changed, - // delete coverage - coveragesToDelete.add(dbCov); - iter.remove(); - } else { - // current coverage still valid - validDbCoverageNames.add(dbCov.getName()); - } - } - - // delete grids, models, coverages, and hdf5 for namesToDelete. - for (GridCoverage cov : coveragesToDelete) { - logger.info("Model " - + cov.getSubGridModel() - + " has changed subGrid definition, deleting out of date data"); - if (!dao.deleteCoverageAssociatedData(cov, true)) { - logger.warn("Failed to delete GridCoverage " + cov.getName() - + ". Manual intervention required."); - } else { - logger.info("GridModel successfully deleted"); - } - } - - // remove the valid db coverages from the map - fileSubGridCoverageMap.keySet().removeAll(validDbCoverageNames); - - // need to delete model information for new adds, as old grid may not - // have been subgridded - GribModelDao modelDao = new GribModelDao(); - for (GridCoverage cov : fileSubGridCoverageMap.values()) { - logger.info("Model " - + cov.getSubGridModel() - + " has changed subGrid definition, deleting out of date data"); - // look up parent - if (modelDao.deleteModelAndAssociatedData(cov.getSubGridModel()) < 0) { - logger.warn("Failed to delete SubGrid Model " - + cov.getSubGridModel() - + ". Manual intervention required."); - } else { - logger.info("GridModel successfully deleted"); - } - } - - // add new grids, persisting individually - for (GridCoverage cov : fileSubGridCoverageMap.values()) { - try { - putGrid(cov, true, true); - subGridCoverageMap.put(cov.getSubGridModel(), cov.getId()); - } catch (Exception e) { - logger.error( - "Failed to initialize grid definition " + cov.getName(), - e); - } - } - - // put database grids into map - for (GridCoverage cov : oldSubGridCoverages) { - try { - putGrid(cov, true, true); - subGridCoverageMap.put(cov.getSubGridModel(), cov.getId()); - } catch (Exception e) { - logger.error( - "Failed to initialize grid definition " + cov.getName(), - e); - } - } - } - - private void processUnknownGrids(GridCoverageDao dao) { - List unknownGrids = dao.loadUnknownGrids(); - for (GridCoverage cov : unknownGrids) { - try { - GridCoverage dbCov = getGrid(cov); - if (!cov.getName().equals(dbCov.getName())) { - logger.info("Unknown grid " + cov.getName() - + " is now mapped by " + dbCov.getName() - + ". Deleting unknown grid"); - dao.deleteCoverageAssociatedData(cov, true); - } - } catch (Exception e) { - logger.error("Erro occurred scanning unknown grids", e); - } - } - } - - private Map loadSubGridDefinitionsFromDisk( - FileDataList currentFdl) { - GribModelLookup gribModelLUT = GribModelLookup.getInstance(); - List subGridDefs = currentFdl.getSubGridFileList(); - Map subGrids = null; - - if (subGridDefs != null && subGridDefs.size() > 0) { - subGrids = new HashMap(subGridDefs.size() * 3); - Coordinate wfoCenterPoint = null; - String wfo = SiteUtil.getSite(); - GetWfoCenterPoint centerPointRequest = new GetWfoCenterPoint(wfo); - try { - wfoCenterPoint = new GetWfoCenterHandler() - .handleRequest(centerPointRequest); - } catch (Exception e) { - logger.error( - "Failed to generate sub grid definitions. Unable to lookup WFO Center Point", - e); - return new HashMap(0); - } - - for (FileData fd : subGridDefs) { - try { - SubGridDef subGridDef = loadSubGridDef(fd.getFilePath()); - - if (subGridDef != null) { - String referenceModel = subGridDef.getReferenceModel(); - - GridCoverage gridCoverage = getGrid(referenceModel); - - if (gridCoverage != null) { - Coordinate wfoCenter = MapUtil - .latLonToGridCoordinate(wfoCenterPoint, - PixelOrientation.CENTER, - gridCoverage); - - double xCenterPoint = wfoCenter.x; - double yCenterPoint = wfoCenter.y; - - double xDistance = subGridDef.getNx() / 2; - double yDistance = subGridDef.getNy() / 2; - Coordinate lowerLeftPosition = new Coordinate( - xCenterPoint - xDistance, yCenterPoint - + yDistance); - Coordinate upperRightPosition = new Coordinate( - xCenterPoint + xDistance, yCenterPoint - - yDistance); - - lowerLeftPosition = MapUtil.gridCoordinateToLatLon( - lowerLeftPosition, PixelOrientation.CENTER, - gridCoverage); - upperRightPosition = MapUtil - .gridCoordinateToLatLon(upperRightPosition, - PixelOrientation.CENTER, - gridCoverage); - - subGridDef.setLowerLeftLon(lowerLeftPosition.x); - subGridDef.setLowerLeftLat(lowerLeftPosition.y); - subGridDef.setUpperRightLon(upperRightPosition.x); - subGridDef.setUpperRightLat(upperRightPosition.y); - - // verify numbers in -180 -> 180 range - subGridDef.setLowerLeftLon(MapUtil - .correctLon(subGridDef.getLowerLeftLon())); - subGridDef.setUpperRightLon(MapUtil - .correctLon(subGridDef.getUpperRightLon())); - - // do a reverse lookup of the model name to get its - // associated grid id - - for (String modelName : subGridDef.getModelNames()) { - GridModel model = gribModelLUT - .getModelByName(modelName); - if (model != null) { - GridCoverage baseCoverage = spatialNameMap - .get(model.getGrid().toString()); - - if (baseCoverage != null) { - SubGrid subGrid = new SubGrid(); - subGrid.setModelName(modelName); - GridCoverage subGridCoverage = baseCoverage - .trim(subGridDef, subGrid); - if (subGridCoverage != null) { - subGrids.put( - subGridCoverage.getName(), - subGridCoverage); - definedSubGridMap.put(modelName, - subGrid); - } - } - } - } - } else { - logger.error("Failed to generate sub grid for " - + fd.getFilePath() - + ". Unable to determine coverage for referenceModel [" - + referenceModel + "]"); - } - } - } catch (Exception e) { - // Log error but do not throw exception - logger.error( - "Failed processing sub grid file: " - + fd.getFilePath(), e); - } - } - } else { - subGrids = new HashMap(0); - } - - return subGrids; - } - - /** - * Loads and validates subGridDef pointed to by filePath. If definition - * empty/invalid returns null. - * - * @param filePath - * @return - */ - private SubGridDef loadSubGridDef(String filePath) { - SubGridDef rval = null; - File f = new File(filePath); - - if (f.length() > 0) { - try { - rval = (SubGridDef) SerializationUtil - .jaxbUnmarshalFromXmlFile(f); - if (rval.getReferenceModel() == null - || rval.getModelNames() == null - || rval.getModelNames().size() == 0) { - // sub grid didn't have required definitions - rval = null; - } - } catch (SerializationException e) { - logger.error("Failed reading sub grid file: " + filePath, e); - } - } - - return rval; - } - - private static boolean isDefintionChanged(FileDataList previousFdl, - FileDataList currentFdl) { - boolean rval = true; - if (currentFdl != null) { - rval = !currentFdl.equals(previousFdl); - } else { - rval = previousFdl != null; - } - - return rval; - } - - private FileDataList generateFileDataList() { - /* - * Retrieve the list of files from the localization service - */ - IPathManager pm = PathManagerFactory.getPathManager(); - FileDataList fileList = new FileDataList(); - LocalizationContext[] contexts = pm - .getLocalSearchHierarchy(LocalizationType.EDEX_STATIC); - fileList.addCoverageFiles(pm.listFiles(contexts, "/grib/grids", - new String[] { "xml" }, true, true)); - fileList.addSubGridFiles(pm.listFiles(contexts, "/grib/subgrids", - new String[] { "xml" }, true, true)); - - return fileList; - } - - private FileDataList getPreviousFileDataList() { - IPathManager pm = PathManagerFactory.getPathManager(); - File previousFileData = pm.getFile(pm.getContext( - LocalizationType.EDEX_STATIC, LocalizationLevel.CONFIGURED), - "/grib/gridDefFileListing.xml"); - FileDataList rval = null; - - if (previousFileData.exists() && previousFileData.length() > 0) { - try { - Object obj = SerializationUtil - .jaxbUnmarshalFromXmlFile(previousFileData); - if (obj instanceof FileDataList) { - rval = (FileDataList) obj; - } else { - logger.error("Error occurred deserializing " - + previousFileData.getAbsolutePath() - + ", expected type " + FileDataList.class - + " received " + obj.getClass()); - } - } catch (Exception e) { - logger.error( - "Error occurred deserializing " - + previousFileData.getAbsolutePath(), e); - } - } - return rval; - } - - private Map loadGridDefinitionsFromDisk( - FileDataList currentFdl) { - List coverageFiles = currentFdl.getCoverageFileList(); - Map fileCoverageMap = new HashMap( - (int) (coverageFiles.size() * 1.25) + 1); - - /* - * Iterate over file list. Unmarshal to GridCoverage object - */ - for (FileData fd : coverageFiles) { - try { - GridCoverage grid = (GridCoverage) SerializationUtil - .jaxbUnmarshalFromXmlFile(fd.getFilePath()); - GridCoverage previousGrid = fileCoverageMap.put(grid.getName(), - grid); - if (previousGrid != null) { - for (FileData fd2 : coverageFiles) { - GridCoverage grid2 = (GridCoverage) SerializationUtil - .jaxbUnmarshalFromXmlFile(fd2.getFilePath()); - if (grid.getName().equals(grid2.getName())) { - logger.error("Grid " + grid.getName() - + " has already been defined. " - + fd.getFilePath() + " and " - + fd2.getFilePath() - + " have same name. Using " - + fd2.getFilePath()); - break; - } - } - } - } catch (Exception e) { - // Log error but do not throw exception - logger.error( - "Unable to read default grids file: " - + fd.getFilePath(), e); - } - } - - return fileCoverageMap; - } - - private void saveFileDataList(FileDataList fdl) { - try { - IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationFile lf = pm.getLocalizationFile( - pm.getContext(LocalizationType.EDEX_STATIC, - LocalizationLevel.CONFIGURED), - "/grib/gridDefFileListing.xml"); - SerializationUtil.jaxbMarshalToXmlFile(fdl, lf.getFile() - .getAbsolutePath()); - lf.save(); - } catch (Exception e) { - logger.error( - "Failed to save coverage file data list, coverages may be reloaded on next restart", - e); - } - } - - public static void reinitialize() { - GribSpatialCache newInstance = new GribSpatialCache(); - instance = newInstance; - } + /** The logger */ + protected Log logger = LogFactory.getLog(getClass()); + + /** The singleton instance */ + private static GribSpatialCache instance = new GribSpatialCache(); + + /** + * Map containing the GridCoverages
+ * The key for this map is the id field of the GridCoverage object stored as + * the value of the map + */ + private final Map spatialMap; + + /** + * Map containing the GridCoverages
+ * The key for this map is the name field of the GridCoverage object stored + * as the value of the map. This is only used internally for lookup of a + * coverage by name aka gridId. + */ + private final Map spatialNameMap; + + /** + * Map containing the subGrid coverage based on a model name. + */ + private final Map subGridCoverageMap; + + /** + * Map containing the subGrid definition based on a model name. + */ + private final Map definedSubGridMap; + + /** + * Gets the singleton instance of GribSpatialCache + * + * @return The singleton instance of the GribSpatialCache + */ + public static GribSpatialCache getInstance() { + return instance; + } + + /** + * Creates a new GribSpatialCache + */ + private GribSpatialCache() { + spatialMap = new HashMap(); + spatialNameMap = new HashMap(); + definedSubGridMap = new HashMap(); + subGridCoverageMap = new HashMap(); + initializeGrids(); + } + + /** + * Retrieves a grid from the map. If the grid does not exist, null is + * returned + * + * @param id + * The id of the GridCoverage to retrieve + * @return The GridCoverage object, null if not present + * @throws GribException + * @throws DataAccessLayerException + */ + public GridCoverage getGrid(final GridCoverage coverage) + throws GribException { + GridCoverage retVal = spatialMap.get(coverage.getId()); + + if (retVal == null) { + /* + * Coverage not found in cache, but the values provided in the GDS + * may be slightly different than those for the grid in the cache. + * Check the database to be sure. + */ + try { + retVal = ((IGridCoverageDao) EDEXUtil.getESBComponent(coverage + .getProjectionType().replaceAll(" ", "") + "Dao")) + .checkGrid(coverage); + } catch (DataAccessLayerException e) { + throw new GribException("Error querying for grib coverage!", e); + } + + if (retVal != null) { + spatialMap.put(coverage.getId(), retVal); + spatialNameMap.put(coverage.getName(), retVal); + } + + } + + return retVal; + } + + public GridCoverage getGrid(final int id) { + return spatialMap.get(id); + } + + public GridCoverage getGrid(final String modelName) { + GridCoverage rval = null; + + if (modelName != null) { + if (subGridCoverageMap.containsKey(modelName)) { + rval = spatialMap.get(subGridCoverageMap.get(modelName)); + } else { + GridModel model = GribModelLookup.getInstance().getModelByName( + modelName); + if (model != null) { + rval = spatialNameMap.get(model.getGrid().toString()); + } + } + } + + return rval; + } + + public GridCoverage getGridByName(final String name) { + return spatialNameMap.get(name); + } + + /** + * Puts a grid into the GribSpatialCache. + * + * @param grid + * The grid to store + * @param persistToDb + * True if this GridCoverage object is to be persisted to the + * database + * @throws GribException + * If problems occur while initializing the grid + */ + public void putGrid(final GridCoverage grid, final boolean initializeGrid, + final boolean persistToDb) throws GribException { + if (initializeGrid) { + /* + * Prepare the grid to be stored into the cache. Initializes the + * geometry and crs objects and generates the id field + */ + grid.initialize(); + if (grid.getName() == null) { + grid.generateName(); + } + } + + // Persist to the database if desired + if (persistToDb) { + new CoreDao(DaoConfig.DEFAULT).saveOrUpdate(grid); + } + + spatialMap.put(grid.getId(), grid); + spatialNameMap.put(grid.getName(), grid); + } + + public SubGrid getSubGrid(final String modelName) { + return definedSubGridMap.get(modelName); + } + + public GridCoverage getSubGridCoverage(final String modelName) { + GridCoverage rval = null; + + if (subGridCoverageMap.containsKey(modelName)) { + rval = spatialMap.get(subGridCoverageMap.get(modelName)); + } + + return rval; + } + + /** + * Initializes the predefined set of grids. The grids are stored in xml + * format in the utility folder so the localization service has access to + * them.
+ * GridCoverage are created from the xml via JaxB and placed in the cache + */ + private void initializeGrids() { + ClusterTask ct = null; + + do { + ct = ClusterLockUtils.lock("grib", "spatialCache", 120000, true); + } while (!LockState.SUCCESSFUL.equals(ct.getLockState())); + + try { + // pull all the coverage from the database + GridCoverageDao dao = new GridCoverageDao(); + FileDataList previousFdl = getPreviousFileDataList(); + FileDataList currentFdl = generateFileDataList(); + + if (isDefintionChanged(previousFdl, currentFdl)) { + processBaseGridsChanged(dao, currentFdl); + saveFileDataList(currentFdl); + } else { + List baseCoverages = dao + .loadBaseGrids(); + + if ((baseCoverages != null) && (baseCoverages.size() > 0)) { + for (Object obj : baseCoverages) { + try { + putGrid((GridCoverage) obj, false, false); + } catch (Exception e) { + // Log error but do not throw exception, technically + // is + // only from initialize which isn't being called + logger.error( + "Unable to load grid coverage into cache " + + obj, e); + } + } + } else { + // database wiped/plugin re-initialized need to repopulate + processBaseGridsChanged(dao, currentFdl); + saveFileDataList(currentFdl); + } + } + + processUnknownGrids(dao); + processSubGrids(dao, currentFdl); + } finally { + ClusterLockUtils.unlock(ct, false); + } + } + + /** + * A non subgridded definition has been added, deleted, or changed. + * Changed/delete both delete all records, models, and coverage defintion. + * Then Change/Add put in a new coverage definition. + * + * TODO: Post process Unknown definitions to see if they are now known. If + * now known delete definitions of unknown. + * + * @param dao + * @param currentFdl + */ + private void processBaseGridsChanged(final GridCoverageDao dao, + final FileDataList currentFdl) { + List baseCoverages = dao.loadBaseGrids(); + Map fileCoverageMap = loadGridDefinitionsFromDisk(currentFdl); + + // update needs to delete all hdf5 same as delete, so update is + // a delete and then an add to simplify logic and handle primary + // key changes. + List coveragesToDelete = new LinkedList(); + HashSet validDbCoverageNames = new HashSet( + (int) (baseCoverages.size() * 1.25) + 1); + + Iterator iter = baseCoverages.iterator(); + while (iter.hasNext()) { + GridCoverage dbCov = iter.next(); + GridCoverage fileCoverage = fileCoverageMap.get(dbCov.getName()); + if (!dbCov.equals(fileCoverage)) { + // coverage not in flat file or coverage has changed, + // delete coverage old coverage + coveragesToDelete.add(dbCov); + iter.remove(); + } else { + // current coverage still valid + validDbCoverageNames.add(dbCov.getName()); + } + } + + // delete grids, models, coverages, and hdf5 for namesToDelete. + for (GridCoverage cov : coveragesToDelete) { + logger.info("GridCoverage " + cov.getName() + + " has changed. Deleting out of date data"); + if (!dao.deleteCoverageAssociatedData(cov, true)) { + logger.warn("Failed to delete GridCoverage " + cov.getName() + + ". Manual intervention required."); + } else { + logger.info("GridCoverage successfully deleted"); + } + } + + // remove the valid db coverages from the map + fileCoverageMap.keySet().removeAll(validDbCoverageNames); + + // add new grids in bulk + for (GridCoverage cov : fileCoverageMap.values()) { + try { + putGrid(cov, true, false); + } catch (Exception e) { + logger.error( + "Failed to initialize grid definition " + cov.getName(), + e); + } + } + + // bulk persist the spatial maps + if (spatialMap.size() > 0) { + dao.persistAll(spatialMap.values()); + } + + for (GridCoverage cov : baseCoverages) { + try { + putGrid(cov, false, false); + } catch (Exception e) { + logger.error( + "Failed to initialize grid definition " + cov.getName(), + e); + } + } + } + + /** + * A non subGridd definition has been added, deleted, or changed. + * Changed/delete both delete all records, models, and coverage defintion. + * Then Change/Add put in a new coverage definition, and also delete any + * data associated with base model definition. + * + * @param dao + * @param currentFdl + */ + private void processSubGrids(final GridCoverageDao dao, + final FileDataList currentFdl) { + List oldSubGridCoverages = dao.loadSubGrids(); + Map fileSubGridCoverageMap = loadSubGridDefinitionsFromDisk(currentFdl); + + // update needs to delete all hdf5 same as delete, so update is + // a delete and then an add to simplify logic and handle primary + // key changes. + List coveragesToDelete = new LinkedList(); + HashSet validDbCoverageNames = new HashSet( + (int) (oldSubGridCoverages.size() * 1.25) + 1); + + Iterator iter = oldSubGridCoverages.iterator(); + while (iter.hasNext()) { + GridCoverage dbCov = iter.next(); + GridCoverage fileCoverage = fileSubGridCoverageMap.get(dbCov + .getName()); + if (!dbCov.equals(fileCoverage)) { + // coverage not in flat file or coverage has changed, + // delete coverage + coveragesToDelete.add(dbCov); + iter.remove(); + } else { + // current coverage still valid + validDbCoverageNames.add(dbCov.getName()); + } + } + + // delete grids, models, coverages, and hdf5 for namesToDelete. + for (GridCoverage cov : coveragesToDelete) { + logger.info("Model " + + cov.getSubGridModel() + + " has changed subGrid definition, deleting out of date data"); + if (!dao.deleteCoverageAssociatedData(cov, true)) { + logger.warn("Failed to delete GridCoverage " + cov.getName() + + ". Manual intervention required."); + } else { + logger.info("GridModel successfully deleted"); + } + } + + // remove the valid db coverages from the map + fileSubGridCoverageMap.keySet().removeAll(validDbCoverageNames); + + // need to delete model information for new adds, as old grid may not + // have been subgridded + GribModelDao modelDao = new GribModelDao(); + for (GridCoverage cov : fileSubGridCoverageMap.values()) { + logger.info("Model " + + cov.getSubGridModel() + + " has changed subGrid definition, deleting out of date data"); + // look up parent + if (modelDao.deleteModelAndAssociatedData(cov.getSubGridModel()) < 0) { + logger.warn("Failed to delete SubGrid Model " + + cov.getSubGridModel() + + ". Manual intervention required."); + } else { + logger.info("GridModel successfully deleted"); + } + } + + // add new grids, persisting individually + for (GridCoverage cov : fileSubGridCoverageMap.values()) { + try { + putGrid(cov, true, true); + subGridCoverageMap.put(cov.getSubGridModel(), cov.getId()); + } catch (Exception e) { + logger.error( + "Failed to initialize grid definition " + cov.getName(), + e); + } + } + + // put database grids into map + for (GridCoverage cov : oldSubGridCoverages) { + try { + putGrid(cov, true, true); + subGridCoverageMap.put(cov.getSubGridModel(), cov.getId()); + } catch (Exception e) { + logger.error( + "Failed to initialize grid definition " + cov.getName(), + e); + } + } + } + + private void processUnknownGrids(final GridCoverageDao dao) { + List unknownGrids = dao.loadUnknownGrids(); + for (GridCoverage cov : unknownGrids) { + try { + GridCoverage dbCov = getGrid(cov); + if (!cov.getName().equals(dbCov.getName())) { + logger.info("Unknown grid " + cov.getName() + + " is now mapped by " + dbCov.getName() + + ". Deleting unknown grid"); + dao.deleteCoverageAssociatedData(cov, true); + } + } catch (Exception e) { + logger.error("Erro occurred scanning unknown grids", e); + } + } + } + + private Map loadSubGridDefinitionsFromDisk( + final FileDataList currentFdl) { + GribModelLookup gribModelLUT = GribModelLookup.getInstance(); + List subGridDefs = currentFdl.getSubGridFileList(); + Map subGrids = null; + + if ((subGridDefs != null) && (subGridDefs.size() > 0)) { + subGrids = new HashMap(subGridDefs.size() * 3); + + Coordinate defaultCenterPoint = null; + + try { + defaultCenterPoint = getDefaultSubGridCenterPoint(); + } catch (Exception e) { + logger.error( + "Failed to generate sub grid definitions. Unable to lookup WFO Center Point", + e); + return new HashMap(0); + } + + for (FileData fd : subGridDefs) { + try { + SubGridDef subGridDef = loadSubGridDef(fd.getFilePath(), + defaultCenterPoint); + + if (subGridDef != null) { + String referenceModel = subGridDef.getReferenceModel(); + + GridCoverage gridCoverage = getGrid(referenceModel); + + if (gridCoverage != null) { + Coordinate subGridCenterLatLon = new Coordinate( + subGridDef.getCenterLongitude(), + subGridDef.getCenterLatitude()); + + Coordinate subGridCenterGridCoord = MapUtil + .latLonToGridCoordinate( + subGridCenterLatLon, + PixelOrientation.CENTER, + gridCoverage); + + double xCenterPoint = subGridCenterGridCoord.x; + double yCenterPoint = subGridCenterGridCoord.y; + + double xDistance = subGridDef.getNx() / 2; + double yDistance = subGridDef.getNy() / 2; + Coordinate lowerLeftPosition = new Coordinate( + xCenterPoint - xDistance, yCenterPoint + + yDistance); + Coordinate upperRightPosition = new Coordinate( + xCenterPoint + xDistance, yCenterPoint + - yDistance); + + lowerLeftPosition = MapUtil.gridCoordinateToLatLon( + lowerLeftPosition, PixelOrientation.CENTER, + gridCoverage); + upperRightPosition = MapUtil + .gridCoordinateToLatLon(upperRightPosition, + PixelOrientation.CENTER, + gridCoverage); + + subGridDef.setLowerLeftLon(lowerLeftPosition.x); + subGridDef.setLowerLeftLat(lowerLeftPosition.y); + subGridDef.setUpperRightLon(upperRightPosition.x); + subGridDef.setUpperRightLat(upperRightPosition.y); + + // verify numbers in -180 -> 180 range + subGridDef.setLowerLeftLon(MapUtil + .correctLon(subGridDef.getLowerLeftLon())); + subGridDef.setUpperRightLon(MapUtil + .correctLon(subGridDef.getUpperRightLon())); + + // do a reverse lookup of the model name to get its + // associated grid id + + for (String modelName : subGridDef.getModelNames()) { + GridModel model = gribModelLUT + .getModelByName(modelName); + if (model != null) { + GridCoverage baseCoverage = spatialNameMap + .get(model.getGrid().toString()); + + if (baseCoverage != null) { + SubGrid subGrid = new SubGrid(); + subGrid.setModelName(modelName); + GridCoverage subGridCoverage = baseCoverage + .trim(subGridDef, subGrid); + if (subGridCoverage != null) { + subGrids.put( + subGridCoverage.getName(), + subGridCoverage); + definedSubGridMap.put(modelName, + subGrid); + } + } + } + } + } else { + logger.error("Failed to generate sub grid for " + + fd.getFilePath() + + ". Unable to determine coverage for referenceModel [" + + referenceModel + "]"); + } + } + } catch (Exception e) { + // Log error but do not throw exception + logger.error( + "Failed processing sub grid file: " + + fd.getFilePath(), e); + } + } + } else { + subGrids = new HashMap(0); + } + + return subGrids; + } + + /** + * Loads and validates subGridDef pointed to by filePath. If definition + * empty/invalid returns null. + * + * @param filePath + * @return + */ + private SubGridDef loadSubGridDef(final String filePath, + final Coordinate defaultCenter) { + SubGridDef rval = null; + File f = new File(filePath); + + if (f.length() > 0) { + try { + rval = (SubGridDef) SerializationUtil + .jaxbUnmarshalFromXmlFile(f); + if ((rval.getReferenceModel() == null) + || (rval.getModelNames() == null) + || (rval.getModelNames().size() == 0)) { + // sub grid didn't have required definitions + rval = null; + } else { + if ((rval.getCenterLatitude() == null) + || (rval.getCenterLongitude() == null)) { + rval.setCenterLatitude(defaultCenter.y); + rval.setCenterLongitude(defaultCenter.x); + } + } + } catch (SerializationException e) { + logger.error("Failed reading sub grid file: " + filePath, e); + } + } + + return rval; + } + + private static boolean isDefintionChanged(final FileDataList previousFdl, + final FileDataList currentFdl) { + boolean rval = true; + if (currentFdl != null) { + rval = !currentFdl.equals(previousFdl); + } else { + rval = previousFdl != null; + } + + return rval; + } + + private FileDataList generateFileDataList() { + /* + * Retrieve the list of files from the localization service + */ + IPathManager pm = PathManagerFactory.getPathManager(); + FileDataList fileList = new FileDataList(); + LocalizationContext[] contexts = pm + .getLocalSearchHierarchy(LocalizationType.EDEX_STATIC); + fileList.addCoverageFiles(pm.listFiles(contexts, "/grib/grids", + new String[] { "xml" }, true, true)); + fileList.addSubGridFiles(pm.listFiles(contexts, "/grib/subgrids", + new String[] { "xml" }, true, true)); + + return fileList; + } + + private FileDataList getPreviousFileDataList() { + IPathManager pm = PathManagerFactory.getPathManager(); + File previousFileData = pm.getFile(pm.getContext( + LocalizationType.EDEX_STATIC, LocalizationLevel.CONFIGURED), + "/grib/gridDefFileListing.xml"); + FileDataList rval = null; + + if (previousFileData.exists() && (previousFileData.length() > 0)) { + try { + Object obj = SerializationUtil + .jaxbUnmarshalFromXmlFile(previousFileData); + if (obj instanceof FileDataList) { + rval = (FileDataList) obj; + } else { + logger.error("Error occurred deserializing " + + previousFileData.getAbsolutePath() + + ", expected type " + FileDataList.class + + " received " + obj.getClass()); + } + } catch (Exception e) { + logger.error( + "Error occurred deserializing " + + previousFileData.getAbsolutePath(), e); + } + } + return rval; + } + + private Map loadGridDefinitionsFromDisk( + final FileDataList currentFdl) { + List coverageFiles = currentFdl.getCoverageFileList(); + Map fileCoverageMap = new HashMap( + (int) (coverageFiles.size() * 1.25) + 1); + + /* + * Iterate over file list. Unmarshal to GridCoverage object + */ + for (FileData fd : coverageFiles) { + try { + GridCoverage grid = (GridCoverage) SerializationUtil + .jaxbUnmarshalFromXmlFile(fd.getFilePath()); + GridCoverage previousGrid = fileCoverageMap.put(grid.getName(), + grid); + if (previousGrid != null) { + for (FileData fd2 : coverageFiles) { + GridCoverage grid2 = (GridCoverage) SerializationUtil + .jaxbUnmarshalFromXmlFile(fd2.getFilePath()); + if (grid.getName().equals(grid2.getName())) { + logger.error("Grid " + grid.getName() + + " has already been defined. " + + fd.getFilePath() + " and " + + fd2.getFilePath() + + " have same name. Using " + + fd2.getFilePath()); + break; + } + } + } + } catch (Exception e) { + // Log error but do not throw exception + logger.error( + "Unable to read default grids file: " + + fd.getFilePath(), e); + } + } + + return fileCoverageMap; + } + + private void saveFileDataList(final FileDataList fdl) { + try { + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationFile lf = pm.getLocalizationFile( + pm.getContext(LocalizationType.EDEX_STATIC, + LocalizationLevel.CONFIGURED), + "/grib/gridDefFileListing.xml"); + SerializationUtil.jaxbMarshalToXmlFile(fdl, lf.getFile() + .getAbsolutePath()); + lf.save(); + } catch (Exception e) { + logger.error( + "Failed to save coverage file data list, coverages may be reloaded on next restart", + e); + } + } + + public static void reinitialize() { + GribSpatialCache newInstance = new GribSpatialCache(); + instance = newInstance; + } + + private Coordinate getDefaultSubGridCenterPoint() throws Exception { + Coordinate defaultCenterPoint = null; + IPathManager pm = PathManagerFactory.getPathManager(); + File defaultSubGridLocationFile = pm + .getStaticFile("/grib/defaultSubGridCenterPoint.xml"); + if ((defaultSubGridLocationFile != null) + && defaultSubGridLocationFile.exists()) { + try { + // only used here, just create own manager + JAXBManager mgr = new JAXBManager( + DefaultSubGridCenterPoint.class); + DefaultSubGridCenterPoint defaultSubGridLocation = (DefaultSubGridCenterPoint) mgr + .jaxbUnmarshalFromXmlFile(defaultSubGridLocationFile); + if ((defaultSubGridLocation != null) + && (defaultSubGridLocation.getCenterLatitude() != null) + && (defaultSubGridLocation.getCenterLongitude() != null)) { + defaultCenterPoint = new Coordinate( + defaultSubGridLocation.getCenterLongitude(), + defaultSubGridLocation.getCenterLatitude()); + logger.info("Default sub grid location is overriden as [" + + defaultCenterPoint.y + "/" + defaultCenterPoint.x + + "]"); + } + } catch (Exception e) { + logger.error( + "Unable to load default sub grid location from file: " + + defaultSubGridLocationFile.getAbsolutePath(), + e); + } + } + + if (defaultCenterPoint == null) { + // use wfo center point + String wfo = SiteUtil.getSite(); + GetWfoCenterPoint centerPointRequest = new GetWfoCenterPoint(wfo); + defaultCenterPoint = new GetWfoCenterHandler() + .handleRequest(centerPointRequest); + logger.info("Default sub grid location is wfo center point [" + + defaultCenterPoint.y + "/" + defaultCenterPoint.x + "]"); + } + + return defaultCenterPoint; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/defaultSubGridCenterPoint.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/defaultSubGridCenterPoint.xml new file mode 100644 index 0000000000..4ad2509ec3 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/defaultSubGridCenterPoint.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HPCGuideClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HPCGuideClip.xml index c21da411d4..ab94f7dc86 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HPCGuideClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HPCGuideClip.xml @@ -23,4 +23,8 @@ HPCGuide 1000 689 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresEastClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresEastClip.xml index 82f91ed105..e7b2a4dcd4 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresEastClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresEastClip.xml @@ -23,4 +23,8 @@ HiResW-ARW-East 350 350 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresWestClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresWestClip.xml index 23e0015f63..4d6bc9c00b 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresWestClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/HiresWestClip.xml @@ -23,4 +23,8 @@ HiResW-ARW-West 350 350 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/NamDng5Clip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/NamDng5Clip.xml index 2caa2abc3b..c99157b454 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/NamDng5Clip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/NamDng5Clip.xml @@ -23,4 +23,8 @@ NamDNG5 1000 689 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/RTMAClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/RTMAClip.xml index c4df1fae25..eb01326f9a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/RTMAClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/RTMAClip.xml @@ -23,4 +23,8 @@ RTMA 1000 689 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/TPCSurgeProbClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/TPCSurgeProbClip.xml index 4ea0ecc485..92e3392120 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/TPCSurgeProbClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/TPCSurgeProbClip.xml @@ -23,4 +23,8 @@ TPCSurgeProb 1300 1200 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/eta12Clip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/eta12Clip.xml index d5d24291e0..016e515cd7 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/eta12Clip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/eta12Clip.xml @@ -23,4 +23,8 @@ ETA218 175 175 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/lampClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/lampClip.xml index eb867ff980..0b10917a4a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/lampClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/lampClip.xml @@ -23,4 +23,8 @@ GFSLAMPTstorm 1000 689 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mEtaClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mEtaClip.xml index 00d0305989..731e71509f 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mEtaClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mEtaClip.xml @@ -23,4 +23,8 @@ mesoEta215 175 173 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip.xml index f7b13838f6..5eb5d17fab 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip.xml @@ -23,4 +23,8 @@ MOSGuide 350 350 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip_AK.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip_AK.xml index 7caec069b9..8406bef85a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip_AK.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/mosGuideClip_AK.xml @@ -23,4 +23,8 @@ MOSGuide-AK 1649 1105 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/qpf218Clip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/qpf218Clip.xml index 0c9510408a..eec432b1f6 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/qpf218Clip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/qpf218Clip.xml @@ -23,4 +23,8 @@ RFCqpf 175 175 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/ruc13Clip.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/ruc13Clip.xml index 366dcf955e..27fadd9eae 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/ruc13Clip.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/subgrids/ruc13Clip.xml @@ -23,4 +23,8 @@ RUC130 175 175 + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/.classpath b/edexOsgi/com.raytheon.edex.plugin.pirep/.classpath index 1fa3e6803d..c83df31842 100644 --- a/edexOsgi/com.raytheon.edex.plugin.pirep/.classpath +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/.classpath @@ -3,5 +3,6 @@ + diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.edex.plugin.pirep/META-INF/MANIFEST.MF index 3a178e8193..b535f2431e 100644 --- a/edexOsgi/com.raytheon.edex.plugin.pirep/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/META-INF/MANIFEST.MF @@ -12,7 +12,8 @@ Require-Bundle: com.raytheon.edex.common, org.geotools, javax.measure, javax.persistence, - org.apache.camel;bundle-version="1.0.0";resolution:=optional + org.apache.camel;bundle-version="1.0.0";resolution:=optional, + org.junit;bundle-version="1.0.0" Export-Package: com.raytheon.edex.plugin.pirep, com.raytheon.edex.plugin.pirep.decoder Bundle-RequiredExecutionEnvironment: JavaSE-1.6 diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepParser.java b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepParser.java index 9ee5b4902d..5cb40aa13b 100644 --- a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepParser.java +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepParser.java @@ -58,6 +58,11 @@ import com.vividsolutions.jts.geom.Point; * Date PR# Engineer Description * ----------- ---------- ------------ -------------------------- * 20080116 798 jkorman Changed logging levels. + * ====================================== + * AWIPS2 DR Work + * 08/09/2012 1011 jkorman Changed parser to use TEIInfo to + * parse text elements properly. Removed test code to unit-test + * parse TEIs. * * * @author jkorman @@ -69,14 +74,6 @@ public class PirepParser { // Allowable future time in milliseconds (15 minutes). private static final int ALLOWABLE_TIME = 15; - private static final String[] RPIDS = { "UUA", "UA" }; - - /** - * Note that there are intentionally spaces after some of the teis. - */ - private static final String[] TEIS = { "/OV ", "/TM", "/FL", "/TP", "/SK ", - "/WX", "/TA", "/WV", "/TB", "/IC", "/RM" }; - private static final String SK_SKC = "SKC"; private static final String SK_CLR = "CLR"; @@ -171,12 +168,6 @@ public class PirepParser { // Was character non-alphanumeric but not whitespace? private static final int NONALPHANUMERIC = 3; - // The last search position when looking for TEIs - private int theSearchPos = -1; - - // Where was the Token found - private int theTokenPos; - private String reportData = null; private String theReportingStationId = null; @@ -219,6 +210,7 @@ public class PirepParser { private Headers headers; + private int reportType = IDecoderConstants.PIREP_NORMAL; /** * Construct a PirepParser from given String data. The report is completely * parsed and decoded upon success. @@ -256,7 +248,7 @@ public class PirepParser { } public Integer getReportType() { - return IDecoderConstants.PIREP_NORMAL; + return reportType; } /** @@ -397,114 +389,74 @@ public class PirepParser { * An error occurred within this method. */ protected void parse() { - int pirepIndex = 0; - - // Look for a 'UUA' or 'UA' indicator to denote the start of - // the report. - if (!nextString(reportData, pirepIndex, reportData.length(), RPIDS)) { - return; - } - // if failed to decode reporting station id, this must be Canadian pirep // TODO convert! - - // Find the first TEI within the report. - if (!nextString(reportData, pirepIndex, reportData.length(), TEIS)) { - return; - } - int pos1 = this.theSearchPos; - int tei1 = this.theTokenPos; - int teiIndex = pos1 + TEIS[tei1].length(); - int pos2, tei2; - - while (teiIndex < reportData.length()) { - // Find the end of the data for this TEI by finding the next - // TEI within the report. - int endTeiIndex; - boolean lastTei = !nextString(reportData, teiIndex, - reportData.length(), TEIS); - pos2 = this.theSearchPos; - tei2 = this.theTokenPos; - if (lastTei) { - // This is the last TEI within the report, so set the end - // of the data for this TEI equal to the end of the report. - endTeiIndex = reportData.length(); - } else { - endTeiIndex = pos2; - } - + + List positions = TEIInfo.findTEIs(reportData); + // Look for a 'UUA' or 'UA' indicator to denote the start of + // the report. + if ((positions.size() > 0) && (TEI.PIREP.equals(positions.get(0).getTei()))) { boolean success = false; - switch (tei1) { - case 0: - // Decode and store the "/OV" (i.e. location) data. - success = decodeLocationData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 1: - // Decode and store the "/TM" (i.e. time) data. - success = decodeTimeData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 2: - // Decode and store the "/FL" (i.e. flight level) data. - success = decodeFlightLevelData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 3: - // Decode and store the "/TP" (i.e. aircraft type) data. - success = decodeAircraftTypeData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 4: - // Decode and store the "/SK" (i.e. sky cover) data. - success = decodeSkyCoverData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 5: - // Decode and store the "/WX" (i.e. weather) data. - success = decodeWeatherData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 6: - // Decode and store the "/TA" (i.e. temperature) data. - success = decodeTemperatureData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 7: - // Decode and store the "/WV" (i.e. wind) data. - success = decodeWindData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 8: - // Decode and store the "/TB" (i.e. turbulence) data. - success = decodeTurbulenceData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 9: - // Decode and store the "/IC" (i.e. icing) data. - success = decodeIcingData(reportData.substring(teiIndex, - endTeiIndex)); - break; - case 10: - // Decode and store the "/RM" (i.e. remarks) data. - success = decodeRemarksData(reportData.substring(teiIndex, - endTeiIndex)); - break; - } // switch() + for (TEIInfo t : positions) { + switch (t.getTei()) { + case PIREP: { + // success = decodeReportingStationId(t.getTeiText()); + success = true; + break; + } + case OV: + // Decode and store the "/OV" (i.e. location) data. + success = decodeLocationData(t.getTeiText()); + break; + case TM: + // Decode and store the "/TM" (i.e. time) data. + success = decodeTimeData(t.getTeiText()); + break; + case FL: + // Decode and store the "/FL" (i.e. flight level) data. + success = decodeFlightLevelData(t.getTeiText()); + break; + case TP: + // Decode and store the "/TP" (i.e. aircraft type) data. + success = decodeAircraftTypeData(t.getTeiText()); + break; + case SK: + // Decode and store the "/SK" (i.e. sky cover) data. + success = decodeSkyCoverData(t.getTeiText()); + break; + case WX: + // Decode and store the "/WX" (i.e. weather) data. + success = decodeWeatherData(t.getTeiText()); + break; + case TA: + // Decode and store the "/TA" (i.e. temperature) data. + success = decodeTemperatureData(t.getTeiText()); + break; + case WV: + // Decode and store the "/WV" (i.e. wind) data. + success = decodeWindData(t.getTeiText()); + break; + case TB: + // Decode and store the "/TB" (i.e. turbulence) data. + success = decodeTurbulenceData(t.getTeiText()); + break; + case IC: + // Decode and store the "/IC" (i.e. icing) data. + success = decodeIcingData(t.getTeiText()); + break; + case RM: + // Decode and store the "/RM" (i.e. remarks) data. + success = decodeRemarksData(t.getTeiText()); + break; + default: { + logger.error(String.format("Invalid PIREP identifier [%s] found", t.getTeiText())); + break; + } + } // switch() + } // for + } else { - // discontinue if processing of any data fails - if (!success) { - // TODO: add logging - } - - if (lastTei) { - teiIndex = reportData.length(); - } else { - pos1 = pos2; - tei1 = tei2; - teiIndex = pos1 + TEIS[tei1].length(); - } - } // while() + } } // parse() /** @@ -1034,7 +986,7 @@ public class PirepParser { * A possible temperature to be decoded. * @return Was the temperature data decoded. * @throws DecodeException - * If a decode error occured. + * If a decode error occurred. */ protected boolean decodeTemperatureData(String aTemperature) { // Break up the input string into groups of "like-type" in order @@ -1495,54 +1447,6 @@ public class PirepParser { } } - /** - * The nextString method determines the position of the first occurrence of - * any of a list of substrings within the input string. This method provides - * equivalent functionality to the routine ST_NXTS in the ported code. The - * outputs are provided in member variables. - * - * @param str - * Input string - * @param firstPos - * First position to check - * @param lastPos - * Last position to check - * @param subStrings - * List of substrings - * @return success or failure - */ - protected boolean nextString(String str, int firstPos, int lastPos, - String subStrings[]) { - this.theTokenPos = -1; - String tstr = str.substring(0, lastPos); - for (int i = 0; i < subStrings.length; i++) { - if ((this.theSearchPos = tstr.indexOf(subStrings[i], firstPos)) != -1) { - this.theTokenPos = i; - return true; - } - } - - return false; - } - - /** - * This method finds a string in a string array and returns its index. - * - * @param str - * String to find - * @param strs - * Strings to compare - * @return index of matching string or -1 on failure - */ - protected int findString(String str, String[] strs) { - for (int i = 0; i < strs.length; i++) { - if (strs[i].equals(str)) { - return i; - } - } - return -1; - } // findString() - /** * This method groups "like-types" of characters to facilitate decoding. * This method provides equivalent functionality to the UT_BKGP subroutine @@ -1587,63 +1491,4 @@ public class PirepParser { return strs.toArray(new String[0]); } - - public static final void main(String[] args) { - - String[] latlons = { "0000N 00000W", "0000S 00000E", "9000S 00000W", - "9000N 00000W", "0000N 09000W", "9000S 09000W", "9000N 09000W", - - "0000N 09000W", "4500S 09000W", "9000N 09000W", - - "9000N 09959W", "0000N 10000W", - - "4500S 09000W", "9000N 09000W", - - "9000N 18000E", "9000S 18000E", "9000N 18000W", "9000S 18000W", - "9000N 17959W", "9000S 17959W", - - }; - - Pattern p = Pattern.compile(LATLON_PTRN); - - for (String s : latlons) { - Matcher m = p.matcher(s); - if (m.find()) { - BasePoint b = parseLatLon(m.group()); - if (b != null) { - System.out.println(String.format("%16s %10.6f %11.6f", s, - b.getLatitude(), b.getLongitude())); - } else { - System.out.println("Invalid parse " + s); - } - } else { - System.out.println("no match for " + s); - } - } - - String str = "123 123 123 \r SCT"; - - str = str.replaceAll("[\r\n]", " "); - str = str.replaceAll(" {2,}", " "); - - System.out.println("[" + str + "]"); - - p = Pattern.compile(bearingDistPattern); - Matcher m = p.matcher("OMA 080056"); - if(m.find()) { - System.out.println(m.group(1)); - System.out.println(m.group(2) + " " + m.group(3)); - } - m = p.matcher("OMA080056"); - if(m.find()) { - System.out.println(m.group(1)); - System.out.println(m.group(2) + " " + m.group(3)); - } - - - - - - } - } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepTools.java b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepTools.java index d88d009a59..b1421b4814 100644 --- a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepTools.java +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/PirepTools.java @@ -20,16 +20,14 @@ package com.raytheon.edex.plugin.pirep.decoder; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import com.raytheon.uf.edex.decodertools.aircraft.AircraftFlightCondition; import com.raytheon.uf.edex.decodertools.aircraft.Entry; import com.raytheon.uf.edex.decodertools.aircraft.WordTranslator; /** - * TODO Add Description + * Perform decode on PIREP turbulence layers. * *
  * 
@@ -38,6 +36,9 @@ import com.raytheon.uf.edex.decodertools.aircraft.WordTranslator;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Jun 10, 2011            jkorman     Initial creation
+ * ======================================
+ * AWIPS2 DR Work
+ * 08/09/2012         1011 jkorman     Removed test code to unit test.
  * 
  * 
* @@ -50,7 +51,6 @@ public class PirepTools { private static final char SPACE = ' '; private static final char DASH = '-'; - private static final char SOLIDUS = '/'; @@ -164,13 +164,15 @@ public class PirepTools { TURBC_WORDS.enter("-", "-", false, TURBC_SYN_DASH, SYN_ID); } + // Data that may contain layer information. private String layerData; + // Layers decoded from layerData private List layers; /** - * - * @param data + * Construct zero or more layers from the supplied data. + * @param data A string that may contain layer information. */ public PirepTools(String data) { layerData = data; @@ -403,9 +405,9 @@ public class PirepTools { } /** - * If there are two intensity modifiers, reorder them so the the - * lower intensity occurs first. - * @param layer A layer that may contain intensity modifiers. + * If there are two heights, reorder them so the the + * lower height occurs first. + * @param layer A layer that may contain layer heights. */ private void reOrderHeight(AircraftFlightCondition layer) { if(layer != null) { @@ -440,57 +442,4 @@ public class PirepTools { return retValue; } // parseInteger() - /** - * @param args - */ - public static void main(String[] args) { - - // PirepTools tools = new - // PirepTools("OCNL LGT CHOP/MDT 100-150/LGT 150-200"); - - -// List list = tools.decodeTurbulenceData(); -// for (AircraftFlightCondition c : list) { -// System.out.println(c); -// } - - String [] data = { - "LGT 100-120", - "MOD TO SVR 100", - "SVR OCNL MOD 200-300", - "LGT CHOP 150 TO 110", - "LGT-MDT 120-150", - "MDT BLO\n 100", - "LIT-MOD CHOP ABOVE 120", - "CONTINOUS MOD 120-080"}; - for(String s : data) { - PirepTools tools = new PirepTools(s); - - List list = tools.decodeTurbulenceData(); - for(AircraftFlightCondition afc : list) { - String ss = afc.getFrequency(); - System.out.print((ss != null) ? ss : "----"); - System.out.print(" "); - ss = afc.getIntensity1(); - System.out.print((ss != null) ? ss : "----"); - System.out.print(" "); - ss = afc.getIntensity2(); - System.out.print((ss != null) ? ss : "----"); - System.out.print(" "); - ss = afc.getType(); - System.out.print((ss != null) ? ss : "----"); - System.out.print(" "); - Integer n = afc.getBaseHeight(); - System.out.print((n != null) ? n : "----"); - System.out.print(" "); - n = afc.getTopHeight(); - System.out.print((n != null) ? n : "----"); - System.out.println(); - - } - } - - - } - } diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEI.java b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEI.java new file mode 100644 index 0000000000..7547311a05 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEI.java @@ -0,0 +1,124 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.edex.plugin.pirep.decoder; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Enum that identifies the PIREP Text Element Indicators (TEIs). + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * AWIPS2 DR Work
+ * Aug 7, 2012        1011 jkorman     Initial creation
+ * 
+ * 
+ * + * @author jkorman + * @version 1.0 + */ + +public enum TEI implements Iterable { + // This TEI is used to identify the start of the PIREP, i.e. SSS [UA|UUA] + PIREP("PIREP"), OV("/OV "), TM("/TM "), FL("/FL"), TP("/TP"), SK("/SK "), WX( + "/WX"), TA("/TA"), WV("/WV"), TB("/TB"), IC("/IC"), RM("/RM"), + + NF("NF"); // These two don't go into the id map! + + // Map of valid TEIs. + private static Map ID_MAP = new HashMap(); + static { + ID_MAP.put(OV.id, OV); + ID_MAP.put(TM.id, TM); + ID_MAP.put(FL.id, FL); + ID_MAP.put(TP.id, TP); + ID_MAP.put(SK.id, SK); + ID_MAP.put(WX.id, WX); + ID_MAP.put(TA.id, TA); + ID_MAP.put(WV.id, WV); + ID_MAP.put(TB.id, TB); + ID_MAP.put(IC.id, IC); + ID_MAP.put(RM.id, RM); + } + + private String id; + + /** + * Construct a TEI with a specified identifier. + * + * @param id + * The identifier to assign. + */ + private TEI(String id) { + this.id = id; + } + + /** + * Get the identifier for this TEI. + * + * @return The TEI identifier. + */ + public String getId() { + return id; + } + + /** + * Get the string representation of this TEI. This returns the same as + * getId(). + * + * @return The TEI string representation. + */ + public String toString() { + return id; + } + + /** + * Get an iterator to the valid TEIs. This iterable iterator the TEI NF (not + * found). + * + * @return An iterator to the valid TEIs. + */ + @Override + public Iterator iterator() { + return ID_MAP.values().iterator(); + } + + /** + * Get a TEI based on its string identifier. Returns the TEI "NF" if the TEI + * identifier could not be found. + * + * @param id + * A candidate TEI identifier. + * @return The TEI found, or NF if not found. + */ + public static TEI getTEI(String id) { + TEI tei = NF; + if (ID_MAP.containsKey(id)) { + tei = ID_MAP.get(id); + } + return tei; + } +} \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEIInfo.java b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEIInfo.java new file mode 100644 index 0000000000..3b3d767171 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/src/com/raytheon/edex/plugin/pirep/decoder/TEIInfo.java @@ -0,0 +1,210 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.edex.plugin.pirep.decoder; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Parse Pilot Report (PIREP) Text Element Indicators (TEIs) from potential + * report text. This + * + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * AWIPS2 DR Work
+ * Aug 7, 2012        1011 jkorman     Initial creation
+ * 
+ * 
+ * + * @author jkorman + * @version 1.0 + */ + +public class TEIInfo implements Comparable { + // The start position of this TEI within the decoded data. + private int start; + + // The stop position of this TEI's text within the decoded data. + private int stop; + + // The TEI associated with the info. + private TEI tei; + + // The extracted text associated with this TEI. + private String teiText; + + /** + * Construct a TEIInfo instance with a given TEI, position, and index. + * + * @param tei + * @param position + * @param teiIndex + */ + private TEIInfo(TEI tei, int position) { + this.tei = tei; + start = position; + } + + /** + * + */ + @Override + public String toString() { + return String.format("%s:%d:%d:%d", tei, start, stop); + } + + /** + * Calculate the hashCode for this instance. + * + * @return The calculated hashCode. + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + start; + result = prime * result + ((tei == null) ? 0 : tei.hashCode()); + result = prime * result + ((teiText == null) ? 0 : teiText.hashCode()); + return result; + } + + /** + * Is this instance equal to another object instance. + * + * @return Is this instance equal to another object instance. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TEIInfo other = (TEIInfo) obj; + if (start != other.start) + return false; + if (tei != other.tei) + return false; + if (teiText == null) { + if (other.teiText != null) + return false; + } else if (!teiText.equals(other.teiText)) + return false; + return true; + } + + /** + * Override compareTo for TEIInfo. This method uses the start position of + * the TEI within the decoded data as the comparands. + */ + @Override + public int compareTo(TEIInfo t) { + return (t.start == start) ? 0 : (t.start < start) ? 1 : -1; + } + + /** + * Get the TEI that was decoded. + * + * @return The decoded TEI. + */ + public TEI getTei() { + return tei; + } + + /** + * Get the extracted text for the TEI. + * + * @return The TEI extracted text. + */ + public String getTeiText() { + return teiText; + } + + /** + * Extract the TEI information as well as the text data associated with that + * TEI into a collection of TEIInfo objects. Out of order data can be correctly + * parsed and returned. + * + * @param str + * Data containing a PIREP. + * @return Returns a list of TEIs found in the input data. Returns a zero + * length list if the input was null or no TEIs could be found. + */ + public static List findTEIs(String str) { + List positions = new ArrayList(); + if (str != null) { + int teiIndex = 0; + // loop over the valid TEIs + for (TEI tei : TEI.PIREP) { + int n = str.indexOf(tei.getId()); + if (n >= 0) { + TEIInfo info = new TEIInfo(tei, n); + positions.add(info); + } + teiIndex++; + } + Collections.sort(positions); + if (positions.size() > 0) { + TEIInfo tt = positions.get(0); + // Ensure that the PIREP is starting correctly! + if (TEI.OV.equals(tt.tei)) { + // Note that this will find both "UA" and "UUA" + if (str.substring(0, tt.start).indexOf("UA") > 0) { + // Insert the PIREP element at the 'head' of the list + positions.add(0, new TEIInfo(TEI.PIREP, 0)); + // Now iterate the list and fixup the stop positions + // of each TEI + TEIInfo previous = null; + for (TEIInfo t : positions) { + if (previous == null) { + previous = t; + } else { + previous.stop = t.start; + previous = t; + } + } + // Set the last TEI stop position to the end of the + // report. + previous.stop = str.length(); + } + } + } + // Now come in and extract the text associated with each TEI. + for (TEIInfo t : positions) { + if (TEI.PIREP.equals(t.getTei())) { + // Pick up the leading portion of the PIREP + t.teiText = str.substring(t.start, t.stop).trim(); + } else { + t.teiText = str.substring( + t.start + t.getTei().getId().length(), t.stop) + .trim(); + } + } + } + return positions; + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPParser.java b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPParser.java new file mode 100644 index 0000000000..53d3fb75bd --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPParser.java @@ -0,0 +1,167 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package test.pirep; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Test; + +import com.raytheon.edex.plugin.pirep.decoder.PirepTools; +import com.raytheon.uf.edex.decodertools.core.BasePoint; + +import static org.junit.Assert.*; + + +/** + * Extracted methods tests from PirepParser. + * + *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 10, 2012            jkorman     Initial creation
+ *
+ * 
+ * + * @author jkorman + * @version 1.0 + */ + +public class TestPIREPParser { + + private static final String LATLON_PTRN = "((([0-8]\\d[0-5]\\d)|(9000))[NS] ((0\\d{2}[0-5]\\d)|([1][0-7]\\d[0-5]\\d)|(18000))[EW])"; + + private static BasePoint parseLatLon(String latlon) { + BasePoint point = null; + + // 012345678901 + // lldds llldds + + Integer lat_dd = PirepTools.parseInteger(latlon.substring(0, 2)); + Integer lat_mm = PirepTools.parseInteger(latlon.substring(2, 4)); + Integer lon_dd = PirepTools.parseInteger(latlon.substring(6, 9)); + Integer lon_mm = PirepTools.parseInteger(latlon.substring(9, 11)); + + if ((lat_dd != null) && (lat_mm) != null) { + if ((lon_dd != null) && (lon_mm) != null) { + + Double lat = lat_dd + (lat_mm / 60.0d); + Double lon = lon_dd + (lon_mm / 60.0d); + if (lat_dd.equals(0) && (lat_mm.equals(0))) { + lat = 0.0; + } else { + switch (latlon.charAt(4)) { + case 'N': { + break; + } + case 'S': { + lat = lat * -1; + break; + } + default: { + lat = null; + } + } + } + if (lon_dd.equals(0) && (lon_mm.equals(0))) { + lon = 0.0; + } else { + switch (latlon.charAt(11)) { + case 'E': { + break; + } + case 'W': { + lon = lon * -1; + break; + } + default: { + lon = null; + } + } + } + if (lat != null && lon != null) { + point = new BasePoint(lat, lon); + } + } + } + return point; + } + + @Test + public void testparseLatLon() { + String[] latlons = { "0000N 00000W", "0000S 00000E", "9000S 00000W", + "9000N 00000W", "0000N 09000W", "9000S 09000W", "9000N 09000W", + + "0000N 09000W", "4500S 09000W", "9000N 09000W", + + "9000N 09959W", "0000N 10000W", + + "4500S 09000W", "9000N 09000W", + + "9000N 18000E", "9000S 18000E", "9000N 18000W", "9000S 18000W", + "9000N 17959W", "9000S 17959W", + }; + + Pattern p = Pattern.compile(LATLON_PTRN); + + for (String s : latlons) { + Matcher m = p.matcher(s); + if (m.find()) { + BasePoint b = parseLatLon(m.group()); + if (b != null) { + System.out.println(String.format("%16s %10.6f %11.6f", s, + b.getLatitude(), b.getLongitude())); + } else { + fail("Invalid parse " + s); + } + } else { + fail("no match for " + s); + } + } + } + + @Test + public void testBearingDistancePattern() { + final String bearingDistPattern = "^([A-Z,0-9]{3,4})\\s*(\\d{3})(\\d{3})$"; + + String str = "123 123 123 \r SCT"; + + str = str.replaceAll("[\r\n]", " "); + str = str.replaceAll(" {2,}", " "); + + System.out.println("[" + str + "]"); + + Pattern p = Pattern.compile(bearingDistPattern); + Matcher m = p.matcher("OMA 080056"); + if(m.find()) { + System.out.println(m.group(1)); + System.out.println(m.group(2) + " " + m.group(3)); + } + m = p.matcher("OMA080056"); + if(m.find()) { + System.out.println(m.group(1)); + System.out.println(m.group(2) + " " + m.group(3)); + } + + } +} diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPRecord.java b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPRecord.java new file mode 100644 index 0000000000..70e1f7607a --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestPIREPRecord.java @@ -0,0 +1,233 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package test.pirep; + +import java.util.List; + +import org.junit.Test; + +import com.raytheon.edex.plugin.pirep.decoder.PirepTools; +import com.raytheon.uf.common.dataplugin.pirep.PirepLayerData; +import com.raytheon.uf.common.dataplugin.pirep.PirepRecord; +import com.raytheon.uf.edex.decodertools.aircraft.AircraftFlightCondition; + +import static org.junit.Assert.*; + +/** + * Test various PIREP decoder components. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 8, 2012            jkorman     Initial creation
+ * 
+ * 
+ * + * @author jkorman + * @version 1.0 + */ + +public class TestPIREPRecord { + + /** + * Test that the getter for TBF (turbulence frequency) and TBI (turbulence + * intensity) get the data for the greatest intensity. + */ + @Test + public void testTurbulenceConstruction() { + + PirepRecord rec = new PirepRecord(); + + PirepLayerData layer = new PirepLayerData(rec); + layer.setLayerType(PirepLayerData.LAYER_TYP_TURBC); + layer.setFrequency("OCN"); + layer.setFirstValue("LGT"); + layer.setSecondValue("MOD"); + layer.setBaseLayerHeight(15000); + layer.setTopLayerHeight(20000); + rec.addLayer(layer); + + layer = new PirepLayerData(rec); + layer.setLayerType(PirepLayerData.LAYER_TYP_TURBC); + layer.setFrequency("CON"); + layer.setFirstValue("MOD"); + layer.setSecondValue("SEV"); + layer.setBaseLayerHeight(20000); + layer.setTopLayerHeight(22000); + rec.addLayer(layer); + + String[] data = rec.getStrings("TBF"); + assertNotNull(data); + assertTrue(data.length > 0); + assertEquals("CON", data[0]); + data = rec.getStrings("TBI"); + assertNotNull(data); + assertTrue(data.length > 0); + assertEquals("MODSEV", data[0]); + } + + /** + * Turbulence at one level, differing intensities. + */ + @Test + public void testPirepTurbc_1() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(10000); + expected.setTopHeight(null); + expected.setIntensity1("MOD"); + expected.setIntensity2("SEV"); + expected.setType(null); + expected.setFrequency(null); + + PirepTools t = new PirepTools("MOD TO SVR 100"); + checkLevel(t, 1); + checkData(expected, t.decodeTurbulenceData().get(0)); + } + + /** + * Turbulence between levels, differing intensities with frequency. + */ + @Test + public void testPirepTurbc_2() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(20000); + expected.setTopHeight(30000); + expected.setIntensity1("MOD"); + expected.setIntensity2("SEV"); + expected.setType(null); + expected.setFrequency("OCN"); + + PirepTools t = new PirepTools("SVR OCNL MOD 200-300"); + checkLevel(t, 1); + checkData(expected, t.decodeTurbulenceData().get(0)); + } + + /** + * Turbulence between levels, differing intensities. + */ + @Test + public void testPirepTurbc_3() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(12000); + expected.setTopHeight(15000); + expected.setIntensity1("LGT"); + expected.setIntensity2("MOD"); + expected.setType(null); + expected.setFrequency(null); + + PirepTools t = new PirepTools("LGT-MDT 120-150"); + checkLevel(t, 1); + checkData(expected, t.decodeTurbulenceData().get(0)); + } + + /** + * Turbulence below a level, single intensity. Embedded carriage control + * should be ignored. + */ + @Test + public void testPirepTurbc_4() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(-9999); + expected.setTopHeight(10000); + expected.setIntensity1("MOD"); + expected.setIntensity2(null); + expected.setType(null); + expected.setFrequency(null); + + PirepTools t = new PirepTools("MDT BLO\n 100"); + checkLevel(t, 1); + checkData(expected, t.decodeTurbulenceData().get(0)); + } + + /** + * Turbulence above a level, differing intensities. Light turbulence (LGT) + * is misspelled. Includes a turbulence type. + */ + @Test + public void testPirepTurbc_5() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(-9999); + expected.setTopHeight(12000); + expected.setIntensity1("LGT"); + expected.setIntensity2("MOD"); + expected.setType("CHOP"); + expected.setFrequency(null); + + PirepTools t = new PirepTools("LIT-MOD CHOP ABOVE 120"); + checkLevel(t, 1); + checkData(expected, t.decodeTurbulenceData().get(0)); + } + + /** + * Turbulence between two levels, show that levels are reordered. Includes a + * turbulence frequency, show that it is corrected. + */ + @Test + public void testPirepTurbc_6() { + AircraftFlightCondition expected = new AircraftFlightCondition(); + expected.setBaseHeight(8000); + expected.setTopHeight(12000); + expected.setIntensity1("MOD"); + expected.setIntensity2(null); + expected.setType(null); + expected.setFrequency("CON"); + + PirepTools t = new PirepTools("CONTINOUS MOD 120-080"); + checkLevel(t, 1); + List list = t.decodeTurbulenceData(); + checkData(expected, list.get(0)); + } + + /** + * Checks that the PirepTools has decoded data. + * + * @param tools + * The tools object that contains decoded data. + */ + private void checkLevel(PirepTools tools, int elements) { + assertNotNull(tools); + List list = tools.decodeTurbulenceData(); + assertNotNull(list); + assertEquals(elements, list.size()); + } + + /** + * Checks individual data elements. + * + * @param expected + * The expected flight conditions. + * @param actual + * The actual decoded flight conditions. + */ + private void checkData(AircraftFlightCondition expected, + AircraftFlightCondition actual) { + assertEquals(expected.getFrequency(), actual.getFrequency()); + assertEquals(expected.getIntensity1(), actual.getIntensity1()); + assertEquals(expected.getIntensity2(), actual.getIntensity2()); + assertEquals(expected.getType(), actual.getType()); + assertEquals(expected.getBaseHeight(), actual.getBaseHeight()); + assertEquals(expected.getTopHeight(), actual.getTopHeight()); + + } + +} diff --git a/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestTEIInfo.java b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestTEIInfo.java new file mode 100644 index 0000000000..6431bbfe10 --- /dev/null +++ b/edexOsgi/com.raytheon.edex.plugin.pirep/unit-test/test/pirep/TestTEIInfo.java @@ -0,0 +1,118 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package test.pirep; + +import java.util.List; + +import org.junit.Test; +import static org.junit.Assert.*; + +import com.raytheon.edex.plugin.pirep.decoder.TEI; +import com.raytheon.edex.plugin.pirep.decoder.TEIInfo; + +/** + * Various unit tests for the TEIInfo parser class. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 7, 2012            jkorman     Initial creation
+ * 
+ * 
+ * + * @author jkorman + * @version 1.0 + */ + +public class TestTEIInfo { + + /** + * Test that a legal PIREP is parsed correctly. + */ + @Test + public void testParseNormal() { + final String data = "LYH UA /OV LYH/TM 1226/FL210/TP P180/SK OVC100/WX FV99SM/TA 0/WV 27035KT/TB MDT/IC LGT RIME/RM CB W="; + + List parts = TEIInfo.findTEIs(data); + assertNotNull(parts); + assertEquals(12, parts.size()); + assertEquals(TEI.PIREP, parts.get(0).getTei()); + assertEquals(TEI.OV, parts.get(1).getTei()); + assertEquals(TEI.TM, parts.get(2).getTei()); + assertEquals(TEI.FL, parts.get(3).getTei()); + assertEquals(TEI.TP, parts.get(4).getTei()); + assertEquals(TEI.SK, parts.get(5).getTei()); + assertEquals(TEI.WX, parts.get(6).getTei()); + assertEquals(TEI.TA, parts.get(7).getTei()); + assertEquals(TEI.WV, parts.get(8).getTei()); + assertEquals(TEI.TB, parts.get(9).getTei()); + assertEquals(TEI.IC, parts.get(10).getTei()); + assertEquals(TEI.RM, parts.get(11).getTei()); + } + + /** + * Test that out of order elements are parsed correctly. + */ + @Test + public void testParseBadOrder() { + final String data = "LYH UA /OV LYH/TM 1226/FL210/SK OVC100/TP P180/WX FV99SM/TA 0/WV 27035KT/IC LGT RIME/TB MDT/RM CB W="; + + List parts = TEIInfo.findTEIs(data); + assertNotNull(parts); + assertEquals(12, parts.size()); + assertEquals(TEI.PIREP, parts.get(0).getTei()); + assertEquals(TEI.OV, parts.get(1).getTei()); + assertEquals(TEI.TM, parts.get(2).getTei()); + assertEquals(TEI.FL, parts.get(3).getTei()); + assertEquals(TEI.SK, parts.get(4).getTei()); + assertEquals(TEI.TP, parts.get(5).getTei()); + assertEquals(TEI.WX, parts.get(6).getTei()); + assertEquals(TEI.TA, parts.get(7).getTei()); + assertEquals(TEI.WV, parts.get(8).getTei()); + assertEquals(TEI.IC, parts.get(9).getTei()); + assertEquals(TEI.TB, parts.get(10).getTei()); + assertEquals(TEI.RM, parts.get(11).getTei()); + } + + /** + * Test that "/SKC" does not get confused with the "/SK" TEI. + */ + @Test + public void testSky() { + final String data = "LYH UA /OV LYH/TM 1226/FL210/SK OVC100/SKC/TA 0/WV 27035KT="; + final String skyData = "OVC100/SKC"; + + List parts = TEIInfo.findTEIs(data); + assertNotNull(parts); + assertEquals(7, parts.size()); + assertEquals(TEI.PIREP, parts.get(0).getTei()); + assertEquals(TEI.OV, parts.get(1).getTei()); + assertEquals(TEI.TM, parts.get(2).getTei()); + assertEquals(TEI.FL, parts.get(3).getTei()); + assertEquals(TEI.SK, parts.get(4).getTei()); + assertEquals(skyData, parts.get(4).getTeiText()); + assertEquals(TEI.TA, parts.get(5).getTei()); + assertEquals(TEI.WV, parts.get(6).getTei()); + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java index 41cc02bc04..51fdd5e2cf 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPDataContainer.java @@ -31,7 +31,6 @@ import com.raytheon.uf.common.monitor.xml.SourceXML; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; - /** * FFTI Data Container * @@ -42,6 +41,7 @@ import com.raytheon.uf.common.status.UFStatus; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 03/31/11 5489 D. Hladky Initial release + * 07/31/12 578 D.Hladky finished it * * * @@ -50,14 +50,14 @@ import com.raytheon.uf.common.status.UFStatus; */ public class FFMPDataContainer { - - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(FFMPDataContainer.class); + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(FFMPDataContainer.class); private HashMap basinDataMap = new HashMap(); private String sourceName = null; - + private String filePath = null; public FFMPDataContainer() { @@ -88,11 +88,11 @@ public class FFMPDataContainer { * @return */ public FFMPBasinData getBasinData(String huc) { - if (basinDataMap.containsKey(huc)) { - return basinDataMap.get(huc); - } else { - return null; - } + if (basinDataMap.containsKey(huc)) { + return basinDataMap.get(huc); + } else { + return null; + } } /** @@ -142,160 +142,150 @@ public class FFMPDataContainer { if (source.getSourceType().equals(SOURCE_TYPE.GUIDANCE.getSourceType())) { guid = true; } - - FFMPBasinData currBasinData = getBasinData(huc); - if (currBasinData == null) { - setBasinData(huc, newBasinData); - } else { + FFMPBasinData currBasinData = getBasinData(huc); - for (Long key : newBasinData.getBasins().keySet()) { + if (currBasinData == null) { + setBasinData(huc, newBasinData); + } else { - if (guid) { + for (Long key : newBasinData.getBasins().keySet()) { - FFMPGuidanceBasin basin = null; + if (guid) { - if (currBasinData.get(key) instanceof FFMPGuidanceBasin) { - basin = (FFMPGuidanceBasin) currBasinData.get(key); - } + FFMPGuidanceBasin basin = null; - if (basin == null) { + if (currBasinData.get(key) instanceof FFMPGuidanceBasin) { + basin = (FFMPGuidanceBasin) currBasinData.get(key); + } - FFMPBasin newbasin = newBasinData.get(key); - basin = new FFMPGuidanceBasin(key, - newbasin.getAggregated()); + if (basin == null) { - if (newbasin instanceof FFMPGuidanceBasin) { + FFMPBasin newbasin = newBasinData.get(key); + basin = new FFMPGuidanceBasin(key, + newbasin.getAggregated()); - basin.setValue( - source.getSourceName(), - date, - ((FFMPGuidanceBasin) newbasin).getValue( - source.getSourceName(), - source.getExpirationMinutes(siteKey) * 60 * 1000)); - } else { - basin.setValue(source.getSourceName(), date, - newBasinData.get(key).getValue()); - } + if (newbasin instanceof FFMPGuidanceBasin) { - currBasinData.put(key, basin); + Float val = ((FFMPGuidanceBasin) newbasin).getValue(date, source.getSourceName()); + basin.setValue(source.getSourceName(), date, val); + } else { + Float val = newbasin.getValue(date); + basin.setValue(source.getSourceName(), date, val); + } - } else { + currBasinData.put(key, basin); - FFMPBasin newbasin = newBasinData.get(key); + } else { - if (newbasin instanceof FFMPGuidanceBasin) { + FFMPBasin newbasin = newBasinData.get(key); - if (basin.getValue(date, source.getSourceName()) != null - && (basin.getValue(date, - source.getSourceName()) >= 0.0f && !basin - .getValue(date, - source.getSourceName()) - .isNaN())) { + if (newbasin instanceof FFMPGuidanceBasin) { + + FFMPGuidanceBasin newGbasin = (FFMPGuidanceBasin)newBasinData.get(key); + Float basinVal = basin.getValue(date, source.getSourceName()); + Float newBasinVal = newGbasin.getValue(date, source.getSourceName()); - if (((FFMPGuidanceBasin) newbasin).getValue( - date, source.getSourceName()) >= 0.0f - && !((FFMPGuidanceBasin) newbasin) - .getValue(date, - source.getSourceName()) - .isNaN()) { + if (basinVal != null + && basinVal >= 0.0f + && !basinVal.isNaN() + && basinVal != FFMPUtils.MISSING) { - float val = (float) (basin.getValue(date, - source.getSourceName()) + ((FFMPGuidanceBasin) newbasin) - .getValue( - source.getSourceName(), - source.getExpirationMinutes(siteKey) * 60 * 1000) / 2.0); + if (newBasinVal != null + && newBasinVal >= 0.0f + && !newBasinVal.isNaN() + && newBasinVal != FFMPUtils.MISSING) { - basin.setValue(source.getSourceName(), - date, val); - } + float val = (float) ((basinVal + newBasinVal) / 2.0); + basin.setValue(source.getSourceName(), + date, val); + } + } else { + + if (newBasinVal.isNaN()) { + newBasinVal = FFMPUtils.MISSING; + } + + basin.setValue(source.getSourceName(), + date, newBasinVal); + } - } else { + } else { - if (!basin.containsKey(date, - source.getSourceName()) - && newbasin != null) { - basin.setValue(source.getSourceName(), - date, - ((FFMPGuidanceBasin) newbasin) - .getValue(date, source - .getSourceName())); - } - } + Float basinVal = basin.getValue(date, source.getSourceName()); + Float newBasinVal = newbasin.getValue(); + + if (basinVal != null + && basinVal >= 0.0f + && !basinVal.isNaN() + && basinVal != FFMPUtils.MISSING) { + + if (newBasinVal != null + && newBasinVal >= 0.0f + && !newBasinVal.isNaN() + && newBasinVal != FFMPUtils.MISSING) { - } else { - // meaning, it's a brand new file, we don't cast - // those out + float val = (float) ((basinVal + newBasinVal) / 2.0); + basin.setValue(source.getSourceName(), + date, val); + } + } else { + + if (newBasinVal.isNaN()) { + newBasinVal = FFMPUtils.MISSING; + } + + basin.setValue(source.getSourceName(), + date, newBasinVal); + } + } + } + + } else { - if (newbasin.getValue(date) != null - && newbasin.getValue(date) >= 0.0f - && !newbasin.getValue(date).isNaN() - && ((FFMPGuidanceBasin) basin).getValue( - date, source.getSourceName()) >= 0.0f - && !((FFMPGuidanceBasin) basin).getValue( - date, source.getSourceName()) - .isNaN()) { + FFMPBasin basin = currBasinData.get(key); + FFMPBasin newbasin = newBasinData.get(key); + Float val = 0.0f; - float val = (float) ((basin.getValue(date, - source.getSourceName()) + newbasin - .getValue()) / 2); + if (basin == null) { - basin.setValue(source.getSourceName(), date, - val); + basin = new FFMPBasin(key, newbasin.getAggregated()); + val = newbasin.getValue(date); - } else { + if (val.isNaN()) { + val = 0.0f; + } - basin.setValue(source.getSourceName(), date, - newbasin.getValue(date)); - } - } - } + basin.setValue(date, val); + currBasinData.put(key, basin); - } else { + } else { - FFMPBasin basin = currBasinData.get(key); - FFMPBasin newbasin = newBasinData.get(key); - Float val = 0.0f; + if (basin.getValue(date) != null + && !basin.getValue(date).isNaN() + && basin.getValue(date) != 0.0) { + if (newbasin.getValue(date) != null + && !newbasin.getValue(date).isNaN() + && newbasin.getValue(date) != 0.0) { - if (basin == null) { + val = (float) ((basin.getValue(date) + newbasin + .getValue(date)) / 2); + } - basin = new FFMPBasin(key, newbasin.getAggregated()); - val = newbasin.getValue(date); + } else { + val = newbasin.getValue(date); - if (val.isNaN()) { - val = 0.0f; - } + if (val.isNaN()) { + val = 0.0f; + } + } - basin.setValue(date, val); - currBasinData.put(key, basin); - - } else { - - if (basin.getValue(date) != null - && !basin.getValue(date).isNaN() - && basin.getValue(date) != 0.0) { - if (newbasin.getValue(date) != null - && !newbasin.getValue(date).isNaN() - && newbasin.getValue(date) != 0.0) { - - val = (float) ((basin.getValue(date) + newbasin - .getValue(date)) / 2); - } - - } else { - val = newbasin.getValue(date); - - if (val.isNaN()) { - val = 0.0f; - } - } - - basin.setValue(date, val); - } - } - } - } - } + basin.setValue(date, val); + } + } + } + } + } public void setSourceName(String sourceName) { this.sourceName = sourceName; @@ -322,8 +312,8 @@ public class FFMPDataContainer { } } } catch (Exception e) { - statusHandler.debug("No old times available..."+getSourceName()); - return null; + statusHandler.debug("No old times available..." + getSourceName()); + return null; } return null; } @@ -345,13 +335,14 @@ public class FFMPDataContainer { orderedTimes.add(time); } } - + Collections.reverse(orderedTimes); - + return orderedTimes; } } catch (Exception e) { - statusHandler.debug("No ordered times available..."+getSourceName()); + statusHandler.debug("No ordered times available..." + + getSourceName()); return null; } @@ -375,7 +366,7 @@ public class FFMPDataContainer { } } } catch (Exception e) { - statusHandler.debug("No new times available..."+getSourceName()); + statusHandler.debug("No new times available..." + getSourceName()); return null; } @@ -458,9 +449,9 @@ public class FFMPDataContainer { public double getMaxValue(ArrayList pfafs, Date backDate, Date currDate, long expirationTime, boolean rate) { - double val = getBasinData("ALL").getAccumMaxValue(pfafs, currDate, backDate, - expirationTime, rate); - + double val = getBasinData("ALL").getAccumMaxValue(pfafs, currDate, + backDate, expirationTime, rate); + return val; } @@ -473,12 +464,12 @@ public class FFMPDataContainer { } } - public void setFilePath(String filePath) { - this.filePath = filePath; - } + public void setFilePath(String filePath) { + this.filePath = filePath; + } - public String getFilePath() { - return filePath; - } + public String getFilePath() { + return filePath; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/MANIFEST.MF index 9f09b06c07..64f1c7ccb0 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/META-INF/MANIFEST.MF @@ -35,6 +35,7 @@ Export-Package: com.raytheon.uf.common.dataplugin.gfe, com.raytheon.uf.common.dataplugin.gfe.server.request, com.raytheon.uf.common.dataplugin.gfe.slice, com.raytheon.uf.common.dataplugin.gfe.textproduct, + com.raytheon.uf.common.dataplugin.gfe.time, com.raytheon.uf.common.dataplugin.gfe.util, com.raytheon.uf.common.dataplugin.gfe.weather, com.raytheon.uf.common.dataplugin.gfe.weatherelement diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.java deleted file mode 100644 index e03fb4c321..0000000000 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.uf.common.dataplugin.gfe.request; - -import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; - -/** - * TODO Add Description - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jan 19, 2011            dgilling     Initial creation
- * 
- * 
- * - * @author dgilling - * @version 1.0 - */ - -@DynamicSerialize -public class GetActiveSitesRequest extends AbstractGfeRequest { - -} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.java new file mode 100644 index 0000000000..b87aa14c02 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.java @@ -0,0 +1,90 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin.gfe.request; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * Request that allows a defined selection time range to be retrieved by name. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 1, 2012             dgilling    Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ +@DynamicSerialize +public class GetSelectTimeRangeRequest extends AbstractGfeRequest { + + @DynamicSerializeElement + private String name; + + public GetSelectTimeRangeRequest() { + super(); + this.name = null; + } + + public GetSelectTimeRangeRequest(String name) { + super(); + this.name = name; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("GetSelectTimeRangeRequest [name="); + builder.append(name); + builder.append(", workstationID="); + if (workstationID == null) { + builder.append("null"); + } else { + builder.append(workstationID.toPrettyString()); + } + builder.append(", siteID="); + if (siteID == null) { + builder.append("null"); + } else { + builder.append(siteID); + } + builder.append("]"); + return builder.toString(); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/time/SelectTimeRange.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/time/SelectTimeRange.java similarity index 95% rename from cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/time/SelectTimeRange.java rename to edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/time/SelectTimeRange.java index b6017859a8..32d11e5605 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/time/SelectTimeRange.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/time/SelectTimeRange.java @@ -18,7 +18,7 @@ * further licensing information. **/ -package com.raytheon.viz.gfe.core.time; +package com.raytheon.uf.common.dataplugin.gfe.time; import java.util.Calendar; import java.util.Date; @@ -36,7 +36,8 @@ import com.raytheon.uf.common.time.TimeRange; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jun 24, 2008 mnash Initial creation + * Jun 24, 2008 mnash Initial creation + * Aug 01, 2012 #965 dgilling Moved to dataplugin.gfe project. * * * @@ -117,6 +118,7 @@ public class SelectTimeRange implements Comparable { /** * @see java.lang.Comparable#compareTo(java.lang.Object) */ + @Override public int compareTo(SelectTimeRange other) { if (start != other.start) { return start - other.start; diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/subgrid/SubGridDef.java b/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/subgrid/SubGridDef.java index 60e07f2744..989fd6bf9e 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/subgrid/SubGridDef.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.grib/src/com/raytheon/uf/common/dataplugin/grib/subgrid/SubGridDef.java @@ -27,6 +27,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlList; import javax.xml.bind.annotation.XmlRootElement; +import com.raytheon.uf.common.geospatial.MapUtil; import com.raytheon.uf.common.serialization.ISerializableObject; /** @@ -38,7 +39,7 @@ import com.raytheon.uf.common.serialization.ISerializableObject; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 25, 2010 rjpeter Initial creation - * + * Jul 25, 2012 977 rjpeter Add optional centerLatitude/centerLongitude * * * @author rjpeter @@ -51,37 +52,39 @@ public class SubGridDef implements ISerializableObject { @XmlElement(required = true) @XmlList private List modelNames; - + @XmlElement(required = true) private String referenceModel; + @XmlElement(required = true) + private double nx; + + @XmlElement(required = true) + private double ny; + + // annotation on setter to enforce data constraints + private Double centerLatitude; + + // annotation on setter to enforce data constraints + private Double centerLongitude; + /** the lower left latitude */ - @XmlElement private double lowerLeftLat; /** the lower left longitude */ - @XmlElement private double lowerLeftLon; /** the upper right latitude */ - @XmlElement private double upperRightLat; /** the upper right longitude */ - @XmlElement private double upperRightLon; - - @XmlElement(required = true) - private double nx; - - @XmlElement(required = true) - private double ny; public List getModelNames() { return modelNames; } - public void setModelNames(List modelNames) { + public void setModelNames(final List modelNames) { this.modelNames = modelNames; } @@ -89,7 +92,7 @@ public class SubGridDef implements ISerializableObject { return lowerLeftLat; } - public void setLowerLeftLat(double lowerLeftLat) { + public void setLowerLeftLat(final double lowerLeftLat) { this.lowerLeftLat = lowerLeftLat; } @@ -97,7 +100,7 @@ public class SubGridDef implements ISerializableObject { return lowerLeftLon; } - public void setLowerLeftLon(double lowerLeftLon) { + public void setLowerLeftLon(final double lowerLeftLon) { this.lowerLeftLon = lowerLeftLon; } @@ -105,7 +108,7 @@ public class SubGridDef implements ISerializableObject { return upperRightLat; } - public void setUpperRightLat(double upperRightLat) { + public void setUpperRightLat(final double upperRightLat) { this.upperRightLat = upperRightLat; } @@ -113,7 +116,7 @@ public class SubGridDef implements ISerializableObject { return upperRightLon; } - public void setUpperRightLon(double upperRightLon) { + public void setUpperRightLon(final double upperRightLon) { this.upperRightLon = upperRightLon; } @@ -121,7 +124,7 @@ public class SubGridDef implements ISerializableObject { return nx; } - public void setNx(double nx) { + public void setNx(final double nx) { this.nx = nx; } @@ -129,7 +132,7 @@ public class SubGridDef implements ISerializableObject { return ny; } - public void setNy(double ny) { + public void setNy(final double ny) { this.ny = ny; } @@ -137,9 +140,33 @@ public class SubGridDef implements ISerializableObject { return referenceModel; } - public void setReferenceModel(String referenceModel) { + public void setReferenceModel(final String referenceModel) { this.referenceModel = referenceModel; } - - -} \ No newline at end of file + + public Double getCenterLatitude() { + return centerLatitude; + } + + @XmlElement + public void setCenterLatitude(final Double centerLatitude) { + this.centerLatitude = centerLatitude; + if (this.centerLatitude != null) { + this.centerLatitude = new Double(MapUtil.correctLat(centerLatitude + .doubleValue())); + } + } + + public Double getCenterLongitude() { + return centerLongitude; + } + + @XmlElement + public void setCenterLongitude(final Double centerLongitude) { + this.centerLongitude = centerLongitude; + if (this.centerLongitude != null) { + this.centerLongitude = new Double( + MapUtil.correctLon(centerLongitude.doubleValue())); + } + } +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.pirep/src/com/raytheon/uf/common/dataplugin/pirep/PirepRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.pirep/src/com/raytheon/uf/common/dataplugin/pirep/PirepRecord.java index 250453f3f0..6a0d595114 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.pirep/src/com/raytheon/uf/common/dataplugin/pirep/PirepRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.pirep/src/com/raytheon/uf/common/dataplugin/pirep/PirepRecord.java @@ -70,6 +70,12 @@ import com.vividsolutions.jts.geom.Geometry; * 20090408 952 jsanchez Updated getValue and getStrings methods. * Added getMessageData method. * 20090521 2338 jsanchez Changed the unit of the alititude. + * ====================================== + * AWIPS2 DR Work + * 08/09/2012 1011 jkorman Added separate max icing level as well + * as separated code to generate distinct max icing/turbulence levels. Removed + * code that used "display" boolean to determine data access. + * * * * @author jkorman @@ -138,7 +144,10 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, } @Transient - private PirepLayerData maxPirepLayerData = null; + private PirepLayerData maxTurbcLayerData = null; + + @Transient + private PirepLayerData maxIcingLayerData = null; @Transient private boolean display = true; @@ -591,32 +600,31 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, */ @Override public Amount getValue(String paramName) { + findMaxIcingLayer(); + findMaxTurbcLayer(); Amount a = null; String pName = PARM_MAP.get(paramName); - if (display) { - if (SFC_TEMP.equals(pName) && (temp != null)) { - a = new Amount(temp, TEMPERATURE_UNIT); - } else if (SFC_WNDSPD.equals(pName) && (windSpeed != null)) { - a = new Amount(windSpeed, WIND_SPEED_UNIT); - } else if (SFC_WNDDIR.equals(pName) && (windDirection != null)) { - a = new Amount(windDirection, WIND_DIR_UNIT); - } else if (STA_LAT.equals(pName)) { - a = new Amount(this.getLatitude(), LOCATION_UNIT); - } else if (STA_LON.equals(pName)) { - a = new Amount(this.getLongitude(), LOCATION_UNIT); - } else if (UA_FLTLVL.equals(pName) && getFlightLevel() != null) { - a = new Amount(this.getFlightLevel().intValue(), ALTITUDE_UNIT); - } else if (UA_TOPHGT.equals(pName) && maxPirepLayerData != null - && maxPirepLayerData.getTopLayerHeight() != null) { - a = new Amount( - maxPirepLayerData.getTopLayerHeight().intValue(), - ALTITUDE_UNIT); - } else if (UA_BOTHGT.equals(pName) && maxPirepLayerData != null - && maxPirepLayerData.getBaseLayerHeight() != null) { - a = new Amount(maxPirepLayerData.getBaseLayerHeight() - .intValue(), ALTITUDE_UNIT); - } + if (SFC_TEMP.equals(pName) && (temp != null)) { + a = new Amount(temp, TEMPERATURE_UNIT); + } else if (SFC_WNDSPD.equals(pName) && (windSpeed != null)) { + a = new Amount(windSpeed, WIND_SPEED_UNIT); + } else if (SFC_WNDDIR.equals(pName) && (windDirection != null)) { + a = new Amount(windDirection, WIND_DIR_UNIT); + } else if (STA_LAT.equals(pName)) { + a = new Amount(this.getLatitude(), LOCATION_UNIT); + } else if (STA_LON.equals(pName)) { + a = new Amount(this.getLongitude(), LOCATION_UNIT); + } else if (UA_FLTLVL.equals(pName) && getFlightLevel() != null) { + a = new Amount(this.getFlightLevel().intValue(), ALTITUDE_UNIT); + } else if (UA_TOPHGT.equals(pName) && maxTurbcLayerData != null + && maxTurbcLayerData.getTopLayerHeight() != null) { + a = new Amount(maxTurbcLayerData.getTopLayerHeight().intValue(), + ALTITUDE_UNIT); + } else if (UA_BOTHGT.equals(pName) && maxTurbcLayerData != null + && maxTurbcLayerData.getBaseLayerHeight() != null) { + a = new Amount(maxTurbcLayerData.getBaseLayerHeight().intValue(), + ALTITUDE_UNIT); } return a; } @@ -636,81 +644,85 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, @Override public String[] getStrings(String paramName) { - if ("ICI".matches(paramName)) { - int rank = -1; - String iceIntensity = null; - for (PirepLayerData layer : this.ancPirepData) { - String intensity = ""; - if (layer.getLayerType().equals(PirepLayerData.LAYER_TYP_ICING)) { - if (layer.getFirstValue() != null) { - intensity = layer.getFirstValue(); - } - if (layer.getSecondValue() != null) { - intensity += layer.getSecondValue(); - } + findMaxIcingLayer(); + findMaxTurbcLayer(); - if (ICING_MAP.get(intensity).intValue() > rank) { - rank = ICING_MAP.get(intensity).intValue(); - iceIntensity = intensity; - maxPirepLayerData = layer; - } + String[] retData = null; + if ("ICI".matches(paramName)) { + if (maxIcingLayerData != null) { + String intensity = getIntensity(maxIcingLayerData); + if (intensity != null) { + retData = new String[] { intensity }; } } - if (iceIntensity != null) { - String[] maxIntensity = { iceIntensity }; - return maxIntensity; - } else { - display = false; - } - } else if ("ICT".matches(paramName) && maxPirepLayerData != null) { - if (maxPirepLayerData == null) { - findMaxTurbcLayer(); - } - if (maxPirepLayerData != null) { - String type = maxPirepLayerData.getDataType(); + } else if ("ICT".matches(paramName) && maxIcingLayerData != null) { + if (maxIcingLayerData != null) { + String type = maxIcingLayerData.getDataType(); if (type != null) { - return new String[] { type, }; + retData = new String[] { type, }; } } } else if ("TBI".matches(paramName)) { - if (maxPirepLayerData == null) { - findMaxTurbcLayer(); - } - if (maxPirepLayerData != null) { - String intensity = getIntensity(maxPirepLayerData); + if (maxTurbcLayerData != null) { + String intensity = getIntensity(maxTurbcLayerData); if (intensity != null) { - return new String[] { intensity, }; + retData = new String[] { intensity }; } } } else if ("TBF".matches(paramName)) { - if (maxPirepLayerData == null) { - findMaxTurbcLayer(); - } - if (maxPirepLayerData != null) { - String freq = maxPirepLayerData.getFrequency(); + findMaxTurbcLayer(); + if (maxTurbcLayerData != null) { + String freq = maxTurbcLayerData.getFrequency(); if (freq != null) { - return new String[] { freq, }; + retData = new String[] { freq, }; } } } - return null; + return retData; + } + + private void findMaxIcingLayer() { + if (maxIcingLayerData == null) { + int rank = -1; + for (PirepLayerData layer : this.ancPirepData) { + if (layer.getLayerType().equals(PirepLayerData.LAYER_TYP_ICING)) { + String intensity = getIntensity(layer); + Integer n = ICING_MAP.get(intensity); + if ((n != null) && (n > rank)) { + rank = n; + maxIcingLayerData = layer; + } + } + } + if (maxIcingLayerData != null) { + display = (getIntensity(maxIcingLayerData) != null); + } else { + display = false; + } + } } /** * Find a turbulence layer with the greatest ordinal intensity. */ private void findMaxTurbcLayer() { - int rank = -1; - for (PirepLayerData layer : this.ancPirepData) { - if (PirepLayerData.LAYER_TYP_TURBC.equals(layer.getLayerType())) { - String intensity = getIntensity(layer); - if (TURB_MAP.containsKey(intensity)) { - if (TURB_MAP.get(intensity).intValue() > rank) { - rank = TURB_MAP.get(intensity).intValue(); - maxPirepLayerData = layer; + if (maxTurbcLayerData == null) { + int rank = -1; + for (PirepLayerData layer : this.ancPirepData) { + if (PirepLayerData.LAYER_TYP_TURBC.equals(layer.getLayerType())) { + String intensity = getIntensity(layer); + Integer n = TURB_MAP.get(intensity); + if ((n != null) && (n > rank)) { + rank = n; + maxTurbcLayerData = layer; } } } + if (maxTurbcLayerData != null) { + display = (getIntensity(maxTurbcLayerData) != null); + } else { + display = false; + } } } @@ -788,36 +800,4 @@ public class PirepRecord extends PluginDataObject implements ISpatialEnabled, return false; return true; } - - public static final void main(String[] args) { - - PirepRecord rec = new PirepRecord(); - - PirepLayerData layer = new PirepLayerData(rec); - layer.setLayerType(PirepLayerData.LAYER_TYP_TURBC); - layer.setFrequency("OCN"); - layer.setFirstValue("LGT"); - layer.setSecondValue("MOD"); - layer.setBaseLayerHeight(15000); - layer.setTopLayerHeight(20000); - rec.addLayer(layer); - - layer = new PirepLayerData(rec); - layer.setLayerType(PirepLayerData.LAYER_TYP_TURBC); - layer.setFrequency("CON"); - layer.setFirstValue("MOD"); - layer.setSecondValue("SEV"); - layer.setBaseLayerHeight(20000); - layer.setTopLayerHeight(22000); - rec.addLayer(layer); - - String[] data = rec.getStrings("TBF"); - if ((data != null) && (data.length > 0)) { - System.out.println(data[0]); - } - data = rec.getStrings("TBI"); - if ((data != null) && (data.length > 0)) { - System.out.println(data[0]); - } - } } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/util/PythonFileGenerator.java b/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/util/PythonFileGenerator.java index 01808f374a..5b62498371 100644 --- a/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/util/PythonFileGenerator.java +++ b/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/util/PythonFileGenerator.java @@ -45,6 +45,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 14, 2010 njensen Initial creation + * Jul 31, 2012 #965 dgilling Fix path to file header. * * * @@ -319,7 +320,8 @@ public class PythonFileGenerator { } public static String getHeaderInfo() throws IOException { - File file = new File("../build.cave/tools/headup/AWIPS/awipsHeader.txt"); + File file = new File( + "../../cave/build/tools/headup/AWIPS/awipsHeader.txt"); if (!file.exists()) { System.out .println("Unable to determine header information, skipping header"); diff --git a/edexOsgi/com.raytheon.uf.common.site/src/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.java b/edexOsgi/com.raytheon.uf.common.site/src/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.java index ba45fcb234..ab56dbd594 100644 --- a/edexOsgi/com.raytheon.uf.common.site/src/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.java +++ b/edexOsgi/com.raytheon.uf.common.site/src/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.java @@ -20,7 +20,6 @@ package com.raytheon.uf.common.site.requests; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; -import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.comm.IServerRequest; /** @@ -32,7 +31,8 @@ import com.raytheon.uf.common.serialization.comm.IServerRequest; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Aug 5, 2011 randerso Initial creation + * Aug 05, 2011 randerso Initial creation + * Jul 31, 2012 #965 dgilling Remove unnecessary code. * * * @@ -42,25 +42,5 @@ import com.raytheon.uf.common.serialization.comm.IServerRequest; @DynamicSerialize public class GetActiveSitesRequest implements IServerRequest { - @DynamicSerializeElement - private String[] activeSites; - - public GetActiveSitesRequest() { - } - - /** - * @return the activeSites - */ - public String[] getActiveSites() { - return activeSites; - } - - /** - * @param activeSites - * the activeSites to set - */ - public void setActiveSites(String[] activeSites) { - this.activeSites = activeSites; - } - + // No fields needed } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml index 278c919249..7e563040f4 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/res/spring/ffmp-ingest.xml @@ -8,13 +8,20 @@ - - + + + + + + + + @@ -35,9 +42,4 @@ - - - - \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java index 53fabfb6bd..19f24a5ee3 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/FFMPGenerator.java @@ -103,6 +103,7 @@ import com.raytheon.uf.edex.plugin.ffmp.common.FFTIProcessor; * ------------ ---------- ----------- -------------------------- * 06/21/2009 2521 dhladky Initial Creation. * 02/03/2011 6500 cjeanbap Fixed NullPointerException. + * 07/31/2011 578 dhladky FFTI modifications * * * @author dhladky @@ -110,1491 +111,1805 @@ import com.raytheon.uf.edex.plugin.ffmp.common.FFTIProcessor; */ public class FFMPGenerator extends CompositeProductGenerator implements - MonitorConfigListener { - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(FFMPGenerator.class); + MonitorConfigListener { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(FFMPGenerator.class); - /** - * Public constructor for FFMPGenerator - * - * @param name - * @param compositeProductType - */ - public FFMPGenerator(Executor executor) { + /** + * Public constructor for FFMPGenerator + * + * @param name + * @param compositeProductType + */ + public FFMPGenerator(Executor executor, Executor processexecutor) { - super(genName, productType, executor); - } + super(genName, productType, executor); + this.processexecutor = processexecutor; + } - /** writer thread executor **/ - public Executor writerExecutor = null; + private static final String genName = "FFMP"; - private static final String genName = "FFMP"; + private static final String templateTaskName = "FFMP Template"; - private static final String templateTaskName = "FFMP Template"; + private static final String productType = "ffmp"; - private static final String productType = "ffmp"; + /** ArrayList of domains to filter for */ + private ArrayList domains = null; - /** ArrayList of domains to filter for */ - private ArrayList domains = null; + /** template loader bool **/ + public boolean loaded = false; - /** template loader bool **/ - public boolean loaded = false; + /** check ffg first time you run **/ + public boolean ffgCheck = false; - /** check ffg first time you run **/ - public boolean ffgCheck = false; - - /** ffti finished processing **/ - public boolean fftiDone = true; - - /** products **/ - private ConcurrentHashMap products = null; - - /** Processes map **/ - private ConcurrentHashMap processes = null; - - /** array list of sources to evaluate **/ - public ArrayList fftiSources = new ArrayList(); - - /** run configuration manager **/ - public FFMPRunConfigurationManager frcm = null; - - /** source configuration manager **/ - public FFMPSourceConfigurationManager fscm = null; - - /** temp cache **/ - public ConcurrentHashMap ffmpData = new ConcurrentHashMap(); - - /** FFTI accum/ratio/diff cache **/ - public ConcurrentHashMap fftiData = new ConcurrentHashMap(); - - /** checks for initial load **/ - public ArrayList loadedData = new ArrayList(); - - /** template config manager **/ - public FFMPTemplateConfigurationManager tempConfig = null; - - /** FFMPConfig object **/ - public FFMPConfig config = null; - - /** template **/ - public FFMPTemplates template = null; - - private IPathManager pathManager; - - public static String sharePath = AppsDefaults.getInstance().getToken( - "apps_dir") - + File.separator + "ffmp" + File.separator; - - /** source bins used for finding basin to data correlations **/ - private HashMap sourceBins = new HashMap(); - - @Override - protected void configureFilters() { - - this.pathManager = PathManagerFactory.getPathManager(); - - statusHandler.handle(Priority.DEBUG, getGeneratorName() - + " process Filter Config..."); - domains = new ArrayList(); - boolean configValid = getRunConfig().isPopulated(); - - if (configValid) { - for (FFMPRunXML run : getRunConfig().getFFMPRunners()) { - domains = run.getDomains(); - } - } else { - - /** - * Don't have one, so create an EDEX generated default - */ - LocalizationContext commonStaticSite = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - - List sites = RadarsInUseUtil.getSite(null, - RadarsInUseUtil.LOCAL_CONSTANT); - - FFMPRunXML runner = new FFMPRunXML(); - ArrayList products = new ArrayList(); - // these two are always there in default setups - ProductRunXML hpeProduct = new ProductRunXML(); - hpeProduct.setProductName("DHRMOSAIC"); - hpeProduct.setProductKey("hpe"); - products.add(hpeProduct); - - ProductRunXML biasHpeProduct = new ProductRunXML(); - biasHpeProduct.setProductName("BDHRMOSAIC"); - biasHpeProduct.setProductKey("bhpe"); - products.add(biasHpeProduct); - - ArrayList rfc = new ArrayList(); - - if (sites.isEmpty()) { - RadarStationDao dao = new RadarStationDao(); - List stations = null; - try { - stations = dao.queryByWfo(PropertiesFactory.getInstance() - .getEnvProperties().getEnvValue("SITENAME")); - } catch (DataAccessLayerException e) { - statusHandler - .handle(Priority.ERROR, - "Unable to access data object for radar station table"); - } - - for (RadarStation station : stations) { - // this is just for a default - ProductRunXML dhrProduct = new ProductRunXML(); - dhrProduct.setProductName("DHR"); - dhrProduct.setProductKey(station.getRdaId().toLowerCase()); - products.add(dhrProduct); - - String newRfc = FFMPUtils - .getRFC(dhrProduct.getProductKey()); - if (!rfc.contains(newRfc)) { - rfc.add(newRfc); - } - - sites.add(station.getRdaId().toLowerCase()); - } - - } else { - for (String site : sites) { - // this is just for a default - ProductRunXML dhrProduct = new ProductRunXML(); - dhrProduct.setProductName("DHR"); - dhrProduct.setProductKey(site); - products.add(dhrProduct); - - String newRfc = FFMPUtils - .getRFC(dhrProduct.getProductKey()); - if (!rfc.contains(newRfc)) { - rfc.add(newRfc); - } - } - } - - runner.setProducts(products); - - // Apply site list to all QPE types - for (String source : getSourceConfig().getQPESources()) { - SourceXML qpeSource = getSourceConfig().getSource(source); - // Radar Derived sources use the primary source site keys for - // mosiac datakey - // Auto Config for any Radar derived sources - if (qpeSource.getDataType().equals( - DATA_TYPE.RADAR.getDataType())) { - SourceIngestConfigXML sicm = new SourceIngestConfigXML(); - sicm.setSourceName(qpeSource.getSourceName()); - sicm.setUriSubLocation(3); - - for (String siteid : sites) { - sicm.addDataKey(siteid); - } - - runner.addSourceIngest(sicm); - } - } - - // We have a list of available RFC's, now find mosaic - // Apply this to all RFCFFG sources - for (String source : getSourceConfig().getGuidances()) { - SourceXML guidSource = getSourceConfig().getSource(source); - - // Auto config for RFC sources - if (guidSource.isRfc()) { - // add a source mosaic config to the Run Config - SourceIngestConfigXML sicm = new SourceIngestConfigXML(); - sicm.setSourceName(guidSource.getSourceName()); - sicm.setUriSubLocation(3); - - for (String dataKey : rfc) { - sicm.addDataKey(dataKey); - } - - runner.addSourceIngest(sicm); - } - } - - // Apply site list to all SCANQPF default - for (String source : getSourceConfig().getQPFSources()) { - SourceXML qpfSource = getSourceConfig().getSource(source); - // Radar Derived sources use the primary source site keys for - // mosiac datakey - // Auto Config for any Radar derived sources (QPFSCAN) for - // example - if (qpfSource.getSourceName().equals("QPFSCAN")) { - SourceIngestConfigXML sicm = new SourceIngestConfigXML(); - sicm.setSourceName(qpfSource.getSourceName()); - sicm.setUriSubLocation(3); - - for (String siteid : sites) { - sicm.addDataKey(siteid); - } - - runner.addSourceIngest(sicm); - } - } - - DomainXML domain = new DomainXML(); - domain.setPrimary(true); - domain.setCwa(commonStaticSite.getContextName()); - runner.addDomain(domain); - - getRunConfig().addFFMPRunner(runner); - getRunConfig().saveConfigXml(); - getRunConfig().setPopulated(true); - - domains.add(domain); - } - - // kick off template generation - this.getExecutor().execute(new TemplateLoader(domains)); - } - - @Override - protected void createFilters() { - // do more here if you wish - - ArrayList runners = getRunConfig().getFFMPRunners(); - ArrayList tmp = new ArrayList( - runners.size()); - - for (FFMPRunXML runner : runners) { - DomainXML domain = runner.getPrimaryDomain(); - try { - tmp.add(new FFMPURIFilter(getSiteString(runner) + ":" - + getRFCString(runner) + ":" + domain.getCwa())); - - statusHandler.handle(Priority.INFO, "Created FFMP Filter.." - + " primary Domain: " + domain.getCwa()); - } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, - "Couldn't create FFMP Filter.." + " primary Domain: " - + domain.getCwa() - + " this RUNNER is not a viable FFMP config."); - e.printStackTrace(); - } - } - - filters = tmp.toArray(new URIFilter[tmp.size()]); - - } - - /** - * Slight difference in the way ffmp operates as opposed to the URIFilter in - * general. - */ - @Override - public void matchURIs(DataURINotificationMessage messages) { - - if (messages instanceof DataURINotificationMessage) { - URIFilter[] filters = getFilters(); - if (filters != null) { - for (int i = 0; i < filters.length; i++) { - if (filters[i] != null) { - FFMPURIFilter filter = (FFMPURIFilter) filters[i]; - - if (loaded) { - - synchronized (filter) { - - if (filter.isMatched(messages)) { - - if (!ffgCheck) { - - filter = getFFG(filter); - filter.setValidTime(filter - .getCurrentTime()); - ffgCheck = true; - } - - dispatch(filter); - } - } - } else { - statusHandler - .debug(getGeneratorName() - + ": templates not loaded yet. Skipping product"); - } - } - } - } - } - } - - @Override - public void generateProduct(URIGenerateMessage genMessage) { - if (loaded) { - try { - long time = System.currentTimeMillis(); - this.config = new FFMPConfig( - (FFMPURIGenerateMessage) genMessage, this); - products = new ConcurrentHashMap(); - processes = new ConcurrentHashMap(); - // read config updates, make sure we don't miss something - getRunConfig().readConfigXml(); - getSourceConfig().readConfigXml(); - - if (config.getSources() != null) { - for (String source : config.getSources().keySet()) { - processes.put(source, - getSourceConfig().getSource(source)); - } - } - - // start threads - - for (String source : processes.keySet()) { - this.getExecutor().execute( - new ProcessProduct(processes.get(source), this)); - } - - // count down latch - while (processes.size() > 0) { - // wait for all threads to finish before returning - try { - Thread.sleep(100); - statusHandler.handle(Priority.DEBUG, - "Checking status ..." + processes.size()); - for (String source : processes.keySet()) { - statusHandler.handle(Priority.DEBUG, - "Still processing ..." + source); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - if (products.size() > 0) { - - // Do the FFTI evaluation, if we have FFTI sources - if (fftiSources.size() > 0) { - this.getExecutor().execute(new FFTI(this)); - } - - ArrayList records = new ArrayList( - products.size()); - for (String source : products.keySet()) { - for (FFMPRecord rec : products.get(source)) { - records.add(rec); - } - } - - FFMPRecord[] recs = new FFMPRecord[records.size()]; - for (int i = 0; i < records.size(); i++) { - recs[i] = records.get(i); - } - - this.setPluginDataObjects(recs); - this.setPluginDao(new FFMPDao(getCompositeProductType(), - template, fscm, config.getCWA())); - - while (fftiSources.size() > 0) { - try { - Thread.sleep(100); - statusHandler.handle(Priority.DEBUG, - "Checking status ..." + fftiDone); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - statusHandler.handle( - Priority.INFO, - config.getCWA() + " finished, duration: " - + (System.currentTimeMillis() - time) - + " ms, wrote " + records.size() + " "); - - } else { - statusHandler.handle(Priority.INFO, config.getCWA() - + " no new products to produce."); - } - // dump data we don't need anymore - ffmpData.clear(); - - } catch (Throwable e) { - statusHandler.handle(Priority.ERROR, - "Unable to process FFMP Records."); - e.printStackTrace(); - } - } - } - - /** - * Get the list of domains - * - * @return - */ - public ArrayList getDomains() { - return domains; - } - - /** - * Add a filtering CWA - * - * @param domain - */ - public void addDomain(DomainXML domain) { - domains.add(domain); - } - - @Override - public boolean isRunning() { - return getConfigManager().getFFMPState(); - } - - /** - * Set list of CWA's - * - * @param cwas - */ - public void setDomains(ArrayList domains) { - this.domains = domains; - } - - /** - * Inner class to thread the ffmp processing - * - * @author dhladky - * - */ - private class ProcessProduct implements Runnable { - - SourceXML ffmpProduct; - - FFMPGenerator generator; - - @Override - public void run() { - try { - logger.debug("ProcessProduct: Starting thread " - + ffmpProduct.getSourceName()); - process(); - logger.debug("ProcessProduct: Finishing thread " - + ffmpProduct.getSourceName()); - } catch (Exception e) { - processes.remove(ffmpProduct.getSourceName()); - logger.error("ProcessProduct: removed " - + ffmpProduct.getSourceName()); - e.printStackTrace(); - } - } - - public ProcessProduct(SourceXML ffmpProduct, FFMPGenerator generator) { - this.ffmpProduct = ffmpProduct; - this.generator = generator; - } - - /** - * The actual work gets done here - */ - public void process() throws Exception { - - HashMap dataHash = config.getSourceData(ffmpProduct - .getSourceName()); - ArrayList ffmpRecords = new ArrayList( - dataHash.size()); - - FFMPRunXML runner = getRunConfig().getRunner(config.getCWA()); - - // process all of the dataKeys for this source - for (String dataKey : dataHash.keySet()) { - - ArrayList sites = new ArrayList(); - - // is it a mosaic? - if (ffmpProduct.isMosaic()) { - - // Take care of defaults, all in this case - for (ProductRunXML product : runner.getProducts()) { - // no duplicate keys! - if (!sites.contains(product.getProductKey())) { - sites.add(product.getProductKey()); - } - } - - // do filtering - for (ProductRunXML product : runner.getProducts()) { - // includes - if (product.hasIncludes()) { - for (String includeSourceName : product - .getIncludes()) { - if (ffmpProduct.getSourceName().equals( - includeSourceName)) { - // no duplicate keys! - if (!sites - .contains(product.getProductKey())) { - sites.add(product.getProductKey()); - } - } - } - } - // excludes - if (product.hasExcludes()) { - for (String excludeSourceName : product - .getExcludes()) { - if (ffmpProduct.getSourceName().equals( - excludeSourceName)) { - sites.remove(product.getProductKey()); - } - } - } - } - } else { - // No mosaic, just individual site run - String siteKey = dataKey; - - // special case for XMRG's - if (ffmpProduct.getDataType().equals( - FFMPSourceConfigurationManager.DATA_TYPE.XMRG - .getDataType())) { - - siteKey = null; - String primarySource = null; - - for (ProductXML product : getSourceConfig() - .getProducts()) { - if (product.containsSource(ffmpProduct - .getSourceName())) { - primarySource = product.getPrimarySource(); - break; - } - } - - for (ProductRunXML productRun : runner.getProducts()) { - if (productRun.getProductName().equals( - primarySource)) { - siteKey = productRun.getProductKey(); - break; - } - } - } - - sites.add(siteKey); - } - - for (String productKey : sites) { - - FFMPRecord ffmpRec = new FFMPRecord(); - ffmpRec.setSourceName(ffmpProduct.getSourceName()); - ffmpRec.setDataKey(dataKey); - ffmpRec.setSiteKey(productKey); - ffmpRec.setPluginName(getCompositeProductType()); - ffmpRec.setWfo(config.getCWA()); - FFMPProcessor ffmp = new FFMPProcessor(config, generator, - ffmpRec, template); - ffmpRec = ffmp.processFFMP(ffmpProduct); - ffmpRec.constructDataURI(); - - if (ffmpRec != null) { - - // Don't write loader buddy's on long duration - // sources. Not necessary 6*60 = 360 - if (getSourceConfig() - .getSource(ffmpRec.getSourceName()) - .getExpirationMinutes(productKey) < 360) { - - processDataContainer(ffmpRec); - } - - if (ffmp.isFFTI()) { - fftiDone = false; - if (!fftiSources.contains(ffmp.getFFTISource())) { - FFTIProcessor ffti = new FFTIProcessor( - generator, ffmpRec, - ffmp.getFFTISource()); - fftiSources.add(ffmp.getFFTISource()); - ffti.processFFTI(); - } - } - - ffmpRecords.add(ffmpRec); - } - } - } - - FFMPRecord[] recs = new FFMPRecord[ffmpRecords.size()]; - for (int i = 0; i < ffmpRecords.size(); i++) { - recs[i] = ffmpRecords.get(i); - } - products.put(ffmpProduct.getSourceName(), recs); - processes.remove(ffmpProduct.getSourceName()); - } - } - - /** - * Inner class to background template creation - * - * @author dhladky - * - */ - private class TemplateLoader implements Runnable { - - ArrayList templateDomains; - - DomainXML primaryDomain; - - @Override - public void run() { - statusHandler.handle(Priority.DEBUG, getGeneratorName() - + " Start loader "); - - for (DomainXML domain : templateDomains) { - if (domain.isPrimary()) { - primaryDomain = domain; - } - } - - // generate templates and unify geometries - loaded = load(); - statusHandler.handle(Priority.DEBUG, getGeneratorName() - + " Finishing loader "); - } - - public TemplateLoader(ArrayList templateDomains) { - this.templateDomains = templateDomains; - } - - /** - * - * @param domain - * @return - */ - public void createUnifiedGeometries(DomainXML domain) { - ArrayList hucsToGen = new ArrayList(); - hucsToGen.add("ALL"); - hucsToGen.add("COUNTY"); - - for (int i = template.getTotalHucLevels() - 1; i >= 0; i--) { - hucsToGen.add("HUC" + i); - } - - for (String huc : hucsToGen) { - template.verifyUnifiedGeometries(huc, domain.getCwa()); - } - } - - public boolean load() { - // load / create primary domain - ClusterTask task = null; - String lockDetails = getGeneratorName() + ":" - + primaryDomain.getCwa() + ":" + primaryDomain.getCwa(); - try { - do { - task = ClusterLockUtils.lock(templateTaskName, lockDetails, - 600 * 1000, true); - } while (task.getLockState() != LockState.SUCCESSFUL); - - template = FFMPTemplates.getInstance(primaryDomain, MODE.EDEX); - // setup the config - getTemplateConfig(); - createUnifiedGeometries(primaryDomain); - } finally { - if ((task != null) - && (task.getLockState() == LockState.SUCCESSFUL)) { - ClusterLockUtils.unlock(task, false); - } - } - - // load the secondary domains - List domainsToGen = new ArrayList( - templateDomains); - while (domainsToGen.size() > 0) { - Iterator iter = domainsToGen.iterator(); - boolean processedDomain = false; - while (iter.hasNext()) { - DomainXML domain = iter.next(); - lockDetails = getGeneratorName() + ":" - + primaryDomain.getCwa() + ":" + domain.getCwa(); - try { - task = ClusterLockUtils.lock(templateTaskName, - lockDetails, 300 * 1000, false); - - if (task.getLockState() == LockState.SUCCESSFUL) { - template.addDomain(domain); - createUnifiedGeometries(domain); - iter.remove(); - processedDomain = true; - } - } finally { - if ((task != null) - && (task.getLockState() == LockState.SUCCESSFUL)) { - ClusterLockUtils.unlock(task, false); - } - } - } - - if (!processedDomain) { - // Didn't process a domain, locked by another cluster - // member, sleep and try again - try { - Thread.sleep(100); - } catch (InterruptedException e) { - - } - } - } - - return template.done; - } - } - - /** - * Gets the string buffer for the RFC's - * - * @param run - * @return - */ - private String getRFCString(FFMPRunXML run) { - StringBuffer buf = new StringBuffer(); - - for (SourceIngestConfigXML ingest : run.getSourceIngests()) { - SourceXML source = FFMPSourceConfigurationManager.getInstance() - .getSource(ingest.getSourceName()); - if (source.isRfc()) { - int i = 0; - for (String dataKey : ingest.getDataKey()) { - if (i < ingest.getDataKey().size() - 1) { - buf.append(dataKey + ","); - } else { - buf.append(dataKey); - } - i++; - } - break; - } - } - return buf.toString(); - } - - /** - * Gets the string buffer for the sites, specific to RADAR type data - * - * @param run - * @return - */ - private String getSiteString(FFMPRunXML run) { - String sites = null; - StringBuffer buf = new StringBuffer(); - for (ProductRunXML product : run.getProducts()) { - SourceXML source = getSourceConfig().getSource( - product.getProductName()); - if (source.getDataType().equals(DATA_TYPE.RADAR.getDataType())) { - buf.append(product.getProductKey() + ","); - } - } - sites = buf.toString(); - if (sites.endsWith(",")) { - sites = sites.substring(0, sites.length() - 1); - } - return sites; - } - - /** - * Write your new SourceBins - * - * @param sourceList - */ - public void writeSourceBins(SourceBinList sourceList) { - - try { - LocalizationContext lc = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - - LocalizationFile lflist = pathManager.getLocalizationFile(lc, - getAbsoluteFileName(sourceList.getSourceId())); - - FileUtil.bytes2File( - SerializationUtil.transformToThrift(sourceList), - lflist.getFile(), true); - - lflist.save(); - - statusHandler.handle(Priority.INFO, "Wrote FFMP source Bin File: " - + sourceList.getSourceId()); - - } catch (SerializationException se) { - se.printStackTrace(); - } catch (FileNotFoundException fnfe) { - fnfe.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } catch (LocalizationOpFailedException e) { - e.printStackTrace(); - } - } - - /** - * Read out your SourceBins - * - * @param sourceId - * @return - */ - public SourceBinList readSourceBins(String sourceId) { - - SourceBinList sbl = null; - LocalizationContext lc = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - LocalizationFile f = pathManager.getLocalizationFile(lc, - getAbsoluteFileName(sourceId)); - - try { - sbl = (SourceBinList) SerializationUtil - .transformFromThrift(FileUtil.file2bytes(f.getFile(), true)); - } catch (FileNotFoundException fnfe) { - statusHandler.handle(Priority.ERROR, - "Unable to locate file " + f.getName()); - } catch (SerializationException se) { - statusHandler.handle(Priority.ERROR, - "Unable to read file " + f.getName()); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - - return sbl; - } - - /** - * Gets the completed filename - * - * @return - */ - public String getAbsoluteFileName(String sourceId) { - return "ffmp" + File.separator + "sources" + File.separator + sourceId - + ".bin"; - } - - /** - * See if you have one - * - * @param sourceId - * @return - */ - public boolean isExistingSourceBin(String sourceId) { - LocalizationContext lc = pathManager.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - LocalizationFile f = pathManager.getLocalizationFile(lc, - getAbsoluteFileName(sourceId)); - return f.exists(); - } - - /** - * Gets the list of bins for that source - * - * @param sourceId - * @return - */ - public SourceBinList getSourceBinList(String sourceId) { - SourceBinList sbl = null; - if (!sourceBins.containsKey(sourceId)) { - sbl = readSourceBins(sourceId); - sourceBins.put(sourceId, sbl); - } else { - sbl = sourceBins.get(sourceId); - } - - return sbl; - } - - /** - * Sets the source bins, first time - * - * @param sbl - */ - public void setSourceBinList(SourceBinList sbl) { - sourceBins.put(sbl.getSourceId(), sbl); - writeSourceBins(sbl); - } - - /** - * Do pull strategy on FFG data - * - * @param filter - * @return - */ - private FFMPURIFilter getFFG(FFMPURIFilter filter) { - - ArrayList uris = new ArrayList(); - - for (String rfc : filter.getRFC()) { - // get a hash of the sources and their grib ids - HashMap sources = FFMPUtils.getFFGModelInfo(rfc); - if (sources != null) { - if (sources.size() > 0) { - for (String source : sources.keySet()) { - - SourceXML sourceXml = getSourceConfig().getSource( - source); - - if (sourceXml != null) { - - String plugin = getSourceConfig().getSource(source) - .getPlugin(); - uris.add(FFMPUtils.getFFGDataURI( - sources.get(source), plugin)); - } - } - } - } - } - // treat it like a regular uri in the filter. - if (uris.size() > 0) { - for (String dataUri : uris) { - // add your pattern checks to the key - for (Pattern pattern : filter.getMatchURIs().keySet()) { - statusHandler.handle(Priority.DEBUG, - "Pattern: " + pattern.toString() + " Key: " - + dataUri); - try { - if (pattern.matcher(dataUri).find()) { - // matches one of them, which one? - String matchKey = filter.getPatternName(pattern); - // put the sourceName:dataPath key into the sources - // array list - filter.getSources().put(matchKey, dataUri); - } - } catch (Exception e) { - statusHandler.handle( - Priority.ERROR, - "Unable to locate new FFG file. " - + pattern.toString()); - } - } - } - } - - return filter; - } - - /** - * get the FFMP data container for this source - * - * @param sourceName - * - * @return - */ - - public FFMPDataContainer getFFMPDataContainer(String siteSourceKey, ArrayList hucs, Date backDate) { - - FFMPDataContainer container = ffmpData.get(siteSourceKey); - - if (container == null) { - - String siteKey = null; - - String[] parts = siteSourceKey.split("-"); - - if (parts.length > 1) { - siteKey = parts[0]; - } - - container = loadFFMPDataContainer(siteSourceKey, - - hucs, siteKey, - - config.getCWA(), backDate); - - if (container != null) { - ffmpData.put(siteSourceKey, container); - } - } - - return container; - } - - /* - * Gets the FFTI sources to be run - */ - public ArrayList getFFTISources() { - return fftiSources; - } - - /** - * source config manager - * - * @return - */ - public FFMPSourceConfigurationManager getSourceConfig() { - if (fscm == null) { - fscm = FFMPSourceConfigurationManager.getInstance(); - fscm.addListener(this); - } - return fscm; - } - - /** - * run config manager - * - * @return - */ - public FFMPRunConfigurationManager getRunConfig() { - if (frcm == null) { - frcm = FFMPRunConfigurationManager.getInstance(); - frcm.addListener(this); - } - return frcm; - } - - /** - * Template config manager - * - * @return - */ - public FFMPTemplateConfigurationManager getTemplateConfig() { - if (tempConfig == null) { - tempConfig = FFMPTemplateConfigurationManager.getInstance(); - tempConfig.addListener(this); - } - return tempConfig; - } - - /** - * dispatch a filter for processing - * - * @param filter - */ - private void dispatch(FFMPURIFilter filter) { - - try { - EDEXUtil.getMessageProducer().sendAsync( - routeId, - SerializationUtil.transformToThrift(filter - .createGenerateMessage())); - } catch (Exception e) { - statusHandler.handle(Priority.ERROR, getGeneratorName() - + ": filter: " + filter.getName() - + ": failed to route filter to generator", e); - e.printStackTrace(); - } - - filter.setValidTime(new Date(System.currentTimeMillis())); - filter.reset(); - } - - /** - * FFMP buddy loader - * - * @param ffmpRec - * @param siteKey - */ - private void processDataContainer(FFMPRecord ffmpRec) { - - // write out the fast loader buddy file - SourceXML source = getSourceConfig().getSource(ffmpRec.getSourceName()); - String sourceName = null; - String dataKey = null; - - if (source.getSourceType().equals(SOURCE_TYPE.GUIDANCE.getSourceType())) { - sourceName = source.getDisplayName(); - dataKey = SOURCE_TYPE.GUIDANCE.getSourceType(); - } else { - sourceName = ffmpRec.getSourceName(); - dataKey = ffmpRec.getDataKey(); - } - - String sourceSiteDataKey = sourceName + "-" + ffmpRec.getSiteKey() - + "-" + dataKey; - - // Make a 6 hour "Buddy" loader file - Date backDate = new Date(ffmpRec.getDataTime().getRefTime().getTime() - - (3600 * 1000 * 6)); - - ArrayList hucs = template.getTemplateMgr().getHucLevels(); - - if (source.getSourceType().equals(SOURCE_TYPE.GAGE.getSourceType())) { - hucs.clear(); - hucs.add("ALL"); - } else { - hucs.remove("VIRTUAL"); - } - - // pull from disk if there - FFMPDataContainer fdc = loadFFMPDataContainer(sourceSiteDataKey, - hucs, ffmpRec.getSiteKey(), - ffmpRec.getWfo(), backDate); - - // brand new or initial load up - if (fdc == null || !loadedData.contains(sourceSiteDataKey)) { - - long time = System.currentTimeMillis(); - fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); - fdc = FFTIProcessor.populateDataContainer(fdc, template, hucs, backDate, ffmpRec.getDataTime() - .getRefTime(), ffmpRec.getWfo(), source, ffmpRec.getSiteKey()); - loadedData.add(sourceSiteDataKey); - long time2 = System.currentTimeMillis(); - statusHandler.handle(Priority.INFO, - "Populated new source: in " + (time2 - time) - + " ms: source: " + sourceSiteDataKey); - - } else { - // guidance sources are treated as a mosaic and are handled differently - // This is the main line sequence a source will take when updated. - if (!source.getSourceType().equals( - SOURCE_TYPE.GUIDANCE.getSourceType())) { - - long time = System.currentTimeMillis(); - Date newDate = fdc.getNewest(); - Date oldDate = fdc.getOldest(); - - if (newDate != null && oldDate != null) { - if ((ffmpRec.getDataTime().getRefTime().getTime() - newDate - .getTime()) >= (source.getExpirationMinutes(ffmpRec - .getSiteKey()) * 60 * 1000)) { - // force a re-query back to the newest time in - // existing source container, this will fill in gaps if - // they exist. - fdc = FFTIProcessor.populateDataContainer(fdc, - template, null, newDate, ffmpRec.getDataTime() - .getRefTime(), ffmpRec.getWfo(), - source, ffmpRec.getSiteKey()); - - } else if (oldDate.after(new Date( - backDate.getTime() - - (source.getExpirationMinutes(ffmpRec - .getSiteKey()) * 60 * 1000)))) { - // force a re-query back to barrierTime for - // existing source container, this happens if the - // ingest was turned off for some period of time. - fdc = FFTIProcessor.populateDataContainer(fdc, - template, null, backDate, oldDate, - ffmpRec.getWfo(), source, ffmpRec.getSiteKey()); - } - } - long time2 = System.currentTimeMillis(); - statusHandler.handle(Priority.INFO, - "Checked Source files: in " + (time2 - time) - + " ms: source: " + sourceSiteDataKey); - - // purge it up - fdc.purge(backDate); - } - } - - // add current record data - for (String huc : ffmpRec.getBasinsMap().keySet()) { - fdc.addFFMPEntry(ffmpRec.getDataTime().getRefTime(), source, - ffmpRec.getBasinData(huc), huc, ffmpRec.getSiteKey()); - } - - // set the name - fdc.setFilePath("" + sharePath + ffmpRec.getWfo() + "/"+ sourceSiteDataKey); - // cache it temporarily for FFTI use - ffmpData.put(sourceSiteDataKey, fdc); - // write it out - writeLoaderBuddyFiles(fdc); - } - - /** - * load existing container - * - * @param sourceSiteDataKey - * @param hucs - * @param siteKey - * @param wfo - * @return - */ - public FFMPDataContainer loadFFMPDataContainer(String sourceSiteDataKey, - ArrayList hucs, String siteKey, String wfo, Date backDate) { - - long time = System.currentTimeMillis(); - FFMPDataContainer fdc = null; - - for (String huc : hucs) { - - FFMPBasinData basinData = null; - - if (checkBuddyFile(sourceSiteDataKey, huc, wfo, backDate)) { - basinData = readLoaderBuddyFile(sourceSiteDataKey, huc, wfo, - backDate); - - if (fdc == null) { - fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); - } - } - - if (basinData != null) { - fdc.setBasinBuddyData(basinData, huc); - } - } - - if (fdc != null) { - long time2 = System.currentTimeMillis(); - statusHandler.handle(Priority.DEBUG, "Loaded Source files: in " - + (time2 - time) + " ms: source: " + sourceSiteDataKey); - } - - return fdc; - } - - /** - * Load existing buddy file - * - * @param sourceSiteDataKey - * @param huc - * @param wfo - * @return - */ - private FFMPBasinData readLoaderBuddyFile(String sourceSiteDataKey, - String huc, String wfo, Date backDate) { - - File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" - + huc + ".bin"); - FFMPBasinData basinData = null; - - try { - BufferedInputStream is = new BufferedInputStream( - new FileInputStream(file)); - DynamicSerializationManager dsm = DynamicSerializationManager - .getManager(SerializationType.Thrift); - basinData = (FFMPBasinData) dsm.deserialize(is); - is.close(); - } catch (SerializationException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return basinData; - - } - - /** - * Write buddy file - * - * @param sourceSiteDataKey - * @param huc - * @param wfo - * @return - */ - public void writeLoaderBuddyFiles(FFMPDataContainer fdc) { - - // Write all huc levels in separate files - File fileDir = new File("" + sharePath + config.getCWA()); - if (!fileDir.exists()) { - fileDir.mkdir(); - } - - WriteFiles writer = new WriteFiles(fdc); - writer.run(); - } - - /** - * Inner class to thread writing of BuddyFiles - * - * @author dhladky - * - */ - private class WriteFiles implements Runnable { - - private FFMPDataContainer fdc; - - public void run() { - try { - long time = System.currentTimeMillis(); - write(); - long time2 = System.currentTimeMillis(); - statusHandler.handle(Priority.DEBUG, - "Wrote loader files: in " + (time2 - time) - + " ms"); - } catch (Exception e) { - statusHandler.handle(Priority.ERROR, - "WriteFile: removed " + e.getMessage()); - } - } - - public WriteFiles(FFMPDataContainer fdc) { - this.fdc = fdc; - statusHandler.handle(Priority.DEBUG, "Created FileWriter"); - } - - /** - * The actual work gets done here - */ - public void write() throws Exception { - - try { - - String fileName = fdc.getFilePath(); - // lock for atomic write and read - HashMap fileNames = new HashMap(); - File lockfile = new File(fileName + ".lock"); - lockfile.createNewFile(); - - try { - - for (String huc : fdc.getKeys()) { - - FFMPBasinData fbd = fdc.getBasinData(huc); - - if (fbd.getBasins().size() > 0) { - - String tmpFilePath = fileName + "-" + huc + ".tmp"; - fileNames.put(tmpFilePath, fileName + "-" + huc - + ".bin"); - BufferedOutputStream os = null; - - try { - File file = new File(tmpFilePath); - os = new BufferedOutputStream( - new FileOutputStream(file)); - DynamicSerializationManager dsm = DynamicSerializationManager - .getManager(SerializationType.Thrift); - dsm.serialize(fbd, os); - } catch (SerializationException e) { - statusHandler.handle(Priority.ERROR, - "Serialization Error Writing buddy file: " - + e.getMessage()); - } catch (IOException e) { - statusHandler.handle( - Priority.ERROR, - "IO Error Writing buddy file: " - + e.getMessage()); - } finally { - if (os != null) { - os.close(); - } - } - } - } - } catch (Exception e) { - statusHandler - .handle(Priority.ERROR, - "Error writing Buddy File group: " - + e.getMessage()); - } finally { - // rename the files to real path - try { - for (String tmpName : fileNames.keySet()) { - File file = new File(tmpName); - file.renameTo(new File(fileNames.get(tmpName))); - } - - lockfile.delete(); - - } catch (Exception e) { - statusHandler.handle( - Priority.ERROR, - "IO Error Renaming buddy file: " - + e.getMessage()); - } - } - - } catch (Exception e) { - statusHandler.handle(Priority.ERROR, - "IO Error writing buddy files: " + e.getMessage()); - } - } - } - - /** - * Load existing buddy file - * - * @param sourceSiteDataKey - * @param huc - * @param wfo - * @return - */ - public boolean checkBuddyFile(String sourceSiteDataKey, String huc, - String wfo, Date backDate) { - - File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" - + huc + ".bin"); - - if (file.exists() && (file.lastModified() > backDate.getTime())) { - // System.out.println("File update and exists..."+sourceSiteDataKey); - return true; - } - - return false; - - } - - @Override - public synchronized void configChanged(MonitorConfigEvent fce) { - - boolean reload = false; - - if (fce.getSource() instanceof FFMPTemplateConfigurationManager) { - statusHandler - .handle(Priority.INFO, - "Re-configuring FFMP & URI filters...Template Config change"); - reload = true; - FFMPTemplateConfigurationManager ftcm = (FFMPTemplateConfigurationManager) fce - .getSource(); - if (ftcm.isRegenerate()) { - template.dumpTemplates(); - } - - tempConfig = null; - - } else if (fce.getSource() instanceof FFMPRunConfigurationManager) { - statusHandler.handle(Priority.INFO, - "Re-configuring FFMP & URI filters...Run Config change"); - reload = true; - frcm = null; - } - - else if (fce.getSource() instanceof FFMPSourceConfigurationManager) { - statusHandler.handle(Priority.INFO, - "Re-configuring FFMP & URI filters...Source Config change"); - reload = true; - fscm = null; - } - - if (reload) { - - ffgCheck = false; - resetFilters(); - - if (sourceBins != null) { - sourceBins.clear(); - } - - loadedData.clear(); - - DatMenuUtil dmu = new DatMenuUtil(); - dmu.setDatSite(PropertiesFactory.getInstance().getEnvProperties() - .getEnvValue("SITENAME")); - dmu.setOverride(true); - dmu.createMenus(); - } - } - - /** - * FFTI data cache - * @param ffti - */ - public void addFFTIData(String fftiName, FFTIData ffti) { - if (fftiData.containsKey(fftiName)) { - fftiData.replace(fftiName, ffti); - } else { - fftiData.put(fftiName, ffti); - } - } - - /** - * Get FFTI data cache - * @param fftiName - * @return - */ - public FFTIData getFFTIData(String fftiName) { - return fftiData.get(fftiName); - } - - /** - * Check existence - * @param fftiName - * @return - */ - public boolean isFFTI(String fftiName) { - return fftiData.containsKey(fftiName); - } - - /** - * get the whole container - * @return - */ - public ConcurrentHashMap getFFTIDataContainer() { - return fftiData; - } - -} \ No newline at end of file + /** ffti finished processing **/ + public boolean fftiDone = true; + + /** products **/ + private ConcurrentHashMap products = null; + + /** Processes map **/ + private ConcurrentHashMap processes = null; + + /** array list of sources to evaluate **/ + public ArrayList fftiSources = new ArrayList(); + + /** run configuration manager **/ + public FFMPRunConfigurationManager frcm = null; + + /** source configuration manager **/ + public FFMPSourceConfigurationManager fscm = null; + + /** temp cache **/ + public ConcurrentHashMap ffmpData = new ConcurrentHashMap(); + + /** FFTI accum/ratio/diff cache **/ + public ConcurrentHashMap fftiData = new ConcurrentHashMap(); + + /** checks for initial load **/ + public ArrayList loadedData = new ArrayList(); + + /** thread the productkeys **/ + public HashMap> productKeys = new HashMap>(); + + /** template config manager **/ + public FFMPTemplateConfigurationManager tempConfig = null; + + /** FFMPConfig object **/ + public FFMPConfig config = null; + + /** template **/ + public FFMPTemplates template = null; + + private IPathManager pathManager; + + public static String sharePath = AppsDefaults.getInstance().getToken( + "apps_dir") + + File.separator + "ffmp" + File.separator; + + /** source bins used for finding basin to data correlations **/ + private HashMap sourceBins = new HashMap(); + + /** thread executor **/ + public Executor processexecutor = null; + + @Override + protected void configureFilters() { + + this.pathManager = PathManagerFactory.getPathManager(); + + statusHandler.handle(Priority.DEBUG, getGeneratorName() + + " process Filter Config..."); + domains = new ArrayList(); + boolean configValid = getRunConfig().isPopulated(); + + if (configValid) { + for (FFMPRunXML run : getRunConfig().getFFMPRunners()) { + domains = run.getDomains(); + } + } else { + + /** + * Don't have one, so create an EDEX generated default + */ + LocalizationContext commonStaticSite = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + + List sites = RadarsInUseUtil.getSite(null, + RadarsInUseUtil.LOCAL_CONSTANT); + + FFMPRunXML runner = new FFMPRunXML(); + ArrayList products = new ArrayList(); + // these two are always there in default setups + ProductRunXML hpeProduct = new ProductRunXML(); + hpeProduct.setProductName("DHRMOSAIC"); + hpeProduct.setProductKey("hpe"); + products.add(hpeProduct); + + ProductRunXML biasHpeProduct = new ProductRunXML(); + biasHpeProduct.setProductName("BDHRMOSAIC"); + biasHpeProduct.setProductKey("bhpe"); + products.add(biasHpeProduct); + + ArrayList rfc = new ArrayList(); + + if (sites.isEmpty()) { + RadarStationDao dao = new RadarStationDao(); + List stations = null; + try { + stations = dao.queryByWfo(PropertiesFactory.getInstance() + .getEnvProperties().getEnvValue("SITENAME")); + } catch (DataAccessLayerException e) { + statusHandler + .handle(Priority.ERROR, + "Unable to access data object for radar station table"); + } + + for (RadarStation station : stations) { + // this is just for a default + ProductRunXML dhrProduct = new ProductRunXML(); + dhrProduct.setProductName("DHR"); + dhrProduct.setProductKey(station.getRdaId().toLowerCase()); + products.add(dhrProduct); + + String newRfc = FFMPUtils + .getRFC(dhrProduct.getProductKey()); + if (!rfc.contains(newRfc)) { + rfc.add(newRfc); + } + + sites.add(station.getRdaId().toLowerCase()); + } + + } else { + for (String site : sites) { + // this is just for a default + ProductRunXML dhrProduct = new ProductRunXML(); + dhrProduct.setProductName("DHR"); + dhrProduct.setProductKey(site); + products.add(dhrProduct); + + String newRfc = FFMPUtils + .getRFC(dhrProduct.getProductKey()); + if (!rfc.contains(newRfc)) { + rfc.add(newRfc); + } + } + } + + runner.setProducts(products); + + // Apply site list to all QPE types + for (String source : getSourceConfig().getQPESources()) { + SourceXML qpeSource = getSourceConfig().getSource(source); + // Radar Derived sources use the primary source site keys for + // mosiac datakey + // Auto Config for any Radar derived sources + if (qpeSource.getDataType().equals( + DATA_TYPE.RADAR.getDataType())) { + SourceIngestConfigXML sicm = new SourceIngestConfigXML(); + sicm.setSourceName(qpeSource.getSourceName()); + sicm.setUriSubLocation(3); + + for (String siteid : sites) { + sicm.addDataKey(siteid); + } + + runner.addSourceIngest(sicm); + } + } + + // We have a list of available RFC's, now find mosaic + // Apply this to all RFCFFG sources + for (String source : getSourceConfig().getGuidances()) { + SourceXML guidSource = getSourceConfig().getSource(source); + + // Auto config for RFC sources + if (guidSource.isRfc()) { + // add a source mosaic config to the Run Config + SourceIngestConfigXML sicm = new SourceIngestConfigXML(); + sicm.setSourceName(guidSource.getSourceName()); + sicm.setUriSubLocation(3); + + for (String dataKey : rfc) { + sicm.addDataKey(dataKey); + } + + runner.addSourceIngest(sicm); + } + } + + // Apply site list to all SCANQPF default + for (String source : getSourceConfig().getQPFSources()) { + SourceXML qpfSource = getSourceConfig().getSource(source); + // Radar Derived sources use the primary source site keys for + // mosiac datakey + // Auto Config for any Radar derived sources (QPFSCAN) for + // example + if (qpfSource.getSourceName().equals("QPFSCAN")) { + SourceIngestConfigXML sicm = new SourceIngestConfigXML(); + sicm.setSourceName(qpfSource.getSourceName()); + sicm.setUriSubLocation(3); + + for (String siteid : sites) { + sicm.addDataKey(siteid); + } + + runner.addSourceIngest(sicm); + } + } + + DomainXML domain = new DomainXML(); + domain.setPrimary(true); + domain.setCwa(commonStaticSite.getContextName()); + runner.addDomain(domain); + + getRunConfig().addFFMPRunner(runner); + getRunConfig().saveConfigXml(); + getRunConfig().setPopulated(true); + + domains.add(domain); + } + + // kick off template generation + this.getExecutor().execute(new TemplateLoader(domains)); + } + + @Override + protected void createFilters() { + // do more here if you wish + + ArrayList runners = getRunConfig().getFFMPRunners(); + ArrayList tmp = new ArrayList( + runners.size()); + + for (FFMPRunXML runner : runners) { + DomainXML domain = runner.getPrimaryDomain(); + try { + tmp.add(new FFMPURIFilter(getSiteString(runner) + ":" + + getRFCString(runner) + ":" + domain.getCwa())); + + statusHandler.handle(Priority.INFO, "Created FFMP Filter.." + + " primary Domain: " + domain.getCwa()); + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Couldn't create FFMP Filter.." + " primary Domain: " + + domain.getCwa() + + " this RUNNER is not a viable FFMP config."); + e.printStackTrace(); + } + } + + filters = tmp.toArray(new URIFilter[tmp.size()]); + + } + + /** + * Slight difference in the way ffmp operates as opposed to the URIFilter in + * general. + */ + @Override + public void matchURIs(DataURINotificationMessage messages) { + + if (messages instanceof DataURINotificationMessage) { + URIFilter[] filters = getFilters(); + if (filters != null) { + for (int i = 0; i < filters.length; i++) { + if (filters[i] != null) { + FFMPURIFilter filter = (FFMPURIFilter) filters[i]; + + if (loaded) { + + synchronized (filter) { + + if (filter.isMatched(messages)) { + + if (!ffgCheck) { + + filter = getFFG(filter); + filter.setValidTime(filter + .getCurrentTime()); + ffgCheck = true; + } + + dispatch(filter); + } + } + } else { + statusHandler + .debug(getGeneratorName() + + ": templates not loaded yet. Skipping product"); + } + } + } + } + } + } + + @Override + public void generateProduct(URIGenerateMessage genMessage) { + if (loaded) { + try { + long time = System.currentTimeMillis(); + this.config = new FFMPConfig( + (FFMPURIGenerateMessage) genMessage, this); + products = new ConcurrentHashMap(); + processes = new ConcurrentHashMap(); + // read config updates, make sure we don't miss something + getRunConfig().readConfigXml(); + getSourceConfig().readConfigXml(); + + if (config.getSources() != null) { + for (String source : config.getSources().keySet()) { + processes.put(source, + getSourceConfig().getSource(source)); + } + } + + // start threads + + for (String source : processes.keySet()) { + this.getExecutor().execute( + new ProcessProduct(processes.get(source), this)); + } + + // count down latch + while (processes.size() > 0) { + // wait for all threads to finish before returning + try { + Thread.sleep(100); + statusHandler.handle(Priority.DEBUG, + "Checking status ..." + processes.size()); + for (String source : processes.keySet()) { + statusHandler.handle(Priority.DEBUG, + "Still processing ..." + source); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + if (products.size() > 0) { + + // Do the FFTI evaluation, if we have FFTI sources + if (fftiSources.size() > 0) { + this.getExecutor().execute(new FFTI(this)); + } + + ArrayList records = new ArrayList( + products.size()); + for (String source : products.keySet()) { + for (FFMPRecord rec : products.get(source)) { + records.add(rec); + } + } + + FFMPRecord[] recs = new FFMPRecord[records.size()]; + for (int i = 0; i < records.size(); i++) { + recs[i] = records.get(i); + } + + this.setPluginDataObjects(recs); + this.setPluginDao(new FFMPDao(getCompositeProductType(), + template, fscm, config.getCWA())); + + while (fftiSources.size() > 0) { + try { + Thread.sleep(100); + statusHandler.handle(Priority.DEBUG, + "Checking status ..." + fftiDone); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + statusHandler.handle( + Priority.INFO, + config.getCWA() + " finished, duration: " + + (System.currentTimeMillis() - time) + + " ms, wrote " + records.size() + " "); + + } else { + statusHandler.handle(Priority.INFO, config.getCWA() + + " no new products to produce."); + } + // dump data we don't need anymore + ffmpData.clear(); + // suggest garbage collection + System.gc(); + + } catch (Throwable e) { + statusHandler.handle(Priority.ERROR, + "Unable to process FFMP Records."); + e.printStackTrace(); + } + } + } + + /** + * Get the list of domains + * + * @return + */ + public ArrayList getDomains() { + return domains; + } + + /** + * Add a filtering CWA + * + * @param domain + */ + public void addDomain(DomainXML domain) { + domains.add(domain); + } + + @Override + public boolean isRunning() { + return getConfigManager().getFFMPState(); + } + + /** + * Set list of CWA's + * + * @param cwas + */ + public void setDomains(ArrayList domains) { + this.domains = domains; + } + + /** + * Inner class to thread the ffmp processing + * + * @author dhladky + * + */ + private class ProcessProduct implements Runnable { + + SourceXML ffmpProduct; + + FFMPGenerator generator; + + @Override + public void run() { + try { + logger.debug("ProcessProduct: Starting thread " + + ffmpProduct.getSourceName()); + process(); + logger.debug("ProcessProduct: Finishing thread " + + ffmpProduct.getSourceName()); + } catch (Exception e) { + processes.remove(ffmpProduct.getSourceName()); + logger.error("ProcessProduct: removed " + + ffmpProduct.getSourceName()); + e.printStackTrace(); + } + } + + public ProcessProduct(SourceXML ffmpProduct, FFMPGenerator generator) { + this.ffmpProduct = ffmpProduct; + this.generator = generator; + } + + /** + * The actual work gets done here + */ + public void process() throws Exception { + + HashMap dataHash = config.getSourceData(ffmpProduct + .getSourceName()); + ArrayList ffmpRecords = new ArrayList( + dataHash.size()); + + FFMPRunXML runner = getRunConfig().getRunner(config.getCWA()); + + // process all of the dataKeys for this source + for (String dataKey : dataHash.keySet()) { + + ArrayList sites = new ArrayList(); + + // is it a mosaic? + if (ffmpProduct.isMosaic()) { + + // Take care of defaults, all in this case + for (ProductRunXML product : runner.getProducts()) { + // no duplicate keys! + if (!sites.contains(product.getProductKey())) { + sites.add(product.getProductKey()); + } + } + + // do filtering + for (ProductRunXML product : runner.getProducts()) { + // includes + if (product.hasIncludes()) { + for (String includeSourceName : product + .getIncludes()) { + if (ffmpProduct.getSourceName().equals( + includeSourceName)) { + // no duplicate keys! + if (!sites + .contains(product.getProductKey())) { + sites.add(product.getProductKey()); + } + } + } + } + // excludes + if (product.hasExcludes()) { + for (String excludeSourceName : product + .getExcludes()) { + if (ffmpProduct.getSourceName().equals( + excludeSourceName)) { + sites.remove(product.getProductKey()); + } + } + } + } + } else { + // No mosaic, just individual site run + String siteKey = dataKey; + + // special case for XMRG's + if (ffmpProduct.getDataType().equals( + FFMPSourceConfigurationManager.DATA_TYPE.XMRG + .getDataType())) { + + siteKey = null; + String primarySource = null; + + for (ProductXML product : getSourceConfig() + .getProducts()) { + if (product.containsSource(ffmpProduct + .getSourceName())) { + primarySource = product.getPrimarySource(); + break; + } + } + + for (ProductRunXML productRun : runner.getProducts()) { + if (productRun.getProductName().equals( + primarySource)) { + siteKey = productRun.getProductKey(); + break; + } + } + } + + sites.add(siteKey); + } + + int i = 0; + if (sites != null) { + // set the latch keys + ArrayList lsites = new ArrayList(); + for (String site: sites) { + lsites.add(site); + } + + productKeys.put(ffmpProduct.getSourceName(), lsites); + } + + for (String productKey : sites) { + + FFMPRecord ffmpRec = new FFMPRecord(); + ffmpRec.setSourceName(ffmpProduct.getSourceName()); + ffmpRec.setDataKey(dataKey); + ffmpRec.setSiteKey(productKey); + ffmpRec.setPluginName(getCompositeProductType()); + ffmpRec.setWfo(config.getCWA()); + FFMPProcessor ffmp = new FFMPProcessor(config, generator, + ffmpRec, template); + ffmpRec = ffmp.processFFMP(ffmpProduct); + ffmpRec.constructDataURI(); + + if (ffmpRec != null) { + + if (ffmp.isFFTI()) { + fftiDone = false; + if (!fftiSources.contains(ffmp.getFFTISource())) { + FFTIProcessor ffti = new FFTIProcessor( + generator, ffmpRec, + ffmp.getFFTISource()); + fftiSources.add(ffmp.getFFTISource()); + //System.out.println("Adding source to FFTISources!!!!!!!!!!!!"+ffmpRec.getSourceName()); + ffti.processFFTI(); + } + } + // this is a threaded process!!!!!!!!!!! + // Added this to speed the processing of mosaiced sources. + // Before all processing was in line to the source thread. + // This caused slowness in the overall processing. + // By allowing the mosaic components to be concurrently + // processed it has drastically sped up overall FFMP performance. + processDataContainer(ffmpRec, productKey); + ffmpRecords.add(ffmpRec); + } + i++; + } + + while (productKeys.size() > 0) { + // wait for all threads to finish before returning + try { + Thread.sleep(50); + statusHandler.handle(Priority.DEBUG, + "Checking status ..." + productKeys.size()); + for (String source : productKeys.keySet()) { + statusHandler.handle(Priority.DEBUG, + "Still processing ..." + source); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + FFMPRecord[] recs = new FFMPRecord[ffmpRecords.size()]; + for (int i = 0; i < ffmpRecords.size(); i++) { + recs[i] = ffmpRecords.get(i); + } + products.put(ffmpProduct.getSourceName(), recs); + processes.remove(ffmpProduct.getSourceName()); + } + } + + /** + * Inner class to background template creation + * + * @author dhladky + * + */ + private class TemplateLoader implements Runnable { + + ArrayList templateDomains; + + DomainXML primaryDomain; + + @Override + public void run() { + statusHandler.handle(Priority.DEBUG, getGeneratorName() + + " Start loader "); + + for (DomainXML domain : templateDomains) { + if (domain.isPrimary()) { + primaryDomain = domain; + } + } + + // generate templates and unify geometries + loaded = load(); + statusHandler.handle(Priority.DEBUG, getGeneratorName() + + " Finishing loader "); + } + + public TemplateLoader(ArrayList templateDomains) { + this.templateDomains = templateDomains; + } + + /** + * + * @param domain + * @return + */ + public void createUnifiedGeometries(DomainXML domain) { + ArrayList hucsToGen = new ArrayList(); + hucsToGen.add("ALL"); + hucsToGen.add("COUNTY"); + + for (int i = template.getTotalHucLevels() - 1; i >= 0; i--) { + hucsToGen.add("HUC" + i); + } + + for (String huc : hucsToGen) { + template.verifyUnifiedGeometries(huc, domain.getCwa()); + } + } + + public boolean load() { + // load / create primary domain + ClusterTask task = null; + String lockDetails = getGeneratorName() + ":" + + primaryDomain.getCwa() + ":" + primaryDomain.getCwa(); + try { + do { + task = ClusterLockUtils.lock(templateTaskName, lockDetails, + 600 * 1000, true); + } while (task.getLockState() != LockState.SUCCESSFUL); + + template = FFMPTemplates.getInstance(primaryDomain, MODE.EDEX); + // setup the config + getTemplateConfig(); + createUnifiedGeometries(primaryDomain); + } finally { + if ((task != null) + && (task.getLockState() == LockState.SUCCESSFUL)) { + ClusterLockUtils.unlock(task, false); + } + } + + // load the secondary domains + List domainsToGen = new ArrayList( + templateDomains); + while (domainsToGen.size() > 0) { + Iterator iter = domainsToGen.iterator(); + boolean processedDomain = false; + while (iter.hasNext()) { + DomainXML domain = iter.next(); + lockDetails = getGeneratorName() + ":" + + primaryDomain.getCwa() + ":" + domain.getCwa(); + try { + task = ClusterLockUtils.lock(templateTaskName, + lockDetails, 300 * 1000, false); + + if (task.getLockState() == LockState.SUCCESSFUL) { + template.addDomain(domain); + createUnifiedGeometries(domain); + iter.remove(); + processedDomain = true; + } + } finally { + if ((task != null) + && (task.getLockState() == LockState.SUCCESSFUL)) { + ClusterLockUtils.unlock(task, false); + } + } + } + + if (!processedDomain) { + // Didn't process a domain, locked by another cluster + // member, sleep and try again + try { + Thread.sleep(100); + } catch (InterruptedException e) { + + } + } + } + + return template.done; + } + } + + /** + * Gets the string buffer for the RFC's + * + * @param run + * @return + */ + private String getRFCString(FFMPRunXML run) { + StringBuffer buf = new StringBuffer(); + + for (SourceIngestConfigXML ingest : run.getSourceIngests()) { + SourceXML source = FFMPSourceConfigurationManager.getInstance() + .getSource(ingest.getSourceName()); + if (source.isRfc()) { + int i = 0; + for (String dataKey : ingest.getDataKey()) { + if (i < ingest.getDataKey().size() - 1) { + buf.append(dataKey + ","); + } else { + buf.append(dataKey); + } + i++; + } + break; + } + } + return buf.toString(); + } + + /** + * Gets the string buffer for the sites, specific to RADAR type data + * + * @param run + * @return + */ + private String getSiteString(FFMPRunXML run) { + String sites = null; + StringBuffer buf = new StringBuffer(); + for (ProductRunXML product : run.getProducts()) { + SourceXML source = getSourceConfig().getSource( + product.getProductName()); + if (source.getDataType().equals(DATA_TYPE.RADAR.getDataType())) { + buf.append(product.getProductKey() + ","); + } + } + sites = buf.toString(); + if (sites.endsWith(",")) { + sites = sites.substring(0, sites.length() - 1); + } + return sites; + } + + /** + * Write your new SourceBins + * + * @param sourceList + */ + public void writeSourceBins(SourceBinList sourceList) { + + try { + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + + LocalizationFile lflist = pathManager.getLocalizationFile(lc, + getAbsoluteSourceFileName(sourceList.getSourceId())); + + FileUtil.bytes2File( + SerializationUtil.transformToThrift(sourceList), + lflist.getFile(), true); + + lflist.save(); + + statusHandler.handle(Priority.INFO, "Wrote FFMP source Bin File: " + + sourceList.getSourceId()); + + } catch (SerializationException se) { + se.printStackTrace(); + } catch (FileNotFoundException fnfe) { + fnfe.printStackTrace(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } catch (LocalizationOpFailedException e) { + e.printStackTrace(); + } + } + + /** + * Read out your SourceBins + * + * @param sourceId + * @return + */ + public SourceBinList readSourceBins(String sourceId) { + + SourceBinList sbl = null; + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile f = pathManager.getLocalizationFile(lc, + getAbsoluteSourceFileName(sourceId)); + + try { + sbl = (SourceBinList) SerializationUtil + .transformFromThrift(FileUtil.file2bytes(f.getFile(), true)); + } catch (FileNotFoundException fnfe) { + statusHandler.handle(Priority.ERROR, + "Unable to locate file " + f.getName()); + } catch (SerializationException se) { + statusHandler.handle(Priority.ERROR, + "Unable to read file " + f.getName()); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + + return sbl; + } + + /** + * Gets the completed filename + * + * @return + */ + public String getAbsoluteSourceFileName(String sourceId) { + return "ffmp" + File.separator + "sources" + File.separator + sourceId + + ".bin"; + } + + /** + * See if you have one + * + * @param sourceId + * @return + */ + public boolean isExistingSourceBin(String sourceId) { + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile f = pathManager.getLocalizationFile(lc, + getAbsoluteSourceFileName(sourceId)); + return f.exists(); + } + + /** + * Gets the list of bins for that source + * + * @param sourceId + * @return + */ + public SourceBinList getSourceBinList(String sourceId) { + SourceBinList sbl = null; + if (!sourceBins.containsKey(sourceId)) { + sbl = readSourceBins(sourceId); + sourceBins.put(sourceId, sbl); + } else { + sbl = sourceBins.get(sourceId); + } + + return sbl; + } + + /** + * Sets the source bins, first time + * + * @param sbl + */ + public void setSourceBinList(SourceBinList sbl) { + sourceBins.put(sbl.getSourceId(), sbl); + writeSourceBins(sbl); + } + + /** + * Do pull strategy on FFG data + * + * @param filter + * @return + */ + private FFMPURIFilter getFFG(FFMPURIFilter filter) { + + ArrayList uris = new ArrayList(); + + for (String rfc : filter.getRFC()) { + // get a hash of the sources and their grib ids + HashMap sources = FFMPUtils.getFFGModelInfo(rfc); + if (sources != null) { + if (sources.size() > 0) { + for (String source : sources.keySet()) { + + SourceXML sourceXml = getSourceConfig().getSource( + source); + + if (sourceXml != null) { + + String plugin = getSourceConfig().getSource(source) + .getPlugin(); + uris.add(FFMPUtils.getFFGDataURI( + sources.get(source), plugin)); + } + } + } + } + } + // treat it like a regular uri in the filter. + if (uris.size() > 0) { + for (String dataUri : uris) { + // add your pattern checks to the key + for (Pattern pattern : filter.getMatchURIs().keySet()) { + statusHandler.handle(Priority.DEBUG, + "Pattern: " + pattern.toString() + " Key: " + + dataUri); + try { + if (pattern.matcher(dataUri).find()) { + // matches one of them, which one? + String matchKey = filter.getPatternName(pattern); + // put the sourceName:dataPath key into the sources + // array list + filter.getSources().put(matchKey, dataUri); + } + } catch (Exception e) { + statusHandler.handle( + Priority.ERROR, + "Unable to locate new FFG file. " + + pattern.toString()); + } + } + } + } + + return filter; + } + + /** + * get the FFMP data container for this source + * + * @param sourceName + * + * @return + */ + + public FFMPDataContainer getFFMPDataContainer(String siteSourceKey, + ArrayList hucs, Date backDate) { + + FFMPDataContainer container = ffmpData.get(siteSourceKey); + + if (container == null) { + + String siteKey = null; + + String[] parts = siteSourceKey.split("-"); + + if (parts.length > 1) { + siteKey = parts[0]; + } + + container = loadFFMPDataContainer(siteSourceKey, + + hucs, siteKey, + + config.getCWA(), backDate); + + if (container != null) { + ffmpData.put(siteSourceKey, container); + } + } + + return container; + } + + /* + * Gets the FFTI sources to be run + */ + public ArrayList getFFTISources() { + return fftiSources; + } + + /** + * source config manager + * + * @return + */ + public FFMPSourceConfigurationManager getSourceConfig() { + if (fscm == null) { + fscm = FFMPSourceConfigurationManager.getInstance(); + fscm.addListener(this); + } + return fscm; + } + + /** + * run config manager + * + * @return + */ + public FFMPRunConfigurationManager getRunConfig() { + if (frcm == null) { + frcm = FFMPRunConfigurationManager.getInstance(); + frcm.addListener(this); + } + return frcm; + } + + /** + * Template config manager + * + * @return + */ + public FFMPTemplateConfigurationManager getTemplateConfig() { + if (tempConfig == null) { + tempConfig = FFMPTemplateConfigurationManager.getInstance(); + tempConfig.addListener(this); + } + return tempConfig; + } + + /** + * dispatch a filter for processing + * + * @param filter + */ + private void dispatch(FFMPURIFilter filter) { + + try { + EDEXUtil.getMessageProducer().sendAsync( + routeId, + SerializationUtil.transformToThrift(filter + .createGenerateMessage())); + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, getGeneratorName() + + ": filter: " + filter.getName() + + ": failed to route filter to generator", e); + e.printStackTrace(); + } + + filter.setValidTime(new Date(System.currentTimeMillis())); + filter.reset(); + } + + /** + * Process this data container + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + */ + public void processDataContainer(FFMPRecord ffmpRec, String productKey) { + + this.getProcessExecutor().execute(new ProcessDataContainer(ffmpRec, productKey)); + } + + /** + * Inner class to thread writing of BuddyFiles + * + * @author dhladky + * + */ + private class ProcessDataContainer implements Runnable { + + private FFMPRecord ffmpRec; + private String productKey; + + public void run() { + try { + processDataContainer(ffmpRec, productKey); + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "ProcessDataContainer: removed " + e.getMessage()); + } + } + + public ProcessDataContainer(FFMPRecord ffmpRec, String productKey) { + this.ffmpRec = ffmpRec; + this.productKey = productKey; + } + + /** + * Process this data container + * + * @param ffmpRec + * @param write + */ + private void processDataContainer(FFMPRecord ffmpRec, String productKey) { + + String sourceName = null; + Date backDate = null; + String sourceSiteDataKey = null; + FFMPDataContainer fdc = null; + boolean write = true; + + try { + // write out the fast loader buddy file + + long ptime = System.currentTimeMillis(); + SourceXML source = getSourceConfig().getSource( + ffmpRec.getSourceName()); + String dataKey = ffmpRec.getDataKey(); + + if (source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + sourceName = source.getDisplayName(); + sourceSiteDataKey = sourceName; + // FFG is so infrequent go back a day + backDate = new Date(config.getDate().getTime() + - (3600 * 1000 * 24)); + } else { + sourceName = ffmpRec.getSourceName(); + sourceSiteDataKey = sourceName + "-" + ffmpRec.getSiteKey() + + "-" + dataKey; + backDate = new Date(ffmpRec.getDataTime().getRefTime() + .getTime() + - (3600 * 1000 * 6)); + } + + // deal with setting of needed HUCS + ArrayList hucs = template.getTemplateMgr() + .getHucLevels(); + + if (source.getSourceType().equals( + SOURCE_TYPE.GAGE.getSourceType()) + || source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + hucs.clear(); + hucs.add("ALL"); + } else { + hucs.remove("VIRTUAL"); + } + + // pull from disk if there + fdc = getFFMPDataContainer(sourceSiteDataKey, hucs, backDate); + + // brand new or initial load up + if (fdc == null || !loadedData.contains(sourceSiteDataKey)) { + + long time = System.currentTimeMillis(); + fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); + fdc = FFTIProcessor.populateDataContainer(fdc, template, + hucs, backDate, ffmpRec.getDataTime().getRefTime(), + ffmpRec.getWfo(), source, ffmpRec.getSiteKey()); + + if (!loadedData.contains(sourceSiteDataKey)) { + loadedData.add(sourceSiteDataKey); + } + + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.DEBUG, + "Populated new source: in " + (time2 - time) + + " ms: source: " + sourceSiteDataKey); + + } else { + + long time = System.currentTimeMillis(); + // guidance sources are treated as a mosaic and are handled + // differently. They are force read at startup. + // This is the main line sequence a source will take when + // updated. + if (!source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + + Date newDate = fdc.getNewest(); + Date oldDate = fdc.getOldest(); + + if (newDate != null && oldDate != null) { + if ((ffmpRec.getDataTime().getRefTime().getTime() - newDate + .getTime()) >= (source + .getExpirationMinutes(ffmpRec.getSiteKey()) * 60 * 1000)) { + // force a re-query back to the newest time in + // existing source container, this will fill in + // gaps + // if + // they exist. + fdc = FFTIProcessor.populateDataContainer(fdc, + template, null, newDate, ffmpRec + .getDataTime().getRefTime(), + ffmpRec.getWfo(), source, ffmpRec + .getSiteKey()); + + } else if (oldDate.after(new Date(backDate + .getTime() + - (source.getExpirationMinutes(ffmpRec + .getSiteKey()) * 60 * 1000)))) { + // force a re-query back to barrierTime for + // existing source container, this happens if + // the + // ingest was turned off for some period of + // time. + fdc = FFTIProcessor.populateDataContainer(fdc, + template, null, backDate, oldDate, + ffmpRec.getWfo(), source, + ffmpRec.getSiteKey()); + } + } + + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.DEBUG, + "Checked Source files: in " + (time2 - time) + + " ms: source: " + sourceSiteDataKey); + } + } + + // add current record data + for (String huc : hucs) { + fdc.addFFMPEntry(ffmpRec.getDataTime().getRefTime(), + source, ffmpRec.getBasinData(huc), huc, + ffmpRec.getSiteKey()); + } + // purge it up + fdc.purge(backDate); + // set the name + fdc.setFilePath("" + sharePath + ffmpRec.getWfo() + "/" + + sourceSiteDataKey); + + // cache it temporarily for FFTI use + if (source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + // only write last one + write = false; + + if (!ffmpData.containsKey(sourceSiteDataKey)) { + ffmpData.put(sourceSiteDataKey, fdc); + } else { + ffmpData.replace(sourceSiteDataKey, fdc); + } + } + + statusHandler.handle( + Priority.INFO, + "Processed FFMPDataContainer: in " + + (System.currentTimeMillis() - ptime) + + " ms: source: " + sourceSiteDataKey); + } catch (Exception e) { + statusHandler.handle(Priority.INFO, + "Failed Processing FFMPDataContainer" + e.getMessage()); + + } finally { + // moved writing here to remain safe from possible race condition between processing threads + if (productKeys != null) { + if (productKeys.containsKey(ffmpRec.getSourceName())) { + productKeys.get(ffmpRec.getSourceName()).remove(productKey); + //System.out.println("Removed productKey: "+productKey); + if (productKeys.get(ffmpRec.getSourceName()).size() == 0) { + //System.out.println("Removed source: "+ffmpRec.getSourceName()+" now writing"); + productKeys.remove(ffmpRec.getSourceName()); + // last one, allow write + write = true; + } + } + } + + if (write) { + // write it out + writeLoaderBuddyFiles(fdc); + } + } + } + } + + /** + * load existing container + * + * @param sourceSiteDataKey + * @param hucs + * @param siteKey + * @param wfo + * @return + */ + public FFMPDataContainer loadFFMPDataContainer(String sourceSiteDataKey, + ArrayList hucs, String siteKey, String wfo, Date backDate) { + + long time = System.currentTimeMillis(); + FFMPDataContainer fdc = null; + + synchronized (hucs) { + for (String huc : hucs) { + + FFMPBasinData basinData = null; + + if (checkBuddyFile(sourceSiteDataKey, huc, wfo, backDate)) { + try { + basinData = readLoaderBuddyFile(sourceSiteDataKey, huc, + wfo, backDate); + } catch (Exception e) { + statusHandler.handle( + Priority.ERROR, + "General Error Reading buddy file: " + + e.getMessage()); + } + + if (fdc == null) { + fdc = new FFMPDataContainer(sourceSiteDataKey, hucs); + } + } + + if (basinData != null) { + fdc.setBasinBuddyData(basinData, huc); + } + } + } + + if (fdc != null) { + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.DEBUG, "Loaded Source files: in " + + (time2 - time) + " ms: source: " + sourceSiteDataKey); + } + + return fdc; + } + + /** + * Load existing buddy file + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + * @throws IOException + */ + private FFMPBasinData readLoaderBuddyFile(String sourceSiteDataKey, + String huc, String wfo, Date backDate) throws IOException { + + File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" + + huc + ".bin"); + FFMPBasinData basinData = null; + BufferedInputStream is = null; + + try { + is = new BufferedInputStream( + new FileInputStream(file)); + DynamicSerializationManager dsm = DynamicSerializationManager + .getManager(SerializationType.Thrift); + basinData = (FFMPBasinData) dsm.deserialize(is); + } catch (SerializationException e) { + statusHandler.handle(Priority.ERROR, + "Serialization Error Reading buddy file: " + + e.getMessage()); + } catch (IOException e) { + statusHandler.handle(Priority.ERROR, + "IO Error Reading buddy file: " + + e.getMessage()); + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "General Error Reading buddy file: " + + e.getMessage()); + } catch (Throwable t) { + statusHandler.handle(Priority.ERROR, + "Bogus Thrift Error Reading buddy file: " + + t.getMessage()); + } finally { + if (is != null) { + is.close(); + } + } + + return basinData; + + } + + /** + * Write buddy file + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + */ + public void writeLoaderBuddyFiles(FFMPDataContainer fdc) { + + // Write all huc levels in separate files + File fileDir = new File("" + sharePath + config.getCWA()); + if (!fileDir.exists()) { + fileDir.mkdir(); + } + + WriteFiles writer = new WriteFiles(fdc); + writer.run(); + } + + /** + * Inner class to thread writing of BuddyFiles + * + * @author dhladky + * + */ + private class WriteFiles implements Runnable { + + private FFMPDataContainer fdc; + + public void run() { + try { + long time = System.currentTimeMillis(); + write(); + long time2 = System.currentTimeMillis(); + statusHandler.handle(Priority.DEBUG, "Wrote loader files: in " + + (time2 - time) + " ms :" + fdc.getFilePath()); + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "WriteFile: removed " + e.getMessage()); + } + } + + public WriteFiles(FFMPDataContainer fdc) { + this.fdc = fdc; + statusHandler.handle(Priority.DEBUG, "Created FileWriter"); + } + + /** + * The actual work gets done here + */ + public void write() throws Exception { + + try { + + String fileName = fdc.getFilePath(); + // lock for atomic write and read + HashMap fileNames = new HashMap(); + File lockfile = new File(fileName + ".lock"); + lockfile.createNewFile(); + + try { + + if (lockfile.canWrite()) { + // write the lock if we can even write to anything + synchronized (fdc.getKeys()) { + for (String huc : fdc.getKeys()) { + + FFMPBasinData fbd = fdc.getBasinData(huc); + + if (fbd.getBasins().size() > 0) { + + String tmpFilePath = fileName + "-" + huc + + ".tmp"; + BufferedOutputStream os = null; + + try { + File file = new File(tmpFilePath); + file.createNewFile(); + + if (file.canWrite()) { + os = new BufferedOutputStream( + new FileOutputStream(file)); + DynamicSerializationManager dsm = DynamicSerializationManager + .getManager(SerializationType.Thrift); + dsm.serialize(fbd, os); + fileNames.put(tmpFilePath, fileName + + "-" + huc + ".bin"); + } else { + statusHandler + .handle(Priority.WARN, + "Can not write buddy file: " + + file.getAbsolutePath()); + } + } catch (SerializationException e) { + statusHandler.handle(Priority.ERROR, + "Serialization Error Writing buddy file: " + + e.getMessage()); + } catch (IOException e) { + statusHandler.handle(Priority.ERROR, + "IO Error Writing buddy file: " + + e.getMessage()); + } finally { + if (os != null) { + os.close(); + } + } + } + } + } + } + } catch (Exception e) { + statusHandler + .handle(Priority.ERROR, + "Error writing Buddy File group: " + + e.getMessage()); + } finally { + // rename the files to real path + try { + for (String tmpName : fileNames.keySet()) { + File file = new File(tmpName); + file.renameTo(new File(fileNames.get(tmpName))); + } + + if (lockfile.exists()) { + lockfile.delete(); + } + + } catch (Exception e) { + statusHandler.handle( + Priority.ERROR, + "IO Error Renaming buddy file: " + + e.getMessage()); + } + } + + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "IO Error writing buddy files: " + e.getMessage()); + } + + } + } + + /** + * Load existing buddy file + * + * @param sourceSiteDataKey + * @param huc + * @param wfo + * @return + */ + public boolean checkBuddyFile(String sourceSiteDataKey, String huc, + String wfo, Date backDate) { + + File file = new File(sharePath + wfo + "/" + sourceSiteDataKey + "-" + + huc + ".bin"); + + String sourceName = sourceSiteDataKey.split("-")[0]; + SourceXML source = getSourceConfig().getSourceByDisplayName(sourceName); + if (source != null) { + + if (source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + if (file.exists() && file.canRead() && file.canWrite()) { + return true; + } + } else { + if (file.exists() && file.canRead() && file.canWrite() + && (file.lastModified() > backDate.getTime())) { + // System.out.println("File update and exists..."+sourceSiteDataKey); + return true; + } + } + } + + return false; + + } + + @Override + public synchronized void configChanged(MonitorConfigEvent fce) { + + boolean reload = false; + + if (fce.getSource() instanceof FFMPTemplateConfigurationManager) { + statusHandler + .handle(Priority.INFO, + "Re-configuring FFMP & URI filters...Template Config change"); + reload = true; + FFMPTemplateConfigurationManager ftcm = (FFMPTemplateConfigurationManager) fce + .getSource(); + if (ftcm.isRegenerate()) { + template.dumpTemplates(); + } + + tempConfig = null; + + } else if (fce.getSource() instanceof FFMPRunConfigurationManager) { + statusHandler.handle(Priority.INFO, + "Re-configuring FFMP & URI filters...Run Config change"); + reload = true; + frcm = null; + } + + else if (fce.getSource() instanceof FFMPSourceConfigurationManager) { + statusHandler.handle(Priority.INFO, + "Re-configuring FFMP & URI filters...Source Config change"); + reload = true; + fscm = null; + } + + if (reload) { + + ffgCheck = false; + resetFilters(); + + if (sourceBins != null) { + sourceBins.clear(); + } + + loadedData.clear(); + + if (ffmpData != null) { + ffmpData.clear(); + } + if (fftiData != null) { + fftiData.clear(); + } + + DatMenuUtil dmu = new DatMenuUtil(); + dmu.setDatSite(PropertiesFactory.getInstance().getEnvProperties() + .getEnvValue("SITENAME")); + dmu.setOverride(true); + dmu.createMenus(); + } + } + + /** + * FFTI data cache + * + * @param ffti + */ + public void writeFFTIData(String fftiName, FFTIData ffti) { + if (fftiData.containsKey(fftiName)) { + fftiData.replace(fftiName, ffti); + } else { + fftiData.put(fftiName, ffti); + } + + writeFFTIFile(ffti, fftiName); + } + + /** + * Get FFTI data cache + * + * @param fftiName + * @return + */ + public FFTIData getFFTIData(String fftiName) { + // preserve the state of the reset value + boolean reset = true; + if (fftiData.containsKey(fftiName)) { + reset = fftiData.get(fftiName).isReset(); + } + + FFTIData ffti = readFFTIData(fftiName); + + if (fftiData != null) { + ffti.setReset(reset); + fftiData.put(fftiName, ffti); + } + return ffti; + } + + /** + * Write your FFTI Data files + * + * @param sourceList + */ + public void writeFFTIFile(FFTIData ffti, String fftiName) { + + try { + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + + LocalizationFile lflist = pathManager.getLocalizationFile(lc, + getAbsoluteFFTIFileName(fftiName)); + + FileUtil.bytes2File(SerializationUtil.transformToThrift(ffti), + lflist.getFile(), true); + + lflist.save(); + + statusHandler.handle(Priority.DEBUG, "Wrote FFMP FFTI file: " + + fftiName); + + } catch (SerializationException se) { + se.printStackTrace(); + } catch (FileNotFoundException fnfe) { + fnfe.printStackTrace(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } catch (LocalizationOpFailedException e) { + e.printStackTrace(); + } + } + + /** + * Read out your FFTI Files + * + * @param sourceId + * @return + */ + public FFTIData readFFTIData(String fftiName) { + + FFTIData ffti = null; + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile f = pathManager.getLocalizationFile(lc, + getAbsoluteFFTIFileName(fftiName)); + + try { + ffti = (FFTIData) SerializationUtil.transformFromThrift(FileUtil + .file2bytes(f.getFile(), true)); + } catch (FileNotFoundException fnfe) { + statusHandler.handle(Priority.ERROR, + "Unable to locate file " + f.getName()); + } catch (SerializationException se) { + statusHandler.handle(Priority.ERROR, + "Unable to read file " + f.getName()); + } catch (IOException ioe) { + statusHandler.handle(Priority.ERROR, + "Unable to read file " + f.getName()); + } + + return ffti; + } + + /** + * Gets the completed filename + * + * @return + */ + public String getAbsoluteFFTIFileName(String fftiName) { + return "ffmp" + File.separator + "ffti" + File.separator + fftiName + + ".bin"; + } + + /** + * See if you have one + * + * @param fftiName + * @return + */ + public boolean isFFTI(String fftiName) { + LocalizationContext lc = pathManager.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + LocalizationFile f = pathManager.getLocalizationFile(lc, + getAbsoluteFFTIFileName(fftiName)); + boolean exists = false; + if (f != null) { + exists = f.exists(); + } + + return exists; + } + + /** + * get the whole container + * + * @return + */ + public ConcurrentHashMap getFFTIDataContainer() { + return fftiData; + } + + /** + * the executor runner + * + * @return + */ + public Executor getProcessExecutor() { + return processexecutor; + } + + public void setProcessExecutor(Executor processexecutor) { + this.processexecutor = processexecutor; + } + +} \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java index e37efdc150..be051647fa 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFMPInterpolatedGuidanceDelay.java @@ -40,6 +40,7 @@ import com.raytheon.uf.edex.plugin.ffmp.FFMPGenerator; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 29 July, 2011 6772 dhladky Initial creation + * 29 July, 2012 578 dhladky memory work * * * @author dhladky @@ -92,14 +93,9 @@ public class FFMPInterpolatedGuidanceDelay { ArrayList hucs = new ArrayList(); hucs.add("ALL"); - // if (qpeSource.isMosaic()) { - // qpeContainer = generator.getFFMPDataContainer(qpeSource - // .getSourceName(), hucs, backDate); - // } else { qpeContainer = generator.getFFMPDataContainer(qpeSource.getSourceName() + "-" + siteKey + "-" + siteKey, hucs, backDate); - // } - + long expirationTime = qpeSource.getExpirationMinutes(siteKey) * 60 * 1000; // determine lag_time long lagTime = (currentRecord.getDataTime().getRefTime().getTime()) diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java index e17a1ad813..022f857a15 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java @@ -55,6 +55,7 @@ import com.raytheon.uf.edex.plugin.ffmp.FFMPGenerator; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 01, 2011 dhladky Initial creation + * July 13, 2012 dhladky Revamped to help memory * * * @@ -226,7 +227,7 @@ public class FFTI implements Runnable { for (String displayName : displayNames) { String[] fftiKeys = displayName.split("-"); - + // monolithic processing for mosaic sources if (fftiKeys.length == 1) { @@ -234,29 +235,29 @@ public class FFTI implements Runnable { displayName); ArrayList sites = getSites(source); ArrayList accums = new ArrayList(); - + // process all pieces of the mosaic - for (int i = 0; i < sites.size(); i++) { + for (int i = 0; i < sites.size(); i++) { - String dataKey = sites.get(i); + String dataKey = sites.get(i); - for (int j = 0; j < sites.size(); j++) { + for (int j = 0; j < sites.size(); j++) { - FFTIAccum faccum = getAccumulationForSite(displayName, - sites.get(j), dataKey, duration, - source.getUnit()); + FFTIAccum faccum = getAccumulationForSite(displayName, + sites.get(j), dataKey, duration, + source.getUnit()); - if (faccum != null) { - accums.add(faccum); - } - } - } + if (faccum != null) { + accums.add(faccum); + } + } + } // find the highest for the entire mosaic accum = new FFTIAccum(); accum.setAccumulation(0.0); - for (FFTIAccum faccum: accums) { + for (FFTIAccum faccum : accums) { if (accum.getAccumulation() <= faccum.getAccumulation()) { accum.setAccumulation(faccum.getAccumulation()); @@ -270,35 +271,35 @@ public class FFTI implements Runnable { accum.setUnit(faccum.getUnit()); } - statusHandler.handle( Priority.INFO, "FFTI mosaic ACCUM: " + source.getSourceName() + " " + accum.getAccumulation() + " gap: " + accum.getGap()); accumList.add(accum); - + } else { - + fftiSiteKey = fftiKeys[0]; fftiSourceKey = fftiKeys[1]; source = ffmpgen.getSourceConfig().getSourceByDisplayName( fftiSourceKey); - accum = getAccumulationForSite(fftiSourceKey, fftiSiteKey, fftiSiteKey, duration, source.getUnit()); - - if (accum != null) { - accum.setUnit(source.getUnit()); - statusHandler.handle( - Priority.INFO, - "FFTI ACCUM: " + source.getSourceName() + " " - + fftiSiteKey + " " - + accum.getAccumulation() + " gap: " - + accum.getGap()); + accum = getAccumulationForSite(fftiSourceKey, fftiSiteKey, + fftiSiteKey, duration, source.getUnit()); - accumList.add(accum); - } + if (accum != null) { + accum.setUnit(source.getUnit()); + statusHandler.handle( + Priority.INFO, + "FFTI ACCUM: " + source.getSourceName() + " " + + fftiSiteKey + " " + + accum.getAccumulation() + " gap: " + + accum.getGap()); + + accumList.add(accum); + } } } @@ -346,19 +347,19 @@ public class FFTI implements Runnable { .equals(FFTIAttributeXML.ATTRIBUTE.RATIO .getAttribute())) { - if (values.getGuids() != null - && values.getQpes() != null) { - tempVal = FFMPUtils.getMaxRatioValue( - values.getQpes(), values.getGuids()); - } - } else if (attribute.getAttributeName().equals( - FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) { + if (values.getGuids() != null + && values.getQpes() != null) { + tempVal = FFMPUtils.getMaxRatioValue( + values.getQpes(), values.getGuids()); + } + } else if (attribute.getAttributeName().equals( + FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) { - if (values.getGuids() != null - && values.getQpes() != null) { - tempVal = FFMPUtils.getMaxDiffValue( - values.getQpes(), values.getGuids()); - } + if (values.getGuids() != null + && values.getQpes() != null) { + tempVal = FFMPUtils.getMaxDiffValue( + values.getQpes(), values.getGuids()); + } } if ((tempVal != Float.NaN) @@ -405,20 +406,20 @@ public class FFTI implements Runnable { if (attribute.getAttributeName().equals( FFTIAttributeXML.ATTRIBUTE.RATIO.getAttribute())) { - if (values.getGuids() != null - && values.getQpes() != null) { - val = FFMPUtils.getMaxRatioValue(values.getQpes(), - values.getGuids()); - } - + if (values.getGuids() != null + && values.getQpes() != null) { + val = FFMPUtils.getMaxRatioValue(values.getQpes(), + values.getGuids()); + } + } else if (attribute.getAttributeName().equals( FFTIAttributeXML.ATTRIBUTE.DIFF.getAttribute())) { - if (values.getGuids() != null - && values.getQpes() != null) { - val = FFMPUtils.getMaxDiffValue(values.getQpes(), - values.getGuids()); - } + if (values.getGuids() != null + && values.getQpes() != null) { + val = FFMPUtils.getMaxDiffValue(values.getQpes(), + values.getGuids()); + } } gap = values.getGap(); @@ -459,74 +460,74 @@ public class FFTI implements Runnable { double red = attribute.getRedThrshld(); for (FFTIAccum accum : accumList) { - if (accum != null && accum.getName() != null) { - value = accum.getAccumulation(); - unit = accum.getUnit(); - displayName = accum.getName(); - gapVal = accum.getGap(); + if (accum != null && accum.getName() != null) { + value = accum.getAccumulation(); + unit = accum.getUnit(); + displayName = accum.getName(); + gapVal = accum.getGap(); - String sourceDisplayName = null; - if (displayName.contains("-")) { - sourceDisplayName = displayName.split("-")[1]; - } else { - sourceDisplayName = displayName; - } + String sourceDisplayName = null; + if (displayName.contains("-")) { + sourceDisplayName = displayName.split("-")[1]; + } else { + sourceDisplayName = displayName; + } - SourceXML source = FFMPSourceConfigurationManager - .getInstance().getSourceByDisplayName( - sourceDisplayName); + SourceXML source = FFMPSourceConfigurationManager + .getInstance().getSourceByDisplayName( + sourceDisplayName); - String sourceType = source.getSourceType(); + String sourceType = source.getSourceType(); - // Set up the alert data object - FFTIAlertData fad = new FFTIAlertData(); + // Set up the alert data object + FFTIAlertData fad = new FFTIAlertData(); - if (sourceType.equalsIgnoreCase(SOURCE_TYPE.QPE - .getSourceType())) { - fad.addSource(SOURCE_TYPE.QPE, displayName); - fad.addDuration(SOURCE_TYPE.QPE, setting.getQpeSource() - .getDurationHour()); - } else if (sourceType.equalsIgnoreCase(SOURCE_TYPE.QPF - .getSourceType())) { - fad.addSource(SOURCE_TYPE.QPF, displayName); - fad.addDuration(SOURCE_TYPE.QPF, setting.getQpfSource() - .getDurationHour()); - } + if (sourceType.equalsIgnoreCase(SOURCE_TYPE.QPE + .getSourceType())) { + fad.addSource(SOURCE_TYPE.QPE, displayName); + fad.addDuration(SOURCE_TYPE.QPE, setting.getQpeSource() + .getDurationHour()); + } else if (sourceType.equalsIgnoreCase(SOURCE_TYPE.QPF + .getSourceType())) { + fad.addSource(SOURCE_TYPE.QPF, displayName); + fad.addDuration(SOURCE_TYPE.QPF, setting.getQpfSource() + .getDurationHour()); + } - fad.setAttributeName(attribute.getAttributeName()); - fad.setDisplayName(displayName); - fad.setUnit(unit); - fad.setValue(formatter.format(value)); - fad.setGap(getGapString(gapVal)); + fad.setAttributeName(attribute.getAttributeName()); + fad.setDisplayName(displayName); + fad.setUnit(unit); + fad.setValue(formatter.format(value)); + fad.setGap(getGapString(gapVal)); - if ((value >= yellow) && (value < red)) { - fad.setPriority(String - .valueOf(UFStatus.Priority.PROBLEM.ordinal())); + if ((value >= yellow) && (value < red)) { + fad.setPriority(String + .valueOf(UFStatus.Priority.PROBLEM.ordinal())); - if (messagePriority.ordinal() > Priority.PROBLEM - .ordinal()) { - messagePriority = UFStatus.Priority.PROBLEM; - } - } else if (value >= red) { - fad.setPriority(String - .valueOf(UFStatus.Priority.SIGNIFICANT - .ordinal())); - if (messagePriority.ordinal() > UFStatus.Priority.SIGNIFICANT - .ordinal()) { - messagePriority = UFStatus.Priority.SIGNIFICANT; - } - } else { - fad.setPriority(String.valueOf(UFStatus.Priority.EVENTA - .ordinal())); - if (messagePriority.ordinal() > UFStatus.Priority.EVENTA - .ordinal()) { - messagePriority = UFStatus.Priority.EVENTA; - } - } + if (messagePriority.ordinal() > Priority.PROBLEM + .ordinal()) { + messagePriority = UFStatus.Priority.PROBLEM; + } + } else if (value >= red) { + fad.setPriority(String + .valueOf(UFStatus.Priority.SIGNIFICANT + .ordinal())); + if (messagePriority.ordinal() > UFStatus.Priority.SIGNIFICANT + .ordinal()) { + messagePriority = UFStatus.Priority.SIGNIFICANT; + } + } else { + fad.setPriority(String.valueOf(UFStatus.Priority.EVENTA + .ordinal())); + if (messagePriority.ordinal() > UFStatus.Priority.EVENTA + .ordinal()) { + messagePriority = UFStatus.Priority.EVENTA; + } + } - alertDataArray.add(fad); - } - } + alertDataArray.add(fad); + } + } } catch (Exception e) { e.printStackTrace(); statusHandler @@ -630,7 +631,16 @@ public class FFTI implements Runnable { fad.setAttributeName(attributeName); fad.setDisplayName(displayName); fad.setUnit(unit); - fad.setValue(formatter.format(value)); + + String displayStr = null; + if (attributeName.equals(FFTIAttributeXML.ATTRIBUTE.RATIO + .getAttribute())) { + displayStr = String.valueOf(Math.round(value)); + } else { + displayStr = String.format("%1.2f", value); + } + + fad.setValue(displayStr); fad.setGap(getGapString(gapVal)); fad.setPriority(new Integer(priority).toString()); fad.addDuration(SOURCE_TYPE.GUIDANCE, guidDuration); @@ -718,9 +728,6 @@ public class FFTI implements Runnable { + sourceLengths[1] + "s %-" + sourceLengths[2] + "s %6s %7s %-3s %-6s"; - // String headerFmt = typeFmt + " " + sourceFmt + " %5s " + unitFmt - // + " %8s %8s %s\n"; - String headerStr = String.format(lineFmt, "Type", "QPE", "QPF", "GUID ", "Value", "Unit", "Pri", "GAP"); @@ -793,82 +800,96 @@ public class FFTI implements Runnable { */ private FFTIAccum getAccumulationForSite(String fftiSourceKey, String fftiSiteKey, String fftiDataKey, double duration, String unit) { - + SourceXML ffmpSource = ffmpgen.getSourceConfig() .getSourceByDisplayName(fftiSourceKey); FFTIAccum accumulator = null; - String siteDataKey = ffmpSource.getDisplayName() + "-" + fftiSiteKey + "-"+ fftiDataKey; - + String siteDataKey = ffmpSource.getDisplayName() + "-" + fftiSiteKey + + "-" + fftiDataKey; + if (ffmpgen.isFFTI(siteDataKey)) { - accumulator = (FFTIAccum) ffmpgen.getFFTIData(siteDataKey); + accumulator = (FFTIAccum) ffmpgen.getFFTIData(siteDataKey); } else { - accumulator = new FFTIAccum(); + accumulator = new FFTIAccum(); } - + // This will only happen at initial load, update, and duration changes. - if (accumulator.isReset() || accumulator.getDuration() != duration) { + if (accumulator.isReset() || accumulator.getDuration() != duration) { - accumulator.setDuration(duration); - accumulator.setUnit(unit); + accumulator.setDuration(duration); + accumulator.setUnit(unit); - if (ffmpSource.isMosaic()) { - accumulator.setName(ffmpSource.getDisplayName()); - } else { - accumulator.setName(fftiSiteKey + "-" + fftiSourceKey); - } - - long cur = config.getDate().getTime(); - long timeBack = (long) (duration * 3600 * 1000); - Date backDate = new Date(cur - timeBack); - long expirationTime = ffmpSource.getExpirationMinutes(fftiSiteKey) * 60 * 1000; + if (ffmpSource.isMosaic()) { + accumulator.setName(ffmpSource.getDisplayName()); + } else { + accumulator.setName(fftiSiteKey + "-" + fftiSourceKey); + } - FFMPDataContainer fdc = null; + long cur = config.getDate().getTime(); + long timeBack = (long) (duration * 3600 * 1000); + Date backDate = new Date(cur - timeBack); + long expirationTime = ffmpSource.getExpirationMinutes(fftiSiteKey) * 60 * 1000; - ArrayList hucs = new ArrayList(); - hucs.add("ALL"); + FFMPDataContainer fdc = null; - fdc = ffmpgen.getFFMPDataContainer(siteDataKey, hucs, backDate); + ArrayList hucs = new ArrayList(); + hucs.add("ALL"); - if (fdc != null) { + fdc = ffmpgen.getFFMPDataContainer(siteDataKey, hucs, backDate); - FFMPBasinData fbd = fdc.getBasinData("ALL"); + if (fdc != null) { - // go over the list of CWAs gathering the pfaf list - ArrayList pfafs = new ArrayList(); - ArrayList cwaList = fdm.getCwaList(); + FFMPBasinData fbd = fdc.getBasinData("ALL"); - Double gap = getGap(fdc, ffmpSource, duration, fftiSiteKey); + // go over the list of CWAs gathering the pfaf list + ArrayList pfafs = new ArrayList(); + ArrayList cwaList = fdm.getCwaList(); - if (gap != Double.NaN) { + Double gap = getGap(fdc, ffmpSource, duration, fftiSiteKey); - for (String cwa : cwaList) { - for (Long key : fbd.getBasins().keySet()) { + if (gap != Double.NaN) { + for (Long key : fbd.getBasins().keySet()) { + for (String cwa : cwaList) { - FFMPBasinMetaData basin = templates.getBasin(key); - if ((basin != null) && (basin.getCwa() != null)) { - if (basin.getCwa().equals(cwa)) { - if (!pfafs.contains(key)) { - pfafs.add(key); - } - } - } - } - } + boolean primary = false; + if (cwa.equals(config.getCWA())) { + primary = true; + } - double amount = fdc.getMaxValue(pfafs, backDate, - config.getDate(), expirationTime, - ffmpSource.isRate()); + FFMPBasinMetaData fmdb = templates.getBasin( + fftiSiteKey, key); - // max value for monitored area - accumulator.setAccumulation(amount); - accumulator.setGap(gap); - } - } - - // replace or insert it - accumulator.reset(false); - ffmpgen.addFFTIData(siteDataKey, accumulator); - } + if (fmdb == null) { + continue; + } + + // Gets buffer zones adjacent to CWA + if ((cwa.equals(fmdb.getCwa())) + || (primary && fmdb.isPrimaryCwa())) { + if (!pfafs.contains(key)) { + pfafs.add(key); + } + } + } + } + + double amount = fdc.getMaxValue(pfafs, backDate, + config.getDate(), expirationTime, + ffmpSource.isRate()); + + // max value for monitored area + accumulator.setAccumulation(amount); + accumulator.setGap(gap); + } + } + + // replace or insert it, memory management + if (ffmpgen.ffmpData.containsKey(siteDataKey)) { + ffmpgen.ffmpData.remove(siteDataKey); + } + accumulator.setReset(false); + ffmpgen.writeFFTIData(siteDataKey, accumulator); + } return accumulator; } @@ -882,119 +903,133 @@ public class FFTI implements Runnable { if (ffmpQSource == null) { ffmpQSource = ffmpgen.fscm.getSource(qSourceKey); } - - String siteDataKey = ffgType + "-" + ffmpQSource.getSourceName() + "-"+ qSiteKey; - + + String siteDataKey = ffgType + "-" + ffmpQSource.getSourceName() + "-" + + qSiteKey; + if (ffmpgen.isFFTI(siteDataKey)) { - values = (FFTIRatioDiff) ffmpgen.getFFTIData(siteDataKey); + values = (FFTIRatioDiff) ffmpgen.getFFTIData(siteDataKey); + if (values.getGuids() == null || values.getQpes() == null) { + values.setReset(true); + } } else { - values = new FFTIRatioDiff(); + values = new FFTIRatioDiff(); } - + // This will only happen at initial load, update, and duration changes. - if (values.isReset() || values.getDuration() != duration) { + if (values.isReset() || values.getDuration() != duration) { - values.setDuration(duration); - values.setUnit(unit); - - long cur = config.getDate().getTime(); - long timeBack = (long) (duration * 3600 * 1000); - Date backDate = new Date(cur - timeBack); - long expirationTime = ffmpQSource.getExpirationMinutes(qSiteKey) * 60 * 1000; + values.setDuration(duration); + values.setUnit(unit); - // make sure we have data - Date ffgBackDate = new Date(config.getDate().getTime() - - (3600 * 1000 * 24)); + long cur = config.getDate().getTime(); + long timeBack = (long) (duration * 3600 * 1000); + Date backDate = new Date(cur - timeBack); + long expirationTime = ffmpQSource.getExpirationMinutes(qSiteKey) * 60 * 1000; - String primarySource = ffmpgen.fscm.getPrimarySource(ffmpQSource); - ProductXML product = ffmpgen.fscm.getProduct(primarySource); - ArrayList hucs = new ArrayList(); - hucs.add("ALL"); + // make sure we have data + Date ffgBackDate = new Date(config.getDate().getTime() + - (3600 * 1000 * 24)); - FFMPDataContainer guidContainer = ffmpgen.getFFMPDataContainer( - ffgType, hucs, ffgBackDate); - long guidSourceExpiration = 0l; + String primarySource = ffmpgen.fscm.getPrimarySource(ffmpQSource); + ProductXML product = ffmpgen.fscm.getProduct(primarySource); + ArrayList hucs = new ArrayList(); + hucs.add("ALL"); - if (guidContainer != null) { + FFMPDataContainer guidContainer = ffmpgen.getFFMPDataContainer( + ffgType, hucs, ffgBackDate); - for (SourceXML iguidSource : product - .getGuidanceSourcesByType(ffgType)) { + long guidSourceExpiration = 0l; - if (guidSourceExpiration == 0l) { - guidSourceExpiration = iguidSource - .getExpirationMinutes(qSiteKey) * 60 * 1000; - } + if (guidContainer == null) { + guidContainer = new FFMPDataContainer(ffgType, hucs); + } - if (!guidContainer.containsKey(iguidSource.getSourceName())) { + for (SourceXML iguidSource : product + .getGuidanceSourcesByType(ffgType)) { - guidContainer = FFTIProcessor.populateDataContainer( - guidContainer, templates, null, ffgBackDate, - config.getDate(), config.getCWA(), iguidSource, - qSiteKey); - } - } + if (guidSourceExpiration == 0l) { + guidSourceExpiration = iguidSource + .getExpirationMinutes(qSiteKey) * 60 * 1000; + break; + } + } - // if still nothing, punt! - if (guidContainer.size() == 0) { + // if still nothing, punt! + if (guidContainer.size() == 0) { - statusHandler.handle(Priority.PROBLEM, - "FFTI: No guidance sources available for " - + qSiteKey + " " + qSourceKey + " " - + " comparison."); - return null; - } + statusHandler.handle(Priority.PROBLEM, + "FFTI: No guidance sources available for " + qSiteKey + + " " + qSourceKey + " " + " comparison."); + return values; + } + + FFMPDataContainer qpeContainer = ffmpgen.getFFMPDataContainer( + ffmpQSource.getSourceName() + "-" + qSiteKey + "-" + + qSiteKey, hucs, backDate); - FFMPDataContainer qpeContainer = ffmpgen.getFFMPDataContainer( - ffmpQSource.getSourceName() + "-" + qSiteKey + "-" - + qSiteKey, hucs, backDate); + if (qpeContainer != null) { + // go over the list of CWAs gathering the pfaf list + ArrayList pfafs = new ArrayList(); + ArrayList cwaList = fdm.getCwaList(); + FFMPBasinData fbd = qpeContainer.getBasinData("ALL"); - if (qpeContainer != null) { - // go over the list of CWAs gathering the pfaf list - ArrayList pfafs = new ArrayList(); - ArrayList cwaList = fdm.getCwaList(); - for (String cwa : cwaList) { - for (Long key : qpeContainer.getBasinData("ALL") - .getBasins().keySet()) { - FFMPBasinMetaData basin = templates.getBasin(key); - if ((basin != null) && (basin.getCwa() != null)) { - if (basin.getCwa().equals(cwa)) { - pfafs.add(key); - } - } - } - } + for (Long key : fbd.getBasins().keySet()) { + for (String cwa : cwaList) { - Double gap = getGap(qpeContainer, ffmpQSource, duration, - qSiteKey); + boolean primary = false; + if (cwa.equals(config.getCWA())) { + primary = true; + } - if (gap != Double.NaN) { + FFMPBasinMetaData fmdb = templates.getBasin(qSiteKey, + key); - ArrayList qpes = qpeContainer - .getBasinData("ALL").getAccumValues(pfafs, - backDate, config.getDate(), - expirationTime, false); + if (fmdb == null) { + continue; + } - FFMPGuidanceInterpolation interpolator = new FFMPGuidanceInterpolation( - ffmpgen.fscm, product, ffmpgen.frcm.getRunner( - config.getCWA()).getProduct(qSiteKey), - primarySource, ffgType, qSiteKey); - interpolator.setInterpolationSources(duration); + // Gets buffer zones adjacent to CWA + if ((cwa.equals(fmdb.getCwa())) + || (primary && fmdb.isPrimaryCwa())) { + if (!pfafs.contains(key)) { + pfafs.add(key); + } + } + } + } - ArrayList guids = guidContainer.getBasinData( - "ALL").getGuidanceValues(pfafs, interpolator, - guidSourceExpiration); - - values.setQpes(qpes); - values.setGuids(guids); - values.setGap(gap); - } - } - } - - // replace or insert it - values.reset(false); - ffmpgen.addFFTIData(siteDataKey, values); - } + Double gap = getGap(qpeContainer, ffmpQSource, duration, + qSiteKey); + + if (gap != Double.NaN) { + + ArrayList qpes = qpeContainer.getBasinData("ALL") + .getAccumValues(pfafs, backDate, config.getDate(), + expirationTime, false); + + FFMPGuidanceInterpolation interpolator = new FFMPGuidanceInterpolation( + ffmpgen.fscm, product, ffmpgen.frcm.getRunner( + config.getCWA()).getProduct(qSiteKey), + primarySource, ffgType, qSiteKey); + interpolator.setInterpolationSources(duration); + + ArrayList guids = guidContainer.getBasinData("ALL") + .getGuidanceValues(pfafs, interpolator, + guidSourceExpiration); + + values.setQpes(qpes); + values.setGuids(guids); + values.setGap(gap); + } + } else { + return values; + } + + // replace or insert it + values.setReset(false); + ffmpgen.writeFFTIData(siteDataKey, values); + } return values; } @@ -1025,7 +1060,7 @@ public class FFTI implements Runnable { for (FFMPGap gap : gaps) { gapVal += gap.getGap(); } - + gapVal = gapVal / 60; } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java index c8b240798a..bd15a91443 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIAccum.java @@ -19,6 +19,14 @@ **/ package com.raytheon.uf.edex.plugin.ffmp.common; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + /** * FFTIAccum * @@ -34,11 +42,15 @@ package com.raytheon.uf.edex.plugin.ffmp.common; * @author dhladky * @version 1.0 */ - +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +@DynamicSerialize public class FFTIAccum extends FFTIData { + @DynamicSerializeElement + @XmlElement private Double accumulation = 0.0; - + public Double getAccumulation() { return accumulation; } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java index b91432139f..8ef8dcb43c 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIData.java @@ -1,5 +1,14 @@ package com.raytheon.uf.edex.plugin.ffmp.common; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.common.serialization.ISerializableObject; +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + /** * This software was developed and / or modified by Raytheon Company, * pursuant to Contract DG133W-05-CQ-1067 with the US Government. @@ -36,19 +45,32 @@ package com.raytheon.uf.edex.plugin.ffmp.common; * @version 1.0 */ -public class FFTIData { - - private Double gap = 0.0; - - private Double duration = 0.0; - - private String name = null; - - private String unit = null; - - private boolean isReset = true; +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +@DynamicSerialize +public class FFTIData implements ISerializableObject { - /** + @DynamicSerializeElement + @XmlElement + private Double gap = 0.0; + + @DynamicSerializeElement + @XmlElement + private Double duration = 0.0; + + @DynamicSerializeElement + @XmlElement + private String name = null; + + @DynamicSerializeElement + @XmlElement + private String unit = null; + + @DynamicSerializeElement + @XmlElement + private boolean reset = true; + + /** * @param name * the name to set */ @@ -62,15 +84,15 @@ public class FFTIData { public String getName() { return name; } - - public Double getGap() { + + public Double getGap() { return gap; } public void setGap(Double gap) { this.gap = gap; } - + public Double getDuration() { return duration; } @@ -78,7 +100,7 @@ public class FFTIData { public void setDuration(Double duration) { this.duration = duration; } - + /** * @param unit * the unit to set @@ -93,21 +115,13 @@ public class FFTIData { public String getUnit() { return unit; } - - /** - * Change status - * @param isReset - */ - public void reset(boolean isReset) { - this.isReset = isReset; - } - - /** - * Check status - * @return - */ + public boolean isReset() { - return isReset; + return reset; + } + + public void setReset(boolean reset) { + this.reset = reset; } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java index 98bac0f5cc..d371da2ad1 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIProcessor.java @@ -35,7 +35,6 @@ import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager; import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager.SOURCE_TYPE; import com.raytheon.uf.common.monitor.xml.FFTISourceXML; -import com.raytheon.uf.common.monitor.xml.ProductXML; import com.raytheon.uf.common.monitor.xml.SourceXML; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -54,7 +53,7 @@ import com.raytheon.uf.edex.plugin.ffmp.FFMPGenerator; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 01, 2011 dhladky Initial creation - * + * July 11, 2012 dhladky Edited for FFTI work * * * @author dhladky @@ -71,18 +70,12 @@ public class FFTIProcessor { private FFMPGenerator ffmpgen = null; - private String wfo = null; - - private Date ffgBarrierTime = null; - - private FFMPDataContainer sourceContainer = null; - /** Pattern for dates in radar */ public static String datePattern = "yyyy-MM-dd HH:mm:ss"; - + /** 6 hour back time multiplier */ public static long backTime = 3600 * 1000 * 6; - + /** FFG back time multiplier */ public static long ffgbackTime = 3600 * 1000 * 24; @@ -100,321 +93,214 @@ public class FFTIProcessor { this.ffmpgen = ffmpgen; this.ffmpRec = ffmpRec; this.fftiSource = fftiSource; - this.wfo = ffmpRec.getWfo(); - long curr = ffmpRec.getDataTime().getRefTime().getTime(); - long fftiFFGBarrier = (long) (24.0 * 60.0 * 60.0 * 1000); - this.ffgBarrierTime = new Date(curr - fftiFFGBarrier); } /** * Process FFTI for this source */ public void processFFTI() { - ArrayList dispNameList = fftiSource.getDisplayNameList(); - for (String sourceNameString : dispNameList) { - - String iSiteKey = ffmpRec.getSiteKey(); - String iDataKey = ffmpRec.getDataKey(); - String sourceString = sourceNameString; - - String[] parts = sourceNameString.split("-"); - SourceXML source = null; - if (parts.length > 1) { - iSiteKey = parts[0]; - String sourceName = parts[1]; - source = FFMPSourceConfigurationManager.getInstance() - .getSource(sourceName); - } else { - // mosaic source - source = FFMPSourceConfigurationManager.getInstance() - .getSourceByDisplayName(sourceString); - } + ArrayList dispNameList = fftiSource.getDisplayNameList(); + String iSiteKey = ffmpRec.getSiteKey(); + String iDataKey = ffmpRec.getDataKey(); - if (source.getSourceType().equals( - FFMPSourceConfigurationManager.SOURCE_TYPE.GUIDANCE - .getSourceType())) { - - sourceString = source.getDisplayName(); - - // Mark all GUIDANCE related sources as dirty for FFTI - for (String fftiName: ffmpgen.getFFTIDataContainer().keySet()) { - if (fftiName.startsWith(sourceString)) { - System.out.println("Resetting FFTI source for processing!!!!! "+fftiName); - ffmpgen.getFFTIData(fftiName).reset(true); - } - } - - } else { - - sourceString = source.getDisplayName() + "-" + iSiteKey + "-"+ iDataKey; - - // Mark this source as dirty for FFTI - if (ffmpgen.isFFTI(sourceString)) { - //System.out.println("Resetting FFTI source for processing!!!!! "+sourceString); - ffmpgen.getFFTIData(sourceString).reset(true); - - // Mark associated sources as dirty for FFTI - for (String fftiName: ffmpgen.getFFTIDataContainer().keySet()) { - String[] name = fftiName.split("-"); - if (name.length == 3) { - if (name[1].equals(source.getDisplayName()) && name[2].equals(iDataKey)) { - //System.out.println("Resetting FFTI source for processing!!!!! "+fftiName); - ffmpgen.getFFTIData(fftiName).reset(true); - } - } - } - } - } - - Date backDate = new Date(ffmpRec.getDataTime().getRefTime().getTime() - - (backTime)); - ArrayList hucs = new ArrayList(); - hucs.add("ALL"); + for (String sourceNameString : dispNameList) { - sourceContainer = ffmpgen.getFFMPDataContainer(sourceString, hucs, backDate); + String sourceString = sourceNameString; - // we attempt to reload sources - // this is done to keep all of the clustered - // FFMP's in sync. otherwise one JVM would never - // be updated with what the other had processed. - if (sourceContainer == null) { - // first time being read - // check back this far for an existing file - boolean reload = false; + String[] parts = sourceNameString.split("-"); + SourceXML source = null; - if (source.getSourceType() - .equals(FFMPSourceConfigurationManager.SOURCE_TYPE.GUIDANCE - .getSourceType())) { - reload = true; - } + if (parts.length > 1) { + iSiteKey = parts[0]; + sourceString = parts[1]; + } - if (reload) { - sourceContainer = new FFMPDataContainer(sourceString); - } - } + source = FFMPSourceConfigurationManager.getInstance() + .getSourceByDisplayName(sourceString); - if (sourceContainer != null) { - - boolean write = false; - - if (source.getSourceType().equals( - SOURCE_TYPE.GUIDANCE.getSourceType())) { + // System.out.println("Source XML: "+source.getDisplayName()); - String primarySource = ffmpgen.fscm - .getPrimarySource(source); - ProductXML product = ffmpgen.fscm.getProduct(primarySource); - Date ffgBackDate = new Date(ffmpRec.getDataTime() - .getRefTime().getTime() - - (ffgbackTime)); + if (source != null) { - // try to load any missing one's, other than the new one - for (SourceXML guidSource : product - .getGuidanceSourcesByType(source.getDisplayName())) { - if (!sourceContainer.containsKey(guidSource - .getSourceName()) - && !source.getSourceName().equals( - guidSource.getSourceName())) { - - sourceContainer = populateDataContainer( - sourceContainer, ffmpgen.template, null, - ffgBackDate, ffmpRec.getDataTime() - .getRefTime(), wfo, source, - iSiteKey); - - sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); - write = true; - } - } + if (source.getSourceType().equals( + FFMPSourceConfigurationManager.SOURCE_TYPE.GUIDANCE + .getSourceType())) { - } /*else { + sourceString = source.getDisplayName(); - Date newDate = sourceContainer.getNewest(); - Date oldDate = sourceContainer.getOldest(); + // Mark all GUIDANCE related sources as dirty for FFTI + for (String fftiName : ffmpgen.getFFTIDataContainer() + .keySet()) { + if (fftiName.startsWith(sourceString)) { + // System.out + // .println("Resetting FFTI source for processing!!!!! " + // + fftiName); + ffmpgen.getFFTIData(fftiName).setReset(true); + } + } - if (newDate != null && oldDate != null) { - if ((ffmpRec.getDataTime().getRefTime().getTime() - newDate - .getTime()) >= (source - .getExpirationMinutes(iSiteKey) * 60 * 1000)) { - // force a re-query back to the newest time in - // existing source container - sourceContainer = populateDataContainer( - sourceContainer, ffmpgen.template, null, - newDate, - ffmpRec.getDataTime().getRefTime(), wfo, - source, iSiteKey); - - sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); - write = true; - - } else if (oldDate - .after(new Date( - barrierTime.getTime() - - (source - .getExpirationMinutes(iSiteKey) * 60 * 1000)))) { - // force a re-query back to barrierTime for - // existing source container - sourceContainer = populateDataContainer( - sourceContainer, ffmpgen.template, null, - barrierTime, oldDate, wfo, source, iSiteKey); - - sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); - write = true; - } - } else { - // COMPLETELY EMPTY SOURCE CONTAINER - // force a re-query back to barrierTime from current - // refTime - sourceContainer = populateDataContainer( - sourceContainer, ffmpgen.template, null, - barrierTime, - ffmpRec.getDataTime().getRefTime(), wfo, - source, iSiteKey); - - sourceContainer.setFilePath("" + FFMPGenerator.sharePath + ffmpRec.getWfo() + "/"+ sourceString); - write = true; - } - } - - */ - - if (write) { - sourceContainer.purge(ffgBarrierTime); - //System.out.println("Writing from with in the FFTI Processor!!! "+sourceContainer.getFilePath()); - ffmpgen.writeLoaderBuddyFiles(sourceContainer); - } - } - } - } + } else { - /** - * Populates the FFTI Data back to the determined date - * - * @param sourceContainer - * @param template - * @param startDate - * @param endDate - * @param wfo - * @param source - * @return - */ - public static FFMPDataContainer populateDataContainer( - FFMPDataContainer sourceContainer, FFMPTemplates template, - ArrayList hucs, Date startDate, Date endDate, String wfo, - SourceXML source, String siteKey) { + sourceString = source.getDisplayName() + "-" + iSiteKey + + "-" + iDataKey; - ArrayList uris = getUris(startDate, endDate, wfo, source, - siteKey); - // System.out.println("Number of Records querried: " + siteKey + " : " - // + uris.size()); + // Mark this source as dirty for FFTI + if (ffmpgen.isFFTI(sourceString)) { + // System.out + // .println("Resetting FFTI source for processing!!!!! " + // + sourceString); + ffmpgen.getFFTIData(sourceString).setReset(true); - for (String uri : uris) { + // Mark associated sources as dirty for FFTI + for (String fftiName : ffmpgen.getFFTIDataContainer() + .keySet()) { + String[] name = fftiName.split("-"); + if (name.length == 3) { + if (name[1].equals(source.getDisplayName()) + && name[2].equals(iDataKey)) { + // System.out + // .println("Resetting FFTI source for processing!!!!! " + // + fftiName); + ffmpgen.getFFTIData(fftiName) + .setReset(true); + } + } + } + } + } + } + } + } - FFMPRecord rec = new FFMPRecord(uri); + /** + * Populates the FFTI Data back to the determined date + * + * @param sourceContainer + * @param template + * @param startDate + * @param endDate + * @param wfo + * @param source + * @return + */ + public static FFMPDataContainer populateDataContainer( + FFMPDataContainer sourceContainer, FFMPTemplates template, + ArrayList hucs, Date startDate, Date endDate, String wfo, + SourceXML source, String siteKey) { - boolean contains = false; + ArrayList uris = getUris(startDate, endDate, wfo, source, + siteKey); + // System.out.println("Number of Records querried: " + siteKey + " : " + // + uris.size()); - if (source.getSourceType().equals( - SOURCE_TYPE.GUIDANCE.getSourceType())) { - contains = sourceContainer.containsKey(source.getSourceName()); - // System.out.println("Processing FFG source!!!!!" - // + source.getSourceName()); - } else { - contains = sourceContainer.containsKey(rec.getDataTime() - .getRefTime()); - } + for (String uri : uris) { - if (!contains) { - try { - - if (hucs == null) { - hucs = new ArrayList(); - hucs.add("ALL"); - } - - for (String huc : hucs) { + FFMPRecord rec = new FFMPRecord(uri); - rec = populateRecord(rec, huc, template); - FFMPBasinData newData = rec.getBasinData(huc); - sourceContainer.addFFMPEntry(rec.getDataTime() - .getRefTime(), source, newData, huc, siteKey); + boolean contains = false; - } + if (source.getSourceType().equals( + SOURCE_TYPE.GUIDANCE.getSourceType())) { + contains = sourceContainer.containsKey(source.getSourceName()); + // System.out.println("Processing FFG source!!!!!" + // + source.getSourceName()); + } else { + contains = sourceContainer.containsKey(rec.getDataTime() + .getRefTime()); + } - // System.out.println("Adding Time: " - // + rec.getDataTime().getRefTime()); + if (!contains) { + try { - } catch (PluginException e) { - e.printStackTrace(); - statusHandler.handle(Priority.ERROR, - "Source: " + source.getDisplayName() + " domain: " - + wfo - + " : failed to retrieve FFMP/FFTI Data "); - } - } - } + if (hucs == null) { + hucs = new ArrayList(); + hucs.add("ALL"); + } - return sourceContainer; - } + for (String huc : hucs) { - /** - * Get the uris for this FFTI source - * - * @param startDate - * @param endDate - * @param wfo - * @param source - * @return - */ - public static ArrayList getUris(Date startDate, Date endDate, - String wfo, SourceXML source, String siteKey) { + rec = populateRecord(rec, huc, template); + FFMPBasinData newData = rec.getBasinData(huc); + sourceContainer.addFFMPEntry(rec.getDataTime() + .getRefTime(), source, newData, huc, siteKey); - SimpleDateFormat datef = new SimpleDateFormat(datePattern); - datef.setTimeZone(TimeZone.getTimeZone("Zulu")); - StringBuilder query = new StringBuilder(200); + } - query.append("select datauri from ffmp where wfo = '"); - query.append(wfo); - query.append("' and sourcename = '"); - query.append(source.getSourceName()); - query.append("' and sitekey = '"); - query.append(siteKey); - if (!source.isMosaic()) { - query.append("' and datakey = '"); - query.append(siteKey); - } - query.append("' and reftime >= '"); - query.append(datef.format(startDate)); - query.append("' and reftime < '"); - query.append(datef.format(endDate)); + // System.out.println("Adding Time: " + // + rec.getDataTime().getRefTime()); - query.append("' order by reftime desc"); - // System.out.println("URI query: " + query.toString()); + } catch (PluginException e) { + e.printStackTrace(); + statusHandler.handle(Priority.ERROR, + "Source: " + source.getDisplayName() + " domain: " + + wfo + + " : failed to retrieve FFMP/FFTI Data "); + } + } + } - ArrayList uris = new ArrayList(); + return sourceContainer; + } - try { - CoreDao dao = new CoreDao(DaoConfig.forDatabase(FFMPUtils.META_DB)); - Object[] results = dao.executeSQLQuery(query.toString()); + /** + * Get the uris for this FFTI source + * + * @param startDate + * @param endDate + * @param wfo + * @param source + * @return + */ + public static ArrayList getUris(Date startDate, Date endDate, + String wfo, SourceXML source, String siteKey) { - if (results.length > 0) { - for (int i = 0; i < results.length; i++) { - Object result = results[i]; - if (result != null) { - /* - * System.out.println("Adding URI to FFTI list: " + - * (String) result); - */ - uris.add((String) result); - } - } - } + SimpleDateFormat datef = new SimpleDateFormat(datePattern); + datef.setTimeZone(TimeZone.getTimeZone("Zulu")); + StringBuilder query = new StringBuilder(200); - } catch (Exception e) { - statusHandler.handle(Priority.ERROR, - "Source: " + source.getSourceName() + " domain: " + wfo - + " : failed to query"); - } + query.append("select datauri from ffmp where wfo = '"); + query.append(wfo); + query.append("' and sourcename = '"); + query.append(source.getSourceName()); + query.append("' and sitekey = '"); + query.append(siteKey); + if (!source.isMosaic()) { + query.append("' and datakey = '"); + query.append(siteKey); + } + query.append("' and reftime >= '"); + query.append(datef.format(startDate)); + query.append("' and reftime < '"); + query.append(datef.format(endDate)); + + query.append("' order by reftime desc"); + // System.out.println("URI query: " + query.toString()); + + ArrayList uris = new ArrayList(); + + try { + CoreDao dao = new CoreDao(DaoConfig.forDatabase(FFMPUtils.META_DB)); + Object[] results = dao.executeSQLQuery(query.toString()); + + if (results.length > 0) { + for (int i = 0; i < results.length; i++) { + Object result = results[i]; + if (result != null) { + /* + * System.out.println("Adding URI to FFTI list: " + + * (String) result); + */ + uris.add((String) result); + } + } + } + + } catch (Exception e) { + statusHandler.handle(Priority.ERROR, + "Source: " + source.getSourceName() + " domain: " + wfo + + " : failed to query"); + } return uris; } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java index 8f088bb4b4..e8c16cdffe 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTIRatioDiff.java @@ -22,6 +22,15 @@ package com.raytheon.uf.edex.plugin.ffmp.common; import java.util.ArrayList; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + /** * FFTIRatioDiff * @@ -38,16 +47,23 @@ import java.util.ArrayList; * @version 1.0 */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +@DynamicSerialize public class FFTIRatioDiff extends FFTIData { + @DynamicSerializeElement + @XmlElements({ @XmlElement(name = "qpe", type = Float.class) }) private ArrayList qpes; + @DynamicSerializeElement + @XmlElements({ @XmlElement(name = "guid", type = Float.class) }) private ArrayList guids; - + public FFTIRatioDiff() { - + } - + public FFTIRatioDiff(ArrayList qpes, ArrayList guids, Double gap) { setQpes(qpes); @@ -70,5 +86,5 @@ public class FFTIRatioDiff extends FFTIData { public void setGuids(ArrayList guids) { this.guids = guids; } - + } diff --git a/edexOsgi/com.raytheon.uf.edex.site/src/com/raytheon/uf/edex/site/SiteAwareRegistry.java b/edexOsgi/com.raytheon.uf.edex.site/src/com/raytheon/uf/edex/site/SiteAwareRegistry.java index accf9abff2..d4a94c0b57 100644 --- a/edexOsgi/com.raytheon.uf.edex.site/src/com/raytheon/uf/edex/site/SiteAwareRegistry.java +++ b/edexOsgi/com.raytheon.uf.edex.site/src/com/raytheon/uf/edex/site/SiteAwareRegistry.java @@ -25,7 +25,7 @@ import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; @@ -58,6 +58,8 @@ import com.raytheon.uf.edex.site.SiteActivationMessage.Action; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 30, 2010 rjpeter Initial creation + * Jul 31, 2012 #965 dgilling Force ordering of sites in + * getActiveSites(). * * * @@ -136,7 +138,9 @@ public class SiteAwareRegistry { */ public String[] getActiveSites() { // make a set of the strings for each listener site - Set tmp = new HashSet(); + Set tmp = new LinkedHashSet(); + tmp.add(PropertiesFactory.getInstance().getEnvProperties() + .getEnvValue("SITENAME")); for (ISiteActivationListener sa : activationListeners) { tmp.addAll(sa.getActiveSites()); } @@ -160,8 +164,8 @@ public class SiteAwareRegistry { } return false; } - - public String validateConfig(String siteID){ + + public String validateConfig(String siteID) { StringBuffer retVal = new StringBuffer(); for (ISiteActivationListener sa : activationListeners) { retVal.append(sa.validateConfig(siteID)); diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/publishGFE b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/publishGFE new file mode 100644 index 0000000000..bb65c312a4 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/publishGFE @@ -0,0 +1,50 @@ +#!/bin/bash +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## +############################################################################## +# TODO: ADD DESCRIPTION +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 07/26/12 #965 dgilling Initial Creation. +############################################################################## + +# this allows you to run this script from outside of ./bin +path_to_script=`readlink -f $0` +RUN_FROM_DIR=`dirname $path_to_script` + +BASE_AWIPS_DIR=`dirname $RUN_FROM_DIR` + +# get the base environment +source ${RUN_FROM_DIR}/setup.env + +# setup the environment needed to run the the Python +export LD_LIBRARY_PATH=${BASE_AWIPS_DIR}/src/lib:${PYTHON_INSTALL}/lib +export PYTHONPATH=${RUN_FROM_DIR}/src:$PYTHONPATH + +# execute the ifpInit Python module +_PYTHON="${PYTHON_INSTALL}/bin/python" +_MODULE="${RUN_FROM_DIR}/src/publishgfe/publishGFE.py" + +# quoting of '$@' is used to prevent command line interpretation +$_PYTHON $_MODULE -h ${DEFAULT_HOST} -r ${DEFAULT_PORT} "$@" + diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsyncGridsToCWF.sh b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsyncGridsToCWF.sh index eead9e0880..11c901cb0d 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsyncGridsToCWF.sh +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsyncGridsToCWF.sh @@ -204,13 +204,8 @@ remDirectory1="netcdf-wfo" # Directory where grids are stored on the mask=ISC_Send_Area # Parameter list for the netcdf file -parmlist1="-p MaxT -p MinT -p MaxRH -p MinRH -p T -p Td -p RH -p WindChill -p HeatIndex -p ApparentT" -parmlist2="-p PoP -p PoP12 -p Sky -p Wx -p Hazards -p SnowLevel -p QPF -p SnowAmt -p IceAccum -p Wind -p WindGust" -parmlist3="-p ClearIndex -p FreeWind -p LAL -p Haines -p MixHgt -p VentRate -p TransWind -p Wind20ft -p CLRIndx" -parmlist5="" -parmlist6="" -parmlist="$parmlist1 $parmlist2 $parmlist3 $parmlist4 $parmlist5 $parmlist6" -parmlist="" #uncomment to send all parameters +parmlist="" #send all parameters +. ${IFPS_DATA}/rsync_parms.${1} creationAttempts=3 # How many times do you want script to create and # quality control netcdf files if bad netcdf files @@ -237,11 +232,7 @@ FXA_BIN="/awips2/fxa/bin" CDSHOST="ec" CDSPORT="9581" -# It is possible that you may not have all of the parameters that your service backup sites -# need sent to the webfarms. So if script is run for a backup site, then send all parameters. -parmlist=" " - -# Setting up the infrastructure for a log file. +# set current data and log file name currdate=$(date -u +%Y%m%d) export LOG_FILE="${DXwrkDir}/log/${currdate}/netcdf_rsync.log" @@ -281,6 +272,12 @@ find ${WRKDIR}/. -mmin +60 -exec rm {} -f \; echo ...finished. >> $LOG_FILE echo " " >> $LOG_FILE +if [ "$parmlist" != "" ]; then + echo "Will trim elements to $parmlist" >> $LOG_FILE +else + echo "Will send all elements" >> $LOG_FILE +fi + # Determine the ifpnetCDF start and end times. start_time=$(date +%Y%m%d_%H00 -d "6 hours ago") end_time=$(date +%Y%m%d_%H00 -d "192 hours") diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsync_parms.ccc b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsync_parms.ccc new file mode 100644 index 0000000000..d4613a9b00 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/rsync_parms.ccc @@ -0,0 +1,8 @@ +# Parameter list for the netcdf file +# Example: parmlist1="-p ClearIndex -p MaxT" +parmlist1="" +parmlist2="" +parmlist3="" +parmlist5="" +parmlist6="" +parmlist="$parmlist1 $parmlist2 $parmlist3 $parmlist4 $parmlist5 $parmlist6" diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/ifpservertext/ifpServerText.py b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/ifpservertext/ifpServerText.py index 9c53af54f7..23a6e29aa5 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/ifpservertext/ifpServerText.py +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/ifpservertext/ifpServerText.py @@ -23,7 +23,6 @@ import sys, os, pwd, string, getopt, logging import numpy from dynamicserialize.dstypes.com.raytheon.uf.common.auth.resp import SuccessfulExecution -from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetActiveSitesRequest from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetSingletonDbIdsRequest from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetSiteTimeZoneInfoRequest from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GridLocRequest @@ -39,6 +38,7 @@ from dynamicserialize.dstypes.com.raytheon.uf.common.localization.stream import from dynamicserialize.dstypes.com.raytheon.uf.common.message import WsId from dynamicserialize.dstypes.com.raytheon.uf.common.plugin.nwsauth.user import User from dynamicserialize.dstypes.com.raytheon.uf.common.plugin.nwsauth.user import UserId +from dynamicserialize.dstypes.com.raytheon.uf.common.site.requests import GetActiveSitesRequest from ufpy import ThriftClient # @@ -700,19 +700,14 @@ Usage: ifpServerText -h hostname -p rpcPortNumber -o siteID [-u user] raise Exception, serverResponse.message() elif self.__metaInfo == "site": request = GetActiveSitesRequest() - request.setWorkstationID(wsId) - request.setSiteID("") try: serverResponse = self.__thrift.sendRequest(request) except Exception, e: raise RuntimeError, "Could not retrieve meta information: " + str(e) - if (serverResponse.isOkay()): - sites = serverResponse.getPayload() - for s in sites: - txt = txt + s + "\n" - else: - raise Exception, serverResponse.message() + for site in serverResponse: + txt = txt + site + "\n" + elif self.__metaInfo == "singleton": request = GetSingletonDbIdsRequest() request.setWorkstationID(wsId) diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/publishgfe/publishGFE.py b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/publishgfe/publishGFE.py new file mode 100644 index 0000000000..f59911c365 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/publishgfe/publishGFE.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python + +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +import argparse +import logging +import sys + +from ufpy import UsageArgumentParser +from ufpy.gfe import IFPClient + +from dynamicserialize.dstypes.com.raytheon.uf.common.time import TimeRange +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.db.objects import DatabaseID +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.db.objects import ParmID +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.server.request import CommitGridRequest + + +logger = None +def __initLogger(): + global logger + logger = logging.getLogger("publishGFE") + logger.setLevel(logging.DEBUG) + ch = logging.StreamHandler() + ch.setLevel(logging.INFO) + # Uncomment line below to enable debug-level logging + # ch.setLevel(logging.DEBUG) + formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s", "%H:%M:%S") + ch.setFormatter(formatter) + logger.addHandler(ch) + +## Custom actions for ArgumentParser object ## +class StoreTimeAction(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + (isValid, dateTime) = DatabaseID.decodeDtg(values) + if isValid: + setattr(namespace, self.dest, dateTime) + else: + parser.error("Argument for option " + option_string + " not in yyyymmdd_hhmm format") + +class AppendParmNameAndLevelAction(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + tx = ParmID.parmNameAndLevel(values) + comp = tx[0] + '_' + tx[1] + if (hasattr(namespace, self.dest)) and \ + (getattr(namespace, self.dest) is not None): + currentValues = getattr(namespace, self.dest) + currentValues.append(comp) + setattr(namespace, self.dest, currentValues) + else: + setattr(namespace, self.dest, [comp]) + +def validateArgs(): + parser = UsageArgumentParser.UsageArgumentParser(prog='publishGFE', conflict_handler="resolve") + parser.add_argument("-h", action="store", dest="host", + help="where the ifpServer is running", + required=True, metavar="hostname") + parser.add_argument("-r", action="store", type=int, dest="port", + help="the port that ifpServer is serving", + required=True, metavar="portNumber") + parser.add_argument("-t", action="store", dest="definedTR", + help="(Optional) named time range, supersedes -s and -e", + default="", metavar="namedTR") + parser.add_argument("-s", action=StoreTimeAction, dest="sT", + help="(Optional) start time, format = yyyymmdd_hhmm", + metavar="startTime") + parser.add_argument("-e", action=StoreTimeAction, dest="eT", + help="(Optional) end time, format = yyyymmdd_hhmm", + metavar="endTime") + parser.add_argument("-u", action="store", dest="user", + help="(Optional) user, defaults to SITE", + default="SITE", metavar="user") + parser.add_argument("-o", action="store", dest="site", + help="(Optional) site to publish grids for, defaults to server's primary site", + metavar="site") + parser.add_argument("-p", action=AppendParmNameAndLevelAction, dest="parmNamesAndLevels", + help="(Optional) parm, can have multiple switches; if none, defaults to all parms.", + default=[], metavar="parm") + options = parser.parse_args() + + tr = TimeRange.allTimes() + if options.sT is not None: + tr.setStart(options.sT) + if options.eT is not None: + tr.setEnd(options.eT) + setattr(options, 'tr', tr) + + return options + +def expandToParmInv(inv, definedTR): + expandedTR = definedTR + for tr in inv: + if tr.overlaps(definedTR): + expandedTR = expandedTR.combineWith(tr) + + return expandedTR + +def main(): + __initLogger() + logger.info("Publish Fcst Data to Official") + + args = validateArgs() + logger.debug("Command-line arguments: " + str(args)) + + # build IFPClient object + db = IFPClient.IFPClient(args.host, args.port, args.user, args.site, "publishGFE") + + # get site id + siteID = args.site + if siteID is None or len(siteID) == 0: + sr = db.getSiteID() + if not sr.isOkay(): + logger.error("Unable to determine site id: " + sr.message()) + sys.exit(1) + siteID = sr.getPayload()[0] + + # calculate list of parms + dbid = DatabaseID(siteID + "_GRID__Fcst_00000000_0000") + sr = db.getParmList(dbid) + if not sr.isOkay(): + logger.error("Unable to determine parms: " + sr.message()) + sys.exit(1) + parmsInDb = sr.getPayload() + commitParmList = [] + if len(args.parmNamesAndLevels) == 0: + commitParmList = parmsInDb + else: + for parm in args.parmNamesAndLevels: + tx = ParmID.parmNameAndLevel(parm) + found = False + for dbParm in parmsInDb: + if dbParm.getParmName() == tx[0] and dbParm.getParmLevel() == tx[1]: + commitParmList.append(dbParm) + found = True + if not found: + logger.warning("Unable to find parm [" + str(parm) + "] in database [" + str(dbid) + "]") + + # calculate time ranges + tr = args.tr + if len(args.definedTR) > 0: + sr = db.getSelectTR(args.definedTR) + if not sr.isOkay(): + logger.error("Unable to find select tr definition: " + sr.message()) + sys.exit(1) + tr = sr.getPayload() + + # CommitGridRequest(parmid, commitTime) + requests = [] + for parm in commitParmList: + inv = [] + sr = db.getGridInventory(parm) + if not sr.isOkay(): + logger.error("Unable to get grid inventory: " + sr.message()) + sys.exit(1) + inv = sr.getPayload() + expandTR = expandToParmInv(inv, tr) + req = CommitGridRequest() + req.setParmId(parm) + req.setTimeRange(expandTR) + requests.append(req) + logger.debug(parm.getParmName() + ' ' + str(tr)) + + # commit grid + sr = db.commitGrid(requests) + if not sr.isOkay(): + logger.error("Unable to publish grids: " + sr.message()) + sys.exit(1) + else: + logger.info("Publish completed.") + + +if __name__ == '__main__': + main() diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/__init__.py index cae498053c..2c658821b8 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/__init__.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/__init__.py @@ -33,6 +33,7 @@ __all__ = [ 'pointdata', 'pypies', 'serialization', + 'site', 'time' ] diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmID.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmID.py index e5a9a48328..68d276abfa 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmID.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmID.py @@ -119,13 +119,25 @@ class ParmID(object): if not self.parmLevel.isalnum(): return False - return True - + return True @staticmethod def defaultLevel(): return "SFC" + @staticmethod + def parmNameAndLevel(composite): + retValue = [] + + pos = composite.find('_') + if pos != -1: + retValue.append(composite[:pos]) + retValue.append(composite[pos+1:]) + else: + retValue.append(composite) + retValue.append("SFC") + return retValue + def __str__(self): return self.__repr__() diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/CommitGridsRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/CommitGridsRequest.py new file mode 100644 index 0000000000..28d3d2b119 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/CommitGridsRequest.py @@ -0,0 +1,47 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class CommitGridsRequest(object): + + def __init__(self): + self.commits = None + self.workstationID = None + self.siteID = None + + def getCommits(self): + return self.commits + + def setCommits(self, commits): + self.commits = commits + + def getWorkstationID(self): + return self.workstationID + + def setWorkstationID(self, workstationID): + self.workstationID = workstationID + + def getSiteID(self): + return self.siteID + + def setSiteID(self, siteID): + self.siteID = siteID + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetParmListRequest.py similarity index 87% rename from pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.py rename to pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetParmListRequest.py index 2e8732d9b7..ebb93968b8 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetActiveSitesRequest.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetParmListRequest.py @@ -20,12 +20,19 @@ # File auto-generated against equivalent DynamicSerialize Java class -class GetActiveSitesRequest(object): +class GetParmListRequest(object): def __init__(self): + self.dbIds = None self.workstationID = None self.siteID = None + def getDbIds(self): + return self.dbIds + + def setDbIds(self, dbIds): + self.dbIds = dbIds + def getWorkstationID(self): return self.workstationID diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.py new file mode 100644 index 0000000000..24910d1417 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/GetSelectTimeRangeRequest.py @@ -0,0 +1,47 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class GetSelectTimeRangeRequest(object): + + def __init__(self): + self.name = None + self.workstationID = None + self.siteID = None + + def getName(self): + return self.name + + def setName(self, name): + self.name = name + + def getWorkstationID(self): + return self.workstationID + + def setWorkstationID(self, workstationID): + self.workstationID = workstationID + + def getSiteID(self): + return self.siteID + + def setSiteID(self, siteID): + self.siteID = siteID + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/__init__.py index b9333b2865..c969f576df 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/__init__.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/request/__init__.py @@ -21,21 +21,25 @@ # File auto-generated by PythonFileGenerator __all__ = [ + 'CommitGridsRequest', 'ConfigureTextProductsRequest', 'CreateNetCDFGridRequest', 'ExecuteIscMosaicRequest', 'GetASCIIGridsRequest', - 'GetActiveSitesRequest', 'GetGridDataRequest', 'GetGridInventoryRequest', 'GetLockTablesRequest', - 'GetPythonGridDataRequest', 'GetOfficialDbNameRequest', + 'GetParmListRequest', + 'GetPythonGridDataRequest', + 'GetSelectTimeRangeRequest', 'GetSingletonDbIdsRequest', 'GetSiteTimeZoneInfoRequest', 'GridLocRequest', 'IscDataRecRequest', 'LockChangeRequest', + 'ProcessReceivedConfRequest', + 'ProcessReceivedDigitalDataRequest', 'PurgeGfeGridsRequest', 'SaveASCIIGridsRequest', 'SendGridsToNDFDRequest', @@ -43,21 +47,25 @@ __all__ = [ 'SmartInitRequest' ] +from CommitGridsRequest import CommitGridsRequest from ConfigureTextProductsRequest import ConfigureTextProductsRequest from CreateNetCDFGridRequest import CreateNetCDFGridRequest from ExecuteIscMosaicRequest import ExecuteIscMosaicRequest from GetASCIIGridsRequest import GetASCIIGridsRequest -from GetActiveSitesRequest import GetActiveSitesRequest from GetGridDataRequest import GetGridDataRequest from GetGridInventoryRequest import GetGridInventoryRequest from GetLockTablesRequest import GetLockTablesRequest -from GetPythonGridDataRequest import GetPythonGridDataRequest from GetOfficialDbNameRequest import GetOfficialDbNameRequest +from GetParmListRequest import GetParmListRequest +from GetPythonGridDataRequest import GetPythonGridDataRequest +from GetSelectTimeRangeRequest import GetSelectTimeRangeRequest from GetSingletonDbIdsRequest import GetSingletonDbIdsRequest from GetSiteTimeZoneInfoRequest import GetSiteTimeZoneInfoRequest from GridLocRequest import GridLocRequest from IscDataRecRequest import IscDataRecRequest from LockChangeRequest import LockChangeRequest +from ProcessReceivedConfRequest import ProcessReceivedConfRequest +from ProcessReceivedDigitalDataRequest import ProcessReceivedDigitalDataRequest from PurgeGfeGridsRequest import PurgeGfeGridsRequest from SaveASCIIGridsRequest import SaveASCIIGridsRequest from SendGridsToNDFDRequest import SendGridsToNDFDRequest diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/CommitGridRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/CommitGridRequest.py new file mode 100644 index 0000000000..8b42939a87 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/CommitGridRequest.py @@ -0,0 +1,54 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class CommitGridRequest(object): + + def __init__(self): + self.parmId = None + self.dbId = None + self.timeRange = None + self.clientSendStatus = False + + def getParmId(self): + return self.parmId + + def setParmId(self, parmId): + self.parmId = parmId + + def getDbId(self): + return self.dbId + + def setDbId(self, dbId): + self.dbId = dbId + + def getTimeRange(self): + return self.timeRange + + def setTimeRange(self, timeRange): + self.timeRange = timeRange + + def getClientSendStatus(self): + return self.clientSendStatus + + def setClientSendStatus(self, clientSendStatus): + self.clientSendStatus = bool(clientSendStatus) + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/__init__.py index a96cf2cb49..7c56d14258 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/__init__.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataplugin/gfe/server/request/__init__.py @@ -21,11 +21,13 @@ # File auto-generated by PythonFileGenerator __all__ = [ + 'CommitGridRequest', 'GetGridRequest', 'LockRequest', 'LockTableRequest' ] +from CommitGridRequest import CommitGridRequest from GetGridRequest import GetGridRequest from LockRequest import LockRequest from LockTableRequest import LockTableRequest diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/__init__.py new file mode 100644 index 0000000000..d9702fd5d7 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/__init__.py @@ -0,0 +1,27 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# File auto-generated by PythonFileGenerator + +__all__ = [ + 'requests' + ] + + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.py new file mode 100644 index 0000000000..747ee0320c --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/GetActiveSitesRequest.py @@ -0,0 +1,27 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class GetActiveSitesRequest(object): + + def __init__(self): + super(GetActiveSitesRequest, self).__init__() + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/__init__.py new file mode 100644 index 0000000000..f3ddd21199 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/site/requests/__init__.py @@ -0,0 +1,28 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# File auto-generated by PythonFileGenerator + +__all__ = [ + 'GetActiveSitesRequest' + ] + +from GetActiveSitesRequest import GetActiveSitesRequest + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/time/TimeRange.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/time/TimeRange.py index c521efdba5..a30d4e0316 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/time/TimeRange.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/time/TimeRange.py @@ -27,9 +27,9 @@ import time MAX_TIME = 2147483647 class TimeRange(object): - def __init__(self): - self.start = None - self.end = None + def __init__(self, start=None, end=None): + self.start = self.__convertToDateTime(start) + self.end = self.__convertToDateTime(end) def __str__(self): return self.__repr__() @@ -42,6 +42,21 @@ class TimeRange(object): def __ne__(self, other): return (not self.__eq__(other)) + + def __convertToDateTime(self, timeArg): + if timeArg is None: + return None + if isinstance(timeArg, datetime.datetime): + return timeArg + elif isinstance(timeArg, time.struct_time): + return datetime.datetime(*timeArg[:6]) + else: + totalSecs = long(timeArg) + if totalSecs < MAX_TIME: + return datetime.datetime.utcfromtimestamp(totalSecs) + else: + extraTime = datetime.timedelta(seconds=(totalSecs - MAX_TIME)) + return datetime.datetime.utcfromtimestamp(MAX_TIME) + extraTime def getStart(self): return self.start.utctimetuple() @@ -50,17 +65,7 @@ class TimeRange(object): return long(calendar.timegm(self.getStart()) * 1000) def setStart(self, start): - if isinstance(start, datetime.datetime): - self.start = start - elif isinstance(start, time.struct_time): - self.start = datetime.datetime(*start[:6]) - else: - totalSecs = long(start) - if totalSecs < MAX_TIME: - self.start = datetime.datetime.utcfromtimestamp(totalSecs) - else: - extraTime = datetime.timedelta(seconds=(totalSecs - MAX_TIME)) - self.start = datetime.datetime.utcfromtimestamp(MAX_TIME) + extraTime + self.start = self.__convertToDateTime(start) def getEnd(self): return self.end.utctimetuple() @@ -69,24 +74,43 @@ class TimeRange(object): return long(calendar.timegm(self.getEnd()) * 1000) def setEnd(self, end): - if isinstance(end, datetime.datetime): - self.end = end - elif isinstance(end, time.struct_time): - self.end = datetime.datetime(*end[:6]) - else: - totalSecs = long(end) - if totalSecs < MAX_TIME: - self.end = datetime.datetime.utcfromtimestamp(totalSecs) - else: - extraTime = datetime.timedelta(seconds=(totalSecs - MAX_TIME)) - self.end = datetime.datetime.utcfromtimestamp(MAX_TIME) + extraTime + self.end = self.__convertToDateTime(end) + def duration(self): + delta = self.end - self.start + return long(delta.total_seconds()) + + def contains(self, timeArg): + if isinstance(timeArg, TimeRange): + if self.duration() == 0: + return self.__eq__(timeArg) + elif timeArg.duration() == 0: + return self.contains(timeArg.start) + return (timeArg.start >= self.start and timeArg.end <= self.end) + else: + convTime = self.__convertToDateTime(timeArg) + if type(convTime) is not datetime.datetime: + raise TypeError("Invalid type for argument time specified to TimeRange.contains().") + if self.duration() != 0: + return (convTime >= self.start and convTime < self.end) + return convTime == self.start + def isValid(self): return (self.start != self.end) + def overlaps(self, timeRange): + return (timeRange.contains(self.start) or self.contains(timeRange.start)) + + def combineWith(self, timeRange): + if self.isValid() and timeRange.isValid(): + newStart = min(self.start, timeRange.start) + newEnd = max(self.end, timeRange.end) + return TimeRange(newStart, newEnd) + elif self.isValid(): + return self + + return timeRange + @staticmethod def allTimes(): - tr = TimeRange() - tr.setStart(0) - tr.setEnd(MAX_TIME) - return tr + return TimeRange(0, MAX_TIME) diff --git a/pythonPackages/ufpy/gfe/IFPClient.py b/pythonPackages/ufpy/gfe/IFPClient.py new file mode 100644 index 0000000000..1288094df6 --- /dev/null +++ b/pythonPackages/ufpy/gfe/IFPClient.py @@ -0,0 +1,173 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +from ufpy import ThriftClient + +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.db.objects import DatabaseID +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.db.objects import ParmID +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import CommitGridsRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetGridInventoryRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetParmListRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.request import GetSelectTimeRangeRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.server.request import CommitGridRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.message import WsId +from dynamicserialize.dstypes.com.raytheon.uf.common.site.requests import GetActiveSitesRequest +from dynamicserialize.dstypes.com.raytheon.uf.common.dataplugin.gfe.server.message import ServerResponse + + +# +# Provides a Python-based interface for executing GFE requests. +# +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 07/26/12 dgilling Initial Creation. +# +# +# + + +class IFPClient(object): + def __init__(self, host, port, user, site=None, progName=None): + self.__thrift = ThriftClient.ThriftClient(host, port) + self.__wsId = WsId(userName=user, progName=progName) + # retrieve default site + if site is None: + sr = self.getSiteID() + if len(sr.getPayload()) > 0: + site = sr.getPayload()[0] + self.__siteId = site + + def commitGrid(self, request): + if type(request) is CommitGridRequest: + return self.__commitGrid([request]) + elif self.__isHomogenousIterable(request, CommitGridRequest): + return self.__commitGrid([cgr for cgr in request]) + raise TypeError("Invalid type: " + str(type(request)) + " specified to commitGrid(). Only accepts CommitGridRequest or lists of CommitGridRequest.") + + def __commitGrid(self, requests): + ssr = ServerResponse() + request = CommitGridsRequest() + request.setCommits(requests) + sr = self.__makeRequest(request) + ssr.setMessages(sr.getMessages()) + return ssr + + def getParmList(self, id): + argType = type(id) + if argType is DatabaseID: + return self.__getParmList([id]) + elif self.__isHomogenousIterable(id, DatabaseID): + return self.__getParmList([dbid for dbid in id]) + raise TypeError("Invalid type: " + str(argType) + " specified to getParmList(). Only accepts DatabaseID or lists of DatabaseID.") + + def __getParmList(self, ids): + ssr = ServerResponse() + request = GetParmListRequest() + request.setDbIds(ids) + sr = self.__makeRequest(request) + ssr.setMessages(sr.getMessages()) + list = sr.getPayload() if sr.getPayload() is not None else [] + ssr.setPayload(list) + return ssr + + def __isHomogenousIterable(self, iterable, classType): + try: + iterator = iter(iterable) + for item in iterator: + if not isinstance(item, classType): + return False + except TypeError: + return False + return True + + def getGridInventory(self, parmID): + if type(parmID) is ParmID: + sr = self.__getGridInventory([parmID]) + list = [] + try: + list = sr.getPayload()[parmID] + except KeyError: + # no-op, we've already default the TimeRange list to empty + pass + sr.setPayload(list) + return sr + elif self.__isHomogenousIterable(parmID, ParmID): + return self.__getGridInventory([id for id in parmID]) + raise TypeError("Invalid type: " + str(type(parmID)) + " specified to getGridInventory(). Only accepts ParmID or lists of ParmID.") + + def __getGridInventory(self, parmIDs): + ssr = ServerResponse() + request = GetGridInventoryRequest() + request.setParmIds(parmIDs) + sr = self.__makeRequest(request) + ssr.setMessages(sr.getMessages()) + trs = sr.getPayload() if sr.getPayload() is not None else {} + ssr.setPayload(trs) + return ssr + + def getSelectTR(self, name): + request = GetSelectTimeRangeRequest() + request.setName(name) + sr = self.__makeRequest(request) + ssr = ServerResponse() + ssr.setMessages(sr.getMessages()) + ssr.setPayload(sr.getPayload()) + return ssr + + def getSiteID(self): + ssr = ServerResponse() + request = GetActiveSitesRequest() + sr = self.__makeRequest(request) + ssr.setMessages(sr.getMessages()) + ids = sr.getPayload() if sr.getPayload() is not None else [] + sr.setPayload(ids) + return sr + + def __makeRequest(self, request): + try: + request.setSiteID(self.__siteId) + except AttributeError: + pass + try: + request.setWorkstationID(self.__wsId) + except AttributeError: + pass + + sr = ServerResponse() + response = None + try: + response = self.__thrift.sendRequest(request) + except ThriftClient.ThriftRequestException as e: + sr.setMessages([str(e)]) + try: + sr.setPayload(response.getPayload()) + except AttributeError: + sr.setPayload(response) + try: + sr.setMessages(response.getMessages()) + except AttributeError: + # not a server response, nothing else to do + pass + + return sr diff --git a/pythonPackages/ufpy/gfe/__init__.py b/pythonPackages/ufpy/gfe/__init__.py new file mode 100644 index 0000000000..f2a16d5c47 --- /dev/null +++ b/pythonPackages/ufpy/gfe/__init__.py @@ -0,0 +1,37 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + + +# +# __init__.py for ufpy.gfe package +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 07/26/12 dgilling Initial Creation. +# +# +# + + +__all__ = [ + ] diff --git a/rpms/python.site-packages/Installer.qpid/component.spec b/rpms/python.site-packages/Installer.qpid/component.spec index b9051e5fa8..38b1b1a450 100644 --- a/rpms/python.site-packages/Installer.qpid/component.spec +++ b/rpms/python.site-packages/Installer.qpid/component.spec @@ -3,7 +3,7 @@ Summary: python client commands for a qpid cluster Name: awips2-python-qpid Version: 0.6 -Release: 3 +Release: 4 License: APL Group: AWIPSII BuildRoot: %{_build_root} @@ -115,4 +115,4 @@ rm -rf ${RPM_BUILD_ROOT} /awips2/python/lib/python2.7/site-packages/* /awips2/python/share/* %defattr(755,awips,fxalpha,755) -/awips2/python/bin/* \ No newline at end of file +/awips2/python/bin/*