From 7d092536743849292d1d6b8861580b14d8f5432c Mon Sep 17 00:00:00 2001 From: "Daniel.Huffman" Date: Tue, 26 Aug 2014 13:24:09 +0000 Subject: [PATCH 1/5] ASM #16715 - Reverted and augmented Cities.xml Change-Id: Ib83fab6854b68f11b72ef41104805b3f1431b8f0 Former-commit-id: e2e132e7a50fb749e3c787945aac7cda36dcae69 [formerly 8962a069be7fd9a5ec772bed8837a09ddb6c9272] [formerly d1cd90b487093a9774952ac0086d3ae6ebfcb1fa [formerly 2107976bd25c429521d4df7a92a3726a38806ba3]] Former-commit-id: d1cd90b487093a9774952ac0086d3ae6ebfcb1fa Former-commit-id: 64672eb47802ac260e3837ce72ad6b4932f9f01c --- .../localization/bundles/maps/Cities.xml | 56 +++++-------------- 1 file changed, 13 insertions(+), 43 deletions(-) diff --git a/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/Cities.xml b/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/Cities.xml index a6c0b21089..525d44f264 100644 --- a/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/Cities.xml +++ b/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/Cities.xml @@ -2,19 +2,19 @@ @@ -26,50 +26,20 @@ - - - - + + PLAN_VIEW - - - - - - - - - PLAN_VIEW - - - - - - cities.lpi - Cities - - + + + + + prog_disc + mapdata.city
Cities - - - - - - outlineWidth="1" /> - - PLAN_VIEW - - - - - - mapdata.city
- Cities -
-
From 10114b0bd1b3716bd4f33cd8d1f5ac34fb87632e Mon Sep 17 00:00:00 2001 From: David Friedman Date: Thu, 28 Aug 2014 15:43:32 +0000 Subject: [PATCH 2/5] ASM #15658 - WarnGen: inclusion of watch information in marine products Change-Id: I9f99e6136027f1a6419800f87e5a5709fe5be6b9 Former-commit-id: ea1e9feb1dd654a5520bbaf621c7d823ba68990e [formerly a2dfe8e8f6beae5a1a623b534576a14a5d657b18] [formerly ea9230b37c44afa1395062118e097a803ff21da6 [formerly 6bfa1d6662b00925814be7126592bbe340651649]] Former-commit-id: ea9230b37c44afa1395062118e097a803ff21da6 Former-commit-id: bc22f7309cb61cd6df919f015395122f13668057 --- .../gis/MarineWordingConfiguration.java | 99 ++++++++++++++ .../com/raytheon/viz/warngen/gis/Watch.java | 11 ++ .../raytheon/viz/warngen/gis/WatchUtil.java | 121 +++++++++++++++--- .../warning/config/WarngenConfiguration.java | 12 ++ .../base/warngen/VM_global_library.vm | 30 ++++- .../base/warngen/marineWeatherStatement.xml | 3 + .../base/warngen/marineZoneWording.xml | 24 ++++ .../base/warngen/specialMarineWarning.xml | 3 + .../warngen/specialMarineWarningFollowup.xml | 3 + 9 files changed, 288 insertions(+), 18 deletions(-) create mode 100644 cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/MarineWordingConfiguration.java create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/marineZoneWording.xml diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/MarineWordingConfiguration.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/MarineWordingConfiguration.java new file mode 100644 index 0000000000..36f0b7cc41 --- /dev/null +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/MarineWordingConfiguration.java @@ -0,0 +1,99 @@ +package com.raytheon.viz.warngen.gis; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.common.dataplugin.warning.util.WarnFileUtil; +import com.raytheon.uf.common.serialization.SingleTypeJAXBManager; +import com.raytheon.uf.viz.core.localization.LocalizationManager; +import com.raytheon.viz.warngen.gui.WarngenLayer; + +/** + * WarngenWordingConfiguration + * + *
+ *    SOFTWARE HISTORY
+ *
+ *    Date         Ticket#     Engineer       Description
+ *    ------------ ----------  -------------- --------------------------
+ *    2014-08-28   ASM #15658  D. Friedman    Initial Creation.
+ */
+@XmlAccessorType(XmlAccessType.NONE)
+@XmlRootElement(name = "zoneWordingConfig")
+public class MarineWordingConfiguration {
+
+    private static final String FILE_NAME = "marineZoneWording.xml";
+
+    @XmlElement(name = "entry")
+    private List entries = new ArrayList();
+
+    public List getEntries() {
+        return entries;
+    }
+
+    public void setEntries(List entries) {
+        this.entries = entries;
+    }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    public static class MarineWordingEntry {
+        @XmlAttribute(name = "match")
+        private String matchText;
+        @XmlAttribute(name = "replace")
+        private String replacementText;
+
+        private Pattern ugcPattern;
+
+        public String getMatchText() {
+            return matchText;
+        }
+
+        public void setMatchText(String matchText) {
+            this.matchText = matchText;
+            this.ugcPattern = null;
+        }
+
+        public String getReplacementText() {
+            return replacementText;
+        }
+
+        public void setReplacementText(String replacementText) {
+            this.replacementText = replacementText;
+        }
+
+        public Pattern getUgcPattern() {
+            if (ugcPattern == null) {
+                if (matchText != null) {
+                    ugcPattern = Pattern.compile(matchText);
+                }
+            }
+            return ugcPattern;
+        }
+    }
+
+    private static final SingleTypeJAXBManager jaxb = SingleTypeJAXBManager
+            .createWithoutException(MarineWordingConfiguration.class);
+
+
+    public static MarineWordingConfiguration load(WarngenLayer forLayer) throws Exception {
+        String xmlText = WarnFileUtil.convertFileContentsToString(FILE_NAME,
+                LocalizationManager.getInstance().getCurrentSite(),
+                forLayer.getLocalizedSite());
+
+        MarineWordingConfiguration config = (MarineWordingConfiguration)
+                jaxb.unmarshalFromXml(xmlText);
+        for (MarineWordingEntry entry : config.getEntries()) {
+            // Validate patterns by compiling now.
+            entry.getUgcPattern();
+        }
+        return config;
+    }
+
+}
diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Watch.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Watch.java
index 78c1630ca5..c3707a34b5 100644
--- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Watch.java
+++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Watch.java
@@ -33,6 +33,7 @@ import java.util.List;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Jul 16, 2014 3419       jsanchez     Initial creation
+ * Aug 28, 2014 ASM #15658 D. Friedman  Add marine zone list.
  * 
  * 
