Merge branch 'master_14.3.1' into asm_14.3.1

Former-commit-id: da6b0f2adf [formerly b64d38be69] [formerly da6b0f2adf [formerly b64d38be69] [formerly 6d93f8f3ef [formerly 765d6440b1b19d7b0cf789fb7a873e14b4a679e1]]]
Former-commit-id: 6d93f8f3ef
Former-commit-id: 685b53d6bc [formerly 55fa980898]
Former-commit-id: d62782613b
This commit is contained in:
Brian.Dyke 2014-07-01 13:47:12 -04:00
commit 52977a745e
39 changed files with 1221 additions and 685 deletions

View file

@ -38,6 +38,7 @@ import org.eclipse.ui.commands.ICommandService;
* ------------- -------- ----------- -------------------------- * ------------- -------- ----------- --------------------------
* Aug 30, 2007 randerso Initial Creation. * Aug 30, 2007 randerso Initial Creation.
* Oct 22, 2013 2491 bsteffen Remove ISerializableObject * Oct 22, 2013 2491 bsteffen Remove ISerializableObject
* Jun 23, 2014 3307 njensen Fix xml serialization of looping field
* *
* </pre> * </pre>
* *
@ -50,7 +51,7 @@ public class LoopProperties {
public enum LoopMode { public enum LoopMode {
Forward, Backward, Cycle Forward, Backward, Cycle
}; }
/** frame time increment in ms */ /** frame time increment in ms */
public static final int FRAME_STEP = 100; public static final int FRAME_STEP = 100;
@ -144,12 +145,8 @@ public class LoopProperties {
this.mode = mode; this.mode = mode;
} }
public boolean isLooping() {
return isLooping;
}
@XmlElement @XmlElement
public boolean getLooping() { public boolean isLooping() {
return isLooping; return isLooping;
} }

View file

