Merge "Issue #1149 Refactored watches and warnings." into development
Former-commit-id:c9043f7ff6
[formerlyea144452d4
] [formerlyedb8599f27
[formerly 1ef0b64db34020d82251b177e85091de53795bcb]] Former-commit-id:edb8599f27
Former-commit-id:e3c4d1f162
This commit is contained in:
commit
be8d83bd2b
7 changed files with 1087 additions and 1652 deletions
|
@ -2,19 +2,59 @@ package com.raytheon.viz.warnings.rsc;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.eclipse.swt.graphics.RGB;
|
||||||
|
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||||
|
|
||||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.PracticeWarningRecord;
|
import com.raytheon.uf.common.dataplugin.warning.PracticeWarningRecord;
|
||||||
|
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
||||||
|
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||||
|
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
|
||||||
|
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
|
||||||
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
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.TimeRange;
|
||||||
|
import com.raytheon.uf.viz.core.DrawableString;
|
||||||
|
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||||
|
import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment;
|
||||||
|
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
|
||||||
|
import com.raytheon.uf.viz.core.IGraphicsTarget.TextStyle;
|
||||||
|
import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment;
|
||||||
|
import com.raytheon.uf.viz.core.VizApp;
|
||||||
|
import com.raytheon.uf.viz.core.catalog.LayerProperty;
|
||||||
|
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
|
||||||
|
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
|
||||||
|
import com.raytheon.uf.viz.core.drawables.IFont;
|
||||||
|
import com.raytheon.uf.viz.core.drawables.IShadedShape;
|
||||||
|
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
|
||||||
|
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.uf.viz.core.map.MapDescriptor;
|
import com.raytheon.uf.viz.core.map.MapDescriptor;
|
||||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||||
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
|
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
|
||||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
||||||
|
import com.raytheon.uf.viz.core.rsc.ResourceType;
|
||||||
|
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
|
||||||
|
import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
|
||||||
|
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
|
||||||
import com.raytheon.viz.core.mode.CAVEMode;
|
import com.raytheon.viz.core.mode.CAVEMode;
|
||||||
import com.raytheon.viz.warnings.DateUtil;
|
import com.raytheon.viz.warnings.DateUtil;
|
||||||
|
import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||||
|
import com.vividsolutions.jts.geom.Point;
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -33,6 +73,7 @@ import com.raytheon.viz.warnings.DateUtil;
|
||||||
* May 31, 2012 DR14992 mgamazaychikov Changed the order of strings in the
|
* May 31, 2012 DR14992 mgamazaychikov Changed the order of strings in the
|
||||||
* String array returned from getText method
|
* String array returned from getText method
|
||||||
* Jun 04, 2012 DR14992 mgamazaychikov Reversed the previous changes
|
* Jun 04, 2012 DR14992 mgamazaychikov Reversed the previous changes
|
||||||
|
* Sep 26, 2012 jsanchez Refactored AbstractWarningResource and AbstractWatchesResource into this class.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -42,6 +83,60 @@ import com.raytheon.viz.warnings.DateUtil;
|
||||||
public abstract class AbstractWWAResource extends
|
public abstract class AbstractWWAResource extends
|
||||||
AbstractVizResource<WWAResourceData, MapDescriptor> implements
|
AbstractVizResource<WWAResourceData, MapDescriptor> implements
|
||||||
IResourceDataChanged {
|
IResourceDataChanged {
|
||||||
|
protected static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
|
.getHandler(AbstractWWAResource.class);
|
||||||
|
|
||||||
|
protected class WarningEntry {
|
||||||
|
|
||||||
|
protected AbstractWarningRecord record;
|
||||||
|
|
||||||
|
protected IWireframeShape wireframeShape;
|
||||||
|
|
||||||
|
protected IShadedShape shadedShape;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* whether or not the warning has been altered, ie CON, CAN, EXP. a
|
||||||
|
* warning can only be altered once with the exception of a partial
|
||||||
|
* cancel.
|
||||||
|
**/
|
||||||
|
protected boolean altered = false;
|
||||||
|
|
||||||
|
protected Date timeAltered;
|
||||||
|
|
||||||
|
protected Date frameAltered;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* was the alter a partial cancel? if it was then a matching CON should
|
||||||
|
* be processed and added
|
||||||
|
*/
|
||||||
|
protected boolean partialCancel = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set to true if paint needs to re-init the shape
|
||||||
|
*/
|
||||||
|
protected boolean project = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static GeometryFactory gf = new GeometryFactory();
|
||||||
|
|
||||||
|
protected static PreparedGeometryFactory pgf = new PreparedGeometryFactory();
|
||||||
|
|
||||||
|
/** one hour ahead, entirely arbitrary/magic **/
|
||||||
|
private static final long LAST_FRAME_ADJ = (60 * 60 * 1000);
|
||||||
|
|
||||||
|
protected String resourceName;
|
||||||
|
|
||||||
|
/** map of dataURI to a warning entry **/
|
||||||
|
protected Map<String, WarningEntry> entryMap;
|
||||||
|
|
||||||
|
protected IFont warningsFont;
|
||||||
|
|
||||||
|
protected RGB color;
|
||||||
|
|
||||||
|
protected DataTime earliestRequested;
|
||||||
|
|
||||||
|
protected final Object paintLock = new Object();
|
||||||
|
|
||||||
private static final DataTime[] dataTimes = AbstractVizResource.TIME_AGNOSTIC
|
private static final DataTime[] dataTimes = AbstractVizResource.TIME_AGNOSTIC
|
||||||
.toArray(new DataTime[0]);
|
.toArray(new DataTime[0]);
|
||||||
|
@ -57,13 +152,23 @@ public abstract class AbstractWWAResource extends
|
||||||
|
|
||||||
protected List<AbstractWarningRecord> recordsToLoad;
|
protected List<AbstractWarningRecord> recordsToLoad;
|
||||||
|
|
||||||
|
protected WarningRecordComparator comparator = new WarningRecordComparator();
|
||||||
|
|
||||||
|
protected abstract void updateDisplay(IGraphicsTarget target)
|
||||||
|
throws VizException;
|
||||||
|
|
||||||
|
protected abstract void initShape(IGraphicsTarget target,
|
||||||
|
AbstractWarningRecord record) throws VizException;
|
||||||
|
|
||||||
public AbstractWWAResource(WWAResourceData data, LoadProperties props) {
|
public AbstractWWAResource(WWAResourceData data, LoadProperties props) {
|
||||||
super(data, props);
|
super(data, props);
|
||||||
this.recordsToLoad = new ArrayList<AbstractWarningRecord>();
|
this.recordsToLoad = new ArrayList<AbstractWarningRecord>();
|
||||||
|
resourceData.addChangeListener(this);
|
||||||
|
getCapability(OutlineCapability.class).setOutlineWidth(2);
|
||||||
|
color = getCapability((ColorableCapability.class)).getColor();
|
||||||
|
this.entryMap = new ConcurrentHashMap<String, WarningEntry>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final WarningRecordComparator comparator = new WarningRecordComparator();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
|
@ -79,6 +184,316 @@ public abstract class AbstractWWAResource extends
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String inspect(ReferencedCoordinate coord) throws VizException {
|
||||||
|
if (resourceData.hideSampling) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
// check if we are in the last frame
|
||||||
|
boolean lastFrame = false;
|
||||||
|
FramesInfo framesInfo = this.descriptor.getFramesInfo();
|
||||||
|
int frameIdx = framesInfo.getFrameIndex();
|
||||||
|
DataTime[] frameTimes = framesInfo.getFrameTimes();
|
||||||
|
if (frameIdx < 0 || frameIdx >= frameTimes.length)
|
||||||
|
return "NO DATA";
|
||||||
|
DataTime time = frameTimes[frameIdx];
|
||||||
|
|
||||||
|
TimeRange framePeriod = null;
|
||||||
|
if (frameIdx + 1 < frameTimes.length) {
|
||||||
|
framePeriod = new TimeRange(time.getRefTime(),
|
||||||
|
frameTimes[frameIdx + 1].getRefTime());
|
||||||
|
} else {
|
||||||
|
framePeriod = new TimeRange(time.getRefTime(), LAST_FRAME_ADJ);
|
||||||
|
lastFrame = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time != null) {
|
||||||
|
try {
|
||||||
|
Point point = gf.createPoint(coord.asLatLon());
|
||||||
|
|
||||||
|
for (String key : entryMap.keySet()) {
|
||||||
|
|
||||||
|
WarningEntry entry = entryMap.get(key);
|
||||||
|
AbstractWarningRecord record = entry.record;
|
||||||
|
if (matchesFrame(entry, time, framePeriod, lastFrame)) {
|
||||||
|
|
||||||
|
Geometry recordGeom = record.getGeometry();
|
||||||
|
for (int i = 0; i < recordGeom.getNumGeometries(); i++) {
|
||||||
|
PreparedGeometry prepGeom = pgf.create(recordGeom
|
||||||
|
.getGeometryN(i));
|
||||||
|
|
||||||
|
if (prepGeom.contains(point)) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
String[] textToPrint = getText(record, 0);
|
||||||
|
for (String text : textToPrint) {
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.append(" ");
|
||||||
|
}
|
||||||
|
sb.append(text);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new VizException("Error inspecting resource", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return "NO DATA";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void disposeEntry(final WarningEntry entry) {
|
||||||
|
if (entry.wireframeShape != null || entry.shadedShape != null) {
|
||||||
|
VizApp.runAsync(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (entry.shadedShape != null) {
|
||||||
|
entry.shadedShape.dispose();
|
||||||
|
}
|
||||||
|
if (entry.wireframeShape != null) {
|
||||||
|
entry.wireframeShape.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void project(CoordinateReferenceSystem crs) throws VizException {
|
||||||
|
synchronized (paintLock) {
|
||||||
|
for (Map.Entry<String, WarningEntry> entry : entryMap.entrySet()) {
|
||||||
|
WarningEntry warning = entry.getValue();
|
||||||
|
// dispose and set to null just to be safe
|
||||||
|
if (warning.shadedShape != null) {
|
||||||
|
warning.shadedShape.dispose();
|
||||||
|
warning.shadedShape = null;
|
||||||
|
}
|
||||||
|
if (warning.wireframeShape != null) {
|
||||||
|
warning.wireframeShape.dispose();
|
||||||
|
warning.wireframeShape = null;
|
||||||
|
}
|
||||||
|
warning.project = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintInternal(IGraphicsTarget target,
|
||||||
|
PaintProperties paintProps) throws VizException {
|
||||||
|
FramesInfo info = paintProps.getFramesInfo();
|
||||||
|
DataTime[] frames = info.getFrameTimes();
|
||||||
|
int frameToRequestedCompare = frames[0].compareTo(earliestRequested);
|
||||||
|
if (frameToRequestedCompare < 0) {
|
||||||
|
// we haven't requested data this far back
|
||||||
|
this.requestData(frames[0]);
|
||||||
|
} else if (frameToRequestedCompare > 0) {
|
||||||
|
// the previous earliest frame was removed as updates came in, so
|
||||||
|
// the warnings need to be disposed and we need to update the
|
||||||
|
// earliestRequested so if they ever went back in time to that
|
||||||
|
// again, it would be re-requested
|
||||||
|
earliestRequested = frames[0];
|
||||||
|
if (paintProps.getDataTime() != null) {
|
||||||
|
cleanupData(paintProps.getDataTime(), frames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int index = info.getFrameIndex();
|
||||||
|
if (!this.recordsToLoad.isEmpty()) {
|
||||||
|
this.updateDisplay(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataTime thisFrameTime = null;
|
||||||
|
if (index > -1 && index < frames.length) {
|
||||||
|
thisFrameTime = frames[index];
|
||||||
|
}
|
||||||
|
if (thisFrameTime == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeRange framePeriod = null;
|
||||||
|
boolean lastFrame = false;
|
||||||
|
if (index + 1 < frames.length) {
|
||||||
|
framePeriod = new TimeRange(thisFrameTime.getRefTime(),
|
||||||
|
frames[index + 1].getRefTime());
|
||||||
|
} else {
|
||||||
|
framePeriod = new TimeRange(thisFrameTime.getRefTime(),
|
||||||
|
LAST_FRAME_ADJ);
|
||||||
|
lastFrame = true;
|
||||||
|
}
|
||||||
|
synchronized (paintLock) {
|
||||||
|
HashMap<String, WarningEntry> candidates = new HashMap<String, WarningEntry>();
|
||||||
|
for (WarningEntry entry : entryMap.values()) {
|
||||||
|
if (matchesFrame(entry, paintProps.getDataTime(), framePeriod,
|
||||||
|
lastFrame)) {
|
||||||
|
String key = getEventKey(entry);
|
||||||
|
WarningEntry current = candidates.get(key);
|
||||||
|
|
||||||
|
if (current == null
|
||||||
|
|| current.record.getIssueTime().before(
|
||||||
|
entry.record.getIssueTime())
|
||||||
|
|| (current.record.getIssueTime().equals(
|
||||||
|
entry.record.getIssueTime()) && current.record
|
||||||
|
.getInsertTime().before(
|
||||||
|
entry.record.getInsertTime())))
|
||||||
|
candidates.put(key, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (WarningEntry entry : candidates.values()) {
|
||||||
|
AbstractWarningRecord record = entry.record;
|
||||||
|
|
||||||
|
// check shapes
|
||||||
|
if (entry.project) {
|
||||||
|
initShape(target, entry.record);
|
||||||
|
entry.project = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry != null && entry.wireframeShape != null) {
|
||||||
|
LineStyle lineStyle = (record.getProductClass() != null && record
|
||||||
|
.getProductClass().equals("T")) ? LineStyle.DASHED
|
||||||
|
: LineStyle.SOLID;
|
||||||
|
target.drawWireframeShape(
|
||||||
|
entry.wireframeShape,
|
||||||
|
getCapability(ColorableCapability.class).getColor(),
|
||||||
|
getCapability(OutlineCapability.class)
|
||||||
|
.getOutlineWidth(), lineStyle);
|
||||||
|
} else if (entry != null && entry.shadedShape != null) {
|
||||||
|
target.drawShadedShape(entry.shadedShape, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (record != null && record.getGeometry() != null) {
|
||||||
|
// Calculate the upper left portion of the polygon
|
||||||
|
Coordinate upperLeft = new Coordinate(180, -90);
|
||||||
|
|
||||||
|
for (Coordinate c : record.getGeometry().getCoordinates()) {
|
||||||
|
if (c.y - c.x > upperLeft.y - upperLeft.x) {
|
||||||
|
upperLeft = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double[] d = descriptor.worldToPixel(new double[] {
|
||||||
|
upperLeft.x, upperLeft.y });
|
||||||
|
d[0] -= paintProps.getZoomLevel() * 100;
|
||||||
|
|
||||||
|
double mapWidth = descriptor.getMapWidth()
|
||||||
|
* paintProps.getZoomLevel() / 1000;
|
||||||
|
String[] textToPrint = getText(record, mapWidth);
|
||||||
|
if (warningsFont == null) {
|
||||||
|
warningsFont = target.getDefaultFont().deriveWithSize(
|
||||||
|
11);
|
||||||
|
}
|
||||||
|
// DR14992: reverse the textToPrint array to plot the
|
||||||
|
// strings in correct order
|
||||||
|
String[] textToPrintReversed = new String[textToPrint.length];
|
||||||
|
for (int i = 0; i < textToPrint.length; i++) {
|
||||||
|
textToPrintReversed[i] = textToPrint[textToPrint.length
|
||||||
|
- i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawableString params = new DrawableString(
|
||||||
|
textToPrintReversed, color);
|
||||||
|
params.font = warningsFont;
|
||||||
|
params.setCoordinates(d[0], d[1]);
|
||||||
|
params.textStyle = TextStyle.NORMAL;
|
||||||
|
params.horizontalAlignment = HorizontalAlignment.RIGHT;
|
||||||
|
params.verticallAlignment = VerticalAlignment.BOTTOM;
|
||||||
|
params.magnification = getCapability(
|
||||||
|
MagnificationCapability.class).getMagnification();
|
||||||
|
target.drawStrings(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected String getEventKey(WarningEntry entry);
|
||||||
|
|
||||||
|
protected boolean matchesFrame(WarningEntry entry, DataTime paintTime,
|
||||||
|
TimeRange framePeriod, boolean lastFrame) {
|
||||||
|
TimeRange recordPeriod = new TimeRange(entry.record.getStartTime()
|
||||||
|
.getTimeInMillis(), entry.record.getEndTime().getTimeInMillis());
|
||||||
|
long diff = entry.record.getEndTime().getTimeInMillis()
|
||||||
|
- entry.record.getStartTime().getTimeInMillis();
|
||||||
|
Date centerTime = new Date(entry.record.getStartTime()
|
||||||
|
.getTimeInMillis() + (diff / 2));
|
||||||
|
Date frameTime = framePeriod.getStart();
|
||||||
|
|
||||||
|
Date frameStart = framePeriod.getStart();
|
||||||
|
Date refTime = entry.record.getDataTime().getRefTime();
|
||||||
|
|
||||||
|
if (lastFrame) {
|
||||||
|
// use current system time to determine what to display
|
||||||
|
Date timeToDisplay = SimulatedTime.getSystemTime().getTime();
|
||||||
|
// change frame time
|
||||||
|
frameTime = timeToDisplay;
|
||||||
|
// point paint time to different time
|
||||||
|
paintTime = new DataTime(timeToDisplay);
|
||||||
|
// point framePeriod to new frame
|
||||||
|
framePeriod = new TimeRange(frameTime, LAST_FRAME_ADJ);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the warning is cancelled
|
||||||
|
WarningAction action = WarningAction.valueOf(entry.record.getAct());
|
||||||
|
if (action == WarningAction.CAN && refTime.equals(paintTime)) {
|
||||||
|
return false;
|
||||||
|
// If this entry has been altered/updated, display its pre-altered
|
||||||
|
// version
|
||||||
|
// only in the frames prior to the time it was altered
|
||||||
|
} else if (entry.altered) {
|
||||||
|
if (frameStart.getTime() >= refTime.getTime()
|
||||||
|
&& frameStart.getTime() < (entry.timeAltered.getTime())
|
||||||
|
&& frameStart.getTime() < entry.frameAltered.getTime())
|
||||||
|
return true;
|
||||||
|
if (frameStart.getTime() >= (entry.timeAltered.getTime()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (refTime.equals(paintTime)
|
||||||
|
|| recordPeriod.contains(frameTime)
|
||||||
|
|| (framePeriod.contains(centerTime) && (!lastFrame || !entry.altered))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cleanupData(DataTime paintTime, DataTime[] descFrameTimes) {
|
||||||
|
System.out.println("entryMap size " + entryMap.size());
|
||||||
|
List<TimeRange> framePeriods = new ArrayList<TimeRange>(
|
||||||
|
descFrameTimes.length);
|
||||||
|
for (int i = 0; i < descFrameTimes.length; i++) {
|
||||||
|
if (i == descFrameTimes.length - 1) {
|
||||||
|
framePeriods.add(new TimeRange(descFrameTimes[i].getRefTime(),
|
||||||
|
LAST_FRAME_ADJ));
|
||||||
|
} else {
|
||||||
|
framePeriods.add(new TimeRange(descFrameTimes[i].getRefTime(),
|
||||||
|
descFrameTimes[i + 1].getRefTime()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = framePeriods.size();
|
||||||
|
List<String> toRemove = new ArrayList<String>();
|
||||||
|
for (String key : entryMap.keySet()) {
|
||||||
|
WarningEntry entry = entryMap.get(key);
|
||||||
|
boolean found = false;
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
TimeRange tr = framePeriods.get(i);
|
||||||
|
if (matchesFrame(entry, paintTime, tr, (i == size - 1))) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
toRemove.add(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String key : toRemove) {
|
||||||
|
WarningEntry entry = entryMap.remove(key);
|
||||||
|
System.out.println("removing " + entry.record.getDataURI());
|
||||||
|
disposeEntry(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void addRecord(PluginDataObject[] pdos)
|
public synchronized void addRecord(PluginDataObject[] pdos)
|
||||||
throws VizException {
|
throws VizException {
|
||||||
for (PluginDataObject pdo : pdos) {
|
for (PluginDataObject pdo : pdos) {
|
||||||
|
@ -94,6 +509,59 @@ public abstract class AbstractWWAResource extends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected PluginDataObject[] sort(PluginDataObject[] pdos) {
|
||||||
|
ArrayList<AbstractWarningRecord> sortedWarnings = new ArrayList<AbstractWarningRecord>();
|
||||||
|
for (Object o : pdos) {
|
||||||
|
if (((PluginDataObject) o) instanceof AbstractWarningRecord) {
|
||||||
|
AbstractWarningRecord record = (AbstractWarningRecord) o;
|
||||||
|
sortedWarnings.add(record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sorts by phensig, etn, starttime (descending), act */
|
||||||
|
Collections.sort(sortedWarnings, comparator);
|
||||||
|
return sortedWarnings.toArray(new AbstractWarningRecord[sortedWarnings
|
||||||
|
.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void requestData(DataTime earliest) throws VizException {
|
||||||
|
System.out.println("requesting data");
|
||||||
|
Map<String, RequestConstraint> map = (Map<String, RequestConstraint>) resourceData
|
||||||
|
.getMetadataMap().clone();
|
||||||
|
if (earliestRequested != null) {
|
||||||
|
// don't request data we've already requested
|
||||||
|
String[] times = new String[] { earliest.toString(),
|
||||||
|
earliestRequested.toString() };
|
||||||
|
RequestConstraint constraint = new RequestConstraint();
|
||||||
|
constraint.setConstraintType(ConstraintType.BETWEEN);
|
||||||
|
constraint.setBetweenValueList(times);
|
||||||
|
map.put("endTime", constraint);
|
||||||
|
} else {
|
||||||
|
RequestConstraint endConstraint = new RequestConstraint(
|
||||||
|
earliest.toString(), ConstraintType.GREATER_THAN_EQUALS);
|
||||||
|
map.put("endTime", endConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
earliestRequested = earliest;
|
||||||
|
|
||||||
|
LayerProperty property = new LayerProperty();
|
||||||
|
property.setDesiredProduct(ResourceType.PLAN_VIEW);
|
||||||
|
property.setEntryQueryParameters(map, false);
|
||||||
|
property.setNumberOfImages(9999);
|
||||||
|
|
||||||
|
Object[] resp = null;
|
||||||
|
resp = DataCubeContainer.getData(property, 60000).toArray(
|
||||||
|
new Object[] {});
|
||||||
|
PluginDataObject[] arr = new PluginDataObject[resp.length];
|
||||||
|
int i = 0;
|
||||||
|
for (Object o : resp) {
|
||||||
|
arr[i] = (PluginDataObject) o;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
addRecord(sort(arr));
|
||||||
|
}
|
||||||
|
|
||||||
protected String[] getText(AbstractWarningRecord record, double mapWidth) {
|
protected String[] getText(AbstractWarningRecord record, double mapWidth) {
|
||||||
String vid = record.getPhensig();
|
String vid = record.getPhensig();
|
||||||
String phen = record.getPhen();
|
String phen = record.getPhen();
|
||||||
|
@ -147,4 +615,33 @@ public abstract class AbstractWWAResource extends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
String name = resourceData.name != null ? resourceData.name
|
||||||
|
: resourceName;
|
||||||
|
|
||||||
|
DataTime[] times = this.descriptor.getFramesInfo().getFrameTimes();
|
||||||
|
int timeIdx = this.descriptor.getFramesInfo().getFrameIndex();
|
||||||
|
|
||||||
|
// handle last frame differently, it should always be the latest time
|
||||||
|
boolean lastFrame = false;
|
||||||
|
if (timeIdx == times.length - 1) {
|
||||||
|
lastFrame = true;
|
||||||
|
}
|
||||||
|
DataTime time = null;
|
||||||
|
|
||||||
|
// get time to display
|
||||||
|
if (lastFrame) {
|
||||||
|
time = new DataTime(SimulatedTime.getSystemTime().getTime());
|
||||||
|
} else if (timeIdx > -1 && timeIdx < times.length) {
|
||||||
|
time = times[timeIdx];
|
||||||
|
}
|
||||||
|
|
||||||
|
// add time to legend
|
||||||
|
if (time != null) {
|
||||||
|
name += " " + time.getLegendString();
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,763 +0,0 @@
|
||||||
package com.raytheon.viz.warnings.rsc;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import org.eclipse.swt.graphics.RGB;
|
|
||||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
|
||||||
|
|
||||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
|
||||||
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
|
||||||
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
|
||||||
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
|
|
||||||
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.DataTime;
|
|
||||||
import com.raytheon.uf.common.time.SimulatedTime;
|
|
||||||
import com.raytheon.uf.common.time.TimeRange;
|
|
||||||
import com.raytheon.uf.viz.core.DrawableString;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget.TextStyle;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment;
|
|
||||||
import com.raytheon.uf.viz.core.VizApp;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.IFont;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.IRenderableDisplay;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.IShadedShape;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
|
|
||||||
import com.vividsolutions.jts.geom.Coordinate;
|
|
||||||
import com.vividsolutions.jts.geom.Geometry;
|
|
||||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
|
||||||
import com.vividsolutions.jts.geom.Point;
|
|
||||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
|
||||||
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* TODO njensen: This was a refactored version of AbstractWWAResource. The
|
|
||||||
* WatchesResource was not refactored to work with it. Ideally this class and
|
|
||||||
* AbstractWWAResource should be combined so it supports both watches and
|
|
||||||
* warnings.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
*
|
|
||||||
* SOFTWARE HISTORY
|
|
||||||
*
|
|
||||||
* Date Ticket# Engineer Description
|
|
||||||
* ------------ ---------- ----------- --------------------------
|
|
||||||
* May 3, 2011 jsanchez Initial creation
|
|
||||||
* Aug 5, 2011 njensen Refactored maps
|
|
||||||
* Aug 22, 2011 10631 njensen Major refactor
|
|
||||||
* 2012-04-16 DR 14866 D. Friedman Fix sampling error
|
|
||||||
* May 3, 2012 DR 14741 porricel Updated matchesFrame function
|
|
||||||
* to make SVS warning updates and
|
|
||||||
* original warning display properly
|
|
||||||
* in a given display frame
|
|
||||||
* Jun 04, 2012 DR14992 mgamazaychikov Reversed the textToPrint array to
|
|
||||||
* plot the strings in correct order
|
|
||||||
* Aug 09, 2012 DR 15166 D.Friedman Plot only the most recent record for
|
|
||||||
* an event.
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author jsanchez
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
public abstract class AbstractWarningResource extends AbstractWWAResource
|
|
||||||
implements IResourceDataChanged {
|
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
|
||||||
.getHandler(AbstractWarningResource.class);
|
|
||||||
|
|
||||||
private static GeometryFactory gf = new GeometryFactory();
|
|
||||||
|
|
||||||
private static PreparedGeometryFactory pgf = new PreparedGeometryFactory();
|
|
||||||
|
|
||||||
protected static class RepaintHeartbeat extends TimerTask {
|
|
||||||
|
|
||||||
private HashSet<AbstractVizResource<?, ?>> resourceSet = new HashSet<AbstractVizResource<?, ?>>();
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
public RepaintHeartbeat() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* copy resources from old task, just in case some were added after it
|
|
||||||
* should have been replaced (threads are fun)
|
|
||||||
**/
|
|
||||||
public void copyResourceSet(RepaintHeartbeat oldTask) {
|
|
||||||
// copy resources, in case one was added after a cancel
|
|
||||||
Set<AbstractVizResource<?, ?>> oldResourceSet = oldTask
|
|
||||||
.getResourceSet();
|
|
||||||
synchronized (oldResourceSet) {
|
|
||||||
for (AbstractVizResource<?, ?> rsc : oldResourceSet) {
|
|
||||||
this.addResource(rsc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<AbstractVizResource<?, ?>> getResourceSet() {
|
|
||||||
return resourceSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// get the unique displays from all the added resources
|
|
||||||
ArrayList<IRenderableDisplay> displaysToRefresh = new ArrayList<IRenderableDisplay>(
|
|
||||||
1);
|
|
||||||
synchronized (resourceSet) {
|
|
||||||
for (AbstractVizResource<?, ?> rsc : resourceSet) {
|
|
||||||
try {
|
|
||||||
IRenderableDisplay disp = rsc.getDescriptor()
|
|
||||||
.getRenderableDisplay();
|
|
||||||
if (!displaysToRefresh.contains(disp)) {
|
|
||||||
displaysToRefresh.add(disp);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
statusHandler
|
|
||||||
.handle(Priority.PROBLEM,
|
|
||||||
"Encountered error during Warnings Heartbeat, continuing with other Warnings ",
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create an array with final modifier
|
|
||||||
final IRenderableDisplay[] refreshList = displaysToRefresh
|
|
||||||
.toArray(new IRenderableDisplay[displaysToRefresh.size()]);
|
|
||||||
|
|
||||||
// execute refersh in UI thread
|
|
||||||
VizApp.runAsync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (IRenderableDisplay disp : refreshList) {
|
|
||||||
disp.refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// cancel the task if there are no more resources
|
|
||||||
boolean cancel = false;
|
|
||||||
synchronized (resourceSet) {
|
|
||||||
if (resourceSet.size() < 1) {
|
|
||||||
cancel = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancel) {
|
|
||||||
doCancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addResource(AbstractVizResource<?, ?> rsc) {
|
|
||||||
// if task has no resources then it needs to be started when the
|
|
||||||
// first is added
|
|
||||||
boolean start = false;
|
|
||||||
synchronized (resourceSet) {
|
|
||||||
// if this is the first resource added to an empty set start the
|
|
||||||
// timer
|
|
||||||
if (resourceSet.size() < 1) {
|
|
||||||
start = true;
|
|
||||||
}
|
|
||||||
resourceSet.add(rsc);
|
|
||||||
}
|
|
||||||
if (start) {
|
|
||||||
AbstractWarningResource.scheduleHeartBeat();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeResource(AbstractVizResource<?, ?> rsc) {
|
|
||||||
synchronized (resourceSet) {
|
|
||||||
resourceSet.remove(rsc);
|
|
||||||
// cancel the task if there are no more resources
|
|
||||||
if (resourceSet.size() < 1) {
|
|
||||||
doCancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doCancel() {
|
|
||||||
synchronized (heartBeatChangeLock) {
|
|
||||||
if (cancelled == false) {
|
|
||||||
cancelled = true;
|
|
||||||
heartBeatTimer.cancel();
|
|
||||||
heartBeatTask = new RepaintHeartbeat();
|
|
||||||
heartBeatTimer = new Timer();
|
|
||||||
heartBeatTask.copyResourceSet(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** lock when changing heartBeatTask **/
|
|
||||||
protected static final Object heartBeatChangeLock = new Object();
|
|
||||||
|
|
||||||
protected static RepaintHeartbeat heartBeatTask = null;
|
|
||||||
|
|
||||||
protected static Timer heartBeatTimer = null;
|
|
||||||
|
|
||||||
/** one hour ahead, entirely arbitrary/magic **/
|
|
||||||
private static final long LAST_FRAME_ADJ = (60 * 60 * 1000);
|
|
||||||
|
|
||||||
protected class WarningEntry {
|
|
||||||
|
|
||||||
protected AbstractWarningRecord record;
|
|
||||||
|
|
||||||
protected IWireframeShape wireframeShape;
|
|
||||||
|
|
||||||
protected IShadedShape shadedShape;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* whether or not the warning has been altered, ie CON, CAN, EXP. a
|
|
||||||
* warning can only be altered once with the exception of a partial
|
|
||||||
* cancel.
|
|
||||||
**/
|
|
||||||
protected boolean altered = false;
|
|
||||||
|
|
||||||
protected Date timeAltered;
|
|
||||||
|
|
||||||
protected Date frameAltered;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* was the alter a partial cancel? if it was then a matching CON should
|
|
||||||
* be processed and added
|
|
||||||
*/
|
|
||||||
protected boolean partialCancel = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set to true if paint needs to re-init the shape
|
|
||||||
*/
|
|
||||||
protected boolean project = false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** map of dataURI to a warning entry **/
|
|
||||||
protected Map<String, WarningEntry> entryMap;
|
|
||||||
|
|
||||||
protected IFont warningsFont;
|
|
||||||
|
|
||||||
protected RGB color;
|
|
||||||
|
|
||||||
protected DataTime earliestRequested;
|
|
||||||
|
|
||||||
protected final Object paintLock = new Object();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public AbstractWarningResource(WWAResourceData data, LoadProperties props) {
|
|
||||||
super(data, props);
|
|
||||||
resourceData.addChangeListener(this);
|
|
||||||
getCapability(OutlineCapability.class).setOutlineWidth(2);
|
|
||||||
color = getCapability((ColorableCapability.class)).getColor();
|
|
||||||
this.entryMap = new ConcurrentHashMap<String, WarningEntry>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* schedule the heart beat for the next minute
|
|
||||||
*/
|
|
||||||
protected static void scheduleHeartBeat() {
|
|
||||||
// get simulated time
|
|
||||||
Date currentTime = SimulatedTime.getSystemTime().getTime();
|
|
||||||
// get a calendar
|
|
||||||
Calendar now = Calendar.getInstance();
|
|
||||||
// set calendar time to simulated time
|
|
||||||
now.setTime(currentTime);
|
|
||||||
// add one to the minutes field
|
|
||||||
now.add(Calendar.MINUTE, 1);
|
|
||||||
// reset second and milisecond to 0
|
|
||||||
now.set(Calendar.SECOND, 0);
|
|
||||||
now.set(Calendar.MILLISECOND, 0);
|
|
||||||
// schedule task to fire every minute
|
|
||||||
synchronized (heartBeatChangeLock) {
|
|
||||||
try {
|
|
||||||
if (heartBeatTimer == null) {
|
|
||||||
heartBeatTimer = new Timer();
|
|
||||||
}
|
|
||||||
// schedule on the minute every minute
|
|
||||||
heartBeatTimer.schedule(heartBeatTask, now.getTime(),
|
|
||||||
1 * 60 * 1000);
|
|
||||||
} catch (Exception e) {
|
|
||||||
try {
|
|
||||||
heartBeatTimer.cancel();
|
|
||||||
} catch (Exception e2) {
|
|
||||||
// ignore, we just want to make sure the timer is cancelled
|
|
||||||
} finally {
|
|
||||||
// create a new task if there was an error when scheduling
|
|
||||||
heartBeatTask = new RepaintHeartbeat();
|
|
||||||
heartBeatTimer = new Timer();
|
|
||||||
}
|
|
||||||
statusHandler.handle(Priority.SIGNIFICANT,
|
|
||||||
"Error scheduling warnings heart beat ", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initInternal(IGraphicsTarget target) throws VizException {
|
|
||||||
synchronized (heartBeatChangeLock) {
|
|
||||||
if (heartBeatTask == null) {
|
|
||||||
heartBeatTask = new RepaintHeartbeat();
|
|
||||||
}
|
|
||||||
heartBeatTask.addResource(this);
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
try {
|
|
||||||
addRecord(getWarningRecordArray());
|
|
||||||
} catch (VizException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see com.raytheon.viz.core.rsc.IVizResource#dispose()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void disposeInternal() {
|
|
||||||
synchronized (heartBeatChangeLock) {
|
|
||||||
heartBeatTask.removeResource(this);
|
|
||||||
}
|
|
||||||
for (WarningEntry entry : entryMap.values()) {
|
|
||||||
if (entry.shadedShape != null) {
|
|
||||||
entry.shadedShape.dispose();
|
|
||||||
}
|
|
||||||
if (entry.wireframeShape != null) {
|
|
||||||
entry.wireframeShape.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entryMap.clear();
|
|
||||||
if (warningsFont != null) {
|
|
||||||
warningsFont.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String inspect(ReferencedCoordinate coord) throws VizException {
|
|
||||||
if (resourceData.hideSampling) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
// check if we are in the last frame
|
|
||||||
boolean lastFrame = false;
|
|
||||||
FramesInfo framesInfo = this.descriptor.getFramesInfo();
|
|
||||||
int frameIdx = framesInfo.getFrameIndex();
|
|
||||||
DataTime[] frameTimes = framesInfo.getFrameTimes();
|
|
||||||
if (frameIdx < 0 || frameIdx >= frameTimes.length)
|
|
||||||
return "NO DATA";
|
|
||||||
DataTime time = frameTimes[frameIdx];
|
|
||||||
|
|
||||||
TimeRange framePeriod = null;
|
|
||||||
if (frameIdx + 1 < frameTimes.length) {
|
|
||||||
framePeriod = new TimeRange(time.getRefTime(),
|
|
||||||
frameTimes[frameIdx + 1].getRefTime());
|
|
||||||
} else {
|
|
||||||
framePeriod = new TimeRange(time.getRefTime(), LAST_FRAME_ADJ);
|
|
||||||
lastFrame = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time != null) {
|
|
||||||
try {
|
|
||||||
Point point = gf.createPoint(coord.asLatLon());
|
|
||||||
|
|
||||||
for (String key : entryMap.keySet()) {
|
|
||||||
|
|
||||||
WarningEntry entry = entryMap.get(key);
|
|
||||||
AbstractWarningRecord record = entry.record;
|
|
||||||
if (matchesFrame(entry, time, framePeriod, lastFrame)) {
|
|
||||||
|
|
||||||
Geometry recordGeom = record.getGeometry();
|
|
||||||
for (int i = 0; i < recordGeom.getNumGeometries(); i++) {
|
|
||||||
PreparedGeometry prepGeom = pgf.create(recordGeom
|
|
||||||
.getGeometryN(i));
|
|
||||||
|
|
||||||
if (prepGeom.contains(point)) {
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
String[] textToPrint = getText(record, 0);
|
|
||||||
for (String text : textToPrint) {
|
|
||||||
if (sb.length() > 0) {
|
|
||||||
sb.append(" ");
|
|
||||||
}
|
|
||||||
sb.append(text);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new VizException("Error inspecting Warning Resource", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return "NO DATA";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void disposeEntry(final WarningEntry entry) {
|
|
||||||
if (entry.wireframeShape != null || entry.shadedShape != null) {
|
|
||||||
VizApp.runAsync(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (entry.shadedShape != null) {
|
|
||||||
entry.shadedShape.dispose();
|
|
||||||
}
|
|
||||||
if (entry.wireframeShape != null) {
|
|
||||||
entry.wireframeShape.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void project(CoordinateReferenceSystem crs) throws VizException {
|
|
||||||
synchronized (paintLock) {
|
|
||||||
for (Map.Entry<String, WarningEntry> entry : entryMap.entrySet()) {
|
|
||||||
WarningEntry warning = entry.getValue();
|
|
||||||
// dispose and set to null just to be safe
|
|
||||||
if (warning.shadedShape != null) {
|
|
||||||
warning.shadedShape.dispose();
|
|
||||||
warning.shadedShape = null;
|
|
||||||
}
|
|
||||||
if (warning.wireframeShape != null) {
|
|
||||||
warning.wireframeShape.dispose();
|
|
||||||
warning.wireframeShape = null;
|
|
||||||
}
|
|
||||||
warning.project = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resourceChanged(ChangeType type, Object object) {
|
|
||||||
if (type == ChangeType.DATA_UPDATE) {
|
|
||||||
PluginDataObject[] pdo = (PluginDataObject[]) object;
|
|
||||||
synchronized (AbstractWarningResource.this) {
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
addRecord(pdo);
|
|
||||||
} catch (VizException e) {
|
|
||||||
statusHandler.handle(Priority.SIGNIFICANT,
|
|
||||||
e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type == ChangeType.CAPABILITY) {
|
|
||||||
if (color != null
|
|
||||||
&& color.equals(getCapability((ColorableCapability.class))
|
|
||||||
.getColor()) == false) {
|
|
||||||
color = getCapability((ColorableCapability.class)).getColor();
|
|
||||||
|
|
||||||
// TODO this needs to be fixed to work with watches which are
|
|
||||||
// shaded
|
|
||||||
// for (String dataUri : entryMap.keySet()) {
|
|
||||||
// WarningEntry entry = entryMap.get(dataUri);
|
|
||||||
// TODO init a shape somewhere else
|
|
||||||
// if (entry.shadedShape != null) {
|
|
||||||
// entry.shadedShape.dispose();
|
|
||||||
// try {
|
|
||||||
// initShape(entry.record);
|
|
||||||
// } catch (VizException e) {
|
|
||||||
// statusHandler.handle(Priority.PROBLEM,
|
|
||||||
// e.getLocalizedMessage(), e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
issueRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void paintInternal(IGraphicsTarget target,
|
|
||||||
PaintProperties paintProps) throws VizException {
|
|
||||||
FramesInfo info = paintProps.getFramesInfo();
|
|
||||||
DataTime[] frames = info.getFrameTimes();
|
|
||||||
int frameToRequestedCompare = frames[0].compareTo(earliestRequested);
|
|
||||||
if (frameToRequestedCompare < 0) {
|
|
||||||
// we haven't requested data this far back
|
|
||||||
this.requestData(frames[0]);
|
|
||||||
} else if (frameToRequestedCompare > 0) {
|
|
||||||
// the previous earliest frame was removed as updates came in, so
|
|
||||||
// the warnings need to be disposed and we need to update the
|
|
||||||
// earliestRequested so if they ever went back in time to that
|
|
||||||
// again, it would be re-requested
|
|
||||||
earliestRequested = frames[0];
|
|
||||||
if (paintProps.getDataTime() != null) {
|
|
||||||
cleanupData(paintProps.getDataTime(), frames);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int index = info.getFrameIndex();
|
|
||||||
if (!this.recordsToLoad.isEmpty()) {
|
|
||||||
this.updateDisplay(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
DataTime thisFrameTime = null;
|
|
||||||
if (index > -1 && index < frames.length) {
|
|
||||||
thisFrameTime = frames[index];
|
|
||||||
}
|
|
||||||
if (thisFrameTime == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeRange framePeriod = null;
|
|
||||||
boolean lastFrame = false;
|
|
||||||
if (index + 1 < frames.length) {
|
|
||||||
framePeriod = new TimeRange(thisFrameTime.getRefTime(),
|
|
||||||
frames[index + 1].getRefTime());
|
|
||||||
} else {
|
|
||||||
framePeriod = new TimeRange(thisFrameTime.getRefTime(),
|
|
||||||
LAST_FRAME_ADJ);
|
|
||||||
lastFrame = true;
|
|
||||||
}
|
|
||||||
synchronized (paintLock) {
|
|
||||||
HashMap<String, WarningEntry> candidates =
|
|
||||||
new HashMap<String, AbstractWarningResource.WarningEntry>();
|
|
||||||
for (WarningEntry entry : entryMap.values()) {
|
|
||||||
if (matchesFrame(entry, paintProps.getDataTime(), framePeriod,
|
|
||||||
lastFrame)) {
|
|
||||||
String key = getEventKey(entry);
|
|
||||||
WarningEntry current = candidates.get(key);
|
|
||||||
|
|
||||||
if (current == null || current.record.getIssueTime().
|
|
||||||
before(entry.record.getIssueTime()) ||
|
|
||||||
(current.record.getIssueTime().equals(entry.record.getIssueTime()) &&
|
|
||||||
current.record.getInsertTime().before(entry.record.getInsertTime()))
|
|
||||||
)
|
|
||||||
candidates.put(key, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (WarningEntry entry : candidates.values()) {
|
|
||||||
AbstractWarningRecord record = entry.record;
|
|
||||||
|
|
||||||
// check shapes
|
|
||||||
if (entry.project) {
|
|
||||||
initShape(target, entry.record);
|
|
||||||
entry.project = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry != null && entry.wireframeShape != null) {
|
|
||||||
LineStyle lineStyle = (record.getProductClass() != null && record
|
|
||||||
.getProductClass().equals("T")) ? LineStyle.DASHED
|
|
||||||
: LineStyle.SOLID;
|
|
||||||
target.drawWireframeShape(entry.wireframeShape,
|
|
||||||
getCapability(ColorableCapability.class)
|
|
||||||
.getColor(),
|
|
||||||
getCapability(OutlineCapability.class)
|
|
||||||
.getOutlineWidth(), lineStyle);
|
|
||||||
} else if (entry != null && entry.shadedShape != null) {
|
|
||||||
target.drawShadedShape(entry.shadedShape, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (record != null && record.getGeometry() != null) {
|
|
||||||
// Calculate the upper left portion of the polygon
|
|
||||||
Coordinate upperLeft = new Coordinate(180, -90);
|
|
||||||
|
|
||||||
for (Coordinate c : record.getGeometry()
|
|
||||||
.getCoordinates()) {
|
|
||||||
if (c.y - c.x > upperLeft.y - upperLeft.x) {
|
|
||||||
upperLeft = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double[] d = descriptor.worldToPixel(new double[] {
|
|
||||||
upperLeft.x, upperLeft.y });
|
|
||||||
d[0] -= paintProps.getZoomLevel() * 100;
|
|
||||||
|
|
||||||
double mapWidth = descriptor.getMapWidth()
|
|
||||||
* paintProps.getZoomLevel() / 1000;
|
|
||||||
String[] textToPrint = getText(record, mapWidth);
|
|
||||||
if (warningsFont == null) {
|
|
||||||
warningsFont = target.getDefaultFont()
|
|
||||||
.deriveWithSize(11);
|
|
||||||
}
|
|
||||||
// DR14992: reverse the textToPrint array to plot the strings in correct order
|
|
||||||
String [] textToPrintReversed = new String[textToPrint.length];
|
|
||||||
for(int i = 0; i < textToPrint.length; i++) {
|
|
||||||
textToPrintReversed[i] = textToPrint[textToPrint.length
|
|
||||||
- i - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawableString params = new DrawableString(textToPrintReversed,
|
|
||||||
color);
|
|
||||||
params.font = warningsFont;
|
|
||||||
params.setCoordinates(d[0], d[1]);
|
|
||||||
params.textStyle = TextStyle.NORMAL;
|
|
||||||
params.horizontalAlignment = HorizontalAlignment.RIGHT;
|
|
||||||
params.verticallAlignment = VerticalAlignment.BOTTOM;
|
|
||||||
params.magnification = getCapability(
|
|
||||||
MagnificationCapability.class)
|
|
||||||
.getMagnification();
|
|
||||||
target.drawStrings(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getEventKey(WarningEntry entry) {
|
|
||||||
AbstractWarningRecord r = entry.record;
|
|
||||||
return r.getOfficeid() + '.' + r.getPhensig() + '.' + r.getEtn();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean matchesFrame(WarningEntry entry, DataTime paintTime,
|
|
||||||
TimeRange framePeriod, boolean lastFrame) {
|
|
||||||
TimeRange recordPeriod = new TimeRange(entry.record.getStartTime()
|
|
||||||
.getTimeInMillis(), entry.record.getEndTime().getTimeInMillis());
|
|
||||||
long diff = entry.record.getEndTime().getTimeInMillis()
|
|
||||||
- entry.record.getStartTime().getTimeInMillis();
|
|
||||||
Date centerTime = new Date(entry.record.getStartTime()
|
|
||||||
.getTimeInMillis() + (diff / 2));
|
|
||||||
Date frameTime = framePeriod.getStart();
|
|
||||||
|
|
||||||
Date frameStart = framePeriod.getStart();
|
|
||||||
Date refTime = entry.record.getDataTime().getRefTime();
|
|
||||||
|
|
||||||
if (lastFrame) {
|
|
||||||
// use current system time to determine what to display
|
|
||||||
Date timeToDisplay = SimulatedTime.getSystemTime().getTime();
|
|
||||||
// change frame time
|
|
||||||
frameTime = timeToDisplay;
|
|
||||||
// point paint time to different time
|
|
||||||
paintTime = new DataTime(timeToDisplay);
|
|
||||||
// point framePeriod to new frame
|
|
||||||
framePeriod = new TimeRange(frameTime, LAST_FRAME_ADJ);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the warning is cancelled
|
|
||||||
WarningAction action = WarningAction.valueOf(entry.record.getAct());
|
|
||||||
if (action == WarningAction.CAN && refTime.equals(paintTime)) {
|
|
||||||
return false;
|
|
||||||
// If this entry has been altered/updated, display its pre-altered
|
|
||||||
// version
|
|
||||||
// only in the frames prior to the time it was altered
|
|
||||||
} else if (entry.altered) {
|
|
||||||
if (frameStart.getTime() >= refTime.getTime()
|
|
||||||
&& frameStart.getTime() < (entry.timeAltered.getTime())
|
|
||||||
&& frameStart.getTime() < entry.frameAltered.getTime())
|
|
||||||
return true;
|
|
||||||
if (frameStart.getTime() >= (entry.timeAltered.getTime()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
} else if (refTime.equals(paintTime)
|
|
||||||
|| recordPeriod.contains(frameTime)
|
|
||||||
|| (framePeriod.contains(centerTime) && (!lastFrame || !entry.altered))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void cleanupData(DataTime paintTime, DataTime[] descFrameTimes) {
|
|
||||||
System.out.println("entryMap size " + entryMap.size());
|
|
||||||
List<TimeRange> framePeriods = new ArrayList<TimeRange>(
|
|
||||||
descFrameTimes.length);
|
|
||||||
for (int i = 0; i < descFrameTimes.length; i++) {
|
|
||||||
if (i == descFrameTimes.length - 1) {
|
|
||||||
framePeriods.add(new TimeRange(descFrameTimes[i].getRefTime(),
|
|
||||||
LAST_FRAME_ADJ));
|
|
||||||
} else {
|
|
||||||
framePeriods.add(new TimeRange(descFrameTimes[i].getRefTime(),
|
|
||||||
descFrameTimes[i + 1].getRefTime()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int size = framePeriods.size();
|
|
||||||
List<String> toRemove = new ArrayList<String>();
|
|
||||||
for (String key : entryMap.keySet()) {
|
|
||||||
WarningEntry entry = entryMap.get(key);
|
|
||||||
boolean found = false;
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
TimeRange tr = framePeriods.get(i);
|
|
||||||
if (matchesFrame(entry, paintTime, tr, (i == size - 1))) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
toRemove.add(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String key : toRemove) {
|
|
||||||
WarningEntry entry = entryMap.remove(key);
|
|
||||||
System.out.println("removing " + entry.record.getDataURI());
|
|
||||||
disposeEntry(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void updateDisplay(IGraphicsTarget target);
|
|
||||||
|
|
||||||
protected abstract void requestData(DataTime earliest) throws VizException;
|
|
||||||
|
|
||||||
protected abstract void initShape(IGraphicsTarget target,
|
|
||||||
AbstractWarningRecord record);
|
|
||||||
|
|
||||||
public synchronized void addRecord(PluginDataObject[] pdos)
|
|
||||||
throws VizException {
|
|
||||||
for (PluginDataObject pdo : pdos) {
|
|
||||||
if (pdo instanceof AbstractWarningRecord) {
|
|
||||||
AbstractWarningRecord record = (AbstractWarningRecord) pdo;
|
|
||||||
String officeid = record.getOfficeid();
|
|
||||||
if (!resourceData.getMetadataMap().containsKey("officeid")
|
|
||||||
|| resourceData.getMetadataMap().get("officeid")
|
|
||||||
.getConstraintValue().contains(officeid)) {
|
|
||||||
this.recordsToLoad.add((AbstractWarningRecord) pdo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
String name = resourceData.name != null ? resourceData.name
|
|
||||||
: "Warnings";
|
|
||||||
|
|
||||||
DataTime[] times = this.descriptor.getFramesInfo().getFrameTimes();
|
|
||||||
int timeIdx = this.descriptor.getFramesInfo().getFrameIndex();
|
|
||||||
|
|
||||||
// handle last frame differently, it should always be the latest time
|
|
||||||
boolean lastFrame = false;
|
|
||||||
if (timeIdx == times.length - 1) {
|
|
||||||
lastFrame = true;
|
|
||||||
}
|
|
||||||
DataTime time = null;
|
|
||||||
|
|
||||||
// get time to display
|
|
||||||
if (lastFrame) {
|
|
||||||
time = new DataTime(SimulatedTime.getSystemTime().getTime());
|
|
||||||
} else if (timeIdx > -1 && timeIdx < times.length) {
|
|
||||||
time = times[timeIdx];
|
|
||||||
}
|
|
||||||
|
|
||||||
// add time to legend
|
|
||||||
if (time != null) {
|
|
||||||
name += " " + time.getLegendString();
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,539 +0,0 @@
|
||||||
package com.raytheon.viz.warnings.rsc;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
import org.eclipse.swt.graphics.RGB;
|
|
||||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
|
||||||
|
|
||||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
|
||||||
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
|
||||||
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
|
|
||||||
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.DataTime;
|
|
||||||
import com.raytheon.uf.common.time.SimulatedTime;
|
|
||||||
import com.raytheon.uf.viz.core.DrawableString;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget.TextStyle;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment;
|
|
||||||
import com.raytheon.uf.viz.core.VizApp;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.IFont;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.IShadedShape;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
|
|
||||||
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
|
|
||||||
import com.vividsolutions.jts.geom.Coordinate;
|
|
||||||
import com.vividsolutions.jts.geom.Geometry;
|
|
||||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
|
||||||
import com.vividsolutions.jts.geom.Point;
|
|
||||||
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
|
||||||
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* TODO njensen: Ideally this should be refactored to be more in line with the
|
|
||||||
* AbstractWarningsResource.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
*
|
|
||||||
* SOFTWARE HISTORY
|
|
||||||
*
|
|
||||||
* Date Ticket# Engineer Description
|
|
||||||
* ------------ ---------- ----------- --------------------------
|
|
||||||
* May 3, 2011 jsanchez Initial creation
|
|
||||||
* Aug 5, 2011 njensen Refactored maps
|
|
||||||
* Aug 22, 2011 10631 njensen Major refactor
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author jsanchez
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
public abstract class AbstractWatchesResource extends AbstractWWAResource
|
|
||||||
implements IResourceDataChanged {
|
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
|
||||||
.getHandler(AbstractWatchesResource.class);
|
|
||||||
|
|
||||||
private static PreparedGeometryFactory pgf = new PreparedGeometryFactory();
|
|
||||||
|
|
||||||
private static GeometryFactory gf = new GeometryFactory();
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* this task calls redoTimeMatching on the resource, it should be scheduled
|
|
||||||
* to run for when a warning is set to expire
|
|
||||||
*
|
|
||||||
* @author ekladstrup
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
protected class WarningExpirationTask extends TimerTask {
|
|
||||||
|
|
||||||
private AbstractWatchesResource rsc = null;
|
|
||||||
|
|
||||||
public WarningExpirationTask(AbstractWatchesResource rsc) {
|
|
||||||
this.rsc = rsc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// System.err.println("warning expired");
|
|
||||||
// some warning has expired
|
|
||||||
rsc.redoTimeMatching(this.scheduledExecutionTime());
|
|
||||||
rsc.issueRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class WarningEntry {
|
|
||||||
|
|
||||||
protected AbstractWarningRecord record;
|
|
||||||
|
|
||||||
protected IWireframeShape wireframeShape;
|
|
||||||
|
|
||||||
protected IShadedShape shadedShape;
|
|
||||||
|
|
||||||
protected List<DataTime> times;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected IGraphicsTarget target;
|
|
||||||
|
|
||||||
/** map of dataURI to a warning entry **/
|
|
||||||
protected Map<String, WarningEntry> entryMap;
|
|
||||||
|
|
||||||
protected Map<DataTime, List<AbstractWarningRecord>> frames;
|
|
||||||
|
|
||||||
protected DataTime displayedDate;
|
|
||||||
|
|
||||||
protected IFont warningsFont;
|
|
||||||
|
|
||||||
protected RGB color;
|
|
||||||
|
|
||||||
private Timer timer;
|
|
||||||
|
|
||||||
private Set<Long> expTaskSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public AbstractWatchesResource(WWAResourceData data, LoadProperties props) {
|
|
||||||
super(data, props);
|
|
||||||
resourceData.addChangeListener(this);
|
|
||||||
getCapability(OutlineCapability.class).setOutlineWidth(2);
|
|
||||||
color = getCapability((ColorableCapability.class)).getColor();
|
|
||||||
this.entryMap = new HashMap<String, WarningEntry>();
|
|
||||||
this.frames = Collections
|
|
||||||
.synchronizedMap(new HashMap<DataTime, List<AbstractWarningRecord>>());
|
|
||||||
timer = new Timer();
|
|
||||||
expTaskSet = new HashSet<Long>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initInternal(IGraphicsTarget target) throws VizException {
|
|
||||||
if (this.target == null) {
|
|
||||||
this.target = target;
|
|
||||||
|
|
||||||
synchronized (this) {
|
|
||||||
try {
|
|
||||||
addRecord(getWarningRecordArray());
|
|
||||||
} catch (VizException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// force creation of a frame for any currently active warnings, this
|
|
||||||
// frame might get displayed in place of the last frame.
|
|
||||||
initNewFrame(new DataTime(SimulatedTime.getSystemTime().getTime()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see com.raytheon.viz.core.rsc.IVizResource#dispose()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void disposeInternal() {
|
|
||||||
timer.cancel();
|
|
||||||
|
|
||||||
for (WarningEntry entry : entryMap.values()) {
|
|
||||||
if (entry.shadedShape != null) {
|
|
||||||
entry.shadedShape.dispose();
|
|
||||||
}
|
|
||||||
if (entry.wireframeShape != null) {
|
|
||||||
entry.wireframeShape.dispose();
|
|
||||||
}
|
|
||||||
if (entry.times != null) {
|
|
||||||
entry.times.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entryMap.clear();
|
|
||||||
frames.clear();
|
|
||||||
if (warningsFont != null) {
|
|
||||||
warningsFont.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String inspect(ReferencedCoordinate coord) throws VizException {
|
|
||||||
if (resourceData.hideSampling) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.displayedDate != null
|
|
||||||
&& this.frames.containsKey(displayedDate)) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
Point point = gf.createPoint(coord.asLatLon());
|
|
||||||
|
|
||||||
synchronized (frames) {
|
|
||||||
for (AbstractWarningRecord record : this.frames
|
|
||||||
.get(displayedDate)) {
|
|
||||||
|
|
||||||
Date entryIssue = record.getStartTime().getTime();
|
|
||||||
if (entryIssue == null) {
|
|
||||||
entryIssue = record.getIssueTime().getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
Date entryEnd = record.getEndTime().getTime();
|
|
||||||
Date ref = displayedDate.getRefTime();
|
|
||||||
|
|
||||||
if (entryIssue.compareTo(ref) <= 0
|
|
||||||
&& entryEnd.compareTo(ref) >= 0) {
|
|
||||||
|
|
||||||
Geometry recordGeom = record.getGeometry();
|
|
||||||
for (int i = 0; i < recordGeom.getNumGeometries(); i++) {
|
|
||||||
PreparedGeometry prepGeom = pgf
|
|
||||||
.create(recordGeom.getGeometryN(i));
|
|
||||||
|
|
||||||
if (prepGeom.contains(point)) {
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
String[] textToPrint = getText(record, 0);
|
|
||||||
|
|
||||||
for (String text : textToPrint) {
|
|
||||||
if (sb.length() > 0) {
|
|
||||||
sb.append(" ");
|
|
||||||
}
|
|
||||||
sb.append(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new VizException("Error inspecting Warning Resource", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "NO DATA";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void removeFrame(DataTime dataTime) {
|
|
||||||
synchronized (frames) {
|
|
||||||
DataTime[] frameTimes = descriptor.getFramesInfo().getFrameTimes();
|
|
||||||
DataTime lastTime = frameTimes[frameTimes.length - 1];
|
|
||||||
if (lastTime != null
|
|
||||||
&& lastTime.getMatchValid() < dataTime.getMatchValid()) {
|
|
||||||
// Don't remove warnings that are newer than the last frame.
|
|
||||||
// This allows us to display the latest warnings even if they
|
|
||||||
// don't time match. These warnings will be cleaned up again on
|
|
||||||
// the next redoTimeMatching. Hopefully we aren't keeping too
|
|
||||||
// many around.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<AbstractWarningRecord> warningRecordList = frames
|
|
||||||
.remove(dataTime);
|
|
||||||
// remove times can effect stepping through frames
|
|
||||||
for (AbstractWarningRecord w : warningRecordList) {
|
|
||||||
final WarningEntry entry = entryMap.get(w.getDataURI());
|
|
||||||
if (entry != null) {
|
|
||||||
List<DataTime> list = entry.times;
|
|
||||||
if (list != null && list.remove(dataTime)) {
|
|
||||||
if (list.isEmpty()) {
|
|
||||||
disposeEntry(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (list == null || list.isEmpty()) {
|
|
||||||
entryMap.remove(w.getDataURI());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void disposeEntry(final WarningEntry entry) {
|
|
||||||
if (entry.wireframeShape != null || entry.shadedShape != null) {
|
|
||||||
VizApp.runAsync(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (entry.shadedShape != null) {
|
|
||||||
entry.shadedShape.dispose();
|
|
||||||
}
|
|
||||||
if (entry.wireframeShape != null) {
|
|
||||||
entry.wireframeShape.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void project(CoordinateReferenceSystem crs) throws VizException {
|
|
||||||
this.frames.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resourceChanged(ChangeType type, Object object) {
|
|
||||||
if (type == ChangeType.DATA_UPDATE) {
|
|
||||||
PluginDataObject[] pdo = (PluginDataObject[]) object;
|
|
||||||
synchronized (AbstractWatchesResource.this) {
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
addRecord(pdo);
|
|
||||||
} catch (VizException e) {
|
|
||||||
statusHandler.handle(Priority.SIGNIFICANT,
|
|
||||||
e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type == ChangeType.CAPABILITY) {
|
|
||||||
if (color != null
|
|
||||||
&& color.equals(getCapability((ColorableCapability.class))
|
|
||||||
.getColor()) == false) {
|
|
||||||
color = getCapability((ColorableCapability.class)).getColor();
|
|
||||||
|
|
||||||
for (String dataUri : entryMap.keySet()) {
|
|
||||||
WarningEntry entry = entryMap.get(dataUri);
|
|
||||||
if (entry.shadedShape != null) {
|
|
||||||
entry.shadedShape.dispose();
|
|
||||||
try {
|
|
||||||
initShape(entry.record);
|
|
||||||
} catch (VizException e) {
|
|
||||||
statusHandler.handle(Priority.PROBLEM,
|
|
||||||
e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
issueRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void paintInternal(IGraphicsTarget target,
|
|
||||||
PaintProperties paintProps) throws VizException {
|
|
||||||
FramesInfo info = paintProps.getFramesInfo();
|
|
||||||
DataTime[] frames = info.getFrameTimes();
|
|
||||||
cleanupData(frames);
|
|
||||||
int index = info.getFrameIndex();
|
|
||||||
if (index > -1 && info.getFrameCount() > 0
|
|
||||||
&& index < info.getFrameCount()) {
|
|
||||||
displayedDate = frames[index];
|
|
||||||
if (index == info.getFrameCount() - 1) {
|
|
||||||
// When we are on the last frame, if there exists a frame with
|
|
||||||
// data that is beyond the last frame but within a reasonable
|
|
||||||
// amount of time(1 hour) then we will display that frame
|
|
||||||
// instead of the last frame. We do this so when a new warning
|
|
||||||
// is issued it will display immediately over radar or satellite
|
|
||||||
// data, even if the latest frame is a few minutes behind the
|
|
||||||
// current time.
|
|
||||||
long displayValid = displayedDate.getMatchValid();
|
|
||||||
long latestValid = displayValid;
|
|
||||||
synchronized (frames) {
|
|
||||||
for (Entry<DataTime, List<AbstractWarningRecord>> entry : this.frames
|
|
||||||
.entrySet()) {
|
|
||||||
if (entry.getValue().isEmpty()) {
|
|
||||||
// do not override the frame time for a time with no
|
|
||||||
// records.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
long valid = entry.getKey().getMatchValid();
|
|
||||||
// 3600000 == 1 hour == a magicly random amount of time
|
|
||||||
if (valid > latestValid
|
|
||||||
&& latestValid - displayValid < 3600000) {
|
|
||||||
displayedDate = entry.getKey();
|
|
||||||
latestValid = valid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
displayedDate = paintProps.getDataTime();
|
|
||||||
}
|
|
||||||
if (displayedDate == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.recordsToLoad.isEmpty()) {
|
|
||||||
this.updateFrames();
|
|
||||||
}
|
|
||||||
|
|
||||||
DataTime thisFrameTime = displayedDate;
|
|
||||||
if (!this.frames.containsKey(thisFrameTime)) {
|
|
||||||
this.initNewFrame(thisFrameTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<AbstractWarningRecord> records = this.frames.get(thisFrameTime);
|
|
||||||
for (AbstractWarningRecord record : records) {
|
|
||||||
WarningEntry entry = entryMap.get(record.getDataURI());
|
|
||||||
if (entry != null && entry.wireframeShape != null) {
|
|
||||||
LineStyle lineStyle = (record.getProductClass() != null && record
|
|
||||||
.getProductClass().equals("T")) ? LineStyle.DASHED
|
|
||||||
: LineStyle.SOLID;
|
|
||||||
target.drawWireframeShape(entry.wireframeShape,
|
|
||||||
getCapability(ColorableCapability.class).getColor(),
|
|
||||||
getCapability(OutlineCapability.class)
|
|
||||||
.getOutlineWidth(), lineStyle);
|
|
||||||
} else if (entry != null && entry.shadedShape != null) {
|
|
||||||
target.drawShadedShape(entry.shadedShape, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (record != null && record.getGeometry() != null) {
|
|
||||||
// Calculate the upper left portion of the polygon
|
|
||||||
Coordinate upperLeft = new Coordinate(180, -90);
|
|
||||||
|
|
||||||
for (Coordinate c : record.getGeometry().getCoordinates()) {
|
|
||||||
if (c.y - c.x > upperLeft.y - upperLeft.x) {
|
|
||||||
upperLeft = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double[] d = descriptor.worldToPixel(new double[] {
|
|
||||||
upperLeft.x, upperLeft.y });
|
|
||||||
d[0] -= paintProps.getZoomLevel() * 100;
|
|
||||||
|
|
||||||
double mapWidth = descriptor.getMapWidth()
|
|
||||||
* paintProps.getZoomLevel() / 1000;
|
|
||||||
String[] textToPrint = getText(record, mapWidth);
|
|
||||||
if (warningsFont == null) {
|
|
||||||
warningsFont = target.getDefaultFont().deriveWithSize(11);
|
|
||||||
}
|
|
||||||
DrawableString params = new DrawableString(textToPrint, color);
|
|
||||||
params.font = warningsFont;
|
|
||||||
params.setCoordinates(d[0], d[1]);
|
|
||||||
params.textStyle = TextStyle.NORMAL;
|
|
||||||
params.horizontalAlignment = HorizontalAlignment.RIGHT;
|
|
||||||
params.verticallAlignment = VerticalAlignment.BOTTOM;
|
|
||||||
params.magnification = getCapability(
|
|
||||||
MagnificationCapability.class).getMagnification();
|
|
||||||
target.drawStrings(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void cleanupData(DataTime[] descFrameTimes) {
|
|
||||||
List<DataTime> oldFrames = null;
|
|
||||||
synchronized (frames) {
|
|
||||||
for (DataTime dt : frames.keySet()) {
|
|
||||||
boolean found = false;
|
|
||||||
for (DataTime descTime : descFrameTimes) {
|
|
||||||
if (descTime.equals(dt)) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
if (oldFrames == null) {
|
|
||||||
oldFrames = new ArrayList<DataTime>();
|
|
||||||
}
|
|
||||||
oldFrames.add(dt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldFrames != null) {
|
|
||||||
for (DataTime old : oldFrames) {
|
|
||||||
this.removeFrame(old);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected synchronized void initNewFrame(DataTime thisFrameTime)
|
|
||||||
throws VizException {
|
|
||||||
// subclasses should override
|
|
||||||
}
|
|
||||||
|
|
||||||
protected synchronized void updateFrames() throws VizException {
|
|
||||||
// subclasses should override
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initShape(AbstractWarningRecord record) throws VizException {
|
|
||||||
// subclasses should override
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules a WarningExpirationTask for the end time of the passing in
|
|
||||||
* record
|
|
||||||
*
|
|
||||||
* @param rec
|
|
||||||
* a WarningRecord
|
|
||||||
*/
|
|
||||||
protected void scheduleTimer(AbstractWarningRecord rec) {
|
|
||||||
// only schedule if record has not expired already
|
|
||||||
long now = SimulatedTime.getSystemTime().getTime().getTime();
|
|
||||||
long endTime = rec.getEndTime().getTimeInMillis();
|
|
||||||
synchronized (expTaskSet) {
|
|
||||||
if (endTime > now && !expTaskSet.contains(new Long(endTime))) {
|
|
||||||
WarningExpirationTask task = new WarningExpirationTask(this);
|
|
||||||
timer.schedule(task, rec.getEndTime().getTime());
|
|
||||||
expTaskSet.add(new Long(endTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redo time matching and remove the passed in time from the map of
|
|
||||||
* scheduled times
|
|
||||||
*
|
|
||||||
* @param triggerTime
|
|
||||||
*/
|
|
||||||
public void redoTimeMatching(long triggerTime) {
|
|
||||||
redoTimeMatching();
|
|
||||||
Long time = new Long(triggerTime);
|
|
||||||
// remove the instance of the trigger time from the map
|
|
||||||
synchronized (expTaskSet) {
|
|
||||||
if (expTaskSet != null && expTaskSet.contains(time)) {
|
|
||||||
expTaskSet.remove(time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redo the time matching
|
|
||||||
*/
|
|
||||||
public void redoTimeMatching() {
|
|
||||||
try {
|
|
||||||
this.getDescriptor().getTimeMatcher().redoTimeMatching(this);
|
|
||||||
this.getDescriptor().getTimeMatcher()
|
|
||||||
.redoTimeMatching(this.getDescriptor());
|
|
||||||
} catch (VizException e) {
|
|
||||||
// TODO Auto-generated catch block. Please revise as appropriate.
|
|
||||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,6 +27,7 @@ import com.vividsolutions.jts.io.ParseException;
|
||||||
import com.vividsolutions.jts.io.WKBReader;
|
import com.vividsolutions.jts.io.WKBReader;
|
||||||
import com.vividsolutions.jts.io.WKTReader;
|
import com.vividsolutions.jts.io.WKTReader;
|
||||||
|
|
||||||
|
|
||||||
public class CWASPSResource extends WarningsResource {
|
public class CWASPSResource extends WarningsResource {
|
||||||
|
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
|
@ -230,14 +231,14 @@ public class CWASPSResource extends WarningsResource {
|
||||||
|
|
||||||
textToPrint[2] = record.getPil();
|
textToPrint[2] = record.getPil();
|
||||||
|
|
||||||
SimpleDateFormat startFormat = AbstractWarningResource.DEFAULT_FORMAT;
|
SimpleDateFormat startFormat = AbstractWWAResource.DEFAULT_FORMAT;
|
||||||
SimpleDateFormat endFormat = AbstractWarningResource.DEFAULT_FORMAT;
|
SimpleDateFormat endFormat = AbstractWWAResource.DEFAULT_FORMAT;
|
||||||
if (mapWidth == 0) {
|
if (mapWidth == 0) {
|
||||||
startFormat = AbstractWarningResource.LONG_FORMAT;
|
startFormat = AbstractWWAResource.LONG_FORMAT;
|
||||||
endFormat = AbstractWarningResource.DAY_FORMAT;
|
endFormat = AbstractWWAResource.DAY_FORMAT;
|
||||||
} else if (mapWidth <= 200) {
|
} else if (mapWidth <= 200) {
|
||||||
startFormat = AbstractWarningResource.DAY_FORMAT;
|
startFormat = AbstractWWAResource.DAY_FORMAT;
|
||||||
endFormat = AbstractWarningResource.DAY_FORMAT;
|
endFormat = AbstractWWAResource.DAY_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (startFormat) {
|
synchronized (startFormat) {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* May 12, 2011 jsanchez Initial creation
|
* May 12, 2011 jsanchez Initial creation
|
||||||
*
|
* Sep 27, 2012 1149 jsanchez Updated order of actions. Put CON before CAN,EXP
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author jsanchez
|
* @author jsanchez
|
||||||
|
@ -30,6 +30,7 @@ public class WarningRecordComparator implements
|
||||||
* Compares the WarningRecords by phenSig, ETN, action, then starttime
|
* Compares the WarningRecords by phenSig, ETN, action, then starttime
|
||||||
* (descending order)
|
* (descending order)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int compare(AbstractWarningRecord wr1, AbstractWarningRecord wr2) {
|
public int compare(AbstractWarningRecord wr1, AbstractWarningRecord wr2) {
|
||||||
int rval = 0;
|
int rval = 0;
|
||||||
|
|
||||||
|
@ -39,19 +40,30 @@ public class WarningRecordComparator implements
|
||||||
rval = Double.compare(Double.parseDouble(wr1.getEtn()),
|
rval = Double.compare(Double.parseDouble(wr1.getEtn()),
|
||||||
Double.parseDouble(wr2.getEtn()));
|
Double.parseDouble(wr2.getEtn()));
|
||||||
if (rval == 0) {
|
if (rval == 0) {
|
||||||
if (wr1.getAct().equals(wr2.getAct())) {
|
WarningAction act1 = WarningAction.valueOf(wr1.getAct());
|
||||||
|
WarningAction act2 = WarningAction.valueOf(wr2.getAct());
|
||||||
|
if (act1 == act2) {
|
||||||
rval = 0;
|
rval = 0;
|
||||||
} else if (wr1.getAct().equals(WarningAction.NEW.toString())) {
|
} else if (act1 == WarningAction.NEW) {
|
||||||
rval = -1;
|
rval = -1;
|
||||||
} else if (wr2.getAct().equals(WarningAction.NEW.toString())) {
|
} else if (act2 == WarningAction.NEW) {
|
||||||
rval = 1;
|
rval = 1;
|
||||||
|
} else if (act1 == WarningAction.CON
|
||||||
|
&& (act2 == WarningAction.CAN || act2 == WarningAction.EXP)) {
|
||||||
|
return -1;
|
||||||
|
} else if (act2 == WarningAction.CON
|
||||||
|
&& (act1 == WarningAction.CAN || act1 == WarningAction.EXP)) {
|
||||||
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
rval = wr1.getAct().compareTo(wr2.getAct());
|
rval = wr1.getAct().compareTo(wr2.getAct());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rval == 0) {
|
if (rval == 0) {
|
||||||
rval = -1
|
rval = wr1.getStartTime().compareTo(wr2.getStartTime());
|
||||||
* wr1.getStartTime().compareTo(wr2.getStartTime());
|
// sort warnings in descending order
|
||||||
|
if (!wr1.getSig().equals("A")) {
|
||||||
|
rval *= -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,26 +22,27 @@ package com.raytheon.viz.warnings.rsc;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
||||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
|
||||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
|
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
|
||||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
import com.raytheon.uf.common.time.DataTime;
|
import com.raytheon.uf.common.time.DataTime;
|
||||||
|
import com.raytheon.uf.common.time.SimulatedTime;
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||||
import com.raytheon.uf.viz.core.catalog.LayerProperty;
|
import com.raytheon.uf.viz.core.VizApp;
|
||||||
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
|
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
|
||||||
|
import com.raytheon.uf.viz.core.drawables.IRenderableDisplay;
|
||||||
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
|
import com.raytheon.uf.viz.core.drawables.IWireframeShape;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
|
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
|
||||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
||||||
import com.raytheon.uf.viz.core.rsc.ResourceType;
|
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
|
||||||
import com.raytheon.viz.core.rsc.jts.JTSCompiler;
|
import com.raytheon.viz.core.rsc.jts.JTSCompiler;
|
||||||
import com.raytheon.viz.texteditor.util.SiteAbbreviationUtil;
|
import com.raytheon.viz.texteditor.util.SiteAbbreviationUtil;
|
||||||
import com.vividsolutions.jts.geom.Geometry;
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
@ -55,31 +56,268 @@ import com.vividsolutions.jts.geom.Geometry;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Sep 1, 2010 jsanchez Initial creation
|
* Sep 1, 2010 jsanchez Initial creation
|
||||||
* Aug 22, 2011 10631 njensen Major refactor
|
* Aug 22, 2011 10631 njensen Major refactor
|
||||||
* May 3, 2012 DR 14741 porricel Stop setting end time of orig.
|
* May 3, 2012 DR 14741 porricel Stop setting end time of orig.
|
||||||
* warning to start time of update.
|
* warning to start time of update.
|
||||||
* Jun 04, 2012 DR14992 mgamazaychikov Fix the problem with plotting expiration time for
|
* Jun 04, 2012 DR14992 mgamazaychikov Fix the problem with plotting expiration time for
|
||||||
* NEW warning when CAN warning is issued
|
* NEW warning when CAN warning is issued
|
||||||
*
|
* Sep 27, 2012 1149 jsanchez Refactored methods from AbstractWarningsResource into this class.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author jsanchez
|
* @author jsanchez
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class WarningsResource extends AbstractWarningResource {
|
public class WarningsResource extends AbstractWWAResource {
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
|
||||||
.getHandler(WarningsResource.class);
|
protected static class RepaintHeartbeat extends TimerTask {
|
||||||
|
|
||||||
|
private final HashSet<AbstractVizResource<?, ?>> resourceSet = new HashSet<AbstractVizResource<?, ?>>();
|
||||||
|
|
||||||
|
private boolean cancelled = false;
|
||||||
|
|
||||||
|
public RepaintHeartbeat() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy resources from old task, just in case some were added after it
|
||||||
|
* should have been replaced (threads are fun)
|
||||||
|
**/
|
||||||
|
public void copyResourceSet(RepaintHeartbeat oldTask) {
|
||||||
|
// copy resources, in case one was added after a cancel
|
||||||
|
Set<AbstractVizResource<?, ?>> oldResourceSet = oldTask
|
||||||
|
.getResourceSet();
|
||||||
|
synchronized (oldResourceSet) {
|
||||||
|
for (AbstractVizResource<?, ?> rsc : oldResourceSet) {
|
||||||
|
this.addResource(rsc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<AbstractVizResource<?, ?>> getResourceSet() {
|
||||||
|
return resourceSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// get the unique displays from all the added resources
|
||||||
|
ArrayList<IRenderableDisplay> displaysToRefresh = new ArrayList<IRenderableDisplay>(
|
||||||
|
1);
|
||||||
|
synchronized (resourceSet) {
|
||||||
|
for (AbstractVizResource<?, ?> rsc : resourceSet) {
|
||||||
|
try {
|
||||||
|
IRenderableDisplay disp = rsc.getDescriptor()
|
||||||
|
.getRenderableDisplay();
|
||||||
|
if (!displaysToRefresh.contains(disp)) {
|
||||||
|
displaysToRefresh.add(disp);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
statusHandler
|
||||||
|
.handle(Priority.PROBLEM,
|
||||||
|
"Encountered error during Warnings Heartbeat, continuing with other Warnings ",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an array with final modifier
|
||||||
|
final IRenderableDisplay[] refreshList = displaysToRefresh
|
||||||
|
.toArray(new IRenderableDisplay[displaysToRefresh.size()]);
|
||||||
|
|
||||||
|
// execute refersh in UI thread
|
||||||
|
VizApp.runAsync(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (IRenderableDisplay disp : refreshList) {
|
||||||
|
disp.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// cancel the task if there are no more resources
|
||||||
|
boolean cancel = false;
|
||||||
|
synchronized (resourceSet) {
|
||||||
|
if (resourceSet.size() < 1) {
|
||||||
|
cancel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancel) {
|
||||||
|
doCancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addResource(AbstractVizResource<?, ?> rsc) {
|
||||||
|
// if task has no resources then it needs to be started when the
|
||||||
|
// first is added
|
||||||
|
boolean start = false;
|
||||||
|
synchronized (resourceSet) {
|
||||||
|
// if this is the first resource added to an empty set start the
|
||||||
|
// timer
|
||||||
|
if (resourceSet.size() < 1) {
|
||||||
|
start = true;
|
||||||
|
}
|
||||||
|
resourceSet.add(rsc);
|
||||||
|
}
|
||||||
|
if (start) {
|
||||||
|
WarningsResource.scheduleHeartBeat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeResource(AbstractVizResource<?, ?> rsc) {
|
||||||
|
synchronized (resourceSet) {
|
||||||
|
resourceSet.remove(rsc);
|
||||||
|
// cancel the task if there are no more resources
|
||||||
|
if (resourceSet.size() < 1) {
|
||||||
|
doCancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doCancel() {
|
||||||
|
synchronized (heartBeatChangeLock) {
|
||||||
|
if (cancelled == false) {
|
||||||
|
cancelled = true;
|
||||||
|
heartBeatTimer.cancel();
|
||||||
|
heartBeatTask = new RepaintHeartbeat();
|
||||||
|
heartBeatTimer = new Timer();
|
||||||
|
heartBeatTask.copyResourceSet(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** lock when changing heartBeatTask **/
|
||||||
|
protected static final Object heartBeatChangeLock = new Object();
|
||||||
|
|
||||||
|
protected static RepaintHeartbeat heartBeatTask = null;
|
||||||
|
|
||||||
|
protected static Timer heartBeatTimer = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public WarningsResource(WWAResourceData data, LoadProperties props) {
|
public WarningsResource(WWAResourceData data, LoadProperties props) {
|
||||||
super(data, props);
|
super(data, props);
|
||||||
|
resourceName = "Warnings";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected synchronized void updateDisplay(IGraphicsTarget target) {
|
protected void initInternal(IGraphicsTarget target) throws VizException {
|
||||||
|
DataTime earliest = this.descriptor.getFramesInfo().getFrameTimes()[0];
|
||||||
|
requestData(earliest);
|
||||||
|
synchronized (heartBeatChangeLock) {
|
||||||
|
if (heartBeatTask == null) {
|
||||||
|
heartBeatTask = new RepaintHeartbeat();
|
||||||
|
}
|
||||||
|
heartBeatTask.addResource(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see com.raytheon.viz.core.rsc.IVizResource#dispose()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void disposeInternal() {
|
||||||
|
synchronized (heartBeatChangeLock) {
|
||||||
|
heartBeatTask.removeResource(this);
|
||||||
|
}
|
||||||
|
for (WarningEntry entry : entryMap.values()) {
|
||||||
|
if (entry.shadedShape != null) {
|
||||||
|
entry.shadedShape.dispose();
|
||||||
|
}
|
||||||
|
if (entry.wireframeShape != null) {
|
||||||
|
entry.wireframeShape.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entryMap.clear();
|
||||||
|
if (warningsFont != null) {
|
||||||
|
warningsFont.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resourceChanged(ChangeType type, Object object) {
|
||||||
|
if (type == ChangeType.DATA_UPDATE) {
|
||||||
|
PluginDataObject[] pdo = (PluginDataObject[]) object;
|
||||||
|
synchronized (WarningsResource.this) {
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
addRecord(pdo);
|
||||||
|
} catch (VizException e) {
|
||||||
|
statusHandler.handle(Priority.SIGNIFICANT,
|
||||||
|
e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (type == ChangeType.CAPABILITY) {
|
||||||
|
if (color != null
|
||||||
|
&& color.equals(getCapability((ColorableCapability.class))
|
||||||
|
.getColor()) == false) {
|
||||||
|
color = getCapability((ColorableCapability.class)).getColor();
|
||||||
|
|
||||||
|
// TODO this needs to be fixed to work with watches which are
|
||||||
|
// shaded
|
||||||
|
// for (String dataUri : entryMap.keySet()) {
|
||||||
|
// WarningEntry entry = entryMap.get(dataUri);
|
||||||
|
// TODO init a shape somewhere else
|
||||||
|
// if (entry.shadedShape != null) {
|
||||||
|
// entry.shadedShape.dispose();
|
||||||
|
// try {
|
||||||
|
// initShape(entry.record);
|
||||||
|
// } catch (VizException e) {
|
||||||
|
// statusHandler.handle(Priority.PROBLEM,
|
||||||
|
// e.getLocalizedMessage(), e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
issueRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initShape(IGraphicsTarget target,
|
||||||
|
AbstractWarningRecord record) throws VizException {
|
||||||
|
Geometry geo;
|
||||||
|
|
||||||
|
if (record.getGeometry() != null) {
|
||||||
|
try {
|
||||||
|
WarningEntry entry = entryMap.get(record.getDataURI());
|
||||||
|
if (entry == null) {
|
||||||
|
entry = new WarningEntry();
|
||||||
|
entry.record = record;
|
||||||
|
entryMap.put(record.getDataURI(), entry);
|
||||||
|
}
|
||||||
|
IWireframeShape wfs = entry.wireframeShape;
|
||||||
|
|
||||||
|
if (wfs != null) {
|
||||||
|
wfs.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
wfs = target.createWireframeShape(false, descriptor);
|
||||||
|
geo = (Geometry) record.getGeometry().clone();
|
||||||
|
|
||||||
|
JTSCompiler jtsCompiler = new JTSCompiler(null, wfs, descriptor);
|
||||||
|
jtsCompiler.handle(geo);
|
||||||
|
wfs.compile();
|
||||||
|
entry.wireframeShape = wfs;
|
||||||
|
} catch (Exception e) {
|
||||||
|
statusHandler.handle(Priority.ERROR,
|
||||||
|
"Error creating wireframe", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected synchronized void updateDisplay(IGraphicsTarget target)
|
||||||
|
throws VizException {
|
||||||
if (!this.recordsToLoad.isEmpty()) {
|
if (!this.recordsToLoad.isEmpty()) {
|
||||||
FramesInfo info = getDescriptor().getFramesInfo();
|
FramesInfo info = getDescriptor().getFramesInfo();
|
||||||
DataTime[] frames = info.getFrameTimes();
|
DataTime[] frames = info.getFrameTimes();
|
||||||
|
@ -121,7 +359,7 @@ public class WarningsResource extends AbstractWarningResource {
|
||||||
entry.record.setEndTime((Calendar) warnrec
|
entry.record.setEndTime((Calendar) warnrec
|
||||||
.getStartTime().clone());
|
.getStartTime().clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rec.getCountyheader().equals(
|
if (!rec.getCountyheader().equals(
|
||||||
warnrec.getCountyheader())
|
warnrec.getCountyheader())
|
||||||
&& act == WarningAction.CAN) {
|
&& act == WarningAction.CAN) {
|
||||||
|
@ -166,103 +404,50 @@ public class WarningsResource extends AbstractWarningResource {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
protected void initShape(IGraphicsTarget target,
|
* schedule the heart beat for the next minute
|
||||||
AbstractWarningRecord record) {
|
*/
|
||||||
Geometry geo;
|
protected static void scheduleHeartBeat() {
|
||||||
|
// get simulated time
|
||||||
if (record.getGeometry() != null) {
|
Date currentTime = SimulatedTime.getSystemTime().getTime();
|
||||||
try {
|
// get a calendar
|
||||||
WarningEntry entry = entryMap.get(record.getDataURI());
|
Calendar now = Calendar.getInstance();
|
||||||
if (entry == null) {
|
// set calendar time to simulated time
|
||||||
entry = new WarningEntry();
|
now.setTime(currentTime);
|
||||||
entry.record = record;
|
// add one to the minutes field
|
||||||
entryMap.put(record.getDataURI(), entry);
|
now.add(Calendar.MINUTE, 1);
|
||||||
}
|
// reset second and milisecond to 0
|
||||||
IWireframeShape wfs = entry.wireframeShape;
|
now.set(Calendar.SECOND, 0);
|
||||||
|
now.set(Calendar.MILLISECOND, 0);
|
||||||
if (wfs != null) {
|
// schedule task to fire every minute
|
||||||
wfs.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
wfs = target.createWireframeShape(false, descriptor);
|
|
||||||
geo = (Geometry) record.getGeometry().clone();
|
|
||||||
|
|
||||||
JTSCompiler jtsCompiler = new JTSCompiler(null, wfs, descriptor);
|
|
||||||
jtsCompiler.handle(geo);
|
|
||||||
wfs.compile();
|
|
||||||
entry.wireframeShape = wfs;
|
|
||||||
} catch (Exception e) {
|
|
||||||
statusHandler.handle(Priority.ERROR,
|
|
||||||
"Error creating wireframe", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initInternal(IGraphicsTarget target) throws VizException {
|
|
||||||
DataTime earliest = this.descriptor.getFramesInfo().getFrameTimes()[0];
|
|
||||||
requestData(earliest);
|
|
||||||
synchronized (heartBeatChangeLock) {
|
synchronized (heartBeatChangeLock) {
|
||||||
if (heartBeatTask == null) {
|
try {
|
||||||
heartBeatTask = new RepaintHeartbeat();
|
if (heartBeatTimer == null) {
|
||||||
|
heartBeatTimer = new Timer();
|
||||||
|
}
|
||||||
|
// schedule on the minute every minute
|
||||||
|
heartBeatTimer.schedule(heartBeatTask, now.getTime(),
|
||||||
|
1 * 60 * 1000);
|
||||||
|
} catch (Exception e) {
|
||||||
|
try {
|
||||||
|
heartBeatTimer.cancel();
|
||||||
|
} catch (Exception e2) {
|
||||||
|
// ignore, we just want to make sure the timer is cancelled
|
||||||
|
} finally {
|
||||||
|
// create a new task if there was an error when scheduling
|
||||||
|
heartBeatTask = new RepaintHeartbeat();
|
||||||
|
heartBeatTimer = new Timer();
|
||||||
|
}
|
||||||
|
statusHandler.handle(Priority.SIGNIFICANT,
|
||||||
|
"Error scheduling warnings heart beat ", e);
|
||||||
}
|
}
|
||||||
heartBeatTask.addResource(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
@Override
|
||||||
protected void requestData(DataTime earliest) throws VizException {
|
protected String getEventKey(WarningEntry entry) {
|
||||||
System.out.println("requesting data");
|
AbstractWarningRecord r = entry.record;
|
||||||
Map<String, RequestConstraint> map = (Map<String, RequestConstraint>) resourceData
|
return r.getOfficeid() + '.' + r.getPhensig() + '.' + r.getEtn();
|
||||||
.getMetadataMap().clone();
|
|
||||||
if (earliestRequested != null) {
|
|
||||||
// don't request data we've already requested
|
|
||||||
String[] times = new String[] { earliest.toString(),
|
|
||||||
earliestRequested.toString() };
|
|
||||||
RequestConstraint constraint = new RequestConstraint();
|
|
||||||
constraint.setConstraintType(ConstraintType.BETWEEN);
|
|
||||||
constraint.setBetweenValueList(times);
|
|
||||||
map.put("endTime", constraint);
|
|
||||||
} else {
|
|
||||||
RequestConstraint endConstraint = new RequestConstraint(
|
|
||||||
earliest.toString(), ConstraintType.GREATER_THAN_EQUALS);
|
|
||||||
map.put("endTime", endConstraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
earliestRequested = earliest;
|
|
||||||
|
|
||||||
LayerProperty property = new LayerProperty();
|
|
||||||
property.setDesiredProduct(ResourceType.PLAN_VIEW);
|
|
||||||
property.setEntryQueryParameters(map, false);
|
|
||||||
property.setNumberOfImages(9999);
|
|
||||||
|
|
||||||
Object[] resp = null;
|
|
||||||
resp = DataCubeContainer.getData(property, 60000).toArray(
|
|
||||||
new Object[] {});
|
|
||||||
PluginDataObject[] arr = new PluginDataObject[resp.length];
|
|
||||||
int i = 0;
|
|
||||||
for (Object o : resp) {
|
|
||||||
arr[i] = (PluginDataObject) o;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
addRecord(sort(arr));
|
|
||||||
}
|
|
||||||
|
|
||||||
private PluginDataObject[] sort(PluginDataObject[] pdos) {
|
|
||||||
ArrayList<AbstractWarningRecord> sortedWarnings = new ArrayList<AbstractWarningRecord>();
|
|
||||||
for (Object o : pdos) {
|
|
||||||
if (((PluginDataObject) o) instanceof AbstractWarningRecord) {
|
|
||||||
AbstractWarningRecord record = (AbstractWarningRecord) o;
|
|
||||||
sortedWarnings.add(record);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sorts by phensig, etn, starttime (descending), act */
|
|
||||||
Collections.sort(sortedWarnings, comparator);
|
|
||||||
return sortedWarnings.toArray(new AbstractWarningRecord[sortedWarnings
|
|
||||||
.size()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
package com.raytheon.viz.warnings.rsc;
|
package com.raytheon.viz.warnings.rsc;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||||
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
|
||||||
|
@ -17,250 +22,172 @@ import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintTyp
|
||||||
import com.raytheon.uf.common.geospatial.ISpatialQuery.SearchMode;
|
import com.raytheon.uf.common.geospatial.ISpatialQuery.SearchMode;
|
||||||
import com.raytheon.uf.common.geospatial.SpatialQueryFactory;
|
import com.raytheon.uf.common.geospatial.SpatialQueryFactory;
|
||||||
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
|
||||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
import com.raytheon.uf.common.time.DataTime;
|
import com.raytheon.uf.common.time.DataTime;
|
||||||
import com.raytheon.uf.common.time.TimeRange;
|
import com.raytheon.uf.common.time.SimulatedTime;
|
||||||
import com.raytheon.uf.viz.core.catalog.LayerProperty;
|
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||||
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
|
|
||||||
import com.raytheon.uf.viz.core.drawables.FillPatterns;
|
import com.raytheon.uf.viz.core.drawables.FillPatterns;
|
||||||
import com.raytheon.uf.viz.core.drawables.IShadedShape;
|
import com.raytheon.uf.viz.core.drawables.IShadedShape;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
||||||
import com.raytheon.uf.viz.core.rsc.ResourceType;
|
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
|
||||||
import com.raytheon.viz.core.rsc.jts.JTSCompiler;
|
import com.raytheon.viz.core.rsc.jts.JTSCompiler;
|
||||||
import com.raytheon.viz.core.rsc.jts.JTSCompiler.PointStyle;
|
import com.raytheon.viz.core.rsc.jts.JTSCompiler.PointStyle;
|
||||||
import com.raytheon.viz.texteditor.util.SiteAbbreviationUtil;
|
|
||||||
import com.vividsolutions.jts.geom.Geometry;
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
import com.vividsolutions.jts.geom.GeometryCollection;
|
import com.vividsolutions.jts.geom.GeometryCollection;
|
||||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||||
|
|
||||||
public class WatchesResource extends AbstractWatchesResource {
|
/**
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
*
|
||||||
.getHandler(WatchesResource.class);
|
* TODO Add Description
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Sep 27, 2012 1149 jsanchez Refactored methods from AbstractWarningsResource into this class.
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author jsanchez
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class WatchesResource extends AbstractWWAResource {
|
||||||
|
|
||||||
private Map<String, WeakReference<Geometry>> geometryMap = new HashMap<String, WeakReference<Geometry>>();
|
/**
|
||||||
|
*
|
||||||
|
* this task calls redoTimeMatching on the resource, it should be scheduled
|
||||||
|
* to run for when a warning is set to expire
|
||||||
|
*
|
||||||
|
* @author ekladstrup
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
protected class WarningExpirationTask extends TimerTask {
|
||||||
|
|
||||||
|
private WatchesResource rsc = null;
|
||||||
|
|
||||||
|
public WarningExpirationTask(WatchesResource rsc) {
|
||||||
|
this.rsc = rsc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// System.err.println("warning expired");
|
||||||
|
// some warning has expired
|
||||||
|
rsc.redoTimeMatching(this.scheduledExecutionTime());
|
||||||
|
rsc.issueRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map<String, WeakReference<Geometry>> geometryMap = new HashMap<String, WeakReference<Geometry>>();
|
||||||
|
|
||||||
|
private final Timer timer;
|
||||||
|
|
||||||
|
private final Set<Long> expTaskSet;
|
||||||
|
|
||||||
|
protected IGraphicsTarget target;
|
||||||
|
|
||||||
|
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
|
||||||
|
|
||||||
public WatchesResource(WWAResourceData data, LoadProperties props) {
|
public WatchesResource(WWAResourceData data, LoadProperties props) {
|
||||||
super(data, props);
|
super(data, props);
|
||||||
|
timer = new Timer();
|
||||||
|
expTaskSet = new HashSet<Long>();
|
||||||
|
resourceName = "Watches";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
protected void initInternal(IGraphicsTarget target) throws VizException {
|
||||||
DataTime time = displayedDate;
|
if (this.target == null) {
|
||||||
if (time == null) {
|
this.target = target;
|
||||||
time = descriptor.getTimeForResource(this);
|
|
||||||
}
|
|
||||||
String name = resourceData.name != null ? resourceData.name : "Watches";
|
|
||||||
if (time != null) {
|
|
||||||
name += " " + time.getLegendString();
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
synchronized (this) {
|
||||||
protected synchronized void initNewFrame(DataTime thisFrameTime)
|
try {
|
||||||
throws VizException {
|
addRecord(getWarningRecordArray());
|
||||||
long t0 = System.currentTimeMillis();
|
} catch (VizException e) {
|
||||||
HashMap<String, RequestConstraint> map = (HashMap<String, RequestConstraint>) resourceData
|
e.printStackTrace();
|
||||||
.getMetadataMap().clone();
|
|
||||||
|
|
||||||
LayerProperty property = new LayerProperty();
|
|
||||||
property.setDesiredProduct(ResourceType.PLAN_VIEW);
|
|
||||||
property.setNumberOfImages(9999);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Retrieve all the watches that have a have a range containing the
|
|
||||||
* frame time
|
|
||||||
*/
|
|
||||||
map.put("startTime", new RequestConstraint(thisFrameTime.toString(),
|
|
||||||
ConstraintType.LESS_THAN_EQUALS));
|
|
||||||
map.put("endTime", new RequestConstraint(thisFrameTime.toString(),
|
|
||||||
ConstraintType.GREATER_THAN_EQUALS));
|
|
||||||
property.setEntryQueryParameters(map, false);
|
|
||||||
|
|
||||||
Object[] resp = DataCubeContainer.getData(property, 60000).toArray(
|
|
||||||
new Object[] {});
|
|
||||||
|
|
||||||
ArrayList<AbstractWarningRecord> sortedWatches = new ArrayList<AbstractWarningRecord>();
|
|
||||||
for (Object o : resp) {
|
|
||||||
if (((PluginDataObject) o) instanceof AbstractWarningRecord) {
|
|
||||||
sortedWatches.add((AbstractWarningRecord) o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sorts by phensig, etn, starttime (descending), act */
|
|
||||||
Collections.sort(sortedWatches, comparator);
|
|
||||||
ArrayList<AbstractWarningRecord> remove = new ArrayList<AbstractWarningRecord>();
|
|
||||||
|
|
||||||
AbstractWarningRecord conRecord = null;
|
|
||||||
AbstractWarningRecord expRecord = null;
|
|
||||||
for (AbstractWarningRecord w : sortedWatches) {
|
|
||||||
WarningAction act = WarningAction.valueOf(w.getAct());
|
|
||||||
// Do not plot watches that have been Cancelled or Expired
|
|
||||||
if ((act == WarningAction.CAN || act == WarningAction.EXP)
|
|
||||||
&& w.getStartTime().after(thisFrameTime.getValidTime()) == false
|
|
||||||
&& w.getUgcsString() != null
|
|
||||||
&& w.getUgcsString()[0] != null
|
|
||||||
&& w.getUgcsString()[0].endsWith("000")) {
|
|
||||||
expRecord = w;
|
|
||||||
} else if (expRecord != null
|
|
||||||
&& expRecord.getEtn().equals(w.getEtn())
|
|
||||||
&& expRecord.getPhensig().equals(w.getPhensig())
|
|
||||||
&& expRecord.getStartTime().after(w.getStartTime())) {
|
|
||||||
|
|
||||||
remove.add(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not plot watches that out dated CONs
|
|
||||||
if (act == WarningAction.CON
|
|
||||||
&& (conRecord == null || conRecord.getEtn().equals(
|
|
||||||
w.getEtn()) == false)) {
|
|
||||||
conRecord = w;
|
|
||||||
} else if (conRecord != null
|
|
||||||
&& (act == WarningAction.CON || act == WarningAction.NEW)
|
|
||||||
&& conRecord.getEtn().equals(w.getEtn())
|
|
||||||
&& conRecord.getPhensig().equals(w.getPhensig())
|
|
||||||
&& conRecord.getStartTime().after(w.getStartTime())) {
|
|
||||||
remove.add(w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (AbstractWarningRecord w : remove) {
|
|
||||||
sortedWatches.remove(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, AbstractWarningRecord> watches = new HashMap<String, AbstractWarningRecord>();
|
|
||||||
for (AbstractWarningRecord watchRec : sortedWatches) {
|
|
||||||
TimeRange tr = new TimeRange(watchRec.getStartTime(),
|
|
||||||
watchRec.getEndTime());
|
|
||||||
if (tr.contains(thisFrameTime.getValidTime().getTime())) {
|
|
||||||
addWatch(watches, watchRec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<AbstractWarningRecord> watchList = new ArrayList<AbstractWarningRecord>();
|
|
||||||
if (watches.isEmpty() == false) {
|
|
||||||
for (String key : watches.keySet()) {
|
|
||||||
AbstractWarningRecord watch = watches.get(key);
|
|
||||||
watch.setPil(SiteAbbreviationUtil.getSiteNode(watch.getXxxid())
|
|
||||||
+ watch.getPil() + watch.getXxxid());
|
|
||||||
watchList.add(watch);
|
|
||||||
scheduleTimer(watch);
|
|
||||||
initShape(watch);
|
|
||||||
|
|
||||||
WarningEntry entry = entryMap.get(watch.getDataURI());
|
|
||||||
if (entry == null) {
|
|
||||||
entry = new WarningEntry();
|
|
||||||
entry.record = watch;
|
|
||||||
entryMap.put(watch.getDataURI(), entry);
|
|
||||||
}
|
}
|
||||||
List<DataTime> list = entry.times;
|
}
|
||||||
if (list == null) {
|
}
|
||||||
list = new ArrayList<DataTime>();
|
// force creation of a frame for any currently active warnings, this
|
||||||
}
|
// frame might get displayed in place of the last frame.
|
||||||
list.add(thisFrameTime);
|
requestData(new DataTime(SimulatedTime.getSystemTime().getTime()));
|
||||||
entry.times = list;
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see com.raytheon.viz.core.rsc.IVizResource#dispose()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void disposeInternal() {
|
||||||
|
timer.cancel();
|
||||||
|
|
||||||
|
for (WarningEntry entry : entryMap.values()) {
|
||||||
|
if (entry.shadedShape != null) {
|
||||||
|
entry.shadedShape.dispose();
|
||||||
|
}
|
||||||
|
if (entry.wireframeShape != null) {
|
||||||
|
entry.wireframeShape.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.frames.put(thisFrameTime, watchList);
|
entryMap.clear();
|
||||||
System.out.println("Init Frame: " + (System.currentTimeMillis() - t0)
|
if (warningsFont != null) {
|
||||||
+ " ms");
|
warningsFont.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected synchronized void updateFrames() throws VizException {
|
public void resourceChanged(ChangeType type, Object object) {
|
||||||
if (!this.recordsToLoad.isEmpty()) {
|
if (type == ChangeType.DATA_UPDATE) {
|
||||||
for (AbstractWarningRecord watchRec : recordsToLoad) {
|
PluginDataObject[] pdo = (PluginDataObject[]) object;
|
||||||
WarningAction watchAct = WarningAction.valueOf(watchRec
|
synchronized (WatchesResource.this) {
|
||||||
.getAct());
|
{
|
||||||
TimeRange tr = new TimeRange(watchRec.getStartTime(),
|
try {
|
||||||
watchRec.getEndTime());
|
addRecord(pdo);
|
||||||
synchronized (frames) {
|
} catch (VizException e) {
|
||||||
for (DataTime dt : frames.keySet()) {
|
statusHandler.handle(Priority.SIGNIFICANT,
|
||||||
if (tr.contains(dt.getValidTime().getTime())) {
|
e.getLocalizedMessage(), e);
|
||||||
boolean add = true;
|
}
|
||||||
ArrayList<AbstractWarningRecord> remove = new ArrayList<AbstractWarningRecord>();
|
}
|
||||||
List<AbstractWarningRecord> watchList = frames
|
}
|
||||||
.get(dt);
|
} else if (type == ChangeType.CAPABILITY) {
|
||||||
for (AbstractWarningRecord watch : watchList) {
|
if (color != null
|
||||||
// Do not plot watches that have been Cancelled
|
&& color.equals(getCapability((ColorableCapability.class))
|
||||||
// or
|
.getColor()) == false) {
|
||||||
// Expired
|
color = getCapability((ColorableCapability.class)).getColor();
|
||||||
if ((watchAct == WarningAction.CAN || watchAct == WarningAction.EXP)
|
|
||||||
&& watchRec.getStartTime().after(dt) == false
|
|
||||||
&& watchRec.getEtn().equals(
|
|
||||||
watch.getEtn())
|
|
||||||
&& watchRec.getPhensig().equals(
|
|
||||||
watch.getPhensig())
|
|
||||||
&& watchRec.getUgcsString() != null
|
|
||||||
&& watchRec.getUgcsString()[0] != null
|
|
||||||
&& watchRec.getUgcsString()[0]
|
|
||||||
.endsWith("000")) {
|
|
||||||
remove.add(watch);
|
|
||||||
}
|
|
||||||
if (watchAct == WarningAction.CON
|
|
||||||
&& (WarningAction.valueOf(watch
|
|
||||||
.getAct()) == WarningAction.CON || WarningAction
|
|
||||||
.valueOf(watch.getAct()) == WarningAction.NEW)
|
|
||||||
&& watchRec.getEtn().equals(
|
|
||||||
watch.getEtn())
|
|
||||||
&& watchRec.getPhensig().equals(
|
|
||||||
watch.getPhensig())) {
|
|
||||||
if (watchRec.getStartTime().after(
|
|
||||||
watch.getStartTime())) {
|
|
||||||
remove.add(watch);
|
|
||||||
} else {
|
|
||||||
add = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (AbstractWarningRecord w : remove) {
|
for (String dataUri : entryMap.keySet()) {
|
||||||
watchList.remove(w);
|
WarningEntry entry = entryMap.get(dataUri);
|
||||||
}
|
if (entry.shadedShape != null) {
|
||||||
|
entry.shadedShape.dispose();
|
||||||
if (add) {
|
try {
|
||||||
watchList.add(watchRec);
|
initShape(target, entry.record);
|
||||||
scheduleTimer(watchRec);
|
} catch (VizException e) {
|
||||||
initShape(watchRec);
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
|
e.getLocalizedMessage(), e);
|
||||||
WarningEntry entry = entryMap.get(watchRec
|
|
||||||
.getDataURI());
|
|
||||||
if (entry == null) {
|
|
||||||
entry = new WarningEntry();
|
|
||||||
entry.record = watchRec;
|
|
||||||
entryMap.put(watchRec.getDataURI(), entry);
|
|
||||||
}
|
|
||||||
List<DataTime> list = entry.times;
|
|
||||||
if (list == null) {
|
|
||||||
list = new ArrayList<DataTime>();
|
|
||||||
}
|
|
||||||
list.add(dt);
|
|
||||||
entry.times = list;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (frames.containsKey(new DataTime(watchRec.getStartTime())) == false) {
|
|
||||||
initNewFrame(new DataTime(watchRec.getStartTime()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
recordsToLoad.clear();
|
|
||||||
}
|
}
|
||||||
|
issueRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initShape(AbstractWarningRecord record) throws VizException {
|
protected void initShape(IGraphicsTarget target,
|
||||||
|
AbstractWarningRecord record) throws VizException {
|
||||||
Geometry geo;
|
Geometry geo;
|
||||||
|
|
||||||
if (record.getUgczones().size() > 0) {
|
if (record.getUgczones().size() > 0) {
|
||||||
setGeometry(record);
|
setGeometry(record);
|
||||||
if (record.getGeometry() != null) {
|
if (record.getGeometry() != null) {
|
||||||
IShadedShape ss = target.createShadedShape(false, descriptor,
|
IShadedShape ss = target.createShadedShape(false,
|
||||||
false);
|
descriptor.getGridGeometry(), false);
|
||||||
geo = (Geometry) record.getGeometry().clone();
|
geo = (Geometry) record.getGeometry().clone();
|
||||||
JTSCompiler jtsCompiler = new JTSCompiler(ss, null,
|
JTSCompiler jtsCompiler = new JTSCompiler(ss, null,
|
||||||
this.descriptor, PointStyle.CROSS);
|
this.descriptor, PointStyle.CROSS);
|
||||||
|
@ -279,6 +206,66 @@ public class WatchesResource extends AbstractWatchesResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected synchronized void updateDisplay(IGraphicsTarget target)
|
||||||
|
throws VizException {
|
||||||
|
|
||||||
|
if (!recordsToLoad.isEmpty()) {
|
||||||
|
// Merges all the zones for the same vtec and time
|
||||||
|
List<AbstractWarningRecord> mergedWatches = mergeWatches(recordsToLoad);
|
||||||
|
for (AbstractWarningRecord watchrec : mergedWatches) {
|
||||||
|
|
||||||
|
WarningAction watchact = WarningAction.valueOf(watchrec
|
||||||
|
.getAct());
|
||||||
|
int watchSize = watchrec.getUgczones().size();
|
||||||
|
|
||||||
|
if (watchact != WarningAction.NEW) {
|
||||||
|
AbstractWarningRecord createShape = null;
|
||||||
|
for (String entryKey : entryMap.keySet()) {
|
||||||
|
WarningEntry entry = entryMap.get(entryKey);
|
||||||
|
AbstractWarningRecord rec = entry.record;
|
||||||
|
|
||||||
|
if (rec.getPhensig().equals(watchrec.getPhensig())
|
||||||
|
&& rec.getOfficeid().equals(
|
||||||
|
watchrec.getOfficeid())
|
||||||
|
&& rec.getEtn().equals(watchrec.getEtn())) {
|
||||||
|
int recSize = rec.getUgczones().size();
|
||||||
|
if (!entry.partialCancel) {
|
||||||
|
if (watchact == WarningAction.EXP
|
||||||
|
|| watchact == WarningAction.CAN) {
|
||||||
|
entry.partialCancel = true;
|
||||||
|
entry.record.setEndTime((Calendar) watchrec
|
||||||
|
.getStartTime().clone());
|
||||||
|
} else if (watchact == WarningAction.CON
|
||||||
|
&& recSize > watchSize
|
||||||
|
&& watchrec.getStartTime().after(
|
||||||
|
rec.getStartTime())) {
|
||||||
|
entry.partialCancel = true;
|
||||||
|
entry.record.setEndTime((Calendar) watchrec
|
||||||
|
.getStartTime().clone());
|
||||||
|
createShape = watchrec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createShape != null) {
|
||||||
|
WarningEntry entry = entryMap.get(createShape
|
||||||
|
.getDataURI());
|
||||||
|
if (entry != null) {
|
||||||
|
entry.shadedShape.dispose();
|
||||||
|
}
|
||||||
|
initShape(target, createShape);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
initShape(target, watchrec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recordsToLoad.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setGeometry(AbstractWarningRecord record) {
|
private void setGeometry(AbstractWarningRecord record) {
|
||||||
List<String> county = new ArrayList<String>();
|
List<String> county = new ArrayList<String>();
|
||||||
List<String> marinezone = new ArrayList<String>();
|
List<String> marinezone = new ArrayList<String>();
|
||||||
|
@ -365,35 +352,90 @@ public class WatchesResource extends AbstractWatchesResource {
|
||||||
record.setGeometry(geometry);
|
record.setGeometry(geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Combining watches with the same ETN (Watch No.) into a single record.
|
* Groups all the ugc zones with the same 'product.act.phensig.etn'
|
||||||
* This will also help performance to make a single DB query.
|
|
||||||
*/
|
*/
|
||||||
private void addWatch(Map<String, AbstractWarningRecord> watches,
|
private List<AbstractWarningRecord> mergeWatches(
|
||||||
AbstractWarningRecord watchrec) {
|
List<AbstractWarningRecord> watchrecs) {
|
||||||
String key = watchrec.getProductClass() + "." + watchrec.getPhensig()
|
Map<String, AbstractWarningRecord> watches = new HashMap<String, AbstractWarningRecord>();
|
||||||
+ "." + watchrec.getEtn();
|
for (AbstractWarningRecord watchrec : watchrecs) {
|
||||||
|
String key = watchrec.getAct() + '.' + watchrec.getPhensig() + '.'
|
||||||
AbstractWarningRecord watch = null;
|
+ watchrec.getEtn() + '.'
|
||||||
WarningAction act = WarningAction.valueOf(watchrec.getAct());
|
+ sdf.format(watchrec.getStartTime().getTime());
|
||||||
|
AbstractWarningRecord watch = watches.get(key);
|
||||||
if (watches.containsKey(key)) {
|
if (watch == null) {
|
||||||
watch = watches.get(key);
|
watch = watchrec;
|
||||||
Set<UGCZone> ugcZones = watch.getUgczones();
|
} else if (watchrec.getUgczones() != null) {
|
||||||
for (UGCZone zone : watchrec.getUgczones()) {
|
Set<UGCZone> ugcZones = watch.getUgczones();
|
||||||
if (act == WarningAction.CAN || act == WarningAction.EXP) {
|
ugcZones.addAll(watchrec.getUgczones());
|
||||||
ugcZones.remove(zone);
|
watch.setUgczones(ugcZones);
|
||||||
} else {
|
|
||||||
ugcZones.add(zone);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
watch.setUgczones(ugcZones);
|
|
||||||
} else if (act != WarningAction.CAN && act != WarningAction.EXP) {
|
|
||||||
watch = watchrec;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (watch != null) {
|
|
||||||
watches.put(key, watch);
|
watches.put(key, watch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayList<AbstractWarningRecord> mergedWatches = new ArrayList<AbstractWarningRecord>(
|
||||||
|
watches.values());
|
||||||
|
Collections.sort(mergedWatches, comparator);
|
||||||
|
|
||||||
|
return mergedWatches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a WarningExpirationTask for the end time of the passing in
|
||||||
|
* record
|
||||||
|
*
|
||||||
|
* @param rec
|
||||||
|
* a WarningRecord
|
||||||
|
*/
|
||||||
|
protected void scheduleTimer(AbstractWarningRecord rec) {
|
||||||
|
// only schedule if record has not expired already
|
||||||
|
long now = SimulatedTime.getSystemTime().getTime().getTime();
|
||||||
|
long endTime = rec.getEndTime().getTimeInMillis();
|
||||||
|
synchronized (expTaskSet) {
|
||||||
|
if (endTime > now && !expTaskSet.contains(new Long(endTime))) {
|
||||||
|
WarningExpirationTask task = new WarningExpirationTask(this);
|
||||||
|
timer.schedule(task, rec.getEndTime().getTime());
|
||||||
|
expTaskSet.add(new Long(endTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redo time matching and remove the passed in time from the map of
|
||||||
|
* scheduled times
|
||||||
|
*
|
||||||
|
* @param triggerTime
|
||||||
|
*/
|
||||||
|
public void redoTimeMatching(long triggerTime) {
|
||||||
|
redoTimeMatching();
|
||||||
|
Long time = new Long(triggerTime);
|
||||||
|
// remove the instance of the trigger time from the map
|
||||||
|
synchronized (expTaskSet) {
|
||||||
|
if (expTaskSet != null && expTaskSet.contains(time)) {
|
||||||
|
expTaskSet.remove(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redo the time matching
|
||||||
|
*/
|
||||||
|
public void redoTimeMatching() {
|
||||||
|
try {
|
||||||
|
this.getDescriptor().getTimeMatcher().redoTimeMatching(this);
|
||||||
|
this.getDescriptor().getTimeMatcher()
|
||||||
|
.redoTimeMatching(this.getDescriptor());
|
||||||
|
} catch (VizException e) {
|
||||||
|
// TODO Auto-generated catch block. Please revise as appropriate.
|
||||||
|
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getEventKey(WarningEntry entry) {
|
||||||
|
AbstractWarningRecord r = entry.record;
|
||||||
|
return r.getAct() + '.' + r.getPhensig() + '.' + r.getEtn() + '.'
|
||||||
|
+ sdf.format(entry.record.getStartTime().getTime());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue