Change-Id: I97797a7adbd17532b261987caf2fdcaa1d39c9ed

Former-commit-id: 3c9c34c84ac1cd4962c3e6f877bd33b37aab705a
This commit is contained in:
Michael Gamazaychikov 2014-02-08 01:42:46 +00:00
parent 91c3468462
commit 42399284ca
7 changed files with 273 additions and 17 deletions

View file

@ -94,6 +94,10 @@ import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.uf.viz.core.map.MapDescriptor;
import com.raytheon.uf.viz.core.maps.MapManager;
import com.raytheon.uf.viz.core.notification.INotificationObserver;
import com.raytheon.uf.viz.core.notification.NotificationException;
import com.raytheon.uf.viz.core.notification.NotificationMessage;
import com.raytheon.uf.viz.core.notification.jobs.NotificationManagerJob;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.ResourceProperties;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
@ -196,6 +200,8 @@ import com.vividsolutions.jts.io.WKTReader;
* 10/29/2013 DR 16734 D. Friedman If redraw-from-hatched-area fails, don't allow the pollygon the be used.
* 12/17/2013 DR 16567 Qinglu Lin Added findLargestGeometry() and findLargestQuadrant(), and updated
* populateStrings() and paintText().
* 02/07/2014 DR16090 m.gamazaychikov Added GeomMetaDataUpdateNotificationObserver class to get notification
* when geometry file get updated to re-read them in.
* </pre>
*
* @author mschenke
@ -541,6 +547,56 @@ public class WarngenLayer extends AbstractStormTrackResource {
}
private static class GeomMetaDataUpdateNotificationObserver implements INotificationObserver {
private static final String SHAPEFILE_UPDATE_TOPIC = "edex.geospatialUpdate.msg";
private static GeomMetaDataUpdateNotificationObserver instance = null;
static WarngenLayer warngenLayer;
private GeomMetaDataUpdateNotificationObserver() {
}
public static synchronized GeomMetaDataUpdateNotificationObserver getInstance(WarngenLayer wl) {
if (instance == null) {
instance = new GeomMetaDataUpdateNotificationObserver();
NotificationManagerJob.addObserver(SHAPEFILE_UPDATE_TOPIC, instance);
warngenLayer = wl;
}
return instance;
}
/**
* Remove the alert message observer from the Notification Manager Job
* listener.
*/
public static synchronized void removeNotificationObserver() {
if (instance != null) {
NotificationManagerJob.removeObserver(SHAPEFILE_UPDATE_TOPIC, instance);
instance = null;
}
}
@Override
public void notificationArrived(NotificationMessage[] messages) {
for (NotificationMessage message : messages) {
try {
Object payload = message.getMessagePayload();
if (payload instanceof String ) {
System.out.println("Geometry Metadata has been updated based on " + payload + " shapefile data");
warngenLayer.siteMap.clear();
warngenLayer.init(warngenLayer.configuration);
}
} catch (NotificationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private static Map<String, GeospatialDataList> siteMap = new HashMap<String, GeospatialDataList>();
private static Map<String, Geometry> timezoneMap = new HashMap<String, Geometry>();
@ -604,6 +660,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
private WarningAction warningAction = WarningAction.NEW;
private GeomMetaDataUpdateNotificationObserver geomUpdateObserver;
static {
for (int i = 0; i < 128; i++) {
if (i % 32 == 0) {
@ -756,6 +814,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
protected void disposeInternal() {
customMaps.clearMaps();
GeomMetaDataUpdateNotificationObserver.removeNotificationObserver();
super.disposeInternal();
synchronized (WarngenLayer.class) {
@ -1051,6 +1111,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
String site = getLocalizedSite();
initializeGeomUpdateObserver();
synchronized (siteMap) {
loadGeodataForConfiguration(config);
@ -1075,6 +1137,12 @@ public class WarngenLayer extends AbstractStormTrackResource {
+ (System.currentTimeMillis() - t0) + "ms");
}
private void initializeGeomUpdateObserver() {
if (geomUpdateObserver == null) {
geomUpdateObserver= GeomMetaDataUpdateNotificationObserver.getInstance(this);
}
}
/**
* Adds geospatial data to siteMap and timezoneMap for the given template
* configuration. This must not have any site effects on the currently

View file

@ -13,6 +13,9 @@ acarssounding.cron=00+10,30,50+*+*+*+?
gfe.cron=0+15+*+*+*+?
repack.cron=0+20+*+*+*+?
# warngen geometries updater
geospatial.updater.cron=0+0+0/1+*+*+?
###purge configuration
# Interval at which the purge job kicks off
purge.cron=0+0/1+*+*+*+?

View file

@ -261,6 +261,13 @@
<bean ref="serializationUtil" method="transformToThrift" />
<to uri="jms-generic:topic:edex.alarms.msg" />
</route>
<!-- Route to send geospatial data update notification -->
<route id="geospatialUpdateNotify">
<from uri="vm:edex.geospatialUpdateNotification" />
<bean ref="serializationUtil" method="transformToThrift" />
<to uri="jms-generic:topic:edex.geospatialUpdate.msg" />
</route>
<!-- Route to periodically close any unused jms resources that have been pooled -->
<route id="jmsPooledResourceChecker">

View file

@ -20,4 +20,5 @@ Require-Bundle: org.geotools,
Export-Package: com.raytheon.edex.plugin.warning.tools
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: com.raytheon.uf.common.time,
org.apache.commons.logging,
org.hibernate.annotations

View file

@ -11,4 +11,32 @@
<!-- Instantiating class causes a thread to be run that will generate the warngen geometries -->
<bean class="com.raytheon.edex.plugin.warning.gis.GeospatialDataGeneratorThread"/>
<!--Instantiating class will update the warngen geometries-->
<bean id="geospatialDataUpdater" class="com.raytheon.edex.plugin.warning.gis.GeospatialDataUpdater" />
<camelContext id="geospatialDataUpdater-context"
xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<endpoint id="geospatialDataUpdaterCron"
uri="clusteredquartz://warning/geospatialDataUpdaterScheduled/?cron=${geospatial.updater.cron}" />
<route id="geospatialDataUpdaterScheduled">
<from uri="geospatialDataUpdaterCron" />
<to uri="jms-generic:queue:geospatialDataUpdaterScheduledWork" />
</route>
<route id="geospatialDataUpdaterScheduledWork">
<from uri="jms-generic:queue:geospatialDataUpdaterScheduledWork" />
<doTry>
<bean ref="geospatialDataUpdater" method="runCheckUpdate" />
<doCatch>
<exception>java.lang.Throwable</exception>
<to
uri="log:geospatialDataUpdater?level=ERROR" />
</doCatch>
</doTry>
</route>
</camelContext>
</beans>

View file

@ -96,6 +96,7 @@ import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
* AreaConfiguration to areaFields List.
* May 7, 2013 15690 Qinglu Lin Added convertToMultiPolygon() and updated queryGeospatialData().
* Oct 22, 2013 2361 njensen Use JAXBManager for XML
* Feb 07, 2014 16090 mgamazaychikov Changed visibility of some methods
* </pre>
*
* @author rjpeter
@ -124,12 +125,31 @@ public class GeospatialDataGenerator {
List<String> sites = getBackupSites(dialogConfig);
sites.add(0, mySite);
List<String> templates = getTemplates(dialogConfig);
Set<GeospatialMetadata> metaDataSet = getMetaDataSet(sites, templates);
for (String site : sites) {
statusHandler.handle(Priority.INFO,
"Generating warngen geometries for site: " + site);
for (GeospatialMetadata md : metaDataSet) {
try {
generateGeoSpatialList(site, md);
} catch (Exception e) {
statusHandler
.handle(Priority.ERROR,
"Failed to generate geospatial data for warngen",
e);
}
}
}
}
public static Set<GeospatialMetadata> getMetaDataSet(List<String> sites,
List<String> templates) {
Set<GeospatialMetadata> metaDataSet = new HashSet<GeospatialMetadata>();
for (String site : sites) {
metaDataSet.clear();
statusHandler.handle(Priority.INFO,
"Generating warngen geometries for site: " + site);
// get the unique geospatialMetadata sets to generate
for (String templateName : templates) {
@ -155,21 +175,10 @@ public class GeospatialDataGenerator {
metaDataSet.add(gmd);
}
}
for (GeospatialMetadata md : metaDataSet) {
try {
generateGeoSpatialList(site, md);
} catch (Exception e) {
statusHandler
.handle(Priority.ERROR,
"Failed to generate geospatial data for warngen",
e);
}
}
}
return metaDataSet;
}
private static List<String> getBackupSites(DialogConfiguration dialogConfig) {
static List<String> getBackupSites(DialogConfiguration dialogConfig) {
String[] CWAs = dialogConfig.getBackupCWAs().split(",");
List<String> rval = new ArrayList<String>(CWAs.length + 1);
for (String s : CWAs) {
@ -180,7 +189,7 @@ public class GeospatialDataGenerator {
return rval;
}
private static List<String> getTemplates(DialogConfiguration dialogConfig) {
static List<String> getTemplates(DialogConfiguration dialogConfig) {
String[] mainProducts = dialogConfig.getMainWarngenProducts()
.split(",");
String[] otherProducts = dialogConfig.getOtherWarngenProducts().split(
@ -337,7 +346,7 @@ public class GeospatialDataGenerator {
return rval;
}
private static GeospatialTime queryForCurrentTimes(
static GeospatialTime queryForCurrentTimes(
GeospatialMetadata metaData) throws Exception {
GeospatialTime rval = new GeospatialTime();
String areaSource = metaData.getAreaSource().toLowerCase();

View file

@ -0,0 +1,140 @@
package com.raytheon.edex.plugin.warning.gis;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.raytheon.edex.site.SiteUtil;
import com.raytheon.edex.util.Util;
import com.raytheon.uf.common.dataplugin.warning.config.DialogConfiguration;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialFactory;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialMetadata;
import com.raytheon.uf.common.dataplugin.warning.gis.GeospatialTime;
import com.raytheon.uf.common.geospatial.SpatialException;
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.edex.core.EDEXUtil;
import com.raytheon.uf.edex.core.EdexException;
/**
* Compares current time in the database against the time of last run
* generated geometry and if they differ regenerates the files.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 07, 2014 16090 mgamazaychikov Initial creation
* </pre>
*
* @author mgamazaychikov
* @version 1.0
*/
public class GeospatialDataUpdater {
private final static IUFStatusHandler statusHandler = UFStatus
.getHandler(GeospatialDataUpdater.class);
private static final String UPDATER_ENDPOINT = "geospatialUpdateNotify";
private static Log logger = LogFactory.getLog(Util.class);
private static Set<GeospatialMetadata> metaDataSet = null;
private static Map<GeospatialMetadata, GeospatialTime> map = null;
public static void runCheckUpdate() throws SpatialException {
StringBuilder sb = new StringBuilder();
if (metaDataSet == null){
runInit();
}
GeospatialTime curTime = null;
GeospatialTime lastRunTime = null;
boolean generate = false;
sb.append("GeospatialDataUpdater: ");
for (GeospatialMetadata md : metaDataSet) {
lastRunTime = map.get(md);
try {
curTime = GeospatialDataGenerator.queryForCurrentTimes(md);
} catch (Exception e) {
throw new SpatialException(
"Unable to look up database version times.",
e);
}
if (!curTime.equals(lastRunTime)) {
generate = true;
break;
}
else {
generate = false;
}
}
if (generate){
sb.append("Geometry database time differs from current geometry metadata time: regenerating geometries");
}
else {
return;
}
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler.info(sb.toString());
}
GeospatialDataGenerator.generateUniqueGeospatialMetadataGeometries();
String updatedTimeStamp = getTimeStamp(curTime, lastRunTime);
try {
EDEXUtil.getMessageProducer().sendAsync(UPDATER_ENDPOINT, updatedTimeStamp);
} catch (EdexException e) {
logger.error("Could not send message to alarm/alert", e);
}
metaDataSet = null;
}
private static String getTimeStamp(GeospatialTime curTime,
GeospatialTime lastRunTime) {
long tmStampMs = 0;
if (curTime.getAreaSourceTime() != lastRunTime.getAreaSourceTime()) {
tmStampMs = curTime.getAreaSourceTime();
} else if (curTime.getParentSourceTime() != lastRunTime.getParentSourceTime()) {
tmStampMs = curTime.getParentSourceTime();
} else if (curTime.getTimeZoneSourceTime() != lastRunTime.getTimeZoneSourceTime()) {
tmStampMs = curTime.getTimeZoneSourceTime();
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
calendar.setTimeInMillis(tmStampMs);
return sdf.format(calendar.getTime());
}
private static void runInit() {
String mySite = SiteUtil.getSite();
DialogConfiguration dialogConfig = null;
try {
dialogConfig = DialogConfiguration.loadDialogConfig(mySite);
} catch (Exception e) {
statusHandler.handle(Priority.ERROR,
"Error loading warngen config.xml", e);
return;
}
List<String> sites = GeospatialDataGenerator.getBackupSites(dialogConfig);
sites.add(0, mySite);
List<String> templates = GeospatialDataGenerator.getTemplates(dialogConfig);
metaDataSet = GeospatialDataGenerator.getMetaDataSet(sites, templates);
map = GeospatialFactory.loadLastRunGeoTimeSet(mySite);
StringBuilder sb = new StringBuilder();
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
sb.append("GeospatialDataUpdater has been re-inited");
statusHandler.info(sb.toString());
}
}
}