13.2.1-12 baseline

Former-commit-id: 6316b9db6cbf29e0038128763d2ad86b1b7abae8
This commit is contained in:
Steve Harris 2013-03-07 13:43:04 -05:00
parent 41dc7c0396
commit 23a41ad607
49 changed files with 1554 additions and 491 deletions

View file

@ -53,6 +53,11 @@
<dataURI>/redbook/%/PENJ88/%</dataURI>
<substitute key="wmo" value="PENJ88"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/Redbook.xml"
menuText="Mesoscale Precip Discussion" id="mesoPrecipDisc">
<dataURI>/redbook/%/PENA01/%</dataURI>
<substitute key="wmo" value="PENA01"/>
</contribute>
<contribute xsi:type="separator" id="separator1"/>
<contribute xsi:type="subMenu" menuText="Day 1-3 Prob 4+ Inches Snow">
<contribute xsi:type="bundleItem" file="bundles/Redbook.xml"

View file

@ -683,6 +683,10 @@
<key>PENJ88</key>
<value><name>Sig River Flood Outlook</name></value>
</entry>
<entry>
<key>PENA01</key>
<value><name>Mesoscale Precip Discussion</name></value>
</entry>
<entry>
<key>PEBG98</key>
<value><name>6Hr QPF - Time Proj 36-42Hrs</name></value>

View file

@ -319,4 +319,11 @@
version="0.0.0"
unpack="false"/>
<plugin
id="com.raytheon.uf.common.python.concurrent"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>

View file

@ -271,6 +271,7 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
*
* @return
*/
@Override
@Deprecated
public DataTime[] getFrames() {
return getFramesInfo().frameTimes;
@ -446,6 +447,7 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
/**
* @return the timeMatcher
*/
@Override
@XmlElement
public AbstractTimeMatcher getTimeMatcher() {
return timeManager.timeMatcher;
@ -455,6 +457,7 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
* @param timeMatcher
* the timeMatcher to set
*/
@Override
public void setTimeMatcher(AbstractTimeMatcher timeMatcher) {
this.timeManager.timeMatcher = timeMatcher;
}
@ -477,6 +480,7 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
return currInfo.getTimeForResource(rsc);
}
@Override
public void synchronizeTimeMatching(IDescriptor other) {
if (other instanceof AbstractDescriptor) {
timeManager = ((AbstractDescriptor) other).timeManager;
@ -577,6 +581,8 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
return;
}
}
DataTime oldTime, currTime;
boolean frameChanged = false;
synchronized (timeManager) {
DataTime[] oldTimes = timeManager.frames;
int oldIdx = this.frameIndex;
@ -598,13 +604,16 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
}
FramesInfo currInfo = getFramesInfo();
FramesInfo oldInfo = new FramesInfo(oldTimes, oldIdx);
DataTime oldTime = oldInfo.getCurrentFrame();
DataTime currTime = currInfo.getCurrentFrame();
oldTime = oldInfo.getCurrentFrame();
currTime = currInfo.getCurrentFrame();
if ((oldTime != null && oldTime.equals(currTime) == false)
|| (currTime != null && currTime.equals(oldTime) == false)) {
notifyFrameChanged(oldTime, currTime);
frameChanged = true;
}
}
if (frameChanged) {
notifyFrameChanged(oldTime, currTime);
}
}
@Override

View file

@ -2,7 +2,7 @@
<DerivedParameter unit="m/s" name="Wind Gust" abbreviation="Gust" xmlns:ns2="group">
<Method name="Vector" levels="Surface" models="obs">
<Field level="Station" abbreviation="windGust"/>
<Field abbreviation="WD"/>
<Field abbreviation="WD" unit="deg"/>
<ConstantField value="1.0"/>
</Method>
<Method name="Vector">
@ -11,12 +11,12 @@
</Method>
<Method name="Vector">
<Field abbreviation="WGS" unit="m/s"/>
<Field abbreviation="WGD"/>
<Field abbreviation="WGD" unit="deg"/>
<ConstantField value="1.0"/>
</Method>
<Method name="Vector">
<Field abbreviation="WGS" unit="m/s"/>
<Field abbreviation="WD"/>
<Field abbreviation="WD" unit="deg"/>
<ConstantField value="1.0"/>
</Method>
<Method name="Vector">

View file

@ -21,7 +21,7 @@
<DerivedParameter name="Swell Direction" abbreviation="SWdir" xmlns:ns2="group">
<Method name="Vector">
<ConstantField value="20"/>
<Field abbreviation="SWDIR"/>
<Field abbreviation="SWDIR" unit="deg"/>
<ConstantField value="1"/>
</Method>
</DerivedParameter>

View file

@ -2,7 +2,7 @@
<DerivedParameter name="Wind Wave Direction" abbreviation="WVdir" xmlns:ns2="group">
<Method name="Vector">
<ConstantField value="20"/>
<Field abbreviation="WVDIR"/>
<Field abbreviation="WVDIR" unit="deg"/>
<ConstantField value="1"/>
</Method>
</DerivedParameter>

View file

@ -28,7 +28,7 @@
</Method>
<Method name="Vector">
<Field abbreviation="wSp"/>
<Field abbreviation="WD"/>
<Field abbreviation="WD" unit="deg"/>
<ConstantField value="1.0"/>
</Method>
<!-- TODO this should be an auto-generated average however

View file

@ -25,7 +25,7 @@
</Method>
<Method name="Vector">
<Field abbreviation="WSmean" unit="kts"/>
<Field abbreviation="WDmean" unit="kts"/>
<Field abbreviation="WDmean" unit="deg"/>
<ConstantField value="1.0"/>
</Method>
</DerivedParameter>

View file

@ -2,7 +2,7 @@
<DerivedParameter name="Primary Wave Direction" abbreviation="dirPW" xmlns:ns2="group">
<Method name="Vector">
<ConstantField value="20"/>
<Field abbreviation="DIRPW"/>
<Field abbreviation="DIRPW" unit="deg"/>
<ConstantField value="1"/>
</Method>
</DerivedParameter>

View file

@ -2,7 +2,7 @@
<DerivedParameter name="Secondary Wave Direction" abbreviation="dirSW" xmlns:ns2="group">
<Method name="Vector">
<ConstantField value="20"/>
<Field abbreviation="DIRSW"/>
<Field abbreviation="DIRSW" unit="deg"/>
<ConstantField value="1"/>
</Method>
</DerivedParameter>

View file

