Issue #1474 Fixed MetarPrecipResourceData and LightningResourceData so updates do not required requery. Made an AutoUpdater per plugin so they process independently of each other.

Amend: Only register product alerts in thin client if JMS is not disabled

Change-Id: Ic46daf57ef3ede3aad2a2f067e9764f85f7df9a2

Former-commit-id: b6a29c38a5 [formerly 115dc26748e0779b4c67cc74fe08c5bf17542632]
Former-commit-id: 9655d64069
This commit is contained in:
Max Schenkelberg 2013-01-23 15:10:17 -06:00
parent 3d838584ed
commit a8dc166a1f
12 changed files with 183 additions and 129 deletions

View file

@ -19,8 +19,10 @@
**/
package com.raytheon.uf.viz.core;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;
import org.apache.commons.beanutils.ConstructorUtils;
@ -56,7 +58,7 @@ public class RecordFactory {
private static RecordFactory instance = new RecordFactory();
/** Map containing the pluginName/Record class pairs */
private Map<String, Class<PluginDataObject>> defMap;
private Map<String, Class<PluginDataObject>> defMap = new HashMap<String, Class<PluginDataObject>>();
public static final String WILDCARD = "%";
@ -82,36 +84,39 @@ public class RecordFactory {
}
@SuppressWarnings("unchecked")
private synchronized void loadDefMap() throws VizException {
if (defMap == null) {
GetPluginRecordMapRequest req = new GetPluginRecordMapRequest();
Map<String, String> pluginRecordMap = (Map<String, String>) ThriftClient
.sendRequest(req);
Map<String, Class<PluginDataObject>> newDefMap = new HashMap<String, Class<PluginDataObject>>(
pluginRecordMap.size());
for (Map.Entry<String, String> entry : pluginRecordMap.entrySet()) {
String pluginName = entry.getKey();
String record = entry.getValue();
if (record != null) {
try {
Class<PluginDataObject> clazz = (Class<PluginDataObject>) Class
.forName(record);
newDefMap.put(pluginName, clazz);
} catch (Exception e) {
statusHandler.handle(Priority.DEBUG,
"Can't find record class for " + pluginName
+ " plugin", e);
System.out
.println("DEBUG: Can't find record class for "
+ pluginName + " plugin - alerts on "
+ pluginName + " data will be ignored");
}
private void loadDefMap() throws VizException {
GetPluginRecordMapRequest req = new GetPluginRecordMapRequest();
Map<String, String> pluginRecordMap = (Map<String, String>) ThriftClient
.sendRequest(req);
for (Map.Entry<String, String> entry : pluginRecordMap.entrySet()) {
String pluginName = entry.getKey();
String record = entry.getValue();
if (record != null) {
try {
Class<PluginDataObject> clazz = (Class<PluginDataObject>) Class
.forName(record);
defMap.put(pluginName, clazz);
} catch (Exception e) {
statusHandler.handle(Priority.DEBUG,
"Can't find record class for " + pluginName
+ " plugin", e);
System.out.println("DEBUG: Can't find record class for "
+ pluginName + " plugin - alerts on " + pluginName
+ " data will be ignored");
}
}
defMap = newDefMap;
}
}
/**
* Returns a collection of all supported plugins
*
* @return
*/
public Collection<String> getSupportedPlugins() {
return new TreeSet<String>(defMap.keySet());
}
/**
* Creates a map of the fields and values that compose a given dataURI
*
@ -123,7 +128,6 @@ public class RecordFactory {
*/
public Map<String, Object> loadMapFromUri(String dataURI)
throws VizException {
// If no dataURI return
if (dataURI == null) {
return null;
@ -181,10 +185,10 @@ public class RecordFactory {
*/
public Class<PluginDataObject> getPluginClass(String pluginName)
throws VizException {
if (defMap == null) {
loadDefMap();
Class<PluginDataObject> retVal = null;
if (defMap != null) {
retVal = defMap.get(pluginName);
}
Class<PluginDataObject> retVal = defMap.get(pluginName);
if (retVal == null) {
throw new NoPluginException("Can't find record class for "
+ pluginName + " plugin");

View file

@ -288,7 +288,7 @@ public abstract class AbstractRequestableResourceData extends
}
}
}
this.fireChangeListeners(ChangeType.DATA_UPDATE, updateData);
}
@ -683,7 +683,6 @@ public abstract class AbstractRequestableResourceData extends
int result = 1;
result = prime * result
+ ((binOffset == null) ? 0 : binOffset.hashCode());
result = prime * result + (isUpdatingOnMetadataOnly ? 1231 : 1237);
result = prime * result
+ ((metadataMap == null) ? 0 : metadataMap.hashCode());
result = prime * result
@ -724,10 +723,6 @@ public abstract class AbstractRequestableResourceData extends
return false;
}
if (isUpdatingOnMetadataOnly != other.isUpdatingOnMetadataOnly) {
return false;
}
if (!isObjectsEqual(metadataMap, other.metadataMap)) {
return false;
}

View file

@ -55,9 +55,6 @@ import com.raytheon.uf.viz.thinclient.localization.LocalizationCachePersistence;
import com.raytheon.uf.viz.thinclient.localization.ThinClientLocalizationInitializer;
import com.raytheon.uf.viz.thinclient.preferences.ThinClientPreferenceConstants;
import com.raytheon.uf.viz.thinclient.refresh.TimedRefresher;
import com.raytheon.viz.alerts.jobs.AutoUpdater;
import com.raytheon.viz.alerts.jobs.MenuUpdater;
import com.raytheon.viz.alerts.observers.ProductAlertObserver;
import com.raytheon.viz.ui.personalities.awips.AbstractCAVEComponent;
import com.raytheon.viz.ui.personalities.awips.CAVE;
@ -188,8 +185,11 @@ public class ThinClientComponent extends CAVE implements IThinClientComponent {
@Override
protected void initializeObservers() {
ThinClientNotificationManagerJob.getInstance();
ProductAlertObserver.addObserver(null, new MenuUpdater());
ProductAlertObserver.addObserver(null, new AutoUpdater());
IPreferenceStore store = Activator.getDefault().getPreferenceStore();
if (store.getBoolean(ThinClientPreferenceConstants.P_DISABLE_JMS) == false) {
// JMS Enabled, register product alerts
registerProductAlerts();
}
}
public void stopComponent() {

View file

@ -19,6 +19,7 @@
**/
package com.raytheon.viz.alerts.observers;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -306,58 +307,49 @@ public class ProductAlertObserver implements INotificationObserver {
PracticeDataURINotificationMessage uriMsg = (PracticeDataURINotificationMessage) payLoad;
dataURIs = uriMsg.getDataURIs();
}
for (int i = 0; i < dataURIs.length; ++i) {
String str = dataURIs[i];
processDataURI(str);
}
startWrappers();
if (dataURIs != null && dataURIs.length > 0) {
alertsProcessed += dataURIs.length;
}
long curTime = System.currentTimeMillis();
if (curTime - ALERT_LOG_INTERVAL > lastLogTime) {
if (alertsProcessed > 0) {
statusHandler.handle(Priority.VERBOSE, "Processed "
+ alertsProcessed + " alerts in the last "
+ ((curTime - lastLogTime) / 60000)
+ " minutes");
alertsProcessed = 0;
}
lastLogTime = curTime;
}
processDataURIs(Arrays.asList(dataURIs));
}
}
}
public static void processDerivedAlerts(Collection<String> datauris) {
for (String datauri : datauris) {
getInstance().processDataURI(datauri);
/**
* Processes the DataURIs as alert messages
*
* @param datauris
*/
public static void processDataURIAlerts(Collection<String> datauris) {
getInstance().processDataURIs(datauris);
}
private synchronized void processDataURIs(Collection<String> dataURIs) {
for (String str : dataURIs) {
processDataURI(str);
}
startWrappers();
if (dataURIs != null && dataURIs.size() > 0) {
alertsProcessed += dataURIs.size();
}
long curTime = System.currentTimeMillis();
if (curTime - ALERT_LOG_INTERVAL > lastLogTime) {
if (alertsProcessed > 0) {
statusHandler.handle(Priority.VERBOSE, "Processed "
+ alertsProcessed + " alerts in the last "
+ ((curTime - lastLogTime) / 60000) + " minutes");
alertsProcessed = 0;
}
lastLogTime = curTime;
}
getInstance().startWrappers();
}
private void processDataURI(String datauri) {
if (datauri == null)
return;
try {
Map<String, Object> attribs;
try {
attribs = RecordFactory.getInstance().loadMapFromUri(datauri);
} catch (NoPluginException e) {
// ignore, if we hit this it means we received an alert from
// edex about ingested data, but viz doesn't have the necessary
// plugins to do anything with it
return;
} catch (Exception e1) {
statusHandler.handle(Priority.WARN, e1.getLocalizedMessage(),
e1);
return;
}
Map<String, Object> attribs = RecordFactory.getInstance()
.loadMapFromUri(datauri);
AlertMessage am = new AlertMessage();
am.dataURI = datauri;
am.decodedAlert = Collections.unmodifiableMap(attribs);
@ -379,11 +371,12 @@ public class ProductAlertObserver implements INotificationObserver {
sendToObserver(obs, am);
}
}
} catch (RuntimeException e) {
statusHandler
.handle(Priority.PROBLEM, "Error preparing updates", e);
} catch (NoPluginException e) {
// ignore, if we hit this it means we received an alert from
// edex about ingested data, but viz doesn't have the necessary
// plugins to do anything with it
} catch (Exception e1) {
statusHandler.handle(Priority.WARN, e1.getLocalizedMessage(), e1);
}
}

View file

@ -298,7 +298,7 @@ public class GridUpdater implements IAlertObserver {
}
}
myUpdates.addAll(datauris);
ProductAlertObserver.processDerivedAlerts(datauris);
ProductAlertObserver.processDataURIAlerts(datauris);
}
/**

View file

@ -203,7 +203,7 @@ public class RadarUpdater implements IAlertObserver {
"Unable to generate updates for derived product", e);
}
}
ProductAlertObserver.processDerivedAlerts(datauris);
ProductAlertObserver.processDataURIAlerts(datauris);
}
private CacheKey getCacheKey(RadarRequestableLevelNode rNode) {

View file

@ -81,6 +81,16 @@ public class LightningResourceData extends AbstractRequestableResourceData {
return rsc;
}
@Override
public boolean isUpdatingOnMetadataOnly() {
return true;
}
@Override
public boolean isRetrieveData() {
return true;
}
/**
* @return the handlingPositiveStrikes
*/

View file

@ -157,7 +157,11 @@ public class MetarPrecipResource extends
@Override
protected void paintInternal(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
List<RenderablePrecipData> precips = data.get(paintProps.getDataTime());
DataTime time = paintProps.getDataTime();
if (time == null) {
return;
}
List<RenderablePrecipData> precips = getPrecipData(time);
if (precips == null) {
dataProcessJob.schedule();
return;
@ -201,6 +205,19 @@ public class MetarPrecipResource extends
target.drawStrings(strings);
}
private List<RenderablePrecipData> getPrecipData(DataTime time) {
List<RenderablePrecipData> currData = null;
synchronized (data) {
currData = data.get(time);
}
if (currData != null) {
synchronized (currData) {
return new ArrayList<RenderablePrecipData>(currData);
}
}
return null;
}
@Override
protected void initInternal(IGraphicsTarget target) throws VizException {
@ -262,7 +279,7 @@ public class MetarPrecipResource extends
Double magnification = getCapability(MagnificationCapability.class)
.getMagnification();
List<RenderablePrecipData> precips = data.get(descriptor
List<RenderablePrecipData> precips = getPrecipData(descriptor
.getTimeForResource(this));
if (precips == null || precips.isEmpty()) {
@ -299,12 +316,14 @@ public class MetarPrecipResource extends
private void processReproject() {
if (reproject) {
reproject = false;
for (List<RenderablePrecipData> dataList : data.values()) {
for (RenderablePrecipData precip : dataList) {
Coordinate latLon = precip.getLatLon();
double[] px = descriptor.worldToPixel(new double[] {
latLon.x, latLon.y });
precip.string.setCoordinates(px[0], px[1], px[2]);
synchronized (data) {
for (List<RenderablePrecipData> dataList : data.values()) {
for (RenderablePrecipData precip : dataList) {
Coordinate latLon = precip.getLatLon();
double[] px = descriptor.worldToPixel(new double[] {
latLon.x, latLon.y });
precip.string.setCoordinates(px[0], px[1], px[2]);
}
}
}
}
@ -312,10 +331,12 @@ public class MetarPrecipResource extends
}
private void processRemoves() {
while (!removes.isEmpty()) {
DataTime toRemove = removes.poll();
this.dataTimes.remove(toRemove);
this.data.remove(toRemove);
synchronized (data) {
while (!removes.isEmpty()) {
DataTime toRemove = removes.poll();
this.dataTimes.remove(toRemove);
this.data.remove(toRemove);
}
}
}
@ -354,10 +375,13 @@ public class MetarPrecipResource extends
// No need to reprocess times after the earliest update.
continue;
}
Iterator<RenderablePrecipData> iter = entry.getValue().iterator();
while (iter.hasNext()) {
if (newStations.contains(iter.next().getStationName())) {
iter.remove();
synchronized (entry.getValue()) {
Iterator<RenderablePrecipData> iter = entry.getValue()
.iterator();
while (iter.hasNext()) {
if (newStations.contains(iter.next().getStationName())) {
iter.remove();
}
}
}
addData(time, container.getBasePrecipData(time));
@ -393,6 +417,9 @@ public class MetarPrecipResource extends
}
int curIndex = frameInfo.getFrameIndex();
int count = frameInfo.getFrameCount();
if (times.length != count) {
System.out.println("Uh oh");
}
// This will generate the number series 0, -1, 1, -2, 2, -3, 3...
for (int i = 0; i < count / 2 + 1; i = i < 0 ? -i : -i - 1) {
int index = (count + curIndex + i) % count;
@ -417,27 +444,31 @@ public class MetarPrecipResource extends
}
}
}
// This will only happen if frames were removed while we were processing
// DOn't leave any half created frames
for (DataTime time : baseOnly) {
this.dataTimes.remove(time);
this.data.remove(time);
synchronized (data) {
// This will only happen if frames were removed while we were
// processing. Don't leave any half created frames
for (DataTime time : baseOnly) {
this.dataTimes.remove(time);
this.data.remove(time);
}
}
}
private void addData(DataTime time, List<PrecipData> precips) {
if (precips.isEmpty()) {
if (!dataTimes.contains(time)) {
List<RenderablePrecipData> newPrecips = Collections.emptyList();
data.put(time, newPrecips);
synchronized (data) {
List<RenderablePrecipData> newPrecips = Collections
.emptyList();
data.put(time, newPrecips);
}
dataTimes.add(time);
}
}
if (data.containsKey(time)) {
precips = new ArrayList<PrecipData>(precips);
for (RenderablePrecipData pData : data.get(time)) {
precips.add(pData);
}
precips.addAll(getPrecipData(time));
}
Collections.sort(precips, new Comparator<PrecipData>() {
@ -480,9 +511,11 @@ public class MetarPrecipResource extends
data.distValue = bestDist;
newPrecips.add(data);
}
data.put(time, newPrecips);
if (!dataTimes.contains(time)) {
dataTimes.add(time);
synchronized (data) {
data.put(time, newPrecips);
if (!dataTimes.contains(time)) {
dataTimes.add(time);
}
}
issueRefresh();
}

View file

@ -67,6 +67,16 @@ public class MetarPrecipResourceData extends AbstractRequestableResourceData {
this.duration = duration;
}
@Override
public boolean isUpdatingOnMetadataOnly() {
return true;
}
@Override
public boolean isRetrieveData() {
return false;
}
@Override
public int hashCode() {
final int prime = 31;

View file

@ -102,15 +102,17 @@ public class PointMetadataContainer extends MetadataContainer {
}
pdc = pdca.getBaseRecords(baseParams, originalConstraints);
for (PointDataLevelNode node : nodes) {
IDataRecord rec = pdc.getParameterRecord(node.getParameter());
Set<AbstractRequestableData> cacheSet = new HashSet<AbstractRequestableData>();
cacheSet.add(new PointRequestableData(rec, pdc.getDescription(
node.getParameter()).getUnitObject()));
dataCache.put(node, cacheSet);
if (!Arrays.asList("id", "latitude", "longitude", "dataURI")
.contains(rec.getName())) {
pdc.remove(rec.getName());
if (pdc != null) {
IDataRecord rec = pdc.getParameterRecord(node.getParameter());
cacheSet.add(new PointRequestableData(rec, pdc.getDescription(
node.getParameter()).getUnitObject()));
if (!Arrays.asList("id", "latitude", "longitude", "dataURI")
.contains(rec.getName())) {
pdc.remove(rec.getName());
}
}
dataCache.put(node, cacheSet);
}
}

View file

@ -54,6 +54,7 @@ import com.raytheon.uf.viz.alertviz.SystemStatusHandler;
import com.raytheon.uf.viz.alertviz.ui.dialogs.AlertVisualization;
import com.raytheon.uf.viz.application.ProgramArguments;
import com.raytheon.uf.viz.application.component.IStandaloneComponent;
import com.raytheon.uf.viz.core.RecordFactory;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.localization.CAVELocalizationNotificationObserver;
import com.raytheon.uf.viz.core.localization.LocalizationConstants;
@ -383,9 +384,15 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
protected void initializeObservers() {
// Setup cave notification observer
CAVELocalizationNotificationObserver.register();
// Register product observers
ProductAlertObserver.addObserver(null, new MenuUpdater());
ProductAlertObserver.addObserver(null, new AutoUpdater());
registerProductAlerts();
}
protected void registerProductAlerts() {
// Register product observers
ProductAlertObserver.addObserver(null, new MenuUpdater());
for (String plugin : RecordFactory.getInstance().getSupportedPlugins()) {
// Create separate AutoUpdater per plugin
ProductAlertObserver.addObserver(plugin, new AutoUpdater());
}
}
}

View file

@ -204,7 +204,7 @@ public class BundleLoader extends Job {
if (containerPanes.length != bundleDisplays.length) {
boolean success = ensureOneToOne(container, bundle);
containerPanes = container.getDisplayPanes();
if (success) {
if (success == false) {
throw new VizException("Unable to load "
+ bundleDisplays.length
+ " displays onto container with "