@ -49,6 +49,7 @@ import com.vividsolutions.jts.geom.GeometryFactory;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Sep 15, 2009 njensen Initial creation * Sep 15, 2009 njensen Initial creation
* Jun 3, 2014 16289 zhao Use "end time" instead of "start time" for CCFP report
* *
* </pre> * </pre>
* *
@ -119,7 +120,7 @@ public class CcfpData {
CcfpRecord area = findMostRelevantArea(c, list); CcfpRecord area = findMostRelevantArea(c, list);
List<String> reports = siteReportMap.get(site); List<String> reports = siteReportMap.get(site);
if (area != null) { if (area != null) {
String report = mkCCFPReport(site, dt, area); String report = mkCCFPReport(site, area.getDataTime().getValidPeriod().getEnd(), area);
reports.add(report); reports.add(report);
} }
siteReportMap.put(site, reports); siteReportMap.put(site, reports);

View file

@ -27,7 +27,6 @@ import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -35,14 +34,14 @@ import java.util.Map;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import javax.xml.bind.JAXB;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.preference.IPersistentPreferenceStore; import org.eclipse.jface.preference.IPersistentPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import com.raytheon.uf.common.localization.FileUpdatedMessage; import com.raytheon.uf.common.localization.FileUpdatedMessage;
import com.raytheon.uf.common.localization.ILocalizationFileObserver; import com.raytheon.uf.common.localization.ILocalizationFileObserver;
@ -51,6 +50,8 @@ import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.LocalizationFileInputStream;
import com.raytheon.uf.common.localization.LocalizationFileOutputStream;
import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException; import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
@ -60,7 +61,6 @@ import com.raytheon.uf.common.time.SimulatedTime;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery; import com.raytheon.uf.viz.core.catalog.DirectDbQuery;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage; import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.localization.HierarchicalPreferenceStore;
import com.raytheon.uf.viz.core.localization.LocalizationManager; import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.uf.viz.points.PointsDataManager; import com.raytheon.uf.viz.points.PointsDataManager;
import com.raytheon.viz.awipstools.common.RangeRing; import com.raytheon.viz.awipstools.common.RangeRing;
@ -86,14 +86,14 @@ import com.vividsolutions.jts.geom.LineString;
* 07-11-12 #875 rferrel Move points to PointsDataManager. * 07-11-12 #875 rferrel Move points to PointsDataManager.
* 01-29-14 DR 16351 D. Friedman Fix updates to storm track from preferences. * 01-29-14 DR 16351 D. Friedman Fix updates to storm track from preferences.
* 04-02-14 DR 16351 D. Friedman Fix updates to storm track from preferences. (backport from 14.2.2) * 04-02-14 DR 16351 D. Friedman Fix updates to storm track from preferences. (backport from 14.2.2)
* 06-03-24 3191 njensen Improved saving/loading storm track data
* *
* </pre> * </pre>
* *
* @author bsteffen * @author bsteffen
* @version 1.0 * @version 1.0
*/ */
public class ToolsDataManager implements ILocalizationFileObserver, public class ToolsDataManager implements ILocalizationFileObserver {
IPropertyChangeListener {
private static final transient IUFStatusHandler statusHandler = UFStatus private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ToolsDataManager.class); .getHandler(ToolsDataManager.class);
@ -103,13 +103,9 @@ public class ToolsDataManager implements ILocalizationFileObserver,
private static final String P_RANGERING_LOCATIONS = "rangeRingLocations"; private static final String P_RANGERING_LOCATIONS = "rangeRingLocations";
private static final String P_STORMTRACK_SPEED = "stormSpeed"; private static final String TOOLS_DIR = "awipsTools";
private static final String P_STORMTRACK_ANGLE = "stormAngle"; private static final String STORM_TRACK_FILE = "stormTrackData.xml";
private static final String P_STORMTRACK_POINTS = "stormCoordinates";
private static final String P_STORMTRACK_DATE = "stormDate";
private static final int[] DEFAULT_LINE_RADIUS = { 120, 120, 120, 120, 240, private static final int[] DEFAULT_LINE_RADIUS = { 120, 120, 120, 120, 240,
240, 216, 216, 360, 360 }; 240, 216, 216, 360, 360 };
@ -140,8 +136,6 @@ public class ToolsDataManager implements ILocalizationFileObserver,
private boolean stormTrackDirty = false; private boolean stormTrackDirty = false;
private String site;
private LocalizationFile userToolsDir; private LocalizationFile userToolsDir;
private IPathManager pathMgr; private IPathManager pathMgr;
@ -156,19 +150,19 @@ public class ToolsDataManager implements ILocalizationFileObserver,
} }
private ToolsDataManager() { private ToolsDataManager() {
site = LocalizationManager.getInstance().getCurrentSite();
pathMgr = PathManagerFactory.getPathManager(); pathMgr = PathManagerFactory.getPathManager();
pointsManager = PointsDataManager.getInstance(); pointsManager = PointsDataManager.getInstance();
LocalizationContext userCtx = pathMgr.getContext( LocalizationContext userCtx = pathMgr.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.USER); LocalizationType.CAVE_STATIC, LocalizationLevel.USER);
/*
userToolsDir = pathMgr.getLocalizationFile(userCtx, "awipsTools" * TODO: Since it's already under the user localization, why does it
+ File.separator + site); * then want to have the site underneath that? If anyone knows, please
* document it and remove this TODO. PointsManager does a similar thing.
*/
userToolsDir = pathMgr.getLocalizationFile(userCtx, TOOLS_DIR
+ IPathManager.SEPARATOR
+ LocalizationManager.getInstance().getCurrentSite());
userToolsDir.addFileUpdatedObserver(this); userToolsDir.addFileUpdatedObserver(this);
CorePlugin.getDefault().getPreferenceStore()
.addPropertyChangeListener(this);
} }
public Collection<String> getBaselineNames() { public Collection<String> getBaselineNames() {
@ -253,67 +247,73 @@ public class ToolsDataManager implements ILocalizationFileObserver,
} }
private void loadStormData() { private void loadStormData() {
stormData = new StormTrackData(); IPathManager pathMgr = PathManagerFactory.getPathManager();
HierarchicalPreferenceStore store = (HierarchicalPreferenceStore) CorePlugin LocalizationFile f = pathMgr.getLocalizationFile(
.getDefault().getPreferenceStore(); userToolsDir.getContext(), userToolsDir.getName()
store.setDefault(P_STORMTRACK_SPEED, 35.0); + IPathManager.SEPARATOR + STORM_TRACK_FILE);
double speed = store.getDouble(P_STORMTRACK_SPEED); if (f.exists()) {
stormData.setMotionSpeed(speed); LocalizationFileInputStream is = null;
try {
store.setDefault(P_STORMTRACK_ANGLE, 60.0); is = f.openInputStream();
double angle = store.getDouble(P_STORMTRACK_ANGLE); stormData = JAXB.unmarshal(is, StormTrackData.class);
stormData.setMotionDirection(angle); } catch (Exception e) {
statusHandler.error("Error loading storm track data", e);
long date = store.getLong(P_STORMTRACK_DATE); stormData = defaultStormTrackData();
if (date > 0) { } finally {
stormData.setDate(new Date(date)); if (is != null) {
} try {
String[] points = store.getStringArray(P_STORMTRACK_POINTS); is.close();
if (points != null) { } catch (IOException e) {
setCoordinates(stormData, points); statusHandler.handle(Priority.DEBUG,
"Error closing storm track data input stream",
e);
}
}
}
} else {
stormData = defaultStormTrackData();
} }
stormTrackDirty = false; stormTrackDirty = false;
} }
private void setCoordinates(StormTrackData data, String[] points) { /**
Coordinate[] coords = new Coordinate[points.length]; * Creates and returns a default storm track data
for (int i = 0; i < points.length; ++i) { *
String[] latLon = points[i].split("[ ]"); * @return
try { */
coords[i] = new Coordinate(Double.parseDouble(latLon[0]), private static StormTrackData defaultStormTrackData() {
Double.parseDouble(latLon[1])); StormTrackData data = new StormTrackData();
} catch (NumberFormatException e) { data.setMotionSpeed(35.0);
statusHandler.handle(Priority.PROBLEM, data.setMotionDirection(60.0);
"Error reading storm track coordinates", e); data.setDate(SimulatedTime.getSystemTime().getTime());
coords = new Coordinate[0]; return data;
break;
}
}
data.setCoordinates(coords);
} }
private void storeStormData() { private void storeStormData() {
synchronized (stormLock) { synchronized (stormLock) {
// Update the store time // Update the store time
stormData.setDate(SimulatedTime.getSystemTime().getTime()); stormData.setDate(SimulatedTime.getSystemTime().getTime());
HierarchicalPreferenceStore store = (HierarchicalPreferenceStore) CorePlugin IPathManager pathMgr = PathManagerFactory.getPathManager();
.getDefault().getPreferenceStore(); LocalizationFile f = pathMgr.getLocalizationFile(
store.setValue(P_STORMTRACK_SPEED, stormData.getMotionSpeed()); userToolsDir.getContext(), userToolsDir.getName()
store.setValue(P_STORMTRACK_ANGLE, stormData.getMotionDirection()); + IPathManager.SEPARATOR + STORM_TRACK_FILE);
Coordinate[] coordinates = stormData.getCoordinates(); LocalizationFileOutputStream os = null;
if (coordinates != null) {
String[] coords = new String[coordinates.length];
for (int i = 0; i < coordinates.length; ++i) {
coords[i] = coordinates[i].x + " " + coordinates[i].y;
}
store.setValue(P_STORMTRACK_POINTS, coords);
}
store.setValue(P_STORMTRACK_DATE, stormData.getDate().getTime());
try { try {
store.save(); os = f.openOutputStream();
} catch (IOException e) { JAXB.marshal(stormData, os);
os.closeAndSave();
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM, statusHandler.handle(Priority.PROBLEM,
"Error saving storm track data", e); "Error saving storm track data", e);
try {
if (os != null) {
os.close();
}
} catch (IOException e1) {
statusHandler.handle(Priority.DEBUG,
"Error closing storm track data output stream", e1);
}
} }
} }
} }
@ -594,11 +594,18 @@ public class ToolsDataManager implements ILocalizationFileObserver,
*/ */
@Override @Override
public void fileUpdated(FileUpdatedMessage message) { public void fileUpdated(FileUpdatedMessage message) {
/*
* This will receive messages about points updates too, but since the
* PointsManager is listening for those we don't care.
*/
String fileName = new File(message.getFileName()).getName(); String fileName = new File(message.getFileName()).getName();
if (fileName.startsWith(BASELINE_PREFIX)) { if (fileName.startsWith(BASELINE_PREFIX)) {
baselineFileUpdated(fileName); baselineFileUpdated(fileName);
} else { } else if (fileName.equals(STORM_TRACK_FILE)) {
pointsManager.fileUpdated(message); stormTrackDirty = true;
for (Object listener : stormListeners.getListeners()) {
((IToolChangedListener) listener).toolChanged();
}
} }
} }
@ -643,44 +650,4 @@ public class ToolsDataManager implements ILocalizationFileObserver,
stormListeners.remove(listener); stormListeners.remove(listener);
} }
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
* .jface.util.PropertyChangeEvent)
*/
@Override
public void propertyChange(PropertyChangeEvent event) {
String key = event.getProperty();
if ((P_STORMTRACK_ANGLE.equals(key) || P_STORMTRACK_DATE.equals(key)
|| P_STORMTRACK_POINTS.equals(key) || P_STORMTRACK_SPEED
.equals(key)) && stormData != null) {
synchronized (stormLock) {
Object value = event.getNewValue();
if (P_STORMTRACK_ANGLE.equals(key) && value instanceof Double) {
stormData.setMotionDirection((Double) value);
} else if (P_STORMTRACK_DATE.equals(key)
&& value instanceof Long) {
stormData.setDate(new Date((Long) value));
} else if (P_STORMTRACK_POINTS.equals(key)
&& value instanceof String[]) {
setCoordinates(stormData, (String[]) value);
} else if (P_STORMTRACK_SPEED.equals(key)
&& value instanceof Double) {
stormData.setMotionSpeed((Double) value);
} else {
/* Incompatible value indicates update from preference
* store. We will want to reload.
*/
stormTrackDirty = true;
}
}
// fire listeners
for (Object listener : stormListeners.getListeners()) {
((IToolChangedListener) listener).toolChanged();
}
}
}
} }

View file

