CM-MERGE:14.1.3-2,-3 into 14.2.2

Merge branch 'master_14.1.3' (-3) into master_14.2.2 (-14)

Conflicts:
	edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-request.xml
	edexOsgi/com.raytheon.edex.plugin.gfe/res/spring/gfe-spring.xml
	edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/spc/SPCWatchSrv.java
	edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/tpc/TPCWatchSrv.java
	edexOsgi/com.raytheon.edex.plugin.gfe/test/com/raytheon/edex/plugin/gfe/watch/TestWCLWatchSrv.java
	edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py
	edexOsgi/com.raytheon.uf.common.dataplugin.warning/src/com/raytheon/uf/common/dataplugin/warning/gis/GeospatialFactory.java

Former-commit-id: 419c5f4aba [formerly 16f5ff0979 [formerly b84dda5930] [formerly 419c5f4aba [formerly ce5767f2bbf5c9627bd43e766c6193c261c48af3]]]
Former-commit-id: 16f5ff0979 [formerly b84dda5930]
Former-commit-id: 16f5ff0979
Former-commit-id: 869235c02a
This commit is contained in:
Steve Harris 2014-06-18 13:24:39 -05:00 committed by Brian.Dyke
commit 37b3b421db
25 changed files with 957 additions and 530 deletions

View file

