Omaha #4379 Display live CWAs

Change-Id: I39e1243d9fbc8d3206dea42f91039fc90db9f2ac

Former-commit-id: 7c711723a8b3cc3ddab6523da7e9219bfb9efe72
This commit is contained in:
Nathan Bowler 2015-06-18 16:25:56 -04:00
parent f3f34372da
commit 93e423e9b0
2 changed files with 182 additions and 59 deletions

View file

@ -20,10 +20,16 @@
package com.raytheon.uf.viz.cwa.rsc; package com.raytheon.uf.viz.cwa.rsc;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.CoordinateReferenceSystem;
@ -35,7 +41,10 @@ import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.pointdata.PointDataContainer; import com.raytheon.uf.common.pointdata.PointDataContainer;
import com.raytheon.uf.common.pointdata.PointDataView; import com.raytheon.uf.common.pointdata.PointDataView;
import com.raytheon.uf.common.time.DataTime; import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.ISimulatedTimeChangeListener;
import com.raytheon.uf.common.time.SimulatedTime;
import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.viz.core.AbstractTimeMatcher;
import com.raytheon.uf.viz.core.DrawableString; import com.raytheon.uf.viz.core.DrawableString;
import com.raytheon.uf.viz.core.IGraphicsTarget; import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.drawables.IFont; import com.raytheon.uf.viz.core.drawables.IFont;
@ -46,11 +55,12 @@ import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.MapDescriptor; import com.raytheon.uf.viz.core.map.MapDescriptor;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource; import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged; import com.raytheon.uf.viz.core.rsc.IResourceDataChanged.ChangeType;
import com.raytheon.uf.viz.core.rsc.LoadProperties; 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.ColorableCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability; import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability; import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
import com.raytheon.uf.viz.core.time.TimeMatchingJob;
import com.raytheon.viz.pointdata.PointDataRequest; import com.raytheon.viz.pointdata.PointDataRequest;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.GeometryFactory;
@ -70,6 +80,7 @@ import com.vividsolutions.jts.geom.Polygon;
* Jun 10,2011 9744 cjeanbap Added Magnification, Outline, and Density * Jun 10,2011 9744 cjeanbap Added Magnification, Outline, and Density
* compabilities. * compabilities.
* May 11, 2015 4379 nabowle Display all current CWAs for each frame. * May 11, 2015 4379 nabowle Display all current CWAs for each frame.
* Jun 15, 2015 4379 nabowle Make last frame a live frame.
* </pre> * </pre>
* *
* @author jsanchez * @author jsanchez
@ -77,11 +88,7 @@ import com.vividsolutions.jts.geom.Polygon;
*/ */
public class CWAResource extends public class CWAResource extends
AbstractVizResource<CWAResourceData, MapDescriptor> implements AbstractVizResource<CWAResourceData, MapDescriptor> implements
IResourceDataChanged { ISimulatedTimeChangeListener {
protected DataTime displayedDataTime;
private Map<DataTime, CWAFrame> frameMap;
private static final String LATS = "latitudes"; private static final String LATS = "latitudes";
@ -97,8 +104,6 @@ public class CWAResource extends
private static final String CWA_NAME = "Conus Center Weather Advisory"; private static final String CWA_NAME = "Conus Center Weather Advisory";
private static final String ID = "id";
private static final String DATA_TIME = "dataTime"; private static final String DATA_TIME = "dataTime";
private static final String REF_TIME = "refTime"; private static final String REF_TIME = "refTime";
@ -107,6 +112,16 @@ public class CWAResource extends
private static final String START = DATA_TIME + ".validPeriod.start"; private static final String START = DATA_TIME + ".validPeriod.start";
protected static RefreshTimerTask refreshTask;
protected static Timer refreshTimer;
protected DataTime displayedDataTime;
private Map<DataTime, CWAFrame> frameMap;
private CWAFrame liveFrame = new CWAFrame(now());
private IFont font; private IFont font;
private class CWAFrame implements IRenderable { private class CWAFrame implements IRenderable {
@ -125,14 +140,6 @@ public class CWAResource extends
strings = new ArrayList<DrawableString>(); strings = new ArrayList<DrawableString>();
} }
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.drawables.IRenderable#paint(com.raytheon
* .uf.viz.core.IGraphicsTarget,
* com.raytheon.uf.viz.core.drawables.PaintProperties)
*/
@Override @Override
public void paint(IGraphicsTarget target, PaintProperties paintProps) public void paint(IGraphicsTarget target, PaintProperties paintProps)
throws VizException { throws VizException {
@ -164,7 +171,7 @@ public class CWAResource extends
*/ */
private void updateFrame(IGraphicsTarget target, private void updateFrame(IGraphicsTarget target,
PaintProperties paintProps) throws VizException { PaintProperties paintProps) throws VizException {
Map<String, RequestConstraint> constraints = new HashMap<String, RequestConstraint>(); Map<String, RequestConstraint> constraints = new HashMap<>();
String startTime = TimeUtil.formatToSqlTimestamp(time.getRefTime()); String startTime = TimeUtil.formatToSqlTimestamp(time.getRefTime());
// Select CWAs whose valid period contains this frame's start time. // Select CWAs whose valid period contains this frame's start time.
@ -179,20 +186,12 @@ public class CWAResource extends
constraints.put(END, constraint); constraints.put(END, constraint);
// Request the point data // Request the point data
PointDataContainer pdc = PointDataRequest this.pdc = PointDataRequest
.requestPointDataAllLevels((DataTime) null, .requestPointDataAllLevels((DataTime) null,
resourceData.getMetadataMap().get("pluginName") resourceData.getMetadataMap().get("pluginName")
.getConstraintValue(), .getConstraintValue(),
getParameters(), null, constraints); getParameters(), null, constraints);
if (this.pdc == null) {
this.pdc = pdc;
} else {
this.pdc.combine(pdc);
this.pdc.setCurrentSz(this.pdc.getAllocatedSz());
this.framePdvs = null;
}
if (wfs != null) { if (wfs != null) {
wfs.dispose(); wfs.dispose();
} }
@ -200,7 +199,10 @@ public class CWAResource extends
wfs = target.createWireframeShape(false, descriptor); wfs = target.createWireframeShape(false, descriptor);
if (this.framePdvs == null) { if (this.pdc == null) {
// nothing met the query restraints
this.framePdvs = Collections.emptyList();
} else {
this.framePdvs = getPDVs(); this.framePdvs = getPDVs();
} }
@ -291,6 +293,36 @@ public class CWAResource extends
} }
} }
protected static class RefreshTimerTask extends TimerTask {
private final Set<CWAResource> resourceSet = new HashSet<>();
@Override
public void run() {
List<CWAResource> rscs;
synchronized (resourceSet) {
rscs = new ArrayList<>(resourceSet);
}
for (CWAResource rsc : rscs) {
rsc.updateLiveFrame(now());
rsc.issueRefresh();
rsc.redoTimeMatching();
}
}
public void addResource(CWAResource rsc) {
synchronized (resourceSet) {
resourceSet.add(rsc);
}
}
public void removeResource(CWAResource rsc) {
synchronized (resourceSet) {
resourceSet.remove(rsc);
}
}
}
protected CWAResource(CWAResourceData resourceData, protected CWAResource(CWAResourceData resourceData,
LoadProperties loadProperties) { LoadProperties loadProperties) {
super(resourceData, loadProperties); super(resourceData, loadProperties);
@ -298,19 +330,66 @@ public class CWAResource extends
this.dataTimes = new ArrayList<DataTime>(); this.dataTimes = new ArrayList<DataTime>();
} }
/**
* Cancel the heart beat timer task
*
* @param resource
*/
protected static void cancelRefreshTask(CWAResource resource) {
synchronized (RefreshTimerTask.class) {
if (refreshTask != null) {
refreshTask.removeResource(resource);
if (refreshTask.resourceSet.isEmpty()) {
refreshTimer.cancel();
refreshTimer = null;
refreshTask = null;
}
}
}
}
/**
* schedule the heart beat for the next minute
*/
protected static void scheduleRefreshTask(CWAResource resource) {
synchronized (RefreshTimerTask.class) {
if (refreshTask == null) {
refreshTimer = new Timer(true);
refreshTask = new RefreshTimerTask();
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, 1);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
refreshTimer.scheduleAtFixedRate(refreshTask, cal.getTime(),
TimeUtil.MILLIS_PER_MINUTE);
}
refreshTask.addResource(resource);
}
}
/**
* Get the current/simulated time to the minute. Seconds and Milliseconds
* will be zero so a consistent time can be used each minute when retrieving
* from the frame map.
*
* @return
*/
public static DataTime now() {
Calendar cal = Calendar.getInstance();
cal.setTime(SimulatedTime.getSystemTime().getTime());
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return new DataTime(cal);
}
@Override @Override
public String getName() { public String getName() {
return CWA_NAME; return CWA_NAME;
} }
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#paintInternal(com.raytheon
* .uf.viz.core.IGraphicsTarget,
* com.raytheon.uf.viz.core.drawables.PaintProperties)
*/
@Override @Override
protected void paintInternal(IGraphicsTarget target, protected void paintInternal(IGraphicsTarget target,
PaintProperties paintProps) throws VizException { PaintProperties paintProps) throws VizException {
@ -329,6 +408,7 @@ public class CWAResource extends
@Override @Override
protected void disposeInternal() { protected void disposeInternal() {
cancelRefreshTask(this);
if (font != null) { if (font != null) {
font.dispose(); font.dispose();
font = null; font = null;
@ -346,6 +426,9 @@ public class CWAResource extends
protected void initInternal(IGraphicsTarget target) throws VizException { protected void initInternal(IGraphicsTarget target) throws VizException {
this.font = target.initializeFont("Monospace", 11, this.font = target.initializeFont("Monospace", 11,
new Style[] { Style.ITALIC }); new Style[] { Style.ITALIC });
updateLiveFrame(now());
scheduleRefreshTask(this);
SimulatedTime.getSystemTime().addSimulatedTimeChangeListener(this);
} }
@Override @Override
@ -464,18 +547,13 @@ public class CWAResource extends
} }
} }
/* /**
* (non-Javadoc) * Handle Data Updates by adding the record and refreshing the display.
*
* @see
* com.raytheon.uf.viz.core.rsc.IResourceDataChanged#resourceChanged(com
* .raytheon.uf.viz.core.rsc.IResourceDataChanged.ChangeType,
* java.lang.Object)
*/ */
@Override @Override
public void resourceChanged(ChangeType type, Object object) { protected void resourceDataChanged(ChangeType type, Object updateObject) {
if (type == ChangeType.DATA_UPDATE) { if (type == ChangeType.DATA_UPDATE) {
PluginDataObject[] pdo = (PluginDataObject[]) object; PluginDataObject[] pdo = (PluginDataObject[]) updateObject;
for (PluginDataObject p : pdo) { for (PluginDataObject p : pdo) {
if (p instanceof CWARecord) { if (p instanceof CWARecord) {
addRecord((CWARecord) p); addRecord((CWARecord) p);
@ -485,17 +563,43 @@ public class CWAResource extends
issueRefresh(); issueRefresh();
} }
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#project(org.opengis.
* referencing.crs.CoordinateReferenceSystem)
*/
@Override @Override
public void project(CoordinateReferenceSystem crs) throws VizException { public void project(CoordinateReferenceSystem crs) throws VizException {
frameMap.get(displayedDataTime).wfs.dispose(); frameMap.get(displayedDataTime).wfs.dispose();
frameMap.get(displayedDataTime).wfs = null; frameMap.get(displayedDataTime).wfs = null;
} }
/**
* Update the live frame's time and mapping.
*/
protected void updateLiveFrame(DataTime time) {
synchronized (this.frameMap) {
this.frameMap.remove(this.liveFrame.time);
this.liveFrame.time = time;
this.liveFrame.dispose();
this.liveFrame.wfs = null;
this.frameMap.put(time, this.liveFrame);
}
}
/**
* Redo the time matching
*/
protected void redoTimeMatching() {
AbstractTimeMatcher timeMatcher = this.getDescriptor().getTimeMatcher();
if (timeMatcher != null) {
timeMatcher.redoTimeMatching(this);
TimeMatchingJob.scheduleTimeMatch(this.getDescriptor());
}
}
/**
* Updates the live frame to the current time set.
*/
@Override
public void timechanged() {
updateLiveFrame(now());
issueRefresh();
redoTimeMatching();
}
} }

View file

@ -19,6 +19,10 @@
**/ **/
package com.raytheon.uf.viz.cwa.rsc; package com.raytheon.uf.viz.cwa.rsc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlType;
@ -28,6 +32,7 @@ import com.raytheon.uf.common.dataplugin.cwa.CWARecord;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData; import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource; import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
@ -42,6 +47,7 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Feb 4, 2010 jsanchez Initial creation * Feb 4, 2010 jsanchez Initial creation
* Jun 16, 2015 4379 nabowle Add the current time to {@link #getAvailableTimes()}.
* *
* </pre> * </pre>
* *
@ -55,7 +61,7 @@ public class CWAResourceData extends AbstractRequestableResourceData {
.getHandler(CWAResourceData.class); .getHandler(CWAResourceData.class);
public CWAResourceData() { public CWAResourceData() {
// TODO Auto-generated constructor stub super();
} }
@Override @Override
@ -89,4 +95,17 @@ public class CWAResourceData extends AbstractRequestableResourceData {
} }
return rsc; return rsc;
} }
/**
* Return a set of available times for the given resource data. The current
* time is appended to the list so CWAResource can display a live view of
* active CWAs.
*/
@Override
public DataTime[] getAvailableTimes() throws VizException {
List<DataTime> times = new ArrayList<>();
times.addAll(Arrays.asList(super.getAvailableTimes()));
times.add(CWAResource.now());
return times.toArray(new DataTime[0]);
}
} }