Merge branch 'master_14.3.1' into asm_14.3.1

Conflicts:
	cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java

Former-commit-id: f22cc09d0a6fdc7a806726d5207f6b3507972b94
This commit is contained in:
Brian.Dyke 2014-08-04 16:40:02 -04:00
commit 6f6daaa249
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 * 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> * <pre>
* SOFTWARE HISTORY * SOFTWARE HISTORY
@ -47,6 +50,7 @@ import com.raytheon.uf.viz.core.status.VizStatusInternal;
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Sep 09, 2008 1433 chammack Initial creation * Sep 09, 2008 1433 chammack Initial creation
* Aug 26, 2013 2142 njensen Changed to use SLF4J * Aug 26, 2013 2142 njensen Changed to use SLF4J
* Jul 02, 2014 3337 njensen Disabled logback packaging data
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -62,6 +66,34 @@ public class SystemStatusHandler extends AbstractStatusHandler {
private static final Marker FATAL = MarkerFactory.getMarker("FATAL"); 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) * (non-Javadoc)
* *

View file

@ -26,7 +26,10 @@
<loadProperties> <loadProperties>
<capabilities> <capabilities>
<capability xsi:type="colorableCapability" colorAsString="#9b9b9b" /> <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> </capabilities>
<resourceType>PLAN_VIEW</resourceType> <resourceType>PLAN_VIEW</resourceType>
</loadProperties> </loadProperties>
@ -37,7 +40,23 @@
<capabilities> <capabilities>
<capability xsi:type="colorableCapability" colorAsString="#9b9b9b" /> <capability xsi:type="colorableCapability" colorAsString="#9b9b9b" />
<capability xsi:type="labelableCapability" labelField="name" /> <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" /> outlineWidth="1" />
</capabilities> </capabilities>
<resourceType>PLAN_VIEW</resourceType> <resourceType>PLAN_VIEW</resourceType>
@ -51,27 +70,10 @@
<mapName>Cities</mapName> <mapName>Cities</mapName>
</resourceData> </resourceData>
</resource> </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> </resourceData>
</resource> </resource>
</descriptor> </descriptor>
</displays> </displays>
</displayList> </displayList>
</bundle> </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;
import com.raytheon.uf.common.localization.AutoUpdatingLocalizationFile.AutoUpdatingFileChangedListener; import com.raytheon.uf.common.localization.AutoUpdatingLocalizationFile.AutoUpdatingFileChangedListener;
import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException; 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.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.drawables.AbstractRenderableDisplay; import com.raytheon.uf.viz.core.drawables.AbstractRenderableDisplay;
import com.raytheon.uf.viz.core.exception.VizException; 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.MapScale;
import com.raytheon.uf.viz.core.maps.scales.MapScales.PartId; import com.raytheon.uf.viz.core.maps.scales.MapScales.PartId;
import com.raytheon.uf.viz.core.procedures.Bundle; 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 08, 2013 mschenke Initial creation
* Oct 22, 2013 2491 bsteffen Change from SerializationUtil to * Oct 22, 2013 2491 bsteffen Change from SerializationUtil to
* ProcedureXmlManager * 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> * </pre>
* *
@ -79,6 +84,11 @@ public class MapScalesManager {
private static final String DEFAULT_SCALES_FILE = "scalesInfo.xml"; 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 * Manager class for a single {@link MapScale}. Is able to create a Bundle
* for the scale. May provide functions for modifying/saving scales * for the scale. May provide functions for modifying/saving scales
@ -94,7 +104,7 @@ public class MapScalesManager {
private final String displayName; private final String displayName;
private final PartId[] partIds; private PartId[] partIds;
private final AutoUpdatingLocalizationFile scaleFile; private final AutoUpdatingLocalizationFile scaleFile;
@ -103,13 +113,15 @@ public class MapScalesManager {
private final boolean isCustom; private final boolean isCustom;
private ManagedMapScale(String baseDir, MapScale scale) private ManagedMapScale(String baseDir, MapScale scale)
throws SerializationException { throws IllegalStateException, SerializationException {
this.isCustom = false; this.isCustom = false;
this.partIds = scale.getPartIds();
this.displayName = scale.getDisplayName();
LocalizationFile file = PathManagerFactory.getPathManager() LocalizationFile file = PathManagerFactory.getPathManager()
.getStaticLocalizationFile( .getStaticLocalizationFile(
baseDir + IPathManager.SEPARATOR baseDir + IPathManager.SEPARATOR
+ scale.getFileName()); + scale.getFileName());
if (file == null || !file.exists()) { if (file == null || !file.exists()) {
throw new IllegalStateException( throw new IllegalStateException(
"scalesInfo.xml references missing file " "scalesInfo.xml references missing file "
@ -117,9 +129,18 @@ public class MapScalesManager {
} }
this.scaleFile = new AutoUpdatingLocalizationFile(file); this.scaleFile = new AutoUpdatingLocalizationFile(file);
this.scaleFile.addListener(listener); this.scaleFile.addListener(listener);
this.partIds = scale.getPartIds();
this.displayName = scale.getDisplayName();
loadBundleXml(); 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) private ManagedMapScale(String displayName, Bundle scaleBundle)
@ -190,7 +211,9 @@ public class MapScalesManager {
@Override @Override
public void fileChanged(AutoUpdatingLocalizationFile file) { public void fileChanged(AutoUpdatingLocalizationFile file) {
try { try {
loadMapScales(); MapScales scales = file.loadObject(getJAXBManager(),
MapScales.class);
loadMapScales(scales);
} catch (SerializationException e) { } catch (SerializationException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e); e);
@ -198,7 +221,7 @@ public class MapScalesManager {
} }
}; };
private final AutoUpdatingLocalizationFile scalesFile; private AutoUpdatingLocalizationFile scalesFile;
private final String scaleBundleDir; private final String scaleBundleDir;
@ -223,36 +246,108 @@ public class MapScalesManager {
*/ */
public MapScalesManager(String scalesDir, String scalesFile) public MapScalesManager(String scalesDir, String scalesFile)
throws SerializationException { throws SerializationException {
this(scalesDir, PathManagerFactory.getPathManager() String filename = scalesDir + IPathManager.SEPARATOR + scalesFile;
LocalizationFile locFile = PathManagerFactory.getPathManager()
.getStaticLocalizationFile( .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 * Handles the parts that referenced scales files that couldn't be found.
* deserializable into a {@link MapScales} object
* *
* @param bundleDir * @param missingParts
* directory bundle files are relative to * the parts that were missing
* @param scalesFile * @param goodScales
* @throws SerializationException * the scales that successfully loaded
*/ */
public MapScalesManager(String bundleDir, LocalizationFile scalesFile) protected void handleMissingParts(List<PartId> missingParts) {
throws SerializationException { /*
this.scaleBundleDir = bundleDir; * if the missing part was a side view, fall back to the main pane
this.scalesFile = new AutoUpdatingLocalizationFile(scalesFile); */
this.scalesFile.addListener(listener); ManagedMapScale mainPane = findEditorScale();
loadMapScales();
}
private synchronized void loadMapScales() throws SerializationException { if (mainPane == null) {
List<ManagedMapScale> storedScales = new ArrayList<ManagedMapScale>(); /*
MapScales scales = this.scalesFile.loadObject(getJAXBManager(), * main pane is missing too, so fall back to a base scale that is
MapScales.class); * guaranteed to be there
for (MapScale scale : scales.getScales()) { */
storedScales.add(new ManagedMapScale(scaleBundleDir, scale)); 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 * @param partId
* @return * @return
*/ */
public ManagedMapScale[] getScalesForPart(String partId) { public Bundle getScaleBundleForPart(String partId) {
List<ManagedMapScale> scalesForPart = new ArrayList<ManagedMapScale>(); List<ManagedMapScale> scalesForPart = new ArrayList<ManagedMapScale>();
for (ManagedMapScale scale : storedScales) { for (ManagedMapScale scale : storedScales) {
for (PartId part : scale.getPartIds()) { 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; 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. * cease a null pointer exception.
* May 5, 2014 DR 17201 D. Friedman Make same-radar time matching work more like A1. * 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. * 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> * </pre>
* *
@ -657,7 +658,6 @@ public class TimeMatcher {
if (fspatial) { if (fspatial) {
frameFcsts = dataFcsts; frameFcsts = dataFcsts;
dtf = dt;
} else if (dtf > dt) { } else if (dtf > dt) {
dt = dtf; dt = dtf;
} }

View file

@ -35,7 +35,6 @@ import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI; import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart; 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.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; 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.exception.VizException;
import com.raytheon.uf.viz.core.globals.VizGlobalsManager; 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;
import com.raytheon.uf.viz.core.maps.scales.MapScalesManager.ManagedMapScale;
import com.raytheon.uf.viz.core.procedures.Bundle; import com.raytheon.uf.viz.core.procedures.Bundle;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource; import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IInputHandler; 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 * Mar 21, 2013 1638 mschenke Changed map scales not tied to d2d
* Aug 9, 2013 DR 16427 D. Friedman Swap additional input handlers. * Aug 9, 2013 DR 16427 D. Friedman Swap additional input handlers.
* Oct 10, 2013 #2104 mschenke Switched to use MapScalesManager * Oct 10, 2013 #2104 mschenke Switched to use MapScalesManager
* * Jul 15, 2014 2954 njensen Updated init() for MapScalesManager change
*
* </pre> * </pre>
* *
* @author chammack * @author chammack
@ -141,18 +140,8 @@ public class SideView extends ViewPart implements IMultiPaneEditor,
String myId = site.getId() + UiUtil.SECONDARY_ID_SEPARATOR String myId = site.getId() + UiUtil.SECONDARY_ID_SEPARATOR
+ site.getSecondaryId(); + site.getSecondaryId();
for (ManagedMapScale scale : MapScalesManager.getInstance() bundleToLoad = MapScalesManager.getInstance().getScaleBundleForPart(
.getScalesForPart(myId)) { 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;
}
} }
@Override @Override
@ -284,6 +273,7 @@ public class SideView extends ViewPart implements IMultiPaneEditor,
* *
* @see com.raytheon.viz.core.IDisplayPaneContainer#getActiveDisplayPane() * @see com.raytheon.viz.core.IDisplayPaneContainer#getActiveDisplayPane()
*/ */
@Override
public IDisplayPane getActiveDisplayPane() { public IDisplayPane getActiveDisplayPane() {
return paneManager.getActiveDisplayPane(); return paneManager.getActiveDisplayPane();
} }
@ -774,15 +764,18 @@ public class SideView extends ViewPart implements IMultiPaneEditor,
ISelectedPanesChangedListener listener) { ISelectedPanesChangedListener listener) {
} }
@Override
public void registerMouseHandler(IInputHandler handler, public void registerMouseHandler(IInputHandler handler,
InputPriority priority) { InputPriority priority) {
paneManager.registerMouseHandler(handler, priority); paneManager.registerMouseHandler(handler, priority);
} }
@Override
public void registerMouseHandler(IInputHandler handler) { public void registerMouseHandler(IInputHandler handler) {
paneManager.registerMouseHandler(handler); paneManager.registerMouseHandler(handler);
} }
@Override
public void unregisterMouseHandler(IInputHandler handler) { public void unregisterMouseHandler(IInputHandler handler) {
paneManager.unregisterMouseHandler(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. * 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. * 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. * This will show the tab as updating in the header and data text controls.
* 07/23/2014 15645 zhao modified checkBasicSyntaxError()
* *
* </pre> * </pre>
* *
@ -2110,19 +2111,29 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
return editorComp; return editorComp;
} }
/** /**
* Check if there is an extra '=' sign in a TAF
* *
* @param doLogMessage * @param doLogMessage
* @return true if error found, otherwise false * @return true if error found, otherwise false
*/ */
private boolean checkBasicSyntaxError(boolean doLogMessage) { private boolean checkBasicSyntaxError(boolean doLogMessage) {
boolean errorFound = false;
String in = editorTafTabComp.getTextEditorControl().getText(); String in = editorTafTabComp.getTextEditorControl().getText();
clearSyntaxErrorLevel(); clearSyntaxErrorLevel();
st = editorTafTabComp.getTextEditorControl(); 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>(); final Map<StyleRange, String> syntaxMap = new HashMap<StyleRange, String>();
st.addMouseTrackListener(new MouseTrackAdapter() { st.addMouseTrackListener(new MouseTrackAdapter() {
@ -2154,66 +2165,36 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
} }
}); });
int tafIndex = in.indexOf("TAF"); String msg = "Syntax error: There is an extra '=' sign or 'TAF' is missing at beginning of TAF";
int equalSignIndex = in.indexOf("="); String[] tafs = in.split("\n\n");
int lastEqualSignIndex = equalSignIndex; int tafStartIndex = 0;
for ( String taf : tafs ) {
if (tafIndex < 0 && equalSignIndex < 0) { // empty TAF int firstEqualSignIndex = taf.indexOf('=');
return false; if ( firstEqualSignIndex == -1 ) {
} tafStartIndex += taf.length() + 2;
continue;
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;
} }
int secondEqualSignIndex = taf.indexOf('=', firstEqualSignIndex+1);
tafIndex = in.indexOf("TAF", tafIndex + 1); if ( secondEqualSignIndex == -1 ) {
lastEqualSignIndex = equalSignIndex; tafStartIndex += taf.length() + 2;
equalSignIndex = in.indexOf("=", equalSignIndex + 1); 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() { 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.Grid2DFloat;
import com.raytheon.uf.common.dataplugin.gfe.grid.Op; 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.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;
import com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable.LockMode; import com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable.LockMode;
import com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable.LockStatus; 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. * Apr 02, 2013 #1774 randerso Fixed a possible deadlock issue.
* Aug 27, 2013 #2302 randerso Fix simultaneous save issue * Aug 27, 2013 #2302 randerso Fix simultaneous save issue
* Oct 31, 2013 #2508 randerso Change to use DiscreteGridSlice.getKeys() * 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> * </pre>
* *
@ -619,21 +622,19 @@ public abstract class Parm implements Comparable<Parm> {
return new TimeRange(); return new TimeRange();
} }
if (!isMutable()) { TimeRange tr = getInventorySpan();
return getInventorySpan();
}
TimeRange tr = new TimeRange(); if (isMutable()) {
if (lockTable != null) { LockTable lt = this.lockTable;
if (lockTable.getLocks().size() > 0) { if (lt != null) {
tr = lockTable.getLocks().get(0).getTimeRange(); List<Lock> locks = lt.getLocks();
} for (Lock lock : locks) {
for (int i = 1; i < lockTable.getLocks().size(); i++) { tr = tr.combineWith(lock.getTimeRange());
tr = tr.combineWith(lockTable.getLocks().get(i).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.Status;
import org.eclipse.core.runtime.jobs.Job; 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; import com.raytheon.uf.common.time.TimeRange;
/** /**
@ -40,6 +42,7 @@ import com.raytheon.uf.common.time.TimeRange;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Aug 27, 2013 #2302 randerso Initial creation * Aug 27, 2013 #2302 randerso Initial creation
* Jun 30, 2014 #3332 randerso Added exception handling
* *
* </pre> * </pre>
* *
@ -48,6 +51,9 @@ import com.raytheon.uf.common.time.TimeRange;
*/ */
public class ParmSaveJob extends Job { public class ParmSaveJob extends Job {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ParmSaveJob.class);
public static class ParmSaveStatus { public static class ParmSaveStatus {
boolean successful = false; boolean successful = false;
@ -127,8 +133,13 @@ public class ParmSaveJob extends Job {
protected IStatus run(IProgressMonitor monitor) { protected IStatus run(IProgressMonitor monitor) {
ParmSaveRequest req = null; ParmSaveRequest req = null;
while ((req = this.saveQueue.poll()) != null) { while ((req = this.saveQueue.poll()) != null) {
boolean successful = parm.saveParameterSubClass(req.times); try {
req.status.setSuccessful(successful); 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; return Status.OK_STATUS;
} }

View file

@ -260,6 +260,7 @@ public class RadarBiasTableDialog extends Dialog {
applyBtn = new Button(applyBtnComp, SWT.PUSH); applyBtn = new Button(applyBtnComp, SWT.PUSH);
applyBtn.setText("Apply"); applyBtn.setText("Apply");
applyBtn.setLayoutData(bd); applyBtn.setLayoutData(bd);
applyBtn.setEnabled(false);
applyBtn.addSelectionListener(new SelectionAdapter() { applyBtn.addSelectionListener(new SelectionAdapter() {
/* /*
@ -274,7 +275,6 @@ public class RadarBiasTableDialog extends Dialog {
applyBiasUpdate(dt); applyBiasUpdate(dt);
MPEDisplayManager mgr = MPEDisplayManager.getCurrent(); MPEDisplayManager mgr = MPEDisplayManager.getCurrent();
mgr.setSavedData(false); mgr.setSavedData(false);
shell.dispose();
} }
}); });
@ -560,7 +560,6 @@ public class RadarBiasTableDialog extends Dialog {
editedSPBiasValue[ai] = oldSPBiasValue[ai]; editedSPBiasValue[ai] = oldSPBiasValue[ai];
spBiasValueTextArray[ai].setText(String.format("%-1.2f", editedSPBiasValue[ai])); spBiasValueTextArray[ai].setText(String.format("%-1.2f", editedSPBiasValue[ai]));
spBiasChangeMap.put(radIds[ai], ai); spBiasChangeMap.put(radIds[ai], ai);
applyBtn.setEnabled(false);
spManEditButtonArray[ai].setText("NO"); 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 6, 2012 13365 rferrel Accumulate and Display fix.
* Sep 25, 2012 1196 lvenable Dialog refactor for AlarmDisplayWindow.Added DO_NOT_BLOCK. * Sep 25, 2012 1196 lvenable Dialog refactor for AlarmDisplayWindow.Added DO_NOT_BLOCK.
* Nov 20, 2013 2488 randerso Changed to use DejaVu font * 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> * </pre>
* *
@ -100,19 +102,13 @@ public class AlarmDisplayWindow extends CaveSWTDialog {
/** /**
* @param parentShell * @param parentShell
* @param prodList
* @param accum_state * @param accum_state
*/ */
protected AlarmDisplayWindow(Shell parentShell, protected AlarmDisplayWindow(Shell parentShell, ACCUMULATE_STATE accum_state) {
java.util.List<StdTextProduct> prodList,
ACCUMULATE_STATE accum_state) {
super(parentShell, SWT.RESIZE, CAVE.PERSPECTIVE_INDEPENDENT super(parentShell, SWT.RESIZE, CAVE.PERSPECTIVE_INDEPENDENT
| CAVE.INDEPENDENT_SHELL | CAVE.DO_NOT_BLOCK); | CAVE.INDEPENDENT_SHELL | CAVE.DO_NOT_BLOCK);
setText("Alarm Display Window"); setText("Alarm Display Window");
prods = prodList; prods = new ArrayList<StdTextProduct>(0);
if (prods == null) {
prods = new ArrayList<StdTextProduct>();
}
this.accum_state = accum_state; this.accum_state = accum_state;
} }
@ -265,6 +261,11 @@ public class AlarmDisplayWindow extends CaveSWTDialog {
populateText(); populateText();
} }
public void setLoading() {
actualText = text.getText();
text.setText("Loading...");
}
public void addText(String msg) { public void addText(String msg) {
if (accumulate) { if (accumulate) {
if (text.getText().isEmpty()) { if (text.getText().isEmpty()) {

View file

@ -24,7 +24,13 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; 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.SWT;
import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent; 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.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.util.Pair;
import com.raytheon.uf.edex.services.textdbsrv.IQueryTransport; 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.core.mode.CAVEMode;
import com.raytheon.viz.texteditor.alarmalert.dialogs.AlarmDisplayWindow.ACCUMULATE_STATE; import com.raytheon.viz.texteditor.alarmalert.dialogs.AlarmDisplayWindow.ACCUMULATE_STATE;
import com.raytheon.viz.texteditor.alarmalert.util.AlarmAlertFunctions; import com.raytheon.viz.texteditor.alarmalert.util.AlarmAlertFunctions;
@ -97,8 +105,10 @@ import com.raytheon.viz.ui.dialogs.ModeListener;
* Alarm Queue" GUI * Alarm Queue" GUI
* Sep 6, 2012 13365 rferrel Accumulate and Display fix. * Sep 6, 2012 13365 rferrel Accumulate and Display fix.
* Sep 25, 2012 1196 lvenable Dialog refactor for AlarmDisplayWindow. * Sep 25, 2012 1196 lvenable Dialog refactor for AlarmDisplayWindow.
* Mar 05,2013 15173 mgamazaychikov The dimensions and location of closed window * Mar 05, 2013 15173 mgamazaychikov The dimensions and location of closed window
* are saved and set on the next open. * 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> * </pre>
* *
@ -142,7 +152,7 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
* Location and dimensions of the dialog on the close. * Location and dimensions of the dialog on the close.
*/ */
private static Point closeLocation = null; private static Point closeLocation = null;
private static Point closeDimensions = null; private static Point closeDimensions = null;
/** /**
@ -151,14 +161,65 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
private boolean canRedraw = true; 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 SHELL_WIDTH = 350;
private static final int INIT_HEIGHT = 200; private static final int INIT_HEIGHT = 200;
private static final int INIT_OFFSET = 15; 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 parentShell
* @param style * @param style
@ -261,12 +322,13 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
shellComp = new Composite(shell, SWT.NONE); shellComp = new Composite(shell, SWT.NONE);
shellComp.setLayout(constructShellLayout()); shellComp.setLayout(constructShellLayout());
shellComp.setLayoutData(gd); shellComp.setLayoutData(gd);
/* /*
* DR15173 - Create a listener to save the location * DR15173 - Create a listener to save the location and dimensions of
* and dimensions of closed window. * closed window.
*/ */
shell.addShellListener(new ShellAdapter() { shell.addShellListener(new ShellAdapter() {
@Override
public void shellClosed(ShellEvent event) { public void shellClosed(ShellEvent event) {
closeLocation = getShell().getLocation(); closeLocation = getShell().getLocation();
closeDimensions = getShell().getSize(); closeDimensions = getShell().getSize();
@ -289,11 +351,13 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
Display.getDefault().asyncExec(new Runnable() { Display.getDefault().asyncExec(new Runnable() {
@Override @Override
public void run() { public void run() {
/* /*
* DR15173 - Enforce that the window width does not exceed the SHELL_WIDTH. * 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); shell.setBounds(location.x, location.y, SHELL_WIDTH,
point.y);
shell.setMinimumSize(SHELL_WIDTH, 0);
canRedraw = true; canRedraw = true;
} }
}); });
@ -302,7 +366,7 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
// Initialize all of the controls and layouts // Initialize all of the controls and layouts
initializeComponents(); initializeComponents();
// Set the shell location and dimensions. // Set the shell location and dimensions.
setShellGeometry(); setShellGeometry();
} }
@ -310,26 +374,25 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
/** /**
* Sets the geometry for the Current Alarm Queue shell * Sets the geometry for the Current Alarm Queue shell
*/ */
private void setShellGeometry() { private void setShellGeometry() {
Rectangle displayArea = shell.getDisplay().getClientArea(); Rectangle displayArea = shell.getDisplay().getClientArea();
int locationX = displayArea.x + INIT_OFFSET; int locationX = displayArea.x + INIT_OFFSET;
int locationY = displayArea.y + INIT_OFFSET; int locationY = displayArea.y + INIT_OFFSET;
int width = SHELL_WIDTH; int width = SHELL_WIDTH;
int height = INIT_HEIGHT; int height = INIT_HEIGHT;
if (CurrentAlarmQueue.closeLocation != null) { if (CurrentAlarmQueue.closeLocation != null) {
locationX = CurrentAlarmQueue.closeLocation.x; locationX = CurrentAlarmQueue.closeLocation.x;
locationY = CurrentAlarmQueue.closeLocation.y; locationY = CurrentAlarmQueue.closeLocation.y;
} }
if (CurrentAlarmQueue.closeDimensions != null) { if (CurrentAlarmQueue.closeDimensions != null) {
height = CurrentAlarmQueue.closeDimensions.y; height = CurrentAlarmQueue.closeDimensions.y;
} }
shell.setMinimumSize(width, height); shell.setMinimumSize(width, height);
shell.setLocation(locationX, locationY); shell.setLocation(locationX, locationY);
return; return;
} }
/**
/**
* Initializes each component of the shell * Initializes each component of the shell
*/ */
private void initializeComponents() { private void initializeComponents() {
@ -421,7 +484,7 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
* Display the selected product the current alarm queue list. * Display the selected product the current alarm queue list.
*/ */
private void displayList() { private void displayList() {
String command = ""; String command = null;
Date refDate = null; Date refDate = null;
if (list != null && list.getItemCount() > 0 if (list != null && list.getItemCount() > 0
&& list.getSelectionCount() > 0 && list.getSelection() != null) { && 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 // Display the Alarm Display Window
if (alarmDisplayDlg == null || alarmDisplayDlg.getShell().isDisposed()) { if (alarmDisplayDlg == null || alarmDisplayDlg.getShell().isDisposed()) {
alarmDisplayDlg = new AlarmDisplayWindow(shell, prods, alarmDisplayDlg = new AlarmDisplayWindow(shell,
ACCUMULATE_STATE.UNCHANGE); ACCUMULATE_STATE.UNCHANGE);
alarmDisplayDlg.setCloseCallback(new ICloseCallback() { alarmDisplayDlg.setCloseCallback(new ICloseCallback() {
@ -458,58 +516,52 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
alarmDisplayDlg.open(); alarmDisplayDlg.open();
} else { } else {
alarmDisplayDlg.setProds(prods);
alarmDisplayDlg.setDialogFocus(); 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. * Display all the products in the alarm queue list and clear the list.
*/ */
private void displayAll() { private void displayAll() {
String[] command = null; String[] command = new String[list.getItemCount()];
if (list != null) { for (int i = 0; i < list.getItemCount(); i++) {
command = new String[list.getItemCount()]; command[i] = list.getItems()[i].split(" ")[0];
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();
} }
// Do a count of how many instances of each command are in
java.util.List<StdTextProduct> prods = new ArrayList<StdTextProduct>(); // the queue.
if (command.length > 0) { Map<String, Integer> counter = new HashMap<String, Integer>();
for (int i = 0; i < command.length; i++) { for (int i = 0; i < command.length; ++i) {
prods.addAll(produceTextProduct(command[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 // Display the Alarm Display Window
if (alarmDisplayDlg == null || alarmDisplayDlg.getShell().isDisposed()) { if (alarmDisplayDlg == null || alarmDisplayDlg.getShell().isDisposed()) {
alarmDisplayDlg = new AlarmDisplayWindow(shell, prods, alarmDisplayDlg = new AlarmDisplayWindow(shell,
ACCUMULATE_STATE.TRUE); ACCUMULATE_STATE.TRUE);
alarmDisplayDlg.setCloseCallback(new ICloseCallback() { alarmDisplayDlg.setCloseCallback(new ICloseCallback() {
@Override @Override
@ -523,10 +575,12 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
}); });
alarmDisplayDlg.open(); alarmDisplayDlg.open();
} else { } else {
alarmDisplayDlg.setProds(prods);
alarmDisplayDlg.setAccumulate(true); alarmDisplayDlg.setAccumulate(true);
alarmDisplayDlg.setDialogFocus(); 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. * Get the product for the given AFOS command and reference time.
* *
@ -591,11 +639,16 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
* @param refTime * @param refTime
* @return prodList * @return prodList
*/ */
private java.util.List<StdTextProduct> produceTextProduct(String command, private java.util.List<StdTextProduct> produceTextProducts(Long refTime,
Long refTime) { String... commands) {
ICommand cmd = CommandFactory.getAfosCommand(command, refTime);
executeCommand(cmd); java.util.List<StdTextProduct> prods = new ArrayList<StdTextProduct>();
return prodList; 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 @Override
public void currentAlarmChanged(CurrentAlarmEvent event) { public void currentAlarmChanged(CurrentAlarmEvent event) {
AlarmAlertProduct aap = (AlarmAlertProduct) event.getSource(); final AlarmAlertProduct aap = (AlarmAlertProduct) event.getSource();
if (!shell.isDisposed() && shell != null) { if (!shell.isDisposed() && shell != null) {
CAVEMode mode = CAVEMode.getMode(); CAVEMode mode = CAVEMode.getMode();
if ((CAVEMode.OPERATIONAL.equals(mode) || CAVEMode.TEST if ((CAVEMode.OPERATIONAL.equals(mode) || CAVEMode.TEST
.equals(mode)) && aap.getOperationalMode()) { .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.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.localization.LocalizationManager; import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.viz.texteditor.alarmalert.dialogs.AlarmAlertBell; import com.raytheon.viz.texteditor.alarmalert.dialogs.AlarmAlertBell;
import com.raytheon.viz.texteditor.command.CommandFactory; 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. * 03/19/2012 D. Friedman Fix determination of "Alarm" entries.
* 12/07/2012 15555 m.gamazaychikov Added methods and constants for * 12/07/2012 15555 m.gamazaychikov Added methods and constants for
* the implementation of proximity alarm * the implementation of proximity alarm
* 07/24/2014 3423 randerso Ensure ringBell is called on UI thread
* *
* </pre> * </pre>
* *
@ -211,14 +213,16 @@ public class AlarmAlertFunctions {
match = true; match = true;
} }
if (match) { if (match) {
if (productFound == null) if (productFound == null) {
productFound = p; productFound = p;
}
if ("Alarm".equals(p.getAlarmType()) && p.isAlarm()) { if ("Alarm".equals(p.getAlarmType()) && p.isAlarm()) {
alarm = true; alarm = true;
productFound = p; productFound = p;
} }
if (alarm) if (alarm) {
break; break;
}
} }
} }
} }
@ -229,7 +233,14 @@ public class AlarmAlertFunctions {
instance.getCurrentAlarms().add(prod); instance.getCurrentAlarms().add(prod);
instance.fireNewCurrentAlarmEvent(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.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.notification.INotificationObserver; import com.raytheon.uf.viz.core.notification.INotificationObserver;
import com.raytheon.uf.viz.core.notification.NotificationMessage; import com.raytheon.uf.viz.core.notification.NotificationMessage;
import com.raytheon.uf.viz.core.notification.jobs.NotificationManagerJob; import com.raytheon.uf.viz.core.notification.jobs.NotificationManagerJob;
import com.raytheon.viz.core.mode.CAVEMode; import com.raytheon.viz.core.mode.CAVEMode;
/** /**
* TODO Add Description * Alarm Alert Notification Observer
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* Date Ticket# Engineer Description * 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. * 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> * </pre>
* *
@ -108,7 +108,8 @@ public class AlarmAlertNotificationObserver implements INotificationObserver {
} }
if (run != null) { if (run != null) {
VizApp.runAsync(run); Thread thread = new Thread(run);
thread.start();
} }
} catch (Exception e) { } catch (Exception e) {
statusHandler.handle(Priority.PROBLEM, statusHandler.handle(Priority.PROBLEM,

View file

@ -21,6 +21,7 @@ package com.raytheon.viz.warngen.gis;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; 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;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.exception.VizException; 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.gui.WarngenLayer;
import com.raytheon.viz.warngen.util.Abbreviation; import com.raytheon.viz.warngen.util.Abbreviation;
import com.vividsolutions.jts.geom.Geometry; 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. * Dec 4, 2013 2604 jsanchez Refactored GisUtil and PortionsUtil.
* Apr 29, 2014 3033 jsanchez Updated method to retrieve files in localization. * 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. * 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> * </pre>
* *
* @author chammack * @author chammack
@ -94,6 +99,10 @@ public class Area {
*/ */
public static final double DEFAULT_PORTION_TOLERANCE = 0.60; 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; private PortionsUtil portionsUtil;
public Area(PortionsUtil portionsUtil) { public Area(PortionsUtil portionsUtil) {
@ -181,6 +190,7 @@ public class Area {
} }
List<String> uniqueFips = new ArrayList<String>(); List<String> uniqueFips = new ArrayList<String>();
List<String> uniqueCountyname = new ArrayList<String>();
List<AffectedAreas> areas = new ArrayList<AffectedAreas>(); List<AffectedAreas> areas = new ArrayList<AffectedAreas>();
for (GeospatialData regionFeature : countyMap.values()) { for (GeospatialData regionFeature : countyMap.values()) {
Geometry regionGeom = regionFeature.geometry; Geometry regionGeom = regionFeature.geometry;
@ -260,8 +270,14 @@ public class Area {
area.points = pointList.toArray(new String[pointList.size()]); 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); uniqueFips.add(area.fips);
if (countyName != null) {
uniqueCountyname.add(countyName);
}
areas.add(area); areas.add(area);
} }
} }
@ -297,7 +313,8 @@ public class Area {
Map<String, Object> areasMap = new HashMap<String, Object>(); Map<String, Object> areasMap = new HashMap<String, Object>();
try { try {
Geometry precisionReducedArea = PolygonUtil.reducePrecision(warnArea); Geometry precisionReducedArea = PolygonUtil
.reducePrecision(warnArea);
if (precisionReducedArea.isValid()) { if (precisionReducedArea.isValid()) {
warnArea = precisionReducedArea; warnArea = precisionReducedArea;
} }
@ -335,66 +352,41 @@ public class Area {
public static List<String> converFeAreaToPartList(String feArea) { public static List<String> converFeAreaToPartList(String feArea) {
final List<String> partList = new ArrayList<String>(); final List<String> partList = new ArrayList<String>();
if (feArea == null) { if (feArea != null) {
// Marine warnings feArea = feArea.toUpperCase();
partList.add(""); if (SPECIAL_CASE_FE_AREAS.contains(feArea)) {
} else { partList.add(feArea);
if (feArea.equals("pa")) } else {
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 {
for (int i = 0; i < feArea.length(); i++) { for (int i = 0; i < feArea.length(); i++) {
char c = feArea.charAt(i); char c = feArea.charAt(i);
Direction direction = null;
switch (c) { switch (c) {
case 'c':
partList.add("CENTRAL"); case 'C':
direction = Direction.CENTRAL;
break; break;
case 'w': case 'W':
partList.add("WEST"); direction = Direction.WEST;
break; break;
case 'n': case 'N':
partList.add("NORTH"); direction = Direction.NORTH;
break; break;
case 'e': case 'E':
partList.add("EAST"); direction = Direction.EAST;
break; break;
case 's': case 'S':
partList.add("SOUTH"); direction = Direction.SOUTH;
break; break;
default: default:
break; break;
} }
if (direction != null) {
partList.add(direction.toString());
}
} }
} }
} }
return partList; 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. * 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. * 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. * 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> * </pre>
* *
* @author mschenke * @author mschenke
@ -417,12 +420,15 @@ public class PolygonUtil {
p1--; p1--;
if (p1 >= 0) { if (p1 >= 0) {
Coordinate last = new Coordinate();
int n, best1, best2; int n, best1, best2;
for (n = k = 0; k < npoints; k++) { for (n = k = 0; k < npoints; k++) {
if (match[k] == nv) if (match[k] == nv)
continue; continue;
best1 = match[p1]; best1 = match[p1];
best2 = match[k]; best2 = match[k];
last.x = longest[p1].x;
last.y = longest[p1].y;
p1 = k; p1 = k;
if (best1 < 0 && best2 < 0) { if (best1 < 0 && best2 < 0) {
if (k == n) if (k == n)
@ -460,16 +466,59 @@ public class PolygonUtil {
best1 += nv; best1 += nv;
else if (dn - da < -len2) else if (dn - da < -len2)
best2 += nv; 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++) { for (best1++; best1 <= best2; best1++) {
fixed[n] = 1; fixed[n] = 1;
longest[n++] = new Coordinate(vert[best1]); longest[n++] = new Coordinate(vert[best1]);
} }
else } else {
for (; best1 > best2; best1--) { for (; best1 > best2; best1--) {
fixed[n] = 1; fixed[n] = 1;
longest[n++] = new Coordinate(vert[best1]); longest[n++] = new Coordinate(vert[best1]);
} }
}
continue; continue;
} }
fixed[n] = 1; fixed[n] = 1;
@ -1670,11 +1719,11 @@ public class PolygonUtil {
} }
return slope; return slope;
} }
/** /**
* Create a polygon whose two diagonal coordinates are a and b. * 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; double maxX, minX, maxY, minY;
maxX = Math.max(a.x, b.x); maxX = Math.max(a.x, b.x);
minX = Math.min(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[2] = new Coordinate(maxX, maxY);
coord[3] = new Coordinate(minX, maxY); coord[3] = new Coordinate(minX, maxY);
coord[4] = new Coordinate(coord[0]); coord[4] = new Coordinate(coord[0]);
GeometryFactory gf = new GeometryFactory();
LinearRing lr = gf.createLinearRing(coord); LinearRing lr = gf.createLinearRing(coord);
return gf.createPolygon(lr, null); 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 /** Creates a copy of a Geometry with reduced precision to reduce the chance of topology errors when used
* in intersection operations. * 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 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. * 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. * 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> * </pre>
* *
* @author chammack * @author chammack
@ -166,6 +168,12 @@ public class WarngenDialog extends CaveSWTDialog implements
private static final transient IUFStatusHandler statusHandler = UFStatus private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(WarngenDialog.class); .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_WIDTH = 390;
private static final int BULLET_HEIGHT = 230; private static final int BULLET_HEIGHT = 230;
@ -484,30 +492,39 @@ public class WarngenDialog extends CaveSWTDialog implements
* @param productType2 * @param productType2
*/ */
private void createOtherProductsList(Group productType2) { private void createOtherProductsList(Group productType2) {
other = new Button(productType, SWT.RADIO); if (other == null) {
other.setText("Other:"); other = new Button(productType, SWT.RADIO);
other.setEnabled(true); other.setText("Other:");
other.addSelectionListener(new SelectionAdapter() { other.setEnabled(true);
other.addSelectionListener(new SelectionAdapter() {
@Override @Override
public void widgetSelected(SelectionEvent arg0) { public void widgetSelected(SelectionEvent arg0) {
otherSelected(); 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); updateOtherProductList(otherProductListCbo);
otherProductListCbo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
otherProductSelected();
}
});
} }
private void createMainProductButtons(Group productType) { private void createMainProductButtons(Group productType) {
@ -519,12 +536,13 @@ public class WarngenDialog extends CaveSWTDialog implements
mainProducts.add(str); mainProducts.add(str);
} }
String defaultTemplate = warngenLayer.getDialogConfig() String defaultTemplate = getDefaultTemplate();
.getDefaultTemplate();
if ((defaultTemplate == null) || defaultTemplate.equals("")) {
defaultTemplate = mainProducts.get(0).split("/")[1];
}
if (mainProductBtns != null) {
for (Button button : mainProductBtns) {
button.dispose();
}
}
mainProductBtns = new Button[mainProducts.size()]; mainProductBtns = new Button[mainProducts.size()];
if (mainProducts.size() > 0) { if (mainProducts.size() > 0) {
@ -540,24 +558,29 @@ public class WarngenDialog extends CaveSWTDialog implements
mainProductBtns[0].addSelectionListener(new SelectionAdapter() { mainProductBtns[0].addSelectionListener(new SelectionAdapter() {
@Override @Override
public void widgetSelected(SelectionEvent e) { 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); GridData gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false);
gd.horizontalIndent = 30; if (updateListCbo == null) {
updateListCbo = new Combo(productType, SWT.READ_ONLY | SWT.DROP_DOWN); gd.horizontalIndent = 30;
updateListCbo.setLayoutData(gd); updateListCbo = new Combo(productType, SWT.READ_ONLY
recreateUpdates(); | SWT.DROP_DOWN);
updateListCbo.setLayoutData(gd);
recreateUpdates();
updateListCbo.addSelectionListener(new SelectionAdapter() { updateListCbo.addSelectionListener(new SelectionAdapter() {
@Override @Override
public void widgetSelected(SelectionEvent arg0) { public void widgetSelected(SelectionEvent arg0) {
updateListSelected(); updateListSelected();
} }
}); });
} else if (mainProductBtns.length > 0) {
updateListCbo.moveBelow(mainProductBtns[0]);
}
for (int cnt = 1; cnt < mainProducts.size(); cnt++) { for (int cnt = 1; cnt < mainProducts.size(); cnt++) {
final String[] tmp = mainProducts.get(cnt).split("/"); 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); 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, redrawFrom.setLayoutData(new GridData(SWT.DEFAULT, SWT.FILL, false,
true)); true));
@ -651,9 +675,30 @@ public class WarngenDialog extends CaveSWTDialog implements
damBreakThreatArea.addSelectionListener(new SelectionAdapter() { damBreakThreatArea.addSelectionListener(new SelectionAdapter() {
@Override @Override
public void widgetSelected(SelectionEvent e) { 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) { private void createBackupTrackEditGroups(Composite mainComposite) {
@ -683,7 +728,7 @@ public class WarngenDialog extends CaveSWTDialog implements
backupGroup.setLayout(new GridLayout(2, false)); backupGroup.setLayout(new GridLayout(2, false));
Label label2 = new Label(backupGroup, SWT.BOLD); Label label2 = new Label(backupGroup, SWT.BOLD);
label2.setText("Full:"); label2.setText("WFO:");
label2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); label2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
backupSiteCbo = new Combo(backupGroup, SWT.READ_ONLY | SWT.DROP_DOWN); backupSiteCbo = new Combo(backupGroup, SWT.READ_ONLY | SWT.DROP_DOWN);
backupSiteCbo.addSelectionListener(new SelectionAdapter() { backupSiteCbo.addSelectionListener(new SelectionAdapter() {
@ -1195,7 +1240,11 @@ public class WarngenDialog extends CaveSWTDialog implements
setInstructions(); setInstructions();
} else if (bulletListManager.isDamNameSeletcted() } else if (bulletListManager.isDamNameSeletcted()
&& bulletListManager.isDamCauseSelected()) { && bulletListManager.isDamCauseSelected()) {
damBreakThreatAreaPressed(); DamInfoBullet damBullet = bulletListManager
.getSelectedDamInfoBullet();
if (damBullet != null) {
damBreakThreatAreaPressed(damBullet.getCoords(), true);
}
if (damBreakInstruct != null) { if (damBreakInstruct != null) {
return false; return false;
} }
@ -1323,9 +1372,28 @@ public class WarngenDialog extends CaveSWTDialog implements
} else { } else {
new TemplateRunnerInitJob(backupSite).schedule(); 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) { 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 * Responsible for drawing a pre-defined warning polygon (coords) on the
* the WarnGen layer. The method is called when a drainage basin is selected * WarnGen layer.
* 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.
* *
* @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" damBreakInstruct = "Either no dam selected, no dam info bullets in .xml file, or no\n"
+ "dam break primary cause selected."; + "dam break primary cause selected.";
DamInfoBullet damBullet = bulletListManager.getSelectedDamInfoBullet();
if (damBullet != null) {
if ((damBullet.getCoords() == null) if ((coords == null) || (coords.length() == 0)) {
|| (damBullet.getCoords().length() == 0)) { damBreakInstruct = "LAT...LON can not be found in 'coords' parameter";
damBreakInstruct = "LAT...LON can not be found in 'coords' parameter"; } else {
} else { ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>();
ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>(); Pattern coordinatePtrn = Pattern
Pattern coordinatePtrn = Pattern .compile("LAT...LON+(\\s\\d{3,4}\\s\\d{3,5}){1,}");
.compile("LAT...LON+(\\s\\d{3,4}\\s\\d{3,5}){1,}"); Pattern latLonPtrn = Pattern.compile("\\s(\\d{3,4})\\s(\\d{3,5})");
Pattern latLonPtrn = Pattern
.compile("\\s(\\d{3,4})\\s(\\d{3,5})");
Matcher m = coordinatePtrn.matcher(damBullet.getCoords()); Matcher m = coordinatePtrn.matcher(coords);
if (m.find()) { if (m.find()) {
m = latLonPtrn.matcher(damBullet.getCoords()); m = latLonPtrn.matcher(coords);
while (m.find()) { while (m.find()) {
coordinates.add(new Coordinate((-1 * Double coordinates.add(new Coordinate((-1 * Double.parseDouble(m
.parseDouble(m.group(2))) / 100, Double .group(2))) / 100,
.parseDouble(m.group(1)) / 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.";
} }
}
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) { if (damBreakInstruct != null) {
setInstructions(); setInstructions();
@ -1490,6 +1553,19 @@ public class WarngenDialog extends CaveSWTDialog implements
return result; 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 * 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 * 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) { private void changeTemplate(String templateName) {
// DR 14515
if (templateName.equals(warngenLayer.getTemplateName())) {
return;
}
String lastAreaSource = warngenLayer.getConfiguration() String lastAreaSource = warngenLayer.getConfiguration()
.getHatchedAreaSource().getAreaSource(); .getHatchedAreaSource().getAreaSource();
@ -1641,6 +1712,7 @@ public class WarngenDialog extends CaveSWTDialog implements
otherProducts = new HashMap<String, String>(); otherProducts = new HashMap<String, String>();
String[] otherProductsStr = warngenLayer.getDialogConfig() String[] otherProductsStr = warngenLayer.getDialogConfig()
.getOtherWarngenProducts().split(","); .getOtherWarngenProducts().split(",");
theList.removeAll();
for (String str : otherProductsStr) { for (String str : otherProductsStr) {
String[] s = str.split("/"); String[] s = str.split("/");
otherProducts.put(s[0], s[1]); otherProducts.put(s[0], s[1]);
@ -1791,7 +1863,7 @@ public class WarngenDialog extends CaveSWTDialog implements
templateName = otherProducts.get(otherProductListCbo templateName = otherProducts.get(otherProductListCbo
.getItem(otherProductListCbo.getSelectionIndex())); .getItem(otherProductListCbo.getSelectionIndex()));
} }
changeTemplate(templateName); uiChangeTemplate(templateName);
otherProductListCbo.pack(true); otherProductListCbo.pack(true);
productType.layout(); productType.layout();
@ -2258,7 +2330,7 @@ public class WarngenDialog extends CaveSWTDialog implements
templateName = otherProducts.get(otherProductListCbo templateName = otherProducts.get(otherProductListCbo
.getItem(otherProductListCbo.getSelectionIndex())); .getItem(otherProductListCbo.getSelectionIndex()));
} }
changeTemplate(templateName); uiChangeTemplate(templateName);
} }
private void refreshDisplay() { private void refreshDisplay() {
@ -2510,4 +2582,13 @@ public class WarngenDialog extends CaveSWTDialog implements
warngenLayer.issueRefresh(); 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

@ -213,6 +213,9 @@ import com.vividsolutions.jts.io.WKTReader;
* 04/28,2014 3033 jsanchez Properly handled back up configuration (*.xml) files. Set backupSite to null when backup site is not selected. * 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. * 05/16/2014 DR 17365 D. Friedman Check if moved vertex results in polygon valid in both lat/lon and local coordinates.
* 06/23/2014 DR16322 m.gamazaychikov Fix Warngen unloading previously loaded maps. * 06/23/2014 DR16322 m.gamazaychikov Fix Warngen unloading previously loaded maps.
* 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> * </pre>
* *
* @author mschenke * @author mschenke
@ -225,6 +228,9 @@ public class WarngenLayer extends AbstractStormTrackResource {
String uniqueFip = null; 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 class GeospatialDataList {
private static final String LOCAL_GEOM = "localGeometry"; private static final String LOCAL_GEOM = "localGeometry";
@ -1107,6 +1113,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
DrawableString string = new DrawableString(text, textColor); DrawableString string = new DrawableString(text, textColor);
string.magnification = magnification; string.magnification = magnification;
string.setCoordinates(out[0], out[1]); string.setCoordinates(out[0], out[1]);
string.horizontalAlignment = IGraphicsTarget.HorizontalAlignment.CENTER;
string.verticallAlignment = IGraphicsTarget.VerticalAlignment.MIDDLE;
strings.add(string); strings.add(string);
} }
} }
@ -1190,6 +1198,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
}// end synchronize }// end synchronize
customMaps.loadCustomMaps(Arrays.asList(config.getMaps())); customMaps.loadCustomMaps(Arrays.asList(config.getMaps()));
createAreaAndCentroidMaps();
this.configuration = config; this.configuration = config;
System.out.println("Total time to init warngen config = " System.out.println("Total time to init warngen config = "
+ (System.currentTimeMillis() - t0) + "ms"); + (System.currentTimeMillis() - t0) + "ms");
@ -1392,6 +1402,49 @@ public class WarngenLayer extends AbstractStormTrackResource {
} else { } else {
backupSite = site; 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() { public String getLocalizedSite() {
@ -3162,66 +3215,127 @@ public class WarngenLayer extends AbstractStormTrackResource {
toKeep.toArray(new Geometry[0])); 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 * Populate the W strings with the included counties
*/ */
private void populateStrings() { private void populateStrings() {
state.strings.clear(); state.strings.clear();
Geometry warningArea = state.getWarningArea();
Set<String> prefixes = new HashSet<String>(Arrays.asList(GeometryUtil Set<String> prefixes = new HashSet<String>(Arrays.asList(GeometryUtil
.getGID(state.getWarningArea()))); .getGID(warningArea)));
prefixes = removeDuplicateGid(prefixes); prefixes = removeDuplicateGid(prefixes);
for (GeospatialData f : geoData.features) { Set<Integer> indexes = new HashSet<Integer>();
Geometry geom = f.geometry; String prefixM, prefixN;
Geometry geom2 = null; double areaM, areaN, maxArea = -1.0;
Geometry warningAreaN = null; int geomIndex = -1;
Coordinate populatePt = null; int geomNum = warningArea.getNumGeometries();
Geometry populatePtGeom; // Find an unique index for each county in warningArea. If there is more than one index
boolean contained = false, closeTo = false; // for one county, find the one with max area.
double shift = 1.E-8, distance, minDistance = 10.0; Geometry warningAreaM = null, warningAreaN = null;
int loop, maxLoop = 10; for (int i = 0; i < geomNum; i++) {
Geometry warningArea = state.getWarningArea(); warningAreaM = warningArea.getGeometryN(i);
String prefix = GeometryUtil.getPrefix(geom.getUserData()); prefixM = GeometryUtil.getPrefix(warningAreaM.getUserData());
if (prefixes.contains(prefix)) { if (!prefixes.contains(prefixM)) {
loop = 0; continue;
warningAreaN = findLargestGeometry(GeometryUtil.intersection(geom, warningArea)); }
do { areaM = warningAreaM.getArea();
if (!warningAreaN.isEmpty()) { geomIndex = i;
populatePt = GisUtil.d2dCoordinate(warningAreaN.getCentroid() while (i + 1 < geomNum) {
.getCoordinate()); warningAreaN = warningArea.getGeometryN(i + 1);
for (GeospatialData f2 : geoData.features) { prefixN = GeometryUtil.getPrefix(warningAreaN.getUserData());
geom2 = f2.getGeometry(); if (prefixN.equals(prefixM)) {
if (!GeometryUtil.getPrefix(geom2.getUserData()).equals(prefix)) { areaN = warningAreaN.getArea();
contained = false; if (areaN > areaM) {
closeTo = false; if (areaN > maxArea) {
populatePtGeom = PolygonUtil.createPolygonByPoints(populatePt, maxArea = areaN;
new Coordinate(populatePt.x + shift, populatePt.y + shift)); geomIndex = i + 1;
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;
}
}
}
} }
} else { } else {
// use the existing populatePt if (areaM > maxArea) {
break; maxArea = areaM;
}
} }
loop += 1; } else {
} while ((contained || closeTo) && loop <= maxLoop); break;
state.strings.put(populatePt, "W"); }
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) { public boolean featureProduct(Coordinate c) {
@ -3498,21 +3612,6 @@ public class WarngenLayer extends AbstractStormTrackResource {
* A Geometry or a GeometryCollection. * A Geometry or a GeometryCollection.
* @return Geometry * @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. * Split the hatched area into four quadrants, and return the largest one.
@ -3523,10 +3622,10 @@ public class WarngenLayer extends AbstractStormTrackResource {
* The geometry of a county/zone. * The geometry of a county/zone.
* @return Geometry * @return Geometry
* The geometey of largest quadrant among the four, which are the result of * 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) { private Geometry findLargestQuadrant(GeometryFactory gf, Geometry geom) {
Geometry envelope = hatchedArea.getEnvelope(); Geometry envelope = geom.getEnvelope();
Coordinate centroidCoord = GisUtil.d2dCoordinate(envelope.getCentroid() Coordinate centroidCoord = GisUtil.d2dCoordinate(envelope.getCentroid()
.getCoordinate()); .getCoordinate());
Coordinate[] envCoords = envelope.getCoordinates(); Coordinate[] envCoords = envelope.getCoordinates();
@ -3536,19 +3635,22 @@ public class WarngenLayer extends AbstractStormTrackResource {
double largestArea = -1.0, area = -1.0; double largestArea = -1.0, area = -1.0;
int index = -1; int index = -1;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
quadrants[i] = PolygonUtil.createPolygonByPoints(envCoords[i], centroidCoord); quadrants[i] = PolygonUtil.createPolygonByPoints(gf, envCoords[i], centroidCoord);
intersections[i] = GeometryUtil.intersection(quadrants[i], hatchedArea); try {
area = intersections[i].getArea(); intersections[i] = GeometryUtil.intersection(quadrants[i], geom);
if (area > largestArea) { area = intersections[i].getArea();
largestArea = area; if (area > largestArea) {
index = i; largestArea = area;
index = i;
}
} catch (Exception e) {
;
} }
} }
if (intersections[index].isValid()) if (null != intersections[index] && intersections[index].isValid())
return intersections[index]; return intersections[index];
else { else {
// "intersections[" + index + "] is invalid" return geom;
return hatchedArea;
} }
} }
@ -3564,4 +3666,5 @@ public class WarngenLayer extends AbstractStormTrackResource {
StormTrackState.trackType = "lineOfStorms"; StormTrackState.trackType = "lineOfStorms";
} }
} }
} }

View file

@ -37,42 +37,25 @@ import java.util.Hashtable;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.TreeMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; 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.Template;
import org.apache.velocity.VelocityContext; import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity; import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.tools.generic.ListTool; 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.AbstractWarningRecord;
import com.raytheon.uf.common.dataplugin.warning.WarningConstants; import com.raytheon.uf.common.dataplugin.warning.WarningConstants;
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction; 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.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.GisUtil;
import com.raytheon.uf.common.dataplugin.warning.portions.PortionsUtil; import com.raytheon.uf.common.dataplugin.warning.portions.PortionsUtil;
import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil; 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.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext; import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.localization.LocalizationContext.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.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime; import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.SimulatedTime; 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.common.util.FileUtil;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.localization.LocalizationManager; 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.ToolsDataManager;
import com.raytheon.viz.awipstools.common.StormTrackData; import com.raytheon.viz.awipstools.common.StormTrackData;
import com.raytheon.viz.awipstools.common.stormtrack.StormTrackState; 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.Area;
import com.raytheon.viz.warngen.gis.ClosestPointComparator; import com.raytheon.viz.warngen.gis.ClosestPointComparator;
import com.raytheon.viz.warngen.gis.PathCast; 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.gis.Wx;
import com.raytheon.viz.warngen.gui.BackupData; import com.raytheon.viz.warngen.gui.BackupData;
import com.raytheon.viz.warngen.gui.FollowupData; 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.FipsUtil;
import com.raytheon.viz.warngen.util.FollowUpUtil; import com.raytheon.viz.warngen.util.FollowUpUtil;
import com.raytheon.viz.warngen.util.WarnGenMathTool; 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.raytheon.viz.warnings.DateUtil;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry; 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 * Mar 17, 2014 DR 16309 Qinglu Lin Updated getWatches(), processATEntries() and determineAffectedPortions(), and
* added determineAffectedMarinePortions(). * added determineAffectedMarinePortions().
* Apr 28, 2014 3033 jsanchez Set the site and backup site in Velocity Engine's properties * Apr 28, 2014 3033 jsanchez Set the site and backup site in Velocity Engine's properties
* Jul 21, 2014 3419 jsanchez Refactored WatchUtil.
* </pre> * </pre>
* *
* @author njensen * @author njensen
@ -172,16 +153,13 @@ public class TemplateRunner {
private static final String LOGIN_NAME_KEY = "LOGNAME"; 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 private static final Pattern BBB_PATTERN = Pattern
.compile(".*\\sCC([A-Z])"); .compile(".*\\sCC([A-Z])");
private static Hashtable<String, DateFormat> dateFormat; private static Hashtable<String, DateFormat> dateFormat;
private static WatchUtil watchUtil;
static { static {
dateFormat = new Hashtable<String, DateFormat>(); dateFormat = new Hashtable<String, DateFormat>();
dateFormat dateFormat
@ -876,11 +854,14 @@ public class TemplateRunner {
// Store Watches // Store Watches
try { try {
t0 = System.currentTimeMillis(); t0 = System.currentTimeMillis();
WatchUtil watches = getWatches(warngenLayer, config, warnPolygon, if (watchUtil == null) {
areas, fourLetterSiteId, simulatedTime); watchUtil = new WatchUtil(warngenLayer);
}
List<Watch> watches = watchUtil.getWatches(config, warnPolygon,
simulatedTime);
System.out.println("getWatches time: " System.out.println("getWatches time: "
+ (System.currentTimeMillis() - t0)); + (System.currentTimeMillis() - t0));
if (watches != null) { if (watches != null && watches.isEmpty() == false) {
context.put("watches", watches); context.put("watches", watches);
} }
} catch (Exception e) { } catch (Exception e) {
@ -980,574 +961,4 @@ public class TemplateRunner {
return rval; 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> </doTry>
</route> </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> </camelContext>
<bean factory-bean="contextManager" factory-method="registerClusteredContext"> <bean factory-bean="contextManager" factory-method="registerClusteredContext">

View file

@ -101,7 +101,7 @@ import com.raytheon.uf.edex.database.purge.PurgeLogger;
* D2DGridDatabase constructor * D2DGridDatabase constructor
* 04/23/13 #1949 rjpeter Added inventory retrieval for a given time range. * 04/23/13 #1949 rjpeter Added inventory retrieval for a given time range.
* 05/02/13 #1969 randerso Fixed possible null pointer in getParmList * 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/03/13 #1974 randerso Fixed error logging to include stack trace
* 05/14/13 #2004 randerso Added methods to synch GridParmManager across JVMs * 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. * 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. * the same parm simultaneously.
* Added code to check the purge times when publishing and not publish * Added code to check the purge times when publishing and not publish
* data that is eligible to be purged. * 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> * </pre>
* *
* @author bphillip * @author bphillip
@ -172,7 +175,7 @@ public class GridParmManager {
this.lockMgr.setGridParmMgr(this); this.lockMgr.setGridParmMgr(this);
initializeManager(); initializeManager();
} }
/** /**
* Dispose the GridParmManager * Dispose the GridParmManager
@ -199,7 +202,7 @@ public class GridParmManager {
.debug("No matching GridDatabase for requested ParmID in createParm()"); .debug("No matching GridDatabase for requested ParmID in createParm()");
// TODO: should we return null? // TODO: should we return null?
return new GridParm(); return new GridParm();
} }
} }
/** /**
@ -330,10 +333,10 @@ public class GridParmManager {
for (SaveGridRequest req : saveRequest) { for (SaveGridRequest req : saveRequest) {
ServerResponse<?> ssr = null; ServerResponse<?> ssr = null;
GridParm gp = null; GridParm gp = null;
gp = gridParm(req.getParmId()); gp = gridParm(req.getParmId());
if (!gp.isValid()) { if (!gp.isValid()) {
sr.addMessage("Unknown Parm: " + req.getParmId() sr.addMessage("Unknown Parm: " + req.getParmId()
+ " in saveGridData()"); + " in saveGridData()");
statusHandler.error("Unknown Parm: " + req.getParmId() statusHandler.error("Unknown Parm: " + req.getParmId()
+ " in saveGridData()"); + " in saveGridData()");
continue; continue;
@ -455,27 +458,27 @@ public class GridParmManager {
// for the source data // for the source data
ParmID sourceParmId = req.getParmId(); ParmID sourceParmId = req.getParmId();
GridParm sourceGP = gridParm(sourceParmId); GridParm sourceGP = gridParm(sourceParmId);
if (!sourceGP.isValid()) { if (!sourceGP.isValid()) {
ssr.addMessage("Unknown Source Parm: " + req.getParmId() ssr.addMessage("Unknown Source Parm: " + req.getParmId()
+ " in commitGrid()"); + " in commitGrid()");
srDetailed.addMessages(ssr); srDetailed.addMessages(ssr);
failures.add(req); failures.add(req);
continue; continue;
} }
// for the destination data // for the destination data
ParmID destParmId = new ParmID(req.getParmId().getParmName(), ParmID destParmId = new ParmID(req.getParmId().getParmName(),
officialDBid, req.getParmId().getParmLevel()); officialDBid, req.getParmId().getParmLevel());
String destParmIdStr = destParmId.toString(); String destParmIdStr = destParmId.toString();
GridParm destGP = null; GridParm destGP = null;
destGP = gridParm(destParmId); destGP = gridParm(destParmId);
if (!destGP.isValid()) { if (!destGP.isValid()) {
ssr.addMessage("Unknown Destination Parm: " + destGP ssr.addMessage("Unknown Destination Parm: " + destGP
+ " in commitGrid()"); + " in commitGrid()");
srDetailed.addMessages(ssr); srDetailed.addMessages(ssr);
failures.add(req); failures.add(req);
continue; continue;
} }
// verify that the source and destination are matched // verify that the source and destination are matched
GridParmInfo sourceInfo, destInfo; GridParmInfo sourceInfo, destInfo;
@ -519,17 +522,17 @@ public class GridParmManager {
publishTime.setStart(startTime); publishTime.setStart(startTime);
} }
inventoryTimer.start(); inventoryTimer.start();
ServerResponse<List<TimeRange>> invSr = sourceGP ServerResponse<List<TimeRange>> invSr = sourceGP
.getGridInventory(publishTime); .getGridInventory(publishTime);
List<TimeRange> overlapInventory = invSr.getPayload(); List<TimeRange> overlapInventory = invSr.getPayload();
ssr.addMessages(invSr); ssr.addMessages(invSr);
if (!ssr.isOkay()) { if (!ssr.isOkay()) {
ssr.addMessage("GetGridInventory for source for commitGrid() failure: " ssr.addMessage("GetGridInventory for source for commitGrid() failure: "
+ ssr.message()); + ssr.message());
srDetailed.addMessages(ssr); srDetailed.addMessages(ssr);
failures.add(req); failures.add(req);
} }
// expand publish time to span overlapping inventory // expand publish time to span overlapping inventory
if (!overlapInventory.isEmpty()) { if (!overlapInventory.isEmpty()) {
@ -546,173 +549,173 @@ public class GridParmManager {
} }
invSr = destGP.getGridInventory(publishTime); invSr = destGP.getGridInventory(publishTime);
inventoryTimer.stop(); inventoryTimer.stop();
List<TimeRange> destInventory = invSr.getPayload(); List<TimeRange> destInventory = invSr.getPayload();
ssr.addMessages(invSr); 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);
if (!ssr.isOkay()) { if (!ssr.isOkay()) {
ssr.addMessage("GetGridData for official for commidtGrid() failure: " ssr.addMessage("GetGridInventory for destination for commitGrid() failure: "
+ ssr.message()); + ssr.message());
srDetailed.addMessages(ssr); srDetailed.addMessages(ssr);
failures.add(req); failures.add(req);
continue; continue;
} }
// insert the grid into the "sourceGrid" list // get the source grid data
for (int t = 0; t < officialTR.size(); t++) { List<IGridSlice> sourceData = null;
// before List<TimeRange> badGridTR = new ArrayList<TimeRange>();
try {
if (officialTR.get(t).getStart() // System.out.println("overlapInventory initial size "
.before(publishTime.getStart())) { // + 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) IGridSlice tempSlice = officialData.get(t)
.clone(); .clone();
tempSlice.setValidTime(new TimeRange(officialTR tempSlice.setValidTime(new TimeRange(officialTR
.get(t).getStart(), publishTime .get(t).getStart(), publishTime
.getStart())); .getStart()));
sourceData.add(0, tempSlice); sourceData.add(0, tempSlice);
publishTime.setStart(officialTR.get(t) publishTime.setStart(officialTR.get(t)
.getStart()); .getStart());
overlapInventory.add(tempSlice.getValidTime()); overlapInventory.add(tempSlice.getValidTime());
} }
// after // after
if (officialTR.get(t).getEnd() if (officialTR.get(t).getEnd()
.after(publishTime.getEnd())) { .after(publishTime.getEnd())) {
IGridSlice tempSlice = officialData.get(t) IGridSlice tempSlice = officialData.get(t)
.clone(); .clone();
tempSlice.setValidTime(new TimeRange( tempSlice.setValidTime(new TimeRange(
publishTime.getEnd(), officialTR.get(t) publishTime.getEnd(), officialTR.get(t)
.getEnd())); .getEnd()));
sourceData.add(tempSlice); sourceData.add(tempSlice);
publishTime.setEnd(officialTR.get(t).getEnd()); publishTime.setEnd(officialTR.get(t).getEnd());
overlapInventory.add(tempSlice.getValidTime()); 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 // save off the source grid history, to update the source
// database modify the source grid data for the dest ParmID and // database modify the source grid data for the dest ParmID and
// GridDataHistory // GridDataHistory
Map<TimeRange, List<GridDataHistory>> histories = new HashMap<TimeRange, List<GridDataHistory>>(); Map<TimeRange, List<GridDataHistory>> histories = new HashMap<TimeRange, List<GridDataHistory>>();
Date nowTime = new Date(); Date nowTime = new Date();
for (IGridSlice slice : sourceData) { for (IGridSlice slice : sourceData) {
GridDataHistory[] sliceHist = slice.getHistory(); GridDataHistory[] sliceHist = slice.getHistory();
for (GridDataHistory hist : sliceHist) { for (GridDataHistory hist : sliceHist) {
hist.setPublishTime((Date) nowTime.clone()); hist.setPublishTime((Date) nowTime.clone());
} }
slice.getGridInfo().resetParmID(destParmId); slice.getGridInfo().resetParmID(destParmId);
histories.put(slice.getValidTime(), histories.put(slice.getValidTime(),
Arrays.asList(sliceHist)); Arrays.asList(sliceHist));
} }
// update the history for publish time for grids that are // update the history for publish time for grids that are
// unchanged // unchanged
for (TimeRange tr : historyOnly.keySet()) { for (TimeRange tr : historyOnly.keySet()) {
List<GridDataHistory> histList = historyOnly.get(tr); List<GridDataHistory> histList = historyOnly.get(tr);
for (GridDataHistory hist : histList) { for (GridDataHistory hist : histList) {
hist.setPublishTime((Date) nowTime.clone()); hist.setPublishTime((Date) nowTime.clone());
}
histories.put(tr, histList);
} }
histories.put(tr, histList);
}
// update the publish times in the source database, // update the publish times in the source database,
// update the notifications // update the notifications
historyUpdateTimer.start(); historyUpdateTimer.start();
sr.addMessages(sourceGP.updatePublishTime(histories.values(), sr.addMessages(sourceGP.updatePublishTime(histories.values(),
(Date) nowTime.clone())); (Date) nowTime.clone()));
// System.out.println("Updated " + histories.size() + // System.out.println("Updated " + histories.size() +
// " histories"); // " histories");
historyUpdateTimer.stop(); historyUpdateTimer.stop();
List<TimeRange> historyTimes = new ArrayList<TimeRange>( List<TimeRange> historyTimes = new ArrayList<TimeRange>(
histories.keySet()); histories.keySet());
@ -723,56 +726,56 @@ public class GridParmManager {
// update the histories of destination database for ones // update the histories of destination database for ones
// that are not going to be saved since there hasn't been a // that are not going to be saved since there hasn't been a
// change // change
List<TimeRange> historyOnlyList = new ArrayList<TimeRange>(); List<TimeRange> historyOnlyList = new ArrayList<TimeRange>();
historyOnlyList.addAll(historyOnly.keySet()); historyOnlyList.addAll(historyOnly.keySet());
historyRetrieveTimer.start(); historyRetrieveTimer.start();
Map<TimeRange, List<GridDataHistory>> destHistory = destGP Map<TimeRange, List<GridDataHistory>> destHistory = destGP
.getGridHistory(historyOnlyList).getPayload(); .getGridHistory(historyOnlyList).getPayload();
historyRetrieveTimer.stop(); historyRetrieveTimer.stop();
for (TimeRange tr : destHistory.keySet()) { for (TimeRange tr : destHistory.keySet()) {
List<GridDataHistory> srcHistList = histories.get(tr); List<GridDataHistory> srcHistList = histories.get(tr);
List<GridDataHistory> destHistList = destHistory.get(tr); List<GridDataHistory> destHistList = destHistory.get(tr);
for (int i = 0; i < srcHistList.size(); i++) { for (int i = 0; i < srcHistList.size(); i++) {
destHistList.get(i).replaceValues(srcHistList.get(i)); destHistList.get(i).replaceValues(srcHistList.get(i));
}
} }
}
// only need to update the publish time on the destination // only need to update the publish time on the destination
// histories of grids that are not being saved (due to no // histories of grids that are not being saved (due to no
// changes), because the saveGridSlices() call below will update // changes), because the saveGridSlices() call below will update
// the publish time of the ones with changes // the publish time of the ones with changes
historyUpdateTimer.start(); historyUpdateTimer.start();
destGP.updatePublishTime(destHistory.values(), destGP.updatePublishTime(destHistory.values(),
(Date) nowTime.clone()); (Date) nowTime.clone());
historyUpdateTimer.stop(); historyUpdateTimer.stop();
// save data directly to the official database (bypassing // save data directly to the official database (bypassing
// the checks in Parm intentionally) // the checks in Parm intentionally)
storeTimer.start(); storeTimer.start();
ssr.addMessages(officialDBPtr.saveGridSlices(destParmId, ssr.addMessages(officialDBPtr.saveGridSlices(destParmId,
publishTime, sourceData, requestorId, historyOnlyList)); publishTime, sourceData, requestorId, historyOnlyList));
storeTimer.stop(); storeTimer.stop();
// System.out.println("Published " + sourceData.size() + // System.out.println("Published " + sourceData.size() +
// " slices"); // " slices");
if (!ssr.isOkay()) { if (!ssr.isOkay()) {
ssr.addMessage("SaveGridData for official for commitGrid() failure: " ssr.addMessage("SaveGridData for official for commitGrid() failure: "
+ ssr.message()); + ssr.message());
srDetailed.addMessages(ssr); srDetailed.addMessages(ssr);
failures.add(req); failures.add(req);
continue; continue;
} }
// make the notification // make the notification
GridUpdateNotification not = new GridUpdateNotification( GridUpdateNotification not = new GridUpdateNotification(
destParmId, publishTime, histories, requestorId, siteID); destParmId, publishTime, histories, requestorId, siteID);
changes.add(not); changes.add(not);
sr.getPayload().add(not); sr.getPayload().add(not);
} finally { } finally {
ClusterLockUtils.unlock(ct, false); ClusterLockUtils.unlock(ct, false);
} }
} }
perfLog.logDuration("Publish Grids: Acquiring cluster lock", perfLog.logDuration("Publish Grids: Acquiring cluster lock",
@ -822,8 +825,8 @@ public class GridParmManager {
this.dbMap.keySet()); this.dbMap.keySet());
sr.setPayload(databases); sr.setPayload(databases);
return sr; return sr;
} }
/** /**
* Get a database if available * Get a database if available
@ -832,6 +835,10 @@ public class GridParmManager {
* @return GridDatabase or null if not available * @return GridDatabase or null if not available
*/ */
public GridDatabase getDatabase(DatabaseID dbId) { public GridDatabase getDatabase(DatabaseID dbId) {
return getDatabase(dbId, true);
}
private GridDatabase getDatabase(DatabaseID dbId, boolean notify) {
// look up the database in the map // look up the database in the map
GridDatabase db = this.dbMap.get(dbId); GridDatabase db = this.dbMap.get(dbId);
@ -846,12 +853,14 @@ public class GridParmManager {
ServerResponse<GridDatabase> status = createDB(dbId); ServerResponse<GridDatabase> status = createDB(dbId);
if (status.isOkay()) { if (status.isOkay()) {
db = status.getPayload(); db = status.getPayload();
createDbNotification(Arrays.asList(dbId), null); }
} }
}
if (db != null) { if (db != null) {
this.addDB(db); this.addDB(db);
if (notify) {
createDbNotification(Arrays.asList(dbId), null);
}
} }
} }
@ -886,8 +895,8 @@ public class GridParmManager {
return sr; return sr;
} }
return sr; return sr;
} }
/** /**
* Delete database * Delete database
@ -944,9 +953,9 @@ public class GridParmManager {
if (db == null) { if (db == null) {
sr.addMessage("Database " + dbId sr.addMessage("Database " + dbId
+ " does not exist for getParmList()"); + " does not exist for getParmList()");
return sr; return sr;
} }
sr = db.getParmList(); sr = db.getParmList();
return sr; return sr;
@ -988,7 +997,7 @@ public class GridParmManager {
// determine desired number of versions // determine desired number of versions
desiredVersions = this.config.desiredDbVersions(dbId); desiredVersions = this.config.desiredDbVersions(dbId);
} }
// process the id and determine whether it should be purged // process the id and determine whether it should be purged
count++; count++;
@ -1012,9 +1021,9 @@ public class GridParmManager {
toRemove.removeAll(newInv); toRemove.removeAll(newInv);
for (DatabaseID dbId : toRemove) { for (DatabaseID dbId : toRemove) {
if (dbMap.remove(dbId) != null) { if (dbMap.remove(dbId) != null) {
statusHandler statusHandler
.info("Synching GridParmManager with database inventory, removing " .info("Synching GridParmManager with database inventory, removing "
+ dbId); + dbId);
} }
// add any removals to the deletions list // add any removals to the deletions list
@ -1073,14 +1082,14 @@ public class GridParmManager {
List<LockNotification> lockNotify = new ArrayList<LockNotification>(); List<LockNotification> lockNotify = new ArrayList<LockNotification>();
GridParm gp = createParm(parmId); GridParm gp = createParm(parmId);
if (gp.isValid()) { if (gp.isValid()) {
ServerResponse<Integer> sr1 = gp.timePurge(purgeTime, ServerResponse<Integer> sr1 = gp.timePurge(purgeTime,
gridNotify, lockNotify); gridNotify, lockNotify);
sr.addMessages(sr1); sr.addMessages(sr1);
purgedCount += sr1.getPayload(); purgedCount += sr1.getPayload();
gridNotifications.addAll(gridNotify); gridNotifications.addAll(gridNotify);
lockNotifications.addAll(lockNotify); lockNotifications.addAll(lockNotify);
} }
} }
PurgeLogger.logInfo("Purge " + purgedCount + " items from " + dbId, PurgeLogger.logInfo("Purge " + purgedCount + " items from " + dbId,
@ -1119,7 +1128,7 @@ public class GridParmManager {
if (dbId.getRemovedDate() != null) { if (dbId.getRemovedDate() != null) {
// mark database as not removed // mark database as not removed
try { try {
GFEDao gfeDao = new GFEDao(); GFEDao gfeDao = new GFEDao();
gfeDao.setDatabaseRemovedDate(dbId, null); gfeDao.setDatabaseRemovedDate(dbId, null);
statusHandler.info("Database " + dbId + " restored"); statusHandler.info("Database " + dbId + " restored");
@ -1127,7 +1136,7 @@ public class GridParmManager {
statusHandler.handle(Priority.PROBLEM, statusHandler.handle(Priority.PROBLEM,
"Unable to mark database restored: " + dbId, e); "Unable to mark database restored: " + dbId, e);
} }
} }
// add to list of databases // add to list of databases
addDB(db); addDB(db);
@ -1177,8 +1186,8 @@ public class GridParmManager {
if (manID.getFormat().equals(DataType.GRID) if (manID.getFormat().equals(DataType.GRID)
&& !inventory.contains(manID)) { && !inventory.contains(manID)) {
inventory.add(manID); inventory.add(manID);
}
} }
}
// create the databases (the list should now only contain GRID dbs) // create the databases (the list should now only contain GRID dbs)
ServerResponse<GridDatabase> sr = new ServerResponse<GridDatabase>(); ServerResponse<GridDatabase> sr = new ServerResponse<GridDatabase>();
@ -1208,11 +1217,6 @@ public class GridParmManager {
ClusterTask ct = ClusterLockUtils.lookupLock(SMART_INIT_TASK_NAME, ClusterTask ct = ClusterLockUtils.lookupLock(SMART_INIT_TASK_NAME,
SMART_INIT_TASK_DETAILS + siteID); 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 ct = ClusterLockUtils
.lock(SMART_INIT_TASK_NAME, SMART_INIT_TASK_DETAILS .lock(SMART_INIT_TASK_NAME, SMART_INIT_TASK_DETAILS
+ siteID, SMART_INIT_TIMEOUT, false); + siteID, SMART_INIT_TIMEOUT, false);
@ -1285,7 +1289,7 @@ public class GridParmManager {
if (db == null) { if (db == null) {
// New database // New database
db = D2DGridDatabase.getDatabase(config, d2dModelName, refTime); db = D2DGridDatabase.getDatabase(config, d2dModelName, refTime);
if (db == null) { if (db == null) {
continue; continue;
} }
@ -1308,16 +1312,16 @@ public class GridParmManager {
queue.queue(siteID, config, dbId, validTime, false, queue.queue(siteID, config, dbId, validTime, false,
SmartInitRecord.LIVE_SMART_INIT_PRIORITY); SmartInitRecord.LIVE_SMART_INIT_PRIORITY);
} }
} }
} }
// send notifications; // send notifications;
try { try {
SendNotifications.send(guns); SendNotifications.send(guns);
} catch (Exception e) { } catch (Exception e) {
statusHandler.error("Unable to send grib ingest notifications", e); statusHandler.error("Unable to send grib ingest notifications", e);
} }
} }
/** /**
* @param records * @param records
@ -1339,9 +1343,9 @@ public class GridParmManager {
Date validTime = gun.getReplacementTimeRange().getStart(); Date validTime = gun.getReplacementTimeRange().getStart();
queue.queue(siteID, config, dbId, validTime, false, queue.queue(siteID, config, dbId, validTime, false,
SmartInitRecord.LIVE_SMART_INIT_PRIORITY); SmartInitRecord.LIVE_SMART_INIT_PRIORITY);
}
} }
} }
}
try { try {
SendNotifications.send(guns); SendNotifications.send(guns);
@ -1349,7 +1353,7 @@ public class GridParmManager {
statusHandler.error( statusHandler.error(
"Unable to send satellite ingest notifications", e); "Unable to send satellite ingest notifications", e);
} }
} }
private Date purgeTime(DatabaseID id) { private Date purgeTime(DatabaseID id) {
int numHours = this.config.gridPurgeAgeInHours(id); int numHours = this.config.gridPurgeAgeInHours(id);
@ -1427,8 +1431,8 @@ public class GridParmManager {
for (ParmID pid : parmList) { for (ParmID pid : parmList) {
out.add(new CommitGridRequest(pid, req.getTimeRange(), out.add(new CommitGridRequest(pid, req.getTimeRange(),
req.isClientSendStatus())); req.isClientSendStatus()));
} }
} else { } else {
sr.addMessage("Could not find database for " sr.addMessage("Could not find database for "
+ req.getDbId() + " in convertToParmReq()"); + req.getDbId() + " in convertToParmReq()");
} }
@ -1495,25 +1499,7 @@ public class GridParmManager {
ServerResponse<GridDatabase> sr = new ServerResponse<GridDatabase>(); ServerResponse<GridDatabase> sr = new ServerResponse<GridDatabase>();
for (DatabaseID dbId : invChanged.getAdditions()) { for (DatabaseID dbId : invChanged.getAdditions()) {
// TODO: This is pretty much just a duplicate of what's in this.getDatabase(dbId, false);
// 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);
} }
if (!sr.isOkay()) { if (!sr.isOkay()) {
statusHandler.error("Error updating GridParmManager: " statusHandler.error("Error updating GridParmManager: "
@ -1544,7 +1530,7 @@ public class GridParmManager {
DatabaseID dbId = db.getDbId(); DatabaseID dbId = db.getDbId();
statusHandler.info("addDB called, adding " + dbId); statusHandler.info("addDB called, adding " + dbId);
this.dbMap.put(dbId, db); this.dbMap.put(dbId, db);
} }
/** /**
* Process D2D grid data purge notification * Process D2D grid data purge notification
@ -1568,44 +1554,22 @@ public class GridParmManager {
newInventory.addAll(dbIds); newInventory.addAll(dbIds);
} catch (DataAccessLayerException e) { } catch (DataAccessLayerException e) {
statusHandler.error(e.getLocalizedMessage(), 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); List<DatabaseID> deleted = new ArrayList<DatabaseID>(currentInventory);
deleted.removeAll(newInventory); 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(); Iterator<DatabaseID> iter = deleted.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
DatabaseID dbid = iter.next(); DatabaseID dbid = iter.next();
// remove satellite database and non-D2D databases from deletes // don't delete non-D2D databases
if (!dbid.getDbType().equals("D2D") || dbid.equals(satDbid)) { if (!dbid.getDbType().equals("D2D")) {
iter.remove(); iter.remove();
} else { } else {
// remove the database // remove the database
@ -1613,19 +1577,16 @@ public class GridParmManager {
statusHandler.info("d2dGridDataPurged removing database: " statusHandler.info("d2dGridDataPurged removing database: "
+ dbid); + dbid);
} }
}
} }
}
// if ((added.size() > 0) || (deleted.size() > 0)) {
// DBInvChangeNotification changed = new DBInvChangeNotification(
// added, deleted, siteID);
if (deleted.size() > 0) { if (deleted.size() > 0) {
DBInvChangeNotification changed = new DBInvChangeNotification(null, DBInvChangeNotification changed = new DBInvChangeNotification(null,
deleted, siteID); deleted, siteID);
SendNotifications.send(changed); SendNotifications.send(changed);
}
} }
}
/** /**
* Process D2D satellite data purge notification * 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 * Added function to create a D2DGridDatabase object only if there is
* data in postgres for the desired model/reftime * data in postgres for the desired model/reftime
* 04/17/2014 #2934 dgilling Change getGridParmInfo to use D2DParm's GridParmInfo. * 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> * </pre>
* *
@ -176,8 +178,9 @@ public class D2DGridDatabase extends VGridDatabase {
String d2dModelName, Date refTime) { String d2dModelName, Date refTime) {
try { try {
GFED2DDao dao = new GFED2DDao(); GFED2DDao dao = new GFED2DDao();
// TODO create query for single refTime int dbVersions = config.desiredDbVersions(getDbId(d2dModelName,
List<Date> result = dao.getModelRunTimes(d2dModelName, -1); refTime, config));
List<Date> result = dao.getModelRunTimes(d2dModelName, dbVersions);
if (result.contains(refTime)) { if (result.contains(refTime)) {
D2DGridDatabase db = new D2DGridDatabase(config, d2dModelName, 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 * May 7, 2008 njensen Initial creation
* Jun 13, 2013 #2044 randerso Refactored to use IFPServer * Jun 13, 2013 #2044 randerso Refactored to use IFPServer
* Jul 28, 2014 RM 15655 ryu Negate raising exception for empty db in constructor
* *
* </pre> * </pre>
* *
@ -88,7 +89,6 @@ public class IFPDB {
} }
} else { } else {
this.keys = Collections.emptyList(); this.keys = Collections.emptyList();
throw new GfeException(sr.message());
} }
} }

View file

@ -30,6 +30,7 @@ except:
import numpy import numpy
import JUtil import JUtil
from java.lang import System
from java.util import ArrayList from java.util import ArrayList
from java.util import LinkedHashMap from java.util import LinkedHashMap
from com.raytheon.uf.common.dataplugin.gfe.grid import Grid2DFloat 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. # 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/03/2014 2737 randerso Allow iscMosaic to blankOtherPeriods even when no grids received
# 04/11/2014 17242 David Gillingham (code checked in by zhao) # 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 BATCH_DELAY = 0.0
@ -727,6 +729,9 @@ class IscMosaic:
# process incoming grids # process incoming grids
for i in xrange(len(inTimes)): 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. # Put in a delay so we don't hammer the server so hard.
if self.__gridDelay > 0.0: if self.__gridDelay > 0.0:
time.sleep(self.__gridDelay) time.sleep(self.__gridDelay)

View file

@ -2929,7 +2929,6 @@
<name>HPCGuide</name> <name>HPCGuide</name>
<center>7</center> <center>7</center>
<subcenter>5</subcenter> <subcenter>5</subcenter>
<grid>197</grid>
<process> <process>
<id>183</id> <id>183</id>
</process> </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.SHEFDate;
import com.raytheon.edex.plugin.shef.util.ShefParm; 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;
import com.raytheon.uf.common.dataplugin.shef.util.ParameterCode.Duration; import com.raytheon.uf.common.dataplugin.shef.util.ParameterCode.Duration;
import com.raytheon.uf.common.dataplugin.shef.util.ParameterCode.Extremum; 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. * 03/19/08 387 M. Duff Initial creation.
* 10/16/2008 1548 jelkins Integrated ParameterCode Types * 10/16/2008 1548 jelkins Integrated ParameterCode Types
* 04/29/2014 3088 mpduff cleanup. * 04/29/2014 3088 mpduff cleanup.
* 06/26/2014 3321 mpduff Added ingestfilter primary key getter.
* *
* </pre> * </pre>
*/ */
@ -805,14 +807,30 @@ public class ShefData implements ISerializableObject {
* *
* @return * @return
*/ */
public String getPeTsE() { public String getPeDTsE() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(this.getPhysicalElement().getCode()); sb.append(this.getPhysicalElement().getCode());
sb.append(this.getTypeSource().getCode()); sb.append(this.getTypeSource().getCode());
sb.append(this.getExtremum().getCode()); sb.append(this.getExtremum().getCode());
sb.append(this.getDurationCodeVariable());
return sb.toString(); 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 * @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 * SOFTWARE HISTORY
* Date Ticket# Engineer Description * 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. * 06/02/2008 1166 M. Duff Added checks for null data objects.
* 22Jul2008 1277 MW Fegan Use CoreDao in checkIngest(). * 22Jul2008 1277 MW Fegan Use CoreDao in checkIngest().
* 10/16/2008 1548 jelkins Integrated ParameterCode Types and misc fixes * 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. * 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 * 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/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> * </pre>
* *
* @author mduff * @author mduff
@ -228,7 +231,7 @@ public class PostShef {
private Map<String, ShefAdjustFactor> adjustmentMap = new HashMap<String, ShefAdjustFactor>(); private Map<String, ShefAdjustFactor> adjustmentMap = new HashMap<String, ShefAdjustFactor>();
/** Map of location identifier to IngestSwitch */ /** 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 // AppsDefaults tokens
private String undefStation; private String undefStation;
@ -274,9 +277,6 @@ public class PostShef {
/** Basis time TimeStamp */ /** Basis time TimeStamp */
private java.sql.Timestamp basisTimeAnsi = new Timestamp(basisBeginTime); private java.sql.Timestamp basisTimeAnsi = new Timestamp(basisBeginTime);
/** River status update flag. update if true */
private boolean riverStatusUpdateFlag = true;
/** river status update query value */ /** river status update query value */
private boolean riverStatusUpdateValueFlag; private boolean riverStatusUpdateValueFlag;
@ -295,39 +295,12 @@ public class PostShef {
/** Forecast query results */ /** Forecast query results */
private Object[] queryForecastResults; private Object[] queryForecastResults;
/** Location range data found flag */ /** Cache of data limits and loc data limits */
private boolean locRangeFound = false; private Map<String, ShefRangeData> dataRangeMap = new HashMap<String, ShefRangeData>();
/** Default range data found flag */
private boolean defRangeFound = false;
/** Valid date range flag */ /** Valid date range flag */
private boolean validDateRange = false; private boolean validDateRange = false;
/** Gross range minimum value */
private double grossRangeMin = ShefConstants.SHEF_MISSING_INT;
/** Gross range maximum value */
private double grossRangeMax = ShefConstants.SHEF_MISSING_INT;
/** Reasonable range minimum value */
private double reasonRangeMin = ShefConstants.SHEF_MISSING_INT;
/** Reasonable range maximum value */
private double reasonRangeMax = ShefConstants.SHEF_MISSING_INT;
/** Alert upper limit value */
private double alertUpperLimit = ShefConstants.SHEF_MISSING_INT;
/** Alarm upper limit value */
private double alarmUpperLimit = ShefConstants.SHEF_MISSING_INT;
/** Alert lower limit value */
private double alertLowerLimit = ShefConstants.SHEF_MISSING_INT;
/** Alarm lower limit value */
private double alarmLowerLimit = ShefConstants.SHEF_MISSING_INT;
/** /**
* *
* @param date * @param date
@ -529,7 +502,7 @@ public class PostShef {
if (dataLog) { if (dataLog) {
log.info(LOG_SEP); log.info(LOG_SEP);
log.info("Posting process started for LID [" + locId log.info("Posting process started for LID [" + locId
+ "] PEDTSEP [" + data.getPeTsE() + "] value [" + "] PEDTSEP [" + data.getPeDTsE() + "] value ["
+ dataValue + "]"); + dataValue + "]");
} }
@ -650,7 +623,7 @@ public class PostShef {
if (Location.LOC_LOCATION.equals(postLocData) if (Location.LOC_LOCATION.equals(postLocData)
|| (Location.LOC_GEOAREA.equals(postLocData))) { || (Location.LOC_GEOAREA.equals(postLocData))) {
if (!DataType.CONTINGENCY.equals(dataType)) { if (!DataType.CONTINGENCY.equals(dataType)) {
ingestSwitch = checkIngest(locId, data, ingestSwitch); ingestSwitch = checkIngest(locId, data);
} }
if (ShefConstants.IngestSwitch.POST_PE_OFF if (ShefConstants.IngestSwitch.POST_PE_OFF
.equals(ingestSwitch)) { .equals(ingestSwitch)) {
@ -1107,23 +1080,12 @@ public class PostShef {
// Reset .E cache vars // Reset .E cache vars
tsList.clear(); tsList.clear();
useLatest = MISSING; useLatest = MISSING;
riverStatusUpdateFlag = true;
qualityCheckFlag = true; qualityCheckFlag = true;
useTs = null; useTs = null;
basisTimeValues = null; basisTimeValues = null;
previousQueryForecast = null; previousQueryForecast = null;
locRangeFound = false; dataRangeMap.clear();
defRangeFound = false;
validDateRange = false; validDateRange = false;
grossRangeMin = ShefConstants.SHEF_MISSING_INT;
grossRangeMax = ShefConstants.SHEF_MISSING_INT;
reasonRangeMin = ShefConstants.SHEF_MISSING_INT;
reasonRangeMax = ShefConstants.SHEF_MISSING_INT;
alertUpperLimit = ShefConstants.SHEF_MISSING_INT;
alarmUpperLimit = ShefConstants.SHEF_MISSING_INT;
alertLowerLimit = ShefConstants.SHEF_MISSING_INT;
alarmLowerLimit = ShefConstants.SHEF_MISSING_INT;
} }
/** /**
@ -1448,15 +1410,7 @@ public class PostShef {
if ((shefList != null) && (shefList.size() > 0)) { if ((shefList != null) && (shefList.size() > 0)) {
ShefData maxShefDataValue = findMaxFcst(shefList); ShefData maxShefDataValue = findMaxFcst(shefList);
if (shefRecord.getShefType() == ShefType.E) { riverStatusUpdateValueFlag = updateRiverStatus(lid, pe, ts);
if (riverStatusUpdateFlag) {
riverStatusUpdateFlag = false;
riverStatusUpdateValueFlag = updateRiverStatus(lid, pe, ts);
}
} else {
riverStatusUpdateValueFlag = updateRiverStatus(lid, pe, ts);
}
postTables.postRiverStatus(shefRecord, maxShefDataValue, postTables.postRiverStatus(shefRecord, maxShefDataValue,
riverStatusUpdateValueFlag); riverStatusUpdateValueFlag);
} else { } else {
@ -2125,8 +2079,7 @@ public class PostShef {
* ingest switch setting * ingest switch setting
* @return * @return
*/ */
private IngestSwitch checkIngest(String locId, ShefData data, private IngestSwitch checkIngest(String locId, ShefData data) {
ShefConstants.IngestSwitch ingestSwitch) {
StringBuilder errorMsg = new StringBuilder(); StringBuilder errorMsg = new StringBuilder();
boolean matchFound = false; boolean matchFound = false;
int hNum = 0; int hNum = 0;
@ -2152,13 +2105,16 @@ public class PostShef {
String telem = null; String telem = null;
String sql = null; String sql = null;
Object[] oa = null; Object[] oa = null;
String key = locId + data.getPeTsE();
IngestfilterId key = data.getIngestFilterKey();// .getPeDTsE();
// Default to off
ShefConstants.IngestSwitch ingestSwitch = IngestSwitch.POST_PE_OFF;
try { try {
if (!ingestSwitchMap.containsKey(key)) { 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 = '" sql = "select lid, pe, dur, ts, extremum, ts_rank, ingest, ofs_input, stg2_input from IngestFilter where lid = '"
+ locId + "'"; + locId + "'";
errorMsg.setLength(0);
errorMsg.append("Error requesting IngestFilter data: " + sql); errorMsg.append("Error requesting IngestFilter data: " + sql);
oa = dao.executeSQLQuery(sql); oa = dao.executeSQLQuery(sql);
if (oa.length > 0) { if (oa.length > 0) {
@ -2443,7 +2399,7 @@ public class PostShef {
if (!matchFound) { if (!matchFound) {
log.warn(locId + " - " + data.getPhysicalElement() + "(" log.warn(locId + " - " + data.getPhysicalElement() + "("
+ data.getDuration() + ")" + data.getTypeSource() + data.getDuration() + ")" + data.getTypeSource()
+ data.getExtremum() + " ingest " + "filter not defined"); + data.getExtremum() + " ingest filter not defined");
stats.incrementWarningMessages(); stats.incrementWarningMessages();
ingestSwitch = ShefConstants.IngestSwitch.POST_PE_OFF; ingestSwitch = ShefConstants.IngestSwitch.POST_PE_OFF;
} }
@ -2646,24 +2602,12 @@ public class PostShef {
return ShefConstants.QC_MANUAL_FAILED; 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 locLimitSql = new StringBuilder();
StringBuilder defLimitSql = new StringBuilder(); StringBuilder defLimitSql = new StringBuilder();
String key = lid + data.getPhysicalElement().getCode()
+ data.getDurationValue();
try { try {
if (executeQuery) { if (!dataRangeMap.containsKey(key)) {
String sqlStart = "select monthdaystart, monthdayend, gross_range_min, gross_range_max, reason_range_min, " 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, " + "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, " + "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()); Object[] oa = dao.executeSQLQuery(locLimitSql.toString());
if (oa.length == 0) { if (oa.length == 0) {
dataRangeMap.put(key, null);
// default range // default range
defLimitSql = new StringBuilder(sqlStart); defLimitSql = new StringBuilder(sqlStart);
defLimitSql.append("datalimits where pe = '") defLimitSql.append("datalimits where pe = '")
@ -2687,7 +2632,13 @@ public class PostShef {
.append(data.getDurationValue()); .append(data.getDurationValue());
oa = dao.executeSQLQuery(defLimitSql.toString()); 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++) { for (int i = 0; i < oa.length; i++) {
Object[] oa2 = (Object[]) oa[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 * if a range is found, then check the value and set the
* flag * flag
*/ */
grossRangeMin = ShefUtil.getDouble(oa2[2], missing); ShefRangeData rangeData = new ShefRangeData();
grossRangeMax = ShefUtil.getDouble(oa2[3], missing); rangeData.setGrossRangeMin(ShefUtil.getDouble(oa2[2],
reasonRangeMin = ShefUtil.getDouble(oa2[4], missing); missing));
reasonRangeMax = ShefUtil.getDouble(oa2[5], missing); rangeData.setGrossRangeMax(ShefUtil.getDouble(oa2[3],
alertUpperLimit = ShefUtil.getDouble(oa2[7], missing); missing));
alertLowerLimit = ShefUtil.getDouble(oa2[11], missing); rangeData.setReasonRangeMin(ShefUtil.getDouble(oa2[4],
alarmLowerLimit = ShefUtil.getDouble(oa2[12], missing); missing));
alarmUpperLimit = ShefUtil.getDouble(oa2[9], missing); rangeData.setReasonRangeMax(ShefUtil.getDouble(oa2[5],
defRangeFound = true; 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; 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 a range is found, then check the value and set the flag
*/ */
if (((grossRangeMin != missing) && (dValue < grossRangeMin)) if (((rangeData.getGrossRangeMin() != missing) && (dValue < rangeData
|| ((grossRangeMax != missing) && (dValue > grossRangeMax))) { .getGrossRangeMin()))
|| ((rangeData.getGrossRangeMax() != missing) && (dValue > rangeData
.getGrossRangeMax()))) {
qualityCode = ShefQC.setQcCode( qualityCode = ShefQC.setQcCode(
(int) ShefConstants.QC_GROSSRANGE_FAILED, (int) ShefConstants.QC_GROSSRANGE_FAILED,
qualityCode); qualityCode);
if (dataLog) { if (dataLog) {
log.info(lid + " failed gross range check: " + dValue log.info(lid + " failed gross range check: " + dValue
+ " out of range " + grossRangeMin + " - " + " out of range "
+ grossRangeMax); + rangeData.getGrossRangeMin() + " - "
+ rangeData.getGrossRangeMax());
} }
/* /*
* don't do anything if it fails the gross range check * don't do anything if it fails the gross range check
*/ */
} else { } else {
if (((reasonRangeMin != missing) && (dValue < reasonRangeMin)) if (((rangeData.getReasonRangeMin() != missing) && (dValue < rangeData
|| ((reasonRangeMax != missing) && (dValue > reasonRangeMax))) { .getReasonRangeMin()))
|| ((rangeData.getReasonRangeMax() != missing) && (dValue > rangeData
.getReasonRangeMax()))) {
qualityCode = ShefQC.setQcCode( qualityCode = ShefQC.setQcCode(
(int) ShefConstants.QC_REASONRANGE_FAILED, (int) ShefConstants.QC_REASONRANGE_FAILED,
qualityCode); qualityCode);
if (dataLog) { if (dataLog) {
log.info(lid + " failed reasonable range check: " log.info(lid + " failed reasonable range check: "
+ dValue + " out of range " + dValue + " out of range "
+ reasonRangeMin + " - " + reasonRangeMax); + rangeData.getReasonRangeMin() + " - "
+ rangeData.getReasonRangeMax());
} }
} }
@ -2756,17 +2723,17 @@ public class PostShef {
* table. * table.
*/ */
if (shefAlertAlarm) { if (shefAlertAlarm) {
if ((alarmUpperLimit != missing) if ((rangeData.getAlarmUpperLimit() != missing)
&& (dValue >= alarmUpperLimit)) { && (dValue >= rangeData.getAlarmUpperLimit())) {
alertAlarm = ShefConstants.ALARM_UPPER_DETECTED; alertAlarm = ShefConstants.ALARM_UPPER_DETECTED;
} else if ((alertUpperLimit != missing) } else if ((rangeData.getAlertUpperLimit() != missing)
&& (dValue >= alertUpperLimit)) { && (dValue >= rangeData.getAlertUpperLimit())) {
alertAlarm = ShefConstants.ALERT_UPPER_DETECTED; alertAlarm = ShefConstants.ALERT_UPPER_DETECTED;
} else if ((alarmLowerLimit != missing) } else if ((rangeData.getAlarmLowerLimit() != missing)
&& (dValue <= alarmLowerLimit)) { && (dValue <= rangeData.getAlarmLowerLimit())) {
alertAlarm = ShefConstants.ALARM_LOWER_DETECTED; alertAlarm = ShefConstants.ALARM_LOWER_DETECTED;
} else if ((alertLowerLimit != missing) } else if ((rangeData.getAlertLowerLimit() != missing)
&& (dValue <= alertLowerLimit)) { && (dValue <= rangeData.getAlertLowerLimit())) {
alertAlarm = ShefConstants.ALERT_LOWER_DETECTED; 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.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.raytheon.edex.utility.ProtectedFiles; import com.raytheon.edex.utility.ProtectedFiles;
import com.raytheon.uf.common.auth.exception.AuthorizationException; import com.raytheon.uf.common.auth.exception.AuthorizationException;
@ -54,6 +54,7 @@ import com.raytheon.uf.edex.core.EDEXUtil;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Aug 11, 2010 mschenke Initial creation * Aug 11, 2010 mschenke Initial creation
* Jul 14, 2014 3372 njensen fileMap is ConcurrentHashMap for thread safety
* *
* </pre> * </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) * (non-Javadoc)

View file

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

View file

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

View file

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

View file

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

View file

@ -189,33 +189,35 @@ ${drainage.name}##
########END MACRO ########END MACRO
#macro(inserttorwatches $watches $list $secondtimezone $dateUtil $timeFormat) #macro(inserttorwatches $watches $list $secondtimezone $dateUtil $timeFormat)
#set($torWatches = ${watches.getTorWatches()}) #set($tornadoWatches = [])
#set($torWatchAlso = "") #foreach(${watch} in ${watches})
#set($torWatchFirst = 1) #if(${watch.getPhenSig()} == 'TO.A')
#foreach(${watch} in ${torWatches}) #set($success = $tornadoWatches.add($watch))
#if($torWatchFirst) #set($endTime = ${watch.endTime})
#set($torWatchFirst = 0) #if(!$latestEndTime || ${endTime.after($latestEndTime)})
#else #set($latestEndTime = ${endTime})
##
#end #end
A TORNADO WATCH ${torWatchAlso}REMAINS IN EFFECT UNTIL ${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${localtimezone})}## #end
${dateUtil.period(${watches.getLatestTorTime()},${timeFormat.plain}, 15, ${localtimezone})}## #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}) #if(${secondtimezone})
/${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${secondtimezone})}/## /${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${secondtimezone})}/##
#end #end
FOR ## FOR ##
#set($numPortions = ${list.size(${watch.getPortions()})}) #set($numPortions = ${list.size(${tornadoWatches})})
#set($count = 0) #set($count = 0)
#foreach(${portion} in ${watch.getPortions()}) #foreach(${watch} in ${tornadoWatches})
#set($count = $count + 1) #set($count = $count + 1)
#areaFormat(${portion.partOfParentRegion} true false true)${portion.parentRegion}## #areaFormat(${watch.partOfState} true false true)${watch.state}##
#if($count == $numPortions - 1) #if($count == $numPortions - 1)
AND ## AND ##
#elseif($count < $numPortions) #elseif($count < $numPortions)
...## ...##
#end #end
#end #end
#set($torWatchAlso = "ALSO ")
. ## . ##
#end #end
@ -223,33 +225,35 @@ ${dateUtil.period(${watches.getLatestTorTime()},${timeFormat.plain}, 15, ${local
########END MACRO ########END MACRO
#macro(insertsvrwatches $watches $list $secondtimezone $dateUtil $timeFormat) #macro(insertsvrwatches $watches $list $secondtimezone $dateUtil $timeFormat)
#set($svrWatches = ${watches.getSvrWatches()}) #set($severeWatches = [])
#set($svrWatchAlso = "") #foreach(${watch} in ${watches})
#set($svrWatchFirst = 1) #if(${watch.getPhenSig()} == 'SV.A')
#foreach(${watch} in ${svrWatches}) #set($success = $severeWatches.add($watch))
#if($svrWatchFirst) #set($endTime = ${watch.endTime})
#set($svrWatchFirst = 0) #if(!$latestEndTime || ${endTime.after($latestEndTime)})
#else #set($latestEndTime = ${endTime})
##
#end #end
A SEVERE THUNDERSTORM WATCH ${svrWatchAlso}REMAINS IN EFFECT UNTIL ${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${localtimezone})}## #end
${dateUtil.period(${watches.getLatestSvrTime()},${timeFormat.plain}, 15, ${localtimezone})}## #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}) #if(${secondtimezone})
/${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${secondtimezone})}/## /${dateUtil.format(${watch.getEndTime()}, ${timeFormat.plain}, 15, ${secondtimezone})}/##
#end #end
FOR ## FOR ##
#set($numPortions = ${list.size(${watch.getPortions()})}) #set($numPortions = ${list.size(${severeWatches})})
#set($count = 0) #set($count = 0)
#foreach(${portion} in ${watch.getPortions()}) #foreach(${watch} in ${severeWatches})
#set($count = $count + 1) #set($count = $count + 1)
#areaFormat(${portion.partOfParentRegion} true false true)${portion.parentRegion}## #areaFormat(${watch.partOfState} true false true)${watch.state}##
#if($count == $numPortions - 1) #if($count == $numPortions - 1)
AND ## AND ##
#elseif($count < $numPortions) #elseif($count < $numPortions)
...## ...##
#end #end
#end #end
#set($svrWatchAlso = "ALSO ")
. ## . ##
#end #end
@ -368,18 +372,6 @@ SOUTH##
#if(${list.contains($directionSet, "WEST")}) #if(${list.contains($directionSet, "WEST")})
#set($output = "${output}WEST") #set($output = "${output}WEST")
#end #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(${useCentral} && ${list.contains($directionSet, "CENTRAL")})
#if(${list.contains($directionSet, "NORTH")} || ${list.contains($directionSet, "SOUTH")} || ${list.contains($directionSet, "EAST")} || ${list.contains($directionSet, "WEST")}) #if(${list.contains($directionSet, "NORTH")} || ${list.contains($directionSet, "SOUTH")} || ${list.contains($directionSet, "EAST")} || ${list.contains($directionSet, "WEST")})
#set($output = "${output} ") #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 ## If sites do not want watches in their AWW product comment out the
## section below ## 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}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #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}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the warning --> <!-- 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> <enableDamBreakThreat>true</enableDamBreakThreat>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>.
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
--> -->

View file

@ -191,10 +191,10 @@ THE SAFEST PLACE TO BE DURING A MAJOR LANDFALLING HURRICANE IS IN A REINFORCED I
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the warning --> <!-- durations: the list of possible durations of the warning -->

View file

@ -69,10 +69,10 @@ THIS IS A TEST MESSAGE. ##
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#end #end
@ -238,10 +238,10 @@ THE SAFEST PLACE TO BE DURING A MAJOR LANDFALLING HURRICANE IS IN A REINFORCED I
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#end #end
@ -346,10 +346,10 @@ THIS IS A TEST MESSAGE.##
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${productClass}=="T") #if(${productClass}=="T")
@ -468,10 +468,10 @@ THE SAFEST PLACE TO BE DURING A MAJOR LANDFALLING HURRICANE IS IN A REINFORCED I
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#end #end
@ -512,10 +512,10 @@ THIS IS A TEST MESSAGE.##
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the svs --> <!-- 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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
</includedWatches> </includedWatches>

View file

@ -67,11 +67,11 @@ Must be paired with proper vm code (also commented out in flashFloodWarning.vm)!
<!-- <trackEnabled>true</trackEnabled> --> <!-- <trackEnabled>true</trackEnabled> -->
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the warning --> <!-- 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 ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#* NO NEED TO INCLUDE SVR T-STM WATCHES IN A SVR WARNING!!!! #* 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}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
# #
#end #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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the warning --> <!-- durations: the list of possible durations of the warning -->

View file

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

View file

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

View file

@ -470,10 +470,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${productClass}=="T") #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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the warning --> <!-- durations: the list of possible durations of the warning -->

View file

@ -397,10 +397,10 @@ ${canwarning}
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#end #end
@ -571,10 +571,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#end #end
@ -679,10 +679,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${productClass}=="T") #if(${productClass}=="T")
@ -880,10 +880,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#elseif(${CORCAN} == "true") #elseif(${CORCAN} == "true")
@ -952,10 +952,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${productClass}=="T") #if(${productClass}=="T")
@ -1142,10 +1142,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#end #end
@ -1219,10 +1219,10 @@ ${expwarning}
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the svs --> <!-- 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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations --> <!-- 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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations --> <!-- 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 ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the warning --> <!-- durations: the list of possible durations of the warning -->

View file

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

View file

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

View file

@ -230,11 +230,11 @@ LOCATIONS CAN EXPECT !** EXPECTED SNOW **! INCHES OF SNOW.
############# #############
## WATCHES ## ## 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}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #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}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the warning --> <!-- 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 ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the warning --> <!-- 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 ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${productClass}=="T") #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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the warning --> <!-- durations: the list of possible durations of the warning -->

View file

@ -365,10 +365,10 @@ ${canwarning}
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#end #end
@ -538,10 +538,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#end #end
@ -646,10 +646,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${productClass}=="T") #if(${productClass}=="T")
@ -845,10 +845,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#elseif(${CORCAN} == "true") #elseif(${CORCAN} == "true")
@ -917,10 +917,10 @@ THE ${eventType} !** WEAKENED / MOVED OUT OF THE WARNED AREA **! AND NO LONGER $
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
@ -1104,10 +1104,10 @@ REPORT SEVERE WEATHER TO THE COAST GUARD OR NEAREST LAW ENFORCEMENT AGENCY. THEY
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#end #end
@ -1182,10 +1182,10 @@ ${expwarning}
############# #############
## WATCHES ## ## WATCHES ##
############# #############
#if(${list.contains(${includedWatches}, "torWatches")}) #if(${list.contains(${includedWatches}, "TO.A")})
#inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #inserttorwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#if(${list.contains(${includedWatches}, "svrWatches")}) #if(${list.contains(${includedWatches}, "SV.A")})
#insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat}) #insertsvrwatches(${watches}, ${list}, ${secondtimezone}, ${dateUtil}, ${timeFormat})
#end #end
#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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the svs --> <!-- 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> <autoLockText>true</autoLockText>
<!-- Included watches: If a tornado watch or severe thunderstorm watch is to be <!-- 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/>. --> respectively. Please refer to 'includedWatchAreaBuffer' in <areaConfig/>. -->
<includedWatches> <includedWatches>
<includedWatch>torWatches</includedWatch> <includedWatch>TO.A</includedWatch>
<includedWatch>svrWatches</includedWatch> <includedWatch>SV.A</includedWatch>
</includedWatches> </includedWatches>
<!-- durations: the list of possible durations of the warning --> <!-- durations: the list of possible durations of the warning -->

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2 Bundle-ManifestVersion: 2
Bundle-Name: Activetablesrv Plug-in Bundle-Name: Activetablesrv Plug-in
Bundle-SymbolicName: com.raytheon.uf.edex.activetable Bundle-SymbolicName: com.raytheon.uf.edex.activetable
Bundle-Version: 1.12.1174.qualifier Bundle-Version: 1.13.0.qualifier
Bundle-Vendor: RAYTHEON Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: com.raytheon.uf.common.activetable, 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.raytheon.uf.edex.site;bundle-version="1.0.0",
com.google.guava;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.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 Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Export-Package: com.raytheon.uf.edex.activetable Export-Package: com.raytheon.uf.edex.activetable

View file

@ -24,14 +24,15 @@ import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeSet;
import jep.JepException; import jep.JepException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import com.raytheon.edex.site.SiteUtil;
import com.raytheon.edex.util.Util; import com.raytheon.edex.util.Util;
import com.raytheon.uf.common.activetable.ActiveTableMode; import com.raytheon.uf.common.activetable.ActiveTableMode;
import com.raytheon.uf.common.activetable.ActiveTableRecord; 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.PyUtil;
import com.raytheon.uf.common.python.PythonScript; import com.raytheon.uf.common.python.PythonScript;
import com.raytheon.uf.common.site.SiteMap; 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.IUFStatusHandler;
import com.raytheon.uf.common.status.PerformanceStatus;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.util.CollectionUtil; 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.common.util.FileUtil;
import com.raytheon.uf.edex.core.EDEXUtil; import com.raytheon.uf.edex.core.EDEXUtil;
import com.raytheon.uf.edex.database.DataAccessLayerException; 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 * Mar 06, 2014 2883 randerso Pass siteId into python code
* Apr 10, 2014 3004 dgilling Remove ActiveTableMode parameter from * Apr 10, 2014 3004 dgilling Remove ActiveTableMode parameter from
* clearPracticeTable(). * clearPracticeTable().
* Jun 17, 2014 3296 randerso Cached PythonScript. Moved active table
* backup and purging to a separate thread.
* Added performance logging
* *
* </pre> * </pre>
* *
@ -97,9 +105,44 @@ public class ActiveTable {
private static final Logger changeLog = Logger private static final Logger changeLog = Logger
.getLogger("ActiveTableChange"); .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( private static CoreDao practiceDao = new CoreDao(
DaoConfig.forClass(PracticeActiveTableRecord.class)); DaoConfig.forClass(PracticeActiveTableRecord.class));
@ -107,25 +150,9 @@ public class ActiveTable {
private static CoreDao operationalDao = new CoreDao( private static CoreDao operationalDao = new CoreDao(
DaoConfig.forClass(OperationalActiveTableRecord.class)); DaoConfig.forClass(OperationalActiveTableRecord.class));
private PythonScript python; /**
* Default constructor
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);
}
public ActiveTable() { public ActiveTable() {
} }
@ -154,6 +181,10 @@ public class ActiveTable {
* the active table mode (PRACTICE or OPERATIONAL) * the active table mode (PRACTICE or OPERATIONAL)
* @param phensigList * @param phensigList
* phensigs to include. If null, all phensigs will be included. * 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 * @param requestValidTimes
* true if only valid times are to be returned * true if only valid times are to be returned
* @return the active table corresponding to the input parameters * @return the active table corresponding to the input parameters
@ -173,6 +204,10 @@ public class ActiveTable {
* the active table mode (PRACTICE or OPERATIONAL) * the active table mode (PRACTICE or OPERATIONAL)
* @param phensigList * @param phensigList
* phensigs to include. If null, all phensigs will be included. * 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 * @param requestValidTimes
* true if only valid times are to be returned * true if only valid times are to be returned
* @param wfos * @param wfos
@ -186,32 +221,18 @@ public class ActiveTable {
String[] wfos) { String[] wfos) {
if (wfos == null || !Arrays.asList(wfos).contains("all")) { if (wfos == null || !Arrays.asList(wfos).contains("all")) {
SiteMap siteMap = SiteMap.getInstance();
if (wfos == null || wfos.length == 0) { if (wfos == null || wfos.length == 0) {
// default to WFOs from VTECPartners // default to WFOs from VTECPartners
// Use the 3-char site or VTEC_DECODER_SITES will be empty Set<String> wfoSet = getDecoderSites(siteId);
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);
}
wfoSet.add(siteId); wfoSet.add(siteId);
wfos = wfoSet.toArray(new String[0]); wfos = wfoSet.toArray(new String[0]);
} }
// We have an array of 3- or 4-char WFOs to filter against. // We have an array of 3- or 4-char WFOs to filter against.
// We need a String "KMFL,KTBW,..." for the query. // We need a String "KMFL,KTBW,..." for the query.
SiteMap siteMap = SiteMap.getInstance();
StringBuilder wfosb = new StringBuilder(); StringBuilder wfosb = new StringBuilder();
String sep = ""; String sep = "";
for (String wfo : wfos) { for (String wfo : wfos) {
@ -228,6 +249,26 @@ public class ActiveTable {
false); 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 * Updates the active table with the new warnings
* *
@ -244,11 +285,38 @@ public class ActiveTable {
mode = ActiveTableMode.OPERATIONAL; mode = ActiveTableMode.OPERATIONAL;
} }
MergeResult result = filterTable(siteId, IPerformanceStatusHandler perfStat = PerformanceStatus
getActiveTable(siteId, mode), newRecords, mode, offsetSecs); .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); updateTable(siteId, result, mode);
timer.stop();
perfStat.logDuration("updateTable", timer.getElapsedTime());
if (result.changeList.size() > 0) { if (result.changeList.size() > 0) {
sendNotification(mode, result.changeList, "VTECDecoder"); sendNotification(mode, result.changeList, "VTECDecoder");
} }
@ -281,26 +349,17 @@ public class ActiveTable {
args.put("offsetSecs", offsetSecs); args.put("offsetSecs", offsetSecs);
MergeResult result = null; MergeResult result = null;
try { try {
PythonScript python = threadLocalPythonScript.get();
try { try {
python = new PythonScript(filePath, includePath, result = (MergeResult) python.execute("mergeFromJava", args);
ActiveTable.class.getClassLoader());
try {
result = (MergeResult) python
.execute("mergeFromJava", args);
} catch (JepException e) { } catch (JepException e) {
statusHandler.handle(Priority.PROBLEM, statusHandler.handle(Priority.PROBLEM,
"Error updating active table", e); "Error updating active table", e);
} }
} catch (JepException e) { } catch (Exception e) {
statusHandler.handle(Priority.PROBLEM, statusHandler.handle(Priority.PROBLEM,
"Error initializing active table python", e); "Error initializing active table python", e);
} }
} finally {
if (python != null) {
python.dispose();
python = null;
}
}
return result; 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) { public Exception merge(List<ActiveTableRecord> newRecords) {
return merge(newRecords, 0.0f); 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) { public Exception merge(List<ActiveTableRecord> newRecords, float timeOffset) {
Exception exc = null; Exception exc = null;
try { try {
if (newRecords != null) { if (newRecords != null) {
String siteId = newRecords.get(0).getOfficeid(); String siteId = SiteUtil.getSite();
siteId = SiteMap.getInstance().getSite4LetterId(siteId);
updateActiveTable(siteId, newRecords, timeOffset); updateActiveTable(siteId, newRecords, timeOffset);
} }
} catch (Throwable t) { } 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) public static void clearPracticeTable(String requestedSiteId)
throws DataAccessLayerException { throws DataAccessLayerException {
CoreDao dao = practiceDao; CoreDao dao = practiceDao;
@ -544,6 +623,13 @@ public class ActiveTable {
dao.executeNativeSql(sql); dao.executeNativeSql(sql);
} }
/**
* Dump product text to temp file
*
* @param productText
* product text
* @return the temp file
*/
public static File dumpProductToTempFile(String productText) { public static File dumpProductToTempFile(String productText) {
File file = Util.createTempFile(productText.getBytes(), "vtec"); File file = Util.createTempFile(productText.getBytes(), "vtec");
file.deleteOnExit(); 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; package com.raytheon.uf.edex.activetable;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import com.raytheon.edex.esb.Headers; import com.raytheon.edex.esb.Headers;
import com.raytheon.uf.common.activetable.ActiveTableMode; import com.raytheon.uf.common.activetable.ActiveTableMode;
import com.raytheon.uf.common.activetable.ActiveTableRecord; import com.raytheon.uf.common.activetable.ActiveTableRecord;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord; import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
import com.raytheon.uf.common.status.IUFStatusHandler; 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;
import com.raytheon.uf.common.status.UFStatus.Priority; 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 * 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 * Mar 17, 2009 njensen Initial creation
* Jul 14, 2009 #2950 njensen Multiple site support * Jul 14, 2009 #2950 njensen Multiple site support
* Dec 21, 2009 #4055 njensen No site filtering * Dec 21, 2009 #4055 njensen No site filtering
* Jun 17, 2014 3296 randerso Added performance logging
* *
* </pre> * </pre>
* *
@ -54,16 +56,30 @@ public class ActiveTableSrv {
private static final transient IUFStatusHandler statusHandler = UFStatus private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ActiveTableSrv.class); .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) { public void vtecArrived(List<AbstractWarningRecord> records) {
ITimer timer = TimeUtil.getTimer();
timer.start();
try { try {
long threadId = Thread.currentThread().getId(); ActiveTable activeTable = threadLocalActiveTable.get();
ActiveTable activeTable = activeTableMap.get(threadId);
if (activeTable == null) {
activeTable = new ActiveTable();
activeTableMap.put(threadId, activeTable);
}
if (records != null && records.size() > 0) { if (records != null && records.size() > 0) {
activeTable.merge(ActiveTableRecord.transformFromWarnings( activeTable.merge(ActiveTableRecord.transformFromWarnings(
records, ActiveTableMode.OPERATIONAL)); records, ActiveTableMode.OPERATIONAL));
@ -72,8 +88,18 @@ public class ActiveTableSrv {
statusHandler.handle(Priority.PROBLEM, statusHandler.handle(Priority.PROBLEM,
"Error merging active table", t); "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, public void practiceVtecArrived(List<AbstractWarningRecord> records,
Headers headers) { Headers headers) {
Integer offsetSeconds = null; Integer offsetSeconds = null;
@ -84,12 +110,7 @@ public class ActiveTableSrv {
offsetSeconds = Integer.valueOf(0); offsetSeconds = Integer.valueOf(0);
} }
if (records != null && records.size() > 0) { if (records != null && records.size() > 0) {
long threadId = Thread.currentThread().getId(); ActiveTable activeTable = threadLocalActiveTable.get();
ActiveTable activeTable = activeTableMap.get(threadId);
if (activeTable == null) {
activeTable = new ActiveTable();
activeTableMap.put(threadId, activeTable);
}
try { try {
activeTable.merge(ActiveTableRecord.transformFromWarnings( activeTable.merge(ActiveTableRecord.transformFromWarnings(
records, ActiveTableMode.PRACTICE), offsetSeconds records, ActiveTableMode.PRACTICE), offsetSeconds

View file

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

View file

@ -1,24 +1,38 @@
## ##
# This software was developed and / or modified by Raytheon Company, # This software was developed and / or modified by Raytheon Company,
# pursuant to Contract DG133W-05-CQ-1067 with the US Government. # pursuant to Contract DG133W-05-CQ-1067 with the US Government.
# #
# U.S. EXPORT CONTROLLED TECHNICAL DATA # U.S. EXPORT CONTROLLED TECHNICAL DATA
# This software product contains export-restricted data whose # This software product contains export-restricted data whose
# export/transfer/disclosure is restricted by U.S. law. Dissemination # export/transfer/disclosure is restricted by U.S. law. Dissemination
# to non-U.S. persons whether in the United States or abroad requires # to non-U.S. persons whether in the United States or abroad requires
# an export license or other authorization. # an export license or other authorization.
# #
# Contractor Name: Raytheon Company # Contractor Name: Raytheon Company
# Contractor Address: 6825 Pine Street, Suite 340 # Contractor Address: 6825 Pine Street, Suite 340
# Mail Stop B8 # Mail Stop B8
# Omaha, NE 68106 # Omaha, NE 68106
# 402.291.0100 # 402.291.0100
# #
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for # See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information. # further licensing information.
## ##
#
# 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 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 # This class takes a VTEC active table and eliminates unnecessary
# records. Records purged consist of old SPC watches, old Tropical # records. Records purged consist of old SPC watches, old Tropical
# events, last year's records, and extraneous records not needed for # events, last year's records, and extraneous records not needed for
@ -27,7 +41,7 @@ import os, sys, time, copy, LogStream
class VTECTableSqueeze: class VTECTableSqueeze:
#constructor #constructor
def __init__(self, currentTime, debug=True): def __init__(self, currentTime, debug=False):
self.__ctime = currentTime self.__ctime = currentTime
self.__thisYear = time.gmtime(self.__ctime)[0] self.__thisYear = time.gmtime(self.__ctime)[0]
self.__debug = debug self.__debug = debug
@ -41,7 +55,11 @@ class VTECTableSqueeze:
LogStream.logDebug(self.__printActiveTable(table)) LogStream.logDebug(self.__printActiveTable(table))
# modify old UFN events (in case fcstrs didn't CAN them) # modify old UFN events (in case fcstrs didn't CAN them)
timer.reset()
timer.start()
table, modTable = self.__modifyOldUFNEvents(table) table, modTable = self.__modifyOldUFNEvents(table)
timer.stop()
perfStat.logDuration("updateActiveTable squeeze __modifyOldUFNEvents", timer.getElapsedTime());
if self.__debug: if self.__debug:
LogStream.logDebug("************** MOD UFN TABLE *********************") LogStream.logDebug("************** MOD UFN TABLE *********************")
for old, new in modTable: for old, new in modTable:
@ -50,8 +68,12 @@ class VTECTableSqueeze:
LogStream.logDebug(" -----------") LogStream.logDebug(" -----------")
# remove the national center and short fused events # remove the national center and short fused events
timer.reset()
timer.start()
shortWFO, shortNC, purgeT = \ shortWFO, shortNC, purgeT = \
self.__removeOldNationalAndShortFusedEvents(table) self.__removeOldNationalAndShortFusedEvents(table)
timer.stop()
perfStat.logDuration("updateActiveTable squeeze __removeOldNationalAndShortFusedEvents", timer.getElapsedTime());
if self.__debug: if self.__debug:
LogStream.logDebug("************** SHORT WFO TABLE *********************") LogStream.logDebug("************** SHORT WFO TABLE *********************")
LogStream.logDebug(self.__printActiveTable(shortWFO)) LogStream.logDebug(self.__printActiveTable(shortWFO))
@ -61,10 +83,18 @@ class VTECTableSqueeze:
LogStream.logDebug(self.__printActiveTable(purgeT)) LogStream.logDebug(self.__printActiveTable(purgeT))
# separate out the shortWFO into dictionary structure # separate out the shortWFO into dictionary structure
timer.reset()
timer.start()
dict = self.__separateTable(shortWFO) dict = self.__separateTable(shortWFO)
timer.stop()
perfStat.logDuration("updateActiveTable squeeze __separateTable", timer.getElapsedTime());
# purge old entries with LowerETNs that aren't in effect # purge old entries with LowerETNs that aren't in effect
timer.reset()
timer.start()
shorterT, purgeT2 = self.__purgeOldEntriesWithLowerETNs(dict) shorterT, purgeT2 = self.__purgeOldEntriesWithLowerETNs(dict)
timer.stop()
perfStat.logDuration("updateActiveTable squeeze __purgeOldEntriesWithLowerETNs", timer.getElapsedTime());
if self.__debug: if self.__debug:
LogStream.logDebug("************** TRIMMED WFO TABLE ******************") LogStream.logDebug("************** TRIMMED WFO TABLE ******************")
LogStream.logDebug(self.__printActiveTable(shorterT)) LogStream.logDebug(self.__printActiveTable(shorterT))
@ -72,12 +102,10 @@ class VTECTableSqueeze:
LogStream.logDebug(self.__printActiveTable(purgeT2)) LogStream.logDebug(self.__printActiveTable(purgeT2))
#add in any shortNC entries to final table #add in any shortNC entries to final table
for r in shortNC: shorterT.extend(shortNC)
shorterT.append(r)
#add in the purged entries from before #add in the purged entries from before
for r in purgeT2: purgeT.extend(purgeT2)
purgeT.append(r)
if self.__debug: if self.__debug:
LogStream.logDebug("************** FINAL TABLE ********************") LogStream.logDebug("************** FINAL TABLE ********************")

View file

@ -17,7 +17,14 @@
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for # See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information. # further licensing information.
## ##
# 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 copy
import cPickle import cPickle
@ -384,3 +391,14 @@ class VTECTableUtil:
return JUtil.javaObjToPyVal(javaDictFormat) 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 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated * @generated
@ -35,6 +35,7 @@
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 07/29/13 2215 bkowal Regenerated for thrift 0.9.0 * 07/29/13 2215 bkowal Regenerated for thrift 0.9.0
* 07/22/14 15649 lshi Rollback to thrift 0.8.0
* *
* </pre> * </pre>
* *
@ -43,14 +44,13 @@
*/ */
#include "Notification_types.h" #include "Notification_types.h"
#include <algorithm>
const char* com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::ascii_fingerprint = "ACE4F644F0FDD289DDC4EE5B83BC13C0"; 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}; 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 com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::read(::apache::thrift::protocol::TProtocol* iprot) {
uint32_t xfer = 0; uint32_t xfer = 0;
std::string fname; std::string fname;
::apache::thrift::protocol::TType ftype; ::apache::thrift::protocol::TType ftype;
@ -75,14 +75,14 @@ uint32_t com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::r
this->dataURIs.clear(); this->dataURIs.clear();
uint32_t _size0; uint32_t _size0;
::apache::thrift::protocol::TType _etype3; ::apache::thrift::protocol::TType _etype3;
xfer += iprot->readListBegin(_etype3, _size0); iprot->readListBegin(_etype3, _size0);
this->dataURIs.resize(_size0); this->dataURIs.resize(_size0);
uint32_t _i4; uint32_t _i4;
for (_i4 = 0; _i4 < _size0; ++_i4) for (_i4 = 0; _i4 < _size0; ++_i4)
{ {
xfer += iprot->readString(this->dataURIs[_i4]); xfer += iprot->readString(this->dataURIs[_i4]);
} }
xfer += iprot->readListEnd(); iprot->readListEnd();
} }
this->__isset.dataURIs = true; this->__isset.dataURIs = true;
} else { } 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 com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage::write(::apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0; uint32_t xfer = 0;
xfer += oprot->writeStructBegin("com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage"); xfer += oprot->writeStructBegin("com_raytheon_uf_common_dataplugin_message_DataURINotificationMessage");
xfer += oprot->writeFieldBegin("dataURIs", ::apache::thrift::protocol::T_LIST, 1); 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())); 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->writeListEnd();
} }
xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop(); xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd(); xfer += oprot->writeStructEnd();
return xfer; 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 * COPYRIGHT (c), 2009, RAYTHEON COMPANY
* ALL RIGHTS RESERVED, An Unpublished Work * 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> * <pre>
* *
@ -34,13 +28,21 @@
* *
* Date Ticket# Engineer Description * 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> * </pre>
* *
* @author bkowal * @author gzhou
* @version 1 * @version 1
*/ */
/**
* Autogenerated by Thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
*/
#include "PointDataServer_constants.h" #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 * COPYRIGHT (c), 2009, RAYTHEON COMPANY
* ALL RIGHTS RESERVED, An Unpublished Work * 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> * <pre>
* *
@ -34,240 +28,222 @@
* *
* Date Ticket# Engineer Description * 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> * </pre>
* *
* @author bkowal * @author gzhou
* @version 1 * @version 1
*/ */
#include "PointDataServer_types.h" #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"; xfer += iprot->readStructBegin(fname);
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) { using ::apache::thrift::protocol::TProtocolException;
uint32_t xfer = 0; xfer += iprot->readFieldBegin(fname, ftype, fid);
std::string fname; if (ftype == ::apache::thrift::protocol::T_STRING) {
::apache::thrift::protocol::TType ftype; xfer += iprot->readString(operand);
int16_t fid; this->__isset.operand = true;
} else
xfer += iprot->skip(ftype);
xfer += iprot->readFieldEnd();
xfer += iprot->readStructBegin(fname); xfer += iprot->readStructEnd();
using ::apache::thrift::protocol::TProtocolException; return xfer;
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;
} }
uint32_t com_raytheon_uf_common_dataquery_requests_ConstraintType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t com_raytheon_uf_common_dataquery_requests_ConstraintType::write(
uint32_t xfer = 0; ::apache::thrift::protocol::TProtocol* oprot) const {
xfer += oprot->writeStructBegin("com_raytheon_uf_common_dataquery_requests_ConstraintType"); uint32_t xfer = 0;
xfer
xfer += oprot->writeFieldBegin("operand", ::apache::thrift::protocol::T_STRING, 1); += oprot->writeStructBegin(
xfer += oprot->writeString(this->operand); "com_raytheon_uf_common_dataquery_requests_RequestConstraint$ConstraintType");
xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldBegin("__enumValue__",
::apache::thrift::protocol::T_STRING, 1);
xfer += oprot->writeFieldStop(); xfer += oprot->writeString(this->operand);
xfer += oprot->writeStructEnd(); xfer += oprot->writeFieldEnd();
return xfer; xfer += oprot->writeStructEnd();
return xfer;
} }
void swap(com_raytheon_uf_common_dataquery_requests_ConstraintType &a, com_raytheon_uf_common_dataquery_requests_ConstraintType &b) { const char
using ::std::swap; * com_raytheon_uf_common_dataquery_requests_RequestConstraint::ascii_fingerprint =
swap(a.operand, b.operand); "BDAF55DAA660FA1ADBE30760752211A8";
swap(a.__isset, b.__isset); 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"; uint32_t com_raytheon_uf_common_dataquery_requests_RequestConstraint::write(
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}; ::apache::thrift::protocol::TProtocol* oprot) const {
uint32_t xfer = 0;
uint32_t com_raytheon_uf_common_dataquery_requests_RequestConstraint::read(::apache::thrift::protocol::TProtocol* iprot) { xfer += oprot->writeStructBegin(
"com_raytheon_uf_common_dataquery_requests_RequestConstraint");
uint32_t xfer = 0; xfer += oprot->writeFieldBegin("constraintType",
std::string fname; ::apache::thrift::protocol::T_STRUCT, 1);
::apache::thrift::protocol::TType ftype; xfer += this->constraintType.write(oprot);
int16_t fid; xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("constraintValue",
xfer += iprot->readStructBegin(fname); ::apache::thrift::protocol::T_STRING, 2);
xfer += oprot->writeString(this->constraintValue);
using ::apache::thrift::protocol::TProtocolException; xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldStop();
xfer += oprot->writeStructEnd();
while (true) return xfer;
{
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 { const char
uint32_t xfer = 0; * com_raytheon_uf_common_pointdata_PointDataServerRequest::ascii_fingerprint =
xfer += oprot->writeStructBegin("com_raytheon_uf_common_dataquery_requests_RequestConstraint"); "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); uint32_t com_raytheon_uf_common_pointdata_PointDataServerRequest::read(
xfer += this->constraintType.write(oprot); ::apache::thrift::protocol::TProtocol* iprot) {
xfer += oprot->writeFieldEnd();
xfer += oprot->writeFieldBegin("constraintValue", ::apache::thrift::protocol::T_STRING, 2); uint32_t xfer = 0;
xfer += oprot->writeString(this->constraintValue); std::string fname;
xfer += oprot->writeFieldEnd(); ::apache::thrift::protocol::TType ftype;
int16_t fid;
xfer += oprot->writeFieldStop(); xfer += iprot->readStructBegin(fname);
xfer += oprot->writeStructEnd();
return xfer; 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) { uint32_t com_raytheon_uf_common_pointdata_PointDataServerRequest::write(
using ::std::swap; ::apache::thrift::protocol::TProtocol* oprot) const {
swap(a.constraintType, b.constraintType); uint32_t xfer = 0;
swap(a.constraintValue, b.constraintValue); xfer += oprot->writeStructBegin(
swap(a.__isset, b.__isset); "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 * COPYRIGHT (c), 2009, RAYTHEON COMPANY
* ALL RIGHTS RESERVED, An Unpublished Work * 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> * <pre>
* *
@ -34,13 +28,21 @@
* *
* Date Ticket# Engineer Description * 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> * </pre>
* *
* @author bkowal * @author brockwoo
* @version 1 * @version 1
*/ */
/**
* Autogenerated by Thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
*/
#include "PointData_constants.h" #include "PointData_constants.h"

File diff suppressed because it is too large Load diff