Issue #1149 Refactored watches and warnings.
Former-commit-id: 3e4148ce433d9f8810f383f56c8ca9b24802de93
This commit is contained in:
parent
01a13dee33
commit
e859dd05e9
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.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
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.warning.AbstractWarningRecord;
|
||||
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.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.map.MapDescriptor;
|
||||
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.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.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
|
||||
* String array returned from getText method
|
||||
* Jun 04, 2012 DR14992 mgamazaychikov Reversed the previous changes
|
||||
* Sep 26, 2012 jsanchez Refactored AbstractWarningResource and AbstractWatchesResource into this class.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -42,6 +83,60 @@ import com.raytheon.viz.warnings.DateUtil;
|
|||
public abstract class AbstractWWAResource extends
|
||||
AbstractVizResource<WWAResourceData, MapDescriptor> implements
|
||||
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
|
||||
.toArray(new DataTime[0]);
|
||||
|
@ -57,13 +152,23 @@ public abstract class AbstractWWAResource extends
|
|||
|
||||
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) {
|
||||
super(data, props);
|
||||
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)
|
||||
*
|
||||
|
@ -79,6 +184,316 @@ public abstract class AbstractWWAResource extends
|
|||
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)
|
||||
throws VizException {
|
||||
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) {
|
||||
String vid = record.getPhensig();
|
||||
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.WKTReader;
|
||||
|
||||
|
||||
public class CWASPSResource extends WarningsResource {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
|
@ -230,14 +231,14 @@ public class CWASPSResource extends WarningsResource {
|
|||
|
||||
textToPrint[2] = record.getPil();
|
||||
|
||||
SimpleDateFormat startFormat = AbstractWarningResource.DEFAULT_FORMAT;
|
||||
SimpleDateFormat endFormat = AbstractWarningResource.DEFAULT_FORMAT;
|
||||
SimpleDateFormat startFormat = AbstractWWAResource.DEFAULT_FORMAT;
|
||||
SimpleDateFormat endFormat = AbstractWWAResource.DEFAULT_FORMAT;
|
||||
if (mapWidth == 0) {
|
||||
startFormat = AbstractWarningResource.LONG_FORMAT;
|
||||
endFormat = AbstractWarningResource.DAY_FORMAT;
|
||||
startFormat = AbstractWWAResource.LONG_FORMAT;
|
||||
endFormat = AbstractWWAResource.DAY_FORMAT;
|
||||
} else if (mapWidth <= 200) {
|
||||
startFormat = AbstractWarningResource.DAY_FORMAT;
|
||||
endFormat = AbstractWarningResource.DAY_FORMAT;
|
||||
startFormat = AbstractWWAResource.DAY_FORMAT;
|
||||
endFormat = AbstractWWAResource.DAY_FORMAT;
|
||||
}
|
||||
|
||||
synchronized (startFormat) {
|
||||
|
|
|
@ -17,7 +17,7 @@ import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* May 12, 2011 jsanchez Initial creation
|
||||
*
|
||||
* Sep 27, 2012 1149 jsanchez Updated order of actions. Put CON before CAN,EXP
|
||||
* </pre>
|
||||
*
|
||||
* @author jsanchez
|
||||
|
@ -30,6 +30,7 @@ public class WarningRecordComparator implements
|
|||
* Compares the WarningRecords by phenSig, ETN, action, then starttime
|
||||
* (descending order)
|
||||
*/
|
||||
@Override
|
||||
public int compare(AbstractWarningRecord wr1, AbstractWarningRecord wr2) {
|
||||
int rval = 0;
|
||||
|
||||
|
@ -39,19 +40,30 @@ public class WarningRecordComparator implements
|
|||
rval = Double.compare(Double.parseDouble(wr1.getEtn()),
|
||||
Double.parseDouble(wr2.getEtn()));
|
||||
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;
|
||||
} else if (wr1.getAct().equals(WarningAction.NEW.toString())) {
|
||||
} else if (act1 == WarningAction.NEW) {
|
||||
rval = -1;
|
||||
} else if (wr2.getAct().equals(WarningAction.NEW.toString())) {
|
||||
} else if (act2 == WarningAction.NEW) {
|
||||
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 {
|
||||
rval = wr1.getAct().compareTo(wr2.getAct());
|
||||
}
|
||||
|
||||
if (rval == 0) {
|
||||
rval = -1
|
||||
* wr1.getStartTime().compareTo(wr2.getStartTime());
|
||||
rval = 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.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Date;
|
||||
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.warning.AbstractWarningRecord;
|
||||
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.time.DataTime;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.catalog.LayerProperty;
|
||||
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
|
||||
import com.raytheon.uf.viz.core.VizApp;
|
||||
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.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.ResourceType;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
|
||||
import com.raytheon.viz.core.rsc.jts.JTSCompiler;
|
||||
import com.raytheon.viz.texteditor.util.SiteAbbreviationUtil;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
@ -55,31 +56,268 @@ import com.vividsolutions.jts.geom.Geometry;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 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.
|
||||
* warning to start time of update.
|
||||
* Jun 04, 2012 DR14992 mgamazaychikov Fix the problem with plotting expiration time for
|
||||
* NEW warning when CAN warning is issued
|
||||
*
|
||||
* Sep 27, 2012 1149 jsanchez Refactored methods from AbstractWarningsResource into this class.
|
||||
* </pre>
|
||||
*
|
||||
* @author jsanchez
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class WarningsResource extends AbstractWarningResource {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(WarningsResource.class);
|
||||
public class WarningsResource extends AbstractWWAResource {
|
||||
|
||||
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
|
||||
*/
|
||||
public WarningsResource(WWAResourceData data, LoadProperties props) {
|
||||
super(data, props);
|
||||
resourceName = "Warnings";
|
||||
}
|
||||
|
||||
@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()) {
|
||||
FramesInfo info = getDescriptor().getFramesInfo();
|
||||
DataTime[] frames = info.getFrameTimes();
|
||||
|
@ -121,7 +359,7 @@ public class WarningsResource extends AbstractWarningResource {
|
|||
entry.record.setEndTime((Calendar) warnrec
|
||||
.getStartTime().clone());
|
||||
}
|
||||
|
||||
|
||||
if (!rec.getCountyheader().equals(
|
||||
warnrec.getCountyheader())
|
||||
&& act == WarningAction.CAN) {
|
||||
|
@ -166,103 +404,50 @@ public class WarningsResource extends AbstractWarningResource {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initShape(IGraphicsTarget target,
|
||||
AbstractWarningRecord record) {
|
||||
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 void initInternal(IGraphicsTarget target) throws VizException {
|
||||
DataTime earliest = this.descriptor.getFramesInfo().getFrameTimes()[0];
|
||||
requestData(earliest);
|
||||
/**
|
||||
* 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) {
|
||||
if (heartBeatTask == null) {
|
||||
heartBeatTask = new RepaintHeartbeat();
|
||||
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);
|
||||
}
|
||||
heartBeatTask.addResource(this);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
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));
|
||||
}
|
||||
|
||||
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()]);
|
||||
protected String getEventKey(WarningEntry entry) {
|
||||
AbstractWarningRecord r = entry.record;
|
||||
return r.getOfficeid() + '.' + r.getPhensig() + '.' + r.getEtn();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package com.raytheon.viz.warnings.rsc;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
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 com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||
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.SpatialQueryFactory;
|
||||
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.time.DataTime;
|
||||
import com.raytheon.uf.common.time.TimeRange;
|
||||
import com.raytheon.uf.viz.core.catalog.LayerProperty;
|
||||
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||
import com.raytheon.uf.viz.core.drawables.FillPatterns;
|
||||
import com.raytheon.uf.viz.core.drawables.IShadedShape;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
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.PointStyle;
|
||||
import com.raytheon.viz.texteditor.util.SiteAbbreviationUtil;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.GeometryCollection;
|
||||
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) {
|
||||
super(data, props);
|
||||
timer = new Timer();
|
||||
expTaskSet = new HashSet<Long>();
|
||||
resourceName = "Watches";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
DataTime time = displayedDate;
|
||||
if (time == null) {
|
||||
time = descriptor.getTimeForResource(this);
|
||||
}
|
||||
String name = resourceData.name != null ? resourceData.name : "Watches";
|
||||
if (time != null) {
|
||||
name += " " + time.getLegendString();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
protected void initInternal(IGraphicsTarget target) throws VizException {
|
||||
if (this.target == null) {
|
||||
this.target = target;
|
||||
|
||||
@Override
|
||||
protected synchronized void initNewFrame(DataTime thisFrameTime)
|
||||
throws VizException {
|
||||
long t0 = System.currentTimeMillis();
|
||||
HashMap<String, RequestConstraint> map = (HashMap<String, RequestConstraint>) resourceData
|
||||
.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);
|
||||
synchronized (this) {
|
||||
try {
|
||||
addRecord(getWarningRecordArray());
|
||||
} catch (VizException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
List<DataTime> list = entry.times;
|
||||
if (list == null) {
|
||||
list = new ArrayList<DataTime>();
|
||||
}
|
||||
list.add(thisFrameTime);
|
||||
entry.times = list;
|
||||
}
|
||||
}
|
||||
// force creation of a frame for any currently active warnings, this
|
||||
// frame might get displayed in place of the last frame.
|
||||
requestData(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();
|
||||
}
|
||||
}
|
||||
|
||||
this.frames.put(thisFrameTime, watchList);
|
||||
System.out.println("Init Frame: " + (System.currentTimeMillis() - t0)
|
||||
+ " ms");
|
||||
entryMap.clear();
|
||||
if (warningsFont != null) {
|
||||
warningsFont.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void updateFrames() throws VizException {
|
||||
if (!this.recordsToLoad.isEmpty()) {
|
||||
for (AbstractWarningRecord watchRec : recordsToLoad) {
|
||||
WarningAction watchAct = WarningAction.valueOf(watchRec
|
||||
.getAct());
|
||||
TimeRange tr = new TimeRange(watchRec.getStartTime(),
|
||||
watchRec.getEndTime());
|
||||
synchronized (frames) {
|
||||
for (DataTime dt : frames.keySet()) {
|
||||
if (tr.contains(dt.getValidTime().getTime())) {
|
||||
boolean add = true;
|
||||
ArrayList<AbstractWarningRecord> remove = new ArrayList<AbstractWarningRecord>();
|
||||
List<AbstractWarningRecord> watchList = frames
|
||||
.get(dt);
|
||||
for (AbstractWarningRecord watch : watchList) {
|
||||
// Do not plot watches that have been Cancelled
|
||||
// or
|
||||
// Expired
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void resourceChanged(ChangeType type, Object object) {
|
||||
if (type == ChangeType.DATA_UPDATE) {
|
||||
PluginDataObject[] pdo = (PluginDataObject[]) object;
|
||||
synchronized (WatchesResource.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 (AbstractWarningRecord w : remove) {
|
||||
watchList.remove(w);
|
||||
}
|
||||
|
||||
if (add) {
|
||||
watchList.add(watchRec);
|
||||
scheduleTimer(watchRec);
|
||||
initShape(watchRec);
|
||||
|
||||
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;
|
||||
}
|
||||
for (String dataUri : entryMap.keySet()) {
|
||||
WarningEntry entry = entryMap.get(dataUri);
|
||||
if (entry.shadedShape != null) {
|
||||
entry.shadedShape.dispose();
|
||||
try {
|
||||
initShape(target, entry.record);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (frames.containsKey(new DataTime(watchRec.getStartTime())) == false) {
|
||||
initNewFrame(new DataTime(watchRec.getStartTime()));
|
||||
}
|
||||
}
|
||||
recordsToLoad.clear();
|
||||
}
|
||||
issueRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initShape(AbstractWarningRecord record) throws VizException {
|
||||
protected void initShape(IGraphicsTarget target,
|
||||
AbstractWarningRecord record) throws VizException {
|
||||
Geometry geo;
|
||||
|
||||
if (record.getUgczones().size() > 0) {
|
||||
setGeometry(record);
|
||||
if (record.getGeometry() != null) {
|
||||
IShadedShape ss = target.createShadedShape(false, descriptor,
|
||||
false);
|
||||
IShadedShape ss = target.createShadedShape(false,
|
||||
descriptor.getGridGeometry(), false);
|
||||
geo = (Geometry) record.getGeometry().clone();
|
||||
JTSCompiler jtsCompiler = new JTSCompiler(ss, null,
|
||||
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) {
|
||||
List<String> county = new ArrayList<String>();
|
||||
List<String> marinezone = new ArrayList<String>();
|
||||
|
@ -365,35 +352,90 @@ public class WatchesResource extends AbstractWatchesResource {
|
|||
record.setGeometry(geometry);
|
||||
}
|
||||
|
||||
/*
|
||||
* Combining watches with the same ETN (Watch No.) into a single record.
|
||||
* This will also help performance to make a single DB query.
|
||||
/**
|
||||
* Groups all the ugc zones with the same 'product.act.phensig.etn'
|
||||
*/
|
||||
private void addWatch(Map<String, AbstractWarningRecord> watches,
|
||||
AbstractWarningRecord watchrec) {
|
||||
String key = watchrec.getProductClass() + "." + watchrec.getPhensig()
|
||||
+ "." + watchrec.getEtn();
|
||||
|
||||
AbstractWarningRecord watch = null;
|
||||
WarningAction act = WarningAction.valueOf(watchrec.getAct());
|
||||
|
||||
if (watches.containsKey(key)) {
|
||||
watch = watches.get(key);
|
||||
Set<UGCZone> ugcZones = watch.getUgczones();
|
||||
for (UGCZone zone : watchrec.getUgczones()) {
|
||||
if (act == WarningAction.CAN || act == WarningAction.EXP) {
|
||||
ugcZones.remove(zone);
|
||||
} else {
|
||||
ugcZones.add(zone);
|
||||
}
|
||||
private List<AbstractWarningRecord> mergeWatches(
|
||||
List<AbstractWarningRecord> watchrecs) {
|
||||
Map<String, AbstractWarningRecord> watches = new HashMap<String, AbstractWarningRecord>();
|
||||
for (AbstractWarningRecord watchrec : watchrecs) {
|
||||
String key = watchrec.getAct() + '.' + watchrec.getPhensig() + '.'
|
||||
+ watchrec.getEtn() + '.'
|
||||
+ sdf.format(watchrec.getStartTime().getTime());
|
||||
AbstractWarningRecord watch = watches.get(key);
|
||||
if (watch == null) {
|
||||
watch = watchrec;
|
||||
} else if (watchrec.getUgczones() != null) {
|
||||
Set<UGCZone> ugcZones = watch.getUgczones();
|
||||
ugcZones.addAll(watchrec.getUgczones());
|
||||
watch.setUgczones(ugcZones);
|
||||
}
|
||||
watch.setUgczones(ugcZones);
|
||||
} else if (act != WarningAction.CAN && act != WarningAction.EXP) {
|
||||
watch = watchrec;
|
||||
}
|
||||
|
||||
if (watch != null) {
|
||||
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