@ -21,10 +21,18 @@ package com.raytheon.viz.awipstools.common;
import java.util.Date; import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import com.raytheon.uf.common.serialization.adapters.CoordAdapter;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
/** /**
* TODO Add Description * Data representing a storm track that can be saved to XML
* *
* <pre> * <pre>
* *
@ -32,20 +40,29 @@ import com.vividsolutions.jts.geom.Coordinate;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Aug 12, 2009 bwoodle Initial creation * Aug 12, 2009 bwoodle Initial creation
* Jun 03, 2014 3191 njensen Added xml annotations
* *
* </pre> * </pre>
* *
* @author bwoodle * @author bwoodle
* @version 1.0 * @version 1.0
*/ */
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public class StormTrackData { public class StormTrackData {
@XmlJavaTypeAdapter(DateAdapter.class)
@XmlElement(name = "stormDate")
private Date date; private Date date;
@XmlElement(name = "stormAngle")
private double motionDirection; private double motionDirection;
@XmlElement(name = "stormSpeed")
private double motionSpeed; private double motionSpeed;
@XmlJavaTypeAdapter(CoordAdapter.class)
@XmlElement(name = "stormCoordinates")
private Coordinate[] coordinates; private Coordinate[] coordinates;
public StormTrackData() { public StormTrackData() {
@ -123,4 +140,19 @@ public class StormTrackData {
return date != null && !Double.isNaN(motionDirection) return date != null && !Double.isNaN(motionDirection)
&& !Double.isNaN(motionSpeed); && !Double.isNaN(motionSpeed);
} }
private static class DateAdapter extends XmlAdapter<Long, Date> {
@Override
public Date unmarshal(Long v) throws Exception {
return new Date(v);
}
@Override
public Long marshal(Date v) throws Exception {
return v.getTime();
}
}
} }

View file

@ -103,6 +103,9 @@ import com.vividsolutions.jts.geom.LineString;
* 04-07-2014 DR 17232 D. Friedman Make sure pivot indexes are valid. * 04-07-2014 DR 17232 D. Friedman Make sure pivot indexes are valid.
* 04-24-2014 DR 16356 Qinglu Lin Updated generateTrackInfo(), generateNewTrackInfo(), * 04-24-2014 DR 16356 Qinglu Lin Updated generateTrackInfo(), generateNewTrackInfo(),
* and createTrack(). * and createTrack().
* 06-03-14 3191 njensen Fix postData to not retrieve
* 06-17-2014 DR17409 mgamazaychikov Fix futurePoints calculation in generateNewTrackInfo()
* and generateExistingTrackInfo()
* *
* </pre> * </pre>
* *
@ -938,7 +941,7 @@ public class StormTrackDisplay implements IRenderable {
// time, the arrow of the pathcast is drawn behind the last frame // time, the arrow of the pathcast is drawn behind the last frame
if (state.duration >= 0) { if (state.duration >= 0) {
for (int i = 1; i < futurePoints.length - (remainder == 0 ? 0 : 1); ++i) { 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)); DataTime time = new DataTime(new Date(timeInMillis));
double distance = speed double distance = speed
@ -1095,7 +1098,7 @@ public class StormTrackDisplay implements IRenderable {
// time, the arrow of the pathcast is drawn behind the last frame // time, the arrow of the pathcast is drawn behind the last frame
if (state.duration >= 0) { if (state.duration >= 0) {
for (int i = 1; i < futurePoints.length - (remainder == 0 ? 0 : 1); ++i) { 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)); DataTime time = new DataTime(new Date(timeInMillis));
double distance = speed double distance = speed
@ -1437,7 +1440,7 @@ public class StormTrackDisplay implements IRenderable {
} }
private void postData(StormTrackState state) { private void postData(StormTrackState state) {
StormTrackData data = dataManager.getStormTrackData(); StormTrackData data = new StormTrackData();
Coordinate[] coords = new Coordinate[state.timePoints.length]; Coordinate[] coords = new Coordinate[state.timePoints.length];
for (int i = 0; i < coords.length; ++i) { for (int i = 0; i < coords.length; ++i) {
coords[i] = new Coordinate(state.timePoints[i].coord); coords[i] = new Coordinate(state.timePoints[i].coord);

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

View file

@ -19,9 +19,12 @@
**/ **/
package com.raytheon.viz.gfe.dialogs.sbu; package com.raytheon.viz.gfe.dialogs.sbu;
import java.util.Set;
import com.raytheon.uf.common.auth.user.IUser; 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.CheckPermissionsRequest;
import com.raytheon.uf.common.dataplugin.gfe.request.CheckServiceBackupPrimarySiteRequest; 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.dataplugin.gfe.server.message.ServerResponse;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; 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 * Jul 22, 2013 #1762 dgilling Ensure all fields of
* CheckServiceBackupPrimarySiteRequest are * CheckServiceBackupPrimarySiteRequest are
* filled. * filled.
* * Jun 10, 2013 DR-17401 lshi Added getPrimarySites()
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
@ -104,4 +107,21 @@ public class CheckPermissions {
} }
return false; 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

@ -99,6 +99,7 @@ import com.raytheon.viz.ui.dialogs.CaveJFACEDialog;
* May 01, 2013 1762 dgilling Remove national center check. * May 01, 2013 1762 dgilling Remove national center check.
* Jul 22, 2013 1762 dgilling Fix running as primary check. * Jul 22, 2013 1762 dgilling Fix running as primary check.
* Apr 14, 2014 2984 njensen Moved help files to viz.gfe plugin * Apr 14, 2014 2984 njensen Moved help files to viz.gfe plugin
* Jun 10,2014 DR-17401 lshi
* *
* </pre> * </pre>
* *
@ -166,8 +167,15 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
private boolean authorized; private boolean authorized;
private SVCBU_OP currentOperation = SVCBU_OP.no_backup; private SVCBU_OP currentOperation = SVCBU_OP.no_backup;
private boolean isTerminated = false;
/** public boolean isTerminated() {
return isTerminated;
}
/**
* @param parentShell * @param parentShell
*/ */
public ServiceBackupDlg(Shell parentShell) { public ServiceBackupDlg(Shell parentShell) {
@ -175,6 +183,13 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
authorized = CheckPermissions.getAuthorization(); authorized = CheckPermissions.getAuthorization();
this.site = LocalizationManager.getInstance().getCurrentSite(); this.site = LocalizationManager.getInstance().getCurrentSite();
this.runningAsPrimary = CheckPermissions.runningAsPrimary(this.site); 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()) { if (!ServiceBackupJobManager.getInstance().isRunning()) {
ServiceBackupJobManager.getInstance().start(); ServiceBackupJobManager.getInstance().start();
} }
@ -182,7 +197,6 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
progress = new ProgressDlg(getShell()); progress = new ProgressDlg(getShell());
progress.setBlockOnOpen(false); progress.setBlockOnOpen(false);
updateJob = new Job("SvcbuUpdateJob") { updateJob = new Job("SvcbuUpdateJob") {
@Override @Override
protected IStatus run(IProgressMonitor monitor) { protected IStatus run(IProgressMonitor monitor) {
VizApp.runAsync(new Runnable() { VizApp.runAsync(new Runnable() {
@ -230,7 +244,7 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
@Override @Override
public boolean close() { public boolean close() {
updateJob.cancel(); updateJob.cancel();
return super.close(); return super.close();
} }
/* /*
@ -481,7 +495,7 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
} }
private void doImportConfig() { private void doImportConfig() {
switch (currentOperation) { switch (currentOperation) {
case svcbuMode: case svcbuMode:
displayMessage("" + this.failedSite.toUpperCase() displayMessage("" + this.failedSite.toUpperCase()
@ -537,7 +551,7 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
if (startGFE) { if (startGFE) {
jobManager.addJob(new SvcbuStartGfeJob(failedSite, jobManager.addJob(new SvcbuStartGfeJob(failedSite,
this.site)); this.site));
} }
} }
} }
} }
@ -765,7 +779,7 @@ public class ServiceBackupDlg extends CaveJFACEDialog {
jobManager.addJob(new SvcbuExitJob(this, this.site)); jobManager.addJob(new SvcbuExitJob(this, this.site));
} }
} }
} }
private void doClean(boolean showMessage) { private void doClean(boolean showMessage) {

View file

@ -94,6 +94,7 @@ import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
* fields when magnification set to 0 * fields when magnification set to 0
* Feb 27, 2013 DCS 152 jgerth/elau Support for WWLLN and multiple sources * Feb 27, 2013 DCS 152 jgerth/elau Support for WWLLN and multiple sources
* Jan 21, 2014 2667 bclement renamed record's lightSource field to source * Jan 21, 2014 2667 bclement renamed record's lightSource field to source
* Jun 6, 2014 DR 17367 D. Friedman Fix cache object usage.
* *
* </pre> * </pre>
* *
@ -480,6 +481,24 @@ public class LightningResource extends
*/ */
@Override @Override
public void remove(DataTime dataTime) { 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); dataTimes.remove(dataTime);
cacheObjectMap.remove(dataTime); cacheObjectMap.remove(dataTime);
} }
@ -523,20 +542,20 @@ public class LightningResource extends
List<BinLightningRecord> records = entry.getValue(); List<BinLightningRecord> records = entry.getValue();
CacheObject<LightningFrameMetadata, LightningFrame> co = cacheObjectMap
.get(dt);
LightningFrameMetadata frame; LightningFrameMetadata frame;
if (co == null) { CacheObject<LightningFrameMetadata, LightningFrame> co;
// New frame synchronized (cacheObjectMap) {
frame = new LightningFrameMetadata(dt, co = cacheObjectMap.get(dt);
resourceData.getBinOffset(), this.lightSource); if (co == null) {
co = CacheObject.newCacheObject(frame, resourceBuilder); // New frame
cacheObjectMap.put(dt, co); LightningFrameMetadata key = new LightningFrameMetadata(dt,
dataTimes.add(dt); resourceData.getBinOffset(), this.lightSource);
} else { co = CacheObject.newCacheObject(key, resourceBuilder);
// Frame exists cacheObjectMap.put(dt, co);
frame = co.getMetadata(); dataTimes.add(dt);
}
} }
frame = co.getMetadata();
synchronized (frame) { synchronized (frame) {
// Add as new records // Add as new records

View file

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

View file

@ -280,6 +280,13 @@
<constructor-arg ref="CheckPrimarySiteHandler"/> <constructor-arg ref="CheckPrimarySiteHandler"/>
</bean> </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 id="CleanupSvcBuLogRequestHandler" class="com.raytheon.edex.plugin.gfe.server.handler.svcbu.CleanupSvcBuLogRequestHandler"/>
<bean factory-bean="handlerRegistry" factory-method="register"> <bean factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.dataplugin.gfe.request.CleaunpSvcBuLogRequest"/> <constructor-arg value="com.raytheon.uf.common.dataplugin.gfe.request.CleaunpSvcBuLogRequest"/>

View file

@ -20,9 +20,9 @@
<constructor-arg ref="smartInitSrv"/> <constructor-arg ref="smartInitSrv"/>
</bean> </bean>
<bean id="spcWatch" class="com.raytheon.edex.plugin.gfe.spc.SPCWatchSrv"/> <bean id="spcWatch" class="com.raytheon.edex.plugin.gfe.watch.SPCWatchSrv" />
<bean id="tpcWatch" class="com.raytheon.edex.plugin.gfe.tpc.TPCWatchSrv"/> <bean id="tpcWatch" class="com.raytheon.edex.plugin.gfe.watch.TPCWatchSrv" />
<bean id="wclWatch" class="com.raytheon.edex.plugin.gfe.wcl.WCLWatchSrv"/> <bean id="wclWatch" class="com.raytheon.edex.plugin.gfe.watch.WCLWatchSrv" />
<bean id="vtecChangeListener" class="com.raytheon.edex.plugin.gfe.server.notify.VTECTableChangeListener"/> <bean id="vtecChangeListener" class="com.raytheon.edex.plugin.gfe.server.notify.VTECTableChangeListener"/>
@ -32,7 +32,7 @@
<route id="SPCWatch"> <route id="SPCWatch">
<from uri="vm:gfe.spcWatch"/> <from uri="vm:gfe.spcWatch"/>
<doTry> <doTry>
<bean ref="spcWatch" method="handleSpcWatch"/> <bean ref="spcWatch" method="handleWatch" />
<doCatch> <doCatch>
<exception>java.lang.Throwable</exception> <exception>java.lang.Throwable</exception>
<to <to
@ -44,7 +44,7 @@
<route id="TPCWatch"> <route id="TPCWatch">
<from uri="vm:gfe.tpcWatch"/> <from uri="vm:gfe.tpcWatch"/>
<doTry> <doTry>
<bean ref="tpcWatch" method="handleTpcWatch"/> <bean ref="tpcWatch" method="handleWatch" />
<doCatch> <doCatch>
<exception>java.lang.Throwable</exception> <exception>java.lang.Throwable</exception>
<to <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.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; 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.config.GFESiteActivation;
import com.raytheon.edex.plugin.gfe.util.SendNotifications; 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.dataplugin.gfe.server.notify.UserMessageNotification;
import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext; 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.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.PathManagerFactory; 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.status.UFStatus.Priority;
import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.SimulatedTime;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.uf.edex.core.EdexException; 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 { public class WCLWatchSrv {
private static final String ALERT_FORM = "Alert: " + "%1$s has arrived. " private static final String ALERT_FORM = "Alert: " + "%1$s has arrived. "
+ "Please select ViewWCL and use %1$s. (Hazards menu)"; + "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 private static final Pattern EXPIRE_TIME_PATTERN = Pattern
.compile("(\\d{2})(\\d{2})(\\d{2})\\-"); .compile("(\\d{2})(\\d{2})(\\d{2})\\-");
@ -81,36 +91,8 @@ public class WCLWatchSrv {
private static final Pattern UGC_PATTERN = Pattern.compile("\\d{3}\\-"); private static final Pattern UGC_PATTERN = Pattern.compile("\\d{3}\\-");
protected transient Log logger = LogFactory.getLog(getClass()); private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(WCLWatchSrv.class);
/**
* 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;
}
/** /**
* Process a WCL watch, partially parsed and passed as a WclInfo object. * 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. * or when there are problems generating the WCL script file.
*/ */
public void handleWclWatch(WclInfo wclInfo) throws EdexException { public void handleWclWatch(WclInfo wclInfo) throws EdexException {
logger.debug("handleWclWatch started"); statusHandler.debug("handleWclWatch started");
UserMessageNotification notice = null; Collection<String> sitesToNotify = WatchProductUtil
String completeProductPil = wclInfo.getCompleteProductPil(); .findAttnWFOs(wclInfo.getLines());
Set<String> wfos = attnWFOs(wclInfo.getLines());
Set<String> siteIDs = getSiteIDs(); Set<String> siteIDs = getSiteIDs();
wfos.retainAll(siteIDs); // Keep shared IDs boolean doNotify = true;
if (!wfos.isEmpty()) {
// Get the first matching site ID
String siteID = wfos.toArray(new String[1])[0];
String msg = String.format(ALERT_FORM, completeProductPil); sitesToNotify.retainAll(siteIDs); // Keep shared IDs
notice = new UserMessageNotification(msg, Priority.CRITICAL, "GFE", if (sitesToNotify.isEmpty()) {
siteID); statusHandler.debug("WCL notification: sites not in ATTN list");
doNotify = false;
} }
// Process the WCL regardless of whether we are sending a notice // Process the WCL regardless of whether we are sending a notice
@ -160,96 +139,83 @@ public class WCLWatchSrv {
// Get the watch type // Get the watch type
String watchType = getWatchType(wclInfo); String watchType = getWatchType(wclInfo);
// Get the WCL 'letter'
String completeProductPil = wclInfo.getCompleteProductPil();
// Create a dummy Procedure for export // Create a dummy Procedure for export
String wclStr = makeWclStr(finalUGCList, expireTime, issueTime, String wclStr = makeWclStr(finalUGCList, expireTime, issueTime,
watchType); watchType);
logger.debug("WCLData: " + wclStr); statusHandler.info("WCLData: " + wclStr);
// Write dummy procedure to temp file // Write dummy procedure to temp file
File tmpFile = createTempWclFile(wclStr); File tmpFile = createTempWclFile(wclStr);
// Move the file to the wcl folder // Move the file to the wcl folder
// Rename it to <wclDir>/<completeProductPil> // Rename it to <wclDir>/<completeProductPil>
makePermanent(tmpFile, completeProductPil); statusHandler.info("Placing WCL Procedure Utility in ifpServer ");
try {
if (notice == null || !wclInfo.getNotify()) { makePermanent(tmpFile, completeProductPil, siteIDs);
logger.info("Notification of WCL skipped"); } finally {
} else { if (tmpFile != null) {
SendNotifications.send(notice); tmpFile.delete();
}
} }
logger.debug("handleWclWatch() ending"); if (doNotify && wclInfo.getNotify()) {
return; 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 * Convert a temporary parsed WCL file to a permanent one by copying its
* the WCL directory. This is done through File.renameTo(). Unfortunately, * contents to the localization path cave_static.SITE/gfe/wcl/ for each of
* that method returns a boolean success flag rather than throwing an error, * the specified sites.
* so all we can do is tell the user that the rename failed, not why.
* *
* @param tmpFile * @param tmpFile
* The temporary file (may be null) * The temporary file (may be {@code null})
* @param completeProductPil * @param completeProductPil
* The simple name of the file. * The base name of the files to write.
* @throws EdexException * @param siteIDs
* if tmpFile cannot be renamed. * The set of siteIDs to write out the WCL data for.
*/ */
protected void makePermanent(File tmpFile, String completeProductPil) protected void makePermanent(File tmpFile, String completeProductPil,
throws EdexException { Collection<String> siteIDs) {
logger.debug("makePermanent(" + tmpFile + "," + completeProductPil statusHandler.debug("makePermanent(" + tmpFile + ","
+ ") started"); + completeProductPil + ") started");
if (tmpFile != null) { if (tmpFile != null) {
File wclDir = getWclDir(); for (String siteID : siteIDs) {
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;
try { try {
temp = new FileInputStream(tmpFile).getChannel(); File wclDir = getWclDir(siteID);
perm = new FileOutputStream(dest).getChannel(); if (wclDir != null) {
// should file range be locked before copy? File dest = new File(wclDir, completeProductPil);
temp.transferTo(0, temp.size(), perm); FileUtil.copyFile(tmpFile, dest);
temp.close(); statusHandler.info("Wrote WCL "
tmpFile.delete(); + tmpFile.getAbsolutePath() + " to "
+ dest.getAbsolutePath());
} else {
statusHandler
.error("Could not determine WCL directory for site "
+ siteID);
}
} catch (IOException e) { } catch (IOException e) {
throw new EdexException("Renaming \"" statusHandler.error("Could not copy temporary WCL file "
+ tmpFile.getAbsolutePath() + "\" to \"" + tmpFile.getAbsolutePath()
+ dest.getAbsolutePath() + "\" failed.", e); + " to site directory for " + siteID, 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);
} }
} }
// 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; File tmpFile = null;
PrintStream wclOut = null; PrintStream wclOut = null;
try { try {
tmpFile = File.createTempFile("wcl", null, null); tmpFile = File.createTempFile("wcl", null);
wclOut = new PrintStream(tmpFile); wclOut = new PrintStream(tmpFile);
wclOut.println(wclStr); wclOut.println(wclStr);
} catch (IOException e) { } catch (IOException e) {
@ -445,19 +411,23 @@ public class WCLWatchSrv {
* getSiteIDs(), this is in a method rather than inline so that test code * getSiteIDs(), this is in a method rather than inline so that test code
* can override it in subclasses. * can override it in subclasses.
* *
* @param siteID
* The siteID to write the WCL file for.
*
* @return the directory, as a File. * @return the directory, as a File.
*/ */
protected File getWclDir() { protected File getWclDir(String siteID) {
IPathManager pathManager = PathManagerFactory.getPathManager(); IPathManager pathManager = PathManagerFactory.getPathManager();
LocalizationContext ctx = pathManager.getContext( LocalizationContext ctx = pathManager.getContextForSite(
LocalizationType.CAVE_STATIC, LocalizationLevel.SITE); LocalizationType.CAVE_STATIC, siteID);
String wclName = "gfe" + File.separator + "wcl"; String wclName = FileUtil.join("gfe", "wcl");
File wclDir = pathManager.getFile(ctx, wclName); File wclDir = pathManager.getFile(ctx, wclName);
if (wclDir == null) { if (wclDir == null) {
logger.error("Path manager could not locate " + wclName); statusHandler.error("Path manager could not locate " + wclName);
} else if (!wclDir.exists()) { } else if (!wclDir.exists()) {
wclDir.mkdir(); wclDir.mkdir();
logger.info("Directory " + wclDir.getAbsolutePath() + " created."); statusHandler.info("Directory " + wclDir.getAbsolutePath()
+ " created.");
} }
return wclDir; 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.Collections;
import java.util.Date; import java.util.Date;

View file

@ -30,6 +30,7 @@
<alias base="GeH">geh</alias> <alias base="GeH">geh</alias>
<alias base="GH">gh</alias> <alias base="GH">gh</alias>
<alias base="GVV">gvv</alias> <alias base="GVV">gvv</alias>
<alias base="HAILPROB">hailprob</alias>
<alias base="Heli">heli</alias> <alias base="Heli">heli</alias>
<alias base="HIdx">hidx</alias> <alias base="HIdx">hidx</alias>
<alias base="HTSGW">htsgw</alias> <alias base="HTSGW">htsgw</alias>
@ -48,14 +49,20 @@
<alias base="PoT">pot</alias> <alias base="PoT">pot</alias>
<alias base="P">p</alias> <alias base="P">p</alias>
<alias base="PR">pr</alias> <alias base="PR">pr</alias>
<alias base="PRSVR">prsvr</alias>
<alias base="PRSIGSV">prsigsv</alias>
<alias base="PVV">pvv</alias> <alias base="PVV">pvv</alias>
<alias base="PW">pw</alias> <alias base="PW">pw</alias>
<alias base="RH">rh</alias> <alias base="RH">rh</alias>
<alias base="SCP">scp</alias> <alias base="SCP">scp</alias>
<alias base="SHF">shf</alias> <alias base="SHF">shf</alias>
<alias base="SH">sh</alias> <alias base="SH">sh</alias>
<alias base="SIGHAILPROB">sighailprob</alias>
<alias base="SIGTRNDPROB">sigtrndprob</alias>
<alias base="SIGWINDPROB">sigwindprob</alias>
<alias base="SLI">sli</alias> <alias base="SLI">sli</alias>
<alias base="SnD">snd</alias> <alias base="SnD">snd</alias>
<alias base="SRCONO">srcono</alias>
<alias base="SVV">svv</alias> <alias base="SVV">svv</alias>
<alias base="SWDIR">swdir</alias> <alias base="SWDIR">swdir</alias>
<alias base="SWELL">swell</alias> <alias base="SWELL">swell</alias>
@ -81,6 +88,7 @@
<alias base="WEASD">weasd</alias> <alias base="WEASD">weasd</alias>
<alias base="WGH">wgh</alias> <alias base="WGH">wgh</alias>
<alias base="WGS">wgs</alias> <alias base="WGS">wgs</alias>
<alias base="WINDPROB">windprob</alias>
<alias base="WS">ws</alias> <alias base="WS">ws</alias>
<alias base="WVDIR">wvdir</alias> <alias base="WVDIR">wvdir</alias>
<alias base="WVHGT">wvhgt</alias> <alias base="WVHGT">wvhgt</alias>

View file

@ -42,6 +42,7 @@
# 04/17/14 2934 dgilling Remove alias for TPCSurgeProb D2D database. # 04/17/14 2934 dgilling Remove alias for TPCSurgeProb D2D database.
# 05/09/2014 3148 randerso Add tpHPCndfd to D2DAccumulativeElements for HPCERP # 05/09/2014 3148 randerso Add tpHPCndfd to D2DAccumulativeElements for HPCERP
# #
# 05/29/2014 3224 randerso Added "SPC":8 to D2DDBVERSIONS
######################################################################## ########################################################################
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
@ -1034,6 +1035,7 @@ D2DDBVERSIONS = {
"TPCStormSurge": 1, "TPCStormSurge": 1,
"CRMTopo": 1, "CRMTopo": 1,
"NED": 1, "NED": 1,
"SPC": 8,
} }
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View file

@ -491,7 +491,7 @@ class IrtAccess():
self.logEvent("Transmit: ", cmd) self.logEvent("Transmit: ", cmd)
import siteConfig import siteConfig
from subprocess import Popen,PIPE from subprocess import Popen,PIPE
output,err = Popen(cmd.split(" "), stdout=PIPE,stderr=PIPE).communicate() output,err = Popen(cmd, shell=True, stdout=PIPE,stderr=PIPE).communicate()
if output.find(siteConfig.GFESUITE_MHSID+"-") == -1: if output.find(siteConfig.GFESUITE_MHSID+"-") == -1:
alertMsg = "ISC Send failed transmission to : "+",".join(addresses)+" --> "+output+" "+err alertMsg = "ISC Send failed transmission to : "+",".join(addresses)+" --> "+output+" "+err
self.logProblem(alertMsg) self.logProblem(alertMsg)

View file

@ -209,4 +209,19 @@
<level>SFC</level> <level>SFC</level>
</levels> </levels>
</gridParameterInfo> </gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>srcono</short_name>
<long_name>Convective Outlook</long_name>
<units>1</units>
<udunits>category</udunits>
<uiname>srcono</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
</gridParamInfo> </gridParamInfo>

View file

@ -107,11 +107,5 @@
<processorName>RUC130GribPostProcessor</processorName> <processorName>RUC130GribPostProcessor</processorName>
</postProcessedModel> </postProcessedModel>
<!-- Post processor definition for the TPCSurgeProb model -->
<postProcessedModel>
<modelName>TPCSurgeProb</modelName>
<processorName>TPCSurgeProbPostProcessor</processorName>
</postProcessedModel>
</postProcessedModels> </postProcessedModels>

View file

@ -147,7 +147,7 @@
<pipeline> <pipeline>
<bean ref="stringToFile" /> <bean ref="stringToFile" />
<bean ref="shefDecoder" method="decode" /> <bean ref="shefDecoder" method="decode" />
<bean ref="processUtil" method="log"/> <bean ref="processUtil" method="log"/>
</pipeline> </pipeline>
<doCatch> <doCatch>
<exception>java.lang.Throwable</exception> <exception>java.lang.Throwable</exception>

View file

@ -84,6 +84,7 @@ import com.raytheon.uf.common.dataplugin.shef.util.ShefQC;
import com.raytheon.uf.common.ohd.AppsDefaults; import com.raytheon.uf.common.ohd.AppsDefaults;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.edex.database.dao.CoreDao; import com.raytheon.uf.edex.database.dao.CoreDao;
import com.raytheon.uf.edex.database.dao.DaoConfig; import com.raytheon.uf.edex.database.dao.DaoConfig;
import com.raytheon.uf.edex.decodertools.time.TimeTools; import com.raytheon.uf.edex.decodertools.time.TimeTools;
@ -120,6 +121,8 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools;
* 04/24/2014 16904 lbousaidi gross check should be applied to adjusted value. * 04/24/2014 16904 lbousaidi gross check should be applied to adjusted value.
* 04/29/2014 3088 mpduff Change logging class, clean up/optimization. * 04/29/2014 3088 mpduff Change logging class, clean up/optimization.
* Updated with more performance fixes. * Updated with more performance fixes.
* 05/28/2014 3222 mpduff Fix posting time to be processed time so db doesn't show all post times the same
* 06/02/2014 mpduff Fix for caching of range checks.
* </pre> * </pre>
* *
* @author mduff * @author mduff
@ -292,6 +295,39 @@ public class PostShef {
/** Forecast query results */ /** Forecast query results */
private Object[] queryForecastResults; private Object[] queryForecastResults;
/** Location range data found flag */
private boolean locRangeFound = false;
/** Default range data found flag */
private boolean defRangeFound = false;
/** Valid date range flag */
private boolean validDateRange = false;
/** Gross range minimum value */
private double grossRangeMin = ShefConstants.SHEF_MISSING_INT;
/** Gross range maximum value */
private double grossRangeMax = ShefConstants.SHEF_MISSING_INT;
/** Reasonable range minimum value */
private double reasonRangeMin = ShefConstants.SHEF_MISSING_INT;
/** Reasonable range maximum value */
private double reasonRangeMax = ShefConstants.SHEF_MISSING_INT;
/** Alert upper limit value */
private double alertUpperLimit = ShefConstants.SHEF_MISSING_INT;
/** Alarm upper limit value */
private double alarmUpperLimit = ShefConstants.SHEF_MISSING_INT;
/** Alert lower limit value */
private double alertLowerLimit = ShefConstants.SHEF_MISSING_INT;
/** Alarm lower limit value */
private double alarmLowerLimit = ShefConstants.SHEF_MISSING_INT;
/** /**
* *
* @param date * @param date
@ -459,6 +495,8 @@ public class PostShef {
return; return;
} }
postDate.setTime(getToNearestSecond(TimeUtil
.currentTimeMillis()));
boolean same_lid_product = false; boolean same_lid_product = false;
String dataValue = data.getStringValue(); String dataValue = data.getStringValue();
@ -477,6 +515,7 @@ public class PostShef {
data.setCreationDate("1970-01-01 00:00:00"); data.setCreationDate("1970-01-01 00:00:00");
} }
locId = data.getLocationId();
String key = locId + prodId + data.getObservationTime(); String key = locId + prodId + data.getObservationTime();
if (idLocations.containsKey(key)) { if (idLocations.containsKey(key)) {
postLocData = idLocations.get(key); postLocData = idLocations.get(key);
@ -730,7 +769,7 @@ public class PostShef {
* shefrec structure * shefrec structure
*/ */
if (!dataValue.equals(ShefConstants.SHEF_MISSING)) { if (!dataValue.equals(ShefConstants.SHEF_MISSING)) {
adjustRawValue(locId, data); adjustRawValue(locId, data);
} }
dataValue = data.getStringValue(); dataValue = data.getStringValue();
@ -1073,6 +1112,18 @@ public class PostShef {
useTs = null; useTs = null;
basisTimeValues = null; basisTimeValues = null;
previousQueryForecast = null; previousQueryForecast = null;
locRangeFound = false;
defRangeFound = false;
validDateRange = false;
grossRangeMin = ShefConstants.SHEF_MISSING_INT;
grossRangeMax = ShefConstants.SHEF_MISSING_INT;
reasonRangeMin = ShefConstants.SHEF_MISSING_INT;
reasonRangeMax = ShefConstants.SHEF_MISSING_INT;
alertUpperLimit = ShefConstants.SHEF_MISSING_INT;
alarmUpperLimit = ShefConstants.SHEF_MISSING_INT;
alertLowerLimit = ShefConstants.SHEF_MISSING_INT;
alarmLowerLimit = ShefConstants.SHEF_MISSING_INT;
} }
/** /**
@ -2101,9 +2152,9 @@ public class PostShef {
String telem = null; String telem = null;
String sql = null; String sql = null;
Object[] oa = null; Object[] oa = null;
String key = locId + data.getPeTsE();
try { try {
if (!ingestSwitchMap.containsKey(locId)) { if (!ingestSwitchMap.containsKey(key)) {
errorMsg.append("Error getting connection to IHFS Database"); errorMsg.append("Error getting connection to IHFS Database");
sql = "select lid, pe, dur, ts, extremum, ts_rank, ingest, ofs_input, stg2_input from IngestFilter where lid = '" sql = "select lid, pe, dur, ts, extremum, ts_rank, ingest, ofs_input, stg2_input from IngestFilter where lid = '"
+ locId + "'"; + locId + "'";
@ -2140,11 +2191,11 @@ public class PostShef {
} }
} }
ingestSwitchMap.put(locId, ingestSwitch); ingestSwitchMap.put(key, ingestSwitch);
} }
matchFound = ingestSwitchMap.containsKey(locId); matchFound = ingestSwitchMap.containsKey(key);
ingestSwitch = ingestSwitchMap.get(locId); ingestSwitch = ingestSwitchMap.get(key);
/* /*
* if there is no ingest record for this entry, then check if the * if there is no ingest record for this entry, then check if the
@ -2538,6 +2589,8 @@ public class PostShef {
*/ */
private void postProductLink(String locId, String productId, Date obsTime) { private void postProductLink(String locId, String productId, Date obsTime) {
PersistableDataObject link = null; PersistableDataObject link = null;
postDate.setTime(getToNearestSecond(TimeUtil.currentTimeMillis()));
try { try {
/* Get a Data Access Object */ /* Get a Data Access Object */
link = new Productlink(new ProductlinkId(locId, productId, obsTime, link = new Productlink(new ProductlinkId(locId, productId, obsTime,
@ -2575,14 +2628,6 @@ public class PostShef {
long qualityCode = ShefConstants.DEFAULT_QC_VALUE; long qualityCode = ShefConstants.DEFAULT_QC_VALUE;
String monthdaystart = null; String monthdaystart = null;
String monthdayend = null; String monthdayend = null;
double grossRangeMin = missing;
double grossRangeMax = missing;
double reasonRangeMin = missing;
double reasonRangeMax = missing;
double alertUpperLimit = missing;
double alarmUpperLimit = missing;
double alertLowerLimit = missing;
double alarmLowerLimit = missing;
alertAlarm = ShefConstants.NO_ALERTALARM; alertAlarm = ShefConstants.NO_ALERTALARM;
@ -2601,10 +2646,6 @@ public class PostShef {
return ShefConstants.QC_MANUAL_FAILED; return ShefConstants.QC_MANUAL_FAILED;
} }
boolean locRangeFound = false;
boolean defRangeFound = false;
boolean validDateRange = false;
boolean executeQuery = true; boolean executeQuery = true;
if (!qualityCheckFlag) { if (!qualityCheckFlag) {
// If qualityCheckFlag is false the the query has already been // If qualityCheckFlag is false the the query has already been
@ -2916,6 +2957,7 @@ public class PostShef {
ShefData data, String locId, String tableName, String dataValue, ShefData data, String locId, String tableName, String dataValue,
String qualifier, long qualityCode) { String qualifier, long qualityCode) {
PersistableDataObject dataObj = null; PersistableDataObject dataObj = null;
postDate.setTime(getToNearestSecond(TimeUtil.currentTimeMillis()));
if (ShefConstants.COMMENT_VALUE.equalsIgnoreCase(tableName)) { if (ShefConstants.COMMENT_VALUE.equalsIgnoreCase(tableName)) {
Commentvalue comment = new Commentvalue(new CommentvalueId()); Commentvalue comment = new Commentvalue(new CommentvalueId());
@ -3164,6 +3206,19 @@ public class PostShef {
return dataObj; return dataObj;
} }
/**
* Convert the provided millisecond value to the nearest second.
*
* @param time
* time in milliseconds
*
* @return milliseconds rounded to the nearest second.
*/
private long getToNearestSecond(long time) {
// Force time to nearest second.
return time - (time % 1000);
}
public void close() { public void close() {
postTables.close(); postTables.close();
} }

View file

@ -41,6 +41,7 @@
# Sep 12, 2013 2249 rferrel When incoming file from warngen adjust # Sep 12, 2013 2249 rferrel When incoming file from warngen adjust
# start time from file's timestamp. # start time from file's timestamp.
# Oct 03, 2013 2402 bsteffen Make PythonDecoder more extendable. # Oct 03, 2013 2402 bsteffen Make PythonDecoder more extendable.
# Jun 10, 2014 3268 dgilling Update location of WclInfo class.
# </pre> # </pre>
# #
@ -174,7 +175,7 @@ class StdWarningDecoder():
if self._productPil[0:3] == "WCL": if self._productPil[0:3] == "WCL":
endpoint = "WCLWatch" endpoint = "WCLWatch"
# build a Java object for the warning # 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 import JUtil
lines = JUtil.pyValToJavaObj(self._lines) lines = JUtil.pyValToJavaObj(self._lines)
warning = WclInfo(long(self._issueTime * 1000), 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. * to areaFields.
* Jan 9, 2013 15600 Qinglu Lin Execute "timezones = myTimeZones;" even if timezones != null. * Jan 9, 2013 15600 Qinglu Lin Execute "timezones = myTimeZones;" even if timezones != null.
* Oct 22, 2013 2361 njensen Use JAXBManager for XML * Oct 22, 2013 2361 njensen Use JAXBManager for XML
* Jun 17, 2014 DR 17390 Qinglu Lin Updated getMetaDataMap() for lonField and latField.
* *
* </pre> * </pre>
* *
@ -216,6 +217,9 @@ public class GeospatialFactory {
areaFields.add(feAreaField); areaFields.add(feAreaField);
} }
areaFields.add("LON");
areaFields.add("LAT");
if (timeZoneField != null) { if (timeZoneField != null) {
areaFields.add(timeZoneField); areaFields.add(timeZoneField);
} }

View file

@ -21,6 +21,7 @@
package com.raytheon.uf.common.dataplugin.warning.portions; package com.raytheon.uf.common.dataplugin.warning.portions;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
@ -29,6 +30,7 @@ import java.util.List;
import org.geotools.referencing.GeodeticCalculator; 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.Coordinate;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.GeometryFactory;
@ -54,6 +56,8 @@ import com.vividsolutions.jts.geom.GeometryFactory;
* May 1, 2013 1963 jsanchez Refactored calculatePortion to match A1. Do not allow 'Central' to be included if East and West is included. * 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 3, 2013 2029 jsanchez Updated A1 special case for calculating a central portion. Allowed East Central and West Central.
* Dec 4, 2013 2604 jsanchez Moved out of viz.warngen. * Dec 4, 2013 2604 jsanchez Moved out of viz.warngen.
* Jun 17, 2014 DR 17390 Qinglu Lin Update calculateLocationPortion(). Use centroid in maps county table for geomCentroid
* for county based products.
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -345,13 +349,22 @@ public class GisUtil {
* @return * @return
*/ */
public static EnumSet<Direction> calculateLocationPortion( 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++) { for (int i = 0; i < locationGeom.getNumGeometries(); i++) {
Geometry geom = locationGeom.getGeometryN(i); Geometry geom = locationGeom.getGeometryN(i);
if (geom.intersects(reference)) { if (geom.intersects(reference)) {
Coordinate geomCentroid = geom.getEnvelope().getCentroid() Coordinate geomCentroid = null;
.getCoordinate(); 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() Coordinate refCentroid = reference.getCentroid()
.getCoordinate(); .getCoordinate();

View file

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.geotools.coverage.grid.GeneralGridGeometry; import org.geotools.coverage.grid.GeneralGridGeometry;
import com.raytheon.uf.common.dataplugin.warning.util.CountyUserData;
import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.MathTransform;
import com.raytheon.uf.common.dataplugin.warning.portions.GisUtil.Direction; import com.raytheon.uf.common.dataplugin.warning.portions.GisUtil.Direction;
@ -42,6 +43,7 @@ import com.vividsolutions.jts.geom.Geometry;
* Aug 5, 2013 2177 jsanchez Initial creation * Aug 5, 2013 2177 jsanchez Initial creation
* Sep 22, 2013 2177 jsanchez Updated logic. Used GisUtil for very small portions. * Sep 22, 2013 2177 jsanchez Updated logic. Used GisUtil for very small portions.
* Dec 4, 2013 2604 jsanchez Moved out of viz.warngen. * Dec 4, 2013 2604 jsanchez Moved out of viz.warngen.
* Jun 17, 2014 DR 17390 Qinglu Lin Update getPortions().
* </pre> * </pre>
* *
* @author jsanchez * @author jsanchez
@ -84,8 +86,15 @@ public class PortionsUtil {
// This takes into account the warned areas that are very small // This takes into account the warned areas that are very small
// the convex hull of the warned area is used for case the // the convex hull of the warned area is used for case the
// warnedArea is a geometry collection. // warnedArea is a geometry collection.
portions = GisUtil.calculateLocationPortion(countyOrZone, CountyUserData cud = (CountyUserData) countyOrZone.getUserData();
warnedArea.convexHull(), useExtreme); 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 { } else {
portions = getAreaDesc(entityData.getMeanMask(), portions = getAreaDesc(entityData.getMeanMask(),
entityData.getCoverageMask(), entityData.getOctants(), entityData.getCoverageMask(), entityData.getOctants(),

View file

@ -11,6 +11,7 @@
##### Evan Bookbinder 05-05-2013 handleClosesPoints and 3rd bullet changes (OVER & now) ##### 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 ##### 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 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 ##'.
#################################################################################################### ####################################################################################################
#* #*
Mile Marker Test Code Mile Marker Test Code

View file

@ -35,7 +35,9 @@ import com.raytheon.uf.common.localization.FileLocker.Type;
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Jun 23, 2011 mschenke Initial creation * Jun 23, 2011 mschenke Initial creation
* Jun 05, 2014 3248 njensen Fix constructors so lock is obtained
* before super constructor called
* *
* </pre> * </pre>
* *
@ -46,7 +48,9 @@ import com.raytheon.uf.common.localization.FileLocker.Type;
public class LockingFileOutputStream extends FileOutputStream { public class LockingFileOutputStream extends FileOutputStream {
private File file; private File file;
private final Object locker;
/** /**
* Create a new LockingFileOuputStream, creates an exclusive lock on the * Create a new LockingFileOuputStream, creates an exclusive lock on the
* file * file
@ -55,9 +59,7 @@ public class LockingFileOutputStream extends FileOutputStream {
* @throws FileNotFoundException * @throws FileNotFoundException
*/ */
public LockingFileOutputStream(File file) throws FileNotFoundException { public LockingFileOutputStream(File file) throws FileNotFoundException {
super(file); this(file, false);
this.file = file;
FileLocker.lock(this, file, Type.WRITE);
} }
/** /**
@ -70,9 +72,40 @@ public class LockingFileOutputStream extends FileOutputStream {
*/ */
public LockingFileOutputStream(File file, boolean isAppending) public LockingFileOutputStream(File file, boolean isAppending)
throws FileNotFoundException { throws FileNotFoundException {
this(file, isAppending, new Object());
}
/**
* Intentionally private constructor that takes a locker object to provide a
* unique lock tied to this stream instance. This constructor enforces that
* the FileLocker lock will be obtained before the super constructor is
* called. Otherwise, if isAppending is false, the super constructor will
* set the file length to zero, wiping out the contents, and we absolutely
* must have the write lock before that.
*
* @param file
* @param isAppending
* @param locker
* @throws FileNotFoundException
*/
private LockingFileOutputStream(File file, boolean isAppending, Object locker) throws FileNotFoundException {
this(file, isAppending, locker, FileLocker.lock(locker, file, Type.WRITE));
}
/**
* Intentionally private constructor that should be called after the file
* lock is obtained.
*
* @param file
* @param isAppending
* @param locker
* @param gotLock
* @throws FileNotFoundException
*/
private LockingFileOutputStream(File file, boolean isAppending, Object locker, boolean gotLock) throws FileNotFoundException {
super(file, isAppending); super(file, isAppending);
this.file = file; this.file = file;
FileLocker.lock(this, file, Type.WRITE); this.locker = locker;
} }
@Override @Override
@ -106,7 +139,10 @@ public class LockingFileOutputStream extends FileOutputStream {
} }
} }
/**
* Unlocks the file lock associated with the stream.
*/
public void unlock() { public void unlock() {
FileLocker.unlock(this, file); FileLocker.unlock(locker, file);
} }
} }

View file

@ -49,7 +49,7 @@ fi
if [ -d ${LOCALIZATION_PATH}/cave_static/site/${CAPS_FAILED_SITE}/gfe ]; then if [ -d ${LOCALIZATION_PATH}/cave_static/site/${CAPS_FAILED_SITE}/gfe ]; then
log_msg "Removing cave site configuration for site ${CAPS_FAILED_SITE}" log_msg "Removing cave site configuration for site ${CAPS_FAILED_SITE}"
rm -fr ${LOCALIZATION_PATH}/cave_static/site/${SITE}/gfe rm -fr ${LOCALIZATION_PATH}/cave_static/site/${CAPS_FAILED_SITE}/gfe
fi fi
if [ -d ${LOCALIZATION_PATH}/cave_static/site/${CAPS_FAILED_SITE}/bundles/maps ]; then if [ -d ${LOCALIZATION_PATH}/cave_static/site/${CAPS_FAILED_SITE}/bundles/maps ]; then

View file

@ -1,4 +1,34 @@
#!/bin/bash #!/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} import_file=${1}
log_msg Processing file: $import_file log_msg Processing file: $import_file
@ -98,7 +128,7 @@ log_msg "CDSPORT is $CDSPORT"
log_msg Beginning iscMosaic log_msg Beginning iscMosaic
log_msg 75 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 ] if [ $? -ne 0 ]
then then
log_msg "ERROR: iscMosaic failed to import grids from ${SITE}_GRID__Fcst_00000000_0000" log_msg "ERROR: iscMosaic failed to import grids from ${SITE}_GRID__Fcst_00000000_0000"

View file

@ -1,4 +1,35 @@
#!/bin/bash #!/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 ] if [ ${#AWIPS_HOME} = 0 ]
then then
path_to_script=`readlink -f $0` path_to_script=`readlink -f $0`
@ -94,7 +125,7 @@ if [ -a ${import_file} ]
then then
#use iscMosaic to load grids into databases #use iscMosaic to load grids into databases
log_msg "Running iscMosaic to unpack griddded data..." 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 ]; if [ $? -ne 0 ];
then then
log_msg "ERROR: iscMosaic failed to run correctly. Please re-run iscMosaic manually." 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 * See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information. * 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.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@ -29,6 +29,8 @@ import java.io.File;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -37,11 +39,12 @@ import java.util.TimeZone;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
// TODO fix? import com.raytheon.edex.plugin.gfe.watch.WCLWatchSrv;
@Ignore import com.raytheon.edex.plugin.gfe.watch.WatchProductUtil;
import com.raytheon.edex.plugin.gfe.watch.WclInfo;
public class TestWCLWatchSrv { public class TestWCLWatchSrv {
private WclInfo wclInfoA; private WclInfo wclInfoA;
@ -78,11 +81,11 @@ public class TestWCLWatchSrv {
wfosExpected.add("OAX"); wfosExpected.add("OAX");
wfosExpected.add("MFL"); wfosExpected.add("MFL");
wfosExpected.add("ICT"); wfosExpected.add("ICT");
Set<String> wfos = wclWatchSrv.attnWFOs(linesA); Collection<String> wfos = WatchProductUtil.findAttnWFOs(linesA);
assertEquals("LinesA", wfosExpected, wfos); assertEquals("LinesA", wfosExpected, wfos);
wfosExpected.clear(); wfosExpected.clear();
wfos = wclWatchSrv.attnWFOs(linesB); wfos = WatchProductUtil.findAttnWFOs(linesB);
assertEquals("LinesB", wfosExpected, wfos); assertEquals("LinesB", wfosExpected, wfos);
} }
@ -98,7 +101,7 @@ public class TestWCLWatchSrv {
} }
@Override @Override
protected File getWclDir() { protected File getWclDir(String siteID) {
String home = System.getenv("HOME"); String home = System.getenv("HOME");
File fakeDir = new File(home); File fakeDir = new File(home);
return fakeDir; return fakeDir;
@ -128,7 +131,7 @@ public class TestWCLWatchSrv {
// localization. // localization.
wclWatchSrv = new WCLWatchSrv() { wclWatchSrv = new WCLWatchSrv() {
@Override @Override
protected File getWclDir() { protected File getWclDir(String siteID) {
String home = System.getenv("HOME"); String home = System.getenv("HOME");
return new File(home); return new File(home);
} }
@ -138,7 +141,8 @@ public class TestWCLWatchSrv {
PrintWriter pw = new PrintWriter(temp); PrintWriter pw = new PrintWriter(temp);
pw.println("Testing"); pw.println("Testing");
pw.close(); pw.close();
wclWatchSrv.makePermanent(temp, completePIL); Collection<String> dummy = Collections.emptySet();
wclWatchSrv.makePermanent(temp, completePIL, dummy);
assertTrue("expetedFile exists", expectedFile.exists()); assertTrue("expetedFile exists", expectedFile.exists());
assertTrue("expectedFile isFile", expectedFile.isFile()); assertTrue("expectedFile isFile", expectedFile.isFile());
assertFalse("temp exists", temp.exists()); assertFalse("temp exists", temp.exists());