@ -12,11 +12,11 @@ import java.util.Set;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.eclipse.core.runtime.Platform;
/**
*
@ -33,6 +33,7 @@ import org.eclipse.core.runtime.Platform;
* Oct 12, 2010 mschenke Initial creation
* Jan 24, 2013 1522 bkowal Halt initialization if a p2 installation
* has been started
* Mar 05, 2013 1754 djohnson Catch exceptions and allow as much of the Spring container to boot as possible.
*
* </pre>
*
@ -64,7 +65,8 @@ public class Activator implements BundleActivator {
* @see
* org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
@Override
public void start(BundleContext context) throws Exception {
if (this.isInstallOperation()) {
return;
}
@ -137,16 +139,27 @@ public class Activator implements BundleActivator {
}
}
if (parentContexts.size() > 0) {
// Context with parent context
appCtx = new OSGIXmlApplicationContext(
new OSGIGroupApplicationContext(parentContexts),
files.toArray(new String[0]), bundle);
} else {
// No parent context required
appCtx = new OSGIXmlApplicationContext(
files.toArray(new String[0]), bundle);
}
try {
if (parentContexts.size() > 0) {
// Context with parent context
appCtx = new OSGIXmlApplicationContext(
new OSGIGroupApplicationContext(
parentContexts),
files.toArray(new String[0]), bundle);
} else {
// No parent context required
appCtx = new OSGIXmlApplicationContext(
files.toArray(new String[0]), bundle);
}
} catch (Throwable t) {
// No access to the statusHandler yet, so print the
// stack trace to the console. By catching this, we also
// allow as many beans as possible to continue to be
// created
System.err
.println("Errors booting the Spring container. CAVE will not be fully functional.");
t.printStackTrace();
}
}
}
contextMap.put(bundleName, appCtx);
@ -161,7 +174,8 @@ public class Activator implements BundleActivator {
* @see
* org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
@Override
public void stop(BundleContext context) throws Exception {
plugin = null;
}

View file

@ -65,6 +65,7 @@ import com.raytheon.viz.ui.input.EditableManager;
* that it can be stored in the
* StormTrackState.
* 02-12-2013 1600 jsanchez Changed the visibility of the method adjustAngle
* 03-05-2013 1600 jsanchez Returned the visibility of the method adjustAngle to protected.
* </pre>
*
* @author mschenke
@ -264,12 +265,12 @@ public abstract class AbstractStormTrackResource extends
}
/**
* Adjusts the angle from -360/360 to be between -180/180
* Adjusts the angle to be within the range -180 to +180 degrees.
*
* @param angle
* @return
*/
public static double adjustAngle(double angle) {
protected double adjustAngle(double angle) {
double newVal = angle % 360;
if (newVal > 180) {
newVal -= 360;

View file

@ -28,7 +28,8 @@ Require-Bundle: org.eclipse.ui,
org.apache.commons.logging,
com.raytheon.uf.viz.application;bundle-version="1.0.0",
com.raytheon.viz.ui.personalities.awips;bundle-version="1.12.1174",
com.raytheon.uf.common.auth;bundle-version="1.12.1174"
com.raytheon.uf.common.auth;bundle-version="1.12.1174",
com.raytheon.uf.common.python;bundle-version="1.12.1174"
Bundle-ActivationPolicy: lazy
Export-Package: com.raytheon.viz.gfe,
com.raytheon.viz.gfe.constants,
@ -55,7 +56,7 @@ Import-Package: com.raytheon.edex.meteoLib,
com.raytheon.uf.common.colormap,
com.raytheon.uf.common.dissemination,
com.raytheon.uf.common.message,
com.raytheon.uf.common.python,
com.raytheon.uf.common.python.concurrent,
com.raytheon.uf.common.serialization.comm,
com.raytheon.uf.viz.python.swt,
com.raytheon.uf.viz.python.swt.widgets,

View file

@ -57,6 +57,7 @@ import com.raytheon.viz.gfe.rsc.GFEResource;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 14, 2012 mschenke Initial creation
* Feb 26, 2013 #1708 randerso Fixed double notification for time change
*
* </pre>
*
@ -162,6 +163,9 @@ public class GFETimeMatcher extends AbstractTimeMatcher {
FramesInfo currInfo = descriptor.getFramesInfo();
int currIdx = currInfo.getFrameIndex();
DataTime currTime = currInfo.getCurrentFrame();
if (selectedDate != null) {
currTime = new DataTime(selectedDate);
}
// Create descriptor times, for each resource, time match against them
DataTime[] descriptorTimes = calculateDescriptorTimes(descriptor,

View file

@ -32,13 +32,15 @@ import com.raytheon.viz.gfe.core.msgs.IReferenceSetIDChangedListener;
import com.raytheon.viz.gfe.core.msgs.IReferenceSetInvChangedListener;
/**
* TODO Add Description
* Public interface for ReferenceSetManager
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 2, 2008 randerso Initial creation
* 02/14/2013 #1506 mnash Move away from using QueryScript on the UI thread
* 02/26/2013 #1708 randerso Remove evaluateRefSet from public interface
*
* </pre>
*
@ -210,6 +212,7 @@ public interface IReferenceSetManager {
*/
public abstract Grid2DBit mySiteGridpoints();
@Override
public abstract String toString();
/**
@ -306,13 +309,6 @@ public interface IReferenceSetManager {
public void deleteGroup(String groupName);
/**
* Force the active ref set to be re-evalutated
*
* @return the active refersence set
*/
public ReferenceData evaluateActiveRefSet();
/**
* Dispose of this instance
*/

View file

@ -37,8 +37,6 @@ import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import jep.JepException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
@ -65,6 +63,10 @@ import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.LocalizationUtil;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.python.concurrent.AbstractPythonScriptFactory;
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
import com.raytheon.uf.common.python.concurrent.IPythonJobListener;
import com.raytheon.uf.common.python.concurrent.PythonJobCoordinator;
import com.raytheon.uf.common.serialization.SerializationUtil;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
@ -82,8 +84,10 @@ import com.raytheon.viz.gfe.core.msgs.IReferenceSetInvChangedListener;
import com.raytheon.viz.gfe.core.msgs.ISpatialEditorTimeChangedListener;
import com.raytheon.viz.gfe.core.msgs.Message;
import com.raytheon.viz.gfe.core.msgs.Message.IMessageClient;
import com.raytheon.viz.gfe.query.QueryFactory;
import com.raytheon.viz.gfe.query.QueryScript;
import com.raytheon.viz.gfe.query.QueryScriptExecutor;
import com.raytheon.viz.gfe.query.QueryScriptFactory;
import com.raytheon.viz.gfe.query.QueryScriptRecurseExecutor;
import com.raytheon.viz.gfe.ui.AccessMgr;
import com.vividsolutions.jts.geom.Envelope;
@ -100,6 +104,9 @@ import com.vividsolutions.jts.geom.Envelope;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 1, 2008 #1053 randerso Initial creation
* 02/14/2013 #1506 mnash Move QueryScript to use new Python concurrency implementation
* 02/12/2013 #1597 randerso Improved error message for exceptions evaluating queries
* 02/26/2013 #1708 randerso Removed no longer needed near duplicate methods
*
* </pre>
*
@ -177,6 +184,8 @@ public class ReferenceSetManager implements IReferenceSetManager,
private final ArrayList<String> historyStack;
private PythonJobCoordinator<QueryScript> coordinator;
/**
* Set the wait cursor on or off
*
@ -558,6 +567,11 @@ public class ReferenceSetManager implements IReferenceSetManager,
*/
@SuppressWarnings("unchecked")
public ReferenceSetManager(DataManager dataManager) {
// ready the PythonJobCoordinator
AbstractPythonScriptFactory<QueryScript> factory = new QueryScriptFactory(
dataManager);
coordinator = PythonJobCoordinator.newInstance(factory);
// MessageClient("ReferenceSetMgr", msgHandler);
this.dataManager = dataManager;
@ -674,8 +688,8 @@ public class ReferenceSetManager implements IReferenceSetManager,
public void setActiveRefSet(final ReferenceData refData) {
refData.getGrid(); // force it to a grid
statusHandler.handle(Priority.VERBOSE, "PrevActiveSet = "
+ activeRefSet.getId());
// statusHandler.handle(Priority.VERBOSE, "PrevActiveSet = "
// + activeRefSet.getId());
// turn on wait cursor
setCursor(0);
@ -700,8 +714,8 @@ public class ReferenceSetManager implements IReferenceSetManager,
// turn off wait cursor
setCursor(1);
statusHandler.handle(Priority.VERBOSE,
"NewActiveSet = " + activeRefSet.getId());
// statusHandler.handle(Priority.VERBOSE,
// "NewActiveSet = " + activeRefSet.getId());
}
/*
@ -762,8 +776,8 @@ public class ReferenceSetManager implements IReferenceSetManager,
if (lf != null) {
try {
refData = (ReferenceData) SerializationUtil
.jaxbUnmarshalFromXmlFile(lf.getFile().getPath());
refData = SerializationUtil.jaxbUnmarshalFromXmlFile(
ReferenceData.class, lf.getFile().getPath());
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
"Error reading xml file "
@ -1306,22 +1320,30 @@ public class ReferenceSetManager implements IReferenceSetManager,
* com.raytheon.viz.gfe.core.IReferenceSetManager.RefSetMode)
*/
@Override
public void incomingRefSet(ReferenceData refData, RefSetMode mode) {
public void incomingRefSet(ReferenceData refData, final RefSetMode mode) {
// Evaluate the Incoming refData if necessary
// Then, change the active Reference Set using the given mode.
ReferenceData ref = null;
if (refData.isQuery()) {
String query = refData.getQuery();
try {
ref = evaluateQuery(query);
ref.setQuery(query);
} catch (JepException e) {
return;
final String query = refData.getQuery();
IPythonJobListener<ReferenceData> listener = new IPythonJobListener<ReferenceData>() {
@Override
public void jobFailed(Throwable e) {
statusHandler.handle(Priority.PROBLEM,
"Unable to run QueryScript job", e);
}
@Override
public void jobFinished(ReferenceData result) {
result.setQuery(query);
setRefSet(result, mode);
}
};
evaluateQuery(query, listener);
} else {
ref = refData;
setRefSet(ref, mode);
}
setRefSet(ref, mode);
}
/**
@ -1699,48 +1721,50 @@ public class ReferenceSetManager implements IReferenceSetManager,
sendEditAreaGroupInvChanged();
}
private ReferenceData evaluateQuery(String query) throws JepException {
QueryScript script = QueryFactory.getCachedScript(dataManager);
HashMap<String, Object> argMap = new HashMap<String, Object>();
private void evaluateQuery(String query,
IPythonJobListener<ReferenceData> listener) {
Map<String, Object> argMap = new HashMap<String, Object>();
argMap.put("expression", query);
ReferenceData newRef = (ReferenceData) script.execute("evaluate",
argMap);
return newRef;
IPythonExecutor<QueryScript, ReferenceData> executor = new QueryScriptExecutor(
"evaluate", argMap);
try {
coordinator.submitAsyncJob(executor, listener);
} catch (Exception e) {
statusHandler.handle(Priority.ERROR,
"Unable to submit job to ExecutorService", e);
}
}
@Override
public boolean willRecurse(String name, String query) {
Map<String, Object> argMap = new HashMap<String, Object>();
argMap.put("name", name);
argMap.put("str", query);
IPythonExecutor<QueryScript, Integer> executor = new QueryScriptRecurseExecutor(
argMap);
int result = 0;
try {
QueryScript script = QueryFactory.getCachedScript(dataManager);
HashMap<String, Object> argMap = new HashMap<String, Object>();
argMap.put("name", name);
argMap.put("str", query);
int result = (Integer) script.execute("willRecurse", argMap);
return result != 0;
} catch (JepException e) {
statusHandler.handle(Priority.PROBLEM, "", e);
result = coordinator.submitSyncJob(executor);
} catch (Exception e) {
statusHandler.handle(Priority.ERROR,
"Unable to submit job to ExecutorService", e);
return true;
}
return true;
return result != 0;
}
@Override
public ReferenceData evaluateActiveRefSet() {
// If activeRefSet is a query, re-evaluate it
private void evaluateActiveRefSet(IPythonJobListener<ReferenceData> listener) {
ReferenceData active = getActiveRefSet();
if (active.isQuery()) {
// Re-evaluate the activeRefSet
try {
ReferenceData newRef = evaluateQuery(active.getQuery());
if (!newRef.getGrid().equals(active.getGrid())) {
setActiveRefSet(newRef);
}
} catch (JepException e) {
statusHandler.handle(Priority.PROBLEM,
"Error evaluating query", e);
}
evaluateQuery(active.getQuery(), listener);
} else {
// if non-query,need to fire, but do this in an else otherwise we
// will fire the listener twice for queries
listener.jobFinished(getActiveRefSet());
}
return getActiveRefSet();
}
/*
@ -1752,20 +1776,28 @@ public class ReferenceSetManager implements IReferenceSetManager,
*/
@Override
public void receiveMessage(final Message message) {
VizApp.runAsync(new Runnable() {
IPythonJobListener<ReferenceData> listener = new IPythonJobListener<ReferenceData>() {
@Override
public void run() {
GridDataChangedMsg msg = (GridDataChangedMsg) message;
Date spedTime = dataManager.getSpatialDisplayManager()
.getSpatialEditorTime();
if (spedTime != null && msg.getTimeRange().contains(spedTime)) {
evaluateActiveRefSet();
}
public void jobFailed(Throwable e) {
statusHandler.handle(Priority.ERROR,
"Unable to finish QueryScript job", e);
}
});
@Override
public void jobFinished(ReferenceData result) {
getActiveRefSet();
if (!result.getGrid().equals(getActiveRefSet().getGrid())) {
setActiveRefSet(result);
}
};
};
GridDataChangedMsg msg = (GridDataChangedMsg) message;
Date spedTime = dataManager.getSpatialDisplayManager()
.getSpatialEditorTime();
if (spedTime != null && msg.getTimeRange().contains(spedTime)) {
evaluateActiveRefSet(listener);
}
}
@Override
@ -1798,6 +1830,20 @@ public class ReferenceSetManager implements IReferenceSetManager,
*/
@Override
public void spatialEditorTimeChanged(Date date) {
evaluateActiveRefSet();
IPythonJobListener<ReferenceData> listener = new IPythonJobListener<ReferenceData>() {
@Override
public void jobFailed(Throwable e) {
statusHandler.handle(Priority.PROBLEM,
"Unable to run QueryScript job", e);
}
@Override
public void jobFinished(ReferenceData result) {
if (!result.getGrid().equals(activeRefSet.getGrid())) {
setActiveRefSet(result);
}
}
};
evaluateActiveRefSet(listener);
}
}

View file

@ -25,10 +25,9 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import jep.JepException;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuAdapter;
@ -55,12 +54,17 @@ import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData;
import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData.CoordinateType;
import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData.RefType;
import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceID;
import com.raytheon.uf.common.python.concurrent.AbstractPythonScriptFactory;
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
import com.raytheon.uf.common.python.concurrent.IPythonJobListener;
import com.raytheon.uf.common.python.concurrent.PythonJobCoordinator;
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.viz.core.VizApp;
import com.raytheon.viz.gfe.Activator;
import com.raytheon.viz.gfe.core.DataManager;
import com.raytheon.viz.gfe.core.DataManagerUIFactory;
import com.raytheon.viz.gfe.core.IParmManager;
import com.raytheon.viz.gfe.core.IReferenceSetManager;
import com.raytheon.viz.gfe.core.IReferenceSetManager.RefSetMode;
@ -74,8 +78,9 @@ import com.raytheon.viz.gfe.core.wxvalue.DiscreteWxValue;
import com.raytheon.viz.gfe.core.wxvalue.VectorWxValue;
import com.raytheon.viz.gfe.core.wxvalue.WeatherWxValue;
import com.raytheon.viz.gfe.core.wxvalue.WxValue;
import com.raytheon.viz.gfe.query.QueryFactory;
import com.raytheon.viz.gfe.query.QueryScript;
import com.raytheon.viz.gfe.query.QueryScriptExecutor;
import com.raytheon.viz.gfe.query.QueryScriptFactory;
import com.raytheon.viz.ui.dialogs.CaveJFACEDialog;
import com.raytheon.viz.ui.dialogs.ICloseCallback;
import com.raytheon.viz.ui.widgets.ToggleSelectList;
@ -96,7 +101,8 @@ import com.vividsolutions.jts.geom.MultiPolygon;
* Oct 24, 2012 1287 rferrel Changes for non-blocking SaveDeleteEditAreaGroupDialog.
* Oct 31, 2012 1298 rferrel Changes for non-blocking MaskDialog.
* Changes for non-blocking WeatherDialog.
* Changes for non-blocking DiscreteDialog.
* Changes for non-blocking DiscreteDialog.
* 2/14/2013 mnash Move QueryScript to use new Python concurrency implementation
*
* </pre>
*
@ -173,6 +179,7 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements
* Modal dialog from the menu so only one can be open at a time.
*/
private CaveJFACEDialog menuModalDlg;
private SaveDeleteEditAreaGroupDialog deleteGroupDlg;
private SaveDeleteEditAreaGroupDialog saveGroupDlg;
@ -842,23 +849,44 @@ public class DefineRefSetDialog extends CaveJFACEDialog implements
}
private void submit() {
try {
String s = this.queryField.getText().trim();
QueryScript script = QueryFactory.getCachedScript(DataManager
.getCurrentInstance());
HashMap<String, Object> argMap = new HashMap<String, Object>();
argMap.put("expression", s);
ReferenceData newRef = (ReferenceData) script.execute("evaluate",
argMap);
final String s = this.queryField.getText().trim();
AbstractPythonScriptFactory<QueryScript> factory = new QueryScriptFactory(
DataManagerUIFactory.getCurrentInstance());
PythonJobCoordinator coordinator = PythonJobCoordinator
.newInstance(factory);
Map<String, Object> argMap = new HashMap<String, Object>();
argMap.put("expression", s);
IPythonExecutor<QueryScript, ReferenceData> executor = new QueryScriptExecutor(
"evaluate", argMap);
this.activeDisplay.setText(s);
this.refSetMgr.incomingRefSet(newRef, RefSetMode.USE_CURRENT);
addToHistory(s);
this.queryField.setText("");
} catch (JepException e) {
String errorMsg = e.getMessage();
IPythonJobListener<ReferenceData> listener = new IPythonJobListener<ReferenceData>() {
@Override
public void jobFailed(Throwable e) {
statusHandler.handle(Priority.PROBLEM,
"Unable to finish QueryScript :" + e.getMessage(), e);
}
@Override
public void jobFinished(final ReferenceData result) {
VizApp.runAsync(new Runnable() {
@Override
public void run() {
if (result != null) {
activeDisplay.setText(s);
refSetMgr.incomingRefSet(result,
RefSetMode.USE_CURRENT);
addToHistory(s);
queryField.setText("");
}
};
});
}
};
try {
coordinator.submitAsyncJob(executor, listener);
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
"Syntax error in query string '" + errorMsg + "'", e);
"Unable to submit job to ExecutorService", e);
}
}

View file

@ -1,91 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.gfe.query;
import java.io.File;
import jep.JepException;
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.python.PyUtil;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.viz.gfe.core.DataManager;
/**
* Builds a QueryScript instance
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 10, 2008 njensen Initial creation
*
* </pre>
*
* @author njensen
* @version 1.0
*/
public class QueryFactory {
private static final String FILEDIR = FileUtil.join("gfe", "query");
private static final String FILENAME = "Evaluator.py";
private static QueryScript cachedScript;
/**
* Builds a query script
*
* @param dm
* the data manager for the script
* @return an initialized script object
* @throws JepException
*/
public static QueryScript buildQueryScript(DataManager dm)
throws JepException {
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext ctx = pathMgr.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.BASE);
File file = pathMgr.getFile(ctx, FileUtil.join(FILEDIR, FILENAME));
File includeDir = pathMgr.getFile(ctx, FILEDIR);
return new QueryScript(file.getPath(), PyUtil.buildJepIncludePath(
includeDir.getPath(),
GfePyIncludeUtil.getCommonGfeIncludePath()),
QueryScript.class.getClassLoader(), dm);
}
public static QueryScript getCachedScript(DataManager dm)
throws JepException {
if (cachedScript == null) {
cachedScript = buildQueryScript(dm);
}
return cachedScript;
}
}

View file

@ -19,11 +19,20 @@
**/
package com.raytheon.viz.gfe.query;
import java.io.File;
import java.util.Map;
import jep.JepException;
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.python.PyUtil;
import com.raytheon.uf.common.python.PythonScript;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.viz.gfe.core.DataManager;
/**
@ -33,7 +42,8 @@ import com.raytheon.viz.gfe.core.DataManager;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 9, 2008 njensen Initial creation
* Jul 9, 2008 njensen Initial creation
* 2/14/2013 mnash Add QueryScript instantiation logic
*
* </pre>
*
@ -47,13 +57,38 @@ public class QueryScript extends PythonScript {
private DataManager dataMgr;
protected QueryScript(String filePath, String anIncludePath,
ClassLoader classLoader, DataManager aDataMgr) throws JepException {
super(filePath, anIncludePath, classLoader);
dataMgr = aDataMgr;
private static final String FILEDIR = FileUtil.join("gfe", "query");
private static final String FILENAME = "Evaluator.py";
public QueryScript(DataManager dm) throws JepException {
super(buildFilePath(), buildIncludePath(), QueryScript.class
.getClassLoader());
dataMgr = dm;
init();
}
private static String buildFilePath() {
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext ctx = pathMgr.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.BASE);
File file = pathMgr.getFile(ctx, FileUtil.join(FILEDIR, FILENAME));
return file.getPath();
}
private static String buildIncludePath() {
IPathManager pathMgr = PathManagerFactory.getPathManager();
LocalizationContext ctx = pathMgr.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.BASE);
File includeDir = pathMgr.getFile(ctx, FILEDIR);
return PyUtil.buildJepIncludePath(includeDir.getPath(),
GfePyIncludeUtil.getCommonGfeIncludePath());
}
private void init() throws JepException {
jep.set("dataMgr", dataMgr);
jep.eval(INSTANCE + " = Evaluator(dataMgr)");

View file

@ -0,0 +1,85 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.gfe.query;
import java.util.Map;
import jep.JepException;
import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData;
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
/**
* {@link IPythonExecutor} class for {@link QueryScript} that runs an execute
* method in the script using the ExecutorService
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 7, 2013 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class QueryScriptExecutor implements
IPythonExecutor<QueryScript, ReferenceData> {
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(QueryScriptExecutor.class);
private String methodName;
private Map<String, Object> args;
/**
*
*/
public QueryScriptExecutor(String methodName, Map<String, Object> args) {
this.methodName = methodName;
this.args = args;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.python.concurrent.IPythonExecutor#execute(com.
* raytheon.uf.common.python.PythonInterpreter)
*/
@Override
public ReferenceData execute(QueryScript script) {
ReferenceData retVal = null;
try {
retVal = (ReferenceData) script.execute(methodName, args);
} catch (JepException e) {
statusHandler.handle(Priority.ERROR,
"Error evaluating edit area query: " + e.getMessage(), e);
}
return retVal;
}
}

View file

@ -0,0 +1,87 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.gfe.query;
import jep.JepException;
import com.raytheon.uf.common.python.concurrent.AbstractPythonScriptFactory;
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.viz.gfe.core.DataManager;
/**
* Instantiates a {@link QueryScript} on a separate thread.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 7, 2013 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class QueryScriptFactory extends
AbstractPythonScriptFactory<QueryScript> {
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(QueryScriptFactory.class);
private DataManager manager;
/**
*
*/
public QueryScriptFactory(DataManager dataMgr) {
this("gfequeryscript", 1);
this.manager = dataMgr;
}
/**
* @param name
* @param maxThreads
*/
public QueryScriptFactory(String name, int maxThreads) {
super(name, maxThreads);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.python.concurrent.AbstractPythonScriptFactory#
* createPythonScript()
*/
@Override
public QueryScript createPythonScript() {
try {
return new QueryScript(manager);
} catch (JepException e) {
statusHandler.handle(Priority.ERROR,
"Unable to create query script", e);
}
return null;
}
}

View file

@ -0,0 +1,82 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.gfe.query;
import java.util.Map;
import jep.JepException;
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
/**
* Calls the willRecurse method for QueryScript and returns the correct type
*
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 14, 2013 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class QueryScriptRecurseExecutor implements
IPythonExecutor<QueryScript, Integer> {
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(QueryScriptRecurseExecutor.class);
private Map<String, Object> args;
/**
*
*/
public QueryScriptRecurseExecutor(Map<String, Object> args) {
this.args = args;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.python.concurrent.IPythonExecutor#execute(com.
* raytheon.uf.common.python.PythonInterpreter)
*/
@Override
public Integer execute(QueryScript script) {
Integer retVal = null;
try {
retVal = (Integer) script.execute("willRecurse", args);
} catch (JepException e) {
statusHandler.handle(Priority.PROBLEM, "Unable to execute script",
e);
}
return retVal;
}
}

View file

@ -60,6 +60,8 @@ import com.vividsolutions.jts.geom.MultiPolygon;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 27, 2008 #1053 randerso Initial creation
* 02/14/2013 #1506 mnash Use the new Python concurrency for QueryScript
* 02/26/2013 #1708 randerso Changed to not evaluate the ref set
*
* </pre>
*
@ -149,13 +151,14 @@ public class GFEReferenceSetResource extends
outlineShape = target.createWireframeShape(false, this.descriptor);
shadedShape = target.createShadedShape(false, this.descriptor, true);
shadedShape = target.createShadedShape(false,
this.descriptor.getGridGeometry(), true);
JTSCompiler jtsCompiler = new JTSCompiler(shadedShape, outlineShape,
this.descriptor);
this.needsUpdate = false;
ReferenceData refData = this.refSetMgr.evaluateActiveRefSet();
ReferenceData refData = this.refSetMgr.getActiveRefSet();
refData.setGrid(refData.getGrid());

View file

@ -158,8 +158,9 @@ import com.vividsolutions.jts.geom.Envelope;
* 03/01/2008 chammack Initial Creation.
* Aug 20, 2008 dglazesk Update for the ColorMap interface change
* Nov 23, 2011 mli set vector lineStyle
* May 11, 2012 njensen Allow rsc to be recycled
* May 11, 2012 njensen Allow rsc to be recycled
* Nov 08, 2012 1298 rferrel Changes for non-blocking FuzzValueDialog.
* Mar 04, 2013 1637 randerso Fix time matching for ISC grids
*
* </pre>
*
@ -455,7 +456,14 @@ public class GFEResource extends
PaintProperties paintProps) throws VizException {
GFEPaintProperties myPaintProps = (GFEPaintProperties) paintProps;
this.curTime = myPaintProps.getDataTime();
// TODO: Time matching changes for Hazard Services broke display of ISC
// grids when in ISC mode with no Fcst grid present. This fixes the
// issue for now but will need to be resolved for Hazard Services
// this.curTime = myPaintProps.getDataTime();
this.curTime = new DataTime(this.dataManager.getSpatialDisplayManager()
.getSpatialEditorTime());
if (curTime == null) {
return;
@ -585,8 +593,9 @@ public class GFEResource extends
if (dataManager.getParmManager().iscMode() || iscParm) {
vectorSlice = new VectorGridSlice();
mask = dataManager.getIscDataAccess().getCompositeGrid(
new GridID(this.parm, this.curTime
.getValidPeriod().getStart()), true,
new GridID(this.parm, this.dataManager
.getSpatialDisplayManager()
.getSpatialEditorTime()), true,
vectorSlice);
}
@ -655,8 +664,9 @@ public class GFEResource extends
if (dataManager.getParmManager().iscMode() || iscParm) {
scalarSlice = new ScalarGridSlice();
mask = dataManager.getIscDataAccess().getCompositeGrid(
new GridID(this.parm, this.curTime
.getValidPeriod().getStart()), true,
new GridID(this.parm, this.dataManager
.getSpatialDisplayManager()
.getSpatialEditorTime()), true,
scalarSlice);
}
@ -701,8 +711,9 @@ public class GFEResource extends
if (dataManager.getParmManager().iscMode() || iscParm) {
slice = new DiscreteGridSlice();
GridID gid = new GridID(parm, this.curTime
.getValidPeriod().getStart());
GridID gid = new GridID(parm, this.dataManager
.getSpatialDisplayManager()
.getSpatialEditorTime());
mask = dataManager.getIscDataAccess().getCompositeGrid(
gid, true, slice);
}
@ -784,8 +795,9 @@ public class GFEResource extends
if (dataManager.getParmManager().iscMode() || iscParm) {
slice = new WeatherGridSlice();
GridID gid = new GridID(parm, this.curTime
.getValidPeriod().getStart());
GridID gid = new GridID(parm, this.dataManager
.getSpatialDisplayManager()
.getSpatialEditorTime());
mask = dataManager.getIscDataAccess().getCompositeGrid(
gid, true, slice);
}

View file

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jep.JepException;
@ -33,22 +34,26 @@ import org.eclipse.swt.widgets.Display;
import com.raytheon.uf.common.dataplugin.gfe.GridDataHistory;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridParmInfo;
import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData;
import com.raytheon.uf.common.python.concurrent.AbstractPythonScriptFactory;
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
import com.raytheon.uf.common.python.concurrent.PythonJobCoordinator;
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.TimeRange;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.gfe.GFEOperationFailedException;
import com.raytheon.viz.gfe.core.DataManager;
import com.raytheon.viz.gfe.core.DataManagerUIFactory;
import com.raytheon.viz.gfe.core.IParmManager;
import com.raytheon.viz.gfe.core.griddata.IGridData;
import com.raytheon.viz.gfe.core.msgs.Message;
import com.raytheon.viz.gfe.core.msgs.MissingDataModeMsg;
import com.raytheon.viz.gfe.core.parm.Parm;
import com.raytheon.viz.gfe.core.parm.ParmState;
import com.raytheon.viz.gfe.query.QueryFactory;
import com.raytheon.viz.gfe.query.QueryScript;
import com.raytheon.viz.gfe.query.QueryScriptExecutor;
import com.raytheon.viz.gfe.query.QueryScriptFactory;
import com.raytheon.viz.gfe.smarttool.SmartToolException.ErrorType;
import com.raytheon.viz.gfe.smarttool.script.SmartToolController;
@ -60,6 +65,8 @@ import com.raytheon.viz.gfe.smarttool.script.SmartToolController;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 27, 2007 njensen Initial creation
* Jan 08, 2013 1486 dgilling Support changes to BaseGfePyController.
* 2/14/2013 1506 mnash Change QueryScript to use new Python concurrency
*
* </pre>
*
@ -91,6 +98,8 @@ public class Tool {
*/
private ReferenceData trueEditArea;
private PythonJobCoordinator coordinator = null;
/**
* Constructor
*
@ -111,6 +120,9 @@ public class Tool {
toolName = aToolName;
tool = aTool;
AbstractPythonScriptFactory<QueryScript> factory = new QueryScriptFactory(
DataManagerUIFactory.getCurrentInstance());
coordinator = PythonJobCoordinator.newInstance(factory);
try {
if (!tool.isInstantiated(toolName)) {
tool.instantiatePythonTool(toolName);
@ -441,8 +453,9 @@ public class Tool {
// # PreProcess Tool
handlePreAndPostProcess("preProcessTool", null, timeRange,
editArea, dataMode);
statusHandler.handle(Priority.DEBUG, "Running smartTool: " + toolName);
statusHandler.handle(Priority.DEBUG, "Running smartTool: "
+ toolName);
// Iterate over time range
// Process each grid in the time range.
int numberOfGrids = grids.length;
@ -485,33 +498,21 @@ public class Tool {
// Re-evaluate edit area if a query
if (editArea.isQuery()) {
// have to use runSync here to force the QueryScript to
// execute on the proper thread for JEP
if (Display.getDefault().isDisposed() == false) {
VizApp.runSync(new Runnable() {
@Override
public void run() {
QueryScript script;
try {
script = QueryFactory
.getCachedScript(DataManager
.getCurrentInstance());
HashMap<String, Object> argMap = new HashMap<String, Object>();
argMap.put("expression",
editArea.getQuery());
argMap.put("timeInfluence", timeInfluence);
Tool.this.trueEditArea = (ReferenceData) script
.execute("evaluate", argMap);
} catch (JepException e) {
statusHandler.handle(Priority.PROBLEM,
"Error re-evaluating edit area "
+ editArea.getId()
.getName() + ": "
+ e.getLocalizedMessage(),
e);
}
}
});
Map<String, Object> argMap = new HashMap<String, Object>();
argMap.put("expression", editArea.getQuery());
argMap.put("timeInfluence", timeInfluence);
IPythonExecutor<QueryScript, ReferenceData> executor = new QueryScriptExecutor(
"evaluate", argMap);
try {
Tool.this.trueEditArea = (ReferenceData) coordinator
.submitSyncJob(executor);
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
"Error re-evaluating edit area "
+ editArea.getId().getName() + ": "
+ e.getLocalizedMessage(), e);
}
}
} else {
trueEditArea = editArea;
@ -602,10 +603,13 @@ public class Tool {
try {
parmToEdit.startParmEdit(new Date[] { timeInfluence });
} catch (GFEOperationFailedException e) {
statusHandler.handle(Priority.PROBLEM,
"Error during start parm edit for " + toolName + " - already running." +
" Please wait for the operation to complete and try again.",
e);
statusHandler
.handle(Priority.PROBLEM,
"Error during start parm edit for "
+ toolName
+ " - already running."
+ " Please wait for the operation to complete and try again.",
e);
return;
}
startedParmEdit = true;

View file

@ -27,10 +27,10 @@ import com.raytheon.uf.common.geospatial.SpatialQueryFactory;
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.maps.rsc.DbMapQueryFactory;
import com.raytheon.viz.awipstools.common.stormtrack.AbstractStormTrackResource;
import com.raytheon.viz.core.map.GeoUtil;
import com.raytheon.viz.warngen.gis.ClosestPoint;
import com.raytheon.viz.warngen.gis.ClosestPointComparator;
import com.raytheon.viz.warngen.util.AdjustAngle;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
@ -49,6 +49,7 @@ import com.vividsolutions.jts.geom.Point;
* Sep 25, 2012 #15425 Qinglu Lin Added getGid().
* Oct 17, 2012 jsanchez Added pathcast algorithm.
* Feb 12, 2013 1600 jsanchez Used adjustAngle method from AbstractStormTrackResource.
* Mar 5, 2013 1600 jsanchez Used AdjustAngle instead of AbstractStormTrackResource to handle angle adjusting.
*
* </pre>
*
@ -338,10 +339,9 @@ abstract public class AbstractDbSourceDataAdaptor {
gc.setStartingGeographicPoint(cp.getPoint().x, cp.getPoint().y);
gc.setDestinationGeographicPoint(closestCoord.x, closestCoord.y);
cp.setAzimuth(gc.getAzimuth());
cp.setOppositeAzimuth(AbstractStormTrackResource.adjustAngle(cp
.getAzimuth() + 180));
cp.setOppositeAzimuth(AdjustAngle.to360Degrees(cp.getAzimuth() + 180));
cp.setRoundedAzimuth(GeoUtil.roundAzimuth(cp.getAzimuth()));
cp.setOppositeRoundedAzimuth(AbstractStormTrackResource.adjustAngle(cp
cp.setOppositeRoundedAzimuth(AdjustAngle.to360Degrees(cp
.getRoundedAzimuth() + 180));
cp.setArea(area);
cp.setParentArea(parentArea);

View file

@ -66,7 +66,6 @@ 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.viz.core.exception.VizException;
import com.raytheon.viz.awipstools.common.stormtrack.AbstractStormTrackResource;
import com.raytheon.viz.awipstools.common.stormtrack.StormTrackDisplay;
import com.raytheon.viz.awipstools.common.stormtrack.StormTrackState;
import com.raytheon.viz.core.map.GeoUtil;
@ -75,6 +74,7 @@ import com.raytheon.viz.warngen.WarngenException;
import com.raytheon.viz.warngen.config.AbstractDbSourceDataAdaptor;
import com.raytheon.viz.warngen.config.DataAdaptorFactory;
import com.raytheon.viz.warngen.util.Abbreviation;
import com.raytheon.viz.warngen.util.AdjustAngle;
import com.raytheon.viz.warnings.DateUtil;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
@ -104,6 +104,7 @@ import com.vividsolutions.jts.geom.Point;
* Oct 17, 2012 jsanchez Moved the path cast data collecting to a separate class.
* Jan 31, 2013 1557 jsanchez Used allowDuplicates flag to collect points with duplicate names.
* Feb 12, 2013 1600 jsanchez Used adjustAngle method from AbstractStormTrackResource.
* Mar 5, 2013 1600 jsanchez Used AdjustAngle instead of AbstractStormTrackResource to handle angle adjusting.
*
* </pre>
*
@ -847,11 +848,10 @@ public class Wx {
.getCoordinate());
gc.setDestinationGeographicPoint(cen.x, cen.y);
cp2.azimuth = gc.getAzimuth();
cp2.oppositeAzimuth = AbstractStormTrackResource
.adjustAngle(cp2.azimuth + 180);
cp2.oppositeAzimuth = AdjustAngle.to360Degrees(cp2.azimuth + 180);
cp2.roundedAzimuth = GeoUtil.roundAzimuth(cp2.azimuth);
cp2.oppositeRoundedAzimuth = AbstractStormTrackResource
.adjustAngle(cp2.roundedAzimuth + 180);
cp2.oppositeRoundedAzimuth = AdjustAngle
.to360Degrees(cp2.roundedAzimuth + 180);
return cp2;
}

View file

@ -160,6 +160,7 @@ import com.vividsolutions.jts.io.WKTReader;
* 12/18/2012 DR 15571 Qinglu Lin Resolved coordinate issue in TML line caused by clicking Restart button.
* 01/24/2013 DR 15723 Qinglu Lin Added initRemovedGids() and updated updateWarnedAreas() to prevent the removed
* counties from being re-hatched.
* 03/06/2013 DR 15831 D. Friedman Use area inclusion filter in followups.
*
* </pre>
*
@ -1147,6 +1148,38 @@ public class WarngenLayer extends AbstractStormTrackResource {
}
}
/** Determine if a feature should be included based on how much of it
* is hatched and the configured inclusion criteria.
* @param feature
* @param featureAreaToConsider the portion of the feature that is hatched
* @param localCoordinates if true, use local CRS; otherwise, use lat/lon
* @param anyAmountOfArea if true, ignore the configured criteria and
* include the feature if event a small amount is hatched.
* @return true if the feature should be included
*/
private boolean filterArea(GeospatialData feature, Geometry featureAreaToConsider, boolean localCRS, boolean anyAmountOfArea) {
Geometry geom = localCRS ?
(Geometry) feature.attributes.get(GeospatialDataList.LOCAL_GEOM) :
feature.geometry;
double ratio = featureAreaToConsider.getArea() / geom.getArea();
double ratioInPercent = ratio * 100.;
Double areaOfGeom = (Double) feature.attributes.get(AREA);
double areaInKmSqOfIntersection = meterSqToKmSq
.convert(areaOfGeom * ratio);
if (anyAmountOfArea) {
return areaInKmSqOfIntersection > 1;
} else {
boolean percentOk = ratioInPercent >= getConfiguration()
.getHatchedAreaSource().getInclusionPercent();
boolean areaOk = areaInKmSqOfIntersection > getConfiguration()
.getHatchedAreaSource().getInclusionArea();
return getConfiguration().getHatchedAreaSource()
.getInclusionAndOr().equalsIgnoreCase("AND") ?
percentOk && areaOk : percentOk || areaOk;
}
}
/**
*
* @param snapHatchedAreaToPolygon
@ -1177,6 +1210,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
long t0 = System.currentTimeMillis();
Geometry newHatchedArea = null;
boolean insideCWA = false;
Set<String> filteredOutGids = new HashSet<String>();
// Loop through each of our counties returned from the query
for (GeospatialData f : geoData.features) {
// get the geometry of the county and make sure it intersects with
@ -1189,7 +1223,10 @@ public class WarngenLayer extends AbstractStormTrackResource {
try {
// Get intersection between county and hatched boundary
intersection = GeometryUtil.intersection(hatchedArea, prepGeom);
if (oldWarningArea != null)
intersection = GeometryUtil.intersection(intersection, oldWarningArea);
if (intersection.isEmpty()) {
filteredOutGids.addAll(Arrays.asList(GeometryUtil.getGID(f.geometry)));
continue;
}
insideCWA = true;
@ -1199,32 +1236,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
}
try {
double ratio = intersection.getArea() / geom.getArea();
double ratioInPercent = ratio * 100.;
Double areaOfGeom = (Double) f.attributes.get(AREA);
double areaInKmSqOfIntersection = meterSqToKmSq
.convert(areaOfGeom * ratio);
boolean includeArea = false;
if (!determineInclusion) {
includeArea = areaInKmSqOfIntersection > 1;
} else if (getConfiguration().getHatchedAreaSource()
.getInclusionAndOr().equalsIgnoreCase("AND")) {
if ((ratioInPercent >= getConfiguration()
.getHatchedAreaSource().getInclusionPercent())
&& (areaInKmSqOfIntersection > getConfiguration()
.getHatchedAreaSource().getInclusionArea())) {
includeArea = true;
}
} else {
if ((ratioInPercent >= getConfiguration()
.getHatchedAreaSource().getInclusionPercent())
|| (areaInKmSqOfIntersection > getConfiguration()
.getHatchedAreaSource().getInclusionArea())) {
includeArea = true;
}
}
if (includeArea
if (filterArea(f, intersection, true, ! determineInclusion)
&& (oldWarningPolygon == null || prepGeom
.intersects(oldWarningPolygon))) {
if (newHatchedArea == null) {
@ -1233,6 +1245,8 @@ public class WarngenLayer extends AbstractStormTrackResource {
newHatchedArea = GeometryUtil.union(newHatchedArea,
intersection);
}
} else {
filteredOutGids.addAll(Arrays.asList(GeometryUtil.getGID(f.geometry)));
}
} catch (TopologyException e) {
statusHandler.handle(Priority.VERBOSE,
@ -1284,7 +1298,7 @@ public class WarngenLayer extends AbstractStormTrackResource {
String[] gids = GeometryUtil.getGID(geom);
boolean flag = false;
for (String gid: gids) {
if (removedGids.contains(gid)) {
if (removedGids.contains(gid) || filteredOutGids.contains(gid)) {
flag = true;
break;
}
@ -2172,10 +2186,12 @@ public class WarngenLayer extends AbstractStormTrackResource {
geom = GeometryUtil.intersection(
warningPolygon, geom);
}
state.setWarningArea(GeometryUtil.union(
state.getWarningArea(), geom));
for (String gid: gids) {
removedGids.remove(gid);
if (filterArea(f, geom, false, false)) {
state.setWarningArea(GeometryUtil.union(
state.getWarningArea(), geom));
for (String gid: gids) {
removedGids.remove(gid);
}
}
}
} else {

View file

@ -76,7 +76,6 @@ import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.viz.awipstools.ToolsDataManager;
import com.raytheon.viz.awipstools.common.StormTrackData;
import com.raytheon.viz.awipstools.common.stormtrack.AbstractStormTrackResource;
import com.raytheon.viz.awipstools.common.stormtrack.StormTrackState;
import com.raytheon.viz.awipstools.common.stormtrack.StormTrackState.DisplayType;
import com.raytheon.viz.core.mode.CAVEMode;
@ -93,6 +92,7 @@ import com.raytheon.viz.warngen.gui.WarngenLayer;
import com.raytheon.viz.warngen.gui.WarngenUIState;
import com.raytheon.viz.warngen.text.WarningTextHandler;
import com.raytheon.viz.warngen.text.WarningTextHandlerFactory;
import com.raytheon.viz.warngen.util.AdjustAngle;
import com.raytheon.viz.warngen.util.CurrentWarnings;
import com.raytheon.viz.warngen.util.FipsUtil;
import com.raytheon.viz.warngen.util.FollowUpUtil;
@ -515,8 +515,8 @@ public class TemplateRunner {
// StormTrackData motion direction is between -180/180,
// whereas a WarningRecord motion direction is between
// -360/360
double motionDirection = AbstractStormTrackResource
.adjustAngle(oldWarn.getMotdir() - 180);
double motionDirection = AdjustAngle.to180Degrees(oldWarn
.getMotdir() - 180);
StormTrackData std = ToolsDataManager.getInstance()
.getStormTrackData();
std.setDate(simulatedTime);

View file

@ -0,0 +1,74 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.warngen.util;
/**
* Utility methods to adjust an angle.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 5, 2013 1600 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class AdjustAngle {
/**
* Adjusts the angle to be within the range -180 to +180 degrees.
*
* @param angle
* @return
*/
public static double to180Degrees(double angle) {
double newVal = angle % 360;
if (newVal > 180) {
newVal -= 360;
} else if (newVal < -180) {
newVal += 360;
}
return newVal;
}
/**
* Adjusts the angle to be within the range 0 to 360 degrees.
*
* @param angle
* @return
*/
public static double to360Degrees(double angle) {
double newVal = angle % 360;
if (newVal < 0) {
newVal += 360;
} else if (newVal > 360) {
newVal -= 360;
}
return newVal;
}
}

View file

@ -0,0 +1,23 @@
#!/bin/bash
SQL_SCRIPT="fixParameterUnits.sql"
# ensure that the sql script is present
if [ ! -f ${SQL_SCRIPT} ]; then
echo "ERROR: the required sql script - ${SQL_SCRIPT} was not found."
echo "FATAL: the update has failed!"
exit 1
fi
echo "INFO: update started - fix parameter units degree definitions"
# run the update
/awips2/psql/bin/psql -U awips -d metadata -f ${SQL_SCRIPT}
if [ $? -ne 0 ]; then
echo "FATAL: the update has failed!"
exit 1
fi
echo "INFO: the update has completed successfully!"
exit 0

View file

@ -0,0 +1,30 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
\set ON_ERROR_STOP 1
\connect metadata;
-- Start a transaction
BEGIN;
-- update 'Degree true' and 'deg true' to 'deg'
update metadata.parameter set unit = 'deg' where unit like 'Deg%true' or unit like 'deg%true';
-- Commit the transaction
END;

View file

@ -1,165 +1,162 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml version="1.0" encoding="UTF-8"?>
<gridParamInfo xmlns:ns2="group">
<valtimeMINUSreftime>
<fcst>302400</fcst>
<fcst>324000</fcst>
<fcst>345600</fcst>
<fcst>367200</fcst>
<fcst>388800</fcst>
<fcst>410400</fcst>
<fcst>432000</fcst>
<fcst>453600</fcst>
<fcst>475200</fcst>
<fcst>496800</fcst>
<fcst>518400</fcst>
<fcst>540000</fcst>
<fcst>561600</fcst>
<fcst>583200</fcst>
<fcst>604800</fcst>
<fcst>626400</fcst>
<fcst>648000</fcst>
</valtimeMINUSreftime>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>mxt</short_name>
<long_name>Maximum Temperature</long_name>
<units>K</units>
<udunits>degree_Kelvin</udunits>
<uiname>maxT</uiname>
<valid_range>180.0</valid_range>
<valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levels>FHAG 2</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>staticSpacing</short_name>
<long_name>Grid spacing</long_name>
<units>m</units>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>mnt</short_name>
<long_name>Minimum Temperature</long_name>
<units>K</units>
<udunits>degree_Kelvin</udunits>
<uiname>minT</uiname>
<valid_range>180.0</valid_range>
<valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levels>FHAG 2</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>pop</short_name>
<long_name>Probability of precip Delta</long_name>
<units>%</units>
<udunits>percent</udunits>
<uiname>PcpProb</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levels>SFC</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>staticTopo</short_name>
<long_name>Topography</long_name>
<units>m</units>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>ws</short_name>
<long_name>Wind Speed</long_name>
<units>m/s</units>
<udunits>meter/sec</udunits>
<uiname>windSpeed</uiname>
<valid_range>-150.0</valid_range>
<valid_range>150.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levels>FHAG 10</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>tcc</short_name>
<long_name>Total Cloud Cover</long_name>
<units>%</units>
<udunits>percent</udunits>
<uiname>totalCldCvr</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levels>EA</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>dpt</short_name>
<long_name>Dewpoint Temperature</long_name>
<units>K</units>
<udunits>degree_Kelvin</udunits>
<uiname>Td</uiname>
<valid_range>180.0</valid_range>
<valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levels>FHAG 2</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>wx</short_name>
<long_name>Weather</long_name>
<units></units>
<udunits></udunits>
<uiname>Weather</uiname>
<valid_range>0.0</valid_range>
<valid_range>10.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levels>SFC</levels>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>reftime</short_name>
<long_name>reference time</long_name>
<units>seconds since (1970-1-1 00:00:00.0)</units>
<fillValue>0.0</fillValue>
<n3D>0</n3D>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>staticCoriolis</short_name>
<long_name>Coriolis parameter</long_name>
<units>s^-1</units>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>valtimeMINUSreftime</short_name>
<units>seconds</units>
<fillValue>0.0</fillValue>
<n3D>0</n3D>
</gridParameterInfo>
<gridParameterInfo xsi:type="parameterInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>wd</short_name>
<long_name>Wind Direction</long_name>
<units>degreeTrue</units>
<udunits>degree_True</udunits>
<uiname>windDir</uiname>
<valid_range>0.0</valid_range>
<valid_range>360.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levels>FHAG 10</levels>
</gridParameterInfo>
<valtimeMINUSreftime>
<fcst>302400</fcst>
<fcst>324000</fcst>
<fcst>345600</fcst>
<fcst>367200</fcst>
<fcst>388800</fcst>
<fcst>410400</fcst>
<fcst>432000</fcst>
<fcst>453600</fcst>
<fcst>475200</fcst>
<fcst>496800</fcst>
<fcst>518400</fcst>
<fcst>540000</fcst>
<fcst>561600</fcst>
<fcst>583200</fcst>
<fcst>604800</fcst>
<fcst>626400</fcst>
<fcst>648000</fcst>
<fcst>669600</fcst>
<fcst>691200</fcst>
</valtimeMINUSreftime>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>mnt</short_name>
<long_name>Minimum Temperature</long_name>
<units>K</units>
<udunits>degree_Kelvin</udunits>
<uiname>minT</uiname>
<valid_range>180.0</valid_range>
<valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 2</levelsDesc>
<levels>
<level>FHAG2</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>pop</short_name>
<long_name>Probability of precip Delta</long_name>
<units>%</units>
<udunits>percent</udunits>
<uiname>PcpProb</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>staticSpacing</short_name>
<long_name>Grid spacing</long_name>
<units>meters</units>
<fillValue>-99999.0</fillValue>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>tcc</short_name>
<long_name>Total Cloud Cover</long_name>
<units>%</units>
<udunits>percent</udunits>
<uiname>totalCldCvr</uiname>
<valid_range>0.0</valid_range>
<valid_range>100.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>EA</levelsDesc>
<levels>
<level>EA</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>wd</short_name>
<long_name>Wind Direction</long_name>
<units>degreeTrue</units>
<udunits>degree_True</udunits>
<uiname>windDir</uiname>
<valid_range>0.0</valid_range>
<valid_range>360.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 10</levelsDesc>
<levels>
<level>FHAG10</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>mxt</short_name>
<long_name>Maximum Temperature</long_name>
<units>K</units>
<udunits>degree_Kelvin</udunits>
<uiname>maxT</uiname>
<valid_range>180.0</valid_range>
<valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 2</levelsDesc>
<levels>
<level>FHAG2</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>staticCoriolis</short_name>
<long_name>Coriolis parameter</long_name>
<units>/second</units>
<fillValue>-99999.0</fillValue>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>ws</short_name>
<long_name>Wind Speed</long_name>
<units>m/s</units>
<udunits>meter/sec</udunits>
<uiname>windSpeed</uiname>
<valid_range>-150.0</valid_range>
<valid_range>150.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 10</levelsDesc>
<levels>
<level>FHAG10</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>wxType</short_name>
<long_name>Weather</long_name>
<units/>
<udunits/>
<uiname>Weather</uiname>
<valid_range>0.0</valid_range>
<valid_range>12.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>0</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>dpt</short_name>
<long_name>Dewpoint Temperature</long_name>
<units>K</units>
<udunits>degree_Kelvin</udunits>
<uiname>Td</uiname>
<valid_range>180.0</valid_range>
<valid_range>330.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>FHAG 2</levelsDesc>
<levels>
<level>FHAG2</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo">
<short_name>staticTopo</short_name>
<long_name>Topography</long_name>
<units>meters</units>
<fillValue>-99999.0</fillValue>
</gridParameterInfo>
</gridParamInfo>

View file

@ -1,5 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
res/
.

View file

@ -1,13 +0,0 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd">
<util:constant id="requestServerKey"
static-field="com.raytheon.uf.common.auth.RequestConstants.REQUEST_SERVER" />
</beans>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.common.python.concurrent</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,9 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Concurrent
Bundle-SymbolicName: com.raytheon.uf.common.python.concurrent
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: com.raytheon.uf.common.python;bundle-version="1.12.1174"
Export-Package: com.raytheon.uf.common.python.concurrent

View file

@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.

View file

@ -0,0 +1,75 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.python.concurrent;
import com.raytheon.uf.common.python.PythonInterpreter;
/**
* Must be extended by all classes that want to run Python on different threads.
* Defines the thread pool, gets the {@link PythonInterpreter}, and tells how to
* execute.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 5, 2013 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public abstract class AbstractPythonScriptFactory<P extends PythonInterpreter> {
private final int maxThreads;
private final String name;
/**
* This method will be called on the Python thread and will instantiate the
* PythonInterpreter that is going to be used.
*
* @return
*/
public abstract P createPythonScript();
public AbstractPythonScriptFactory(String name, int maxThreads) {
this.name = name;
this.maxThreads = maxThreads;
}
/**
* @return the maxThreads
*/
public final int getMaxThreads() {
return maxThreads;
}
/**
* @return the name
*/
public final String getName() {
return name;
}
}

View file

@ -0,0 +1,51 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.python.concurrent;
import com.raytheon.uf.common.python.PythonInterpreter;
/**
* Any class that implements this will be able to execute methods on the
* PythonInterpreter that is passed in
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 5, 2013 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public interface IPythonExecutor<P extends PythonInterpreter, R extends Object> {
/**
* Method takes a {@link PythonInterpreter} and executes the necessary parts
* of it
*
* @param script
* @return
*/
public abstract R execute(P script);
}

View file

@ -0,0 +1,56 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.python.concurrent;
import java.util.EventListener;
/**
* Subclasses can create their own instance of this class to specify what to do
* when the {@link PythonJob} is finished
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 30, 2013 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public interface IPythonJobListener<R extends Object> extends EventListener {
/**
* When a job has finished successfully this will get fired.
*
* @param result
*/
public void jobFinished(R result);
/**
* When a job has finished with exceptions, this will get fired.
*
* @param e
*/
public void jobFailed(Throwable e);
}

View file

@ -0,0 +1,87 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.python.concurrent;
import java.util.concurrent.Callable;
import com.raytheon.uf.common.python.PythonInterpreter;
/**
* Task that will invoke methods on a {@link IPythonExecutor} subclass
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 31, 2013 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class PythonJob<P extends PythonInterpreter, R extends Object>
implements Callable<R> {
/*
* When code creates a new PythonJob, this gets set to the instance of the
* ThreadLocal that corresponds with whichever thread the application is
* running on
*/
private ThreadLocal<P> threadPython = null;
private IPythonJobListener<R> listener;
private IPythonExecutor<P, R> executor;
public PythonJob(IPythonExecutor<P, R> executor,
IPythonJobListener<R> listener, ThreadLocal<P> threadLocal) {
this.listener = listener;
this.threadPython = threadLocal;
this.executor = executor;
}
public PythonJob(IPythonExecutor<P, R> executor, ThreadLocal<P> threadLocal) {
this.threadPython = threadLocal;
this.executor = executor;
}
@Override
public R call() {
P script = threadPython.get();
R result = null;
try {
result = executor.execute(script);
} catch (Throwable t) {
if (listener != null) {
listener.jobFailed(t);
}
return null;
}
// fire listener to alert the original caller that we are done
if (listener != null) {
listener.jobFinished(result);
}
return result;
}
}

