Merge branch 'master_14.2.2' into master_14.3.1 CM-MERGE:14.2.2-17,-18,-19,-20,-21,-22,-23,-24 into 14.3.1

Conflicts:
	cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/RadarBiasTableDialog.java
	cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenDialog.java
	cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java
	cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java
	edexOsgi/com.raytheon.edex.plugin.shef/src/com/raytheon/edex/plugin/shef/database/PostShef.java
	edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTable.java

Former-commit-id: b209604e1f0d6e790980d0bc8f1760e38f448076
This commit is contained in:
Brian.Dyke 2014-08-04 13:10:13 -04:00
commit 9abb02ea8a
82 changed files with 4145 additions and 3289 deletions

View file

@ -39,7 +39,10 @@ import com.raytheon.uf.viz.core.status.VizStatusInternal;
/**
* Implements status handling by converting status messages into StatusMessages
* and sending them to alertviz
* and sending them to alertviz.
*
* Also logs to a file so the error can be traced to the specific process id and
* as a safety net in case alertviz cannot be reached.
*
* <pre>
* SOFTWARE HISTORY
@ -47,6 +50,7 @@ import com.raytheon.uf.viz.core.status.VizStatusInternal;
* ------------ ---------- ----------- --------------------------
* Sep 09, 2008 1433 chammack Initial creation
* Aug 26, 2013 2142 njensen Changed to use SLF4J
* Jul 02, 2014 3337 njensen Disabled logback packaging data
* </pre>
*
* @author chammack
@ -62,6 +66,34 @@ public class SystemStatusHandler extends AbstractStatusHandler {
private static final Marker FATAL = MarkerFactory.getMarker("FATAL");
static {
/*
* Disables the packaging data feature of logback (ie how the
* stacktraces list the jar the class is in). Due to the viz dependency
* tree, in some scenarios the determination of the packaging data can
* spend an inordinate amount of time in the OSGi classloader trying to
* find classes. If the viz dependency tree is cleaned up (ie
* modularized, unnecessary imports removed, register buddies reduced)
* then this may be able to be re-enabled without a performance hit.
*
* Unfortunately there is no way to do this other than casting to a
* logback Logger, see http://jira.qos.ch/browse/LOGBACK-730 and
* http://jira.qos.ch/browse/LOGBACK-899
*/
try {
((ch.qos.logback.classic.Logger) logger).getLoggerContext()
.setPackagingDataEnabled(false);
} catch (Throwable t) {
/*
* given that this static block is for initializing the logger
* correctly, if that went wrong let's not even try to "log" it,
* just use stderr
*/
System.err.println("Error disabling logback packaging data");
t.printStackTrace();
}
}
/*
* (non-Javadoc)
*

View file

@ -26,7 +26,10 @@
<loadProperties>
<capabilities>
<capability xsi:type="colorableCapability" colorAsString="#9b9b9b" />
<capability xsi:type="outlineCapability" lineStyle="SOLID" outlineOn="true" />
<capability xsi:type="pointCapability" pointStyle="NONE" />
<capability xsi:type="labelableCapability" labelField="id" />
<capability xsi:type="magnificationCapability" magnification="1.0" />
<capability xsi:type="densityCapability" density="1.0" />
</capabilities>
<resourceType>PLAN_VIEW</resourceType>
</loadProperties>
@ -37,7 +40,23 @@
<capabilities>
<capability xsi:type="colorableCapability" colorAsString="#9b9b9b" />
<capability xsi:type="labelableCapability" labelField="name" />
<capability xsi:type="outlineCapability" lineStyle="SOLID" outlineOn="true"
</capabilities>
<resourceType>PLAN_VIEW</resourceType>
</loadProperties>
<properties isSystemResource="false" isBlinking="false" isMapLayer="true" isHoverOn="false" isVisible="true">
<pdProps maxDisplayWidth="100000000" minDisplayWidth="0" />
</properties>
<resourceData xsi:type="lpiResourceData">
<filename>cities.lpi</filename>
<mapName>Cities</mapName>
</resourceData>
</resource>
<mapName>Cities</mapName>
<resource>
<loadProperties>
<capabilities>
<capability xsi:type="colorableCapability" colorAsString="#9b9b9b" />
<capability xsi:type="labelableCapability" labelField="name" />
outlineWidth="1" />
</capabilities>
<resourceType>PLAN_VIEW</resourceType>
@ -51,27 +70,10 @@
<mapName>Cities</mapName>
</resourceData>
</resource>
<resource>
<loadProperties>
<capabilities>
<capability xsi:type="colorableCapability" colorAsString="#9b9b9b" />
<capability xsi:type="labelableCapability" labelField="name" />
<capability xsi:type="outlineCapability" lineStyle="SOLID" outlineOn="true" outlineWidth="1" />
</capabilities>
<resourceType>PLAN_VIEW</resourceType>
</loadProperties>
<properties isSystemResource="false" isBlinking="false" isMapLayer="true" isHoverOn="false" isVisible="true">
<pdProps maxDisplayWidth="100000000" minDisplayWidth="0" />
</properties>
<resourceData xsi:type="lpiResourceData">
<filename>cities.lpi</filename>
<mapName>Cities</mapName>
</resourceData>
</resource>
<mapName>Cities</mapName>
</resourceData>
</resource>
</descriptor>
</displays>
</displayList>
</bundle>

View file

@ -30,6 +30,9 @@ import org.eclipse.ui.IWorkbenchWindow;
import com.raytheon.uf.common.localization.AutoUpdatingLocalizationFile;
import com.raytheon.uf.common.localization.AutoUpdatingLocalizationFile.AutoUpdatingFileChangedListener;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException;
@ -41,6 +44,7 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.drawables.AbstractRenderableDisplay;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.maps.display.VizMapEditor;
import com.raytheon.uf.viz.core.maps.scales.MapScales.MapScale;
import com.raytheon.uf.viz.core.maps.scales.MapScales.PartId;
import com.raytheon.uf.viz.core.procedures.Bundle;
@ -61,7 +65,8 @@ import com.raytheon.viz.ui.actions.LoadSerializedXml;
* Oct 08, 2013 mschenke Initial creation
* Oct 22, 2013 2491 bsteffen Change from SerializationUtil to
* ProcedureXmlManager
* Mar 24, 2014 2954 mpduff Check for missing map scale files and handle the situation.
* Mar 24, 2014 2954 mpduff Log when missing map scale files
* Jul 15, 2014 2954 njensen Added fallbacks when missing map scale files
*
* </pre>
*
@ -79,6 +84,11 @@ public class MapScalesManager {
private static final String DEFAULT_SCALES_FILE = "scalesInfo.xml";
// TODO would be better to fall back to a worldwide display
private static final String LAST_RESORT_NAME = "Northern Hemisphere";
private static final String LAST_RESORT_FILENAME = "NHemisphere.xml";
/**
* Manager class for a single {@link MapScale}. Is able to create a Bundle
* for the scale. May provide functions for modifying/saving scales
@ -94,7 +104,7 @@ public class MapScalesManager {
private final String displayName;
private final PartId[] partIds;
private PartId[] partIds;
private final AutoUpdatingLocalizationFile scaleFile;
@ -103,13 +113,15 @@ public class MapScalesManager {
private final boolean isCustom;
private ManagedMapScale(String baseDir, MapScale scale)
throws SerializationException {
throws IllegalStateException, SerializationException {
this.isCustom = false;
this.partIds = scale.getPartIds();
this.displayName = scale.getDisplayName();
LocalizationFile file = PathManagerFactory.getPathManager()
.getStaticLocalizationFile(
baseDir + IPathManager.SEPARATOR
+ scale.getFileName());
if (file == null || !file.exists()) {
throw new IllegalStateException(
"scalesInfo.xml references missing file "
@ -117,9 +129,18 @@ public class MapScalesManager {
}
this.scaleFile = new AutoUpdatingLocalizationFile(file);
this.scaleFile.addListener(listener);
this.partIds = scale.getPartIds();
this.displayName = scale.getDisplayName();
loadBundleXml();
/*
* TODO this is inefficient to unmarshal it eagerly for no purpose
* other than to validate, but it ensures that if the files exist
* but have bad XML, then the thrown exception from getScaleBundle()
* will cause the fallback code to be triggered, leading to no blank
* panes
*/
// validate the XML is good
getScaleBundle();
}
private ManagedMapScale(String displayName, Bundle scaleBundle)
@ -190,7 +211,9 @@ public class MapScalesManager {
@Override
public void fileChanged(AutoUpdatingLocalizationFile file) {
try {
loadMapScales();
MapScales scales = file.loadObject(getJAXBManager(),
MapScales.class);
loadMapScales(scales);
} catch (SerializationException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e);
@ -198,7 +221,7 @@ public class MapScalesManager {
}
};
private final AutoUpdatingLocalizationFile scalesFile;
private AutoUpdatingLocalizationFile scalesFile;
private final String scaleBundleDir;
@ -223,36 +246,108 @@ public class MapScalesManager {
*/
public MapScalesManager(String scalesDir, String scalesFile)
throws SerializationException {
this(scalesDir, PathManagerFactory.getPathManager()
String filename = scalesDir + IPathManager.SEPARATOR + scalesFile;
LocalizationFile locFile = PathManagerFactory.getPathManager()
.getStaticLocalizationFile(
scalesDir + IPathManager.SEPARATOR + scalesFile));
filename);
MapScales scales = null;
try {
this.scalesFile = new AutoUpdatingLocalizationFile(locFile);
scales = this.scalesFile.loadObject(getJAXBManager(),
MapScales.class);
} catch (SerializationException e) {
/*
* failed to load scalesInfo file, try and fall back to BASE
*/
statusHandler.error("Error loading " + DEFAULT_SCALES_FILE
+ ". Attempting to revert to base version. ", e);
if (!locFile.getContext().getLocalizationLevel()
.equals(LocalizationLevel.BASE)) {
locFile = PathManagerFactory.getPathManager()
.getLocalizationFile(
new LocalizationContext(
LocalizationType.CAVE_STATIC,
LocalizationLevel.BASE), filename);
this.scalesFile = new AutoUpdatingLocalizationFile(locFile);
scales = this.scalesFile.loadObject(getJAXBManager(),
MapScales.class);
} else {
throw e;
}
}
this.scaleBundleDir = scalesDir;
this.scalesFile.addListener(listener);
loadMapScales(scales);
}
private synchronized void loadMapScales(MapScales scales)
{
List<ManagedMapScale> storedScales = new ArrayList<ManagedMapScale>();
List<PartId> failedParts = new ArrayList<PartId>();
for (MapScale scale : scales.getScales()) {
try {
storedScales.add(new ManagedMapScale(scaleBundleDir, scale));
} catch (Exception e) {
StringBuilder sb = new StringBuilder();
sb.append("Error loading " + scale.getDisplayName()
+ " scale. ");
if (scale.getPartIds() != null && scale.getPartIds().length > 0) {
sb.append(scale.getDisplayName()
+ " pane will attempt to revert to working scale. ");
}
sb.append(scale.getDisplayName()
+ " will not appear in the menu. ");
statusHandler.error(sb.toString(), e);
if (scale.getPartIds() != null) {
for (PartId p : scale.getPartIds()) {
failedParts.add(p);
}
}
}
}
this.storedScales = storedScales;
// storedScales must be set before handleMissingParts()
if (!failedParts.isEmpty()) {
handleMissingParts(failedParts);
}
}
/**
* Construct a MapScalesManager for the given scales file. File must be
* deserializable into a {@link MapScales} object
* Handles the parts that referenced scales files that couldn't be found.
*
* @param bundleDir
* directory bundle files are relative to
* @param scalesFile
* @throws SerializationException
* @param missingParts
* the parts that were missing
* @param goodScales
* the scales that successfully loaded
*/
public MapScalesManager(String bundleDir, LocalizationFile scalesFile)
throws SerializationException {
this.scaleBundleDir = bundleDir;
this.scalesFile = new AutoUpdatingLocalizationFile(scalesFile);
this.scalesFile.addListener(listener);
loadMapScales();
}
protected void handleMissingParts(List<PartId> missingParts) {
/*
* if the missing part was a side view, fall back to the main pane
*/
ManagedMapScale mainPane = findEditorScale();
private synchronized void loadMapScales() throws SerializationException {
List<ManagedMapScale> storedScales = new ArrayList<ManagedMapScale>();
MapScales scales = this.scalesFile.loadObject(getJAXBManager(),
MapScales.class);
for (MapScale scale : scales.getScales()) {
storedScales.add(new ManagedMapScale(scaleBundleDir, scale));
if (mainPane == null) {
/*
* main pane is missing too, so fall back to a base scale that is
* guaranteed to be there
*/
mainPane = getLastResortScale();
storedScales.add(mainPane);
}
this.storedScales = storedScales;
/*
* Set all the missing parts to the scale in the main pane
*/
List<PartId> combinedParts = new ArrayList<PartId>(
mainPane.partIds.length + missingParts.size());
for (PartId p : mainPane.getPartIds()) {
combinedParts.add(p);
}
for (PartId p : missingParts) {
combinedParts.add(p);
}
mainPane.partIds = combinedParts.toArray(new PartId[0]);
}
/**
@ -336,12 +431,12 @@ public class MapScalesManager {
}
/**
* Gets the {@link ManagedMapScale}s defined for the partId
* Gets the Bundle defined for the partId.
*
* @param partId
* @return
*/
public ManagedMapScale[] getScalesForPart(String partId) {
public Bundle getScaleBundleForPart(String partId) {
List<ManagedMapScale> scalesForPart = new ArrayList<ManagedMapScale>();
for (ManagedMapScale scale : storedScales) {
for (PartId part : scale.getPartIds()) {
@ -351,7 +446,26 @@ public class MapScalesManager {
}
}
}
return scalesForPart.toArray(new ManagedMapScale[0]);
Bundle b = null;
for (ManagedMapScale scale : scalesForPart) {
try {
b = scale.getScaleBundle();
} catch (SerializationException e) {
statusHandler.error("Error deserializing bundle for scale: "
+ scale, e);
}
if (b != null) {
break;
}
}
if (b != null) {
b.setView(partId);
}
return b;
}
/**
@ -408,4 +522,54 @@ public class MapScalesManager {
}
return jaxbManager;
}
/**
* Gets a base scale that should always be there and should always work.
* Used to prevent blank panes if scale overrides are misconfigured.
*
* @return
*/
protected ManagedMapScale getLastResortScale() {
ManagedMapScale scale = null;
PartId fallbackPartId = new PartId();
fallbackPartId.setId(VizMapEditor.EDITOR_ID);
fallbackPartId.setView(false);
MapScale fallback = new MapScale();
fallback.setPartIds(new PartId[] { fallbackPartId });
fallback.setDisplayName(LAST_RESORT_NAME);
fallback.setFileName(LAST_RESORT_FILENAME);
try {
scale = new ManagedMapScale(scaleBundleDir, fallback);
} catch (Exception e) {
statusHandler.fatal("Error loading the last resort scale "
+ LAST_RESORT_FILENAME, e);
// things will null pointer if this ever hits, but come on
}
return scale;
}
/**
* Finds the editor pane (ie VizMapEditor.EDITOR_ID) associated with a list
* of scales
*
* @return the first scale tied to a VizMapEditor, or null if none are found
*/
public ManagedMapScale findEditorScale() {
ManagedMapScale editorScale = null;
for (ManagedMapScale scale : storedScales) {
PartId[] parts = scale.partIds;
if (parts != null) {
for (PartId p : parts) {
if (VizMapEditor.EDITOR_ID.equals(p.getId())) {
editorScale = scale;
break;
}
}
}
if (editorScale != null) {
break;
}
}
return editorScale;
}
}

View file

@ -53,6 +53,7 @@ import com.raytheon.uf.common.time.DataTimeComparator;
* cease a null pointer exception.
* May 5, 2014 DR 17201 D. Friedman Make same-radar time matching work more like A1.
* Aug 08, 2013 2245 bsteffen Make all DataTime comparisons consistent.
* Jul 18, 2014 ASM #15049 D. Friedman Fix LAPS problem introduced by DR 17201
*
* </pre>
*
@ -657,7 +658,6 @@ public class TimeMatcher {
if (fspatial) {
frameFcsts = dataFcsts;
dtf = dt;
} else if (dtf > dt) {
dt = dtf;
}

View file

@ -35,7 +35,6 @@ import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
@ -52,7 +51,6 @@ import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.globals.VizGlobalsManager;
import com.raytheon.uf.viz.core.maps.scales.MapScalesManager;
import com.raytheon.uf.viz.core.maps.scales.MapScalesManager.ManagedMapScale;
import com.raytheon.uf.viz.core.procedures.Bundle;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IInputHandler;
@ -96,7 +94,8 @@ import com.vividsolutions.jts.geom.Coordinate;
* Mar 21, 2013 1638 mschenke Changed map scales not tied to d2d
* Aug 9, 2013 DR 16427 D. Friedman Swap additional input handlers.
* Oct 10, 2013 #2104 mschenke Switched to use MapScalesManager
*
* Jul 15, 2014 2954 njensen Updated init() for MapScalesManager change
*
* </pre>
*
* @author chammack
@ -141,18 +140,8 @@ public class SideView extends ViewPart implements IMultiPaneEditor,
String myId = site.getId() + UiUtil.SECONDARY_ID_SEPARATOR
+ site.getSecondaryId();
for (ManagedMapScale scale : MapScalesManager.getInstance()
.getScalesForPart(myId)) {
try {
Bundle b = scale.getScaleBundle();
b.setView(myId);
bundleToLoad = b;
} catch (SerializationException e) {
statusHandler.handle(Priority.PROBLEM,
"Error deserializing bundle for scale: " + scale, e);
}
break;
}
bundleToLoad = MapScalesManager.getInstance().getScaleBundleForPart(
myId);
}
@Override
@ -284,6 +273,7 @@ public class SideView extends ViewPart implements IMultiPaneEditor,
*
* @see com.raytheon.viz.core.IDisplayPaneContainer#getActiveDisplayPane()
*/
@Override
public IDisplayPane getActiveDisplayPane() {
return paneManager.getActiveDisplayPane();
}
@ -774,15 +764,18 @@ public class SideView extends ViewPart implements IMultiPaneEditor,
ISelectedPanesChangedListener listener) {
}
@Override
public void registerMouseHandler(IInputHandler handler,
InputPriority priority) {
paneManager.registerMouseHandler(handler, priority);
}
@Override
public void registerMouseHandler(IInputHandler handler) {
paneManager.registerMouseHandler(handler);
}
@Override
public void unregisterMouseHandler(IInputHandler handler) {
paneManager.unregisterMouseHandler(handler);
}

View file

@ -236,6 +236,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
* 21Mar2014 #2925 lvenable Fixed NPE error found during testing.
* 09Apr2014 #3005 lvenable Added calls to mark the tabs as not current when the tabs are changed.
* This will show the tab as updating in the header and data text controls.
* 07/23/2014 15645 zhao modified checkBasicSyntaxError()
*
* </pre>
*
@ -2110,19 +2111,29 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
return editorComp;
}
/**
/**
* Check if there is an extra '=' sign in a TAF
*
* @param doLogMessage
* @return true if error found, otherwise false
*/
private boolean checkBasicSyntaxError(boolean doLogMessage) {
boolean errorFound = false;
String in = editorTafTabComp.getTextEditorControl().getText();
clearSyntaxErrorLevel();
st = editorTafTabComp.getTextEditorControl();
in = in.toUpperCase().replaceAll("TAF", "\n\nTAF").trim();
while ( in.contains("\n\n\n") ) {
in = in.replace("\n\n\n", "\n\n");
}
st.setText(in);
final Map<StyleRange, String> syntaxMap = new HashMap<StyleRange, String>();
st.addMouseTrackListener(new MouseTrackAdapter() {
@ -2154,66 +2165,36 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
}
});
int tafIndex = in.indexOf("TAF");
int equalSignIndex = in.indexOf("=");
int lastEqualSignIndex = equalSignIndex;
if (tafIndex < 0 && equalSignIndex < 0) { // empty TAF
return false;
}
while (tafIndex > -1 || equalSignIndex > -1) {
if (tafIndex == -1 || tafIndex > equalSignIndex) {
int lineIndexOfFirstEqualSign = st
.getLineAtOffset(lastEqualSignIndex);
int lineIndexOfSecondEqualSign = st
.getLineAtOffset(equalSignIndex);
if (lineIndexOfFirstEqualSign == lineIndexOfSecondEqualSign) {
StyleRange sr = new StyleRange(lastEqualSignIndex, 1, null,
qcColors[3]);
String msg = "Syntax error: there is an extra '=' sign in this line";
syntaxMap.put(sr, msg);
st.setStyleRange(null);
st.setStyleRange(sr);
if (doLogMessage) {
msgStatComp.setMessageText(msg, qcColors[3].getRGB());
}
return true;
}
int startIndex = lastEqualSignIndex;
while (!in.substring(startIndex, startIndex + 1).matches(
"[A-Z]")
&& !in.substring(startIndex, startIndex + 1).matches(
"[0-9]")) {
startIndex++;
}
int length = 6;
if ((equalSignIndex - startIndex) < 6) {
length = equalSignIndex - startIndex;
}
StyleRange sr = new StyleRange(startIndex, length, null,
qcColors[3]);
String msg = "Syntax error: There is an extra '=' sign before this point, or 'TAF' is missing at beginning of TAF";
syntaxMap.put(sr, msg);
st.setStyleRange(null);
st.setStyleRange(sr);
if (doLogMessage) {
msgStatComp.setMessageText(msg, qcColors[3].getRGB());
}
return true;
String msg = "Syntax error: There is an extra '=' sign or 'TAF' is missing at beginning of TAF";
String[] tafs = in.split("\n\n");
int tafStartIndex = 0;
for ( String taf : tafs ) {
int firstEqualSignIndex = taf.indexOf('=');
if ( firstEqualSignIndex == -1 ) {
tafStartIndex += taf.length() + 2;
continue;
}
tafIndex = in.indexOf("TAF", tafIndex + 1);
lastEqualSignIndex = equalSignIndex;
equalSignIndex = in.indexOf("=", equalSignIndex + 1);
int secondEqualSignIndex = taf.indexOf('=', firstEqualSignIndex+1);
if ( secondEqualSignIndex == -1 ) {
tafStartIndex += taf.length() + 2;
continue;
}
while ( secondEqualSignIndex > -1 ) {
int secondEqualSignIndexInEditorText = tafStartIndex + secondEqualSignIndex;
StyleRange sr = new StyleRange(secondEqualSignIndexInEditorText, 1, null, qcColors[3]);
syntaxMap.put(sr, msg);
st.setStyleRange(sr);
secondEqualSignIndex = taf.indexOf('=', secondEqualSignIndex+1);
}
errorFound = true;
tafStartIndex += taf.length() + 2;
}
return false;
if ( doLogMessage ) {
msgStatComp.setMessageText(msg, qcColors[3].getRGB());
}
return errorFound;
}
private void syntaxCheck() {

View file

@ -54,6 +54,7 @@ import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DByte;
import com.raytheon.uf.common.dataplugin.gfe.grid.Grid2DFloat;
import com.raytheon.uf.common.dataplugin.gfe.grid.Op;
import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData;
import com.raytheon.uf.common.dataplugin.gfe.server.lock.Lock;
import com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable;
import com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable.LockMode;
import com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable.LockStatus;
@ -185,6 +186,8 @@ import com.vividsolutions.jts.geom.Coordinate;
* Apr 02, 2013 #1774 randerso Fixed a possible deadlock issue.
* Aug 27, 2013 #2302 randerso Fix simultaneous save issue
* Oct 31, 2013 #2508 randerso Change to use DiscreteGridSlice.getKeys()
* Jun 30, 2014 #3332 randerso Kept local reference to lock table to avoid
* race conditions with asynchronous updates
*
* </pre>
*
@ -619,21 +622,19 @@ public abstract class Parm implements Comparable<Parm> {
return new TimeRange();
}
if (!isMutable()) {
return getInventorySpan();
}
TimeRange tr = getInventorySpan();
TimeRange tr = new TimeRange();
if (lockTable != null) {
if (lockTable.getLocks().size() > 0) {
tr = lockTable.getLocks().get(0).getTimeRange();
}
for (int i = 1; i < lockTable.getLocks().size(); i++) {
tr = tr.combineWith(lockTable.getLocks().get(i).getTimeRange());
if (isMutable()) {
LockTable lt = this.lockTable;
if (lt != null) {
List<Lock> locks = lt.getLocks();
for (Lock lock : locks) {
tr = tr.combineWith(lock.getTimeRange());
}
}
}
return tr.combineWith(getInventorySpan());
return tr;
}
/**

View file

@ -28,6 +28,8 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.TimeRange;
/**
@ -40,6 +42,7 @@ import com.raytheon.uf.common.time.TimeRange;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 27, 2013 #2302 randerso Initial creation
* Jun 30, 2014 #3332 randerso Added exception handling
*
* </pre>
*
@ -48,6 +51,9 @@ import com.raytheon.uf.common.time.TimeRange;
*/
public class ParmSaveJob extends Job {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ParmSaveJob.class);
public static class ParmSaveStatus {
boolean successful = false;
@ -127,8 +133,13 @@ public class ParmSaveJob extends Job {
protected IStatus run(IProgressMonitor monitor) {
ParmSaveRequest req = null;
while ((req = this.saveQueue.poll()) != null) {
boolean successful = parm.saveParameterSubClass(req.times);
req.status.setSuccessful(successful);
try {
boolean successful = parm.saveParameterSubClass(req.times);
req.status.setSuccessful(successful);
} catch (Exception e) {
statusHandler.error("Error saving grids for " + this.parm, e);
req.status.setSuccessful(false);
}
}
return Status.OK_STATUS;
}

View file

@ -260,6 +260,7 @@ public class RadarBiasTableDialog extends Dialog {
applyBtn = new Button(applyBtnComp, SWT.PUSH);
applyBtn.setText("Apply");
applyBtn.setLayoutData(bd);
applyBtn.setEnabled(false);
applyBtn.addSelectionListener(new SelectionAdapter() {
/*
@ -274,7 +275,6 @@ public class RadarBiasTableDialog extends Dialog {
applyBiasUpdate(dt);
MPEDisplayManager mgr = MPEDisplayManager.getCurrent();
mgr.setSavedData(false);
shell.dispose();
}
});
@ -560,7 +560,6 @@ public class RadarBiasTableDialog extends Dialog {
editedSPBiasValue[ai] = oldSPBiasValue[ai];
spBiasValueTextArray[ai].setText(String.format("%-1.2f", editedSPBiasValue[ai]));
spBiasChangeMap.put(radIds[ai], ai);
applyBtn.setEnabled(false);
spManEditButtonArray[ai].setText("NO");
}
}

View file

@ -62,6 +62,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* Sep 6, 2012 13365 rferrel Accumulate and Display fix.
* Sep 25, 2012 1196 lvenable Dialog refactor for AlarmDisplayWindow.Added DO_NOT_BLOCK.
* Nov 20, 2013 2488 randerso Changed to use DejaVu font
* Jul 24, 2014 3423 randerso Added setLoading() to indicate waiting on product
* retrieval. Removed prods from constructor.
*
* </pre>
*
@ -100,19 +102,13 @@ public class AlarmDisplayWindow extends CaveSWTDialog {
/**
* @param parentShell
* @param prodList
* @param accum_state
*/
protected AlarmDisplayWindow(Shell parentShell,
java.util.List<StdTextProduct> prodList,
ACCUMULATE_STATE accum_state) {
protected AlarmDisplayWindow(Shell parentShell, ACCUMULATE_STATE accum_state) {
super(parentShell, SWT.RESIZE, CAVE.PERSPECTIVE_INDEPENDENT
| CAVE.INDEPENDENT_SHELL | CAVE.DO_NOT_BLOCK);
setText("Alarm Display Window");
prods = prodList;
if (prods == null) {
prods = new ArrayList<StdTextProduct>();
}
prods = new ArrayList<StdTextProduct>(0);
this.accum_state = accum_state;
}
@ -265,6 +261,11 @@ public class AlarmDisplayWindow extends CaveSWTDialog {
populateText();
}
public void setLoading() {
actualText = text.getText();
text.setText("Loading...");
}
public void addText(String msg) {
if (accumulate) {
if (text.getText().isEmpty()) {

View file

@ -24,7 +24,13 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
@ -52,7 +58,9 @@ import com.raytheon.uf.common.dataplugin.text.db.StdTextProduct;
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.util.Pair;
import com.raytheon.uf.edex.services.textdbsrv.IQueryTransport;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.viz.core.mode.CAVEMode;
import com.raytheon.viz.texteditor.alarmalert.dialogs.AlarmDisplayWindow.ACCUMULATE_STATE;
import com.raytheon.viz.texteditor.alarmalert.util.AlarmAlertFunctions;
@ -97,8 +105,10 @@ import com.raytheon.viz.ui.dialogs.ModeListener;
* Alarm Queue" GUI
* Sep 6, 2012 13365 rferrel Accumulate and Display fix.
* Sep 25, 2012 1196 lvenable Dialog refactor for AlarmDisplayWindow.
* Mar 05,2013 15173 mgamazaychikov The dimensions and location of closed window
* are saved and set on the next open.
* Mar 05, 2013 15173 mgamazaychikov The dimensions and location of closed window
* are saved and set on the next open.
* Jul 24, 2014 3423 randerso Created eclipse job to get afos command
* execution off the UI thread
*
* </pre>
*
@ -142,7 +152,7 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
* Location and dimensions of the dialog on the close.
*/
private static Point closeLocation = null;
private static Point closeDimensions = null;
/**
@ -151,14 +161,65 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
private boolean canRedraw = true;
/**
* Maximum width,initial height and offset of the window
* Maximum width,initial height and offset of the window
*/
private static final int SHELL_WIDTH = 350;
private static final int INIT_HEIGHT = 200;
private static final int INIT_OFFSET = 15;
/**
* Job to retrieve text products off the UI thread
*/
private class ProduceTextProductsJob extends Job {
private Queue<Pair<Long, String[]>> queue = new ConcurrentLinkedQueue<Pair<Long, String[]>>();
/**
* Constructor
*/
public ProduceTextProductsJob() {
super("ProduceTextProductsJob");
setSystem(true);
}
/**
* Queue a text product retrieval job
*
* @param refTime
* @param commands
*/
public void queue(Long refTime, String... commands) {
queue.add(new Pair<Long, String[]>(refTime, commands));
this.schedule();
}
@Override
protected IStatus run(IProgressMonitor monitor) {
while (queue.size() > 0) {
Pair<Long, String[]> pair = queue.poll();
if (pair != null) {
final java.util.List<StdTextProduct> prods = produceTextProducts(
pair.getFirst(), pair.getSecond());
VizApp.runSync(new Runnable() {
@Override
public void run() {
if (alarmDisplayDlg != null
&& !alarmDisplayDlg.isDisposed()) {
alarmDisplayDlg.setProds(prods);
}
}
});
}
}
return Status.OK_STATUS;
}
}
private ProduceTextProductsJob produceTextProductsJob = new ProduceTextProductsJob();
/**
* @param parentShell
* @param style
@ -261,12 +322,13 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
shellComp = new Composite(shell, SWT.NONE);
shellComp.setLayout(constructShellLayout());
shellComp.setLayoutData(gd);
/*
* DR15173 - Create a listener to save the location
* and dimensions of closed window.
* DR15173 - Create a listener to save the location and dimensions of
* closed window.
*/
shell.addShellListener(new ShellAdapter() {
@Override
public void shellClosed(ShellEvent event) {
closeLocation = getShell().getLocation();
closeDimensions = getShell().getSize();
@ -289,11 +351,13 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
/*
* DR15173 - Enforce that the window width does not exceed the SHELL_WIDTH.
*/
shell.setBounds(location.x, location.y, SHELL_WIDTH, point.y);
shell.setMinimumSize(SHELL_WIDTH, 0);
/*
* DR15173 - Enforce that the window width does not
* exceed the SHELL_WIDTH.
*/
shell.setBounds(location.x, location.y, SHELL_WIDTH,
point.y);
shell.setMinimumSize(SHELL_WIDTH, 0);
canRedraw = true;
}
});
@ -302,7 +366,7 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
// Initialize all of the controls and layouts
initializeComponents();
// Set the shell location and dimensions.
setShellGeometry();
}
@ -310,26 +374,25 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
/**
* Sets the geometry for the Current Alarm Queue shell
*/
private void setShellGeometry() {
Rectangle displayArea = shell.getDisplay().getClientArea();
int locationX = displayArea.x + INIT_OFFSET;
int locationY = displayArea.y + INIT_OFFSET;
int width = SHELL_WIDTH;
int height = INIT_HEIGHT;
if (CurrentAlarmQueue.closeLocation != null) {
locationX = CurrentAlarmQueue.closeLocation.x;
locationY = CurrentAlarmQueue.closeLocation.y;
}
if (CurrentAlarmQueue.closeDimensions != null) {
height = CurrentAlarmQueue.closeDimensions.y;
}
shell.setMinimumSize(width, height);
shell.setLocation(locationX, locationY);
return;
}
private void setShellGeometry() {
Rectangle displayArea = shell.getDisplay().getClientArea();
int locationX = displayArea.x + INIT_OFFSET;
int locationY = displayArea.y + INIT_OFFSET;
int width = SHELL_WIDTH;
int height = INIT_HEIGHT;
if (CurrentAlarmQueue.closeLocation != null) {
locationX = CurrentAlarmQueue.closeLocation.x;
locationY = CurrentAlarmQueue.closeLocation.y;
}
if (CurrentAlarmQueue.closeDimensions != null) {
height = CurrentAlarmQueue.closeDimensions.y;
}
shell.setMinimumSize(width, height);
shell.setLocation(locationX, locationY);
return;
}
/**
/**
* Initializes each component of the shell
*/
private void initializeComponents() {
@ -421,7 +484,7 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
* Display the selected product the current alarm queue list.
*/
private void displayList() {
String command = "";
String command = null;
Date refDate = null;
if (list != null && list.getItemCount() > 0
&& list.getSelectionCount() > 0 && list.getSelection() != null) {
@ -436,14 +499,9 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
}
}
java.util.List<StdTextProduct> prods = null;
if (command != "" && refDate != null) {
prods = produceTextProduct(command, refDate.getTime());
}
// Display the Alarm Display Window
if (alarmDisplayDlg == null || alarmDisplayDlg.getShell().isDisposed()) {
alarmDisplayDlg = new AlarmDisplayWindow(shell, prods,
alarmDisplayDlg = new AlarmDisplayWindow(shell,
ACCUMULATE_STATE.UNCHANGE);
alarmDisplayDlg.setCloseCallback(new ICloseCallback() {
@ -458,58 +516,52 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
alarmDisplayDlg.open();
} else {
alarmDisplayDlg.setProds(prods);
alarmDisplayDlg.setDialogFocus();
}
if (command != null && refDate != null) {
alarmDisplayDlg.setLoading();
produceTextProductsJob.queue(refDate.getTime(), command);
}
}
/**
* Display all the products in the alarm queue list and clear the list.
*/
private void displayAll() {
String[] command = null;
if (list != null) {
command = new String[list.getItemCount()];
for (int i = 0; i < list.getItemCount(); i++) {
command[i] = list.getItems()[i].split(" ")[0];
}
// Do a count of how many instances of each command are in
// the queue.
Map<String, Integer> counter = new HashMap<String, Integer>();
for (int i = 0; i < command.length; ++i) {
if (counter.get(command[i]) == null) {
counter.put(command[i], 0);
} else {
counter.put(command[i], (counter.get(command[i]) + 1));
}
}
// For each command, see how far back it needs to go to
// account for multiple instances, and construct the
// appropriate AFOS command.
for (int j = 0; j < command.length; ++j) {
Integer count = counter.get(command[j]);
if (count > 0) {
String newCom = "-" + count.toString() + ":" + command[j];
counter.put(command[j], (count - 1));
command[j] = newCom;
}
}
AlarmAlertLists.getInstance().getCurrentAlarms().clear();
listDates.clear();
list.removeAll();
AlarmAlertFunctions.getAlarmalertbell().close();
String[] command = new String[list.getItemCount()];
for (int i = 0; i < list.getItemCount(); i++) {
command[i] = list.getItems()[i].split(" ")[0];
}
java.util.List<StdTextProduct> prods = new ArrayList<StdTextProduct>();
if (command.length > 0) {
for (int i = 0; i < command.length; i++) {
prods.addAll(produceTextProduct(command[i]));
// Do a count of how many instances of each command are in
// the queue.
Map<String, Integer> counter = new HashMap<String, Integer>();
for (int i = 0; i < command.length; ++i) {
if (counter.get(command[i]) == null) {
counter.put(command[i], 0);
} else {
counter.put(command[i], (counter.get(command[i]) + 1));
}
}
// For each command, see how far back it needs to go to
// account for multiple instances, and construct the
// appropriate AFOS command.
for (int j = 0; j < command.length; ++j) {
Integer count = counter.get(command[j]);
if (count > 0) {
String newCom = "-" + count.toString() + ":" + command[j];
counter.put(command[j], (count - 1));
command[j] = newCom;
}
}
AlarmAlertLists.getInstance().getCurrentAlarms().clear();
listDates.clear();
list.removeAll();
AlarmAlertFunctions.getAlarmalertbell().close();
// Display the Alarm Display Window
if (alarmDisplayDlg == null || alarmDisplayDlg.getShell().isDisposed()) {
alarmDisplayDlg = new AlarmDisplayWindow(shell, prods,
alarmDisplayDlg = new AlarmDisplayWindow(shell,
ACCUMULATE_STATE.TRUE);
alarmDisplayDlg.setCloseCallback(new ICloseCallback() {
@Override
@ -523,10 +575,12 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
});
alarmDisplayDlg.open();
} else {
alarmDisplayDlg.setProds(prods);
alarmDisplayDlg.setAccumulate(true);
alarmDisplayDlg.setDialogFocus();
}
alarmDisplayDlg.setLoading();
produceTextProductsJob.queue(null, command);
}
/**
@ -578,12 +632,6 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
}
}
public java.util.List<StdTextProduct> produceTextProduct(String command) {
ICommand cmd = CommandFactory.getAfosCommand(command);
executeCommand(cmd);
return prodList;
}
/**
* Get the product for the given AFOS command and reference time.
*
@ -591,11 +639,16 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
* @param refTime
* @return prodList
*/
private java.util.List<StdTextProduct> produceTextProduct(String command,
Long refTime) {
ICommand cmd = CommandFactory.getAfosCommand(command, refTime);
executeCommand(cmd);
return prodList;
private java.util.List<StdTextProduct> produceTextProducts(Long refTime,
String... commands) {
java.util.List<StdTextProduct> prods = new ArrayList<StdTextProduct>();
for (String command : commands) {
ICommand cmd = CommandFactory.getAfosCommand(command, refTime);
executeCommand(cmd);
prods.addAll(prodList);
}
return prods;
}
/*
@ -652,12 +705,19 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
*/
@Override
public void currentAlarmChanged(CurrentAlarmEvent event) {
AlarmAlertProduct aap = (AlarmAlertProduct) event.getSource();
final AlarmAlertProduct aap = (AlarmAlertProduct) event.getSource();
if (!shell.isDisposed() && shell != null) {
CAVEMode mode = CAVEMode.getMode();
if ((CAVEMode.OPERATIONAL.equals(mode) || CAVEMode.TEST
.equals(mode)) && aap.getOperationalMode()) {
addToQueue(aap.getProductId(), aap.getDateReceived());
VizApp.runAsync(new Runnable() {
@Override
public void run() {
addToQueue(aap.getProductId(), aap.getDateReceived());
}
});
}
}
}

View file

@ -56,6 +56,7 @@ import com.raytheon.uf.common.localization.exception.LocalizationOpFailedExcepti
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.viz.texteditor.alarmalert.dialogs.AlarmAlertBell;
import com.raytheon.viz.texteditor.command.CommandFactory;
@ -79,6 +80,7 @@ import com.vividsolutions.jts.geom.GeometryFactory;
* 03/19/2012 D. Friedman Fix determination of "Alarm" entries.
* 12/07/2012 15555 m.gamazaychikov Added methods and constants for
* the implementation of proximity alarm
* 07/24/2014 3423 randerso Ensure ringBell is called on UI thread
*
* </pre>
*
@ -211,14 +213,16 @@ public class AlarmAlertFunctions {
match = true;
}
if (match) {
if (productFound == null)
if (productFound == null) {
productFound = p;
}
if ("Alarm".equals(p.getAlarmType()) && p.isAlarm()) {
alarm = true;
productFound = p;
}
if (alarm)
if (alarm) {
break;
}
}
}
}
@ -229,7 +233,14 @@ public class AlarmAlertFunctions {
instance.getCurrentAlarms().add(prod);
instance.fireNewCurrentAlarmEvent(prod);
ringBell(alarm);
final boolean sound = alarm;
VizApp.runAsync(new Runnable() {
@Override
public void run() {
ringBell(sound);
}
});
}
}
}

View file

@ -23,22 +23,22 @@ import com.raytheon.uf.common.dataplugin.text.alarms.AlarmAlertProduct;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.notification.INotificationObserver;
import com.raytheon.uf.viz.core.notification.NotificationMessage;
import com.raytheon.uf.viz.core.notification.jobs.NotificationManagerJob;
import com.raytheon.viz.core.mode.CAVEMode;
/**
* TODO Add Description
* Alarm Alert Notification Observer
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 13, 2009 mnash Initial creation
* Oct 13, 2009 mnash Initial creation
* Jun 07, 2010 5851 cjeanbap Properly stop alarm/alert observer listener.
* Jul 24, 2014 3423 randerso Get afos command execution off the UI thread
*
* </pre>
*
@ -108,7 +108,8 @@ public class AlarmAlertNotificationObserver implements INotificationObserver {
}
if (run != null) {
VizApp.runAsync(run);
Thread thread = new Thread(run);
thread.start();
}
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,

View file

@ -21,6 +21,7 @@ package com.raytheon.viz.warngen.gis;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -47,6 +48,8 @@ import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.exception.VizException;
//import com.raytheon.viz.warngen.gis.GisUtil.Direction;
import com.raytheon.uf.common.dataplugin.warning.portions.GisUtil.Direction;
import com.raytheon.viz.warngen.gui.WarngenLayer;
import com.raytheon.viz.warngen.util.Abbreviation;
import com.vividsolutions.jts.geom.Geometry;
@ -79,6 +82,8 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometry;
* Dec 4, 2013 2604 jsanchez Refactored GisUtil and PortionsUtil.
* Apr 29, 2014 3033 jsanchez Updated method to retrieve files in localization.
* May 16, 2014 DR 17365 D. Friedman Reduce precision of warning area to avoid topology errors.
* Jun 30, 2014 DR 17447 Qinglu lin Updated findAffectedAreas().
* Jul 22, 23014 3419 jsanchez Cleaned up converFeAreaToPartList.
* </pre>
*
* @author chammack
@ -94,6 +99,10 @@ public class Area {
*/
public static final double DEFAULT_PORTION_TOLERANCE = 0.60;
private static final List<String> SPECIAL_CASE_FE_AREAS = Arrays
.asList(new String[] { "PA", "MI", "PD", "UP", "BB", "ER", "EU",
"SR", "NR", "WU", "DS" });
private PortionsUtil portionsUtil;
public Area(PortionsUtil portionsUtil) {
@ -181,6 +190,7 @@ public class Area {
}
List<String> uniqueFips = new ArrayList<String>();
List<String> uniqueCountyname = new ArrayList<String>();
List<AffectedAreas> areas = new ArrayList<AffectedAreas>();
for (GeospatialData regionFeature : countyMap.values()) {
Geometry regionGeom = regionFeature.geometry;
@ -260,8 +270,14 @@ public class Area {
area.points = pointList.toArray(new String[pointList.size()]);
}
if (uniqueFips.contains(area.fips) == false) {
String countyName = (String) regionFeature.attributes
.get("COUNTYNAME");
if (uniqueFips.contains(area.fips) == false
|| !uniqueCountyname.contains(countyName)) {
uniqueFips.add(area.fips);
if (countyName != null) {
uniqueCountyname.add(countyName);
}
areas.add(area);
}
}
@ -297,7 +313,8 @@ public class Area {
Map<String, Object> areasMap = new HashMap<String, Object>();
try {
Geometry precisionReducedArea = PolygonUtil.reducePrecision(warnArea);
Geometry precisionReducedArea = PolygonUtil
.reducePrecision(warnArea);
if (precisionReducedArea.isValid()) {
warnArea = precisionReducedArea;
}
@ -335,66 +352,41 @@ public class Area {
public static List<String> converFeAreaToPartList(String feArea) {
final List<String> partList = new ArrayList<String>();
if (feArea == null) {
// Marine warnings
partList.add("");
} else {
if (feArea.equals("pa"))
partList.add("PA");
else if (feArea.equals("mi"))
partList.add("MI");
else if (feArea.equals("pd"))
partList.add("PD");
else if (feArea.equals("up"))
partList.add("UP");
else if (feArea.equals("bb"))
partList.add("BB");
else if (feArea.equals("er"))
partList.add("ER");
else if (feArea.equals("eu"))
partList.add("EU");
else if (feArea.equals("sr"))
partList.add("SR");
else if (feArea.equals("nr"))
partList.add("NR");
else if (feArea.equals("wu"))
partList.add("WU");
else if (feArea.equals("ds"))
partList.add("DS");
else if (feArea.equals("ne"))
partList.add("NE");
else if (feArea.equals("nw"))
partList.add("NW");
else if (feArea.equals("se"))
partList.add("SE");
else if (feArea.equals("sw"))
partList.add("SW");
else {
if (feArea != null) {
feArea = feArea.toUpperCase();
if (SPECIAL_CASE_FE_AREAS.contains(feArea)) {
partList.add(feArea);
} else {
for (int i = 0; i < feArea.length(); i++) {
char c = feArea.charAt(i);
Direction direction = null;
switch (c) {
case 'c':
partList.add("CENTRAL");
case 'C':
direction = Direction.CENTRAL;
break;
case 'w':
partList.add("WEST");
case 'W':
direction = Direction.WEST;
break;
case 'n':
partList.add("NORTH");
case 'N':
direction = Direction.NORTH;
break;
case 'e':
partList.add("EAST");
case 'E':
direction = Direction.EAST;
break;
case 's':
partList.add("SOUTH");
case 'S':
direction = Direction.SOUTH;
break;
default:
break;
}
if (direction != null) {
partList.add(direction.toString());
}
}
}
}
return partList;
}
}

View file

@ -86,6 +86,9 @@ import com.vividsolutions.jts.precision.SimpleGeometryPrecisionReducer;
* 01/09/2014 DR 16974 D. Friedman Improve followup redraw-from-hatched-area polygons.
* 04/15/2014 DR 17247 D. Friedman Prevent some invalid coordinates in adjustVertex.
* 05/16/2014 DR 17365 D. Friedman Prevent some Coordinate reuse. Add reducePrecision.
* 06/27/2014 DR 17443 D. Friedman Fix some odd cases in which parts of a polygon not covering a
* hatched area would be retained after redrawing.
* 07/22/2014 DR 17475 Qinglu Lin Updated createPolygonByPoints() and created second createPolygonByPoints().
* </pre>
*
* @author mschenke
@ -417,12 +420,15 @@ public class PolygonUtil {
p1--;
if (p1 >= 0) {
Coordinate last = new Coordinate();
int n, best1, best2;
for (n = k = 0; k < npoints; k++) {
if (match[k] == nv)
continue;
best1 = match[p1];
best2 = match[k];
last.x = longest[p1].x;
last.y = longest[p1].y;
p1 = k;
if (best1 < 0 && best2 < 0) {
if (k == n)
@ -460,16 +466,59 @@ public class PolygonUtil {
best1 += nv;
else if (dn - da < -len2)
best2 += nv;
if (best1 < best2)
/*
* We have apparently jumped from side best1 to side
* best2. Should we add all of the original
* vert[best1] -> vert[best2] vertices? If this is
* significantly longer then the distance from the
* last contour point to this one, it is probably
* the wrong thing to do.
*
* The factor of 3 assumes that all points along the
* contour we ware redrawing are fairly close so
* that three times the length from any one point to
* another is not very long.
*/
double maxPatchLen = last.distance(longest[k]) * 3;
double patchLen = 0;
int va = Math.min(best1, best2);
int vb = Math.max(best1, best2);
if (va < nv) {
patchLen = totlen[Math.min(nv, vb)] - totlen[va];
if (vb >= nv)
patchLen += totlen[vb % nv];
} else {
patchLen = totlen[vb % nv] - totlen[va % nv];
}
if (patchLen >= maxPatchLen) {
/*
* Adding all of the other vertices would be
* going of the rails, so just add a vertex for
* the last point (since it may be far from
* vert[best1] and the current point. Only add
* one point if adding two would cause the
* output in longest to overtake the input.
*/
if (n + 1 < k) {
fixed[n] = 1;
longest[n++] = new Coordinate(last);
}
fixed[n] = 1;
longest[n++] = longest[k];
} else if (best1 < best2) {
for (best1++; best1 <= best2; best1++) {
fixed[n] = 1;
longest[n++] = new Coordinate(vert[best1]);
}
else
} else {
for (; best1 > best2; best1--) {
fixed[n] = 1;
longest[n++] = new Coordinate(vert[best1]);
}
}
continue;
}
fixed[n] = 1;
@ -1670,11 +1719,11 @@ public class PolygonUtil {
}
return slope;
}
/**
* Create a polygon whose two diagonal coordinates are a and b.
**/
static public Geometry createPolygonByPoints(Coordinate a, Coordinate b) {
static public Geometry createPolygonByPoints(GeometryFactory gf, Coordinate a, Coordinate b) {
double maxX, minX, maxY, minY;
maxX = Math.max(a.x, b.x);
minX = Math.min(a.x, b.x);
@ -1686,10 +1735,14 @@ public class PolygonUtil {
coord[2] = new Coordinate(maxX, maxY);
coord[3] = new Coordinate(minX, maxY);
coord[4] = new Coordinate(coord[0]);
GeometryFactory gf = new GeometryFactory();
LinearRing lr = gf.createLinearRing(coord);
return gf.createPolygon(lr, null);
}
}
static public Geometry createPolygonByPoints(GeometryFactory gf, Coordinate a, double shift) {
Coordinate b = new Coordinate(a.x + shift, a.y + shift);
return createPolygonByPoints(gf, a, b);
}
/** Creates a copy of a Geometry with reduced precision to reduce the chance of topology errors when used
* in intersection operations.

View file

@ -0,0 +1,191 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.gis;
import java.util.Date;
import java.util.List;
/**
* Simple POJO for a watch. The phenSig, action, etn, start time, and end time
* make each watch unique similar to the VTEC.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 16, 2014 3419 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class Watch {
private String phenSig;
private String action;
private String etn;
private Date startTime;
private Date endTime;
private List<String> areas;
private String state;
private List<String> partOfState;
public Watch(String state, String action, String phenSig, String etn,
Date startTime, Date endTime) {
this.state = state;
this.action = action;
this.phenSig = phenSig;
this.etn = etn;
this.startTime = startTime;
this.endTime = endTime;
}
public String getPhenSig() {
return phenSig;
}
public void setPhenSig(String phenSig) {
this.phenSig = phenSig;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public List<String> getAreas() {
return areas;
}
public void setAreas(List<String> areas) {
this.areas = areas;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public List<String> getPartOfState() {
return partOfState;
}
public void setPartOfState(List<String> partOfState) {
this.partOfState = partOfState;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public String getEtn() {
return etn;
}
public void setEtn(String etn) {
this.etn = etn;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((action == null) ? 0 : action.hashCode());
result = prime * result + ((endTime == null) ? 0 : endTime.hashCode());
result = prime * result + ((etn == null) ? 0 : etn.hashCode());
result = prime * result + ((phenSig == null) ? 0 : phenSig.hashCode());
result = prime * result
+ ((startTime == null) ? 0 : startTime.hashCode());
result = prime * result + ((state == null) ? 0 : state.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Watch other = (Watch) obj;
if (action == null) {
if (other.action != null)
return false;
} else if (!action.equals(other.action))
return false;
if (endTime == null) {
if (other.endTime != null)
return false;
} else if (!endTime.equals(other.endTime))
return false;
if (etn == null) {
if (other.etn != null)
return false;
} else if (!etn.equals(other.etn))
return false;
if (phenSig == null) {
if (other.phenSig != null)
return false;
} else if (!phenSig.equals(other.phenSig))
return false;
if (startTime == null) {
if (other.startTime != null)
return false;
} else if (!startTime.equals(other.startTime))
return false;
if (state == null) {
if (other.state != null)
return false;
} else if (!state.equals(other.state))
return false;
return true;
}
}

View file

@ -0,0 +1,536 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.gis;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import org.apache.commons.lang.Validate;
import com.raytheon.uf.common.activetable.ActiveTableRecord;
import com.raytheon.uf.common.activetable.OperationalActiveTableRecord;
import com.raytheon.uf.common.activetable.PracticeActiveTableRecord;
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialData;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.viz.core.mode.CAVEMode;
import com.raytheon.viz.warngen.gui.WarngenLayer;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Polygon;
/**
* Determines the valid watches related to the warning.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 17, 2014 3419 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class WatchUtil {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(WatchUtil.class);
private static final UnitConverter milesToKilometer = NonSI.MILE
.getConverterTo(SI.KILOMETER);
private static final double KmToDegrees = 111.12;
private static final String ISSUE_TIME_FIELD = "issueTime";
private static final String START_TIME_FIELD = "startTime";
private static final String END_TIME_FIELD = "endTime";
private static final String UGC_ZONE_FIELD = "ugcZone";
private static final String PHEN_SIG_FIELD = "phensig";
private static final String ETN = "etn";
private static final String ACTION = "act";
private static final String COUNTY_FIPS_FIELD = "FIPS";
private static final String COUNTY_FE_AREA_FIELD = "FE_AREA";
private static final String STATE_FIELD = "STATE";
private static final String COUNTY_TABLE = "County";
private static final String PARENT_NAME_FIELD = "NAME";
private static final String[] REQUEST_FIELDS = new String[] {
ISSUE_TIME_FIELD, START_TIME_FIELD, END_TIME_FIELD, UGC_ZONE_FIELD,
PHEN_SIG_FIELD, END_TIME_FIELD, ACTION, ETN };
private GeospatialData[] countyGeoData;
private WarngenLayer warngenLayer;
public WatchUtil(WarngenLayer warngenLayer) throws InstantiationException {
countyGeoData = warngenLayer.getGeodataFeatures(COUNTY_TABLE,
warngenLayer.getLocalizedSite());
if ((countyGeoData == null) || (countyGeoData.length == 0)) {
throw new InstantiationException("Cannot get geospatial data for "
+ COUNTY_TABLE + "-based watches");
}
this.warngenLayer = warngenLayer;
}
/**
* Retrieves valid watches based on the constraints in the config, the
* warning polygon, and the current simulated time.
*
* @param config
* @param warningPolygon
* @param simulatedTime
* @return
* @throws Exception
*/
public List<Watch> getWatches(WarngenConfiguration config,
Geometry warningPolygon, Date simulatedTime) throws Exception {
List<Watch> watches = null;
AreaSourceConfiguration hatchedAreaSourceConfig = config
.getHatchedAreaSource();
// Validation check
Validate.notNull(hatchedAreaSourceConfig,
"Cannot process watches: missing HATCHING area source configuration");
double watchAreaBuffer = hatchedAreaSourceConfig
.getIncludedWatchAreaBuffer();
// Validation check
Validate.isTrue(watchAreaBuffer >= 0,
"'includedWatchAreaBuffer' can not be negative in .xml file");
String[] includedWatches = config.getIncludedWatches();
if ((includedWatches != null) && (includedWatches.length > 0)) {
StringBuilder phenSigConstraint = new StringBuilder();
Iterator<String> iterator = Arrays.asList(includedWatches)
.iterator();
while (iterator.hasNext()) {
phenSigConstraint.append(iterator.next());
if (iterator.hasNext()) {
phenSigConstraint.append(",");
}
}
// Determine entity class
Class<? extends ActiveTableRecord> entityClass = OperationalActiveTableRecord.class;
if (CAVEMode.getMode() != CAVEMode.OPERATIONAL) {
entityClass = PracticeActiveTableRecord.class;
}
DbQueryRequest request = buildRequest(simulatedTime,
phenSigConstraint.toString(), warngenLayer.getAllUgcs(),
entityClass);
DbQueryResponse response = (DbQueryResponse) ThriftClient
.sendRequest(request);
List<ActiveTableRecord> records = convertReponse(entityClass,
response);
if (records.isEmpty() == false) {
try {
long t0 = System.currentTimeMillis();
Polygon watchArea = (Polygon) warningPolygon
.buffer(milesToKilometer.convert(watchAreaBuffer)
/ KmToDegrees);
System.out.println("create watch area buffer time: "
+ (System.currentTimeMillis() - t0));
Set<String> validUgcZones = warngenLayer
.getUgcsForWatches(watchArea);
watches = processRecords(records, validUgcZones);
} catch (RuntimeException e) {
statusHandler
.handle(Priority.ERROR,
"Error determining areas to search for watches.",
e);
}
}
}
return watches;
}
/**
* Builds a DBQueryRequest object.
*
* @param simulatedTime
* @param phenSig
* @param ugcs
* @param entityClass
* @return
*/
private static DbQueryRequest buildRequest(Date simulatedTime,
String phenSig, Set<String> ugcs,
Class<? extends ActiveTableRecord> entityClass) {
// Create start constraint
Calendar cal = Calendar.getInstance();
cal.setTime(simulatedTime);
cal.add(Calendar.MINUTE, 3);
Date startConstraintTime = cal.getTime();
DbQueryRequest request = new DbQueryRequest();
request.setEntityClass(entityClass);
request.addConstraint(START_TIME_FIELD,
new RequestConstraint(TimeUtil.formatDate(startConstraintTime),
ConstraintType.LESS_THAN_EQUALS));
request.addConstraint(END_TIME_FIELD,
new RequestConstraint(TimeUtil.formatDate(simulatedTime),
ConstraintType.GREATER_THAN_EQUALS));
request.addConstraint("phensig",
new RequestConstraint(phenSig.toString(), ConstraintType.IN));
/*
* Get all UGCs in the CWA now so that the watches will be formatted
* with all portions of the affected state(s).
*
* Filtering for valid UGCs is performed in processATEntries
*/
RequestConstraint ugcConstraint = new RequestConstraint("",
ConstraintType.IN);
ugcConstraint.setConstraintValueList(ugcs);
request.addConstraint("ugcZone", ugcConstraint);
// These are the only fields we need for processing watches
request.addFields(REQUEST_FIELDS);
return request;
}
/**
* Converts the results of DbQueryResponse into a list of
* ActiveTableRecords.
*
* @param entityClass
* @param response
* @return
* @throws IllegalAccessException
* @throws InstantiationException
*/
private static final List<ActiveTableRecord> convertReponse(
Class<? extends ActiveTableRecord> entityClass,
DbQueryResponse response) throws IllegalAccessException,
InstantiationException {
List<ActiveTableRecord> records = new ArrayList<ActiveTableRecord>(
response.getNumResults());
for (Map<String, Object> result : response.getResults()) {
WarningAction action = WarningAction.valueOf(String.valueOf(result
.get(ACTION)));
/*
* TODO: Currently limited to filtering out one of ("CAN","EXP").
* Could use "Act" in addition to "act", but this should really be
* fixed the underlying system. request.addConstraint("act", new
* RequestConstraint("CAN", ConstraintType.NOT_EQUALS));
*/
if (action != WarningAction.CAN || action != WarningAction.EXP) {
ActiveTableRecord record = entityClass.newInstance();
record.setIssueTime((Calendar) result.get(ISSUE_TIME_FIELD));
record.setStartTime((Calendar) result.get(START_TIME_FIELD));
record.setEndTime((Calendar) result.get(END_TIME_FIELD));
record.setEndTime((Calendar) result.get(END_TIME_FIELD));
record.setUgcZone(String.valueOf(result.get(UGC_ZONE_FIELD)));
record.setPhensig(String.valueOf(result.get(PHEN_SIG_FIELD)));
record.setEtn(String.valueOf(result.get(ETN)));
record.setAct(String.valueOf(result.get(ACTION)));
records.add(record);
}
}
return records;
}
/**
* Groups the activeTableRecords into Watch objects that share phenSig,
* action, ETN, start time, and end time. It also determines the part of
* state the watch covers.
*
* @param activeTableRecords
* @param validUgcZones
*
* @return
*/
private List<Watch> processRecords(
List<ActiveTableRecord> activeTableRecords,
Set<String> validUgcZones) {
List<Watch> watches = new ArrayList<Watch>();
/*
* Assumption 1: TO.A and SV.A UGC line will always be in county format
* from WOU.
*/
/*
* Assumption 2: At least 1 warning for the issuing site supports county
* based warnings. This will allow the county geo features to be cached.
*/
Map<Watch, List<String>> map = new HashMap<Watch, List<String>>();
// For each watch event, get the end time and list of active zones
for (ActiveTableRecord ar : activeTableRecords) {
/*
* Currently reports all zones in the watch even if a given zone is
* not in the warning polygon. If the logic is changed to only show
* the portions of the watch near our warning polygon, filter on
* validUgcZones here.
*/
String ugcZone = ar.getUgcZone();
String state = getStateName(ugcZone.substring(0, 2));
String action = ar.getAct();
String phenSig = ar.getPhensig();
String etn = ar.getEtn();
Date startTime = ar.getStartTime().getTime();
Date endTime = ar.getEndTime().getTime();
if (validUgcZones.contains(ugcZone)) {
Watch watch = new Watch(state, action, phenSig, etn, startTime,
endTime);
List<String> areas = map.get(watch);
if (areas == null) {
areas = new ArrayList<String>();
}
areas.add(ugcZone);
map.put(watch, areas);
}
}
// Sets the areas for the watch
for (Entry<Watch, List<String>> entry : map.entrySet()) {
Watch watch = entry.getKey();
watch.setAreas(entry.getValue());
List<String> partOfState = new ArrayList<String>(
determineAffectedPortions(watch.getAreas()));
watch.setPartOfState(partOfState);
watches.add(watch);
}
// Sorts the watches based on state name.
Collections.sort(watches, new Comparator<Watch>() {
@Override
public int compare(Watch watch1, Watch watch2) {
return watch1.getState().compareTo(watch2.getState());
}
});
return watches;
}
/**
* Determines the directional set of a state.
*
* @param ugcs
* @return
*/
private Set<String> determineAffectedPortions(List<String> ugcs) {
Set<String> feAreas = new HashSet<String>();
for (String ugc : ugcs) {
// Want the first 2 letters
String stateAbbrev = ugc.substring(0, 2);
// Want the last 3 digits
String fips = ugc.substring(ugc.length() - 3);
String feArea = getFeArea(stateAbbrev, fips);
// Checks to see if feArea in CWA
if (feArea != null) {
feAreas.add(feArea);
}
}
Set<String> affectedPortions = new HashSet(
Area.converFeAreaToPartList(mungeFeAreas(feAreas)));
return affectedPortions;
}
/**
* Returns the full state name from the state abbreviation.
*
* @param stateAbrev
* @return
*/
private String getStateName(String stateAbrev) {
for (GeospatialData g : countyGeoData) {
if (stateAbrev.equals(g.attributes.get(STATE_FIELD))) {
return (String) g.parent.attributes.get(PARENT_NAME_FIELD);
}
}
return null;
}
/**
* Returns the feArea field in the county table (i.e. n, s, e, w).
*
* @param stateAbbrev
* @param ugc
* @return
*/
private String getFeArea(String stateAbbrev, String ugc) {
for (GeospatialData g : countyGeoData) {
if (stateAbbrev.equals(g.attributes.get(STATE_FIELD))
&& ((String) g.attributes.get(COUNTY_FIPS_FIELD))
.endsWith(ugc)) {
return (String) g.attributes.get(COUNTY_FE_AREA_FIELD);
}
}
return null;
}
// Based on AWIPS 1 SELSparagraphs.C SELSparagraphs::processWOU().
private String mungeFeAreas(Set<String> feAreas) {
String abrev = "";
// If eight or more portions, don't qualify area of state
int m = feAreas.size();
if (m < 8) {
String partAbrev = "";
/*
* TODO: Unused variables should be removed if we are not going to
* improve this in A2.
*/
@SuppressWarnings("unused")
int nw, nc, ne, wc, cc, ec, sw, sc, se, pa;
int eee, www, nnn, sss, ee, ww, nn, ss;
// Identify individual sub areas of this state affected
nw = nc = ne = wc = cc = ec = sw = sc = se = pa = 0;
eee = www = nnn = sss = ee = ww = nn = ss = 0;
for (String part : feAreas) {
if ("pa".equals(part)) {
pa = 1;
continue;
} else if ("nn".equals(part)) {
nnn = nn = 1;
} else if ("ss".equals(part)) {
sss = ss = 1;
} else if ("ee".equals(part)) {
eee = ee = 1;
} else if ("ww".equals(part)) {
www = ww = 1;
} else if ("nw".equals(part)) {
nnn = www = nw = 1;
} else if ("nc".equals(part)) {
nnn = nc = 1;
} else if ("ne".equals(part)) {
nnn = eee = ne = 1;
} else if ("wc".equals(part)) {
www = wc = 1;
} else if ("cc".equals(part)) {
cc = 1;
continue;
} else if ("ec".equals(part)) {
eee = ec = 1;
} else if ("sw".equals(part)) {
sss = www = sw = 1;
} else if ("sc".equals(part)) {
sss = sc = 1;
} else if ("se".equals(part)) {
sss = eee = se = 1;
}
partAbrev = part;
}
// decide how to describe these subareas.
if ((ne > 0) && (nw > 0)) {
nn = 1;
}
if ((se > 0) && (sw > 0)) {
ss = 1;
}
if ((se > 0) && (ne > 0)) {
ee = 1;
}
if ((sw > 0) && (nw > 0)) {
ww = 1;
}
if ((nnn > 0) && (sss > 0) && (eee > 0) && (www > 0)) {
return abrev;
}
if (((nn > 0) && (ss > 0)) || ((ee > 0) && (ww > 0))) {
return abrev;
}
if (nnn + sss + eee + www == 3) {
if (www == 0) {
abrev = "e";
} else if (eee == 0) {
abrev = "w";
} else if (nnn == 0) {
abrev = "s";
} else if (sss == 0) {
abrev = "n";
}
return abrev;
}
if (((nnn == sss) && (eee == www)) || (cc == m)) {
abrev = "c";
return abrev;
}
if ((pa != 0) && (cc == 0)) {
abrev = "pa";
if (--m <= 0) {
return abrev;
}
}
if (m == 1 + cc) {
abrev += partAbrev + " ";
return abrev;
}
if (nnn != sss) {
abrev += nnn != 0 ? "n" : "s";
}
if (eee != www) {
abrev += eee != 0 ? "e" : "w";
}
}
return abrev;
}
}

View file

@ -156,6 +156,8 @@ import com.vividsolutions.jts.geom.Polygon;
* Apr 24, 2014 DR 16356 Qinglu Lin Updated selectOneStorm() and selectLineOfStorms().
* Apr 28, 2014 3033 jsanchez Re-initialized the Velocity Engine when switching back up sites.
* May 09, 2014 DR16694 m.gamazaychikov Fixed disabled duration menu after creating text for a COR SVS.
* Jul 01, 2014 DR 17450 D. Friedman Use list of templates from backup site.
* Jul 21, 2014 3419 jsanchez Created a hidden button to make recreating polygons easier.
* </pre>
*
* @author chammack
@ -166,6 +168,12 @@ public class WarngenDialog extends CaveSWTDialog implements
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(WarngenDialog.class);
/*
* This flag allows a hidden button to appear to help recreating warning
* polygons that had issues in the feed.
*/
private boolean debug = false;
private static final int BULLET_WIDTH = 390;
private static final int BULLET_HEIGHT = 230;
@ -484,30 +492,39 @@ public class WarngenDialog extends CaveSWTDialog implements
* @param productType2
*/
private void createOtherProductsList(Group productType2) {
other = new Button(productType, SWT.RADIO);
other.setText("Other:");
other.setEnabled(true);
other.addSelectionListener(new SelectionAdapter() {
if (other == null) {
other = new Button(productType, SWT.RADIO);
other.setText("Other:");
other.setEnabled(true);
other.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
otherSelected();
@Override
public void widgetSelected(SelectionEvent arg0) {
otherSelected();
}
});
otherProductListCbo = new Combo(productType, SWT.READ_ONLY
| SWT.DROP_DOWN);
GridData gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false);
otherProductListCbo.setLayoutData(gd);
otherProductListCbo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
otherProductSelected();
}
});
} else {
other.setSelection(false);
if (mainProductBtns.length > 0 && mainProductBtns.length > 0) {
other.moveBelow(mainProductBtns[mainProductBtns.length - 1]);
}
otherProductListCbo.moveBelow(other);
}
});
otherProductListCbo = new Combo(productType, SWT.READ_ONLY
| SWT.DROP_DOWN);
GridData gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false);
otherProductListCbo.setLayoutData(gd);
updateOtherProductList(otherProductListCbo);
otherProductListCbo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
otherProductSelected();
}
});
}
private void createMainProductButtons(Group productType) {
@ -519,12 +536,13 @@ public class WarngenDialog extends CaveSWTDialog implements
mainProducts.add(str);
}
String defaultTemplate = warngenLayer.getDialogConfig()
.getDefaultTemplate();
if ((defaultTemplate == null) || defaultTemplate.equals("")) {
defaultTemplate = mainProducts.get(0).split("/")[1];
}
String defaultTemplate = getDefaultTemplate();
if (mainProductBtns != null) {
for (Button button : mainProductBtns) {
button.dispose();
}
}
mainProductBtns = new Button[mainProducts.size()];
if (mainProducts.size() > 0) {
@ -540,24 +558,29 @@ public class WarngenDialog extends CaveSWTDialog implements
mainProductBtns[0].addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
changeTemplate(mainProducts.get(0).split("/")[1]);
uiChangeTemplate(mainProducts.get(0).split("/")[1]);
}
});
}
GridData gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false);
gd.horizontalIndent = 30;
updateListCbo = new Combo(productType, SWT.READ_ONLY | SWT.DROP_DOWN);
updateListCbo.setLayoutData(gd);
recreateUpdates();
if (updateListCbo == null) {
gd.horizontalIndent = 30;
updateListCbo = new Combo(productType, SWT.READ_ONLY
| SWT.DROP_DOWN);
updateListCbo.setLayoutData(gd);
recreateUpdates();
updateListCbo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
updateListSelected();
}
updateListCbo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
updateListSelected();
}
});
});
} else if (mainProductBtns.length > 0) {
updateListCbo.moveBelow(mainProductBtns[0]);
}
for (int cnt = 1; cnt < mainProducts.size(); cnt++) {
final String[] tmp = mainProducts.get(cnt).split("/");
@ -586,7 +609,7 @@ public class WarngenDialog extends CaveSWTDialog implements
}
}
changeTemplate(templateName);
uiChangeTemplate(templateName);
}
}
});
@ -616,7 +639,8 @@ public class WarngenDialog extends CaveSWTDialog implements
});
Composite redrawFrom = new Composite(redrawBox, SWT.NONE);
redrawFrom.setLayout(new GridLayout(3, false));
int columns = debug ? 4 : 3;
redrawFrom.setLayout(new GridLayout(columns, false));
redrawFrom.setLayoutData(new GridData(SWT.DEFAULT, SWT.FILL, false,
true));
@ -651,9 +675,30 @@ public class WarngenDialog extends CaveSWTDialog implements
damBreakThreatArea.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
damBreakThreatAreaPressed();
DamInfoBullet damBullet = bulletListManager
.getSelectedDamInfoBullet();
if (damBullet != null) {
damBreakThreatAreaPressed(damBullet.getCoords(), true);
}
}
});
if (debug) {
Button drawPolygonButton = new Button(redrawFrom, SWT.PUSH);
drawPolygonButton.setText("?");
drawPolygonButton.setEnabled(true);
drawPolygonButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
/*
* Copy/paste the LAT...LON line from the text product to
* quickly recreate the polygon.
*/
String latLon = "LAT...LON 4282 7174 4256 7129 4248 7159 4280 7198";
damBreakThreatAreaPressed(latLon, false);
}
});
}
}
private void createBackupTrackEditGroups(Composite mainComposite) {
@ -683,7 +728,7 @@ public class WarngenDialog extends CaveSWTDialog implements
backupGroup.setLayout(new GridLayout(2, false));
Label label2 = new Label(backupGroup, SWT.BOLD);
label2.setText("Full:");
label2.setText("WFO:");
label2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
backupSiteCbo = new Combo(backupGroup, SWT.READ_ONLY | SWT.DROP_DOWN);
backupSiteCbo.addSelectionListener(new SelectionAdapter() {
@ -1195,7 +1240,11 @@ public class WarngenDialog extends CaveSWTDialog implements
setInstructions();
} else if (bulletListManager.isDamNameSeletcted()
&& bulletListManager.isDamCauseSelected()) {
damBreakThreatAreaPressed();
DamInfoBullet damBullet = bulletListManager
.getSelectedDamInfoBullet();
if (damBullet != null) {
damBreakThreatAreaPressed(damBullet.getCoords(), true);
}
if (damBreakInstruct != null) {
return false;
}
@ -1323,9 +1372,28 @@ public class WarngenDialog extends CaveSWTDialog implements
} else {
new TemplateRunnerInitJob(backupSite).schedule();
}
// Refresh template
changeTemplate(warngenLayer.getTemplateName());
resetPressed();
/*
* When the product selection buttons are recreated below, the
* button for the default template will be selected and mainProducts
* will have been recreated. Then getDefaultTemplate() can be used
* here to change the state.
*/
createMainProductButtons(productType);
createOtherProductsList(productType);
// Don't let errors prevent the new controls from being displayed!
try {
changeTemplate(getDefaultTemplate());
resetPressed();
} catch (Exception e) {
statusHandler
.error("Error occurred while switching to the default template.",
e);
}
productType.layout(true, true);
getShell().pack(true);
}
if (backupSiteCbo.getSelectionIndex() == 0) {
@ -1413,55 +1481,50 @@ public class WarngenDialog extends CaveSWTDialog implements
}
/**
* This method is responsible for drawing a pre-defined drainage basin on
* the WarnGen layer. The method is called when a drainage basin is selected
* in the WarnGen Dialog Bullet List and the Dam Break Threat Area button is
* pressed. Dam info geometries are defined in the Database so a Spatial
* Query is performed to retrieve the data.
* Responsible for drawing a pre-defined warning polygon (coords) on the
* WarnGen layer.
*
* @param coords
* pre-defined warning polygon coordinates in LAT...LON form.
* @param lockPolygon
* indicates if the polygon should be locked or not.
*/
private void damBreakThreatAreaPressed() {
private void damBreakThreatAreaPressed(String coords, boolean lockPolygon) {
damBreakInstruct = "Either no dam selected, no dam info bullets in .xml file, or no\n"
+ "dam break primary cause selected.";
DamInfoBullet damBullet = bulletListManager.getSelectedDamInfoBullet();
if (damBullet != null) {
if ((damBullet.getCoords() == null)
|| (damBullet.getCoords().length() == 0)) {
damBreakInstruct = "LAT...LON can not be found in 'coords' parameter";
} else {
ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>();
Pattern coordinatePtrn = Pattern
.compile("LAT...LON+(\\s\\d{3,4}\\s\\d{3,5}){1,}");
Pattern latLonPtrn = Pattern
.compile("\\s(\\d{3,4})\\s(\\d{3,5})");
if ((coords == null) || (coords.length() == 0)) {
damBreakInstruct = "LAT...LON can not be found in 'coords' parameter";
} else {
ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>();
Pattern coordinatePtrn = Pattern
.compile("LAT...LON+(\\s\\d{3,4}\\s\\d{3,5}){1,}");
Pattern latLonPtrn = Pattern.compile("\\s(\\d{3,4})\\s(\\d{3,5})");
Matcher m = coordinatePtrn.matcher(damBullet.getCoords());
if (m.find()) {
m = latLonPtrn.matcher(damBullet.getCoords());
while (m.find()) {
coordinates.add(new Coordinate((-1 * Double
.parseDouble(m.group(2))) / 100, Double
.parseDouble(m.group(1)) / 100));
}
if (coordinates.size() < 3) {
damBreakInstruct = "Lat/Lon pair for dam break threat area is less than three";
} else {
coordinates.add(coordinates.get(0));
PolygonUtil.truncate(coordinates, 2);
warngenLayer.createDamThreatArea(coordinates
.toArray(new Coordinate[coordinates.size()]));
setPolygonLocked(true);
warngenLayer.issueRefresh();
damBreakInstruct = null;
}
} else {
damBreakInstruct = "The 'coords' parameter maybe be misformatted or the\n"
+ "La/Lon for dam break threat area is not in pairs.";
Matcher m = coordinatePtrn.matcher(coords);
if (m.find()) {
m = latLonPtrn.matcher(coords);
while (m.find()) {
coordinates.add(new Coordinate((-1 * Double.parseDouble(m
.group(2))) / 100,
Double.parseDouble(m.group(1)) / 100));
}
}
if (coordinates.size() < 3) {
damBreakInstruct = "Lat/Lon pair for dam break threat area is less than three";
} else {
coordinates.add(coordinates.get(0));
PolygonUtil.truncate(coordinates, 2);
warngenLayer.createDamThreatArea(coordinates
.toArray(new Coordinate[coordinates.size()]));
setPolygonLocked(lockPolygon);
warngenLayer.issueRefresh();
damBreakInstruct = null;
}
} else {
damBreakInstruct = "The 'coords' parameter maybe be misformatted or the\n"
+ "La/Lon for dam break threat area is not in pairs.";
}
}
if (damBreakInstruct != null) {
setInstructions();
@ -1490,6 +1553,19 @@ public class WarngenDialog extends CaveSWTDialog implements
return result;
}
/**
* Called by controls that can change the current template. Do not do
* anything if the request template is already selected. This check is
* necessary to prevent certain state being reset if a followup has been
* selected as this is not handled by changeTemplate() (DR 14515.)
*/
private void uiChangeTemplate(String templateName) {
if (templateName.equals(warngenLayer.getTemplateName())) {
return;
}
changeTemplate(templateName);
}
/**
* This method updates the Warngen Layer and Warngen Dialog based on a new
* template selection. This method should also be called when the CWA is
@ -1502,11 +1578,6 @@ public class WarngenDialog extends CaveSWTDialog implements
*/
private void changeTemplate(String templateName) {
// DR 14515
if (templateName.equals(warngenLayer.getTemplateName())) {
return;
}
String lastAreaSource = warngenLayer.getConfiguration()
.getHatchedAreaSource().getAreaSource();
@ -1641,6 +1712,7 @@ public class WarngenDialog extends CaveSWTDialog implements
otherProducts = new HashMap<String, String>();
String[] otherProductsStr = warngenLayer.getDialogConfig()
.getOtherWarngenProducts().split(",");
theList.removeAll();
for (String str : otherProductsStr) {
String[] s = str.split("/");
otherProducts.put(s[0], s[1]);
@ -1791,7 +1863,7 @@ public class WarngenDialog extends CaveSWTDialog implements
templateName = otherProducts.get(otherProductListCbo
.getItem(otherProductListCbo.getSelectionIndex()));
}
changeTemplate(templateName);
uiChangeTemplate(templateName);
otherProductListCbo.pack(true);
productType.layout();
@ -2258,7 +2330,7 @@ public class WarngenDialog extends CaveSWTDialog implements
templateName = otherProducts.get(otherProductListCbo
.getItem(otherProductListCbo.getSelectionIndex()));
}
changeTemplate(templateName);
uiChangeTemplate(templateName);
}
private void refreshDisplay() {
@ -2510,4 +2582,13 @@ public class WarngenDialog extends CaveSWTDialog implements
warngenLayer.issueRefresh();
}
private String getDefaultTemplate() {
String defaultTemplate = warngenLayer.getDialogConfig()
.getDefaultTemplate();
if ((defaultTemplate == null) || defaultTemplate.equals("")) {
defaultTemplate = mainProducts.get(0).split("/")[1];
}
return defaultTemplate;
}
}

View file

@ -212,6 +212,9 @@ import com.vividsolutions.jts.io.WKTReader;
* 04/23/2014 DR 16356 Qinglu Lin Updated initializeState() and added reset().
* 04/28,2014 3033 jsanchez Properly handled back up configuration (*.xml) files. Set backupSite to null when backup site is not selected.
* 05/16/2014 DR 17365 D. Friedman Check if moved vertex results in polygon valid in both lat/lon and local coordinates.
* 07/01/2014 DR 17450 D. Friedman Use list of templates from backup site.
* 07/28/2014 DR 17475 Qinglu Lin Updated populateStrings() and findLargestQuadrant(), removed findLargestGeometry(),
* added createAreaAndCentroidMaps() and movePopulatePt(), updated paintText() to center W.
* </pre>
*
* @author mschenke
@ -224,6 +227,9 @@ public class WarngenLayer extends AbstractStormTrackResource {
String uniqueFip = null;
Map<String, Double> geomArea = new HashMap<String, Double>();
Map<String, Point> geomCentroid = new HashMap<String, Point>();
private static class GeospatialDataList {
private static final String LOCAL_GEOM = "localGeometry";
@ -1096,6 +1102,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
DrawableString string = new DrawableString(text, textColor);
string.magnification = magnification;
string.setCoordinates(out[0], out[1]);
string.horizontalAlignment = IGraphicsTarget.HorizontalAlignment.CENTER;
string.verticallAlignment = IGraphicsTarget.VerticalAlignment.MIDDLE;
strings.add(string);
}
}
@ -1179,6 +1187,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
}// end synchronize
customMaps.loadCustomMaps(Arrays.asList(config.getMaps()));
createAreaAndCentroidMaps();
this.configuration = config;
System.out.println("Total time to init warngen config = "
+ (System.currentTimeMillis() - t0) + "ms");
@ -1381,6 +1391,49 @@ public class WarngenLayer extends AbstractStormTrackResource {
} else {
backupSite = site;
}
DialogConfiguration dc = null;
if (backupSite != null) {
boolean haveBackupConfig = DialogConfiguration.isSiteDialogConfigExtant(backupSite);
if (haveBackupConfig) {
try {
dc = DialogConfiguration.loadDialogConfigNoUser(backupSite);
} catch (Exception e) {
statusHandler.error(String.format(
"Unable to load WarnGen configuration for site %s. Falling back to local configuration.",
getLocalizedSite()), e);
}
} else {
statusHandler.warn(String.format(
"WarnGen configuration for site %s does not exist. Falling back to local configuration.",
backupSite));
}
if (dc == null) {
try {
dc = DialogConfiguration.loadDialogConfigNoUser(LocalizationManager
.getInstance().getCurrentSite());
} catch (Exception e) {
dc = new DialogConfiguration();
statusHandler.error(String.format(
"Unable to load WarnGen configuration for site %s.",
getLocalizedSite()), e);
}
}
} else {
try {
dc = DialogConfiguration.loadDialogConfig(LocalizationManager
.getInstance().getCurrentSite());
} catch (Exception e) {
dc = new DialogConfiguration();
statusHandler.error(
"Unable to load local WarnGen configuration.", e);
}
}
if (dc != null && dialogConfig != null) {
dialogConfig.setDefaultTemplate(dc.getDefaultTemplate());
dialogConfig.setMainWarngenProducts(dc.getMainWarngenProducts());
dialogConfig.setOtherWarngenProducts(dc.getOtherWarngenProducts());
}
}
public String getLocalizedSite() {
@ -3151,66 +3204,127 @@ public class WarngenLayer extends AbstractStormTrackResource {
toKeep.toArray(new Geometry[0]));
}
private void createAreaAndCentroidMaps() {
String gid;
geomArea.clear();
geomCentroid.clear();
for (GeospatialData f : geoData.features) {
Geometry geom = f.getGeometry();
gid = ((CountyUserData)geom.getUserData()).gid;
geomArea.put(gid, geom.getArea());
geomCentroid.put(gid, geom.getCentroid());
}
}
/**
* Populate the W strings with the included counties
*/
private void populateStrings() {
state.strings.clear();
Geometry warningArea = state.getWarningArea();
Set<String> prefixes = new HashSet<String>(Arrays.asList(GeometryUtil
.getGID(state.getWarningArea())));
.getGID(warningArea)));
prefixes = removeDuplicateGid(prefixes);
for (GeospatialData f : geoData.features) {
Geometry geom = f.geometry;
Geometry geom2 = null;
Geometry warningAreaN = null;
Coordinate populatePt = null;
Geometry populatePtGeom;
boolean contained = false, closeTo = false;
double shift = 1.E-8, distance, minDistance = 10.0;
int loop, maxLoop = 10;
Geometry warningArea = state.getWarningArea();
String prefix = GeometryUtil.getPrefix(geom.getUserData());
if (prefixes.contains(prefix)) {
loop = 0;
warningAreaN = findLargestGeometry(GeometryUtil.intersection(geom, warningArea));
do {
if (!warningAreaN.isEmpty()) {
populatePt = GisUtil.d2dCoordinate(warningAreaN.getCentroid()
.getCoordinate());
for (GeospatialData f2 : geoData.features) {
geom2 = f2.getGeometry();
if (!GeometryUtil.getPrefix(geom2.getUserData()).equals(prefix)) {
contained = false;
closeTo = false;
populatePtGeom = PolygonUtil.createPolygonByPoints(populatePt,
new Coordinate(populatePt.x + shift, populatePt.y + shift));
if (GeometryUtil.contains(geom2, populatePtGeom)) {
// populatePt is in another county/zone.
warningAreaN = findLargestQuadrant(warningAreaN, geom);
contained = true;
break;
} else {
distance = populatePtGeom.distance(geom2);
if (distance < minDistance) {
// populatePt is very close to the boundary of another county/zone.
warningAreaN = findLargestQuadrant(warningAreaN, geom);
closeTo = true;
break;
}
}
}
Set<Integer> indexes = new HashSet<Integer>();
String prefixM, prefixN;
double areaM, areaN, maxArea = -1.0;
int geomIndex = -1;
int geomNum = warningArea.getNumGeometries();
// Find an unique index for each county in warningArea. If there is more than one index
// for one county, find the one with max area.
Geometry warningAreaM = null, warningAreaN = null;
for (int i = 0; i < geomNum; i++) {
warningAreaM = warningArea.getGeometryN(i);
prefixM = GeometryUtil.getPrefix(warningAreaM.getUserData());
if (!prefixes.contains(prefixM)) {
continue;
}
areaM = warningAreaM.getArea();
geomIndex = i;
while (i + 1 < geomNum) {
warningAreaN = warningArea.getGeometryN(i + 1);
prefixN = GeometryUtil.getPrefix(warningAreaN.getUserData());
if (prefixN.equals(prefixM)) {
areaN = warningAreaN.getArea();
if (areaN > areaM) {
if (areaN > maxArea) {
maxArea = areaN;
geomIndex = i + 1;
}
} else {
// use the existing populatePt
break;
if (areaM > maxArea) {
maxArea = areaM;
}
}
loop += 1;
} while ((contained || closeTo) && loop <= maxLoop);
state.strings.put(populatePt, "W");
} else {
break;
}
i = i + 1;
}
indexes.add(geomIndex);
}
Map<String, Coordinate> populatePtMap = new HashMap<String, Coordinate>();
GeometryFactory gf = new GeometryFactory();
Geometry geomN = null, populatePtGeom = null;
Coordinate populatePt = new Coordinate();
Point centroid = null;
int loop, maxLoop = 10;
double threshold = 0.1, weight = 0.5, shift = 1.E-8, minArea = 1.0E-2, area;
Iterator<Integer> iter = indexes.iterator();
while (iter.hasNext()) {
warningAreaM = warningArea.getGeometryN(iter.next().intValue());
prefixM = GeometryUtil.getPrefix(warningAreaM.getUserData());
area = warningAreaM.getArea();
if (area < minArea || area / geomArea.get(prefixM) < threshold) {
// Hatched area inside a county is small, move W toward to default centroid
centroid = movePopulatePt(gf, warningAreaM, geomCentroid.get(prefixM), weight);
populatePt = new Coordinate(centroid.getX(), centroid.getY());
populatePtGeom = PolygonUtil.createPolygonByPoints(gf, populatePt, shift);
} else {
// Use the controid of the hatched area in a county
centroid = warningAreaM.getCentroid();
populatePt = new Coordinate(centroid.getX(), centroid.getY());
populatePtGeom = PolygonUtil.createPolygonByPoints(gf, populatePt, shift);
}
for (GeospatialData gd : geoData.features) {
geomN = gd.getGeometry();
CountyUserData cud = (CountyUserData)geomN.getUserData();
prefixN = cud.gid;
if (prefixN.length() > 0 && prefixM.length() > 0 &&
!prefixN.equals(prefixM)) {
if (GeometryUtil.contains(geomN, populatePtGeom)) {
// W is inside a county. Use default centroid of a county (not that of its hatched area)
centroid = geomCentroid.get(prefixM);
populatePt = new Coordinate(centroid.getX(), centroid.getY());
populatePtGeom = PolygonUtil.createPolygonByPoints(gf, populatePt, shift);
}
loop = 1;
while (GeometryUtil.contains(geomN, populatePtGeom) && loop < maxLoop) {
// W is still inside a county, move W to the largest quadrant
warningAreaM = findLargestQuadrant(gf, warningAreaM);
centroid = warningAreaM.getCentroid();
populatePt = new Coordinate(centroid.getX(), centroid.getY());
populatePtGeom = PolygonUtil.createPolygonByPoints(gf, populatePt, shift);
loop += 1;
}
}
}
populatePtMap.put(prefixM, populatePt);
}
for (String key: populatePtMap.keySet()) {
state.strings.put(populatePtMap.get(key), "W");
}
}
private Point movePopulatePt(GeometryFactory gf, Geometry geom, Point point, double weight) {
Point centroid = geom.getCentroid();
Coordinate coord = new Coordinate();
coord.x = centroid.getX() * weight + point.getX() * (1.0 - weight);
coord.y = centroid.getY() * weight + point.getY() * (1.0 - weight);
return gf.createPoint(new Coordinate(coord.x, coord.y));
}
public boolean featureProduct(Coordinate c) {
@ -3487,21 +3601,6 @@ public class WarngenLayer extends AbstractStormTrackResource {
* A Geometry or a GeometryCollection.
* @return Geometry
*/
private Geometry findLargestGeometry(Geometry g) {
int size = g.getNumGeometries();
if (size == 1)
return g;
double area, maxArea = -1.0;
int index = 0;
for (int i = 0; i < size; i++) {
area = g.getGeometryN(i).getArea();
if (area > maxArea) {
maxArea = area;
index = i;
}
}
return g.getGeometryN(index);
}
/**
* Split the hatched area into four quadrants, and return the largest one.
@ -3512,10 +3611,10 @@ public class WarngenLayer extends AbstractStormTrackResource {
* The geometry of a county/zone.
* @return Geometry
* The geometey of largest quadrant among the four, which are the result of
* splitting of hatchedArea.
* splitting of a county's hatched area.
*/
private Geometry findLargestQuadrant(Geometry hatchedArea, Geometry geom) {
Geometry envelope = hatchedArea.getEnvelope();
private Geometry findLargestQuadrant(GeometryFactory gf, Geometry geom) {
Geometry envelope = geom.getEnvelope();
Coordinate centroidCoord = GisUtil.d2dCoordinate(envelope.getCentroid()
.getCoordinate());
Coordinate[] envCoords = envelope.getCoordinates();
@ -3525,19 +3624,22 @@ public class WarngenLayer extends AbstractStormTrackResource {
double largestArea = -1.0, area = -1.0;
int index = -1;
for (int i = 0; i < size; i++) {
quadrants[i] = PolygonUtil.createPolygonByPoints(envCoords[i], centroidCoord);
intersections[i] = GeometryUtil.intersection(quadrants[i], hatchedArea);
area = intersections[i].getArea();
if (area > largestArea) {
largestArea = area;
index = i;
quadrants[i] = PolygonUtil.createPolygonByPoints(gf, envCoords[i], centroidCoord);
try {
intersections[i] = GeometryUtil.intersection(quadrants[i], geom);
area = intersections[i].getArea();
if (area > largestArea) {
largestArea = area;
index = i;
}
} catch (Exception e) {
;
}
}
if (intersections[index].isValid())
if (null != intersections[index] && intersections[index].isValid())
return intersections[index];
else {
// "intersections[" + index + "] is invalid"
return hatchedArea;
return geom;
}
}
@ -3553,4 +3655,5 @@ public class WarngenLayer extends AbstractStormTrackResource {
StormTrackState.trackType = "lineOfStorms";
}
}
}

View file

@ -37,42 +37,25 @@ import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import org.apache.commons.lang.Validate;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.tools.generic.ListTool;
import com.raytheon.uf.common.activetable.ActiveTableRecord;
import com.raytheon.uf.common.activetable.OperationalActiveTableRecord;
import com.raytheon.uf.common.activetable.PracticeActiveTableRecord;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
import com.raytheon.uf.common.dataplugin.warning.WarningConstants;
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration;
import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration.AreaType;
import com.raytheon.uf.common.dataplugin.warning.config.WarngenConfiguration;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialData;
import com.raytheon.uf.common.dataplugin.warning.portions.GisUtil;
import com.raytheon.uf.common.dataplugin.warning.portions.PortionsUtil;
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
@ -84,11 +67,9 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.SimulatedTime;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.viz.awipstools.ToolsDataManager;
import com.raytheon.viz.awipstools.common.StormTrackData;
import com.raytheon.viz.awipstools.common.stormtrack.StormTrackState;
@ -99,6 +80,8 @@ import com.raytheon.viz.warngen.gis.AffectedAreas;
import com.raytheon.viz.warngen.gis.Area;
import com.raytheon.viz.warngen.gis.ClosestPointComparator;
import com.raytheon.viz.warngen.gis.PathCast;
import com.raytheon.viz.warngen.gis.Watch;
import com.raytheon.viz.warngen.gis.WatchUtil;
import com.raytheon.viz.warngen.gis.Wx;
import com.raytheon.viz.warngen.gui.BackupData;
import com.raytheon.viz.warngen.gui.FollowupData;
@ -111,9 +94,6 @@ import com.raytheon.viz.warngen.util.CurrentWarnings;
import com.raytheon.viz.warngen.util.FipsUtil;
import com.raytheon.viz.warngen.util.FollowUpUtil;
import com.raytheon.viz.warngen.util.WarnGenMathTool;
import com.raytheon.viz.warngen.util.WatchUtil;
import com.raytheon.viz.warngen.util.WeatherAdvisoryWatch;
import com.raytheon.viz.warngen.util.WeatherAdvisoryWatch.Portion;
import com.raytheon.viz.warnings.DateUtil;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
@ -160,6 +140,7 @@ import com.vividsolutions.jts.io.WKTReader;
* Mar 17, 2014 DR 16309 Qinglu Lin Updated getWatches(), processATEntries() and determineAffectedPortions(), and
* added determineAffectedMarinePortions().
* Apr 28, 2014 3033 jsanchez Set the site and backup site in Velocity Engine's properties
* Jul 21, 2014 3419 jsanchez Refactored WatchUtil.
* </pre>
*
* @author njensen
@ -172,16 +153,13 @@ public class TemplateRunner {
private static final String LOGIN_NAME_KEY = "LOGNAME";
private static final UnitConverter milesToKilometer = NonSI.MILE
.getConverterTo(SI.KILOMETER);
private static final double KmToDegrees = 111.12;
private static final Pattern BBB_PATTERN = Pattern
.compile(".*\\sCC([A-Z])");
private static Hashtable<String, DateFormat> dateFormat;
private static WatchUtil watchUtil;
static {
dateFormat = new Hashtable<String, DateFormat>();
dateFormat
@ -876,11 +854,14 @@ public class TemplateRunner {
// Store Watches
try {
t0 = System.currentTimeMillis();
WatchUtil watches = getWatches(warngenLayer, config, warnPolygon,
areas, fourLetterSiteId, simulatedTime);
if (watchUtil == null) {
watchUtil = new WatchUtil(warngenLayer);
}
List<Watch> watches = watchUtil.getWatches(config, warnPolygon,
simulatedTime);
System.out.println("getWatches time: "
+ (System.currentTimeMillis() - t0));
if (watches != null) {
if (watches != null && watches.isEmpty() == false) {
context.put("watches", watches);
}
} catch (Exception e) {
@ -980,574 +961,4 @@ public class TemplateRunner {
return rval;
}
/**
* This method populates a WatchUtil object with tornado and severe
* thunderstorm watches from the active table that are contained by the
* polygon. Furthermore, watches that have not yet expired (current time <
* end time) are only included.
*
* @param config
* WarnGen template configuration settings
* ([template_name_site.xml])
* @param polygon
* The Geometry surrounded by the warning polygon.
* @param simulatedTime
* @return
* @throws Exception
*/
private static WatchUtil getWatches(WarngenLayer warngenLayer,
WarngenConfiguration config, Geometry polygon,
AffectedAreas[] affectedAreas, String fourLetterSiteId,
Date simulatedTime) throws Exception {
Validate.isTrue(config.getHatchedAreaSource()
.getIncludedWatchAreaBuffer() >= 0,
"IncludedWatchAreaBuffer can not be negative");
WatchUtil rval = null;
String[] includedWatches = config.getIncludedWatches();
if ((includedWatches != null) && (includedWatches.length > 0)) {
String phensigList = null;
for (String includedWatch : includedWatches) {
if (includedWatch.equalsIgnoreCase("torWatches")) {
phensigList = phensigList == null ? "TO.A" : phensigList
+ ",TO.A";
} else if (includedWatch.equalsIgnoreCase("svrWatches")) {
phensigList = phensigList == null ? "SV.A" : phensigList
+ ",SV.A";
}
}
if (phensigList != null) {
// Create start/endtime constraints
Date endConstraintTime = simulatedTime;
Calendar cal = Calendar.getInstance();
cal.setTime(simulatedTime);
cal.add(Calendar.MINUTE, 3);
Date startConstraintTime = cal.getTime();
// Get record type
Class<? extends ActiveTableRecord> recordType = CAVEMode
.getMode() == CAVEMode.OPERATIONAL ? OperationalActiveTableRecord.class
: PracticeActiveTableRecord.class;
DbQueryRequest request = new DbQueryRequest();
request.setEntityClass(recordType);
request.addConstraint("startTime", new RequestConstraint(
TimeUtil.formatDate(startConstraintTime),
ConstraintType.LESS_THAN_EQUALS));
request.addConstraint(
"endTime",
new RequestConstraint(TimeUtil
.formatDate(endConstraintTime),
ConstraintType.GREATER_THAN_EQUALS));
/*
* TODO: Currently limited to filtering out one of
* ("CAN","EXP"). Could use "Act" in addition to "act", but this
* should really be fixed the underlying system.
* request.addConstraint("act", new RequestConstraint("CAN",
* ConstraintType.NOT_EQUALS));
*/
request.addConstraint("act", new RequestConstraint("EXP",
ConstraintType.NOT_EQUALS));
request.addConstraint("phensig", new RequestConstraint(
phensigList, ConstraintType.IN));
// TODO: Talk to Jonathan about this... Do I even need officeid
// IN or is ugc zone good enough?
/*
* Get all UGCs in the CWA now so that the watches will be
* formatted with all portions of the affected state(s).
*
* Filtering for valid UGCs is performed in processATEntries
*/
RequestConstraint ugcConstraint = new RequestConstraint("",
ConstraintType.IN);
ugcConstraint.setConstraintValueList(warngenLayer
.getAllUgcs());
request.addConstraint("ugcZone", ugcConstraint);
// These are the only fields we need for processing watches
request.addFields(new String[] { "issueTime", "startTime",
"endTime", "ugcZone", "phensig", "vtecstr", "etn",
"act" });
DbQueryResponse response = (DbQueryResponse) ThriftClient
.sendRequest(request);
List<ActiveTableRecord> records = new ArrayList<ActiveTableRecord>(
response.getNumResults());
for (Map<String, Object> result : response.getResults()) {
/*
* TODO: Doing this here because only "EXP" is filtered out
* by the query. Remove "act" from the field list once this
* is fixed.
*/
if ("CAN".equals(result.get("act")))
continue;
ActiveTableRecord record = recordType.newInstance();
record.setIssueTime((Calendar) result.get("issueTime"));
record.setStartTime((Calendar) result.get("startTime"));
record.setEndTime((Calendar) result.get("endTime"));
record.setUgcZone((String) result.get("ugcZone"));
record.setPhensig((String) result.get("phensig"));
record.setVtecstr((String) result.get("vtecstr"));
record.setEtn((String) result.get("etn"));
records.add(record);
}
if (records.size() > 0) {
Set<String> validUgcZones;
try {
long t0, t1;
t0 = System.currentTimeMillis();
Polygon watchArea = (Polygon) polygon
.buffer(milesToKilometer.convert(config
.getHatchedAreaSource()
.getIncludedWatchAreaBuffer())
/ KmToDegrees);
t1 = System.currentTimeMillis();
System.out.println("getWatches.polygonBuffer time: "
+ (t1 - t0));
validUgcZones = warngenLayer
.getUgcsForWatches(watchArea);
} catch (RuntimeException e) {
statusHandler
.handle(Priority.ERROR,
"Error determining areas to search for watches.",
e);
return rval;
}
rval = processATEntries(records, warngenLayer,
validUgcZones);
}
}
}
return rval;
}
private static class WatchWork {
public WeatherAdvisoryWatch waw;
public boolean valid;
public ArrayList<String> ugcZone = new ArrayList<String>();
public WatchWork(WeatherAdvisoryWatch waw) {
this.waw = waw;
}
}
/**
* Create the list of objects representing active watches that will be
* passed to the template context.
*
* @param activeTable
* List of entries for active watches
* @param warngenLayer
* @param validUgcZones
* @return
*/
private static WatchUtil processATEntries(
List<ActiveTableRecord> activeTable, WarngenLayer warngenLayer,
Set<String> validUgcZones) {
WatchUtil rval = new WatchUtil();
TreeMap<WeatherAdvisoryWatch, WatchWork> map = new TreeMap<WeatherAdvisoryWatch, TemplateRunner.WatchWork>();
AreaSourceConfiguration asc = null;
for (AreaSourceConfiguration a : warngenLayer.getConfiguration()
.getAreaSources()) {
if (a.getType() == AreaType.HATCHING) {
asc = a;
break;
}
}
if (asc == null) {
statusHandler
.handle(Priority.ERROR,
"Cannot process watches: missing HATCHING area source configuration");
return rval;
}
GeospatialData[] geoData = warngenLayer.getGeodataFeatures(
asc.getAreaSource(), warngenLayer.getLocalizedSite());
if ((geoData == null) || (geoData.length == 0)) {
statusHandler.handle(Priority.ERROR,
"Cannot process watches: cannot get geospatial data");
return rval;
}
// For each watch event, get the end time and list of active zones
for (ActiveTableRecord ar : activeTable) {
/*
* Currently reports all zones in the watch even if a given zone is
* not in the warning polygon. If the logic is changed to only show
* the portions of the watch near our warning polygon, filter on
* validUgcZones here.
*/
WeatherAdvisoryWatch waw = new WeatherAdvisoryWatch();
waw.setPhensig(ar.getPhensig());
try {
waw.setEventId(Integer.parseInt(ar.getEtn()));
} catch (RuntimeException e) {
statusHandler.handle(Priority.ERROR, String.format(
"Watch %s has null end time; not included.",
ar.getVtecstr()));
continue;
}
WatchWork work = map.get(waw);
if (work == null) {
waw.setEndTime(ar.getEndTime().getTime());
work = new WatchWork(waw);
map.put(waw, work);
}
if (validUgcZones.contains(ar.getUgcZone())) {
work.valid = true;
}
/*
* There are no checks here to determine whether or not the given
* zone is in the CWA. That should have already been done the query
* performed in getWatches.
*
* There is also validation performed later in
* determineAffectedPortions.
*/
work.ugcZone.add(ar.getUgcZone());
}
for (WatchWork work : map.values()) {
/*
* If none of the areas in the watch were neer our warning polygon,
* do not included it.
*/
if (!work.valid) {
continue;
}
boolean isMarineZone = warngenLayer.getConfiguration().getGeospatialConfig()
.getAreaSource().equalsIgnoreCase(WarngenLayer.MARINE);
if (!isMarineZone) {
if (determineAffectedPortions(work.ugcZone, asc, geoData, work.waw)) {
rval.addWaw(work.waw);
}
} else {
if (determineAffectedMarinePortions(work.ugcZone, asc, geoData, work.waw)) {
rval.addWaw(work.waw);
}
}
}
return rval;
}
/**
* Given the list of counties in a watch, fill out the "portions" part of
* the given WeatherAdvisoryWatch. Also checks if the given counties are
* actually in the CWA.
*
* @param ugcs
* @param asc
* @param geoData
* @param waw
*/
private static boolean determineAffectedPortions(List<String> ugcs,
AreaSourceConfiguration asc, GeospatialData[] geoData,
WeatherAdvisoryWatch waw) {
// Maps state abbreviation to unique fe_area values
HashMap<String, Set<String>> map = new HashMap<String, Set<String>>();
for (String ugc : ugcs) {
Map<String, String[]> parsed = FipsUtil.parseHeader(ugc, "County");
Entry<String, String[]> e = null;
// Either zero or more than one sates/counties would be wrong
if ((parsed.size() != 1)
|| ((e = parsed.entrySet().iterator().next()).getValue().length != 1)) {
statusHandler.handle(Priority.ERROR,
"Invalid ugczone in active table entry: " + ugc);
continue;
}
String stateAbbrev = e.getKey();
String feArea = null;
try {
feArea = getFeArea(stateAbbrev, e.getValue()[0], asc, geoData);
} catch (RuntimeException exc) {
statusHandler.handle(Priority.ERROR,
"Error generating included watches.", exc);
return false;
}
if (feArea == NOT_IN_CWA) {
continue;
}
Set<String> feAreas = map.get(stateAbbrev);
if (feAreas == null) {
feAreas = new HashSet<String>();
map.put(stateAbbrev, feAreas);
}
if (feArea != null) {
feAreas.add(feArea);
}
}
ArrayList<Portion> portions = new ArrayList<Portion>(map.size());
for (Entry<String, Set<String>> e : map.entrySet()) {
Portion portion = new Portion();
try {
portion.parentRegion = getStateName(e.getKey(), asc, geoData)
.toUpperCase();
} catch (RuntimeException exc) {
statusHandler.handle(Priority.ERROR,
"Error generating included watches.", exc);
return false;
}
portion.partOfParentRegion = Area
.converFeAreaToPartList(mungeFeAreas(e.getValue()));
portions.add(portion);
}
waw.setPortions(portions);
// Set legacy values
if (portions.size() > 0) {
waw.setParentRegion(portions.get(0).parentRegion);
waw.setPartOfParentRegion(portions.get(0).partOfParentRegion);
}
return true;
}
/**
* Given the list of marine zones in a watch, fill out the "portions" part of
* the given WeatherAdvisoryWatch. Also checks if the given marine zones are
* actually in the CWA.
*
* @param ugcs
* @param asc
* @param geoData
* @param waw
*/
@SuppressWarnings("deprecation")
private static boolean determineAffectedMarinePortions(List<String> ugcs,
AreaSourceConfiguration asc, GeospatialData[] geoData,
WeatherAdvisoryWatch waw) {
// Maps state abbreviation to unique fe_area values
HashMap<String, Set<String>> map = new HashMap<String, Set<String>>();
Set<String> marinezonenameSet = new HashSet<String>();
for (String ugc : ugcs) {
for (GeospatialData gd: geoData) {
if (gd.attributes.get("ID").equals(ugc)) {
marinezonenameSet.add((String)gd.attributes.get("NAME"));
}
}
}
String marinezonename = "";
int size = marinezonenameSet.size();
Iterator<String> iter = marinezonenameSet.iterator();
int count = 0;
while (iter.hasNext()) {
String s = iter.next();
marinezonename += s;
count += 1;
if (size > 1) {
if (size == 2 && count < 2) {
marinezonename += " and ";
} else {
if (count == size - 1) {
marinezonename += ", and ";
} else {
if (count < size - 1) {
marinezonename += ", ";
}
}
}
}
}
for (String ugc : ugcs) {
Map<String, String[]> parsed = FipsUtil.parseHeader(ugc, "Marine");
Entry<String, String[]> e = null;
// Either zero or more than one marine zone would be wrong
if ((parsed.size() != 1)
|| ((e = parsed.entrySet().iterator().next()).getValue().length != 1)) {
statusHandler.handle(Priority.ERROR,
"Invalid ugczone in active table entry: " + ugc);
continue;
}
String stateAbbrev = e.getKey();
Set<String> feAreas = map.get(stateAbbrev);
if (feAreas == null) {
feAreas = new HashSet<String>();
map.put(stateAbbrev, feAreas);
}
}
ArrayList<Portion> portions = new ArrayList<Portion>(map.size());
Portion portion = new Portion();
portion.parentRegion = marinezonename;
portion.partOfParentRegion = new ArrayList<String>();
portion.partOfParentRegion.add("");
portions.add(portion);
waw.setPortions(portions);
// Set legacy values
if (portions.size() > 0) {
waw.setParentRegion(portions.get(0).parentRegion);
waw.setPartOfParentRegion(portions.get(0).partOfParentRegion);
}
return true;
}
// Based on AWIPS 1 SELSparagraphs.C SELSparagraphs::processWOU().
private static String mungeFeAreas(Set<String> feAreas) {
String abrev = "";
// If eight or more portions, don't qualify area of state
int m = feAreas.size();
if (m < 8) {
String partAbrev = "";
/*
* TODO: Unused variables should be removed if we are not going to
* improve this in A2.
*/
@SuppressWarnings("unused")
int nw, nc, ne, wc, cc, ec, sw, sc, se, pa;
int eee, www, nnn, sss, ee, ww, nn, ss;
// Identify individual sub areas of this state affected
nw = nc = ne = wc = cc = ec = sw = sc = se = pa = 0;
eee = www = nnn = sss = ee = ww = nn = ss = 0;
for (String part : feAreas) {
if ("pa".equals(part)) {
pa = 1;
continue;
} else if ("nn".equals(part)) {
nnn = nn = 1;
} else if ("ss".equals(part)) {
sss = ss = 1;
} else if ("ee".equals(part)) {
eee = ee = 1;
} else if ("ww".equals(part)) {
www = ww = 1;
} else if ("nw".equals(part)) {
nnn = www = nw = 1;
} else if ("nc".equals(part)) {
nnn = nc = 1;
} else if ("ne".equals(part)) {
nnn = eee = ne = 1;
} else if ("wc".equals(part)) {
www = wc = 1;
} else if ("cc".equals(part)) {
cc = 1;
continue;
} else if ("ec".equals(part)) {
eee = ec = 1;
} else if ("sw".equals(part)) {
sss = www = sw = 1;
} else if ("sc".equals(part)) {
sss = sc = 1;
} else if ("se".equals(part)) {
sss = eee = se = 1;
}
partAbrev = part;
}
// decide how to describe these subareas.
if ((ne > 0) && (nw > 0)) {
nn = 1;
}
if ((se > 0) && (sw > 0)) {
ss = 1;
}
if ((se > 0) && (ne > 0)) {
ee = 1;
}
if ((sw > 0) && (nw > 0)) {
ww = 1;
}
if ((nnn > 0) && (sss > 0) && (eee > 0) && (www > 0)) {
return abrev;
}
if (((nn > 0) && (ss > 0)) || ((ee > 0) && (ww > 0))) {
return abrev;
}
if (nnn + sss + eee + www == 3) {
if (www == 0) {
abrev = "e";
} else if (eee == 0) {
abrev = "w";
} else if (nnn == 0) {
abrev = "s";
} else if (sss == 0) {
abrev = "n";
}
return abrev;
}
if (((nnn == sss) && (eee == www)) || (cc == m)) {
abrev = "c";
return abrev;
}
if ((pa != 0) && (cc == 0)) {
abrev = "pa";
if (--m <= 0) {
return abrev;
}
}
if (m == 1 + cc) {
abrev += partAbrev + " ";
return abrev;
}
if (nnn != sss) {
abrev += nnn != 0 ? "n" : "s";
}
if (eee != www) {
abrev += eee != 0 ? "e" : "w";
}
}
return abrev;
}
private static String getStateName(String key, AreaSourceConfiguration asc,
GeospatialData[] geoData) {
for (GeospatialData g : geoData) {
if (key.equals(g.attributes.get("STATE"))) {
return (String) g.parent.attributes.get("NAME");
}
}
return null;
}
private static String NOT_IN_CWA = new String("NOT_IN_CWA");
/**
* Determines if the given UGC is in the CWA and if it is, returns the
* portion of the CWA.
*
* @param stateAbbrev
* @param ugc
* @param asc
* @param geoData
* @return
*/
private static String getFeArea(String stateAbbrev, String ugc,
AreaSourceConfiguration asc, GeospatialData[] geoData) {
for (GeospatialData g : geoData) {
if (stateAbbrev.equals(g.attributes.get("STATE"))
&& ((String) g.attributes.get(asc.getFipsField()))
.endsWith(ugc)) {
return (String) g.attributes.get(asc.getFeAreaField());
}
}
// TODO: Is this the correct way to determine if the county is in the
// CWA?
return NOT_IN_CWA;
}
}

View file

@ -1,100 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.util;
import java.util.ArrayList;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;
/**
* This utility will provide an object to be sent into velocity templates which
* will allow the template to output current Warnings.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 1, 2009 bwoodle Initial creation
*
* </pre>
*
* @author bwoodle
* @version 1.0
*/
public class WatchUtil {
private Date latestTorTime;
private Date latestSvrTime;
private ArrayList<WeatherAdvisoryWatch> torWatches;
private ArrayList<WeatherAdvisoryWatch> svrWatches;
public WatchUtil() {
torWatches = new ArrayList<WeatherAdvisoryWatch>();
svrWatches = new ArrayList<WeatherAdvisoryWatch>();
}
public void addWaw(WeatherAdvisoryWatch watch) {
if (watch.getPhensig().equalsIgnoreCase("SV.A")) {
svrWatches.add(watch);
if (latestSvrTime == null
|| watch.getEndTime().after(latestSvrTime)) {
latestSvrTime = watch.getEndTime();
}
} else if (watch.getPhensig().equalsIgnoreCase("TO.A")) {
torWatches.add(watch);
if (latestTorTime == null
|| watch.getEndTime().after(latestTorTime)) {
latestTorTime = watch.getEndTime();
}
}
}
public ArrayList<WeatherAdvisoryWatch> getTorWatches() {
Set<WeatherAdvisoryWatch> rval = new TreeSet<WeatherAdvisoryWatch>();
for (WeatherAdvisoryWatch w : torWatches) {
w.setEndTime(latestTorTime);
rval.add(w);
}
return new ArrayList<WeatherAdvisoryWatch>(rval);
}
public ArrayList<WeatherAdvisoryWatch> getSvrWatches() {
Set<WeatherAdvisoryWatch> rval = new TreeSet<WeatherAdvisoryWatch>();
for (WeatherAdvisoryWatch w : svrWatches) {
w.setEndTime(latestSvrTime);
rval.add(w);
}
return new ArrayList<WeatherAdvisoryWatch>(rval);
}
public Date getLatestTorTime() {
return latestTorTime;
}
public Date getLatestSvrTime() {
return latestSvrTime;
}
}

View file

@ -1,155 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.util;
import java.util.Date;
import java.util.List;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 1, 2009 bwoodle Initial creation
* Nov 9, 2012 DR 15430 D. Friedman Support proper watch inclusion language
*
* </pre>
*
* @author bwoodle
* @version 1.0
*/
public class WeatherAdvisoryWatch implements Comparable<WeatherAdvisoryWatch> {
public static class Portion {
public String parentRegion;
public List<String> partOfParentRegion;
public String getParentRegion() {
return parentRegion;
}
public void setParentRegion(String parentRegion) {
this.parentRegion = parentRegion;
}
public List<String> getPartOfParentRegion() {
return partOfParentRegion;
}
public void setPartOfParentRegion(List<String> partOfParentRegion) {
this.partOfParentRegion = partOfParentRegion;
}
}
/* TODO: NOTE: There is no site field. We currently only process
* WCNs for the site and not WOUs from the SPC.
*/
private String phensig;
private int eventId;
private Date endTime;
private List<Portion> portions;
@Deprecated
private String parentRegion;
@Deprecated
private List<String> partOfParentRegion;
public String getPhensig() {
return phensig;
}
public void setPhensig(String phensig) {
this.phensig = phensig;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
@Deprecated
public String getParentRegion() {
return parentRegion;
}
@Deprecated
public void setParentRegion(String parentRegion) {
this.parentRegion = parentRegion;
}
@Deprecated
public List<String> getPartOfParentRegion() {
return partOfParentRegion;
}
@Deprecated
public void setPartOfParentRegion(List<String> partOfParentRegion) {
this.partOfParentRegion = partOfParentRegion;
}
@Override
public boolean equals(Object obj) {
return obj instanceof WeatherAdvisoryWatch &&
this.compareTo((WeatherAdvisoryWatch) obj) == 0;
}
public int compareTo(WeatherAdvisoryWatch waw) {
if (this.phensig == null)
return waw.phensig == null ? 0 : -1;
else if (waw.phensig == null)
return 1;
else {
int c = this.phensig.compareTo(waw.phensig);
if (c == 0)
return this.eventId - waw.eventId;
else
return c;
}
}
public int getEventId() {
return eventId;
}
public void setEventId(int eventId) {
this.eventId = eventId;
}
public List<Portion> getPortions() {
return portions;
}
public void setPortions(List<Portion> portions) {
this.portions = portions;
}
}

View file

@ -136,6 +136,19 @@
</doTry>
</route>
<!-- Convert the topic into a queue so only one consumer gets each message and we still have competing consumers. -->
<route id="gfePurgeNotificationQueueRoute">
<from uri="jms-generic:topic:pluginPurged"/>
<doTry>
<to uri="jms-generic:queue:gfePurgeNotification"/>
<doCatch>
<exception>java.lang.Throwable</exception>
<to
uri="log:ifpServer?level=ERROR"/>
</doCatch>
</doTry>
</route>
</camelContext>
<bean factory-bean="contextManager" factory-method="registerClusteredContext">

View file

@ -101,7 +101,7 @@ import com.raytheon.uf.edex.database.purge.PurgeLogger;
* D2DGridDatabase constructor
* 04/23/13 #1949 rjpeter Added inventory retrieval for a given time range.
* 05/02/13 #1969 randerso Fixed possible null pointer in getParmList
* Removed inventory from DBInvChangedNotification
* Removed inventory from DBInvChangeNotification
* 05/03/13 #1974 randerso Fixed error logging to include stack trace
* 05/14/13 #2004 randerso Added methods to synch GridParmManager across JVMs
* 05/30/13 #2044 randerso Refactored to better match A1 design. Removed D2DParmIDCache.
@ -119,7 +119,10 @@ import com.raytheon.uf.edex.database.purge.PurgeLogger;
* the same parm simultaneously.
* Added code to check the purge times when publishing and not publish
* data that is eligible to be purged.
*
* 06/24/2014 #3317 randerso Send DBInvChangeNotification when database is created, unless it's
* created in response to another DBInvChangeNotification so IFPServers stay in synch.
* Cleaned up commented code.
* 07/21/2014 #3415 randerso Fixed d2dGridDataPurged to not purge NetCDF databases.
* </pre>
*
* @author bphillip
@ -172,7 +175,7 @@ public class GridParmManager {
this.lockMgr.setGridParmMgr(this);
initializeManager();
}
}
/**
* Dispose the GridParmManager
@ -199,7 +202,7 @@ public class GridParmManager {
.debug("No matching GridDatabase for requested ParmID in createParm()");
// TODO: should we return null?
return new GridParm();
}
}
}
/**
@ -330,10 +333,10 @@ public class GridParmManager {
for (SaveGridRequest req : saveRequest) {
ServerResponse<?> ssr = null;
GridParm gp = null;
gp = gridParm(req.getParmId());
if (!gp.isValid()) {
sr.addMessage("Unknown Parm: " + req.getParmId()
+ " in saveGridData()");
gp = gridParm(req.getParmId());
if (!gp.isValid()) {
sr.addMessage("Unknown Parm: " + req.getParmId()
+ " in saveGridData()");
statusHandler.error("Unknown Parm: " + req.getParmId()
+ " in saveGridData()");
continue;
@ -455,27 +458,27 @@ public class GridParmManager {
// for the source data
ParmID sourceParmId = req.getParmId();
GridParm sourceGP = gridParm(sourceParmId);
if (!sourceGP.isValid()) {
ssr.addMessage("Unknown Source Parm: " + req.getParmId()
+ " in commitGrid()");
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
if (!sourceGP.isValid()) {
ssr.addMessage("Unknown Source Parm: " + req.getParmId()
+ " in commitGrid()");
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
// for the destination data
ParmID destParmId = new ParmID(req.getParmId().getParmName(),
officialDBid, req.getParmId().getParmLevel());
String destParmIdStr = destParmId.toString();
GridParm destGP = null;
destGP = gridParm(destParmId);
if (!destGP.isValid()) {
ssr.addMessage("Unknown Destination Parm: " + destGP
+ " in commitGrid()");
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
destGP = gridParm(destParmId);
if (!destGP.isValid()) {
ssr.addMessage("Unknown Destination Parm: " + destGP
+ " in commitGrid()");
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
// verify that the source and destination are matched
GridParmInfo sourceInfo, destInfo;
@ -519,17 +522,17 @@ public class GridParmManager {
publishTime.setStart(startTime);
}
inventoryTimer.start();
inventoryTimer.start();
ServerResponse<List<TimeRange>> invSr = sourceGP
.getGridInventory(publishTime);
List<TimeRange> overlapInventory = invSr.getPayload();
ssr.addMessages(invSr);
if (!ssr.isOkay()) {
ssr.addMessage("GetGridInventory for source for commitGrid() failure: "
+ ssr.message());
srDetailed.addMessages(ssr);
failures.add(req);
}
ssr.addMessages(invSr);
if (!ssr.isOkay()) {
ssr.addMessage("GetGridInventory for source for commitGrid() failure: "
+ ssr.message());
srDetailed.addMessages(ssr);
failures.add(req);
}
// expand publish time to span overlapping inventory
if (!overlapInventory.isEmpty()) {
@ -546,173 +549,173 @@ public class GridParmManager {
}
invSr = destGP.getGridInventory(publishTime);
inventoryTimer.stop();
List<TimeRange> destInventory = invSr.getPayload();
ssr.addMessages(invSr);
if (!ssr.isOkay()) {
ssr.addMessage("GetGridInventory for destination for commitGrid() failure: "
+ ssr.message());
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
// get the source grid data
List<IGridSlice> sourceData = null;
List<TimeRange> badGridTR = new ArrayList<TimeRange>();
// System.out.println("overlapInventory initial size "
// + overlapInventory.size());
historyRetrieveTimer.start();
ServerResponse<Map<TimeRange, List<GridDataHistory>>> history = sourceGP
.getGridHistory(overlapInventory);
Map<TimeRange, List<GridDataHistory>> currentDestHistory = destGP
.getGridHistory(overlapInventory).getPayload();
historyRetrieveTimer.stop();
Map<TimeRange, List<GridDataHistory>> historyOnly = new HashMap<TimeRange, List<GridDataHistory>>();
for (TimeRange tr : history.getPayload().keySet()) {
// should only ever be one history for source grids
List<GridDataHistory> gdhList = history.getPayload()
.get(tr);
boolean doPublish = false;
for (GridDataHistory gdh : gdhList) {
// if update time is less than publish time, grid
// has not changed since last published,
// therefore only update history, do not publish
if ((gdh.getPublishTime() == null)
|| (gdh.getUpdateTime().getTime() > gdh
.getPublishTime().getTime())
// in service backup, times on srcHistory
// could appear as not needing a publish,
// even though dest data does not exist
|| (currentDestHistory.get(tr) == null)
|| (currentDestHistory.get(tr).size() == 0)) {
doPublish = true;
}
}
if (!doPublish) {
historyOnly.put(tr, gdhList);
overlapInventory.remove(tr);
}
}
retrieveTimer.start();
ServerResponse<List<IGridSlice>> getSr = sourceGP.getGridData(
new GetGridRequest(req.getParmId(), overlapInventory),
badGridTR);
retrieveTimer.stop();
// System.out.println("Retrieved " + overlapInventory.size()
// + " grids");
sourceData = getSr.getPayload();
ssr.addMessages(getSr);
if (!ssr.isOkay()) {
ssr.addMessage("GetGridData for source for commitGrid() failure: "
+ ssr.message());
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
// get list of official grids that overlap publish range and
// aren't contained in the publish range, these have to be
// included in the publish step. Then get the grids, shorten
// and insert into sourceData.
List<IGridSlice> officialData = new ArrayList<IGridSlice>();
List<TimeRange> officialTR = new ArrayList<TimeRange>();
for (int t = 0; t < destInventory.size(); t++) {
if (!publishTime.contains(destInventory.get(t))) {
officialTR.add(destInventory.get(t));
}
}
if (!officialTR.isEmpty()) {
retrieveTimer.start();
getSr = destGP.getGridData(new GetGridRequest(destParmId,
officialTR), badGridTR);
retrieveTimer.stop();
officialData = getSr.getPayload();
ssr.addMessages(getSr);
inventoryTimer.stop();
List<TimeRange> destInventory = invSr.getPayload();
ssr.addMessages(invSr);
if (!ssr.isOkay()) {
ssr.addMessage("GetGridData for official for commidtGrid() failure: "
ssr.addMessage("GetGridInventory for destination for commitGrid() failure: "
+ ssr.message());
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
// insert the grid into the "sourceGrid" list
for (int t = 0; t < officialTR.size(); t++) {
// before
try {
if (officialTR.get(t).getStart()
.before(publishTime.getStart())) {
// get the source grid data
List<IGridSlice> sourceData = null;
List<TimeRange> badGridTR = new ArrayList<TimeRange>();
// System.out.println("overlapInventory initial size "
// + overlapInventory.size());
historyRetrieveTimer.start();
ServerResponse<Map<TimeRange, List<GridDataHistory>>> history = sourceGP
.getGridHistory(overlapInventory);
Map<TimeRange, List<GridDataHistory>> currentDestHistory = destGP
.getGridHistory(overlapInventory).getPayload();
historyRetrieveTimer.stop();
Map<TimeRange, List<GridDataHistory>> historyOnly = new HashMap<TimeRange, List<GridDataHistory>>();
for (TimeRange tr : history.getPayload().keySet()) {
// should only ever be one history for source grids
List<GridDataHistory> gdhList = history.getPayload()
.get(tr);
boolean doPublish = false;
for (GridDataHistory gdh : gdhList) {
// if update time is less than publish time, grid
// has not changed since last published,
// therefore only update history, do not publish
if ((gdh.getPublishTime() == null)
|| (gdh.getUpdateTime().getTime() > gdh
.getPublishTime().getTime())
// in service backup, times on srcHistory
// could appear as not needing a publish,
// even though dest data does not exist
|| (currentDestHistory.get(tr) == null)
|| (currentDestHistory.get(tr).size() == 0)) {
doPublish = true;
}
}
if (!doPublish) {
historyOnly.put(tr, gdhList);
overlapInventory.remove(tr);
}
}
retrieveTimer.start();
ServerResponse<List<IGridSlice>> getSr = sourceGP.getGridData(
new GetGridRequest(req.getParmId(), overlapInventory),
badGridTR);
retrieveTimer.stop();
// System.out.println("Retrieved " + overlapInventory.size()
// + " grids");
sourceData = getSr.getPayload();
ssr.addMessages(getSr);
if (!ssr.isOkay()) {
ssr.addMessage("GetGridData for source for commitGrid() failure: "
+ ssr.message());
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
// get list of official grids that overlap publish range and
// aren't contained in the publish range, these have to be
// included in the publish step. Then get the grids, shorten
// and insert into sourceData.
List<IGridSlice> officialData = new ArrayList<IGridSlice>();
List<TimeRange> officialTR = new ArrayList<TimeRange>();
for (int t = 0; t < destInventory.size(); t++) {
if (!publishTime.contains(destInventory.get(t))) {
officialTR.add(destInventory.get(t));
}
}
if (!officialTR.isEmpty()) {
retrieveTimer.start();
getSr = destGP.getGridData(new GetGridRequest(destParmId,
officialTR), badGridTR);
retrieveTimer.stop();
officialData = getSr.getPayload();
ssr.addMessages(getSr);
if (!ssr.isOkay()) {
ssr.addMessage("GetGridData for official for commidtGrid() failure: "
+ ssr.message());
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
// insert the grid into the "sourceGrid" list
for (int t = 0; t < officialTR.size(); t++) {
// before
try {
if (officialTR.get(t).getStart()
.before(publishTime.getStart())) {
IGridSlice tempSlice = officialData.get(t)
.clone();
tempSlice.setValidTime(new TimeRange(officialTR
.get(t).getStart(), publishTime
.getStart()));
sourceData.add(0, tempSlice);
.getStart()));
sourceData.add(0, tempSlice);
publishTime.setStart(officialTR.get(t)
.getStart());
overlapInventory.add(tempSlice.getValidTime());
}
overlapInventory.add(tempSlice.getValidTime());
}
// after
if (officialTR.get(t).getEnd()
.after(publishTime.getEnd())) {
// after
if (officialTR.get(t).getEnd()
.after(publishTime.getEnd())) {
IGridSlice tempSlice = officialData.get(t)
.clone();
tempSlice.setValidTime(new TimeRange(
publishTime.getEnd(), officialTR.get(t)
.getEnd()));
sourceData.add(tempSlice);
publishTime.setEnd(officialTR.get(t).getEnd());
overlapInventory.add(tempSlice.getValidTime());
sourceData.add(tempSlice);
publishTime.setEnd(officialTR.get(t).getEnd());
overlapInventory.add(tempSlice.getValidTime());
}
} catch (CloneNotSupportedException e) {
sr.addMessage("Error cloning GridSlice "
+ e.getMessage());
}
} catch (CloneNotSupportedException e) {
sr.addMessage("Error cloning GridSlice "
+ e.getMessage());
}
}
}
// save off the source grid history, to update the source
// database modify the source grid data for the dest ParmID and
// GridDataHistory
Map<TimeRange, List<GridDataHistory>> histories = new HashMap<TimeRange, List<GridDataHistory>>();
Date nowTime = new Date();
// GridDataHistory
Map<TimeRange, List<GridDataHistory>> histories = new HashMap<TimeRange, List<GridDataHistory>>();
Date nowTime = new Date();
for (IGridSlice slice : sourceData) {
GridDataHistory[] sliceHist = slice.getHistory();
for (GridDataHistory hist : sliceHist) {
hist.setPublishTime((Date) nowTime.clone());
}
slice.getGridInfo().resetParmID(destParmId);
for (IGridSlice slice : sourceData) {
GridDataHistory[] sliceHist = slice.getHistory();
for (GridDataHistory hist : sliceHist) {
hist.setPublishTime((Date) nowTime.clone());
}
slice.getGridInfo().resetParmID(destParmId);
histories.put(slice.getValidTime(),
Arrays.asList(sliceHist));
}
}
// update the history for publish time for grids that are
// unchanged
for (TimeRange tr : historyOnly.keySet()) {
List<GridDataHistory> histList = historyOnly.get(tr);
for (GridDataHistory hist : histList) {
hist.setPublishTime((Date) nowTime.clone());
for (TimeRange tr : historyOnly.keySet()) {
List<GridDataHistory> histList = historyOnly.get(tr);
for (GridDataHistory hist : histList) {
hist.setPublishTime((Date) nowTime.clone());
}
histories.put(tr, histList);
}
histories.put(tr, histList);
}
// update the publish times in the source database,
// update the notifications
historyUpdateTimer.start();
sr.addMessages(sourceGP.updatePublishTime(histories.values(),
(Date) nowTime.clone()));
historyUpdateTimer.start();
sr.addMessages(sourceGP.updatePublishTime(histories.values(),
(Date) nowTime.clone()));
// System.out.println("Updated " + histories.size() +
// " histories");
historyUpdateTimer.stop();
historyUpdateTimer.stop();
List<TimeRange> historyTimes = new ArrayList<TimeRange>(
histories.keySet());
@ -723,56 +726,56 @@ public class GridParmManager {
// update the histories of destination database for ones
// that are not going to be saved since there hasn't been a
// change
List<TimeRange> historyOnlyList = new ArrayList<TimeRange>();
historyOnlyList.addAll(historyOnly.keySet());
List<TimeRange> historyOnlyList = new ArrayList<TimeRange>();
historyOnlyList.addAll(historyOnly.keySet());
historyRetrieveTimer.start();
Map<TimeRange, List<GridDataHistory>> destHistory = destGP
.getGridHistory(historyOnlyList).getPayload();
historyRetrieveTimer.stop();
for (TimeRange tr : destHistory.keySet()) {
List<GridDataHistory> srcHistList = histories.get(tr);
List<GridDataHistory> destHistList = destHistory.get(tr);
for (int i = 0; i < srcHistList.size(); i++) {
destHistList.get(i).replaceValues(srcHistList.get(i));
historyRetrieveTimer.start();
Map<TimeRange, List<GridDataHistory>> destHistory = destGP
.getGridHistory(historyOnlyList).getPayload();
historyRetrieveTimer.stop();
for (TimeRange tr : destHistory.keySet()) {
List<GridDataHistory> srcHistList = histories.get(tr);
List<GridDataHistory> destHistList = destHistory.get(tr);
for (int i = 0; i < srcHistList.size(); i++) {
destHistList.get(i).replaceValues(srcHistList.get(i));
}
}
}
// only need to update the publish time on the destination
// histories of grids that are not being saved (due to no
// changes), because the saveGridSlices() call below will update
// the publish time of the ones with changes
historyUpdateTimer.start();
destGP.updatePublishTime(destHistory.values(),
(Date) nowTime.clone());
historyUpdateTimer.stop();
historyUpdateTimer.start();
destGP.updatePublishTime(destHistory.values(),
(Date) nowTime.clone());
historyUpdateTimer.stop();
// save data directly to the official database (bypassing
// the checks in Parm intentionally)
storeTimer.start();
ssr.addMessages(officialDBPtr.saveGridSlices(destParmId,
publishTime, sourceData, requestorId, historyOnlyList));
storeTimer.stop();
// save data directly to the official database (bypassing
// the checks in Parm intentionally)
storeTimer.start();
ssr.addMessages(officialDBPtr.saveGridSlices(destParmId,
publishTime, sourceData, requestorId, historyOnlyList));
storeTimer.stop();
// System.out.println("Published " + sourceData.size() +
// " slices");
if (!ssr.isOkay()) {
ssr.addMessage("SaveGridData for official for commitGrid() failure: "
+ ssr.message());
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
if (!ssr.isOkay()) {
ssr.addMessage("SaveGridData for official for commitGrid() failure: "
+ ssr.message());
srDetailed.addMessages(ssr);
failures.add(req);
continue;
}
// make the notification
// make the notification
GridUpdateNotification not = new GridUpdateNotification(
destParmId, publishTime, histories, requestorId, siteID);
changes.add(not);
sr.getPayload().add(not);
changes.add(not);
sr.getPayload().add(not);
} finally {
ClusterLockUtils.unlock(ct, false);
}
}
}
perfLog.logDuration("Publish Grids: Acquiring cluster lock",
@ -822,8 +825,8 @@ public class GridParmManager {
this.dbMap.keySet());
sr.setPayload(databases);
return sr;
}
return sr;
}
/**
* Get a database if available
@ -832,6 +835,10 @@ public class GridParmManager {
* @return GridDatabase or null if not available
*/
public GridDatabase getDatabase(DatabaseID dbId) {
return getDatabase(dbId, true);
}
private GridDatabase getDatabase(DatabaseID dbId, boolean notify) {
// look up the database in the map
GridDatabase db = this.dbMap.get(dbId);
@ -846,12 +853,14 @@ public class GridParmManager {
ServerResponse<GridDatabase> status = createDB(dbId);
if (status.isOkay()) {
db = status.getPayload();
createDbNotification(Arrays.asList(dbId), null);
}
}
}
if (db != null) {
this.addDB(db);
if (notify) {
createDbNotification(Arrays.asList(dbId), null);
}
}
}
@ -886,8 +895,8 @@ public class GridParmManager {
return sr;
}
return sr;
}
return sr;
}
/**
* Delete database
@ -944,9 +953,9 @@ public class GridParmManager {
if (db == null) {
sr.addMessage("Database " + dbId
+ " does not exist for getParmList()");
+ " does not exist for getParmList()");
return sr;
}
}
sr = db.getParmList();
return sr;
@ -988,7 +997,7 @@ public class GridParmManager {
// determine desired number of versions
desiredVersions = this.config.desiredDbVersions(dbId);
}
}
// process the id and determine whether it should be purged
count++;
@ -1012,9 +1021,9 @@ public class GridParmManager {
toRemove.removeAll(newInv);
for (DatabaseID dbId : toRemove) {
if (dbMap.remove(dbId) != null) {
statusHandler
.info("Synching GridParmManager with database inventory, removing "
+ dbId);
statusHandler
.info("Synching GridParmManager with database inventory, removing "
+ dbId);
}
// add any removals to the deletions list
@ -1073,14 +1082,14 @@ public class GridParmManager {
List<LockNotification> lockNotify = new ArrayList<LockNotification>();
GridParm gp = createParm(parmId);
if (gp.isValid()) {
ServerResponse<Integer> sr1 = gp.timePurge(purgeTime,
ServerResponse<Integer> sr1 = gp.timePurge(purgeTime,
gridNotify, lockNotify);
sr.addMessages(sr1);
purgedCount += sr1.getPayload();
sr.addMessages(sr1);
purgedCount += sr1.getPayload();
gridNotifications.addAll(gridNotify);
lockNotifications.addAll(lockNotify);
}
gridNotifications.addAll(gridNotify);
lockNotifications.addAll(lockNotify);
}
}
PurgeLogger.logInfo("Purge " + purgedCount + " items from " + dbId,
@ -1119,7 +1128,7 @@ public class GridParmManager {
if (dbId.getRemovedDate() != null) {
// mark database as not removed
try {
try {
GFEDao gfeDao = new GFEDao();
gfeDao.setDatabaseRemovedDate(dbId, null);
statusHandler.info("Database " + dbId + " restored");
@ -1127,7 +1136,7 @@ public class GridParmManager {
statusHandler.handle(Priority.PROBLEM,
"Unable to mark database restored: " + dbId, e);
}
}
}
// add to list of databases
addDB(db);
@ -1177,8 +1186,8 @@ public class GridParmManager {
if (manID.getFormat().equals(DataType.GRID)
&& !inventory.contains(manID)) {
inventory.add(manID);
}
}
}
// create the databases (the list should now only contain GRID dbs)
ServerResponse<GridDatabase> sr = new ServerResponse<GridDatabase>();
@ -1208,11 +1217,6 @@ public class GridParmManager {
ClusterTask ct = ClusterLockUtils.lookupLock(SMART_INIT_TASK_NAME,
SMART_INIT_TASK_DETAILS + siteID);
// TODO: reconsider this as changes to localConfig may change what
// smartInits should be run
// TODO: re-enable check
// if ((ct.getLastExecution() + SMART_INIT_TIMEOUT) < System
// .currentTimeMillis()) {
ct = ClusterLockUtils
.lock(SMART_INIT_TASK_NAME, SMART_INIT_TASK_DETAILS
+ siteID, SMART_INIT_TIMEOUT, false);
@ -1285,7 +1289,7 @@ public class GridParmManager {
if (db == null) {
// New database
db = D2DGridDatabase.getDatabase(config, d2dModelName, refTime);
if (db == null) {
if (db == null) {
continue;
}
@ -1308,16 +1312,16 @@ public class GridParmManager {
queue.queue(siteID, config, dbId, validTime, false,
SmartInitRecord.LIVE_SMART_INIT_PRIORITY);
}
}
}
}
}
// send notifications;
try {
try {
SendNotifications.send(guns);
} catch (Exception e) {
} catch (Exception e) {
statusHandler.error("Unable to send grib ingest notifications", e);
}
}
}
}
/**
* @param records
@ -1339,9 +1343,9 @@ public class GridParmManager {
Date validTime = gun.getReplacementTimeRange().getStart();
queue.queue(siteID, config, dbId, validTime, false,
SmartInitRecord.LIVE_SMART_INIT_PRIORITY);
}
}
}
}
try {
SendNotifications.send(guns);
@ -1349,7 +1353,7 @@ public class GridParmManager {
statusHandler.error(
"Unable to send satellite ingest notifications", e);
}
}
}
private Date purgeTime(DatabaseID id) {
int numHours = this.config.gridPurgeAgeInHours(id);
@ -1427,8 +1431,8 @@ public class GridParmManager {
for (ParmID pid : parmList) {
out.add(new CommitGridRequest(pid, req.getTimeRange(),
req.isClientSendStatus()));
}
} else {
}
} else {
sr.addMessage("Could not find database for "
+ req.getDbId() + " in convertToParmReq()");
}
@ -1495,25 +1499,7 @@ public class GridParmManager {
ServerResponse<GridDatabase> sr = new ServerResponse<GridDatabase>();
for (DatabaseID dbId : invChanged.getAdditions()) {
// TODO: This is pretty much just a duplicate of what's in
// getDatabase.
// Verify this works and then remove this commented code
// if (dbId.getDbType().equals("D2D")) {
// String d2dModelName = config.d2dModelNameMapping(dbId
// .getModelName());
// D2DGridDatabase db = D2DGridDatabase.getDatabase(config,
// d2dModelName, dbId.getModelDate());
// if (db != null) {
// this.addDB(db);
// }
// statusHandler
// .info("handleGfeNotification new D2D database: "
// + dbId);
// } else {
// sr = this.createDB(dbId);
// }
this.getDatabase(dbId);
this.getDatabase(dbId, false);
}
if (!sr.isOkay()) {
statusHandler.error("Error updating GridParmManager: "
@ -1544,7 +1530,7 @@ public class GridParmManager {
DatabaseID dbId = db.getDbId();
statusHandler.info("addDB called, adding " + dbId);
this.dbMap.put(dbId, db);
}
}
/**
* Process D2D grid data purge notification
@ -1568,44 +1554,22 @@ public class GridParmManager {
newInventory.addAll(dbIds);
} catch (DataAccessLayerException e) {
statusHandler.error(e.getLocalizedMessage(), e);
}
}
}
}
DatabaseID satDbid = D2DSatDatabase.getDbId(siteID);
// TODO why are we processing adds in a purge method. We should get adds
// via other means
// Verify and remove the commented code
// List<DatabaseID> added = new ArrayList<DatabaseID>(newInventory);
// added.removeAll(currentInventory);
// Iterator<DatabaseID> iter = added.iterator();
// while (iter.hasNext()) {
// DatabaseID dbid = iter.next();
// // remove satellite database and non-D2D databases from adds
// if (!dbid.getDbType().equals("D2D") || dbid.equals(satDbid)) {
// iter.remove();
// } else {
// // add the new database
// try {
// D2DGridDatabase db = new D2DGridDatabase(config, dbid);
// addDB(db);
// statusHandler.info("d2dGridDataPurged new D2D database: "
// + dbid);
// } catch (Exception e) {
// statusHandler.handle(Priority.PROBLEM,
// e.getLocalizedMessage(), e);
// }
// }
// }
List<DatabaseID> deleted = new ArrayList<DatabaseID>(currentInventory);
deleted.removeAll(newInventory);
// don't delete NetCDF and satellite databases.
deleted.removeAll(NetCDFDatabaseManager.getDatabaseIds(siteID));
deleted.remove(D2DSatDatabase.getDbId(siteID));
Iterator<DatabaseID> iter = deleted.iterator();
while (iter.hasNext()) {
DatabaseID dbid = iter.next();
// remove satellite database and non-D2D databases from deletes
if (!dbid.getDbType().equals("D2D") || dbid.equals(satDbid)) {
// don't delete non-D2D databases
if (!dbid.getDbType().equals("D2D")) {
iter.remove();
} else {
// remove the database
@ -1613,19 +1577,16 @@ public class GridParmManager {
statusHandler.info("d2dGridDataPurged removing database: "
+ dbid);
}
}
}
}
// if ((added.size() > 0) || (deleted.size() > 0)) {
// DBInvChangeNotification changed = new DBInvChangeNotification(
// added, deleted, siteID);
if (deleted.size() > 0) {
DBInvChangeNotification changed = new DBInvChangeNotification(null,
deleted, siteID);
SendNotifications.send(changed);
}
}
}
/**
* Process D2D satellite data purge notification

View file

@ -114,6 +114,8 @@ import com.raytheon.uf.edex.database.DataAccessLayerException;
* Added function to create a D2DGridDatabase object only if there is
* data in postgres for the desired model/reftime
* 04/17/2014 #2934 dgilling Change getGridParmInfo to use D2DParm's GridParmInfo.
* 06/24/2014 #3317 randerso Don't allow database to be created if it exceeds D2DDBVERSIONS and
* should be purged.
*
* </pre>
*
@ -176,8 +178,9 @@ public class D2DGridDatabase extends VGridDatabase {
String d2dModelName, Date refTime) {
try {
GFED2DDao dao = new GFED2DDao();
// TODO create query for single refTime
List<Date> result = dao.getModelRunTimes(d2dModelName, -1);
int dbVersions = config.desiredDbVersions(getDbId(d2dModelName,
refTime, config));
List<Date> result = dao.getModelRunTimes(d2dModelName, dbVersions);
if (result.contains(refTime)) {
D2DGridDatabase db = new D2DGridDatabase(config, d2dModelName,

View file

@ -41,6 +41,7 @@ import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
* ------------ ---------- ----------- --------------------------
* May 7, 2008 njensen Initial creation
* Jun 13, 2013 #2044 randerso Refactored to use IFPServer
* Jul 28, 2014 RM 15655 ryu Negate raising exception for empty db in constructor
*
* </pre>
*
@ -88,7 +89,6 @@ public class IFPDB {
}
} else {
this.keys = Collections.emptyList();
throw new GfeException(sr.message());
}
}

View file

@ -30,6 +30,7 @@ except:
import numpy
import JUtil
from java.lang import System
from java.util import ArrayList
from java.util import LinkedHashMap
from com.raytheon.uf.common.dataplugin.gfe.grid import Grid2DFloat
@ -88,6 +89,7 @@ from com.raytheon.uf.edex.database.cluster import ClusterTask
# 02/04/14 17042 ryu Check in changes for randerso.
# 04/03/2014 2737 randerso Allow iscMosaic to blankOtherPeriods even when no grids received
# 04/11/2014 17242 David Gillingham (code checked in by zhao)
# 07/22/2014 17484 randerso Update cluster lock time to prevent time out
#
BATCH_DELAY = 0.0
@ -727,6 +729,9 @@ class IscMosaic:
# process incoming grids
for i in xrange(len(inTimes)):
# update cluster lock time to avoid time out
ClusterLockUtils.updateLockTime("ISC Write Lock", parmName ,System.currentTimeMillis())
# Put in a delay so we don't hammer the server so hard.
if self.__gridDelay > 0.0:
time.sleep(self.__gridDelay)

View file

@ -2929,7 +2929,6 @@
<name>HPCGuide</name>
<center>7</center>
<subcenter>5</subcenter>
<grid>197</grid>
<process>
<id>183</id>
</process>

View file

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
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.
-->
<subGridDef>
<modelNames>HPCGuide</modelNames>
<referenceGrid>197</referenceGrid>
<nx>1000</nx>
<ny>689</ny>
<!--
<centerLatitude>46.0</centerLatitude>
<centerLongitude>-95.5</centerLongitude>
-->
</subGridDef>

View file

@ -25,6 +25,7 @@ import java.util.regex.Pattern;
import com.raytheon.edex.plugin.shef.util.SHEFDate;
import com.raytheon.edex.plugin.shef.util.ShefParm;
import com.raytheon.uf.common.dataplugin.shef.tables.IngestfilterId;
import com.raytheon.uf.common.dataplugin.shef.util.ParameterCode;
import com.raytheon.uf.common.dataplugin.shef.util.ParameterCode.Duration;
import com.raytheon.uf.common.dataplugin.shef.util.ParameterCode.Extremum;
@ -47,6 +48,7 @@ import com.raytheon.uf.common.serialization.ISerializableObject;
* 03/19/08 387 M. Duff Initial creation.
* 10/16/2008 1548 jelkins Integrated ParameterCode Types
* 04/29/2014 3088 mpduff cleanup.
* 06/26/2014 3321 mpduff Added ingestfilter primary key getter.
*
* </pre>
*/
@ -805,14 +807,30 @@ public class ShefData implements ISerializableObject {
*
* @return
*/
public String getPeTsE() {
public String getPeDTsE() {
StringBuilder sb = new StringBuilder();
sb.append(this.getPhysicalElement().getCode());
sb.append(this.getTypeSource().getCode());
sb.append(this.getExtremum().getCode());
sb.append(this.getDurationCodeVariable());
return sb.toString();
}
/**
* Get the ingest filter table primary key value for this data object.
*
* @return The primary key object
*/
public IngestfilterId getIngestFilterKey() {
IngestfilterId id = new IngestfilterId();
id.setLid(this.getLocationId());
id.setDur(this.getDurationValue());
id.setExtremum(this.getExtremum().getCode());
id.setPe(this.getPhysicalElement().getCode());
id.setTs(this.getTypeSource().getCode());
return id;
}
/**
*
* @param element
@ -885,5 +903,4 @@ public class ShefData implements ISerializableObject {
}
}
}

View file

@ -96,7 +96,7 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 04/21/2008 387 M. Duff Initial Version.
* 04/21/2008 387 M. Duff Initial Version.
* 06/02/2008 1166 M. Duff Added checks for null data objects.
* 22Jul2008 1277 MW Fegan Use CoreDao in checkIngest().
* 10/16/2008 1548 jelkins Integrated ParameterCode Types and misc fixes
@ -123,6 +123,9 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools;
* 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.
* 06/26/2014 3321 mpduff Fix ingestSwitchMap checks
* 07/10/2014 3370 mpduff Fix update/insert issue for riverstatus
* 07/14/2014 mpduff Fix data range checks
* </pre>
*
* @author mduff
@ -228,7 +231,7 @@ public class PostShef {
private Map<String, ShefAdjustFactor> adjustmentMap = new HashMap<String, ShefAdjustFactor>();
/** Map of location identifier to IngestSwitch */
private Map<String, IngestSwitch> ingestSwitchMap = new HashMap<String, IngestSwitch>();
private Map<IngestfilterId, IngestSwitch> ingestSwitchMap = new HashMap<IngestfilterId, IngestSwitch>();
// AppsDefaults tokens
private String undefStation;
@ -274,9 +277,6 @@ public class PostShef {
/** Basis time TimeStamp */
private java.sql.Timestamp basisTimeAnsi = new Timestamp(basisBeginTime);
/** River status update flag. update if true */
private boolean riverStatusUpdateFlag = true;
/** river status update query value */
private boolean riverStatusUpdateValueFlag;
@ -295,39 +295,12 @@ public class PostShef {
/** Forecast query results */
private Object[] queryForecastResults;
/** Location range data found flag */
private boolean locRangeFound = false;
/** Default range data found flag */
private boolean defRangeFound = false;
/** Cache of data limits and loc data limits */
private Map<String, ShefRangeData> dataRangeMap = new HashMap<String, ShefRangeData>();
/** 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
@ -529,7 +502,7 @@ public class PostShef {
if (dataLog) {
log.info(LOG_SEP);
log.info("Posting process started for LID [" + locId
+ "] PEDTSEP [" + data.getPeTsE() + "] value ["
+ "] PEDTSEP [" + data.getPeDTsE() + "] value ["
+ dataValue + "]");
}
@ -650,7 +623,7 @@ public class PostShef {
if (Location.LOC_LOCATION.equals(postLocData)
|| (Location.LOC_GEOAREA.equals(postLocData))) {
if (!DataType.CONTINGENCY.equals(dataType)) {
ingestSwitch = checkIngest(locId, data, ingestSwitch);
ingestSwitch = checkIngest(locId, data);
}
if (ShefConstants.IngestSwitch.POST_PE_OFF
.equals(ingestSwitch)) {
@ -1107,23 +1080,12 @@ public class PostShef {
// Reset .E cache vars
tsList.clear();
useLatest = MISSING;
riverStatusUpdateFlag = true;
qualityCheckFlag = true;
useTs = null;
basisTimeValues = null;
previousQueryForecast = null;
locRangeFound = false;
defRangeFound = false;
dataRangeMap.clear();
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;
}
/**
@ -1448,15 +1410,7 @@ public class PostShef {
if ((shefList != null) && (shefList.size() > 0)) {
ShefData maxShefDataValue = findMaxFcst(shefList);
if (shefRecord.getShefType() == ShefType.E) {
if (riverStatusUpdateFlag) {
riverStatusUpdateFlag = false;
riverStatusUpdateValueFlag = updateRiverStatus(lid, pe, ts);
}
} else {
riverStatusUpdateValueFlag = updateRiverStatus(lid, pe, ts);
}
riverStatusUpdateValueFlag = updateRiverStatus(lid, pe, ts);
postTables.postRiverStatus(shefRecord, maxShefDataValue,
riverStatusUpdateValueFlag);
} else {
@ -2125,8 +2079,7 @@ public class PostShef {
* ingest switch setting
* @return
*/
private IngestSwitch checkIngest(String locId, ShefData data,
ShefConstants.IngestSwitch ingestSwitch) {
private IngestSwitch checkIngest(String locId, ShefData data) {
StringBuilder errorMsg = new StringBuilder();
boolean matchFound = false;
int hNum = 0;
@ -2152,13 +2105,16 @@ public class PostShef {
String telem = null;
String sql = null;
Object[] oa = null;
String key = locId + data.getPeTsE();
IngestfilterId key = data.getIngestFilterKey();// .getPeDTsE();
// Default to off
ShefConstants.IngestSwitch ingestSwitch = IngestSwitch.POST_PE_OFF;
try {
if (!ingestSwitchMap.containsKey(key)) {
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 = '"
+ locId + "'";
errorMsg.setLength(0);
errorMsg.append("Error requesting IngestFilter data: " + sql);
oa = dao.executeSQLQuery(sql);
if (oa.length > 0) {
@ -2443,7 +2399,7 @@ public class PostShef {
if (!matchFound) {
log.warn(locId + " - " + data.getPhysicalElement() + "("
+ data.getDuration() + ")" + data.getTypeSource()
+ data.getExtremum() + " ingest " + "filter not defined");
+ data.getExtremum() + " ingest filter not defined");
stats.incrementWarningMessages();
ingestSwitch = ShefConstants.IngestSwitch.POST_PE_OFF;
}
@ -2646,24 +2602,12 @@ public class PostShef {
return ShefConstants.QC_MANUAL_FAILED;
}
boolean executeQuery = true;
if (!qualityCheckFlag) {
// If qualityCheckFlag is false the the query has already been
// executed
executeQuery = false;
}
if (shefRecord.getShefType() == ShefType.E) {
// if qualityCheckFlag is true then don't need to query
if (qualityCheckFlag) {
qualityCheckFlag = false;
}
}
StringBuilder locLimitSql = new StringBuilder();
StringBuilder defLimitSql = new StringBuilder();
String key = lid + data.getPhysicalElement().getCode()
+ data.getDurationValue();
try {
if (executeQuery) {
if (!dataRangeMap.containsKey(key)) {
String sqlStart = "select monthdaystart, monthdayend, gross_range_min, gross_range_max, reason_range_min, "
+ "reason_range_max, roc_max, alert_upper_limit, alert_roc_limit, alarm_upper_limit, "
+ "alarm_roc_limit, alert_lower_limit, alarm_lower_limit, alert_diff_limit, "
@ -2679,6 +2623,7 @@ public class PostShef {
Object[] oa = dao.executeSQLQuery(locLimitSql.toString());
if (oa.length == 0) {
dataRangeMap.put(key, null);
// default range
defLimitSql = new StringBuilder(sqlStart);
defLimitSql.append("datalimits where pe = '")
@ -2687,7 +2632,13 @@ public class PostShef {
.append(data.getDurationValue());
oa = dao.executeSQLQuery(defLimitSql.toString());
key = data.getPhysicalElement().getCode()
+ data.getDurationValue();
if (oa.length == 0) {
dataRangeMap.put(key, null);
}
}
for (int i = 0; i < oa.length; i++) {
Object[] oa2 = (Object[]) oa[i];
@ -2704,49 +2655,65 @@ public class PostShef {
* if a range is found, then check the value and set the
* flag
*/
grossRangeMin = ShefUtil.getDouble(oa2[2], missing);
grossRangeMax = ShefUtil.getDouble(oa2[3], missing);
reasonRangeMin = ShefUtil.getDouble(oa2[4], missing);
reasonRangeMax = ShefUtil.getDouble(oa2[5], missing);
alertUpperLimit = ShefUtil.getDouble(oa2[7], missing);
alertLowerLimit = ShefUtil.getDouble(oa2[11], missing);
alarmLowerLimit = ShefUtil.getDouble(oa2[12], missing);
alarmUpperLimit = ShefUtil.getDouble(oa2[9], missing);
defRangeFound = true;
ShefRangeData rangeData = new ShefRangeData();
rangeData.setGrossRangeMin(ShefUtil.getDouble(oa2[2],
missing));
rangeData.setGrossRangeMax(ShefUtil.getDouble(oa2[3],
missing));
rangeData.setReasonRangeMin(ShefUtil.getDouble(oa2[4],
missing));
rangeData.setReasonRangeMax(ShefUtil.getDouble(oa2[5],
missing));
rangeData.setAlarmLowerLimit(ShefUtil.getDouble(
oa2[12], missing));
rangeData.setAlarmUpperLimit(ShefUtil.getDouble(oa2[9],
missing));
rangeData.setAlertLowerLimit(ShefUtil.getDouble(
oa2[11], missing));
rangeData.setAlertUpperLimit(ShefUtil.getDouble(oa2[7],
missing));
this.dataRangeMap.put(key, rangeData);
break;
}
}
}
if (locRangeFound || defRangeFound) {
ShefRangeData rangeData = dataRangeMap.get(key);
if (rangeData != null) {
/*
* if a range is found, then check the value and set the flag
*/
if (((grossRangeMin != missing) && (dValue < grossRangeMin))
|| ((grossRangeMax != missing) && (dValue > grossRangeMax))) {
if (((rangeData.getGrossRangeMin() != missing) && (dValue < rangeData
.getGrossRangeMin()))
|| ((rangeData.getGrossRangeMax() != missing) && (dValue > rangeData
.getGrossRangeMax()))) {
qualityCode = ShefQC.setQcCode(
(int) ShefConstants.QC_GROSSRANGE_FAILED,
qualityCode);
if (dataLog) {
log.info(lid + " failed gross range check: " + dValue
+ " out of range " + grossRangeMin + " - "
+ grossRangeMax);
+ " out of range "
+ rangeData.getGrossRangeMin() + " - "
+ rangeData.getGrossRangeMax());
}
/*
* don't do anything if it fails the gross range check
*/
} else {
if (((reasonRangeMin != missing) && (dValue < reasonRangeMin))
|| ((reasonRangeMax != missing) && (dValue > reasonRangeMax))) {
if (((rangeData.getReasonRangeMin() != missing) && (dValue < rangeData
.getReasonRangeMin()))
|| ((rangeData.getReasonRangeMax() != missing) && (dValue > rangeData
.getReasonRangeMax()))) {
qualityCode = ShefQC.setQcCode(
(int) ShefConstants.QC_REASONRANGE_FAILED,
qualityCode);
if (dataLog) {
log.info(lid + " failed reasonable range check: "
+ dValue + " out of range "
+ reasonRangeMin + " - " + reasonRangeMax);
+ rangeData.getReasonRangeMin() + " - "
+ rangeData.getReasonRangeMax());
}
}
@ -2756,17 +2723,17 @@ public class PostShef {
* table.
*/
if (shefAlertAlarm) {
if ((alarmUpperLimit != missing)
&& (dValue >= alarmUpperLimit)) {
if ((rangeData.getAlarmUpperLimit() != missing)
&& (dValue >= rangeData.getAlarmUpperLimit())) {
alertAlarm = ShefConstants.ALARM_UPPER_DETECTED;
} else if ((alertUpperLimit != missing)
&& (dValue >= alertUpperLimit)) {
} else if ((rangeData.getAlertUpperLimit() != missing)
&& (dValue >= rangeData.getAlertUpperLimit())) {
alertAlarm = ShefConstants.ALERT_UPPER_DETECTED;
} else if ((alarmLowerLimit != missing)
&& (dValue <= alarmLowerLimit)) {
} else if ((rangeData.getAlarmLowerLimit() != missing)
&& (dValue <= rangeData.getAlarmLowerLimit())) {
alertAlarm = ShefConstants.ALARM_LOWER_DETECTED;
} else if ((alertLowerLimit != missing)
&& (dValue <= alertLowerLimit)) {
} else if ((rangeData.getAlertLowerLimit() != missing)
&& (dValue <= rangeData.getAlertLowerLimit())) {
alertAlarm = ShefConstants.ALERT_LOWER_DETECTED;
}

View file

@ -0,0 +1,179 @@
/**
* 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.shef.database;
import com.raytheon.uf.common.dataplugin.shef.util.ShefConstants;
/**
* Data object for holding SHEF range limits
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 14, 2014 mpduff Initial creation
*
* </pre>
*
* @author mpduff
* @version 1.0
*/
public class ShefRangeData {
private double grossRangeMin = ShefConstants.SHEF_MISSING_INT;
private double grossRangeMax = ShefConstants.SHEF_MISSING_INT;
private double reasonRangeMin = ShefConstants.SHEF_MISSING_INT;
private double reasonRangeMax = ShefConstants.SHEF_MISSING_INT;
private double alertUpperLimit = ShefConstants.SHEF_MISSING_INT;
private double alarmUpperLimit = ShefConstants.SHEF_MISSING_INT;
private double alertLowerLimit = ShefConstants.SHEF_MISSING_INT;
private double alarmLowerLimit = ShefConstants.SHEF_MISSING_INT;
/**
* @return the grossRangeMin
*/
public double getGrossRangeMin() {
return grossRangeMin;
}
/**
* @param grossRangeMin
* the grossRangeMin to set
*/
public void setGrossRangeMin(double grossRangeMin) {
this.grossRangeMin = grossRangeMin;
}
/**
* @return the grossRangeMax
*/
public double getGrossRangeMax() {
return grossRangeMax;
}
/**
* @param grossRangeMax
* the grossRangeMax to set
*/
public void setGrossRangeMax(double grossRangeMax) {
this.grossRangeMax = grossRangeMax;
}
/**
* @return the reasonRangeMin
*/
public double getReasonRangeMin() {
return reasonRangeMin;
}
/**
* @param reasonRangeMin
* the reasonRangeMin to set
*/
public void setReasonRangeMin(double reasonRangeMin) {
this.reasonRangeMin = reasonRangeMin;
}
/**
* @return the reasonRangeMax
*/
public double getReasonRangeMax() {
return reasonRangeMax;
}
/**
* @param reasonRangeMax
* the reasonRangeMax to set
*/
public void setReasonRangeMax(double reasonRangeMax) {
this.reasonRangeMax = reasonRangeMax;
}
/**
* @return the alertUpperLimit
*/
public double getAlertUpperLimit() {
return alertUpperLimit;
}
/**
* @param alertUpperLimit
* the alertUpperLimit to set
*/
public void setAlertUpperLimit(double alertUpperLimit) {
this.alertUpperLimit = alertUpperLimit;
}
/**
* @return the alarmUpperLimit
*/
public double getAlarmUpperLimit() {
return alarmUpperLimit;
}
/**
* @param alarmUpperLimit
* the alarmUpperLimit to set
*/
public void setAlarmUpperLimit(double alarmUpperLimit) {
this.alarmUpperLimit = alarmUpperLimit;
}
/**
* @return the alertLowerLimit
*/
public double getAlertLowerLimit() {
return alertLowerLimit;
}
/**
* @param alertLowerLimit
* the alertLowerLimit to set
*/
public void setAlertLowerLimit(double alertLowerLimit) {
this.alertLowerLimit = alertLowerLimit;
}
/**
* @return the alarmLowerLimit
*/
public double getAlarmLowerLimit() {
return alarmLowerLimit;
}
/**
* @param alarmLowerLimit
* the alarmLowerLimit to set
*/
public void setAlarmLowerLimit(double alarmLowerLimit) {
this.alarmLowerLimit = alarmLowerLimit;
}
}

View file

@ -23,8 +23,8 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.raytheon.edex.utility.ProtectedFiles;
import com.raytheon.uf.common.auth.exception.AuthorizationException;
@ -54,6 +54,7 @@ import com.raytheon.uf.edex.core.EDEXUtil;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 11, 2010 mschenke Initial creation
* Jul 14, 2014 3372 njensen fileMap is ConcurrentHashMap for thread safety
*
* </pre>
*
@ -75,7 +76,7 @@ public class LocalizationStreamHandler
}
}
private Map<StreamPair, File> fileMap = new HashMap<StreamPair, File>();
private Map<StreamPair, File> fileMap = new ConcurrentHashMap<StreamPair, File>();
/*
* (non-Javadoc)

View file

@ -47,7 +47,7 @@
<parameter>zAGL</parameter>
</paramLevelMatches>
<contourStyle>
<displayUnits>dam</displayUnits>
<displayUnits>ft</displayUnits>
<contourLabeling labelSpacing="4" labelFormat="#">
<increment>50</increment>
</contourLabeling>

View file

@ -84,7 +84,7 @@
<parameter>Topo</parameter>
</paramLevelMatches>
<imageStyle>
<displayUnits>km</displayUnits>
<displayUnits>ft</displayUnits>
<defaultColormap>Grid/gridded data</defaultColormap>
</imageStyle>
</styleRule>

View file

@ -43,6 +43,7 @@ import com.raytheon.uf.common.serialization.SingleTypeJAXBManager;
* --/--/---- Initial creation
* 10/22/2013 2361 njensen Use JAXBManager for XML
* Apr 28, 2014 3033 jsanchez Refactored file retrieval.
* Jul 02, 2014 DR 17450 D. Friedman Support using list of templates from backup site.
* </pre>
*
* @author jsanchez
@ -91,6 +92,18 @@ public class DialogConfiguration {
return (DialogConfiguration) jaxb.unmarshalFromXml(xml);
}
public static DialogConfiguration loadDialogConfigNoUser(String site)
throws FileNotFoundException, IOException, JAXBException {
String xml = WarnFileUtil.convertFileContentsToStringNoUser(
CONFIG_FILE, site);
return (DialogConfiguration) jaxb.unmarshalFromXml(xml);
}
public static boolean isSiteDialogConfigExtant(String backupSite) {
return WarnFileUtil.isLocalizationFileExtantAtSiteLevel(CONFIG_FILE,
backupSite);
}
public String getWarngenOfficeShort() {
return warngenOfficeShort;
}

View file

@ -25,12 +25,18 @@ import com.raytheon.uf.common.localization.PathManagerFactory;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 28, 2014 3033 jsanchez Searches the backup site directory before the localized site directory.
* Jul 02, 2014 DR 17450 D. Friedman Support using list of templates from backup site.
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class WarnFileUtil {
public static LocalizationFile findFileInLocalizationIncludingBackupSite(String filename,
String issuingSiteID, String backupSiteID) throws FileNotFoundException {
return findFileInLocalizationIncludingBackupSite(filename, issuingSiteID, backupSiteID, true);
}
/**
* Returns the appropriate file in localization. If a backupSiteID is not
* null and a corresponding file does exist in the backup site directory,
@ -49,7 +55,7 @@ public class WarnFileUtil {
* @throws FileNotFoundException
*/
public static LocalizationFile findFileInLocalizationIncludingBackupSite(String filename,
String issuingSiteID, String backupSiteID)
String issuingSiteID, String backupSiteID, boolean allowUser)
throws FileNotFoundException {
IPathManager pm = PathManagerFactory.getPathManager();
@ -71,6 +77,9 @@ public class WarnFileUtil {
LocalizationContext[] searchContext = pm
.getLocalSearchHierarchy(LocalizationType.COMMON_STATIC);
for (LocalizationContext ctx : searchContext) {
if (!allowUser && ctx.getLocalizationLevel() == LocalizationLevel.USER)
continue;
if ((ctx.getLocalizationLevel() == LocalizationLevel.SITE || ctx
.getLocalizationLevel() == LocalizationLevel.CONFIGURED)
&& issuingSiteID != null) {
@ -90,6 +99,18 @@ public class WarnFileUtil {
return fileToUse;
}
public static boolean isLocalizationFileExtantAtSiteLevel(String filename, String siteID) {
IPathManager pm = PathManagerFactory.getPathManager();
String fileToRetrieve = WarningConstants.WARNGEN_DIR
+ IPathManager.SEPARATOR + filename;
LocalizationContext backupSiteCtx = pm.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.SITE);
backupSiteCtx.setContextName(siteID);
LocalizationFile backupFile = pm.getLocalizationFile(backupSiteCtx,
fileToRetrieve);
return backupFile != null && backupFile.exists();
}
/**
* Locates the appropriate file in the localization hierarchy including the
* backupSite directory (if provided) and converts the content of the file
@ -105,10 +126,20 @@ public class WarnFileUtil {
public static String convertFileContentsToString(String filename,
String localizedSite, String backupSite)
throws FileNotFoundException, IOException {
StringBuffer sb = new StringBuffer();
BufferedReader input = null;
File file = findFileInLocalizationIncludingBackupSite(filename, localizedSite, backupSite)
.getFile();
return convertFileContentsToString(file);
}
public static String convertFileContentsToStringNoUser(String filename,
String site) throws FileNotFoundException {
File file = findFileInLocalizationIncludingBackupSite(filename, site, null, false).getFile();
return convertFileContentsToString(file);
}
private static String convertFileContentsToString(File file) {
StringBuffer sb = new StringBuffer();
BufferedReader input = null;
try {
input = new BufferedReader(new FileReader(file));

View file

@ -189,33 +189,35 @@ ${drainage.name}##
########END MACRO
#macro(inserttorwatches $watches $list $secondtimezone $dateUtil $timeFormat)
#set($torWatches = ${watches.getTorWatches()})
#set($torWatchAlso = "")
#set($torWatchFirst = 1)
#foreach(${watch} in ${torWatches})
#if($torWatchFirst)
#set($torWatchFirst = 0)
#else
##
#set($tornadoWatches = [])
#foreach(${watch} in ${watches})
#if(${watch.getPhenSig()} == 'TO.A')
#set($success = $tornadoWatches.add($watch))
#set($endTime = ${watch.endTime})
#if(!$latestEndTime || ${endTime.after($latestEndTime)})
#set($latestEndTime = ${endTime})
#end
A TORNADO WATCH ${torWatchAlso}REMAINS IN EFFECT UNTIL ${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${localtimezone})}##
${dateUtil.period(${watches.getLatestTorTime()},${timeFormat.plain}, 15, ${localtimezone})}##
#end
#end
#if(!${list.isEmpty($tornadoWatches)})
A TORNADO WATCH REMAINS IN EFFECT UNTIL ${dateUtil.format(${latestEndTime}, ${timeFormat.plain}, 15, ${localtimezone})}##
${dateUtil.period(${latestEndTime},${timeFormat.plain}, 15, ${localtimezone})}##
#if(${secondtimezone})
/${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${secondtimezone})}/##
#end
FOR ##
#set($numPortions = ${list.size(${watch.getPortions()})})
#set($numPortions = ${list.size(${tornadoWatches})})
#set($count = 0)
#foreach(${portion} in ${watch.getPortions()})
#foreach(${watch} in ${tornadoWatches})
#set($count = $count + 1)
#areaFormat(${portion.partOfParentRegion} true false true)${portion.parentRegion}##
#areaFormat(${watch.partOfState} true false true)${watch.state}##
#if($count == $numPortions - 1)
AND ##
#elseif($count < $numPortions)
...##
#end
#end
#set($torWatchAlso = "ALSO ")
. ##
#end
@ -223,33 +225,35 @@ ${dateUtil.period(${watches.getLatestTorTime()},${timeFormat.plain}, 15, ${local
########END MACRO
#macro(insertsvrwatches $watches $list $secondtimezone $dateUtil $timeFormat)
#set($svrWatches = ${watches.getSvrWatches()})
#set($svrWatchAlso = "")
#set($svrWatchFirst = 1)
#foreach(${watch} in ${svrWatches})
#if($svrWatchFirst)
#set($svrWatchFirst = 0)
#else
##
#set($severeWatches = [])
#foreach(${watch} in ${watches})
#if(${watch.getPhenSig()} == 'SV.A')
#set($success = $severeWatches.add($watch))
#set($endTime = ${watch.endTime})
#if(!$latestEndTime || ${endTime.after($latestEndTime)})
#set($latestEndTime = ${endTime})
#end
A SEVERE THUNDERSTORM WATCH ${svrWatchAlso}REMAINS IN EFFECT UNTIL ${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${localtimezone})}##
${dateUtil.period(${watches.getLatestSvrTime()},${timeFormat.plain}, 15, ${localtimezone})}##
#end
#end
#if(!${list.isEmpty($severeWatches)})
A SEVERE THUNDERSTORM WATCH REMAINS IN EFFECT UNTIL ${dateUtil.format(${latestEndTime}, ${timeFormat.plain}, 15, ${localtimezone})}##
${dateUtil.period(${latestEndTime},${timeFormat.plain}, 15, ${localtimezone})}##
#if(${secondtimezone})
/${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${secondtimezone})}/##
#end
FOR ##
#set($numPortions = ${list.size(${watch.getPortions()})})
#set($numPortions = ${list.size(${severeWatches})})
#set($count = 0)
#foreach(${portion} in ${watch.getPortions()})
#foreach(${watch} in ${severeWatches})
#set($count = $count + 1)
#areaFormat(${portion.partOfParentRegion} true false true)${portion.parentRegion}##
#areaFormat(${watch.partOfState} true false true)${watch.state}##
#if($count == $numPortions - 1)
AND ##
#elseif($count < $numPortions)
...##
#end
#end
#set($svrWatchAlso = "ALSO ")
. ##
#end
@ -368,18 +372,6 @@ SOUTH##
#if(${list.contains($directionSet, "WEST")})
#set($output = "${output}WEST")
#end
#if(${list.contains($directionSet, "NE")})
#set($output = "${output}NORTHEAST")
#end
#if(${list.contains($directionSet, "NW")})
#set($output = "${output}NORTHWEST")
#end
#if(${list.contains($directionSet, "SE")})
#set($output = "${output}SOUTHEAST")
#end
#if(${list.contains($directionSet, "SW")})
#set($output = "${output}SOUTHWEST")
#end
#if(${useCentral} && ${list.contains($directionSet, "CENTRAL")})
#if(${list.contains($directionSet, "NORTH")} || ${list.contains($directionSet, "SOUTH")} || ${list.contains($directionSet, "EAST")} || ${list.contains($directionSet, "WEST")})
#set($output = "${output} ")

View file

@ -119,11 +119,11 @@ FOR THE FOLLOWING THREATS...
## If sites do not want watches in their AWW product comment out the
## section below
#######################################################################
#if(${list.contains(${includedWatches}, "torWatches")} && ${list.contains(${bullets}, "includeTorWatches")})
#if(${list.contains(${includedWatches}, "TO.A")} && ${list.contains(${bullets}, "includeTorWatches")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")} && ${list.contains(${bullets}, "includeSvrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")} && ${list.contains(${bullets}, "includeSvrWatches")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -48,11 +48,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -59,11 +59,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<enableDamBreakThreat>true</enableDamBreakThreat>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>.
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
-->

View file

@ -191,10 +191,10 @@ THE SAFEST PLACE TO BE DURING A MAJOR LANDFALLING HURRICANE IS IN A REINFORCED I
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -52,11 +52,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -69,10 +69,10 @@ THIS IS A TEST MESSAGE. ##
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -238,10 +238,10 @@ THE SAFEST PLACE TO BE DURING A MAJOR LANDFALLING HURRICANE IS IN A REINFORCED I
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -346,10 +346,10 @@ THIS IS A TEST MESSAGE.##
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")
@ -468,10 +468,10 @@ THE SAFEST PLACE TO BE DURING A MAJOR LANDFALLING HURRICANE IS IN A REINFORCED I
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -512,10 +512,10 @@ THIS IS A TEST MESSAGE.##
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end

View file

@ -57,11 +57,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the svs -->

View file

@ -52,7 +52,7 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
</includedWatches>

View file

@ -67,11 +67,11 @@ Must be paired with proper vm code (also commented out in flashFloodWarning.vm)!
<!-- <trackEnabled>true</trackEnabled> -->
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -624,12 +624,12 @@ TORRENTIAL RAINFALL IS OCCURRING WITH THIS STORM...AND MAY LEAD TO FLASH FLOODIN
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#* NO NEED TO INCLUDE SVR T-STM WATCHES IN A SVR WARNING!!!!
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#
#end

View file

@ -54,10 +54,10 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -290,10 +290,10 @@ ${expcanPhrase} ${addthreat}
###########################################
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
@ -1180,7 +1180,7 @@ TORRENTIAL RAINFALL IS OCCURRING WITH THIS STORM...AND MAY LEAD TO FLASH FLOODIN
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")} && ${phenomena}=="SV")
#if(${list.contains(${includedWatches}, "TO.A")} && ${phenomena}=="SV")
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -72,8 +72,8 @@ turned on unless the corresponding .vm file is turned on in a given template's .
</phensigs>
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<enableRestart>false</enableRestart>

View file

@ -470,10 +470,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")

View file

@ -52,11 +52,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -397,10 +397,10 @@ ${canwarning}
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -571,10 +571,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -679,10 +679,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")
@ -880,10 +880,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#elseif(${CORCAN} == "true")
@ -952,10 +952,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")
@ -1142,10 +1142,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -1219,10 +1219,10 @@ ${expwarning}
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end

View file

@ -52,11 +52,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the svs -->

View file

@ -51,11 +51,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations -->

View file

@ -51,11 +51,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations -->

View file

@ -471,7 +471,7 @@ TORRENTIAL RAINFALL IS ALSO OCCURRING WITH THIS STORM...AND MAY LEAD TO FLASH FL
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -58,10 +58,10 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -262,10 +262,10 @@ ${expcanPhrase} ${addthreat}
###########################################
## WATCHES ##
#############
###if(${list.contains(${includedWatches}, "torWatches")})
###if(${list.contains(${includedWatches}, "TO.A")})
###inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
###end
###if(${list.contains(${includedWatches}, "svrWatches")})
###if(${list.contains(${includedWatches}, "SV.A")})
###insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
###end
#if(${list.contains(${bullets}, "svrboxactive")})
@ -924,7 +924,7 @@ TORRENTIAL RAINFALL IS ALSO OCCURRING WITH THIS STORM...AND MAY LEAD TO FLASH FL
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")} && ${phenomena}=="SV")
#if(${list.contains(${includedWatches}, "TO.A")} && ${phenomena}=="SV")
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -69,8 +69,8 @@ turned on unless the corresponding .vm file is turned on in a given template's .
</phensigs>
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<enableRestart>false</enableRestart>

View file

@ -230,11 +230,11 @@ LOCATIONS CAN EXPECT !** EXPECTED SNOW **! INCHES OF SNOW.
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")} && ${list.contains(${bullets}, "includeTorWatches")})
#if(${list.contains(${includedWatches}, "TO.A")} && ${list.contains(${bullets}, "includeTorWatches")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")} && ${list.contains(${bullets}, "includeSvrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")} && ${list.contains(${bullets}, "includeSvrWatches")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end

View file

@ -54,11 +54,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -309,10 +309,10 @@ IF ON OR NEAR !**Name Of Lake**!...GET OUT OF THE WATER AND MOVE INDOORS OR INSI
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
####################################

View file

@ -50,11 +50,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -431,10 +431,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")

View file

@ -54,11 +54,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -365,10 +365,10 @@ ${canwarning}
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -538,10 +538,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -646,10 +646,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${productClass}=="T")
@ -845,10 +845,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#elseif(${CORCAN} == "true")
@ -917,10 +917,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
@ -1104,10 +1104,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end
@ -1182,10 +1182,10 @@ ${expwarning}
#############
## WATCHES ##
#############
#if(${list.contains(${includedWatches}, "torWatches")})
#if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#if(${list.contains(${includedWatches}, "svrWatches")})
#if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end
#end

View file

@ -56,11 +56,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the svs -->

View file

@ -49,11 +49,11 @@ turned on unless the corresponding .vm file is turned on in a given template's .
<autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be
included with the warning product include torWatches and/or svrWatches,
included with the warning product include TO.A and/or SV.A,
respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches>
<includedWatch>torWatches</includedWatch>
<includedWatch>svrWatches</includedWatch>
<includedWatch>TO.A</includedWatch>
<includedWatch>SV.A</includedWatch>
</includedWatches>
<!-- durations: the list of possible durations of the warning -->

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Activetablesrv Plug-in
Bundle-SymbolicName: com.raytheon.uf.edex.activetable
Bundle-Version: 1.12.1174.qualifier
Bundle-Version: 1.13.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: com.raytheon.uf.common.activetable,
@ -26,6 +26,7 @@ Require-Bundle: com.raytheon.uf.common.localization;bundle-version="1.11.1",
com.raytheon.uf.edex.site;bundle-version="1.0.0",
com.google.guava;bundle-version="1.0.0",
com.raytheon.uf.edex.auth;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization.comm
com.raytheon.uf.common.serialization.comm,
org.apache.commons.io;bundle-version="2.4.0"
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Export-Package: com.raytheon.uf.edex.activetable

View file

@ -24,14 +24,15 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import jep.JepException;
import org.apache.log4j.Logger;
import com.raytheon.edex.site.SiteUtil;
import com.raytheon.edex.util.Util;
import com.raytheon.uf.common.activetable.ActiveTableMode;
import com.raytheon.uf.common.activetable.ActiveTableRecord;
@ -49,10 +50,14 @@ import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.python.PyUtil;
import com.raytheon.uf.common.python.PythonScript;
import com.raytheon.uf.common.site.SiteMap;
import com.raytheon.uf.common.status.IPerformanceStatusHandler;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.PerformanceStatus;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.util.CollectionUtil;
import com.raytheon.uf.common.time.util.ITimer;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.database.DataAccessLayerException;
@ -83,6 +88,9 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery;
* Mar 06, 2014 2883 randerso Pass siteId into python code
* Apr 10, 2014 3004 dgilling Remove ActiveTableMode parameter from
* clearPracticeTable().
* Jun 17, 2014 3296 randerso Cached PythonScript. Moved active table
* backup and purging to a separate thread.
* Added performance logging
*
* </pre>
*
@ -97,9 +105,44 @@ public class ActiveTable {
private static final Logger changeLog = Logger
.getLogger("ActiveTableChange");
private static String filePath;
private static ThreadLocal<PythonScript> threadLocalPythonScript = new ThreadLocal<PythonScript>() {
private static String includePath;
/*
* (non-Javadoc)
*
* @see java.lang.ThreadLocal#initialValue()
*/
@Override
protected PythonScript initialValue() {
try {
ITimer timer = TimeUtil.getTimer();
timer.start();
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext commonCx = pathMgr.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.BASE);
String filePath = pathMgr.getFile(commonCx,
"vtec" + File.separator + "ActiveTable.py").getPath();
String siteId = pathMgr.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.SITE)
.getContextName();
String includePath = PyUtil.buildJepIncludePath(
ActiveTablePyIncludeUtil.getCommonPythonIncludePath(),
ActiveTablePyIncludeUtil.getVtecIncludePath(siteId),
ActiveTablePyIncludeUtil
.getGfeConfigIncludePath(siteId));
PythonScript python = new PythonScript(filePath, includePath,
ActiveTable.class.getClassLoader());
timer.stop();
PerformanceStatus.getHandler("ActiveTable").logDuration(
"create PythonScript", timer.getElapsedTime());
return python;
} catch (JepException e) {
throw new RuntimeException(e);
}
}
};
private static CoreDao practiceDao = new CoreDao(
DaoConfig.forClass(PracticeActiveTableRecord.class));
@ -107,25 +150,9 @@ public class ActiveTable {
private static CoreDao operationalDao = new CoreDao(
DaoConfig.forClass(OperationalActiveTableRecord.class));
private PythonScript python;
static {
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext commonCx = pathMgr.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.BASE);
filePath = pathMgr.getFile(commonCx,
"vtec" + File.separator + "ActiveTable.py").getPath();
String siteId = pathMgr.getContext(LocalizationType.COMMON_STATIC,
LocalizationLevel.SITE).getContextName();
String pythonPath = ActiveTablePyIncludeUtil
.getCommonPythonIncludePath();
String vtecPath = ActiveTablePyIncludeUtil.getVtecIncludePath(siteId);
String configPath = ActiveTablePyIncludeUtil
.getGfeConfigIncludePath(siteId);
includePath = PyUtil.buildJepIncludePath(pythonPath, vtecPath,
configPath);
}
/**
* Default constructor
*/
public ActiveTable() {
}
@ -154,6 +181,10 @@ public class ActiveTable {
* the active table mode (PRACTICE or OPERATIONAL)
* @param phensigList
* phensigs to include. If null, all phensigs will be included.
* @param act
* the VTEC action. If null all actions will be included
* @param etn
* the ETN. If null all ETNs will be included
* @param requestValidTimes
* true if only valid times are to be returned
* @return the active table corresponding to the input parameters
@ -173,6 +204,10 @@ public class ActiveTable {
* the active table mode (PRACTICE or OPERATIONAL)
* @param phensigList
* phensigs to include. If null, all phensigs will be included.
* @param act
* the VTEC action. If null all actions will be included
* @param etn
* the ETN. If null all ETNs will be included
* @param requestValidTimes
* true if only valid times are to be returned
* @param wfos
@ -186,32 +221,18 @@ public class ActiveTable {
String[] wfos) {
if (wfos == null || !Arrays.asList(wfos).contains("all")) {
SiteMap siteMap = SiteMap.getInstance();
if (wfos == null || wfos.length == 0) {
// default to WFOs from VTECPartners
// Use the 3-char site or VTEC_DECODER_SITES will be empty
Set<String> site3s = siteMap.getSite3LetterIds(siteId);
Set<String> wfoSet = new TreeSet<String>();
for (String site3 : site3s) {
VTECPartners vtecPartners = VTECPartners.getInstance(site3);
List<String> wfoList = (List<String>) vtecPartners
.getattr("VTEC_DECODER_SITES");
wfoSet.addAll(wfoList);
String spcSite = (String) vtecPartners
.getattr("VTEC_SPC_SITE");
wfoSet.add(spcSite);
String tpcSite = (String) vtecPartners
.getattr("VTEC_TPC_SITE");
wfoSet.add(tpcSite);
}
Set<String> wfoSet = getDecoderSites(siteId);
wfoSet.add(siteId);
wfos = wfoSet.toArray(new String[0]);
}
// We have an array of 3- or 4-char WFOs to filter against.
// We need a String "KMFL,KTBW,..." for the query.
SiteMap siteMap = SiteMap.getInstance();
StringBuilder wfosb = new StringBuilder();
String sep = "";
for (String wfo : wfos) {
@ -228,6 +249,26 @@ public class ActiveTable {
false);
}
private static Set<String> getDecoderSites(String siteId) {
SiteMap siteMap = SiteMap.getInstance();
// Use the 3-char site or VTEC_DECODER_SITES will be empty
Set<String> site3s = siteMap.getSite3LetterIds(siteId);
Set<String> wfoSet = new HashSet<String>();
for (String site3 : site3s) {
VTECPartners vtecPartners = VTECPartners.getInstance(site3);
@SuppressWarnings("unchecked")
List<String> wfoList = (List<String>) vtecPartners
.getattr("VTEC_DECODER_SITES");
wfoSet.addAll(wfoList);
String spcSite = (String) vtecPartners.getattr("VTEC_SPC_SITE");
wfoSet.add(spcSite);
String tpcSite = (String) vtecPartners.getattr("VTEC_TPC_SITE");
wfoSet.add(tpcSite);
}
return wfoSet;
}
/**
* Updates the active table with the new warnings
*
@ -244,11 +285,38 @@ public class ActiveTable {
mode = ActiveTableMode.OPERATIONAL;
}
MergeResult result = filterTable(siteId,
getActiveTable(siteId, mode), newRecords, mode, offsetSecs);
IPerformanceStatusHandler perfStat = PerformanceStatus
.getHandler("ActiveTable");
ITimer timer = TimeUtil.getTimer();
timer.start();
List<ActiveTableRecord> activeTable = getActiveTable(siteId, mode);
timer.stop();
perfStat.logDuration("getActiveTable", timer.getElapsedTime());
// get decoder sites to see if we need to backup active table
Set<String> decoderSites = getDecoderSites(siteId);
// if any new record is from one of the decoder sites
// we need to queue a backup
for (ActiveTableRecord rec : newRecords) {
if (decoderSites.contains(rec.getOfficeid())) {
ActiveTableBackup.queue(mode, activeTable);
break;
}
}
timer.reset();
timer.start();
MergeResult result = filterTable(siteId, activeTable, newRecords,
mode, offsetSecs);
timer.stop();
perfStat.logDuration("filterTable", timer.getElapsedTime());
timer.reset();
timer.start();
updateTable(siteId, result, mode);
timer.stop();
perfStat.logDuration("updateTable", timer.getElapsedTime());
if (result.changeList.size() > 0) {
sendNotification(mode, result.changeList, "VTECDecoder");
}
@ -281,26 +349,17 @@ public class ActiveTable {
args.put("offsetSecs", offsetSecs);
MergeResult result = null;
try {
PythonScript python = threadLocalPythonScript.get();
try {
python = new PythonScript(filePath, includePath,
ActiveTable.class.getClassLoader());
try {
result = (MergeResult) python
.execute("mergeFromJava", args);
result = (MergeResult) python.execute("mergeFromJava", args);
} catch (JepException e) {
statusHandler.handle(Priority.PROBLEM,
"Error updating active table", e);
}
} catch (JepException e) {
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
"Error initializing active table python", e);
}
} finally {
if (python != null) {
python.dispose();
python = null;
}
}
return result;
}
@ -415,15 +474,32 @@ public class ActiveTable {
}
}
/**
* Merge new records into the active table
*
* @param newRecords
* records to be merged
* @return Exception if any occurs during merge
*/
public Exception merge(List<ActiveTableRecord> newRecords) {
return merge(newRecords, 0.0f);
}
/**
* Merge new records into the active table
*
* @param newRecords
* records to be merged
* @param timeOffset
* time offset for practice mode in displaced real time mode
* @return Exception if any occurs during merge
*/
public Exception merge(List<ActiveTableRecord> newRecords, float timeOffset) {
Exception exc = null;
try {
if (newRecords != null) {
String siteId = newRecords.get(0).getOfficeid();
String siteId = SiteUtil.getSite();
siteId = SiteMap.getInstance().getSite4LetterId(siteId);
updateActiveTable(siteId, newRecords, timeOffset);
}
} catch (Throwable t) {
@ -528,10 +604,13 @@ public class ActiveTable {
}
}
public void dispose() {
python.dispose();
}
/**
* Clear the practice active table for the requested site
*
* @param requestedSiteId
* site ID
* @throws DataAccessLayerException
*/
public static void clearPracticeTable(String requestedSiteId)
throws DataAccessLayerException {
CoreDao dao = practiceDao;
@ -544,6 +623,13 @@ public class ActiveTable {
dao.executeNativeSql(sql);
}
/**
* Dump product text to temp file
*
* @param productText
* product text
* @return the temp file
*/
public static File dumpProductToTempFile(String productText) {
File file = Util.createTempFile(productText.getBytes(), "vtec");
file.deleteOnExit();

View file

@ -0,0 +1,231 @@
/**
* 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.edex.activetable;
import java.io.File;
import java.io.FilenameFilter;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import jep.JepException;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import com.raytheon.uf.common.activetable.ActiveTableMode;
import com.raytheon.uf.common.activetable.ActiveTableRecord;
import com.raytheon.uf.common.activetable.VTECPartners;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.python.PyUtil;
import com.raytheon.uf.common.python.PythonScript;
import com.raytheon.uf.common.status.IPerformanceStatusHandler;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.PerformanceStatus;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.ITimer;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.FileUtil;
/**
* Perform Active Table Backup
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 17, 2014 #3296 randerso Initial creation
*
* </pre>
*
* @author randerso
* @version 1.0
*/
public class ActiveTableBackup {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ActiveTableBackup.class);
private static class BackupRequest {
ActiveTableMode activeTableMode;
List<ActiveTableRecord> activeTable;
BackupRequest(ActiveTableMode activeTableMode,
List<ActiveTableRecord> activeTable) {
this.activeTableMode = activeTableMode;
this.activeTable = activeTable;
}
}
private static int QUEUE_LIMIT = 10;
private static BlockingQueue<BackupRequest> queue = new LinkedBlockingQueue<BackupRequest>(
QUEUE_LIMIT);
private static ThreadLocal<PythonScript> threadLocalPythonScript = new ThreadLocal<PythonScript>() {
/*
* (non-Javadoc)
*
* @see java.lang.ThreadLocal#initialValue()
*/
@Override
protected PythonScript initialValue() {
try {
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext commonCx = pathMgr.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.BASE);
String filePath = pathMgr.getFile(commonCx,
"vtec" + File.separator + "VTECTableUtil.py").getPath();
String siteId = pathMgr.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.SITE)
.getContextName();
String includePath = PyUtil.buildJepIncludePath(
ActiveTablePyIncludeUtil.getCommonPythonIncludePath(),
ActiveTablePyIncludeUtil.getVtecIncludePath(siteId));
PythonScript python = new PythonScript(filePath, includePath,
ActiveTableBackup.class.getClassLoader());
return python;
} catch (JepException e) {
throw new RuntimeException(e);
}
}
};
private static Runnable target = new Runnable() {
@Override
public void run() {
IPerformanceStatusHandler perfStat = PerformanceStatus
.getHandler("ActiveTable");
ITimer timer = TimeUtil.getTimer();
long lastPurge = 0;
while (true) {
try {
BackupRequest request = queue.take();
timer.reset();
timer.start();
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext ctx = pathMgr.getContext(
LocalizationType.EDEX_STATIC,
LocalizationLevel.SITE);
String siteId = ctx.getContextName();
File backupDir = pathMgr.getFile(ctx,
FileUtil.join("vtec", "backup")).getAbsoluteFile();
try {
PythonScript python = threadLocalPythonScript.get();
HashMap<String, Object> args = new HashMap<String, Object>(
4, 1.0f);
args.put("activeTable", request.activeTable);
args.put("activeTableMode",
request.activeTableMode.toString());
args.put("filePath", backupDir.getParent());
args.put("siteId", siteId);
try {
python.execute("backupActiveTable", args);
} catch (JepException e) {
statusHandler.handle(Priority.PROBLEM,
"Error backing up active table", e);
}
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
"Error initializing active table python", e);
}
timer.stop();
perfStat.logDuration("backup activeTable",
timer.getElapsedTime());
long now = System.currentTimeMillis();
// don't run purge more than once a day
if ((now - lastPurge) > TimeUtil.MILLIS_PER_DAY) {
timer.reset();
timer.start();
lastPurge = now;
// get purge age in hours
long purgeAge = ((Number) VTECPartners.getInstance(
siteId).getattr("VTEC_BACKUP_TABLE_PURGE_TIME",
168 * 4)).longValue();
// compute purge time
long purgeTime = now
- (purgeAge * TimeUtil.MILLIS_PER_HOUR);
// file filter for backup files for the requested mode
FilenameFilter filter = new WildcardFileFilter("*"
+ request.activeTableMode.toString() + "*.gz");
// purge any backup file older than purge time;
for (File file : backupDir.listFiles(filter)) {
if (file.lastModified() < purgeTime) {
file.delete();
}
}
timer.stop();
perfStat.logDuration("purge activeTable backups",
timer.getElapsedTime());
}
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
}
}
};
private static Thread backupJob = new Thread(target, "activeTableBackup");
/**
* Queue an active table backup request
*
* @param activeTableMode
* @param activeTable
*/
public static void queue(ActiveTableMode activeTableMode,
List<ActiveTableRecord> activeTable) {
BackupRequest req = new BackupRequest(activeTableMode, activeTable);
try {
queue.add(req);
} catch (IllegalStateException e) {
// discard a backup request due to queue full
BackupRequest discard = queue.poll();
queue.add(req);
if (discard != null) {
statusHandler
.warn("ActiveTable backup request discarded, queue full");
}
}
if (!backupJob.isAlive()) {
backupJob.start();
}
}
}

View file

@ -19,17 +19,18 @@
**/
package com.raytheon.uf.edex.activetable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.raytheon.edex.esb.Headers;
import com.raytheon.uf.common.activetable.ActiveTableMode;
import com.raytheon.uf.common.activetable.ActiveTableRecord;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.PerformanceStatus;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.ITimer;
import com.raytheon.uf.common.time.util.TimeUtil;
/**
* Service for the VTEC active table. Determines if the VTEC product corresponds
@ -43,6 +44,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
* Mar 17, 2009 njensen Initial creation
* Jul 14, 2009 #2950 njensen Multiple site support
* Dec 21, 2009 #4055 njensen No site filtering
* Jun 17, 2014 3296 randerso Added performance logging
*
* </pre>
*
@ -54,16 +56,30 @@ public class ActiveTableSrv {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ActiveTableSrv.class);
private static Map<Long, ActiveTable> activeTableMap = new HashMap<Long, ActiveTable>();
private static ThreadLocal<ActiveTable> threadLocalActiveTable = new ThreadLocal<ActiveTable>() {
/*
* (non-Javadoc)
*
* @see java.lang.ThreadLocal#initialValue()
*/
@Override
protected ActiveTable initialValue() {
return new ActiveTable();
}
};
/**
* Merge VTEC info from new warning records into the active table
*
* @param records
*/
public void vtecArrived(List<AbstractWarningRecord> records) {
ITimer timer = TimeUtil.getTimer();
timer.start();
try {
long threadId = Thread.currentThread().getId();
ActiveTable activeTable = activeTableMap.get(threadId);
if (activeTable == null) {
activeTable = new ActiveTable();
activeTableMap.put(threadId, activeTable);
}
ActiveTable activeTable = threadLocalActiveTable.get();
if (records != null && records.size() > 0) {
activeTable.merge(ActiveTableRecord.transformFromWarnings(
records, ActiveTableMode.OPERATIONAL));
@ -72,8 +88,18 @@ public class ActiveTableSrv {
statusHandler.handle(Priority.PROBLEM,
"Error merging active table", t);
}
timer.stop();
PerformanceStatus.getHandler("ActiveTable").logDuration(
"Total time to process " + records.size() + " records",
timer.getElapsedTime());
}
/**
* Merge new warning records into the practice active table
*
* @param records
* @param headers
*/
public void practiceVtecArrived(List<AbstractWarningRecord> records,
Headers headers) {
Integer offsetSeconds = null;
@ -84,12 +110,7 @@ public class ActiveTableSrv {
offsetSeconds = Integer.valueOf(0);
}
if (records != null && records.size() > 0) {
long threadId = Thread.currentThread().getId();
ActiveTable activeTable = activeTableMap.get(threadId);
if (activeTable == null) {
activeTable = new ActiveTable();
activeTableMap.put(threadId, activeTable);
}
ActiveTable activeTable = threadLocalActiveTable.get();
try {
activeTable.merge(ActiveTableRecord.transformFromWarnings(
records, ActiveTableMode.PRACTICE), offsetSeconds

View file

@ -28,6 +28,9 @@
# 06/11/13 #2083 randerso Log active table changes, save backups
# 03/06/14 #2883 randerso Pass siteId into mergeFromJava
# 03/25/14 #2884 randerso Added xxxid to VTECChange
# 06/17/13 #3296 randerso Moved active table backup and purging
# to a separate thread in java.
# Added performance logging
#
import time
@ -40,6 +43,10 @@ from com.raytheon.uf.common.localization import PathManagerFactory
from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType
from com.raytheon.uf.common.localization import LocalizationContext_LocalizationLevel as LocalizationLevel
from com.raytheon.uf.common.time.util import TimeUtil
from com.raytheon.uf.common.status import PerformanceStatus
perfStat = PerformanceStatus.getHandler("ActiveTable")
class ActiveTable(VTECTableUtil.VTECTableUtil):
def __init__(self, activeTableMode):
@ -60,6 +67,8 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
changedFlag = False
#delete "obsolete" records from the old table.
timer = TimeUtil.getTimer()
timer.start()
vts = VTECTableSqueeze.VTECTableSqueeze(self._time+offsetSecs)
activeTable, tossRecords = vts.squeeze(activeTable)
for r in tossRecords:
@ -67,9 +76,13 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
del vts
if len(tossRecords):
changedFlag = True
timer.stop();
perfStat.logDuration("updateActiveTable squeeze", timer.getElapsedTime());
#expand out any 000 UGC codes, such as FLC000, to indicate all
#zones.
timer.reset()
timer.start()
newRecExpanded = []
compare1 = ['phen', 'sig', 'officeid', 'etn', 'pil']
for newR in newRecords:
@ -85,11 +98,15 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
else:
newRecExpanded.append(newR)
newRecords = newRecExpanded
timer.stop();
perfStat.logDuration("updateActiveTable expand", timer.getElapsedTime());
# match new records with old records, with issue time is different
# years and event times overlap. Want to reassign ongoing events
# from last year's issueTime to be 12/31/2359z, rather than the
# real issuetime (which is this year's).
timer.reset()
timer.start()
compare = ['phen', 'sig', 'officeid', 'pil', 'etn']
for newR in newRecords:
cyear = time.gmtime(newR['issueTime'])[0] #current year issuance time
@ -106,9 +123,13 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
"\nNewRec: ", self.printEntry(newR),
"OldRec: ", self.printEntry(oldR))
newR['issueTime'] = lastYearIssueTime
timer.stop();
perfStat.logDuration("updateActiveTable match", timer.getElapsedTime());
# split records out by issuance year for processing
timer.reset()
timer.start()
newRecDict = {} #key is issuance year
oldRecDict = {}
years = []
@ -126,8 +147,12 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
oldRecDict[issueYear] = records
if issueYear not in years:
years.append(issueYear)
timer.stop();
perfStat.logDuration("updateActiveTable split", timer.getElapsedTime());
# process each year
timer.reset()
timer.start()
compare = ['id', 'phen', 'sig', 'officeid', 'pil']
for year in years:
@ -166,8 +191,12 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
oldR['state'] = "Replaced"
changedFlag = True
updatedTable.append(oldR)
timer.stop();
perfStat.logDuration("updateActiveTable process", timer.getElapsedTime());
#always add in the new records (except for ROU)
timer.reset()
timer.start()
compare = ['id', 'phen', 'sig', 'officeid', 'pil', 'etn']
for year in newRecDict.keys():
newRecords = newRecDict[year]
@ -199,8 +228,12 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
rec = (newR['officeid'], newR['pil'], newR['phensig'], newR['xxxid'])
if rec not in changes:
changes.append(rec)
timer.stop();
perfStat.logDuration("updateActiveTable add", timer.getElapsedTime());
#filter out any captured text and overviewText if not in the categories
timer.reset()
timer.start()
cats = self._getTextCaptureCategories()
if cats is not None:
for rec in updatedTable:
@ -210,6 +243,8 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
if rec.has_key('overviewText'):
del rec['overviewText']
timer.stop();
perfStat.logDuration("updateActiveTable filter", timer.getElapsedTime());
return updatedTable, tossRecords, changes, changedFlag
# time overlaps, if tr1 overlaps tr2 (adjacent is not an overlap)
@ -250,35 +285,35 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
return outTable, purgedRecords, changes, changedFlag
def mergeFromJava(siteId, activeTable, newRecords, logger, mode, offsetSecs=0):
perfStat.log("mergeFromJava called for site: %s, activeTable: %d , newRecords: %d" %
(siteId, activeTable.size(), newRecords.size()))
timer = TimeUtil.getTimer()
timer.start()
pyActive = []
szActive = activeTable.size()
for i in range(szActive):
pyActive.append(ActiveTableRecord.ActiveTableRecord(activeTable.get(i)))
decoderSites = VTECPartners.VTEC_DECODER_SITES
decoderSites.append(VTECPartners.get4ID(siteId))
decoderSites.append(VTECPartners.VTEC_SPC_SITE)
decoderSites.append(VTECPartners.VTEC_TPC_SITE)
backup = False
pyNew = []
szNew = newRecords.size()
for i in range(szNew):
rec = ActiveTableRecord.ActiveTableRecord(newRecords.get(i))
if rec['officeid'] in decoderSites:
backup = True
pyNew.append(rec)
active = ActiveTable(mode)
if backup:
oldActiveTable = active._convertTableToPurePython(pyActive, siteId)
active.saveOldActiveTable(oldActiveTable)
pTime = getattr(VTECPartners, "VTEC_BACKUP_TABLE_PURGE_TIME",168)
active.purgeOldSavedTables(pTime)
logger.info("Updating " + mode + " Active Table: new records\n" +
active.printActiveTable(pyNew, combine=1))
timer.stop()
perfStat.logDuration("mergeFromJava preprocess", timer.getElapsedTime());
updatedTable, purgeRecords, changes, changedFlag = active.activeTableMerge(pyActive, pyNew, offsetSecs)
perfStat.log("mergeFromJava activeTableMerge returned updateTable: %d, purgeRecords: %d, changes: %d" %
(len(updatedTable), len(purgeRecords), len(changes)))
timer.reset()
timer.start()
logger.info("Updated " + mode + " Active Table: purged\n" +
active.printActiveTable(purgeRecords, combine=1))
@ -298,15 +333,15 @@ def mergeFromJava(siteId, activeTable, newRecords, logger, mode, offsetSecs=0):
logger.info("Updated " + mode + " Active Table: decoded\n" +
active.printActiveTable(decoded, combine=1))
updatedList = ArrayList()
updatedList = ArrayList(len(updatedTable))
for x in updatedTable:
updatedList.add(x.javaRecord())
purgedList = ArrayList()
purgedList = ArrayList(len(purgeRecords))
for x in purgeRecords:
purgedList.add(x.javaRecord())
changeList = ArrayList()
changeList = ArrayList(len(changes))
if (changedFlag):
from com.raytheon.uf.common.activetable import VTECChange
for c in changes:
@ -314,4 +349,6 @@ def mergeFromJava(siteId, activeTable, newRecords, logger, mode, offsetSecs=0):
from com.raytheon.uf.common.activetable import MergeResult
result = MergeResult(updatedList, purgedList, changeList)
timer.stop()
perfStat.logDuration("mergeFromJava postprocess", timer.getElapsedTime());
return result

View file

@ -1,24 +1,38 @@
##
# 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
# 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
#
# 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.
##
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 06/17/13 #3296 randerso Default debug to False to avoid logging overhead
# Added performance logging
#
import os, sys, time, copy, LogStream
from com.raytheon.uf.common.time.util import TimeUtil
from com.raytheon.uf.common.status import PerformanceStatus
perfStat = PerformanceStatus.getHandler("ActiveTable")
timer = TimeUtil.getTimer()
# This class takes a VTEC active table and eliminates unnecessary
# records. Records purged consist of old SPC watches, old Tropical
# events, last year's records, and extraneous records not needed for
@ -27,7 +41,7 @@ import os, sys, time, copy, LogStream
class VTECTableSqueeze:
#constructor
def __init__(self, currentTime, debug=True):
def __init__(self, currentTime, debug=False):
self.__ctime = currentTime
self.__thisYear = time.gmtime(self.__ctime)[0]
self.__debug = debug
@ -41,7 +55,11 @@ class VTECTableSqueeze:
LogStream.logDebug(self.__printActiveTable(table))
# modify old UFN events (in case fcstrs didn't CAN them)
timer.reset()
timer.start()
table, modTable = self.__modifyOldUFNEvents(table)
timer.stop()
perfStat.logDuration("updateActiveTable squeeze __modifyOldUFNEvents", timer.getElapsedTime());
if self.__debug:
LogStream.logDebug("************** MOD UFN TABLE *********************")
for old, new in modTable:
@ -50,8 +68,12 @@ class VTECTableSqueeze:
LogStream.logDebug(" -----------")
# remove the national center and short fused events
timer.reset()
timer.start()
shortWFO, shortNC, purgeT = \
self.__removeOldNationalAndShortFusedEvents(table)
timer.stop()
perfStat.logDuration("updateActiveTable squeeze __removeOldNationalAndShortFusedEvents", timer.getElapsedTime());
if self.__debug:
LogStream.logDebug("************** SHORT WFO TABLE *********************")
LogStream.logDebug(self.__printActiveTable(shortWFO))
@ -61,10 +83,18 @@ class VTECTableSqueeze:
LogStream.logDebug(self.__printActiveTable(purgeT))
# separate out the shortWFO into dictionary structure
timer.reset()
timer.start()
dict = self.__separateTable(shortWFO)
timer.stop()
perfStat.logDuration("updateActiveTable squeeze __separateTable", timer.getElapsedTime());
# purge old entries with LowerETNs that aren't in effect
timer.reset()
timer.start()
shorterT, purgeT2 = self.__purgeOldEntriesWithLowerETNs(dict)
timer.stop()
perfStat.logDuration("updateActiveTable squeeze __purgeOldEntriesWithLowerETNs", timer.getElapsedTime());
if self.__debug:
LogStream.logDebug("************** TRIMMED WFO TABLE ******************")
LogStream.logDebug(self.__printActiveTable(shorterT))
@ -72,12 +102,10 @@ class VTECTableSqueeze:
LogStream.logDebug(self.__printActiveTable(purgeT2))
#add in any shortNC entries to final table
for r in shortNC:
shorterT.append(r)
shorterT.extend(shortNC)
#add in the purged entries from before
for r in purgeT2:
purgeT.append(r)
purgeT.extend(purgeT2)
if self.__debug:
LogStream.logDebug("************** FINAL TABLE ********************")

View file

@ -17,7 +17,14 @@
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information.
##
# Utility classes for the VTEC active table
# Utility classes for the VTEC util table
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 06/17/13 #3296 randerso Moved active table backup and purging
# to a separate thread in java.
import copy
import cPickle
@ -384,3 +391,14 @@ class VTECTableUtil:
return JUtil.javaObjToPyVal(javaDictFormat)
def backupActiveTable(activeTable, activeTableMode, filePath, siteId):
import ActiveTableRecord
pyActive = []
szActive = activeTable.size()
for i in range(szActive):
pyActive.append(ActiveTableRecord.ActiveTableRecord(activeTable.get(i)))
# create a dummy name to simplify the file access code in VTECTableUtil
util = VTECTableUtil(os.path.join(filePath, activeTableMode + ".tbl"))
oldActiveTable = util._convertTableToPurePython(pyActive, siteId)
util.saveOldActiveTable(oldActiveTable)

View file

@ -1,5 +1,5 @@
/**
* Autogenerated by Thrift Compiler (0.9.0)
* Autogenerated by Thrift Compiler (0.8.0)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
@ -35,6 +35,7 @@
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 07/29/13 2215 bkowal Regenerated for thrift 0.9.0
* 07/22/14 15649 lshi Rollback to thrift 0.8.0
*
* </pre>
*
@ -43,14 +44,13 @@
*/
#include "Notification_types.h"
#include <algorithm>
const char* com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::ascii_fingerprint = "ACE4F644F0FDD289DDC4EE5B83BC13C0";
const uint8_t com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::binary_fingerprint[16] = {0xAC,0xE4,0xF6,0x44,0xF0,0xFD,0xD2,0x89,0xDD,0xC4,0xEE,0x5B,0x83,0xBC,0x13,0xC0};
uint32_t com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::read(::apache::thrift::protocol::TProtocol* iprot) {
uint32_t xfer = 0;
std::string fname;
::apache::thrift::protocol::TType ftype;
@ -75,14 +75,14 @@ uint32_t com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::r
this->dataURIs.clear();
uint32_t _size0;
::apache::thrift::protocol::TType _etype3;
xfer += iprot->readListBegin(_etype3, _size0);
iprot->readListBegin(_etype3, _size0);
this->dataURIs.resize(_size0);
uint32_t _i4;
for (_i4 = 0; _i4 < _size0; ++_i4)
{
xfer += iprot->readString(this->dataURIs[_i4]);
}
xfer += iprot->readListEnd();
iprot->readListEnd();
}
this->__isset.dataURIs = true;
} else {
@ -104,7 +104,6 @@ uint32_t com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::r
uint32_t com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::write(::apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
xfer += oprot->writeStructBegin("com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage");
xfer += oprot->writeFieldBegin("dataURIs", ::apache::thrift::protocol::T_LIST, 1);
{
xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast<uint32_t>(this->dataURIs.size()));
@ -116,16 +115,9 @@ uint32_t com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::w
xfer += oprot->writeListEnd();
}
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd();
return xfer;
}
void swap(com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage &a, com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage &b) {
using ::std::swap;
swap(a.dataURIs, b.dataURIs);
swap(a.__isset, b.__isset);
}

View file

@ -1,10 +1,3 @@
/**
* Autogenerated by Thrift Compiler (0.9.0)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
/*****************************************************************************************
* COPYRIGHT (c), 2009, RAYTHEON COMPANY
* ALL RIGHTS RESERVED, An Unpublished Work
@ -26,7 +19,8 @@
******************************************************************************************/
/*
* Extended thrift protocol to handle messages from edex.
* Support for point data request capability to retrieve point data and metadata
* from EDEX Thrift service.
*
* <pre>
*
@ -34,13 +28,21 @@
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 07/29/13 2215 bkowal Regenerated for thrift 0.9.0
* 08/08/11 9696 gzhou Initial Creation
* 07/29/13 2215 bkowal Regenerated for thrift 0.9.0
* 07/22/14 15649 lshi Rollback to Initial Creation
*
* </pre>
*
* @author bkowal
* @author gzhou
* @version 1
*/
/**
* Autogenerated by Thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
*/
#include "PointDataServer_constants.h"

View file

@ -1,10 +1,3 @@
/**
* Autogenerated by Thrift Compiler (0.9.0)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
/*****************************************************************************************
* COPYRIGHT (c), 2009, RAYTHEON COMPANY
* ALL RIGHTS RESERVED, An Unpublished Work
@ -26,7 +19,8 @@
******************************************************************************************/
/*
* Extended thrift protocol to handle messages from edex.
* Support for point data request capability to retrieve point data and metadata
* from EDEX Thrift service.
*
* <pre>
*
@ -34,240 +28,222 @@
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 07/29/13 2215 bkowal Regenerated for thrift 0.9.0
* 08/08/11 9696 gzhou Initial Creation
* 07/29/13 2215 bkowal Regenerated for thrift 0.9.0
* 07/22/14 15649 lshi Rollback to Initial Creation
*
* </pre>
*
* @author bkowal
* @author gzhou
* @version 1
*/
#include "PointDataServer_types.h"
#include <algorithm>
const char
* com_raytheon_uf_common_dataquery_requests_ConstraintType::ascii_fingerprint =
"EFB929595D312AC8F305D5A794CFEDA1";
const uint8_t
com_raytheon_uf_common_dataquery_requests_ConstraintType::binary_fingerprint[16] =
{ 0xEF, 0xB9, 0x29, 0x59, 0x5D, 0x31, 0x2A, 0xC8, 0xF3, 0x05,
0xD5, 0xA7, 0x94, 0xCF, 0xED, 0xA1 };
uint32_t com_raytheon_uf_common_dataquery_requests_ConstraintType::read(
::apache::thrift::protocol::TProtocol* iprot) {
uint32_t xfer = 0;
std::string fname;
::apache::thrift::protocol::TType ftype;
int16_t fid;
const char* com_raytheon_uf_common_dataquery_requests_ConstraintType::ascii_fingerprint = "EFB929595D312AC8F305D5A794CFEDA1";
const uint8_t com_raytheon_uf_common_dataquery_requests_ConstraintType::binary_fingerprint[16] = {0xEF,0xB9,0x29,0x59,0x5D,0x31,0x2A,0xC8,0xF3,0x05,0xD5,0xA7,0x94,0xCF,0xED,0xA1};
xfer += iprot->readStructBegin(fname);
uint32_t com_raytheon_uf_common_dataquery_requests_ConstraintType::read(::apache::thrift::protocol::TProtocol* iprot) {
using ::apache::thrift::protocol::TProtocolException;
uint32_t xfer = 0;
std::string fname;
::apache::thrift::protocol::TType ftype;
int16_t fid;
xfer += iprot->readFieldBegin(fname, ftype, fid);
if (ftype == ::apache::thrift::protocol::T_STRING) {
xfer += iprot->readString(operand);
this->__isset.operand = true;
} else
xfer += iprot->skip(ftype);
xfer += iprot->readFieldEnd();
xfer += iprot->readStructBegin(fname);
xfer += iprot->readStructEnd();
using ::apache::thrift::protocol::TProtocolException;
while (true)
{
xfer += iprot->readFieldBegin(fname, ftype, fid);
if (ftype == ::apache::thrift::protocol::T_STOP) {
break;
}
switch (fid)
{
case 1:
if (ftype == ::apache::thrift::protocol::T_STRING) {
xfer += iprot->readString(this->operand);
this->__isset.operand = true;
} else {
xfer += iprot->skip(ftype);
}
break;
default:
xfer += iprot->skip(ftype);
break;
}
xfer += iprot->readFieldEnd();
}
xfer += iprot->readStructEnd();
return xfer;
return xfer;
}
uint32_t com_raytheon_uf_common_dataquery_requests_ConstraintType::write(::apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
xfer += oprot->writeStructBegin("com_raytheon_uf_common_dataquery_requests_ConstraintType");
xfer += oprot->writeFieldBegin("operand", ::apache::thrift::protocol::T_STRING, 1);
xfer += oprot->writeString(this->operand);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd();
return xfer;
uint32_t com_raytheon_uf_common_dataquery_requests_ConstraintType::write(
::apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
xfer
+= oprot->writeStructBegin(
"com_raytheon_uf_common_dataquery_requests_RequestConstraint$ConstraintType");
xfer += oprot->writeFieldBegin("__enumValue__",
::apache::thrift::protocol::T_STRING, 1);
xfer += oprot->writeString(this->operand);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeStructEnd();
return xfer;
}
void swap(com_raytheon_uf_common_dataquery_requests_ConstraintType &a, com_raytheon_uf_common_dataquery_requests_ConstraintType &b) {
using ::std::swap;
swap(a.operand, b.operand);
swap(a.__isset, b.__isset);
const char
* com_raytheon_uf_common_dataquery_requests_RequestConstraint::ascii_fingerprint =
"BDAF55DAA660FA1ADBE30760752211A8";
const uint8_t
com_raytheon_uf_common_dataquery_requests_RequestConstraint::binary_fingerprint[16] =
{ 0xBD, 0xAF, 0x55, 0xDA, 0xA6, 0x60, 0xFA, 0x1A, 0xDB, 0xE3,
0x07, 0x60, 0x75, 0x22, 0x11, 0xA8 };
uint32_t com_raytheon_uf_common_dataquery_requests_RequestConstraint::read(
::apache::thrift::protocol::TProtocol* iprot) {
uint32_t xfer = 0;
std::string fname;
::apache::thrift::protocol::TType ftype;
int16_t fid;
xfer += iprot->readStructBegin(fname);
using ::apache::thrift::protocol::TProtocolException;
while (true) {
xfer += iprot->readFieldBegin(fname, ftype, fid);
if (ftype == ::apache::thrift::protocol::T_STOP) {
break;
}
switch (fid) {
case 1:
if (ftype == ::apache::thrift::protocol::T_STRUCT) {
xfer += this->constraintType.read(iprot);
this->__isset.constraintType = true;
} else {
xfer += iprot->skip(ftype);
}
break;
case 2:
if (ftype == ::apache::thrift::protocol::T_STRING) {
xfer += iprot->readString(this->constraintValue);
this->__isset.constraintValue = true;
} else {
xfer += iprot->skip(ftype);
}
break;
default:
xfer += iprot->skip(ftype);
break;
}
xfer += iprot->readFieldEnd();
}
xfer += iprot->readStructEnd();
return xfer;
}
const char* com_raytheon_uf_common_dataquery_requests_RequestConstraint::ascii_fingerprint = "BDAF55DAA660FA1ADBE30760752211A8";
const uint8_t com_raytheon_uf_common_dataquery_requests_RequestConstraint::binary_fingerprint[16] = {0xBD,0xAF,0x55,0xDA,0xA6,0x60,0xFA,0x1A,0xDB,0xE3,0x07,0x60,0x75,0x22,0x11,0xA8};
uint32_t com_raytheon_uf_common_dataquery_requests_RequestConstraint::read(::apache::thrift::protocol::TProtocol* iprot) {
uint32_t xfer = 0;
std::string fname;
::apache::thrift::protocol::TType ftype;
int16_t fid;
xfer += iprot->readStructBegin(fname);
using ::apache::thrift::protocol::TProtocolException;
while (true)
{
xfer += iprot->readFieldBegin(fname, ftype, fid);
if (ftype == ::apache::thrift::protocol::T_STOP) {
break;
}
switch (fid)
{
case 1:
if (ftype == ::apache::thrift::protocol::T_STRUCT) {
xfer += this->constraintType.read(iprot);
this->__isset.constraintType = true;
} else {
xfer += iprot->skip(ftype);
}
break;
case 2:
if (ftype == ::apache::thrift::protocol::T_STRING) {
xfer += iprot->readString(this->constraintValue);
this->__isset.constraintValue = true;
} else {
xfer += iprot->skip(ftype);
}
break;
default:
xfer += iprot->skip(ftype);
break;
}
xfer += iprot->readFieldEnd();
}
xfer += iprot->readStructEnd();
return xfer;
uint32_t com_raytheon_uf_common_dataquery_requests_RequestConstraint::write(
::apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
xfer += oprot->writeStructBegin(
"com_raytheon_uf_common_dataquery_requests_RequestConstraint");
xfer += oprot->writeFieldBegin("constraintType",
::apache::thrift::protocol::T_STRUCT, 1);
xfer += this->constraintType.write(oprot);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("constraintValue",
::apache::thrift::protocol::T_STRING, 2);
xfer += oprot->writeString(this->constraintValue);
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd();
return xfer;
}
uint32_t com_raytheon_uf_common_dataquery_requests_RequestConstraint::write(::apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
xfer += oprot->writeStructBegin("com_raytheon_uf_common_dataquery_requests_RequestConstraint");
const char
* com_raytheon_uf_common_pointdata_PointDataServerRequest::ascii_fingerprint =
"C9F1CC9CD1A896EE01B7C5215E2BE99F";
const uint8_t
com_raytheon_uf_common_pointdata_PointDataServerRequest::binary_fingerprint[16] =
{ 0xC9, 0xF1, 0xCC, 0x9C, 0xD1, 0xA8, 0x96, 0xEE, 0x01, 0xB7,
0xC5, 0x21, 0x5E, 0x2B, 0xE9, 0x9F };
xfer += oprot->writeFieldBegin("constraintType", ::apache::thrift::protocol::T_STRUCT, 1);
xfer += this->constraintType.write(oprot);
xfer += oprot->writeFieldEnd();
uint32_t com_raytheon_uf_common_pointdata_PointDataServerRequest::read(
::apache::thrift::protocol::TProtocol* iprot) {
xfer += oprot->writeFieldBegin("constraintValue", ::apache::thrift::protocol::T_STRING, 2);
xfer += oprot->writeString(this->constraintValue);
xfer += oprot->writeFieldEnd();
uint32_t xfer = 0;
std::string fname;
::apache::thrift::protocol::TType ftype;
int16_t fid;
xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd();
return xfer;
xfer += iprot->readStructBegin(fname);
using ::apache::thrift::protocol::TProtocolException;
while (true) {
xfer += iprot->readFieldBegin(fname, ftype, fid);
if (ftype == ::apache::thrift::protocol::T_STOP) {
break;
}
switch (fid) {
case 1:
if (ftype == ::apache::thrift::protocol::T_MAP) {
{
this->rcMap.clear();
uint32_t _size0;
::apache::thrift::protocol::TType _ktype1;
::apache::thrift::protocol::TType _vtype2;
iprot->readMapBegin(_ktype1, _vtype2, _size0);
uint32_t _i4;
for (_i4 = 0; _i4 < _size0; ++_i4) {
std::string _key5;
xfer += iprot->readString(_key5);
com_raytheon_uf_common_dataquery_requests_RequestConstraint
& _val6 = this->rcMap[_key5];
xfer += _val6.read(iprot);
}
iprot->readMapEnd();
}
this->__isset.rcMap = true;
} else {
xfer += iprot->skip(ftype);
}
break;
default:
xfer += iprot->skip(ftype);
break;
}
xfer += iprot->readFieldEnd();
}
xfer += iprot->readStructEnd();
return xfer;
}
void swap(com_raytheon_uf_common_dataquery_requests_RequestConstraint &a, com_raytheon_uf_common_dataquery_requests_RequestConstraint &b) {
using ::std::swap;
swap(a.constraintType, b.constraintType);
swap(a.constraintValue, b.constraintValue);
swap(a.__isset, b.__isset);
uint32_t com_raytheon_uf_common_pointdata_PointDataServerRequest::write(
::apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
xfer += oprot->writeStructBegin(
"com_raytheon_uf_common_pointdata_PointDataServerRequest");
xfer += oprot->writeFieldBegin("rcMap", ::apache::thrift::protocol::T_MAP,
1);
{
xfer += oprot->writeMapBegin(::apache::thrift::protocol::T_STRING,
::apache::thrift::protocol::T_STRUCT, this->rcMap.size());
std::map<std::string,
com_raytheon_uf_common_dataquery_requests_RequestConstraint>::const_iterator
_iter7;
for (_iter7 = this->rcMap.begin(); _iter7 != this->rcMap.end(); ++_iter7) {
xfer += oprot->writeStructBegin("11");
xfer += oprot->writeString(_iter7->first);
xfer += oprot->writeStructEnd();
xfer += _iter7->second.write(oprot);
}
xfer += oprot->writeMapEnd();
}
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd();
return xfer;
}
const char* com_raytheon_uf_common_pointdata_PointDataServerRequest::ascii_fingerprint = "C9F1CC9CD1A896EE01B7C5215E2BE99F";
const uint8_t com_raytheon_uf_common_pointdata_PointDataServerRequest::binary_fingerprint[16] = {0xC9,0xF1,0xCC,0x9C,0xD1,0xA8,0x96,0xEE,0x01,0xB7,0xC5,0x21,0x5E,0x2B,0xE9,0x9F};
uint32_t com_raytheon_uf_common_pointdata_PointDataServerRequest::read(::apache::thrift::protocol::TProtocol* iprot) {
uint32_t xfer = 0;
std::string fname;
::apache::thrift::protocol::TType ftype;
int16_t fid;
xfer += iprot->readStructBegin(fname);
using ::apache::thrift::protocol::TProtocolException;
while (true)
{
xfer += iprot->readFieldBegin(fname, ftype, fid);
if (ftype == ::apache::thrift::protocol::T_STOP) {
break;
}
switch (fid)
{
case 1:
if (ftype == ::apache::thrift::protocol::T_MAP) {
{
this->rcMap.clear();
uint32_t _size0;
::apache::thrift::protocol::TType _ktype1;
::apache::thrift::protocol::TType _vtype2;
xfer += iprot->readMapBegin(_ktype1, _vtype2, _size0);
uint32_t _i4;
for (_i4 = 0; _i4 < _size0; ++_i4)
{
std::string _key5;
xfer += iprot->readString(_key5);
com_raytheon_uf_common_dataquery_requests_RequestConstraint& _val6 = this->rcMap[_key5];
xfer += _val6.read(iprot);
}
xfer += iprot->readMapEnd();
}
this->__isset.rcMap = true;
} else {
xfer += iprot->skip(ftype);
}
break;
default:
xfer += iprot->skip(ftype);
break;
}
xfer += iprot->readFieldEnd();
}
xfer += iprot->readStructEnd();
return xfer;
}
uint32_t com_raytheon_uf_common_pointdata_PointDataServerRequest::write(::apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
xfer += oprot->writeStructBegin("com_raytheon_uf_common_pointdata_PointDataServerRequest");
xfer += oprot->writeFieldBegin("rcMap", ::apache::thrift::protocol::T_MAP, 1);
{
xfer += oprot->writeMapBegin(::apache::thrift::protocol::T_STRING, ::apache::thrift::protocol::T_STRUCT, static_cast<uint32_t>(this->rcMap.size()));
std::map<std::string, com_raytheon_uf_common_dataquery_requests_RequestConstraint> ::const_iterator _iter7;
for (_iter7 = this->rcMap.begin(); _iter7 != this->rcMap.end(); ++_iter7)
{
xfer += oprot->writeString(_iter7->first);
xfer += _iter7->second.write(oprot);
}
xfer += oprot->writeMapEnd();
}
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd();
return xfer;
}
void swap(com_raytheon_uf_common_pointdata_PointDataServerRequest &a, com_raytheon_uf_common_pointdata_PointDataServerRequest &b) {
using ::std::swap;
swap(a.rcMap, b.rcMap);
swap(a.__isset, b.__isset);
}

View file

@ -1,10 +1,3 @@
/**
* Autogenerated by Thrift Compiler (0.9.0)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
/*****************************************************************************************
* COPYRIGHT (c), 2009, RAYTHEON COMPANY
* ALL RIGHTS RESERVED, An Unpublished Work
@ -26,7 +19,8 @@
******************************************************************************************/
/*
* Extended thrift protocol to handle messages from edex.
* Support for point data request capability to retrieve point data
* from EDEX Thrift service.
*
* <pre>
*
@ -34,13 +28,21 @@
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 07/29/13 2215 bkowal Regenerated for thrift 0.9.0
* 01/18/10 3747 brockwoo Initial Creation
* 07/29/13 2215 bkowal Regenerated for thrift 0.9.0
* 07/22/14 15649 lshi Rollback to Initial Creation
*
* </pre>
*
* @author bkowal
* @author brockwoo
* @version 1
*/
/**
* Autogenerated by Thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
*/
#include "PointData_constants.h"

File diff suppressed because it is too large Load diff