* @@ -58,6 +59,8 @@ public class Watch { private List partOfState; + private List marineAreas; + public Watch(String state, String action, String phenSig, String etn, Date startTime, Date endTime) { this.state = state; @@ -132,6 +135,14 @@ public class Watch { this.etn = etn; } + public List getMarineAreas() { + return marineAreas; + } + + public void setMarineAreas(List marineAreas) { + this.marineAreas = marineAreas; + } + @Override public int hashCode() { final int prime = 31; diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/WatchUtil.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/WatchUtil.java index 029717e702..59b08b19cc 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/WatchUtil.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/WatchUtil.java @@ -54,8 +54,11 @@ import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.uf.common.util.Pair; +import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.requests.ThriftClient; import com.raytheon.viz.core.mode.CAVEMode; +import com.raytheon.viz.warngen.gis.MarineWordingConfiguration.MarineWordingEntry; import com.raytheon.viz.warngen.gui.WarngenLayer; import com.raytheon.viz.warngen.gui.WarngenLayer.GeoFeatureType; import com.vividsolutions.jts.geom.Geometry; @@ -72,6 +75,7 @@ import com.vividsolutions.jts.geom.Polygon; * ------------ ---------- ----------- -------------------------- * Jul 17, 2014 3419 jsanchez Initial creation * Aug 20, 2014 ASM #16703 D. Friedman Ensure watches have a state attribute. + * Aug 28, 2014 ASM #15658 D. Friedman Add marine zones. * * * @@ -106,10 +110,16 @@ public class WatchUtil { private static final String COUNTY_FE_AREA_FIELD = "FE_AREA"; + private static final Object MARINE_ZONE_UGC_FIELD = "ID"; + + private static final Object MARINE_ZONE_NAME_FIELD = "NAME"; + private static final String STATE_FIELD = "STATE"; private static final String COUNTY_TABLE = "County"; + private static final String MARINE_ZONE_TABLE = "MarineZones"; + private static final String PARENT_NAME_FIELD = "NAME"; private static final String[] REQUEST_FIELDS = new String[] { @@ -118,8 +128,12 @@ public class WatchUtil { private GeospatialData[] countyGeoData; + private GeospatialData[] marineGeoData; + private WarngenLayer warngenLayer; + private MarineWordingConfiguration marineWordingConfig; + public WatchUtil(WarngenLayer warngenLayer) throws InstantiationException { countyGeoData = warngenLayer.getGeodataFeatures(COUNTY_TABLE, warngenLayer.getLocalizedSite()); @@ -155,6 +169,17 @@ public class WatchUtil { Validate.isTrue(watchAreaBuffer >= 0, "'includedWatchAreaBuffer' can not be negative in .xml file"); + if (config.isIncludeMarineAreasInWatches()) { + marineGeoData = warngenLayer.getGeodataFeatures(MARINE_ZONE_TABLE, + warngenLayer.getLocalizedSite()); + if (marineGeoData == null) { + throw new VizException("Cannot get geospatial data for " + + MARINE_ZONE_TABLE + "-based watches"); + } + + marineWordingConfig = MarineWordingConfiguration.load(warngenLayer); + } + String[] includedWatches = config.getIncludedWatches(); if ((includedWatches != null) && (includedWatches.length > 0)) { @@ -174,10 +199,16 @@ public class WatchUtil { entityClass = PracticeActiveTableRecord.class; } + HashSet allUgcs = new HashSet( + warngenLayer.getAllUgcs(GeoFeatureType.COUNTY)); + Set marineUgcs = null; + if (config.isIncludeMarineAreasInWatches()) { + marineUgcs = warngenLayer.getAllUgcs(GeoFeatureType.MARINE); + allUgcs.addAll(marineUgcs); + } + DbQueryRequest request = buildRequest(simulatedTime, - phenSigConstraint.toString(), - warngenLayer.getAllUgcs(GeoFeatureType.COUNTY), - entityClass); + phenSigConstraint.toString(), allUgcs, entityClass); DbQueryResponse response = (DbQueryResponse) ThriftClient .sendRequest(request); @@ -192,9 +223,14 @@ public class WatchUtil { / KmToDegrees); System.out.println("create watch area buffer time: " + (System.currentTimeMillis() - t0)); - Set validUgcZones = warngenLayer - .getUgcsForWatches(watchArea, GeoFeatureType.COUNTY); - watches = processRecords(records, validUgcZones); + HashSet validUgcZones = new HashSet( + warngenLayer.getUgcsForWatches(watchArea, + GeoFeatureType.COUNTY)); + if (config.isIncludeMarineAreasInWatches()) { + validUgcZones.addAll(warngenLayer.getUgcsForWatches( + watchArea, GeoFeatureType.MARINE)); + } + watches = processRecords(records, validUgcZones, marineUgcs); } catch (RuntimeException e) { statusHandler .handle(Priority.ERROR, @@ -302,12 +338,13 @@ public class WatchUtil { * * @param activeTableRecords * @param validUgcZones + * @param marineUgcs * * @return */ private List processRecords( List activeTableRecords, - Set validUgcZones) { + Set validUgcZones, Set marineUgcs) { List watches = new ArrayList(); /* @@ -329,14 +366,16 @@ public class WatchUtil { * validUgcZones here. */ String ugcZone = ar.getUgcZone(); - String state = getStateName(ugcZone.substring(0, 2)); + String state = null; - /* - * Temporary fix for SS DR #16703. Remove when marine watch wording - * is fixed. - */ - if (state == null) - continue; + if (marineUgcs != null && marineUgcs.contains(ugcZone)) { + // Just leave state == null + } else { + state = getStateName(ugcZone.substring(0, 2)); + if (state == null) { + continue; + } + } String action = ar.getAct(); String phenSig = ar.getPhensig(); @@ -360,9 +399,13 @@ public class WatchUtil { for (Entry> entry : map.entrySet()) { Watch watch = entry.getKey(); watch.setAreas(entry.getValue()); - List partOfState = new ArrayList( - determineAffectedPortions(watch.getAreas())); - watch.setPartOfState(partOfState); + if (watch.getState() != null) { + List partOfState = new ArrayList( + determineAffectedPortions(watch.getAreas())); + watch.setPartOfState(partOfState); + } else { + watch.setMarineAreas(determineMarineAreas(watch.getAreas())); + } watches.add(watch); } @@ -412,6 +455,40 @@ public class WatchUtil { return affectedPortions; } + private List determineMarineAreas(List areas) { + HashSet> groupedAreas = new HashSet>(); + for (String area : areas) { + int entryIndex = 0; + for (MarineWordingEntry entry : marineWordingConfig.getEntries()) { + if (entry.getUgcPattern().matcher(area).matches()) { + String replacement = entry.getReplacementText(); + if (replacement != null) { + if (replacement.length() > 0) { + groupedAreas.add(new Pair( + entryIndex, entry.getReplacementText())); + } + } else { + groupedAreas.add(new Pair(entryIndex, + getMarineZoneName(area))); + } + } + entryIndex++; + } + } + ArrayList> sorted = new ArrayList>(groupedAreas); + Collections.sort(sorted, new Comparator>() { + public int compare(Pair o1, Pair o2) { + int r = o1.getFirst().compareTo(o2.getFirst()); + return r != 0 ? r : o1.getSecond().compareTo(o2.getSecond()); + }; + }); + ArrayList result = new ArrayList(sorted.size()); + for (Pair value : sorted) { + result.add(value.getSecond()); + } + return result; + } + /** * Returns the full state name from the state abbreviation. * @@ -446,6 +523,16 @@ public class WatchUtil { return null; } + private String getMarineZoneName(String ugc) { + for (GeospatialData g : marineGeoData) { + if (((String) g.attributes.get(MARINE_ZONE_UGC_FIELD)) + .endsWith(ugc)) { + return (String) g.attributes.get(MARINE_ZONE_NAME_FIELD); + } + } + return null; + } + // Based on AWIPS 1 SELSparagraphs.C SELSparagraphs::processWOU(). private String mungeFeAreas(Set feAreas) { String abrev = ""; diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/WarngenConfiguration.java b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/WarngenConfiguration.java index b6c6aff962..8259893bc7 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/WarngenConfiguration.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/config/WarngenConfiguration.java @@ -61,6 +61,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * Apr 24, 2013 1943 jsanchez Marked areaConfig as Deprecated. * Oct 22, 2013 2361 njensen Removed ISerializableObject * Apr 28, 2014 3033 jsanchez Properly handled back up configuration (*.xml) files. + * Aug 28, 2014 ASM #15658 D. Friedman Add marine zone watch wording option. * * * @author chammack @@ -103,6 +104,9 @@ public class WarngenConfiguration { @XmlElement(name = "includedWatch") private String[] includedWatches; + @XmlElement + private boolean includeMarineAreasInWatches; + @XmlElementWrapper(name = "durations") @XmlElement(name = "duration") private int[] durations; @@ -392,6 +396,14 @@ public class WarngenConfiguration { return includedWatches; } + public boolean isIncludeMarineAreasInWatches() { + return includeMarineAreasInWatches; + } + + public void setIncludeMarineAreasInWatches(boolean includeMarineAreasInWatches) { + this.includeMarineAreasInWatches = includeMarineAreasInWatches; + } + public boolean getEnableRestart() { return enableRestart; } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/VM_global_library.vm b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/VM_global_library.vm index 370ca5642e..135c9cb058 100755 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/VM_global_library.vm +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/VM_global_library.vm @@ -11,7 +11,8 @@ ##### Evan Bookbinder 05-05-2013 handleClosesPoints and 3rd bullet changes (OVER & now) ##### Evan Bookbinder 09-20-2013 Fixed rural area otherPoints in pathcast section, added rural phrase ##### Qinglu Lin 03-17-2014 DR 16309. Updated inserttorwatches and insertsvrwatches. -##### Qinglu Lin 05-21-2014 DR 16309. Updated inserttorwatches and insertsvrwatches by changing 'FOR##' to 'FOR ##'. +##### Qinglu Lin 05-21-2014 DR 16309. Updated inserttorwatches and insertsvrwatches by changing 'FOR##' to 'FOR ##'. +##### D. Friedman 08-28-2014 ASM #15658. Add marine watch wording. #################################################################################################### #* Mile Marker Test Code @@ -218,7 +219,11 @@ ${dateUtil.period(${tornadoWatch.endTime},${timeFormat.plain}, 15, ${localtimezo #set($count = 0) #foreach(${watch} in ${tornadoWatches}) #set($count = $count + 1) +#if(!${watch.marineAreas}) #areaFormat(${watch.partOfState} true false true)${watch.state}## +#else +#formatMarineAreas(${watch.marineAreas}) +#end #if($count == $numPortions - 1) AND ## #elseif($count < $numPortions) @@ -263,7 +268,11 @@ ${dateUtil.period(${svrWatch.endTime},${timeFormat.plain}, 15, ${localtimezone}) #set($count = 0) #foreach(${watch} in ${severeWatches}) #set($count = $count + 1) +#if(!${watch.marineAreas}) #areaFormat(${watch.partOfState} true false true)${watch.state}## +#else +#formatMarineAreas(${watch.marineAreas}) +#end #if($count == $numPortions - 1) AND ## #elseif($count < $numPortions) @@ -278,6 +287,25 @@ ${dateUtil.period(${svrWatch.endTime},${timeFormat.plain}, 15, ${localtimezone}) #end ########END +#macro(formatMarineAreas $marineAreas) +#set($macount = 0) +#set($numMarineAreas = ${list.size(${marineAreas})}) +#foreach(${marineArea} in ${marineAreas}) +#set($macount = $macount + 1) +#if(${marineArea}=="THE ADJACENT COASTAL WATERS" && $macount > 1) +OTHER ADJACENT COASTAL WATERS## +#else +${marineArea}## +#end +#if($macount == $numMarineAreas - 1) + AND ## +#elseif($macount < $numMarineAreas) +...## +#end +#end +#end +########END MACRO + #macro(printcoords $coordinates $list) #set($count = 0) LAT...LON ## diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/marineWeatherStatement.xml b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/marineWeatherStatement.xml index 1b741dadd6..8e3877eb75 100755 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/marineWeatherStatement.xml +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/marineWeatherStatement.xml @@ -58,6 +58,9 @@ turned on unless the corresponding .vm file is turned on in a given template's . SV.A + + true + 60 diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/marineZoneWording.xml b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/marineZoneWording.xml new file mode 100644 index 0000000000..a61fd52788 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/marineZoneWording.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/specialMarineWarning.xml b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/specialMarineWarning.xml index a34a8dfd89..fd651f94e2 100755 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/specialMarineWarning.xml +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/specialMarineWarning.xml @@ -61,6 +61,9 @@ turned on unless the corresponding .vm file is turned on in a given template's . SV.A + + true + 30 diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/specialMarineWarningFollowup.xml b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/specialMarineWarningFollowup.xml index cffaf9a764..dc4c01d0cd 100755 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/specialMarineWarningFollowup.xml +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/specialMarineWarningFollowup.xml @@ -63,6 +63,9 @@ turned on unless the corresponding .vm file is turned on in a given template's . SV.A + + true + 30 From eb9b743c469f628a3cd6daa7ab5496f29a4855ce Mon Sep 17 00:00:00 2001 From: "Daniel.Huffman" Date: Thu, 28 Aug 2014 17:20:30 +0000 Subject: [PATCH 3/5] ASM #16715 - Reverted and augmented Airports.xml and Fix.xml Change-Id: Icd15e1947ec7d71b22d621b452d9e1c74767898e Former-commit-id: c3731d56220331b083f485e001df31f2dae02d16 [formerly c89a7169b04d5e1dc70d61a3bbe30d1aeb2c81e4] [formerly ca2aa8811b28e393a873a043b1d479b1cd9550cd [formerly 09e0b79b25ec4f8854dde331469b0e7d6c4ffa1f]] Former-commit-id: ca2aa8811b28e393a873a043b1d479b1cd9550cd Former-commit-id: dc2bc16bcc56309d0ffa5d0311ebc841666b88eb --- .../bundles/maps/FAA/Airports.xml | 32 ----------------- .../localization/bundles/maps/FAA/Fix.xml | 34 ------------------- 2 files changed, 66 deletions(-) diff --git a/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/FAA/Airports.xml b/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/FAA/Airports.xml index f76d3207ae..579e5ccbcc 100644 --- a/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/FAA/Airports.xml +++ b/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/FAA/Airports.xml @@ -22,35 +22,6 @@ - - - - - - - PLAN_VIEW - - - - - - - - - - - PLAN_VIEW - - - - - - mapdata.airport
- Airports -
-
@@ -66,9 +37,6 @@ airport.lpi Airports - - - Airports
diff --git a/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/FAA/Fix.xml b/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/FAA/Fix.xml index b4cab44690..9db555024b 100644 --- a/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/FAA/Fix.xml +++ b/cave/com.raytheon.uf.viz.core.maps/localization/bundles/maps/FAA/Fix.xml @@ -22,37 +22,6 @@ - - - - - - - PLAN_VIEW - - - - - - - - - - - - PLAN_VIEW - - - - - - mapdata.fix
- Fixes/Intersections - type != 'NU' -
-
@@ -70,9 +39,6 @@ Fixes/Intersections
- Fixes/Intersections -
- From b2cc41f3de558bcca4a8f0d2bd2a2f517bcbccf8 Mon Sep 17 00:00:00 2001 From: David Friedman Date: Thu, 28 Aug 2014 18:08:23 +0000 Subject: [PATCH 4/5] ASM #15682 - D-2D: SPC Watches display: Watches do not disappear when expired Change-Id: I3a29b5b0bb5c75dd5ac5f508391f5806cabf47fa Former-commit-id: 9c2545ed64c40dcbb9c662f8199297bce1996d28 [formerly de6e79f9e381e7f2cda70104216b5729dabaa507] [formerly d5c086a0226ce234d8d8a6d3f577b003423e39d5 [formerly aca832a81bc18d954eadb51755ce04597cd264df]] Former-commit-id: d5c086a0226ce234d8d8a6d3f577b003423e39d5 Former-commit-id: 6209bbc36f704fb7a965d1ffce9fee4f687e08cb --- .../bundles/ncepHydro/ConvectiveWatchPlot.xml | 29 ++ .../menus/ncepHydro/spc/baseSPC.xml | 4 +- .../viz/warnings/rsc/WWAResourceData.java | 17 +- .../viz/warnings/rsc/WatchesResource.java | 2 +- .../warnings/rsc/WouWcnWatchesResource.java | 429 ++++++++++++++++++ .../rsc/WouWcnWatchesResourceData.java | 56 +++ 6 files changed, 530 insertions(+), 7 deletions(-) create mode 100644 cave/com.raytheon.uf.viz.d2d.ui.ncephydro/localization/bundles/ncepHydro/ConvectiveWatchPlot.xml create mode 100644 cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WouWcnWatchesResource.java create mode 100644 cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WouWcnWatchesResourceData.java diff --git a/cave/com.raytheon.uf.viz.d2d.ui.ncephydro/localization/bundles/ncepHydro/ConvectiveWatchPlot.xml b/cave/com.raytheon.uf.viz.d2d.ui.ncephydro/localization/bundles/ncepHydro/ConvectiveWatchPlot.xml new file mode 100644 index 0000000000..01d6f48442 --- /dev/null +++ b/cave/com.raytheon.uf.viz.d2d.ui.ncephydro/localization/bundles/ncepHydro/ConvectiveWatchPlot.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cave/com.raytheon.uf.viz.d2d.ui.ncephydro/localization/menus/ncepHydro/spc/baseSPC.xml b/cave/com.raytheon.uf.viz.d2d.ui.ncephydro/localization/menus/ncepHydro/spc/baseSPC.xml index 535f7795f2..b3ed96c9c5 100644 --- a/cave/com.raytheon.uf.viz.d2d.ui.ncephydro/localization/menus/ncepHydro/spc/baseSPC.xml +++ b/cave/com.raytheon.uf.viz.d2d.ui.ncephydro/localization/menus/ncepHydro/spc/baseSPC.xml @@ -20,8 +20,8 @@ --> - + diff --git a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java index ac3b495abc..ade59795fd 100644 --- a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java +++ b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WWAResourceData.java @@ -42,6 +42,7 @@ import com.raytheon.viz.core.mode.CAVEMode; * May 3, 2011 jsanchez Initial creation * Oct 25, 2013 2249 rferrel getAvailableTimes always returns a non-empty list. * Apr 28, 2014 DR 17310 D. Friedman Handle null VTEC fields. + * Aug 28, 2014 ASM #15682 D. Friedman Refactor for WouWcnWatchesResourceData. * * * @@ -98,13 +99,13 @@ public class WWAResourceData extends AbstractRequestableResourceData { @Override public DataTime[] getAvailableTimes() throws VizException { - DataTime[] available = getAvailableTimes(getMetadataMap(), + DataTime[] available = getAvailableWarningTimes(getMetadataMap(), getBinOffset()); return available; } - public static DataTime[] getAvailableTimes( + public DataTime[] getAvailableWarningTimes( Map constraintMap, BinOffset binOffset) throws VizException { DbQueryResponse response = null; @@ -116,8 +117,9 @@ public class WWAResourceData extends AbstractRequestableResourceData { String etn = "etn"; String phensig = "phensig"; String act = "act"; + String pil = "pil"; request.addFields(new String[] { startTimeField, endTimeField, act, - etn, phensig }); + etn, phensig, pil }); response = (DbQueryResponse) ThriftClient.sendRequest(request); if (response.getResults() == null) { @@ -137,7 +139,10 @@ public class WWAResourceData extends AbstractRequestableResourceData { warnRec.setAct((String) map.get(act)); warnRec.setPhensig((String) map.get(phensig)); warnRec.setEtn((String) map.get(etn)); - warnings.add(warnRec); + warnRec.setPil((String) map.get(pil)); + if (isRecordTimeImportant(warnRec)) { + warnings.add(warnRec); + } } RequestConstraint phenSig = constraintMap.get("phensig"); @@ -165,6 +170,10 @@ public class WWAResourceData extends AbstractRequestableResourceData { return availableTimes; } + protected boolean isRecordTimeImportant(AbstractWarningRecord warnRec) { + return true; + } + private static TreeSet getWarningStartTimes( ArrayList warnings) { /* diff --git a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WatchesResource.java b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WatchesResource.java index 1494ac5034..85d5bf47b2 100644 --- a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WatchesResource.java +++ b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WatchesResource.java @@ -290,7 +290,7 @@ public class WatchesResource extends AbstractWWAResource { } } - private void setGeometry(AbstractWarningRecord record) { + protected void setGeometry(AbstractWarningRecord record) { List county = new ArrayList(); List marinezone = new ArrayList(); List geometries = new ArrayList(); diff --git a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WouWcnWatchesResource.java b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WouWcnWatchesResource.java new file mode 100644 index 0000000000..a6374b1e0d --- /dev/null +++ b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WouWcnWatchesResource.java @@ -0,0 +1,429 @@ +package com.raytheon.viz.warnings.rsc; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; + +import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord; +import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction; +import com.raytheon.uf.common.time.ISimulatedTimeChangeListener; +import com.raytheon.uf.common.time.SimulatedTime; +import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.drawables.FillPatterns; +import com.raytheon.uf.viz.core.drawables.IShadedShape; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.rsc.LoadProperties; +import com.raytheon.viz.core.rsc.jts.JTSCompiler; +import com.raytheon.viz.core.rsc.jts.JTSCompiler.PointStyle; +import com.vividsolutions.jts.geom.Geometry; + +/** + * Displays WOUs updated by WCNs + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * 2014-08-28   ASM #15682 D. Friemdan Initial creation
+ * 
+ * + */ +public class WouWcnWatchesResource extends WatchesResource implements ISimulatedTimeChangeListener { + + private static Timer timer; + + private TimerTask timerTask; + + // If this is changed to use the maps database, could probably be static + private Map> cwaUgcMap = new HashMap>(); + + static final ThreadLocal sdf = new ThreadLocal() { + @Override protected SimpleDateFormat initialValue() { + return new SimpleDateFormat("yyyyMMddHHmm"); + } + }; + + public WouWcnWatchesResource(WWAResourceData data, LoadProperties props) { + super(data, props); + comparator = WouWcnWatchesComparator.getInstance(); + resourceName = "Watches"; + } + + private AbstractWarningRecord getPreviousRecordForEvent(AbstractWarningRecord rec) { + String phenSig = rec.getPhensig(); + String etn = rec.getEtn(); + if (phenSig == null || etn == null) + return null; + AbstractWarningRecord best = null; + for (WarningEntry e : entryMap.values()) { + if (!phenSig.equals(e.record.getPhensig()) || + !etn.equals(e.record.getEtn())) + continue; + + if (best == null || WouWcnWatchesComparator.getInstance(). + compare(best, e.record) < 0) { + best = e.record; + } + } + return best; + } + + private Set maskCwaUgcs(Set ugcs, AbstractWarningRecord rec) { + Set cwaUgcs = getUgcsForCwa(rec.getXxxid()); + if (cwaUgcs != null) { + HashSet result = new HashSet(ugcs); + result.removeAll(cwaUgcs); + return result; + } else { + return ugcs; + } + } + + private Set getUgcsForCwa(String cwa) { + return cwaUgcMap.get(cwa.toUpperCase()); + } + + private Set safe(Set set) { + return set != null ? set : new HashSet(); + } + + @Override + protected void updateDisplay(IGraphicsTarget target) throws VizException { + if (recordsToLoad.isEmpty()) + return; + + List mergedWatches = mergeWatches(recordsToLoad); + for (AbstractWarningRecord watchRec : mergedWatches) { + /* If these things are missing, we can't do anything with the warning. */ + if (watchRec.getPhensig() == null || watchRec.getEtn() == null || + watchRec.getIssueTime() == null || watchRec.getStartTime() == null || + watchRec.getEndTime() == null || watchRec.getXxxid() == null || + watchRec.getWmoid() == null || watchRec.getAct() == null) { + continue; + } + + WarningAction watchAct = WarningAction.valueOf(watchRec.getAct()); + + AbstractWarningRecord createShape = null; + boolean isWOU = "WOU".equals(watchRec.getPil()); + + AbstractWarningRecord prevRec = getPreviousRecordForEvent(watchRec); + Set prevUgcs = new HashSet(safe( + prevRec != null ? prevRec.getUgcZones() : null)); + Set newUgcs = null; + + if (watchAct == WarningAction.NEW) { + if (isWOU) { + createShape = watchRec; + } else { + noteCwaUgcs(watchRec); + // As per requirements, we do not create frames for these. + } + } else if (watchAct == WarningAction.CON && isWOU) { + // As per requirements, we do not create frames for these. + } else if (watchAct == WarningAction.CON) { + /* No need to do anything because we really only care about + * the segments paired with the CON. + */ + } else if (watchAct == WarningAction.CAN) { + /* Not really expecting this for a WOU, but shouldn't cause + * a problem if there is one. + */ + newUgcs = prevUgcs; + newUgcs.removeAll(safe(watchRec.getUgcZones())); + createShape = watchRec; + } else if (watchAct == WarningAction.EXA || watchAct == WarningAction.EXB) { + if (!isWOU) { + noteCwaUgcs(watchRec); + } + newUgcs = prevUgcs; + newUgcs.addAll(safe(watchRec.getUgcZones())); + createShape = watchRec; + } else if (watchAct == WarningAction.EXP) { + if (isWOU) { + if (prevRec != null) { + if (! prevRec.getEndTime().equals(watchRec.getEndTime())) { + prevRec.setEndTime(watchRec.getEndTime()); + } + } + /* + * Ideally we do not need to create a shape, but if we do + * not and time matching creates a frame for an EXP that is + * issued before the expiration time, the warning would show + * as still active on that frame. + */ + newUgcs = new HashSet(); + createShape = watchRec; + } else { + newUgcs = maskCwaUgcs(prevUgcs, watchRec); + createShape = watchRec; + } + } + if (watchAct == WarningAction.EXT || watchAct == WarningAction.EXB) { + /* This resource does not handle different expiration times + * for different UGCs. + * + * Also assuming this does not add/remove UGCs. + */ + if (prevRec != null && watchRec.getEndTime() != null) { + if (isWOU && watchRec.getUgcZones() != null && watchRec.getUgcZones().isEmpty()) { + /* + * This probably does not actually happen, but this + * is the only way we can support shortening the + * expiration time with the current design. + */ + prevRec.setEndTime(watchRec.getEndTime()); + } else { + if (prevRec.getEndTime().before(watchRec.getEndTime())) { + prevRec.setEndTime(watchRec.getEndTime()); + } + } + } + } + + if (createShape != null) { + if (newUgcs != null) + createShape.setUgcZones(newUgcs); + else if (createShape.getUgcZones() == null) + createShape.setUgcZones(new HashSet()); + insertShape(target, createShape); + } + } + + recordsToLoad.clear(); + scheduleNextTime(); + } + + + @Override + protected void initShape(IGraphicsTarget target, + AbstractWarningRecord record) throws VizException { + String key = getEntryMapKey(record); + WarningEntry entry = entryMap.get(key); + if (entry != null) { + createShape(target, entry); + } + } + + protected void insertShape(IGraphicsTarget target, AbstractWarningRecord record) throws VizException { + String key = getEntryMapKey(record); + WarningEntry entry = entryMap.get(key); + if (entry == null) { + entry = new WarningEntry(); + entryMap.put(key, entry); + } + entry.record = record; // ...possibly replacing an existing record + if (! record.getUgcZones().isEmpty()) { + setGeometry(record); + } else { + entry.record.setGeometry(null); + } + createShape(target, entry); + } + + protected void createShape(IGraphicsTarget target, WarningEntry entry) throws VizException { + if (entry.shadedShape != null) { + entry.shadedShape.dispose(); + entry.shadedShape = null; + } + AbstractWarningRecord record = entry.record; + if (record.getGeometry() != null) { + IShadedShape ss = target.createShadedShape(false, + descriptor.getGridGeometry(), false); + Geometry geo = (Geometry) record.getGeometry().clone(); + JTSCompiler jtsCompiler = new JTSCompiler(ss, null, + this.descriptor, PointStyle.CROSS); + jtsCompiler.handle(geo, color); + ss.setFillPattern(FillPatterns.getGLPattern(record.getPhen() + .equals("TO") ? "VERTICAL" : "HORIZONTAL")); + ss.compile(); + entry.shadedShape = ss; + } + } + + /** + * Groups all the ugc zones with the same action, phensig, ETN, site, and + * issuance time. + */ + protected List mergeWatches( + List watchrecs) { + SimpleDateFormat sdfi = sdf.get(); + + Map watches = new HashMap(); + for (AbstractWarningRecord watchrec : watchrecs) { + if (watchrec.getIssueTime() == null) + continue; + + String key = watchrec.getAct() + '.' + watchrec.getPhensig() + '.' + + watchrec.getEtn() + '.' + watchrec.getOfficeid() + '.' + + sdfi.format(watchrec.getIssueTime().getTime()); + AbstractWarningRecord watch = watches.get(key); + if (watch == null) { + watch = watchrec; + watches.put(key, watch); + } else { + Set ugcZones = watch.getUgcZones(); + if (ugcZones != null) { + ugcZones.addAll(watchrec.getUgcZones()); + } + } + } + + ArrayList mergedWatches = new ArrayList( + watches.values()); + Collections.sort(mergedWatches, comparator); + + return mergedWatches; + } + + protected String getEntryMapKey(AbstractWarningRecord rec) { + return sdf.get().format(rec.getIssueTime().getTime()) + '.' + + rec.getWmoid() + '.' + rec.getPhensig() + '.' + rec.getEtn(); + } + + @Override + protected String getEventKey(WarningEntry entry) { + AbstractWarningRecord r = entry.record; + return r.getPhensig() + '.' + r.getEtn(); + } + + private void noteCwaUgcs(AbstractWarningRecord watchRec) { + String siteKey = watchRec.getXxxid(); + Set recUgcs = watchRec.getUgcZones(); + if (siteKey == null || recUgcs == null) + return; + + synchronized (cwaUgcMap) { + Set ugcs = cwaUgcMap.get(siteKey); + if (ugcs == null) { + ugcs = new HashSet(); + cwaUgcMap.put(siteKey, ugcs); + } + ugcs.addAll(recUgcs); + } + } + + @Override + protected void disposeInternal() { + synchronized(this) { + if (timerTask != null) + timerTask.cancel(); + } + super.disposeInternal(); + } + + private void scheduleNextTime() { + /* TODO: This is a race condition. Need the last frame time, + * but getLastFrameTimeRange() is also a race condition. So really need + * last drawn last frame time, but LAST_FRAME_ADJ is an hour ahead??! + */ + long vnow = SimulatedTime.getSystemTime().getMillis(); + AbstractWarningRecord best = null; + for (WarningEntry entry : entryMap.values()) { + AbstractWarningRecord rec = entry.record; + if (rec.getEndTime().getTimeInMillis() >= vnow && + (best == null || rec.getEndTime().before(best.getEndTime()))) { + best = rec; + } + } + if (best != null) { + scheduleTimer(best.getEndTime().getTimeInMillis() - vnow); + } else { + scheduleTimer(-1); + } + } + + private synchronized void scheduleTimer(long delay) { + if (timerTask != null) { + timerTask.cancel(); + } + if (delay >= 0) { + timerTask = new WatchesTimerTask(); + getTimer().schedule(timerTask, delay); + } else { + timerTask = null; + } + } + + private Timer getTimer() { + if (timer == null) { + synchronized (WouWcnWatchesResource.class) { + if (timer == null) { + timer = new Timer(WouWcnWatchesResource.class.getName() + " Timer"); + } + } + } + return timer; + } + + @Override + public void timechanged() { + issueRefresh(); + scheduleNextTime(); + } + + protected class WatchesTimerTask extends TimerTask { + + @Override + public void run() { + timechanged(); + } + } + + protected static class WouWcnWatchesComparator implements Comparator { + + static final WouWcnWatchesComparator instance = new WouWcnWatchesComparator(); + + public static Comparator getInstance() { + return instance; + } + + @Override + public int compare(AbstractWarningRecord a, AbstractWarningRecord b) { + int r; + Calendar ca = a.getIssueTime(); + Calendar cb = b.getIssueTime(); + if (ca == null) { + if (cb == null) + r = 0; + else + return 1; + } else if (cb == null) + return -1; + else + r = ca.compareTo(cb); + if (r != 0) + return r; + + // The point of this is to handle the BBB field, but it makes the TTAAii part significant too... + String sa = safeWmo(a); + String sb = safeWmo(b); + r = sa.compareTo(sb); + if (r != 0) + return r; + + r = a.getSeg() - b.getSeg(); + if (r != 0) + return r; + + return 0; + } + } + + private static String safeWmo(AbstractWarningRecord record) { + String wmo = record.getWmoid(); + return wmo != null ? wmo : "TTAA00 CCCC 000000"; + } + +} diff --git a/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WouWcnWatchesResourceData.java b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WouWcnWatchesResourceData.java new file mode 100644 index 0000000000..b90996953a --- /dev/null +++ b/cave/com.raytheon.viz.warnings/src/com/raytheon/viz/warnings/rsc/WouWcnWatchesResourceData.java @@ -0,0 +1,56 @@ +package com.raytheon.viz.warnings.rsc; + +import java.util.ArrayList; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; + +import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord; +import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.rsc.AbstractVizResource; +import com.raytheon.uf.viz.core.rsc.LoadProperties; + +/** + * Displays WOUs updated by WCNs + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * 2014-08-28   ASM #15682 D. Friemdan Initial creation
+ * 
+ * + */ +@XmlAccessorType(XmlAccessType.NONE) +public class WouWcnWatchesResourceData extends WWAResourceData { + + @Override + protected AbstractVizResource constructResource( + LoadProperties loadProperties, PluginDataObject[] objects) + throws VizException { + // add records + records = new ArrayList(objects.length); + for (int i = 0; i < objects.length; i++) { + AbstractWarningRecord r = (AbstractWarningRecord) objects[i]; + records.add(r); + } + + return new WouWcnWatchesResource(this, loadProperties); + } + + @Override + protected boolean isRecordTimeImportant(AbstractWarningRecord warnRec) { + WarningAction act = WarningAction.valueOf(warnRec.getAct()); + if (("WOU".equals(warnRec.getPil()) && WarningAction.CON == act) || + ("WCN".equals(warnRec.getPil()) && WarningAction.NEW == act)) { + return false; + } else { + return super.isRecordTimeImportant(warnRec); + } + } +} + From 3fcdc279ea831ca0303314a33c911fe583646a5e Mon Sep 17 00:00:00 2001 From: "Qinglu.Lin" Date: Tue, 2 Sep 2014 14:33:11 -0400 Subject: [PATCH 5/5] ASM #15551 - WarnGen: only WCN should be used while including TOR/SVR watches in WarnGen products Change-Id: I286bc4cc809fcc9257f72051f1bb74f8acc24c05 Former-commit-id: b32ea402890c128b290dcf690358d2679ae4e3ae [formerly 2374673f8d7f3bb3b78a104e1031429da4a9ad84] [formerly ae13ea419e0bd42b0df7df699e030d82a4bc8988 [formerly 59890eef397f3282ef26f259ca85ffea3db7b710]] Former-commit-id: ae13ea419e0bd42b0df7df699e030d82a4bc8988 Former-commit-id: 075df9d2347dca56668611b87dc81e50cf5c7ab1 --- .../raytheon/viz/warngen/gis/WatchUtil.java | 22 ++++ .../viz/warngen/template/TemplateRunner.java | 34 +++++- .../base/warngen/VM_global_library.vm | 115 ++++++++---------- 3 files changed, 108 insertions(+), 63 deletions(-) diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/WatchUtil.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/WatchUtil.java index 59b08b19cc..2e737b386a 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/WatchUtil.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/WatchUtil.java @@ -76,6 +76,7 @@ import com.vividsolutions.jts.geom.Polygon; * Jul 17, 2014 3419 jsanchez Initial creation * Aug 20, 2014 ASM #16703 D. Friedman Ensure watches have a state attribute. * Aug 28, 2014 ASM #15658 D. Friedman Add marine zones. + * Aug 29, 2014 ASM #15551 Qinglu Lin Sorting watches by ETN in processRecords(). * * * @@ -409,6 +410,8 @@ public class WatchUtil { watches.add(watch); } + // keep the code for their use in the future + /* // Sorts the watches based on state name. Collections.sort(watches, new Comparator() { @@ -426,6 +429,25 @@ public class WatchUtil { return state1.compareTo(state2); } }); + */ + + // Sorts the watches based on ETN. + Collections.sort(watches, new Comparator() { + + @Override + public int compare(Watch watch1, Watch watch2) { + String etn1 = watch1.getEtn(); + String etn2 = watch2.getEtn(); + if (etn1 == etn2) + return 0; + else if (etn1 == null) + return 1; + else if (etn2 == null) + return -1; + else + return etn1.compareTo(etn2); + } + }); return watches; } 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 069853bc96..9373221c0b 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 @@ -141,6 +141,8 @@ import com.vividsolutions.jts.io.WKTReader; * added determineAffectedMarinePortions(). * Jul 21, 2014 3419 jsanchez Refactored WatchUtil. * Aug 15, 2014 DR15701 mgamazaychikov Removed static field watchUtil. + * Aug 28, 2014 ASM #15551 Qinglu Lin Replaced 1200 PM/1200 AM by NOON/MIDNIGHT, removed days in + * included tornado/severe thunderstorm watch message. * * * @author njensen @@ -872,7 +874,37 @@ public class TemplateRunner { System.out.println("velocity time: " + (System.currentTimeMillis() - tz0)); - String text = script.toString(); + String watches[] = {"TORNADO WATCH", "SEVERE THUNDERSTORM WATCH"}; + int index1 = -1, index2 = -1, index1ToUse = -1; + String doubleDollar = "$$"; + boolean firstTime = true; + for (String s: watches) { + index1 = script.indexOf(s, 0); + if (index1 > 0) { + index2 = script.indexOf(doubleDollar, index1); + } + if (firstTime && index1 > -1) { + index1ToUse = index1; + firstTime = false; + } + } + String days[] = {"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"}; + String substring = "", text; + if (index1ToUse > -1 && index2 > -1) { + substring = script.substring(index1ToUse, index2).toUpperCase(); + // remove day + for (String day: days) { + substring = substring.replaceAll(day + " ", ""); + } + // replace 1200 PM/1200 AM with NOON/MIDNIGHT + substring = substring.replaceAll("1200 PM", "NOON"); + substring = substring.replaceAll("1200 AM", "MIDNIGHT"); + // concatenate strings + text = script.substring(0, index1ToUse - 1); + text = text + " " + substring + script.substring(index2, script.length()); + } else { + text = script.toString(); + } WarningTextHandler handler = WarningTextHandlerFactory.getHandler( selectedAction, text, config.getAutoLockText()); String handledText = handler.handle(text, areas, cancelareas, diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/VM_global_library.vm b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/VM_global_library.vm index 135c9cb058..baed0cfbbd 100755 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/VM_global_library.vm +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/VM_global_library.vm @@ -13,6 +13,7 @@ ##### Qinglu Lin 03-17-2014 DR 16309. Updated inserttorwatches and insertsvrwatches. ##### Qinglu Lin 05-21-2014 DR 16309. Updated inserttorwatches and insertsvrwatches by changing 'FOR##' to 'FOR ##'. ##### D. Friedman 08-28-2014 ASM #15658. Add marine watch wording. +##### Qinglu Lin 08-29-2014 ASM #15551. Overhauled inserttorwatches and insertsvrwatches. #################################################################################################### #* Mile Marker Test Code @@ -190,102 +191,92 @@ ${drainage.name}## ########END MACRO #macro(inserttorwatches $watches $list $secondtimezone $dateUtil $timeFormat) -#set($keys = []) -#set($mymap = {}) +#set($tornadoWatches = []) +#set($ALSO = "") + #foreach(${watch} in ${watches}) #if(${watch.getPhenSig()} == 'TO.A') -#set($key = ${watch.action} + ${watch.etn} + ${watch.startTime} + ${watch.endTime}) -#if (${list.contains(${keys}, $key)}) -#set($value = ${mymap.get($key)}) +#set($success = $tornadoWatches.add($watch)) +#end +#end + +#set($lastEtn = "") +#set($lastEndTime = "") +#foreach(${watch} in ${tornadoWatches}) +#if($lastEtn != "" && ${watch.etn} != ${lastEtn}) +. ## +#end +#set($endTime = ${watch.endTime}) +#if(${watch.etn} == ${lastEtn}) +#if(${endTime} == ${lastEndTime}) +...## #else -#set($value = []) -#set($success = $keys.add($key)) +...UNTIL ${dateUtil.format(${endTime}, ${timeFormat.plain}, 15, ${localtimezone})} FOR ## #end -#set($success = $value.add($watch)) -#set($success = ${mymap.put($key,$value)}) +#else +A TORNADO WATCH${ALSO} REMAINS IN EFFECT UNTIL ${dateUtil.format(${endTime}, ${timeFormat.plain}, 15, ${localtimezone})} FOR ## +#set($ALSO = " ALSO") #end -#end -#set($torWatchAlso = "") -#foreach(${key} in ${keys}) -#set($tornadoWatches = ${mymap.get($key)}) -#set($tornadoWatch = ${tornadoWatches.get(0)}) -A TORNADO WATCH ${torWatchAlso}REMAINS IN EFFECT UNTIL ${dateUtil.format(${tornadoWatch.endTime}, ${timeFormat.plain}, 15, ${localtimezone})}## -${dateUtil.period(${tornadoWatch.endTime},${timeFormat.plain}, 15, ${localtimezone})}## #if(${secondtimezone}) /${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${secondtimezone})}/## #end - FOR ## -#set($numPortions = ${list.size(${tornadoWatches})}) -#set($count = 0) -#foreach(${watch} in ${tornadoWatches}) -#set($count = $count + 1) #if(!${watch.marineAreas}) #areaFormat(${watch.partOfState} true false true)${watch.state}## #else #formatMarineAreas(${watch.marineAreas}) #end -#if($count == $numPortions - 1) - AND ## -#elseif($count < $numPortions) -...## +#set($lastEtn = ${watch.etn}) +#set($lastEndTime = ${watch.endTime}) #end +#if(${lastEtn} != "") +. #end -#set($torWatchAlso = "ALSO ") -. ## -#end - - #end ########END MACRO #macro(insertsvrwatches $watches $list $secondtimezone $dateUtil $timeFormat) -#set($keys = []) -#set($mymap = {}) +#set($svrWatches = []) +#set($ALSO = "") + #foreach(${watch} in ${watches}) #if(${watch.getPhenSig()} == 'SV.A') -#set($key = ${watch.action} + ${watch.etn} + ${watch.startTime} + ${watch.endTime}) -#if (${list.contains(${keys}, $key)}) -#set($value = ${mymap.get($key)}) +#set($success = $svrWatches.add($watch)) +#end +#end + +#set($lastEtn = "") +#set($lastEndTime = "") +#foreach(${watch} in ${svrWatches}) +#if($lastEtn != "" && ${watch.etn} != ${lastEtn}) +. ## +#end +#set($endTime = ${watch.endTime}) +#if(${watch.etn} == ${lastEtn}) +#if(${endTime} == ${lastEndTime}) +...## #else -#set($value = []) -#set($success = $keys.add($key)) +...UNTIL ${dateUtil.format(${endTime}, ${timeFormat.plain}, 15, ${localtimezone})} FOR ## #end -#set($success = $value.add($watch)) -#set($success = ${mymap.put($key,$value)}) +#else +A SEVERE THUNDERSTORM WATCH${ALSO} REMAINS IN EFFECT UNTIL ${dateUtil.format(${endTime}, ${timeFormat.plain}, 15, ${localtimezone})} FOR ## +#set($ALSO = " ALSO") #end -#end -#set($svrWatchAlso = "") -#foreach(${key} in ${keys}) -#set($severeWatches = ${mymap.get($key)}) -#set($svrWatch = ${severeWatches.get(0)}) -A SEVERE THUNDERSTORM WATCH ${svrWatchAlso}REMAINS IN EFFECT UNTIL ${dateUtil.format(${svrWatch.endTime}, ${timeFormat.plain}, 15, ${localtimezone})}## -${dateUtil.period(${svrWatch.endTime},${timeFormat.plain}, 15, ${localtimezone})}## #if(${secondtimezone}) /${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${secondtimezone})}/## #end - FOR ## -#set($numPortions = ${list.size(${severeWatches})}) -#set($count = 0) -#foreach(${watch} in ${severeWatches}) -#set($count = $count + 1) #if(!${watch.marineAreas}) #areaFormat(${watch.partOfState} true false true)${watch.state}## #else #formatMarineAreas(${watch.marineAreas}) #end -#if($count == $numPortions - 1) - AND ## -#elseif($count < $numPortions) -...## +#set($lastEtn = ${watch.etn}) +#set($lastEndTime = ${watch.endTime}) +#end +#if(${lastEtn} != "") +. #end #end -#set($svrWatchAlso = "ALSO ") -. ## -#end - - -#end -########END +########END MACRO #macro(formatMarineAreas $marineAreas) #set($macount = 0)