@ -102,6 +102,8 @@ import com.vividsolutions.jts.geom.LineString;
* count changes; made line width configurable.
* 04-07-2014 DR 17232 D. Friedman Make sure pivot indexes are valid.
* 06-03-14 3191 njensen Fix postData to not retrieve
* 06-17-2014 DR17409 mgamazaychikov Fix futurePoints calculation in generateNewTrackInfo()
* and generateExistingTrackInfo()
*
* </pre>
*
@ -922,7 +924,7 @@ public class StormTrackDisplay implements IRenderable {
// time, the arrow of the pathcast is drawn behind the last frame
if (state.duration >= 0) {
for (int i = 1; i < futurePoints.length - (remainder == 0 ? 0 : 1); ++i) {
timeInMillis += minIntervalInSeconds * 1000;
timeInMillis += interval * 60 * 1000;
DataTime time = new DataTime(new Date(timeInMillis));
double distance = speed
@ -1074,7 +1076,7 @@ public class StormTrackDisplay implements IRenderable {
// time, the arrow of the pathcast is drawn behind the last frame
if (state.duration >= 0) {
for (int i = 1; i < futurePoints.length - (remainder == 0 ? 0 : 1); ++i) {
timeInMillis += minIntervalInSeconds * 1000;
timeInMillis += interval * 60 * 1000;
DataTime time = new DataTime(new Date(timeInMillis));
double distance = speed

View file

@ -35,6 +35,7 @@ import com.raytheon.viz.ui.personalities.awips.AbstractCAVEComponent;
* Oct 26, 2012 1287 rferrel Change to force blocking of ServiceBackupDlg.
* Mar 21, 2013 1447 dgilling Fix dialog construction so this dialog
* is created as a top-level shell.
* Jun 11, 2014 DR-17401 lshi
*
* </pre>
*
@ -54,8 +55,11 @@ public class ServiceBackupComponent extends AbstractCAVEComponent {
@Override
protected void startInternal(String componentName) throws Exception {
ServiceBackupDlg svcBuDlg = new ServiceBackupDlg(null);
svcBuDlg.setBlockOnOpen(true);
svcBuDlg.open();
if (!svcBuDlg.isTerminated())
{
svcBuDlg.setBlockOnOpen(true);
svcBuDlg.open();
}
}
/*

View file

@ -19,9 +19,12 @@
**/
package com.raytheon.viz.gfe.dialogs.sbu;
import java.util.Set;
import com.raytheon.uf.common.auth.user.IUser;
import com.raytheon.uf.common.dataplugin.gfe.request.CheckPermissionsRequest;
import com.raytheon.uf.common.dataplugin.gfe.request.CheckServiceBackupPrimarySiteRequest;
import com.raytheon.uf.common.dataplugin.gfe.request.GetServiceBackupPrimarySiteRequest;
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
@ -46,7 +49,7 @@ import com.raytheon.uf.viz.core.requests.ThriftClient;
* Jul 22, 2013 #1762 dgilling Ensure all fields of
* CheckServiceBackupPrimarySiteRequest are
* filled.
*
* Jun 10, 2013 DR-17401 lshi Added getPrimarySites()
* </pre>
*
* @author bphillip
@ -104,4 +107,21 @@ public class CheckPermissions {
}
return false;
}
public static Set<String> getPrimarySites() {
Set <String> primary = null;
GetServiceBackupPrimarySiteRequest request = new GetServiceBackupPrimarySiteRequest();
try {
@SuppressWarnings("unchecked")
ServerResponse<Set<String>> sr = (ServerResponse<Set<String>>) ThriftClient
.sendRequest(request);
primary = sr.getPayload();
return primary;
} catch (VizException e) {
statusHandler
.error("Error getting primary site(s)!", e);
}
return primary;
}
}

View file

@ -94,6 +94,7 @@ import com.raytheon.viz.ui.dialogs.CaveJFACEDialog;
* from A1 DR 21404, some code cleanup.
* May 01, 2013 1762 dgilling Remove national center check.
* Jul 22, 2013 1762 dgilling Fix running as primary check.
* Jun 10,2014 DR-17401 lshi
*
* </pre>
*
@ -161,8 +162,15 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
private boolean authorized;
private SVCBU_OP currentOperation = SVCBU_OP.no_backup;
private boolean isTerminated = false;
/**
public boolean isTerminated() {
return isTerminated;
}
/**
* @param parentShell
*/
public ServiceBackupDlg(Shell parentShell) {
@ -170,6 +178,13 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
authorized = CheckPermissions.getAuthorization();
this.site = LocalizationManager.getInstance().getCurrentSite();
this.runningAsPrimary = CheckPermissions.runningAsPrimary(this.site);
if (!CheckPermissions.getPrimarySites().contains(this.site)) {
displayMessage("You cannot run Service Backup as " + this.site + " - EXITING!!!");
isTerminated = true;
return;
}
if (!ServiceBackupJobManager.getInstance().isRunning()) {
ServiceBackupJobManager.getInstance().start();
}
@ -177,7 +192,6 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
progress = new ProgressDlg(getShell());
progress.setBlockOnOpen(false);
updateJob = new Job("SvcbuUpdateJob") {
@Override
protected IStatus run(IProgressMonitor monitor) {
VizApp.runAsync(new Runnable() {
@ -225,7 +239,7 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
@Override
public boolean close() {
updateJob.cancel();
return super.close();
return super.close();
}
/*
@ -492,7 +506,7 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
}
private void doImportConfig() {
switch (currentOperation) {
case svcbuMode:
displayMessage("" + this.failedSite.toUpperCase()
@ -548,7 +562,7 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
if (startGFE) {
jobManager.addJob(new SvcbuStartGfeJob(failedSite,
this.site));
}
}
}
}
}
@ -776,7 +790,7 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
jobManager.addJob(new SvcbuExitJob(this, this.site));
}
}
}
private void doClean(boolean showMessage) {

View file

@ -93,6 +93,7 @@ import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
* Sep 4, 2012 15335 kshresth Will now display lightning/wind
* fields when magnification set to 0
* Feb 27, 2013 DCS 152 jgerth/elau Support for WWLLN and multiple sources
* Jun 6, 2014 DR 17367 D. Friedman Fix cache object usage.
*
* </pre>
*
@ -479,6 +480,24 @@ public class LightningResource extends
*/
@Override
public void remove(DataTime dataTime) {
/*
* Workaround for time matching which does not know about records at the
* end of a time period that may contain data for the next period. If we
* are asked to remove the latest data time and there is only one record
* we know about, return without removing the time.
*/
if (dataTimes.indexOf(dataTime) == dataTimes.size() - 1) {
CacheObject<LightningFrameMetadata, LightningFrame> co = cacheObjectMap.get(dataTime);
if (co != null) {
LightningFrameMetadata metadata = co.getMetadata();
synchronized (metadata) {
if (metadata.newRecords.size() + metadata.processed.size() < 2) {
return;
}
}
}
}
dataTimes.remove(dataTime);
cacheObjectMap.remove(dataTime);
}
@ -522,20 +541,20 @@ public class LightningResource extends
List<BinLightningRecord> records = entry.getValue();
CacheObject<LightningFrameMetadata, LightningFrame> co = cacheObjectMap
.get(dt);
LightningFrameMetadata frame;
if (co == null) {
// New frame
frame = new LightningFrameMetadata(dt,
resourceData.getBinOffset(), this.lightSource);
co = CacheObject.newCacheObject(frame, resourceBuilder);
cacheObjectMap.put(dt, co);
dataTimes.add(dt);
} else {
// Frame exists
frame = co.getMetadata();
CacheObject<LightningFrameMetadata, LightningFrame> co;
synchronized (cacheObjectMap) {
co = cacheObjectMap.get(dt);
if (co == null) {
// New frame
LightningFrameMetadata key = new LightningFrameMetadata(dt,
resourceData.getBinOffset(), this.lightSource);
co = CacheObject.newCacheObject(key, resourceBuilder);
cacheObjectMap.put(dt, co);
dataTimes.add(dt);
}
}
frame = co.getMetadata();
synchronized (frame) {
// Add as new records

View file

@ -21,6 +21,7 @@
package com.raytheon.viz.warngen.gis;
import java.awt.geom.Point2D;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
@ -29,6 +30,7 @@ import java.util.List;
import org.geotools.referencing.GeodeticCalculator;
import com.raytheon.uf.common.dataplugin.warning.util.CountyUserData;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
@ -53,6 +55,8 @@ import com.vividsolutions.jts.geom.GeometryFactory;
* 0.10 to 0.0625 for EXTREME_DELTA; Added/modified code.
* May 1, 2013 1963 jsanchez Refactored calculatePortion to match A1. Do not allow 'Central' to be included if East and West is included.
* Jun 3, 2013 2029 jsanchez Updated A1 special case for calculating a central portion. Allowed East Central and West Central.
* Jun 17, 2014 DR 17390 Qinglu Lin Update calculateLocationPortion(). Use centroid in maps county table for geomCentroid
* for county based products.
* </pre>
*
* @author chammack
@ -344,13 +348,22 @@ public class GisUtil {
* @return
*/
public static EnumSet<Direction> calculateLocationPortion(
Geometry locationGeom, Geometry reference, boolean useExtreme) {
Geometry locationGeom, Geometry reference, boolean useExtreme, boolean notUseShapefileCentroid) {
for (int i = 0; i < locationGeom.getNumGeometries(); i++) {
Geometry geom = locationGeom.getGeometryN(i);
if (geom.intersects(reference)) {
Coordinate geomCentroid = geom.getEnvelope().getCentroid()
.getCoordinate();
Coordinate geomCentroid = null;
if (notUseShapefileCentroid) {
geomCentroid = geom.getEnvelope().getCentroid()
.getCoordinate();
} else {
geomCentroid = new Coordinate();
geomCentroid.x = ((BigDecimal)((CountyUserData)geom.getUserData()).
entry.attributes.get("LON")).doubleValue();
geomCentroid.y = ((BigDecimal)((CountyUserData)geom.getUserData()).
entry.attributes.get("LAT")).doubleValue();
}
Coordinate refCentroid = reference.getCentroid()
.getCoordinate();

View file

@ -23,6 +23,7 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.dataplugin.warning.util.CountyUserData;
import com.raytheon.viz.warngen.gis.GisUtil.Direction;
import com.raytheon.viz.warngen.gui.WarngenLayer;
import com.vividsolutions.jts.geom.Geometry;
@ -39,6 +40,7 @@ import com.vividsolutions.jts.geom.Geometry;
* ------------ ---------- ----------- --------------------------
* Aug 5, 2013 2177 jsanchez Initial creation
* Sep 22, 2013 2177 jsanchez Updated logic. Used GisUtil for very small portions.
* Jun 17, 2014 DR 17390 Qinglu Lin Update getPortions().
*
* </pre>
*
@ -78,8 +80,15 @@ public class PortionsUtil {
// This takes into account the warned areas that are very small
// the convex hull of the warned area is used for case the
// warnedArea is a geometry collection.
portions = GisUtil.calculateLocationPortion(countyOrZone,
warnedArea.convexHull(), useExtreme);
CountyUserData cud = (CountyUserData) countyOrZone.getUserData();
String countyName = (String) cud.entry.attributes.get("COUNTYNAME");
if (countyName == null) {
portions = GisUtil.calculateLocationPortion(countyOrZone,
warnedArea.convexHull(), useExtreme, true);
} else {
portions = GisUtil.calculateLocationPortion(countyOrZone,
warnedArea.convexHull(), useExtreme, false);
}
} else {
portions = getAreaDesc(entityData.getMeanMask(),
entityData.getCoverageMask(), entityData.getOctants(),

View file

@ -115,6 +115,7 @@ import com.vividsolutions.jts.geom.Point;
* Jun 24, 2013 DR 16317 D. Friedman Handle "motionless" track.
* Jun 25, 2013 16224 Qinglu Lin Resolved the issue with "Date start" for pathcast in CON.
* Apr 29, 2014 3033 jsanchez Updated method to retrieve files in localization.
* Jun 17, 2014 DR 17390 Qinglu Lin Updated getClosestPoints().
* </pre>
*
* @author chammack
@ -766,7 +767,7 @@ public class Wx {
cp.partOfArea = GisUtil.asStringList(GisUtil
.calculateLocationPortion(
cp.prepGeom.getGeometry(), reference,
false));
false, true));
distance = 0;
}
}

View file

@ -282,6 +282,13 @@
<constructor-arg ref="CheckPrimarySiteHandler"/>
</bean>
<bean id="GetServiceBackupPrimarySitesHandler" class="com.raytheon.edex.plugin.gfe.server.handler.svcbu.GetServiceBackupPrimarySiteHandler"/>
<bean factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.dataplugin.gfe.request.GetServiceBackupPrimarySiteRequest"/>
<constructor-arg ref="GetServiceBackupPrimarySitesHandler"/>
</bean>
<bean id="CleanupSvcBuLogRequestHandler" class="com.raytheon.edex.plugin.gfe.server.handler.svcbu.CleanupSvcBuLogRequestHandler"/>
<bean factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.dataplugin.gfe.request.CleaunpSvcBuLogRequest"/>

View file

@ -24,9 +24,9 @@
<constructor-arg ref="smartInitSrvCfg"/>
</bean>
<bean id="spcWatch" class="com.raytheon.edex.plugin.gfe.spc.SPCWatchSrv"/>
<bean id="tpcWatch" class="com.raytheon.edex.plugin.gfe.tpc.TPCWatchSrv"/>
<bean id="wclWatch" class="com.raytheon.edex.plugin.gfe.wcl.WCLWatchSrv"/>
<bean id="spcWatch" class="com.raytheon.edex.plugin.gfe.watch.SPCWatchSrv" />
<bean id="tpcWatch" class="com.raytheon.edex.plugin.gfe.watch.TPCWatchSrv" />
<bean id="wclWatch" class="com.raytheon.edex.plugin.gfe.watch.WCLWatchSrv" />
<bean id="vtecChangeListener" class="com.raytheon.edex.plugin.gfe.server.notify.VTECTableChangeListener"/>
@ -34,7 +34,7 @@
<route id="SPCWatch">
<from uri="vm:gfe.spcWatch"/>
<doTry>
<bean ref="spcWatch" method="handleSpcWatch"/>
<bean ref="spcWatch" method="handleWatch" />
<doCatch>
<exception>java.lang.Throwable</exception>
<to
@ -46,7 +46,7 @@
<route id="TPCWatch">
<from uri="vm:gfe.tpcWatch"/>
<doTry>
<bean ref="tpcWatch" method="handleTpcWatch"/>
<bean ref="tpcWatch" method="handleWatch" />
<doCatch>
<exception>java.lang.Throwable</exception>
<to

View file

@ -0,0 +1,68 @@
/**
* 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.svcbu;
import java.util.Set;
import com.raytheon.edex.plugin.gfe.svcbackup.SvcBackupUtil;
import com.raytheon.uf.common.dataplugin.gfe.request.GetServiceBackupPrimarySiteRequest;
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.serialization.comm.IRequestHandler;
/**
* Handler for <code>CheckServiceBackupPrimarySiteRequest</code>. Determines
* whether the specified site id has been configured as one of service backup's
* primary sites.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 10, 2014 DR-17401 lshi Initial creation
*
* </pre>
*
* @author lshi
* @version 1.0
*/
public class GetServiceBackupPrimarySiteHandler implements
IRequestHandler<GetServiceBackupPrimarySiteRequest> {
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest
* (com.raytheon.uf.common.serialization.comm.IServerRequest)
*/
@Override
public ServerResponse<Set<String>> handleRequest(
GetServiceBackupPrimarySiteRequest request) throws Exception {
ServerResponse<Set<String>> sr = new ServerResponse<Set<String>>();
Set<String> primarySites = SvcBackupUtil.getPrimarySites();
sr.setPayload(primarySites);
return sr;
}
}

View file

@ -1,151 +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.spc;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
import com.raytheon.uf.common.activetable.VTECPartners;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.UserMessageNotification;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.core.EdexException;
import com.raytheon.uf.edex.core.props.EnvProperties;
import com.raytheon.uf.edex.core.props.PropertiesFactory;
/**
* Watches ingested warnings for WOU products from the SPC (Storm Prediction
* Center). If the warning is a WOU, then it looks to see if the site is in the
* ATTN...WFO... line, and if so, sends a user message to GFE to alert users.
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 3, 2008 njensen Initial creation
* Jul 10, 2009 #2590 njensen Added multiple site support
* </pre>
*
* @author njensen
* @version 1.0
*/
public class SPCWatchSrv {
private static final Pattern ATTN_WFO = Pattern
.compile("ATTN\\.\\.\\.WFO\\.\\.\\.([A-Z]{3}\\.\\.\\.)+");
protected transient Log logger = LogFactory.getLog(getClass());
public void handleSpcWatch(List<PluginDataObject> pdos)
throws EdexException {
// create the appropriate SPC notification, returns null if not
// needed.
EnvProperties env = PropertiesFactory.getInstance().getEnvProperties();
String primarySite = env.getEnvValue("SITENAME");
String spcSite = (String) VTECPartners.getInstance(primarySite)
.getattr("VTEC_SPC_SITE", "KWNS");
for (PluginDataObject pdo : pdos) {
AbstractWarningRecord warn = (AbstractWarningRecord) pdo;
if (!warn.getPil().equals("WOU")) {
logger.debug("SPC notification: not WOU product");
return;
}
// find the first record from KWNS, SV.A, TO.A in this product
// action code must be "NEW"
if (warn.getOfficeid().equals(spcSite)
&& warn.getSig().equals("A")
&& (warn.getPhen().equals("TO") || warn.getPhen().equals(
"SV")) && warn.getAct().equals("NEW")) {
// decode the ATTN line, which tells us which WFOs are affected
List<String> wfos = getAttnWfos(warn.getRawmessage());
for (String siteid : GFESiteActivation.getInstance()
.getActiveSites()) {
if (!wfos.contains(siteid)) {
logger.debug("SPC notification: my site not in ATTN list");
continue; // not my WFO
}
// create the message
String txt = "";
if (warn.getPhen().equals("TO")) {
txt = "Tornado Watch";
} else if (warn.getPhen().equals("SV")) {
txt = "Severe Thunderstorm Watch";
}
String testText = "";
if (warn.getVtecstr().charAt(1) == 'T') {
testText = " This is a TEST watch. Please restart the GFE "
+ "in TEST mode before issuing WCN. ";
}
String msg = "Alert: "
+ txt
+ " "
+ warn.getEtn()
+ " has arrived. "
+ "Check for 'red' locks (owned by others) on your Hazard grid and resolve them. "
+ "If hazards are separated into temporary grids, please run MergeHazards. "
+ "Next...save Hazards grid. Finally, select PlotSPCWatches from the Hazards menu.";
msg = msg + testText;
UserMessageNotification notification = new UserMessageNotification(
msg, Priority.CRITICAL, "GFE", siteid);
SendNotifications.send(notification);
}
} else {
logger.debug("SPC notification: "
+ "no SV.A, TO.A vtec lines, or not NEW action code");
}
}
}
private static List<String> getAttnWfos(String rawMessage) {
List<String> list = new ArrayList<String>();
// decode the ATTN line, which tells us which WFOs are affected
// only used for WCL and WOU products
Matcher m = ATTN_WFO.matcher(rawMessage);
if (m.find()) {
String found = m.group();
// eliminate ATTN...WFO...
found = found.substring(13);
if (found != null) {
String[] wfos = found.split("\\.\\.\\.");
for (String s : wfos) {
list.add(s);
}
}
}
return list;
}
}

View file

@ -1,205 +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.tpc;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
import com.raytheon.uf.common.activetable.VTECPartners;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.UserMessageNotification;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.core.EdexException;
import com.raytheon.uf.edex.core.props.EnvProperties;
import com.raytheon.uf.edex.core.props.PropertiesFactory;
/**
* Watches ingested warnings for WOU products from the SPC (Storm Prediction
* Center). If the warning is a WOU, then it looks to see if the site is in the
* ATTN...WFO... line, and if so, sends a user message to GFE to alert users.
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 3, 2008 njensen Initial creation
* Jul 10, 2009 #2590 njensen Added multiple site support
* </pre>
*
* @author njensen
* @version 1.0
*/
public class TPCWatchSrv {
private static final Pattern ATTN_WFO = Pattern
.compile("ATTN\\.\\.\\.WFO\\.\\.\\.([A-Z]{3}\\.\\.\\.)+");
private static final Map<String, String> phensigMap;
private static final Map<String, String> actMap;
static {
Map<String, String> phensigMapTemp = new HashMap<String, String>();
phensigMapTemp.put("HU.A", "Hurricane Watch");
phensigMapTemp.put("HU.S", "Hurricane Local Statement");
phensigMapTemp.put("HU.W", "Hurricane Warning");
phensigMap = Collections.unmodifiableMap(phensigMapTemp);
Map<String, String> actMapTemp = new HashMap<String, String>();
actMapTemp.put("CON", "Continued");
actMapTemp.put("CAN", "Cancelled");
actMapTemp.put("NEW", "New");
actMap = Collections.unmodifiableMap(actMapTemp);
}
private static final String alertTxt = "Alert: {0} has arrived from TPC. "
+ "Check for 'red' locks (owned by others) on your Hazard grid and resolve them. "
+ "If hazards are separated into temporary grids, please run Mergehazards. "
+ "Next...save Hazards grid. Finally, select PlotTPCEvents from Hazards menu.";
protected transient Log logger = LogFactory.getLog(getClass());
public void handleTpcWatch(List<PluginDataObject> pdos)
throws EdexException {
EnvProperties env = PropertiesFactory.getInstance().getEnvProperties();
String primarySite = env.getEnvValue("SITENAME");
String tpcSite = (String) VTECPartners.getInstance(primarySite)
.getattr("VTEC_TPC_SITE", "KNHC");
Set<String> activeSites = GFESiteActivation.getInstance()
.getActiveSites();
AbstractWarningRecord ourWarn = null;
String ourSite = null;
// create the appropriate TPC notification, returns null if not
// needed.
Map<String, Set<String>> phensigStormAct = new HashMap<String, Set<String>>();
for (PluginDataObject pdo : pdos) {
AbstractWarningRecord warn = (AbstractWarningRecord) pdo;
if (!warn.getPil().startsWith("TCV")) {
logger.debug("TPC notification: not TCV product");
return;
}
// The warning is a TPC, but for us?
List<String> wfos = getAttnWfos(warn.getRawmessage());
wfos.retainAll(activeSites);
if (wfos.size() == 0) {
logger.debug("TPC notification: my site not in ATTN list");
continue;
}
if (ourWarn == null) {
ourWarn = warn;
ourSite = wfos.get(0);
}
// Collect action codes by phensig and storm #
if (tpcSite.equals(warn.getOfficeid())) {
String phensig = warn.getPhen() + "." + warn.getSig();
String storm = warn.getEtn();
String act = warn.getAct();
Set<String> psActs = phensigStormAct.get(phensig + ":" + storm);
if (psActs == null) {
psActs = new TreeSet<String>();
phensigStormAct.put(phensig + ":" + storm, psActs);
}
psActs.add(act);
}
}
if (phensigStormAct.size() == 0) {
logger.debug("TPC Notification: no HU/TR vtec lines, or not NEW action code");
return;
}
// Build the notification message
StringBuilder msg = new StringBuilder();
msg.append(MessageFormat.format(alertTxt, ourWarn.getPil()));
for (String phensigStorm : phensigStormAct.keySet()) {
Collection<String> acts = phensigStormAct.get(phensigStorm);
String[] splitKey = phensigStorm.split(":");
String phensig = splitKey[0];
String storm = splitKey[1];
String t1 = phensigMap.get(phensig);
if (t1 == null) {
t1 = phensig;
}
msg.append(t1 + ": #" + storm + "(");
String sep = "";
for (String a : acts) {
String a1 = actMap.get(a);
if (a1 == null) {
a1 = a;
}
msg.append(sep).append(a1);
sep = ",";
}
msg.append("). ");
}
UserMessageNotification notification = new UserMessageNotification(
msg.toString(), Priority.CRITICAL, "GFE", ourSite);
SendNotifications.send(notification);
}
private static List<String> getAttnWfos(String rawMessage) {
List<String> list = new ArrayList<String>();
// decode the ATTN line, which tells us which WFOs are affected
// only used for WCL and WOU products
Matcher m = ATTN_WFO.matcher(rawMessage);
if (m.find()) {
String found = m.group();
// eliminate ATTN...WFO...
found = found.substring(13);
if (found != null) {
String[] wfos = found.split("\\.\\.\\.");
for (String s : wfos) {
list.add(s);
}
}
}
return list;
}
}

View file

@ -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.
**/
package com.raytheon.edex.plugin.gfe.watch;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
import com.raytheon.uf.common.activetable.VTECPartners;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.GfeNotification;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.UserMessageNotification;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
/**
* Base class for a bean that accepts a {@code List} of
* {@code AbstractWarningRecord}s and generates a set of notifications for the
* GFE user if the storm affects their WFO.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 10, 2014 #3268 dgilling Initial creation
*
* </pre>
*
* @author dgilling
* @version 1.0
*/
public abstract class AbstractWatchNotifierSrv {
protected final IUFStatusHandler statusHandler = UFStatus
.getHandler(getClass());
protected final String watchType;
protected final String supportedPIL;
protected AbstractWatchNotifierSrv(String watchType, String supportedPIL) {
this.watchType = watchType;
this.supportedPIL = supportedPIL;
}
/**
* Processes the warning records and generates a notification for each
* currently activated GFE site if the storm affects the site.
*
* @param pdos
* A list of {@code PluginDataObject}s that are assumed to be
* {@code AbstractWarningRecord}s all decoded from a common
* warning product.
*/
public final void handleWatch(List<PluginDataObject> pdos) {
List<AbstractWarningRecord> warningRecs = filterIncomingRecordsByPIL(pdos);
if (warningRecs.isEmpty()) {
String logMsg = String.format("%s notification: not %s product",
watchType, supportedPIL);
statusHandler.debug(logMsg);
return;
}
/*
* We are making an assumption that all PDOs came from the same source
* product. This is a safe assumption because WarningDecoder processes
* records one product at a time and the plugin notifier code that sends
* those records to us does not do any additional grouping or batching.
*
* Hence, any of the remaining records' raw message will be the same as
* the rest and we can just use the first record's copy.
*/
String productText = warningRecs.get(0).getRawmessage();
Collection<String> wfos = WatchProductUtil.findAttnWFOs(productText);
for (String siteid : GFESiteActivation.getInstance().getActiveSites()) {
if (!wfos.contains(siteid)) {
String logMsg = String.format(
"%s notification: my site %s not in ATTN list",
watchType, siteid);
statusHandler.debug(logMsg);
continue;
}
VTECPartners partnersConfig = VTECPartners.getInstance(siteid);
String msg = buildNotification(warningRecs, partnersConfig);
if (msg != null) {
sendNotification(msg, siteid);
}
}
}
/**
* Given a list of {@code PluginDataObject}s that are actually
* {@code AbstractWarningRecord}s, filters the list for only those records
* which have the right PIL code.
*
* @param pdos
* List of {@code AbstractWarningRecord}s to filter.
* @return The list of supported {@code AbstractWarningRecord}s as defined
* by {@code getSupportedPIL}.
*/
protected List<AbstractWarningRecord> filterIncomingRecordsByPIL(
List<PluginDataObject> pdos) {
List<AbstractWarningRecord> warningRecords = new ArrayList<AbstractWarningRecord>();
for (PluginDataObject pdo : pdos) {
AbstractWarningRecord warning = (AbstractWarningRecord) pdo;
if (warning.getPil().startsWith(supportedPIL)) {
warningRecords.add(warning);
}
}
return warningRecords;
}
/**
* Takes the specified list of warning records and {@code VTECPartners}
* configuration data and builds a notification message to send.
*
* @param decodedVTEC
* The warning records.
* @param partnersConfig
* The {@code VTECPartners} configuration data.
* @return The notification message to send to the users for the site, or
* {@code null} if no notification applies.
*/
protected abstract String buildNotification(
List<AbstractWarningRecord> decodedVTEC, VTECPartners partnersConfig);
/**
* Sends the specified notification message as an AletViz alert to all GFE
* users connected as the specified site.
*
* @param message
* The notification message text to send.
* @param siteId
* The site identifier that will receive the message.
* @return A {@code ServerResponse} containing error message if sending the
* notification message failed.
*/
protected ServerResponse<?> sendNotification(String message, String siteId) {
GfeNotification notification = new UserMessageNotification(message,
Priority.CRITICAL, "GFE", siteId);
return SendNotifications.send(notification);
}
}

View file

@ -0,0 +1,119 @@
/**
* 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.watch;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.activetable.VTECPartners;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
/**
* Watches ingested warnings for WOU products from the SPC (Storm Prediction
* Center). If the warning is a WOU, then it looks to see if the site is in the
* ATTN...WFO... line, and if so, sends a user message to GFE to alert users.
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 03, 2008 njensen Initial creation
* Jul 10, 2009 #2590 njensen Added multiple site support
* Jun 10, 2014 #3268 dgilling Re-factor based on AbstractWatchNotifierSrv.
* </pre>
*
* @author njensen
* @version 1.0
*/
public final class SPCWatchSrv extends AbstractWatchNotifierSrv {
private static final String SPC_WATCH_TYPE = "SPC";
private static final String SPC_SUPPORTED_PIL = "WOU";
private static final String SPC_SITE_ATTRIBUTE = "VTEC_SPC_SITE";
private static final String DEFAULT_SPC_SITE = "KNHC";
private static final String TEST_TEXT_MSG = " This is a TEST watch. Please restart the GFE in TEST mode before issuing WCN. ";
private static final String ALERT_MSG = "Alert: %s %s has arrived. "
+ "Check for 'red' locks (owned by others) on your Hazard grid and resolve them. "
+ "If hazards are separated into temporary grids, please run MergeHazards. "
+ "Next...save Hazards grid. Finally, select PlotSPCWatches from the Hazards menu.";
private static final Map<String, String> phenTextMap;
static {
Map<String, String> phenTextMapTemp = new HashMap<String, String>(2, 1f);
phenTextMapTemp.put("TO", "Tornado Watch");
phenTextMapTemp.put("SV", "Severe Thunderstorm Watch");
phenTextMap = Collections.unmodifiableMap(phenTextMapTemp);
}
public SPCWatchSrv() {
super(SPC_WATCH_TYPE, SPC_SUPPORTED_PIL);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.edex.plugin.gfe.warning.AbstractWarningNotifierSrv#
* buildNotification(java.util.List, java.lang.String,
* com.raytheon.uf.common.activetable.VTECPartners)
*/
@Override
protected String buildNotification(List<AbstractWarningRecord> decodedVTEC,
VTECPartners partnersConfig) {
String spcSite = partnersConfig.getattr(SPC_SITE_ATTRIBUTE,
DEFAULT_SPC_SITE).toString();
// find the first record from our configured list of issuing sites.
// Also this product must be a NEW SV.A or TO.A
AbstractWarningRecord matchRecord = null;
for (AbstractWarningRecord e : decodedVTEC) {
if (spcSite.equals(e.getOfficeid())
&& e.getSig().equals("A")
&& ((e.getPhen().equals("TO")) || (e.getPhen().equals("SV")))
&& e.getAct().equals("NEW")) {
matchRecord = e;
break;
}
}
if (matchRecord == null) {
statusHandler.debug("SPC notification: "
+ "no SV.A, TO.A vtec lines, or not NEW action code");
return null;
}
// create the message
String eventType = phenTextMap.get(matchRecord.getPhen());
StringBuilder msg = new StringBuilder(String.format(ALERT_MSG,
eventType, matchRecord.getEtn()));
if (matchRecord.getVtecstr().charAt(1) == 'T') {
msg.append(TEST_TEXT_MSG);
}
return msg.toString();
}
}

View file

@ -0,0 +1,153 @@
/**
* 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.watch;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import com.raytheon.uf.common.activetable.VTECPartners;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
/**
* Watches ingested warnings for WOU products from the SPC (Storm Prediction
* Center). If the warning is a WOU, then it looks to see if the site is in the
* ATTN...WFO... line, and if so, sends a user message to GFE to alert users.
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 03, 2008 njensen Initial creation
* Jul 10, 2009 #2590 njensen Added multiple site support
* Jun 10, 2014 #3268 dgilling Re-factor based on AbstractWatchNotifierSrv.
* </pre>
*
* @author njensen
* @version 1.0
*/
public final class TPCWatchSrv extends AbstractWatchNotifierSrv {
private static final String TPC_WATCH_TYPE = "TPC";
private static final String TPC_SUPPORTED_PIL = "TCV";
private static final String TPC_SITE_ATTRIBUTE = "VTEC_TPC_SITE";
private static final String DEFAULT_TPC_SITE = "KNHC";
private static final String ALERT_TXT = "Alert: %s has arrived from TPC. "
+ "Check for 'red' locks (owned by others) on your Hazard grid and resolve them. "
+ "If hazards are separated into temporary grids, please run Mergehazards. "
+ "Next...save Hazards grid. Finally, select PlotTPCEvents from Hazards menu.";
private static final Map<String, String> phensigMap;
private static final Map<String, String> actMap;
static {
Map<String, String> phensigMapTemp = new HashMap<String, String>(5, 1f);
phensigMapTemp.put("HU.A", "Hurricane Watch");
phensigMapTemp.put("HU.S", "Hurricane Local Statement");
phensigMapTemp.put("HU.W", "Hurricane Warning");
phensigMapTemp.put("TR.A", "Tropical Storm Watch");
phensigMapTemp.put("TR.W", "Tropical Storm Warning");
phensigMap = Collections.unmodifiableMap(phensigMapTemp);
Map<String, String> actMapTemp = new HashMap<String, String>(3, 1f);
actMapTemp.put("CON", "Continued");
actMapTemp.put("CAN", "Cancelled");
actMapTemp.put("NEW", "New");
actMap = Collections.unmodifiableMap(actMapTemp);
}
public TPCWatchSrv() {
super(TPC_WATCH_TYPE, TPC_SUPPORTED_PIL);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.edex.plugin.gfe.warning.AbstractWarningNotifierSrv#
* buildNotification(java.util.List,
* com.raytheon.uf.common.activetable.VTECPartners)
*/
@Override
protected String buildNotification(List<AbstractWarningRecord> decodedVTEC,
VTECPartners partnersConfig) {
String tpcSite = partnersConfig.getattr(TPC_SITE_ATTRIBUTE,
DEFAULT_TPC_SITE).toString();
// get all VTEC records, assemble unique list of phen/sig and storm#
Map<String, Set<String>> phensigStormAct = new HashMap<String, Set<String>>();
for (AbstractWarningRecord e : decodedVTEC) {
if (tpcSite.equals(e.getOfficeid())) {
String phensig = e.getPhensig();
String storm = e.getEtn();
String act = e.getAct();
Set<String> psActs = phensigStormAct.get(phensig + ":" + storm);
if (psActs == null) {
psActs = new TreeSet<String>();
phensigStormAct.put(phensig + ":" + storm, psActs);
}
psActs.add(act);
}
}
if (phensigStormAct.isEmpty()) {
statusHandler
.debug("TPC Notification: no HU/TR vtec lines, or not NEW action code");
return null;
}
// create the message
StringBuilder msg = new StringBuilder(String.format(ALERT_TXT,
supportedPIL));
for (String phensigStorm : phensigStormAct.keySet()) {
Collection<String> acts = phensigStormAct.get(phensigStorm);
String[] splitKey = phensigStorm.split(":");
String phensig = splitKey[0];
String storm = splitKey[1];
String t1 = phensigMap.get(phensig);
if (t1 == null) {
t1 = phensig;
}
msg.append(t1 + ": #" + storm + "(");
String sep = "";
for (String a : acts) {
String a1 = actMap.get(a);
if (a1 == null) {
a1 = a;
}
msg.append(sep).append(a1);
sep = ",";
}
msg.append("). ");
}
return msg.toString();
}
}

View file

@ -20,51 +20,61 @@
/**
*
*/
package com.raytheon.edex.plugin.gfe.wcl;
package com.raytheon.edex.plugin.gfe.watch;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.raytheon.edex.plugin.gfe.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.GfeNotification;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.UserMessageNotification;
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.PathManagerFactory;
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.uf.common.util.FileUtil;
import com.raytheon.uf.edex.core.EdexException;
/**
* @author wldougher
* If a WCL (watch county list) is ingested, this class will send a notification
* to the GFE users alerting them that their WFO may be in the path of an
* upcoming TO.A or SV.A.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* ??? ??, 20?? wldougher Initial creation
* Jun 09, 2014 #3268 dgilling Ensure code works in multi-domain scenarios.
* Jun 13, 2014 #3278 dgilling Ensure temporary files get deleted.
*
* </pre>
*
* @author wldougher
* @version 1.0
*/
public class WCLWatchSrv {
private static final String ALERT_FORM = "Alert: " + "%1$s has arrived. "
+ "Please select ViewWCL and use %1$s. (Hazards menu)";
private static final Pattern ATTN_PATTERN = Pattern.compile("^"
+ Pattern.quote("ATTN...WFO..."));
private static final Pattern EXPIRE_TIME_PATTERN = Pattern
.compile("(\\d{2})(\\d{2})(\\d{2})\\-");
@ -81,36 +91,8 @@ public class WCLWatchSrv {
private static final Pattern UGC_PATTERN = Pattern.compile("\\d{3}\\-");
protected transient Log logger = LogFactory.getLog(getClass());
/**
* Get the WFOs from the ATTN line.
*
* @param lines
* The lines in the warning file
* @return the WFOs from the WFO attention line, as a set of Strings.
*/
protected Set<String> attnWFOs(List<String> lines) {
StringBuilder wfoLine = new StringBuilder();
boolean attnFound = false;
if (lines != null) {
for (String line : lines) {
attnFound = attnFound || ATTN_PATTERN.matcher(line).lookingAt();
if (attnFound) {
wfoLine.append(line);
}
}
}
Set<String> wfosR = new HashSet<String>();
if (wfoLine.length() > 13) {
String[] wfos = wfoLine.substring(13).split(Pattern.quote("..."));
for (String wfo : wfos) {
wfosR.add(wfo.trim());
}
}
return wfosR;
}
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(WCLWatchSrv.class);
/**
* Process a WCL watch, partially parsed and passed as a WclInfo object.
@ -130,20 +112,17 @@ public class WCLWatchSrv {
* or when there are problems generating the WCL script file.
*/
public void handleWclWatch(WclInfo wclInfo) throws EdexException {
logger.debug("handleWclWatch started");
UserMessageNotification notice = null;
String completeProductPil = wclInfo.getCompleteProductPil();
Set<String> wfos = attnWFOs(wclInfo.getLines());
statusHandler.debug("handleWclWatch started");
Collection<String> sitesToNotify = WatchProductUtil
.findAttnWFOs(wclInfo.getLines());
Set<String> siteIDs = getSiteIDs();
wfos.retainAll(siteIDs); // Keep shared IDs
if (!wfos.isEmpty()) {
// Get the first matching site ID
String siteID = wfos.toArray(new String[1])[0];
boolean doNotify = true;
String msg = String.format(ALERT_FORM, completeProductPil);
notice = new UserMessageNotification(msg, Priority.CRITICAL, "GFE",
siteID);
sitesToNotify.retainAll(siteIDs); // Keep shared IDs
if (sitesToNotify.isEmpty()) {
statusHandler.debug("WCL notification: sites not in ATTN list");
doNotify = false;
}
// Process the WCL regardless of whether we are sending a notice
@ -160,96 +139,83 @@ public class WCLWatchSrv {
// Get the watch type
String watchType = getWatchType(wclInfo);
// Get the WCL 'letter'
String completeProductPil = wclInfo.getCompleteProductPil();
// Create a dummy Procedure for export
String wclStr = makeWclStr(finalUGCList, expireTime, issueTime,
watchType);
logger.debug("WCLData: " + wclStr);
statusHandler.info("WCLData: " + wclStr);
// Write dummy procedure to temp file
File tmpFile = createTempWclFile(wclStr);
// Move the file to the wcl folder
// Rename it to <wclDir>/<completeProductPil>
makePermanent(tmpFile, completeProductPil);
if (notice == null || !wclInfo.getNotify()) {
logger.info("Notification of WCL skipped");
} else {
SendNotifications.send(notice);
statusHandler.info("Placing WCL Procedure Utility in ifpServer ");
try {
makePermanent(tmpFile, completeProductPil, siteIDs);
} finally {
if (tmpFile != null) {
tmpFile.delete();
}
}
logger.debug("handleWclWatch() ending");
return;
if (doNotify && wclInfo.getNotify()) {
for (String siteID : sitesToNotify) {
String msg = String.format(ALERT_FORM, completeProductPil);
GfeNotification notify = new UserMessageNotification(msg,
Priority.CRITICAL, "GFE", siteID);
SendNotifications.send(notify);
}
} else {
statusHandler.info("Notification of WCL skipped");
}
statusHandler.debug("handleWclWatch() ending");
}
/**
* Convert a temporary parsed WCL file to a permanent one by moving it to
* the WCL directory. This is done through File.renameTo(). Unfortunately,
* that method returns a boolean success flag rather than throwing an error,
* so all we can do is tell the user that the rename failed, not why.
* Convert a temporary parsed WCL file to a permanent one by copying its
* contents to the localization path cave_static.SITE/gfe/wcl/ for each of
* the specified sites.
*
* @param tmpFile
* The temporary file (may be null)
* The temporary file (may be {@code null})
* @param completeProductPil
* The simple name of the file.
* @throws EdexException
* if tmpFile cannot be renamed.
* The base name of the files to write.
* @param siteIDs
* The set of siteIDs to write out the WCL data for.
*/
protected void makePermanent(File tmpFile, String completeProductPil)
throws EdexException {
logger.debug("makePermanent(" + tmpFile + "," + completeProductPil
+ ") started");
protected void makePermanent(File tmpFile, String completeProductPil,
Collection<String> siteIDs) {
statusHandler.debug("makePermanent(" + tmpFile + ","
+ completeProductPil + ") started");
if (tmpFile != null) {
File wclDir = getWclDir();
File dest = new File(wclDir, completeProductPil);
// Try to do things with renameTo() because it's quick if it works.
if (!tmpFile.renameTo(dest)) {
// renameTo() can fail for a variety of reasons.
// Try to do a copy-and-delete.
FileChannel temp = null;
FileChannel perm = null;
IOException firstFail = null;
for (String siteID : siteIDs) {
try {
temp = new FileInputStream(tmpFile).getChannel();
perm = new FileOutputStream(dest).getChannel();
// should file range be locked before copy?
temp.transferTo(0, temp.size(), perm);
temp.close();
tmpFile.delete();
File wclDir = getWclDir(siteID);
if (wclDir != null) {
File dest = new File(wclDir, completeProductPil);
FileUtil.copyFile(tmpFile, dest);
statusHandler.info("Wrote WCL "
+ tmpFile.getAbsolutePath() + " to "
+ dest.getAbsolutePath());
} else {
statusHandler
.error("Could not determine WCL directory for site "
+ siteID);
}
} catch (IOException e) {
throw new EdexException("Renaming \""
+ tmpFile.getAbsolutePath() + "\" to \""
+ dest.getAbsolutePath() + "\" failed.", e);
} finally {
if (temp != null && temp.isOpen()) {
try {
temp.close();
logger.debug(temp.toString() + " closed");
} catch (IOException e) {
firstFail = e;
}
}
if (perm != null && perm.isOpen()) {
try {
perm.close();
logger.debug(perm.toString() + " closed");
} catch (IOException e) {
if (firstFail == null) {
firstFail = e;
}
}
}
}
if (firstFail != null) {
throw new EdexException("Error closing file", firstFail);
statusHandler.error("Could not copy temporary WCL file "
+ tmpFile.getAbsolutePath()
+ " to site directory for " + siteID, e);
}
}
// If we got to here, claim success!
logger.info("" + tmpFile.getAbsolutePath() + " renamed to "
+ dest.getAbsolutePath());
}
logger.debug("makePermanent(" + tmpFile + "," + completeProductPil
+ ") ending");
statusHandler.debug("makePermanent(" + tmpFile + ","
+ completeProductPil + ") ending");
}
/**
@ -266,7 +232,7 @@ public class WCLWatchSrv {
File tmpFile = null;
PrintStream wclOut = null;
try {
tmpFile = File.createTempFile("wcl", null, null);
tmpFile = File.createTempFile("wcl", null);
wclOut = new PrintStream(tmpFile);
wclOut.println(wclStr);
} catch (IOException e) {
@ -445,19 +411,23 @@ public class WCLWatchSrv {
* getSiteIDs(), this is in a method rather than inline so that test code
* can override it in subclasses.
*
* @param siteID
* The siteID to write the WCL file for.
*
* @return the directory, as a File.
*/
protected File getWclDir() {
protected File getWclDir(String siteID) {
IPathManager pathManager = PathManagerFactory.getPathManager();
LocalizationContext ctx = pathManager.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.SITE);
String wclName = "gfe" + File.separator + "wcl";
LocalizationContext ctx = pathManager.getContextForSite(
LocalizationType.CAVE_STATIC, siteID);
String wclName = FileUtil.join("gfe", "wcl");
File wclDir = pathManager.getFile(ctx, wclName);
if (wclDir == null) {
logger.error("Path manager could not locate " + wclName);
statusHandler.error("Path manager could not locate " + wclName);
} else if (!wclDir.exists()) {
wclDir.mkdir();
logger.info("Directory " + wclDir.getAbsolutePath() + " created.");
statusHandler.info("Directory " + wclDir.getAbsolutePath()
+ " created.");
}
return wclDir;
}

View file

@ -0,0 +1,96 @@
/**
* 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.watch;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.raytheon.uf.common.util.StringUtil;
/**
* Common methods for dealing with watch products that are received from
* national centers.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 14, 2014 #3157 dgilling Initial creation.
*
* </pre>
*
* @author dgilling
* @version 1.0
*/
public class WatchProductUtil {
private static final Pattern ATTN_PATTERN = Pattern
.compile("\\QATTN...WFO...\\E((?:[A-Z]{3}\\Q...\\E)+)");
private WatchProductUtil() {
throw new AssertionError();
}
/**
* Searches the specified watch product text for a "ATTN...WFO..." line and
* returns a collection of WFOs that appeared in that line of the product.
*
* @param lines
* The lines that comprise the watch product.
* @return The list of WFOs that appear in the "ATTN...WFO..." line of the
* product.
*/
public static Collection<String> findAttnWFOs(List<String> lines) {
return findAttnWFOs(StringUtil.join(lines, '\n'));
}
/**
* Searches the specified watch product text for a "ATTN...WFO..." line and
* returns a collection of WFOs that appeared in that line of the product.
*
* @param rawMessage
* The full text of the watch product in a single String.
* @returnThe list of WFOs that appear in the "ATTN...WFO..." line of the
* product.
*/
public static Collection<String> findAttnWFOs(String rawMessage) {
Collection<String> retVal = Collections.emptySet();
// decode the ATTN line, which tells us which WFOs are affected
// only used for WCL and WOU products
Matcher m = WatchProductUtil.ATTN_PATTERN.matcher(rawMessage);
if (m.find()) {
// eliminate ATTN...WFO...
String found = m.group(1);
String[] wfos = found.split(Pattern.quote("..."));
retVal = new HashSet<String>(Arrays.asList(wfos));
}
return retVal;
}
}

View file

@ -20,7 +20,7 @@
/**
*
*/
package com.raytheon.edex.plugin.gfe.wcl;
package com.raytheon.edex.plugin.gfe.watch;
import java.util.Collections;
import java.util.Date;

View file

@ -41,6 +41,7 @@
# Sep 12, 2013 2249 rferrel When incoming file from warngen adjust
# start time from file's timestamp.
# Oct 03, 2013 2402 bsteffen Make PythonDecoder more extendable.
# Jun 10, 2014 3268 dgilling Update location of WclInfo class.
# </pre>
#
@ -174,7 +175,7 @@ class StdWarningDecoder():
if self._productPil[0:3] == "WCL":
endpoint = "WCLWatch"
# build a Java object for the warning
from com.raytheon.edex.plugin.gfe.wcl import WclInfo
from com.raytheon.edex.plugin.gfe.watch import WclInfo
import JUtil
lines = JUtil.pyValToJavaObj(self._lines)
warning = WclInfo(long(self._issueTime * 1000),

View file

@ -0,0 +1,45 @@
/**
* 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;
/**
* Request to determine whether specified site id is one of the server's
* configured primary sites for service backup.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 10, 2014 DR-17401 lshi Initial creation
*
* </pre>
*
* @author lshi
* @version 1.0
*/
@DynamicSerialize
public class GetServiceBackupPrimarySiteRequest extends AbstractGfeRequest {
}

View file

@ -63,6 +63,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
* to areaFields.
* Jan 9, 2013 15600 Qinglu Lin Execute "timezones = myTimeZones;" even if timezones != null.
* Oct 22, 2013 2361 njensen Use JAXBManager for XML
* Jun 17, 2014 DR 17390 Qinglu Lin Updated getMetaDataMap() for lonField and latField.
*
* </pre>
*
@ -216,6 +217,9 @@ public class GeospatialFactory {
areaFields.add(feAreaField);
}
areaFields.add("LON");
areaFields.add("LAT");
if (timeZoneField != null) {
areaFields.add(timeZoneField);
}

View file

@ -1,4 +1,34 @@
#!/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.
##
##############################################################################
# Process Received Digital Grids
# This is run at the backup site to merge the failed site's grids into the
# Fcst database.
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 06/16/15 3276 randerso Added -T to iscMosaic call
##############################################################################
import_file=${1}
log_msg Processing file: $import_file
@ -98,7 +128,7 @@ log_msg "CDSPORT is $CDSPORT"
log_msg Beginning iscMosaic
log_msg 75
${GFESUITE_BIN}/iscMosaic -h $SVCBU_HOST -r $CDSPORT -d ${SITE}_GRID__Fcst_00000000_0000 -f ${SVCBU_HOME}/${failed_site}Grd.netcdf.gz -n
${GFESUITE_BIN}/iscMosaic -h $SVCBU_HOST -r $CDSPORT -d ${SITE}_GRID__Fcst_00000000_0000 -f ${SVCBU_HOME}/${failed_site}Grd.netcdf.gz -n -T
if [ $? -ne 0 ]
then
log_msg "ERROR: iscMosaic failed to import grids from ${SITE}_GRID__Fcst_00000000_0000"

View file

@ -1,4 +1,35 @@
#!/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.
##
##############################################################################
# Receive grids from backup site
# This script is run when importing your digital data back from the backup site.
# The grids are placed in the Restore database.
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 06/16/15 3276 randerso Added -T to iscMosaic call
##############################################################################
if [ ${#AWIPS_HOME} = 0 ]
then
path_to_script=`readlink -f $0`
@ -94,7 +125,7 @@ if [ -a ${import_file} ]
then
#use iscMosaic to load grids into databases
log_msg "Running iscMosaic to unpack griddded data..."
${GFESUITE_BIN}/iscMosaic -h $SVCBU_HOST -r $CDSPORT -d ${SITE}_GRID__Restore_00000000_0000 -f ${import_file} -n -x
${GFESUITE_BIN}/iscMosaic -h $SVCBU_HOST -r $CDSPORT -d ${SITE}_GRID__Restore_00000000_0000 -f ${import_file} -n -T -x
if [ $? -ne 0 ];
then
log_msg "ERROR: iscMosaic failed to run correctly. Please re-run iscMosaic manually."

View file

@ -17,7 +17,7 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.plugin.gfe.wcl;
package com.raytheon.edex.plugin.gfe.watch;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@ -29,6 +29,8 @@ import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
@ -37,11 +39,12 @@ import java.util.TimeZone;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
// TODO fix?
@Ignore
import com.raytheon.edex.plugin.gfe.watch.WCLWatchSrv;
import com.raytheon.edex.plugin.gfe.watch.WatchProductUtil;
import com.raytheon.edex.plugin.gfe.watch.WclInfo;
public class TestWCLWatchSrv {
private WclInfo wclInfoA;
@ -78,11 +81,11 @@ public class TestWCLWatchSrv {
wfosExpected.add("OAX");
wfosExpected.add("MFL");
wfosExpected.add("ICT");
Set<String> wfos = wclWatchSrv.attnWFOs(linesA);
Collection<String> wfos = WatchProductUtil.findAttnWFOs(linesA);
assertEquals("LinesA", wfosExpected, wfos);
wfosExpected.clear();
wfos = wclWatchSrv.attnWFOs(linesB);
wfos = WatchProductUtil.findAttnWFOs(linesB);
assertEquals("LinesB", wfosExpected, wfos);
}
@ -98,7 +101,7 @@ public class TestWCLWatchSrv {
}
@Override
protected File getWclDir() {
protected File getWclDir(String siteID) {
String home = System.getenv("HOME");
File fakeDir = new File(home);
return fakeDir;
@ -128,7 +131,7 @@ public class TestWCLWatchSrv {
// localization.
wclWatchSrv = new WCLWatchSrv() {
@Override
protected File getWclDir() {
protected File getWclDir(String siteID) {
String home = System.getenv("HOME");
return new File(home);
}
@ -138,7 +141,8 @@ public class TestWCLWatchSrv {
PrintWriter pw = new PrintWriter(temp);
pw.println("Testing");
pw.close();
wclWatchSrv.makePermanent(temp, completePIL);
Collection<String> dummy = Collections.emptySet();
wclWatchSrv.makePermanent(temp, completePIL, dummy);
assertTrue("expetedFile exists", expectedFile.exists());
assertTrue("expectedFile isFile", expectedFile.isFile());
assertFalse("temp exists", temp.exists());