View file

@ -0,0 +1,188 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.python.concurrent;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import com.raytheon.uf.common.python.PythonInterpreter;
/**
* Interface to get to the {@link ExecutorService}. Allows multiple thread pools
* to be created in a single JVM, by passing in a different application name.
*
* This class will be used in this way:
*
*
* <pre>
*
* AbstractPythonScriptFactory<PythonInterpreter, Object> factory = new CAVEPythonFactory();
* PythonJobCoordinator coordinator = PythonJobCoordinator
* .newInstance(factory);
* IPythonExecutor<PythonInterpreter, Object> executor = new CAVEExecutor(
* args);
* try {
* coordinator.submitJob(executor, listener);
* } catch (Exception e) {
* e.printStackTrace();
* }
*
* }
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 31, 2013 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class PythonJobCoordinator<P extends PythonInterpreter> {
private ExecutorService execService = null;
private ThreadLocal<P> threadLocal = null;
private static Map<String, PythonJobCoordinator<? extends PythonInterpreter>> pools = new ConcurrentHashMap<String, PythonJobCoordinator<? extends PythonInterpreter>>();
private PythonJobCoordinator(final AbstractPythonScriptFactory<P> factory) {
execService = Executors.newFixedThreadPool(factory.getMaxThreads(),
new PythonThreadFactory(factory.getName()));
threadLocal = new ThreadLocal<P>() {
protected P initialValue() {
return factory.createPythonScript();
};
};
}
/**
* Gets the instance by name, or throw a {@link RuntimeException}.
*
* @param name
* @return
*/
public static PythonJobCoordinator<? extends PythonInterpreter> getInstance(
String name) {
synchronized (pools) {
if (pools.containsKey(name)) {
return pools.get(name);
} else {
throw new RuntimeException(
"Unable to find instance of PythonJobCoordinator named "
+ name
+ ", please call newInstance(AbstractPythonScriptFactory)");
}
}
}
/**
* Creates a new instance of this class for a new application. If the same
* name already exists, it assumes that it is the same application and
* returns the existing instance.
*
* @param name
* @param numThreads
* @return
*/
public static <S extends PythonInterpreter> PythonJobCoordinator<S> newInstance(
AbstractPythonScriptFactory<S> factory) {
synchronized (pools) {
if (pools.containsKey(factory.getName())) {
return (PythonJobCoordinator<S>) pools.get(factory.getName());
} else {
PythonJobCoordinator<S> pool = new PythonJobCoordinator<S>(
factory);
pools.put(factory.getName(), pool);
return pool;
}
}
}
/**
* Submits a job to the {@link ExecutorService}. Fires a listener back after
* it is done. This should be used for asynchronous operations.
*
* @param callable
* @return
* @throws Exception
*/
public <R> void submitAsyncJob(IPythonExecutor<P, R> executor,
IPythonJobListener<R> listener) throws Exception {
// fail if the listener is null, bad things happen then
if (listener == null) {
throw new IllegalArgumentException("Listener cannot be null");
}
// submit job
PythonJob<P, R> job = new PythonJob<P, R>(executor, listener,
threadLocal);
execService.submit(job);
}
/**
* Submits a job to the {@link ExecutorService}. Waits on the result before
* returning back. This should be used for synchronous operations.
*
* @param executor
* @return
* @throws InterruptedException
* @throws ExecutionException
*/
public <R> R submitSyncJob(IPythonExecutor<P, R> executor)
throws InterruptedException, ExecutionException {
// submit job
PythonJob<P, R> job = new PythonJob<P, R>(executor, threadLocal);
Future<R> future = execService.submit(job);
// wait for return object
return future.get();
}
/**
* This function should take the {@link PythonInterpreter} on each thread in
* the thread pool and dispose of it and then shutdown the
* {@link ExecutorService}
*
* @param name
*/
public void shutdownCoordinator(String name) {
/*
* TODO need to add for future functionality
*/
}
/**
* This function should cancel any listeners for a certain task and then
* remove those corresponding tasks off of the queue to be ran. It should
* NOT try to cancel any running python interpreters.
*
* @param name
*/
public void shutdownTask(String name) {
/*
* TODO need to add for future functionality
*/
}
}

View file

@ -0,0 +1,71 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.python.concurrent;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Creates new threads named according to what python task they were created
* for. Based nearly identically off of {@link ThreadFactory}
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 31, 2013 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class PythonThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
public PythonThreadFactory(String name) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread()
.getThreadGroup();
namePrefix = name.toLowerCase() + "-pool-"
+ poolNumber.getAndIncrement() + "-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix
+ threadNumber.getAndIncrement(), 0);
if (t.isDaemon()) {
t.setDaemon(false);
}
if (t.getPriority() != Thread.NORM_PRIORITY) {
t.setPriority(Thread.NORM_PRIORITY);
}
return t;
}
}

View file

@ -21,6 +21,7 @@ package com.raytheon.uf.common.serialization.comm;
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.util.registry.GenericRegistry;
import com.raytheon.uf.common.util.registry.RegistryException;
@ -35,6 +36,8 @@ import com.raytheon.uf.common.util.registry.RegistryException;
* ------------ ---------- ----------- --------------------------
* Dec 9, 2010 rjpeter Initial creation
* Nov 15, 2012 1322 djohnson Add ability to route by server key.
* Mar 05, 2013 1754 djohnson Prevent infinite loop when request.server router not registered,
* info log when router registered.
*
* </pre>
*
@ -62,22 +65,24 @@ public final class RequestRouter {
throws RegistryException {
if (registry.containsKey(t)) {
throw new RegistryException("Unable to register router",
new IllegalStateException(
"IRequestRouter of type ["
+ s.getClass().getName()
new IllegalStateException("IRequestRouter of type ["
+ s.getClass().getName()
+ "] already registered for key [" + t + "]"));
}
statusHandler.info("Registered request router for key [" + t
+ "] of type [" + s.getClass().getName() + "]");
return super.register(t, s);
}
/**
* Clear the registry. Intentionally package-private so it can be cleared by test code.
* Clear the registry. Intentionally package-private so it can be
* cleared by test code.
*/
void clear() {
registry.clear();
}
};
private static final RouterRegistry routerRegistry = new RouterRegistry();
/**
@ -119,13 +124,22 @@ public final class RequestRouter {
*/
public static Object route(IServerRequest request, String service)
throws Exception {
final IRequestRouter router = routerRegistry.getRegisteredObject(service);
final IRequestRouter router = routerRegistry
.getRegisteredObject(service);
if (router == null) {
statusHandler
.error("There is no registered router for service ["
+ service
+ "]. Routing to the request service, but the request may not be able to be processed!");
return route(request);
if (REQUEST_SERVICE.equals(service)) {
final String errorMessage = "There is no registered router for service ["
+ service + "]. The request cannot be processed!";
statusHandler.handle(Priority.FATAL, errorMessage);
throw new IllegalStateException(errorMessage);
} else {
statusHandler
.error("There is no registered router for service ["
+ service
+ "]. Routing to the request service, but the request may not be able to be processed!");
return route(request);
}
} else {
return router.route(request);
}

View file

@ -38,6 +38,7 @@ import com.raytheon.uf.common.util.registry.RegistryException;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 14, 2012 1286 djohnson Initial creation
* Mar 05, 2013 1754 djohnson Test that infinite loop for request server does not occur.
*
* </pre>
*
@ -95,10 +96,10 @@ public class RequestRouterTest {
verify(requestServerRouter).route(serverRequest);
}
@Test
public void testWithServiceSendsToRegisteredRouter() throws Exception {
RequestRouter.route(serverRequest, SERVICE1_KEY);
verify(server1Router).route(serverRequest);
@ -126,6 +127,13 @@ public class RequestRouterTest {
verify(server1Router, never()).route(serverRequest);
}
@Test(expected = IllegalStateException.class)
public void testUnregisteredRequestRouterWillThrowIllegalStateException()
throws Throwable {
RequestRouterTest.clearRegistry();
RequestRouter.route(serverRequest, RequestRouter.REQUEST_SERVICE);
}
@Test(expected = RegistryException.class)
public void testRegisteringTwoRequestRoutersWithSameKeyThrowsException()
throws Exception {