Issue #2868 plot delegate python now uses PythonCoordinatorJob API,
Refactored plot data request, image creation, and sample threading Change-Id: I3e1a3dc70b2346aa826ec4509ee7a3e59c61a918 Former-commit-id:2418c9bdfe
[formerlyfe33896e7e
] [formerly2418c9bdfe
[formerlyfe33896e7e
] [formerlyc4beb293b9
[formerly e421731415d798487c96dd1e56b6f02347d9aa26]]] Former-commit-id:c4beb293b9
Former-commit-id:0acb4621f9
[formerly774091461c
] Former-commit-id:96339798b5
This commit is contained in:
parent
54e1c39279
commit
5b6683bd56
16 changed files with 1055 additions and 597 deletions
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||||
Bundle-ManifestVersion: 2
|
Bundle-ManifestVersion: 2
|
||||||
Bundle-Name: Pointdata Plug-in
|
Bundle-Name: Pointdata Plug-in
|
||||||
Bundle-SymbolicName: com.raytheon.viz.pointdata;singleton:=true
|
Bundle-SymbolicName: com.raytheon.viz.pointdata;singleton:=true
|
||||||
Bundle-Version: 1.12.1174.qualifier
|
Bundle-Version: 1.14.0.qualifier
|
||||||
Bundle-Activator: com.raytheon.viz.pointdata.Activator
|
Bundle-Activator: com.raytheon.viz.pointdata.Activator
|
||||||
Bundle-Vendor: Raytheon
|
Bundle-Vendor: Raytheon
|
||||||
Eclipse-RegisterBuddy: com.raytheon.viz.core, com.raytheon.uf.viz.core
|
Eclipse-RegisterBuddy: com.raytheon.viz.core, com.raytheon.uf.viz.core
|
||||||
|
@ -20,7 +20,8 @@ Require-Bundle: org.apache.batik,
|
||||||
com.raytheon.uf.common.pointdata;bundle-version="1.12.1174",
|
com.raytheon.uf.common.pointdata;bundle-version="1.12.1174",
|
||||||
com.raytheon.uf.common.dataplugin.level;bundle-version="1.12.1174",
|
com.raytheon.uf.common.dataplugin.level;bundle-version="1.12.1174",
|
||||||
com.raytheon.uf.common.colormap;bundle-version="1.12.1174",
|
com.raytheon.uf.common.colormap;bundle-version="1.12.1174",
|
||||||
com.raytheon.uf.common.wxmath
|
com.raytheon.uf.common.wxmath,
|
||||||
|
com.raytheon.uf.common.python.concurrent
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Export-Package: com.raytheon.viz.pointdata,
|
Export-Package: com.raytheon.viz.pointdata,
|
||||||
com.raytheon.viz.pointdata.drawables,
|
com.raytheon.viz.pointdata.drawables,
|
||||||
|
|
|
@ -1,196 +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.pointdata;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
|
|
||||||
import org.eclipse.core.runtime.jobs.Job;
|
|
||||||
import org.eclipse.swt.graphics.RGB;
|
|
||||||
|
|
||||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
|
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
|
||||||
import com.raytheon.uf.viz.core.map.MapDescriptor;
|
|
||||||
import com.raytheon.viz.pointdata.thread.GetDataTask;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thread pool for requesting data for plots. Each data request job is tied to a
|
|
||||||
* plot generator job.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
*
|
|
||||||
* SOFTWARE HISTORY
|
|
||||||
*
|
|
||||||
* Date Ticket# Engineer Description
|
|
||||||
* ------------ ---------- ----------- --------------------------
|
|
||||||
* Jun 30, 2011 njensen Initial creation
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author njensen
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class PlotDataThreadPool {
|
|
||||||
|
|
||||||
private static final int THREADS = 2;
|
|
||||||
|
|
||||||
protected ConcurrentLinkedQueue<GetDataTask> stationQueue = new ConcurrentLinkedQueue<GetDataTask>();
|
|
||||||
|
|
||||||
protected List<PlotModelDataRequestJob> jobList = new ArrayList<PlotModelDataRequestJob>();
|
|
||||||
|
|
||||||
public PlotDataThreadPool(IGraphicsTarget aTarget,
|
|
||||||
MapDescriptor mapDescriptor, String plotModelFile, String levelKey,
|
|
||||||
String plugin, HashMap<String, RequestConstraint> constraintMap,
|
|
||||||
IPlotModelGeneratorCaller caller) throws VizException {
|
|
||||||
for (int i = 0; i < THREADS; i++) {
|
|
||||||
jobList.add(new PlotModelDataRequestJob(aTarget, mapDescriptor,
|
|
||||||
plotModelFile, levelKey, plugin, constraintMap, caller,
|
|
||||||
this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a batch of stations to the queue
|
|
||||||
*
|
|
||||||
* @param station
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void queueStation(GetDataTask task) {
|
|
||||||
List<PlotInfo[]> station = task.getStations();
|
|
||||||
|
|
||||||
Iterator<PlotInfo[]> itr = station.iterator();
|
|
||||||
while (itr.hasNext()) {
|
|
||||||
PlotInfo[] infos = itr.next();
|
|
||||||
boolean allQueued = true;
|
|
||||||
for (PlotInfo info : infos) {
|
|
||||||
switch (task.getRequestType()) {
|
|
||||||
case PLOT_ONLY:
|
|
||||||
if (!info.plotQueued) {
|
|
||||||
allQueued = false;
|
|
||||||
info.plotQueued = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case SAMPLE_ONLY:
|
|
||||||
if (!info.sampleQueued) {
|
|
||||||
allQueued = false;
|
|
||||||
info.sampleQueued = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PLOT_AND_SAMPLE:
|
|
||||||
if (!info.sampleQueued) {
|
|
||||||
allQueued = false;
|
|
||||||
info.sampleQueued = true;
|
|
||||||
}
|
|
||||||
if (!info.plotQueued) {
|
|
||||||
allQueued = false;
|
|
||||||
info.plotQueued = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (allQueued) {
|
|
||||||
itr.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (station.size() > 0) {
|
|
||||||
task.setStations(station);
|
|
||||||
stationQueue.add(task);
|
|
||||||
for (PlotModelDataRequestJob job : jobList) {
|
|
||||||
if (job.getState() != Job.RUNNING) {
|
|
||||||
job.schedule();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlotModelColor(RGB color) {
|
|
||||||
for (PlotModelDataRequestJob job : jobList) {
|
|
||||||
job.setPlotModelColor(color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlotModelLineStyle(LineStyle lineStyle) {
|
|
||||||
for (PlotModelDataRequestJob job : jobList) {
|
|
||||||
job.setPlotModelLineStyle(lineStyle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlotModelLineWidth(int outlineWidth) {
|
|
||||||
for (PlotModelDataRequestJob job : jobList) {
|
|
||||||
job.setPlotModelLineWidth(outlineWidth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlotMissingData(boolean plotMissingData) {
|
|
||||||
for (PlotModelDataRequestJob job : jobList) {
|
|
||||||
job.setPlotMissingData(plotMissingData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLowerLimit(double lowerLimit) {
|
|
||||||
for (PlotModelDataRequestJob job : jobList) {
|
|
||||||
job.setLowerLimit(lowerLimit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpperLimit(double upperLimit) {
|
|
||||||
for (PlotModelDataRequestJob job : jobList) {
|
|
||||||
job.setUpperLimit(upperLimit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getPlotModelWidth() {
|
|
||||||
return jobList.get(0).getPlotModelWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlotModelSize(long round) {
|
|
||||||
for (PlotModelDataRequestJob job : jobList) {
|
|
||||||
job.setPlotModelSize(round);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDone() {
|
|
||||||
for (PlotModelDataRequestJob job : jobList) {
|
|
||||||
if (!job.isDone()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void shutdown() {
|
|
||||||
List<PlotModelDataRequestJob> jobListCopy = new ArrayList<PlotModelDataRequestJob>(
|
|
||||||
jobList);
|
|
||||||
jobList.clear();
|
|
||||||
stationQueue.clear();
|
|
||||||
for (PlotModelDataRequestJob job : jobListCopy) {
|
|
||||||
job.shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -29,6 +29,7 @@ import java.text.ParsePosition;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Formatter;
|
import java.util.Formatter;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -40,8 +41,6 @@ import javax.measure.converter.UnitConverter;
|
||||||
import javax.measure.unit.Unit;
|
import javax.measure.unit.Unit;
|
||||||
import javax.measure.unit.UnitFormat;
|
import javax.measure.unit.UnitFormat;
|
||||||
|
|
||||||
import jep.JepException;
|
|
||||||
|
|
||||||
import org.apache.batik.bridge.BridgeContext;
|
import org.apache.batik.bridge.BridgeContext;
|
||||||
import org.apache.batik.bridge.GVTBuilder;
|
import org.apache.batik.bridge.GVTBuilder;
|
||||||
import org.apache.batik.bridge.UserAgentAdapter;
|
import org.apache.batik.bridge.UserAgentAdapter;
|
||||||
|
@ -57,10 +56,8 @@ import org.w3c.dom.NodeList;
|
||||||
import org.w3c.dom.Text;
|
import org.w3c.dom.Text;
|
||||||
|
|
||||||
import com.raytheon.uf.common.localization.IPathManager;
|
import com.raytheon.uf.common.localization.IPathManager;
|
||||||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
|
||||||
import com.raytheon.uf.common.localization.LocalizationFile;
|
|
||||||
import com.raytheon.uf.common.localization.PathManagerFactory;
|
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||||
import com.raytheon.uf.common.python.PythonScript;
|
import com.raytheon.uf.common.python.concurrent.PythonJobCoordinator;
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
|
@ -69,12 +66,16 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.uf.viz.core.map.IMapDescriptor;
|
import com.raytheon.uf.viz.core.map.IMapDescriptor;
|
||||||
import com.raytheon.viz.pointdata.lookup.IAbstractLookupTable;
|
import com.raytheon.viz.pointdata.lookup.IAbstractLookupTable;
|
||||||
import com.raytheon.viz.pointdata.lookup.LookupUtils;
|
import com.raytheon.viz.pointdata.lookup.LookupUtils;
|
||||||
|
import com.raytheon.viz.pointdata.python.CheckPlotValidityExecutor;
|
||||||
|
import com.raytheon.viz.pointdata.python.PlotPythonScript;
|
||||||
|
import com.raytheon.viz.pointdata.python.PlotPythonScriptFactory;
|
||||||
|
import com.raytheon.viz.pointdata.python.SampleTextExecutor;
|
||||||
import com.raytheon.viz.pointdata.rsc.PlotResource2;
|
import com.raytheon.viz.pointdata.rsc.PlotResource2;
|
||||||
import com.raytheon.viz.pointdata.rsc.PlotResourceData;
|
import com.raytheon.viz.pointdata.rsc.PlotResourceData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A singleton that will create a plot model texture based on a passed in
|
* A factory for generating plot images and sample messages by parsing the
|
||||||
* MetarRecord object.
|
* associated plotModel SVG file.
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
|
@ -89,6 +90,7 @@ import com.raytheon.viz.pointdata.rsc.PlotResourceData;
|
||||||
* Sep 05, 2013 2316 bsteffen Unify pirep and ncpirep.
|
* Sep 05, 2013 2316 bsteffen Unify pirep and ncpirep.
|
||||||
* Sep 05, 2013 2307 dgilling Use better PythonScript constructor.
|
* Sep 05, 2013 2307 dgilling Use better PythonScript constructor.
|
||||||
* Nov 20, 2013 2033 njensen Fix detecting plotModels dirs from multiple plugins
|
* Nov 20, 2013 2033 njensen Fix detecting plotModels dirs from multiple plugins
|
||||||
|
* Mar 21, 2014 2868 njensen Refactored python usage to PythonJobCoordinator
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -99,7 +101,7 @@ public class PlotModelFactory2 {
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
.getHandler(PlotModelFactory2.class);
|
.getHandler(PlotModelFactory2.class);
|
||||||
|
|
||||||
private static final String PLOT_MODEL_DIR = "plotModels";
|
public static final String PLOT_MODEL_DIR = "plotModels";
|
||||||
|
|
||||||
private static final String DM_ATTRIBUTE = "plotMode";
|
private static final String DM_ATTRIBUTE = "plotMode";
|
||||||
|
|
||||||
|
@ -121,8 +123,6 @@ public class PlotModelFactory2 {
|
||||||
|
|
||||||
private static final String REQUIRED = "required";
|
private static final String REQUIRED = "required";
|
||||||
|
|
||||||
private static String cachedIncludePath;
|
|
||||||
|
|
||||||
private final SimpleDateFormat SAMPLE_DATE = new SimpleDateFormat("HHmm");
|
private final SimpleDateFormat SAMPLE_DATE = new SimpleDateFormat("HHmm");
|
||||||
|
|
||||||
// Need to include attribute and code to allow for String2String lookups and
|
// Need to include attribute and code to allow for String2String lookups and
|
||||||
|
@ -137,8 +137,6 @@ public class PlotModelFactory2 {
|
||||||
|
|
||||||
private Document document;
|
private Document document;
|
||||||
|
|
||||||
private GraphicsNode theGraphicsNode;
|
|
||||||
|
|
||||||
private final GVTBuilder builder;
|
private final GVTBuilder builder;
|
||||||
|
|
||||||
private final BridgeContext bridgeContext;
|
private final BridgeContext bridgeContext;
|
||||||
|
@ -171,9 +169,9 @@ public class PlotModelFactory2 {
|
||||||
|
|
||||||
private Map<String, BufferedImage> imageCache = null;
|
private Map<String, BufferedImage> imageCache = null;
|
||||||
|
|
||||||
private ScriptInfo scriptInfo;
|
protected final String plotModelFile;
|
||||||
|
|
||||||
private ScriptInfo sampleScriptInfo;
|
protected PythonJobCoordinator<PlotPythonScript> python;
|
||||||
|
|
||||||
public static enum DisplayMode {
|
public static enum DisplayMode {
|
||||||
TEXT, BARB, TABLE, AVAIL, RANGE, NULL, SAMPLE, ARROW
|
TEXT, BARB, TABLE, AVAIL, RANGE, NULL, SAMPLE, ARROW
|
||||||
|
@ -211,6 +209,10 @@ public class PlotModelFactory2 {
|
||||||
public Node getPlotNode() {
|
public Node getPlotNode() {
|
||||||
return plotNode;
|
return plotNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getParameter() {
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PlotWindElement {
|
public class PlotWindElement {
|
||||||
|
@ -238,6 +240,7 @@ public class PlotModelFactory2 {
|
||||||
byte[] blue = { 0, full };
|
byte[] blue = { 0, full };
|
||||||
byte[] green = { 0, zero };
|
byte[] green = { 0, zero };
|
||||||
regenerateStyle();
|
regenerateStyle();
|
||||||
|
this.plotModelFile = plotModelFile;
|
||||||
this.plotFields = new ArrayList<PlotModelElement>();
|
this.plotFields = new ArrayList<PlotModelElement>();
|
||||||
this.sampleFields = new ArrayList<PlotModelElement>();
|
this.sampleFields = new ArrayList<PlotModelElement>();
|
||||||
|
|
||||||
|
@ -452,12 +455,16 @@ public class PlotModelFactory2 {
|
||||||
imageCache = new HashMap<String, BufferedImage>();
|
imageCache = new HashMap<String, BufferedImage>();
|
||||||
}
|
}
|
||||||
NodeList scriptNodes = document.getElementsByTagName("script");
|
NodeList scriptNodes = document.getElementsByTagName("script");
|
||||||
|
|
||||||
// Only one script node supported
|
// Only one script node supported
|
||||||
if (scriptNodes.getLength() > 0) {
|
int nScriptNodes = scriptNodes.getLength();
|
||||||
|
if (nScriptNodes > 1) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Only one script node allowed in plotModel SVG file. Please check and fix "
|
||||||
|
+ plotModelFile);
|
||||||
|
} else if (nScriptNodes == 1) {
|
||||||
Element scriptNode = (Element) scriptNodes.item(0);
|
Element scriptNode = (Element) scriptNodes.item(0);
|
||||||
scriptInfo = new ScriptInfo();
|
String plotDelegateName = scriptNode.getAttribute("plotDelegate");
|
||||||
scriptInfo.plotDelegateName = scriptNode
|
|
||||||
.getAttribute("plotDelegate");
|
|
||||||
NodeList childNodes = scriptNode.getChildNodes();
|
NodeList childNodes = scriptNode.getChildNodes();
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||||
|
@ -466,14 +473,13 @@ public class PlotModelFactory2 {
|
||||||
sb.append(((Text) child).getData());
|
sb.append(((Text) child).getData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sb.length() > 0) {
|
String scriptText = sb.toString().trim();
|
||||||
scriptInfo.scriptText = sb.toString();
|
if (scriptText.length() > 0) {
|
||||||
|
PlotPythonScriptFactory pythonFactory = new PlotPythonScriptFactory(
|
||||||
|
plotModelFile, scriptText, plotDelegateName);
|
||||||
|
python = PythonJobCoordinator.newInstance(pythonFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
sampleScriptInfo = new ScriptInfo();
|
|
||||||
sampleScriptInfo.plotDelegateName = scriptInfo.plotDelegateName;
|
|
||||||
sampleScriptInfo.scriptText = scriptInfo.scriptText;
|
|
||||||
|
|
||||||
// remove the scriptNode in memory so time isn't wasted
|
// remove the scriptNode in memory so time isn't wasted
|
||||||
// later attempting to render it
|
// later attempting to render it
|
||||||
scriptNode.getParentNode().removeChild(scriptNode);
|
scriptNode.getParentNode().removeChild(scriptNode);
|
||||||
|
@ -491,8 +497,8 @@ public class PlotModelFactory2 {
|
||||||
byte fullr = (byte) color.red;
|
byte fullr = (byte) color.red;
|
||||||
byte fullg = (byte) color.green;
|
byte fullg = (byte) color.green;
|
||||||
byte fullb = (byte) color.blue;
|
byte fullb = (byte) color.blue;
|
||||||
String style = "stroke: rgb(" + color.red + "," + color.green + ","
|
// String style = "stroke: rgb(" + color.red + "," + color.green + ","
|
||||||
+ color.blue + ");";
|
// + color.blue + ");";
|
||||||
// this.svgRoot.setAttribute("style", style);
|
// this.svgRoot.setAttribute("style", style);
|
||||||
// System.out.println(style);
|
// System.out.println(style);
|
||||||
byte[] red = { 0, fullr };
|
byte[] red = { 0, fullr };
|
||||||
|
@ -567,8 +573,7 @@ public class PlotModelFactory2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes the station name and its MetarRecord object and produces a buffered
|
* Takes the station data object and produces a buffered image.
|
||||||
* image.
|
|
||||||
*
|
*
|
||||||
* @param station
|
* @param station
|
||||||
* The station name
|
* The station name
|
||||||
|
@ -591,27 +596,28 @@ public class PlotModelFactory2 {
|
||||||
this.gc.setDestinationGeographicPoint(newWorldLocation[0],
|
this.gc.setDestinationGeographicPoint(newWorldLocation[0],
|
||||||
newWorldLocation[1]);
|
newWorldLocation[1]);
|
||||||
}
|
}
|
||||||
StringBuffer imageId = new StringBuffer();
|
|
||||||
PlotPythonScript script = null;
|
|
||||||
try {
|
try {
|
||||||
boolean discard = false;
|
boolean discard = false;
|
||||||
|
if (python != null) {
|
||||||
if (scriptInfo != null) {
|
Boolean result = false;
|
||||||
script = scriptInfo.getScript();
|
CheckPlotValidityExecutor task = new CheckPlotValidityExecutor(
|
||||||
|
stationData);
|
||||||
try {
|
try {
|
||||||
Object result = script.executePlotDelegateMethod("isValid",
|
result = python.submitSyncJob(task);
|
||||||
"rec", stationData);
|
} catch (Exception e) {
|
||||||
if (result instanceof Boolean
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
&& !((Boolean) result).booleanValue()) {
|
"Error checking if plot is valid for plot model "
|
||||||
|
+ getPlotModelFilename(), e);
|
||||||
|
} finally {
|
||||||
|
if (result.booleanValue() == false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (JepException e) {
|
|
||||||
statusHandler.handle(Priority.PROBLEM,
|
|
||||||
e.getLocalizedMessage(), e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringBuilder imageId = new StringBuilder();
|
||||||
|
|
||||||
for (PlotModelElement element : this.plotFields) {
|
for (PlotModelElement element : this.plotFields) {
|
||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
boolean required = element.required;
|
boolean required = element.required;
|
||||||
|
@ -680,13 +686,13 @@ public class PlotModelFactory2 {
|
||||||
this.plotModelWidth, this.plotModelHeight,
|
this.plotModelWidth, this.plotModelHeight,
|
||||||
BufferedImage.TYPE_BYTE_INDEXED, tm);
|
BufferedImage.TYPE_BYTE_INDEXED, tm);
|
||||||
|
|
||||||
long t0 = System.currentTimeMillis();
|
// long t0 = System.currentTimeMillis();
|
||||||
this.theGraphicsNode = builder.build(this.bridgeContext,
|
GraphicsNode graphicsNode = builder.build(this.bridgeContext,
|
||||||
this.document);
|
this.document);
|
||||||
Graphics2D g2d = null;
|
Graphics2D g2d = null;
|
||||||
try {
|
try {
|
||||||
g2d = bufferedImage.createGraphics();
|
g2d = bufferedImage.createGraphics();
|
||||||
this.theGraphicsNode.primitivePaint(g2d);
|
graphicsNode.primitivePaint(g2d);
|
||||||
} finally {
|
} finally {
|
||||||
if (g2d != null) {
|
if (g2d != null) {
|
||||||
g2d.dispose();
|
g2d.dispose();
|
||||||
|
@ -702,9 +708,6 @@ public class PlotModelFactory2 {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
statusHandler.handle(Priority.PROBLEM,
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
"Error:" + e.getLocalizedMessage(), e);
|
"Error:" + e.getLocalizedMessage(), e);
|
||||||
} catch (JepException e) {
|
|
||||||
statusHandler.handle(Priority.PROBLEM,
|
|
||||||
"Error:" + e.getLocalizedMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -712,20 +715,20 @@ public class PlotModelFactory2 {
|
||||||
|
|
||||||
public synchronized String getStationMessage(PlotData stationData,
|
public synchronized String getStationMessage(PlotData stationData,
|
||||||
String dataURI) {
|
String dataURI) {
|
||||||
PlotPythonScript script = null;
|
|
||||||
StringBuilder sampleMessage = new StringBuilder();
|
StringBuilder sampleMessage = new StringBuilder();
|
||||||
try {
|
try {
|
||||||
if (sampleScriptInfo != null) {
|
if (python != null) {
|
||||||
script = sampleScriptInfo.getScript();
|
String result = null;
|
||||||
|
SampleTextExecutor task = new SampleTextExecutor(stationData);
|
||||||
Object result = script.executePlotDelegateMethod("isValid",
|
try {
|
||||||
"rec", stationData);
|
result = python.submitSyncJob(task);
|
||||||
if (result instanceof Boolean
|
} catch (Exception e) {
|
||||||
&& ((Boolean) result).booleanValue()) {
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
result = script.executePlotDelegateMethod("getSampleText",
|
"Error getting sample text for plot model "
|
||||||
"rec", stationData);
|
+ getPlotModelFilename(), e);
|
||||||
if (result instanceof String) {
|
} finally {
|
||||||
sampleMessage.append((String) result);
|
if (result != null) {
|
||||||
|
sampleMessage.append(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -736,11 +739,8 @@ public class PlotModelFactory2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// TODO
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
"Error generating sample text with " + plotModelFile, e);
|
||||||
} catch (JepException e) {
|
|
||||||
// TODO Auto-generated catch block. Please revise as appropriate.
|
|
||||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String message = sampleMessage.toString();
|
String message = sampleMessage.toString();
|
||||||
|
@ -752,7 +752,7 @@ public class PlotModelFactory2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addToImageId(PlotData stationData, String parameters,
|
private void addToImageId(PlotData stationData, String parameters,
|
||||||
StringBuffer imageId) {
|
StringBuilder imageId) {
|
||||||
for (String parameter : parameters.split(",")) {
|
for (String parameter : parameters.split(",")) {
|
||||||
switch (stationData.getType(parameter)) {
|
switch (stationData.getType(parameter)) {
|
||||||
case STRING:
|
case STRING:
|
||||||
|
@ -809,6 +809,7 @@ public class PlotModelFactory2 {
|
||||||
Formatter testing = new Formatter(sb);
|
Formatter testing = new Formatter(sb);
|
||||||
testing.format(element.format, displayValue);
|
testing.format(element.format, displayValue);
|
||||||
sValue = sb.toString();
|
sValue = sb.toString();
|
||||||
|
testing.close();
|
||||||
} else {
|
} else {
|
||||||
sValue = Double.toString(displayValue);
|
sValue = Double.toString(displayValue);
|
||||||
}
|
}
|
||||||
|
@ -1073,6 +1074,7 @@ public class PlotModelFactory2 {
|
||||||
Formatter testing = new Formatter(sb);
|
Formatter testing = new Formatter(sb);
|
||||||
testing.format(element.format, displayValue);
|
testing.format(element.format, displayValue);
|
||||||
sValue = sb.toString();
|
sValue = sb.toString();
|
||||||
|
testing.close();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sValue = Double.toString(displayValue);
|
sValue = Double.toString(displayValue);
|
||||||
|
@ -1138,6 +1140,7 @@ public class PlotModelFactory2 {
|
||||||
Formatter testing = new Formatter(sb);
|
Formatter testing = new Formatter(sb);
|
||||||
testing.format(element.format, displayValue);
|
testing.format(element.format, displayValue);
|
||||||
sValue = sb.toString();
|
sValue = sb.toString();
|
||||||
|
testing.close();
|
||||||
} else {
|
} else {
|
||||||
sValue = Double.toString(displayValue);
|
sValue = Double.toString(displayValue);
|
||||||
}
|
}
|
||||||
|
@ -1197,8 +1200,8 @@ public class PlotModelFactory2 {
|
||||||
return major * 5;
|
return major * 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized List<PlotModelElement> getPlotFields() {
|
public List<PlotModelElement> getPlotFields() {
|
||||||
return this.plotFields;
|
return Collections.unmodifiableList(this.plotFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1244,140 +1247,6 @@ public class PlotModelFactory2 {
|
||||||
this.plotMissingData = b;
|
this.plotMissingData = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disposeScript() {
|
|
||||||
if (scriptInfo != null) {
|
|
||||||
try {
|
|
||||||
scriptInfo.disposeScript();
|
|
||||||
} catch (JepException e) {
|
|
||||||
statusHandler.handle(Priority.ERROR,
|
|
||||||
"Error disposing plot model script", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disposeSampleScript() {
|
|
||||||
if (sampleScriptInfo != null) {
|
|
||||||
try {
|
|
||||||
sampleScriptInfo.disposeScript();
|
|
||||||
} catch (JepException e) {
|
|
||||||
statusHandler.handle(Priority.ERROR,
|
|
||||||
"Error disposing plot model sample script", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ScriptInfo {
|
|
||||||
public String plotDelegateName;
|
|
||||||
|
|
||||||
public String scriptText;
|
|
||||||
|
|
||||||
private PlotPythonScript script;
|
|
||||||
|
|
||||||
private Thread scriptThread;
|
|
||||||
|
|
||||||
public PlotPythonScript getScript() throws JepException {
|
|
||||||
if (script != null) {
|
|
||||||
if (Thread.currentThread() == scriptThread) {
|
|
||||||
return script;
|
|
||||||
} else {
|
|
||||||
statusHandler.handle(Priority.ERROR,
|
|
||||||
"Plot model scripting was not properly disposed.");
|
|
||||||
script = null;
|
|
||||||
scriptThread = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
script = createScript();
|
|
||||||
scriptThread = Thread.currentThread();
|
|
||||||
return script;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disposeScript() throws JepException {
|
|
||||||
if (script != null) {
|
|
||||||
try {
|
|
||||||
if (Thread.currentThread() == scriptThread) {
|
|
||||||
script.dispose();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
script = null;
|
|
||||||
scriptThread = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private PlotPythonScript createScript() throws JepException {
|
|
||||||
synchronized (PlotModelFactory2.class) {
|
|
||||||
if (cachedIncludePath == null) {
|
|
||||||
IPathManager pm = PathManagerFactory.getPathManager();
|
|
||||||
LocalizationFile[] files = pm
|
|
||||||
.listFiles(
|
|
||||||
pm.getLocalSearchHierarchy(LocalizationType.CAVE_STATIC),
|
|
||||||
PLOT_MODEL_DIR, null, false, false);
|
|
||||||
StringBuilder includePath = new StringBuilder();
|
|
||||||
for (LocalizationFile lf : files) {
|
|
||||||
if (lf.exists() && lf.isDirectory()) {
|
|
||||||
if (includePath.length() > 0) {
|
|
||||||
includePath.append(File.pathSeparator);
|
|
||||||
}
|
|
||||||
includePath.append(lf.getFile().getAbsolutePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cachedIncludePath = includePath.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File baseFile = PathManagerFactory.getPathManager().getStaticFile(
|
|
||||||
PLOT_MODEL_DIR + IPathManager.SEPARATOR
|
|
||||||
+ "PlotModelInterface.py");
|
|
||||||
PlotPythonScript localScript = new PlotPythonScript(
|
|
||||||
baseFile.getAbsolutePath(), cachedIncludePath,
|
|
||||||
plotDelegateName);
|
|
||||||
|
|
||||||
if (scriptText != null) {
|
|
||||||
localScript.evaluate(scriptText);
|
|
||||||
}
|
|
||||||
localScript.executePlotDelegateMethod("init", "plotModelFactory",
|
|
||||||
PlotModelFactory2.this);
|
|
||||||
return localScript;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PlotPythonScript extends PythonScript {
|
|
||||||
|
|
||||||
private static String CHEAT_RUN = "_cheat_run";
|
|
||||||
|
|
||||||
private String plotDelegateName;
|
|
||||||
|
|
||||||
public PlotPythonScript(String filePath, String anIncludePath,
|
|
||||||
String plotDelegateName) throws JepException {
|
|
||||||
super(filePath, anIncludePath, PlotPythonScript.class
|
|
||||||
.getClassLoader());
|
|
||||||
jep.eval("def "
|
|
||||||
+ CHEAT_RUN
|
|
||||||
+ "(text):\n return eval(compile(text,'string','exec'),globals(),globals())");
|
|
||||||
this.plotDelegateName = plotDelegateName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object evaluate(String script) throws JepException {
|
|
||||||
Object result = jep.invoke(CHEAT_RUN, script);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object executePlotDelegateMethod(String methodName,
|
|
||||||
String argName, Object argValue) throws JepException {
|
|
||||||
if (plotDelegateName != null) {
|
|
||||||
HashMap<String, Object> map = null;
|
|
||||||
if (argName != null) {
|
|
||||||
map = new HashMap<String, Object>();
|
|
||||||
map.put(argName, argValue);
|
|
||||||
}
|
|
||||||
return execute(methodName, plotDelegateName, map);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private File getTableFile(String fileName) {
|
private File getTableFile(String fileName) {
|
||||||
File rval = PathManagerFactory.getPathManager().getStaticFile(
|
File rval = PathManagerFactory.getPathManager().getStaticFile(
|
||||||
PLOT_MODEL_DIR + IPathManager.SEPARATOR + fileName);
|
PLOT_MODEL_DIR + IPathManager.SEPARATOR + fileName);
|
||||||
|
@ -1385,10 +1254,24 @@ public class PlotModelFactory2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PlotModelElement> getSampleFields() {
|
public List<PlotModelElement> getSampleFields() {
|
||||||
return this.sampleFields;
|
return Collections.unmodifiableList(this.sampleFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCachingImages() {
|
public boolean isCachingImages() {
|
||||||
return imageCache != null;
|
return imageCache != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPlotModelFilename() {
|
||||||
|
return this.plotModelFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of the plot model
|
||||||
|
*/
|
||||||
|
public void dispose() {
|
||||||
|
if (python != null) {
|
||||||
|
python.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**
|
||||||
|
* 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.pointdata.python;
|
||||||
|
|
||||||
|
import com.raytheon.viz.pointdata.PlotData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class for python plot delegates where the subclasses will implement
|
||||||
|
* IPythonExecutor<PlotPythonScript, R>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Mar 18, 2014 2868 njensen Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author njensen
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class AbstractPlotDelegateExecutor {
|
||||||
|
|
||||||
|
protected PlotData plotData;
|
||||||
|
|
||||||
|
public AbstractPlotDelegateExecutor(PlotData data) {
|
||||||
|
this.plotData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* 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.pointdata.python;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import jep.JepException;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
|
||||||
|
import com.raytheon.viz.pointdata.PlotData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task to check if the plot data is valid based on the python method isValid()
|
||||||
|
* extracted from the SVG file.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Mar 18, 2014 2868 njensen Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author njensen
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class CheckPlotValidityExecutor extends AbstractPlotDelegateExecutor
|
||||||
|
implements IPythonExecutor<PlotPythonScript, Boolean> {
|
||||||
|
|
||||||
|
public CheckPlotValidityExecutor(PlotData data) {
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean execute(PlotPythonScript script) throws JepException {
|
||||||
|
Map<String, Object> args = new HashMap<String, Object>();
|
||||||
|
args.put("rec", plotData);
|
||||||
|
return (Boolean) script.execute("isValid", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
/**
|
||||||
|
* 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.pointdata.python;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import jep.JepException;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.python.PythonScript;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A python interpreter that is expecting to receive and retain a multi-line
|
||||||
|
* script of plot delegate python extracted from a plot model SVG file.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Mar 14, 2014 2868 njensen Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author njensen
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PlotPythonScript extends PythonScript {
|
||||||
|
|
||||||
|
protected String plotDelegateName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param filePath
|
||||||
|
* the path to the plot model interface python
|
||||||
|
* @param anIncludePath
|
||||||
|
* the include path for relevant python modules
|
||||||
|
* @param scriptText
|
||||||
|
* the text of the python code extracted from the plot model svg
|
||||||
|
* @param plotDelegateName
|
||||||
|
* the instance name of the plot delegate
|
||||||
|
* @param svgFilename
|
||||||
|
* the name of the SVG file the python code came from, this is
|
||||||
|
* used in exception stacktraces
|
||||||
|
*
|
||||||
|
* @throws JepException
|
||||||
|
*/
|
||||||
|
public PlotPythonScript(String filePath, String anIncludePath,
|
||||||
|
String scriptText, String plotDelegateName, String svgFilename)
|
||||||
|
throws JepException {
|
||||||
|
super(filePath, anIncludePath, PlotPythonScript.class.getClassLoader());
|
||||||
|
/*
|
||||||
|
* jep.eval() won't evaluate more than a single line of python code,
|
||||||
|
* unless that first line is a python class or method definition, so we
|
||||||
|
* work around that by compiling it, then eval-ing it
|
||||||
|
*
|
||||||
|
* TODO contemplate building the workaround into PythonInterpreter,
|
||||||
|
* PythonScript, or PythonEval
|
||||||
|
*/
|
||||||
|
jep.set("scriptToRun", scriptText);
|
||||||
|
jep.eval("eval(compile(scriptToRun, '" + svgFilename + "', 'exec'))");
|
||||||
|
this.plotDelegateName = plotDelegateName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object execute(String methodName, Map<String, Object> args)
|
||||||
|
throws JepException {
|
||||||
|
return execute(methodName, plotDelegateName, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
/**
|
||||||
|
* 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.pointdata.python;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import jep.JepException;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.localization.IPathManager;
|
||||||
|
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||||
|
import com.raytheon.uf.common.localization.LocalizationFile;
|
||||||
|
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||||
|
import com.raytheon.uf.common.python.concurrent.AbstractPythonScriptFactory;
|
||||||
|
import com.raytheon.viz.pointdata.PlotModelFactory2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a plot delegate python script based on the script text extracted from
|
||||||
|
* a plot model SVG file. The name should be the name of the plot model SVG file
|
||||||
|
* to optimize reusing the interpreters across different resources that display
|
||||||
|
* the same plot model.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Mar 14, 2014 2868 njensen Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author njensen
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PlotPythonScriptFactory extends
|
||||||
|
AbstractPythonScriptFactory<PlotPythonScript> {
|
||||||
|
|
||||||
|
private static String includePath;
|
||||||
|
|
||||||
|
private static String baseFilePath;
|
||||||
|
|
||||||
|
protected String scriptText;
|
||||||
|
|
||||||
|
protected String plotDelegateName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param plotSvgName
|
||||||
|
* the name of the svg file that the python code was extracted
|
||||||
|
* from
|
||||||
|
* @param scriptText
|
||||||
|
* the python code that was extracted from the svg file
|
||||||
|
* @param plotDelegateName
|
||||||
|
* the name of the instance of the plot delegate inside the
|
||||||
|
* python code
|
||||||
|
*/
|
||||||
|
public PlotPythonScriptFactory(String plotSvgName, String scriptText,
|
||||||
|
String plotDelegateName) {
|
||||||
|
super(plotSvgName, 1);
|
||||||
|
this.scriptText = scriptText;
|
||||||
|
this.plotDelegateName = plotDelegateName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlotPythonScript createPythonScript() throws JepException {
|
||||||
|
synchronized (PlotPythonScriptFactory.class) {
|
||||||
|
if (includePath == null) {
|
||||||
|
IPathManager pm = PathManagerFactory.getPathManager();
|
||||||
|
LocalizationFile[] files = pm.listFiles(pm
|
||||||
|
.getLocalSearchHierarchy(LocalizationType.CAVE_STATIC),
|
||||||
|
PlotModelFactory2.PLOT_MODEL_DIR, null, false, false);
|
||||||
|
StringBuilder includeBuilder = new StringBuilder();
|
||||||
|
for (LocalizationFile lf : files) {
|
||||||
|
if (lf.exists() && lf.isDirectory()) {
|
||||||
|
if (includeBuilder.length() > 0) {
|
||||||
|
includeBuilder.append(File.pathSeparator);
|
||||||
|
}
|
||||||
|
includeBuilder.append(lf.getFile().getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
includePath = includeBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseFilePath == null) {
|
||||||
|
File baseFile = PathManagerFactory.getPathManager()
|
||||||
|
.getStaticFile(
|
||||||
|
PlotModelFactory2.PLOT_MODEL_DIR
|
||||||
|
+ IPathManager.SEPARATOR
|
||||||
|
+ "PlotModelInterface.py");
|
||||||
|
baseFilePath = baseFile.getAbsolutePath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PlotPythonScript(baseFilePath, includePath, scriptText,
|
||||||
|
plotDelegateName, this.getName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
* 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.pointdata.python;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import jep.JepException;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
|
||||||
|
import com.raytheon.viz.pointdata.PlotData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task to get the sample data text if the plot data is valid. Uses the python
|
||||||
|
* code of the plot delegate's isValid() and getSampleText() methods to get the
|
||||||
|
* sample text.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Mar 18, 2014 2868 njensen Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author njensen
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SampleTextExecutor extends AbstractPlotDelegateExecutor implements
|
||||||
|
IPythonExecutor<PlotPythonScript, String> {
|
||||||
|
|
||||||
|
public SampleTextExecutor(PlotData data) {
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String execute(PlotPythonScript script) throws JepException {
|
||||||
|
String result = null;
|
||||||
|
Map<String, Object> args = new HashMap<String, Object>();
|
||||||
|
args.put("rec", plotData);
|
||||||
|
Boolean isValid = (Boolean) script.execute("isValid", args);
|
||||||
|
if (isValid.booleanValue()) {
|
||||||
|
result = (String) script.execute("getSampleText", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -60,7 +60,6 @@ import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
|
||||||
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
|
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
|
||||||
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||||
import com.raytheon.viz.pointdata.PlotAlertParser;
|
import com.raytheon.viz.pointdata.PlotAlertParser;
|
||||||
import com.raytheon.viz.pointdata.PlotDataThreadPool;
|
|
||||||
import com.raytheon.viz.pointdata.PlotInfo;
|
import com.raytheon.viz.pointdata.PlotInfo;
|
||||||
import com.raytheon.viz.pointdata.drawables.IPointImageExtension;
|
import com.raytheon.viz.pointdata.drawables.IPointImageExtension;
|
||||||
import com.raytheon.viz.pointdata.drawables.IPointImageExtension.PointImage;
|
import com.raytheon.viz.pointdata.drawables.IPointImageExtension.PointImage;
|
||||||
|
@ -70,6 +69,7 @@ import com.raytheon.viz.pointdata.rsc.progdisc.DynamicProgDisclosure;
|
||||||
import com.raytheon.viz.pointdata.rsc.progdisc.SpiProgDisclosure;
|
import com.raytheon.viz.pointdata.rsc.progdisc.SpiProgDisclosure;
|
||||||
import com.raytheon.viz.pointdata.thread.GetDataTask;
|
import com.raytheon.viz.pointdata.thread.GetDataTask;
|
||||||
import com.raytheon.viz.pointdata.thread.GetDataTask.Params;
|
import com.raytheon.viz.pointdata.thread.GetDataTask.Params;
|
||||||
|
import com.raytheon.viz.pointdata.thread.PlotThreadOverseer;
|
||||||
import com.raytheon.viz.pointdata.units.PlotUnits;
|
import com.raytheon.viz.pointdata.units.PlotUnits;
|
||||||
import com.vividsolutions.jts.geom.Coordinate;
|
import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
|
||||||
|
@ -98,6 +98,7 @@ import com.vividsolutions.jts.geom.Coordinate;
|
||||||
* Jun 25, 2013 1869 bsteffen Fix plot sampling.
|
* Jun 25, 2013 1869 bsteffen Fix plot sampling.
|
||||||
* Sep 04, 2013 16519 kshresth Fix Metar Display Problem
|
* Sep 04, 2013 16519 kshresth Fix Metar Display Problem
|
||||||
* Dec 02, 2013 2473 njensen Prog Disclose paint frames at high priority
|
* Dec 02, 2013 2473 njensen Prog Disclose paint frames at high priority
|
||||||
|
* Mar 21, 2014 2868 njensen Use PlotThreadOverseer for increased efficiency
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -116,7 +117,7 @@ public class PlotResource2 extends
|
||||||
|
|
||||||
private AbstractProgDisclosure progressiveDisclosure;
|
private AbstractProgDisclosure progressiveDisclosure;
|
||||||
|
|
||||||
private PlotDataThreadPool generator;
|
private PlotThreadOverseer generator;
|
||||||
|
|
||||||
private double plotWidth;
|
private double plotWidth;
|
||||||
|
|
||||||
|
@ -265,7 +266,7 @@ public class PlotResource2 extends
|
||||||
Map<String, RequestConstraint> request = resourceData.getMetadataMap();
|
Map<String, RequestConstraint> request = resourceData.getMetadataMap();
|
||||||
RequestConstraint plugin = request.get("pluginName");
|
RequestConstraint plugin = request.get("pluginName");
|
||||||
PlotUnits.register();
|
PlotUnits.register();
|
||||||
generator = new PlotDataThreadPool(aTarget, descriptor,
|
generator = new PlotThreadOverseer(aTarget, descriptor,
|
||||||
this.resourceData.getPlotModelFile(),
|
this.resourceData.getPlotModelFile(),
|
||||||
this.resourceData.getLevelKey(), plugin.getConstraintValue(),
|
this.resourceData.getLevelKey(), plugin.getConstraintValue(),
|
||||||
this.resourceData.getMetadataMap(), this);
|
this.resourceData.getMetadataMap(), this);
|
||||||
|
@ -279,7 +280,7 @@ public class PlotResource2 extends
|
||||||
this.generator.setPlotMissingData(resourceData.isPlotMissingData());
|
this.generator.setPlotMissingData(resourceData.isPlotMissingData());
|
||||||
this.generator.setLowerLimit(resourceData.getLowerLimit());
|
this.generator.setLowerLimit(resourceData.getLowerLimit());
|
||||||
this.generator.setUpperLimit(resourceData.getUpperLimit());
|
this.generator.setUpperLimit(resourceData.getUpperLimit());
|
||||||
this.plotWidth = generator.getPlotModelWidth();
|
this.plotWidth = generator.getOriginalPlotModelWidth();
|
||||||
this.plotWidth *= getCapability(MagnificationCapability.class)
|
this.plotWidth *= getCapability(MagnificationCapability.class)
|
||||||
.getMagnification();
|
.getMagnification();
|
||||||
generator.setPlotModelSize(Math.round(plotWidth));
|
generator.setPlotModelSize(Math.round(plotWidth));
|
||||||
|
@ -431,7 +432,7 @@ public class PlotResource2 extends
|
||||||
list.add(samplePlot);
|
list.add(samplePlot);
|
||||||
Params params = Params.PLOT_AND_SAMPLE;
|
Params params = Params.PLOT_AND_SAMPLE;
|
||||||
GetDataTask task = new GetDataTask(list, params);
|
GetDataTask task = new GetDataTask(list, params);
|
||||||
generator.queueStation(task);
|
generator.enqueueDataRetrieval(task);
|
||||||
// End DR14996
|
// End DR14996
|
||||||
}
|
}
|
||||||
boolean dup = false;
|
boolean dup = false;
|
||||||
|
@ -575,7 +576,7 @@ public class PlotResource2 extends
|
||||||
params = Params.SAMPLE_ONLY;
|
params = Params.SAMPLE_ONLY;
|
||||||
}
|
}
|
||||||
GetDataTask task = new GetDataTask(list, params);
|
GetDataTask task = new GetDataTask(list, params);
|
||||||
generator.queueStation(task);
|
generator.enqueueDataRetrieval(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,7 +617,7 @@ public class PlotResource2 extends
|
||||||
}
|
}
|
||||||
} else if (object instanceof MagnificationCapability) {
|
} else if (object instanceof MagnificationCapability) {
|
||||||
if (generator != null) {
|
if (generator != null) {
|
||||||
this.plotWidth = generator.getPlotModelWidth();
|
this.plotWidth = generator.getOriginalPlotModelWidth();
|
||||||
this.plotWidth *= getCapability(
|
this.plotWidth *= getCapability(
|
||||||
MagnificationCapability.class).getMagnification();
|
MagnificationCapability.class).getMagnification();
|
||||||
generator.setPlotModelSize(Math.round(plotWidth));
|
generator.setPlotModelSize(Math.round(plotWidth));
|
||||||
|
@ -758,7 +759,7 @@ public class PlotResource2 extends
|
||||||
}
|
}
|
||||||
if (toQueue.size() > 0) {
|
if (toQueue.size() > 0) {
|
||||||
GetDataTask task = new GetDataTask(toQueue, Params.PLOT_ONLY);
|
GetDataTask task = new GetDataTask(toQueue, Params.PLOT_ONLY);
|
||||||
generator.queueStation(task);
|
generator.enqueueDataRetrieval(task);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
issueRefresh();
|
issueRefresh();
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
* 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.pointdata.thread;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
|
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract job associated with one of the many details of plot creation.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Mar 21, 2014 2868 njensen Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author njensen
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class AbstractPlotCreationJob extends Job {
|
||||||
|
|
||||||
|
protected static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
|
.getHandler(PlotModelDataRequestJob.class);
|
||||||
|
|
||||||
|
protected PlotThreadOverseer overseer;
|
||||||
|
|
||||||
|
protected IPlotModelGeneratorCaller listener;
|
||||||
|
|
||||||
|
public AbstractPlotCreationJob(String name, PlotThreadOverseer parent,
|
||||||
|
IPlotModelGeneratorCaller caller) {
|
||||||
|
super(name);
|
||||||
|
this.overseer = parent;
|
||||||
|
this.listener = caller;
|
||||||
|
this.setSystem(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDone() {
|
||||||
|
return getState() != Job.RUNNING && getState() != Job.WAITING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shutdown() {
|
||||||
|
return super.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,7 +24,8 @@ import java.util.List;
|
||||||
import com.raytheon.viz.pointdata.PlotInfo;
|
import com.raytheon.viz.pointdata.PlotInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO Add Description
|
* A task to retrieve plot data for a set of stations, possibly requesting the
|
||||||
|
* parameters necessary for the plot image or the sample text or both.
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
|
@ -33,6 +34,7 @@ import com.raytheon.viz.pointdata.PlotInfo;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Jul 18, 2011 njensen Initial creation
|
* Jul 18, 2011 njensen Initial creation
|
||||||
|
* Mar 21, 2014 2868 njensen Improved javadoc
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
* further licensing information.
|
* further licensing information.
|
||||||
**/
|
**/
|
||||||
package com.raytheon.viz.pointdata;
|
package com.raytheon.viz.pointdata.thread;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -27,30 +27,25 @@ import java.util.Map;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.core.runtime.jobs.Job;
|
|
||||||
import org.eclipse.swt.graphics.RGB;
|
|
||||||
|
|
||||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
|
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
|
||||||
import com.raytheon.uf.common.pointdata.PointDataContainer;
|
import com.raytheon.uf.common.pointdata.PointDataContainer;
|
||||||
import com.raytheon.uf.common.pointdata.PointDataView;
|
import com.raytheon.uf.common.pointdata.PointDataView;
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
|
||||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
import com.raytheon.uf.common.time.DataTime;
|
import com.raytheon.uf.common.time.DataTime;
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
|
|
||||||
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
|
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.uf.viz.core.map.IMapDescriptor;
|
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||||
|
import com.raytheon.viz.pointdata.PlotData;
|
||||||
|
import com.raytheon.viz.pointdata.PlotInfo;
|
||||||
import com.raytheon.viz.pointdata.PlotModelFactory2.PlotModelElement;
|
import com.raytheon.viz.pointdata.PlotModelFactory2.PlotModelElement;
|
||||||
|
import com.raytheon.viz.pointdata.PointDataRequest;
|
||||||
import com.raytheon.viz.pointdata.rsc.PlotResourceData;
|
import com.raytheon.viz.pointdata.rsc.PlotResourceData;
|
||||||
import com.raytheon.viz.pointdata.thread.GetDataTask;
|
|
||||||
import com.raytheon.viz.pointdata.thread.PlotSampleGeneratorJob;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Job separated from PlotModelGenerator2 that requests plot data and passes it
|
* Job that requests plot data based on a constraintMap and the parameters
|
||||||
* on to the PlotModelGeneratorJob.
|
* specified inside the plot model SVG file.
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
|
@ -60,6 +55,7 @@ import com.raytheon.viz.pointdata.thread.PlotSampleGeneratorJob;
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Apr 22, 2011 njensen Initial creation
|
* Apr 22, 2011 njensen Initial creation
|
||||||
* May 14, 2013 1869 bsteffen Get plots working without dataURI
|
* May 14, 2013 1869 bsteffen Get plots working without dataURI
|
||||||
|
* Mar 21, 2014 2868 njensen Major refactor
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -67,53 +63,42 @@ import com.raytheon.viz.pointdata.thread.PlotSampleGeneratorJob;
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class PlotModelDataRequestJob extends Job {
|
public class PlotModelDataRequestJob extends AbstractPlotCreationJob {
|
||||||
|
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
|
||||||
.getHandler(PlotModelDataRequestJob.class);
|
|
||||||
|
|
||||||
private PlotModelFactory2 plotCreator;
|
|
||||||
|
|
||||||
private Map<String, RequestConstraint> constraintMap;
|
private Map<String, RequestConstraint> constraintMap;
|
||||||
|
|
||||||
private String plugin;
|
private final String plugin;
|
||||||
|
|
||||||
private String levelKey;
|
private final String levelKey;
|
||||||
|
|
||||||
private PlotModelGeneratorJob generatorJob;
|
private final List<PlotModelElement> plotFields;
|
||||||
|
|
||||||
private PlotSampleGeneratorJob sampleJob;
|
private final List<PlotModelElement> sampleFields;
|
||||||
|
|
||||||
private PlotDataThreadPool parent;
|
public PlotModelDataRequestJob(PlotThreadOverseer parent,
|
||||||
|
IPlotModelGeneratorCaller caller,
|
||||||
public PlotModelDataRequestJob(IGraphicsTarget aTarget,
|
List<PlotModelElement> plotFields,
|
||||||
IMapDescriptor mapDescriptor, String plotModelFile,
|
List<PlotModelElement> sampleFields, String levelKey,
|
||||||
String levelKey, String plugin,
|
String plugin, Map<String, RequestConstraint> constraintMap)
|
||||||
Map<String, RequestConstraint> constraintMap,
|
|
||||||
IPlotModelGeneratorCaller caller, PlotDataThreadPool parent)
|
|
||||||
throws VizException {
|
throws VizException {
|
||||||
super("Requesting Plot Data...");
|
super("Requesting Plot Data...", parent, caller);
|
||||||
plotCreator = new PlotModelFactory2(mapDescriptor, plotModelFile);
|
this.plotFields = plotFields;
|
||||||
|
this.sampleFields = sampleFields;
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.levelKey = levelKey;
|
this.levelKey = levelKey;
|
||||||
this.constraintMap = constraintMap;
|
this.constraintMap = constraintMap;
|
||||||
this.generatorJob = new PlotModelGeneratorJob(plotCreator, caller,
|
|
||||||
aTarget);
|
|
||||||
this.generatorJob.setSystem(false);
|
|
||||||
this.sampleJob = new PlotSampleGeneratorJob(plotCreator, caller);
|
|
||||||
this.sampleJob.setSystem(false);
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IStatus run(IProgressMonitor monitor) {
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
while (parent.stationQueue.size() > 0) {
|
while (overseer.dataRetrievalQueue.size() > 0) {
|
||||||
List<PlotInfo[]> stationQuery = new ArrayList<PlotInfo[]>();
|
List<PlotInfo[]> stationQuery = new ArrayList<PlotInfo[]>();
|
||||||
|
|
||||||
GetDataTask task = null;
|
GetDataTask task = null;
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
task = parent.stationQueue.poll();
|
task = overseer.dataRetrievalQueue.poll();
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
|
// possibility another thread got it first
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
List<PlotInfo[]> batch = task.getStations();
|
List<PlotInfo[]> batch = task.getStations();
|
||||||
|
@ -125,15 +110,15 @@ public class PlotModelDataRequestJob extends Job {
|
||||||
List<PlotModelElement> pme = null;
|
List<PlotModelElement> pme = null;
|
||||||
switch (task.getRequestType()) {
|
switch (task.getRequestType()) {
|
||||||
case PLOT_ONLY:
|
case PLOT_ONLY:
|
||||||
pme = this.plotCreator.getPlotFields();
|
pme = plotFields;
|
||||||
break;
|
break;
|
||||||
case SAMPLE_ONLY:
|
case SAMPLE_ONLY:
|
||||||
pme = this.plotCreator.getSampleFields();
|
pme = sampleFields;
|
||||||
break;
|
break;
|
||||||
case PLOT_AND_SAMPLE:
|
case PLOT_AND_SAMPLE:
|
||||||
pme = new ArrayList<PlotModelElement>();
|
pme = new ArrayList<PlotModelElement>();
|
||||||
pme.addAll(this.plotCreator.getPlotFields());
|
pme.addAll(plotFields);
|
||||||
pme.addAll(this.plotCreator.getSampleFields());
|
pme.addAll(sampleFields);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -161,14 +146,14 @@ public class PlotModelDataRequestJob extends Job {
|
||||||
if (infos[0].pdv != null) {
|
if (infos[0].pdv != null) {
|
||||||
switch (task.getRequestType()) {
|
switch (task.getRequestType()) {
|
||||||
case PLOT_ONLY:
|
case PLOT_ONLY:
|
||||||
this.generatorJob.enqueue(infos);
|
overseer.enqueueImageGeneration(infos);
|
||||||
break;
|
break;
|
||||||
case SAMPLE_ONLY:
|
case SAMPLE_ONLY:
|
||||||
this.sampleJob.enqueue(infos);
|
overseer.enqueueSamplePlot(infos);
|
||||||
break;
|
break;
|
||||||
case PLOT_AND_SAMPLE:
|
case PLOT_AND_SAMPLE:
|
||||||
this.generatorJob.enqueue(infos);
|
overseer.enqueueImageGeneration(infos);
|
||||||
this.sampleJob.enqueue(infos);
|
overseer.enqueueSamplePlot(infos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,12 +171,13 @@ public class PlotModelDataRequestJob extends Job {
|
||||||
List<String> params = new ArrayList<String>();
|
List<String> params = new ArrayList<String>();
|
||||||
|
|
||||||
for (PlotModelElement p : pme) {
|
for (PlotModelElement p : pme) {
|
||||||
if (!p.parameter.equals("") && !p.parameter.contains(",")) {
|
String param = p.getParameter();
|
||||||
params.add(p.parameter);
|
if (!param.equals("") && !param.contains(",")) {
|
||||||
} else if (p.parameter.contains(",")) {
|
params.add(param);
|
||||||
String[] individualParams = p.parameter.split(",");
|
} else if (param.contains(",")) {
|
||||||
for (String param : individualParams) {
|
String[] individualParams = param.split(",");
|
||||||
params.add(param);
|
for (String paramToRequest : individualParams) {
|
||||||
|
params.add(paramToRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,7 +186,7 @@ public class PlotModelDataRequestJob extends Job {
|
||||||
.getPluginProperties(plugin).hasDistinctStationId;
|
.getPluginProperties(plugin).hasDistinctStationId;
|
||||||
String uniquePointDataKey = "stationId";
|
String uniquePointDataKey = "stationId";
|
||||||
String uniqueQueryKey = "location.stationId";
|
String uniqueQueryKey = "location.stationId";
|
||||||
if(!hasDistinctStationId){
|
if (!hasDistinctStationId) {
|
||||||
uniquePointDataKey = "dataURI";
|
uniquePointDataKey = "dataURI";
|
||||||
uniqueQueryKey = uniquePointDataKey;
|
uniqueQueryKey = uniquePointDataKey;
|
||||||
|
|
||||||
|
@ -208,7 +194,7 @@ public class PlotModelDataRequestJob extends Job {
|
||||||
if (!params.contains(uniquePointDataKey)) {
|
if (!params.contains(uniquePointDataKey)) {
|
||||||
params.add(uniquePointDataKey);
|
params.add(uniquePointDataKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, RequestConstraint> map = new HashMap<String, RequestConstraint>();
|
Map<String, RequestConstraint> map = new HashMap<String, RequestConstraint>();
|
||||||
map.putAll(this.constraintMap);
|
map.putAll(this.constraintMap);
|
||||||
RequestConstraint rc = new RequestConstraint();
|
RequestConstraint rc = new RequestConstraint();
|
||||||
|
@ -221,7 +207,7 @@ public class PlotModelDataRequestJob extends Job {
|
||||||
String key = null;
|
String key = null;
|
||||||
if (hasDistinctStationId) {
|
if (hasDistinctStationId) {
|
||||||
key = info.stationId;
|
key = info.stationId;
|
||||||
}else{
|
} else {
|
||||||
key = info.dataURI;
|
key = info.dataURI;
|
||||||
}
|
}
|
||||||
str.add(key);
|
str.add(key);
|
||||||
|
@ -347,50 +333,4 @@ public class PlotModelDataRequestJob extends Job {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUpperLimit(double upperLimit) {
|
|
||||||
this.plotCreator.setUpperLimit(upperLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLowerLimit(double lowerLimit) {
|
|
||||||
this.plotCreator.setLowerLimit(lowerLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPlotModelWidth() {
|
|
||||||
return this.plotCreator.getDefinedPlotModelWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlotModelSize(long width) {
|
|
||||||
this.plotCreator.setPlotDimensions(width, width);
|
|
||||||
this.generatorJob.clearImageCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlotModelColor(RGB color) {
|
|
||||||
this.plotCreator.setColor(color);
|
|
||||||
// this.generatorJob.cleanImages();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlotModelLineWidth(int width) {
|
|
||||||
this.plotCreator.setLineWidth(width);
|
|
||||||
this.generatorJob.clearImageCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlotModelLineStyle(LineStyle style) {
|
|
||||||
this.plotCreator.setLineStyle(style);
|
|
||||||
this.generatorJob.clearImageCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlotMissingData(boolean b) {
|
|
||||||
this.plotCreator.setPlotMissingData(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDone() {
|
|
||||||
return getState() != Job.RUNNING && getState() != Job.WAITING
|
|
||||||
&& generatorJob.isDone();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void shutdown() {
|
|
||||||
this.cancel();
|
|
||||||
this.generatorJob.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -17,29 +17,28 @@
|
||||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
* further licensing information.
|
* further licensing information.
|
||||||
**/
|
**/
|
||||||
package com.raytheon.viz.pointdata;
|
package com.raytheon.viz.pointdata.thread;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.RenderedImage;
|
import java.awt.image.RenderedImage;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
|
|
||||||
import org.apache.commons.collections.map.LRUMap;
|
import org.apache.commons.collections.map.LRUMap;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.core.runtime.jobs.Job;
|
|
||||||
|
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||||
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
||||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||||
import com.raytheon.uf.viz.core.drawables.ext.ISingleColorImageExtension;
|
import com.raytheon.uf.viz.core.drawables.ext.ISingleColorImageExtension;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
|
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||||
|
import com.raytheon.viz.pointdata.PlotInfo;
|
||||||
|
import com.raytheon.viz.pointdata.PlotModelFactory2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Job separated from PlotModelGenerator2 that creates the plot images.
|
* Job that generates plot images using a PlotModelFactory2.
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
|
@ -48,6 +47,7 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Apr 22, 2011 njensen Initial creation
|
* Apr 22, 2011 njensen Initial creation
|
||||||
|
* Mar 21, 2014 2868 njensen Major refactor
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -55,27 +55,20 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class PlotModelGeneratorJob extends Job {
|
public class PlotModelGeneratorJob extends AbstractPlotCreationJob {
|
||||||
|
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
|
||||||
.getHandler(PlotModelDataRequestJob.class);
|
|
||||||
|
|
||||||
private ConcurrentLinkedQueue<PlotInfo[]> taskQueue = new ConcurrentLinkedQueue<PlotInfo[]>();
|
|
||||||
|
|
||||||
private PlotModelFactory2 plotCreator;
|
private PlotModelFactory2 plotCreator;
|
||||||
|
|
||||||
private IPlotModelGeneratorCaller caller;
|
|
||||||
|
|
||||||
private IGraphicsTarget target;
|
private IGraphicsTarget target;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Map<BufferedImage, IImage> imageCache = new LRUMap(1000);
|
private Map<BufferedImage, IImage> imageCache = new LRUMap(1000);
|
||||||
|
|
||||||
protected PlotModelGeneratorJob(PlotModelFactory2 plotCreator,
|
protected PlotModelGeneratorJob(PlotThreadOverseer parent,
|
||||||
IPlotModelGeneratorCaller caller, IGraphicsTarget target) {
|
IPlotModelGeneratorCaller caller, PlotModelFactory2 plotCreator,
|
||||||
super("Creating plots");
|
IGraphicsTarget target) {
|
||||||
|
super("Creating plots", parent, caller);
|
||||||
this.plotCreator = plotCreator;
|
this.plotCreator = plotCreator;
|
||||||
this.caller = caller;
|
|
||||||
this.target = target;
|
this.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,9 +81,14 @@ public class PlotModelGeneratorJob extends Job {
|
||||||
@Override
|
@Override
|
||||||
protected IStatus run(IProgressMonitor monitor) {
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
long t0 = System.currentTimeMillis();
|
long t0 = System.currentTimeMillis();
|
||||||
while (!taskQueue.isEmpty()) {
|
long count = 0;
|
||||||
|
while (!overseer.imageCreationQueue.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
PlotInfo[] infos = taskQueue.poll();
|
PlotInfo[] infos = overseer.imageCreationQueue.poll();
|
||||||
|
if (infos == null) {
|
||||||
|
// possibility another thread got it first
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final BufferedImage bImage = plotCreator.getStationPlot(
|
final BufferedImage bImage = plotCreator.getStationPlot(
|
||||||
infos[0].pdv, infos[0].latitude, infos[0].longitude);
|
infos[0].pdv, infos[0].latitude, infos[0].longitude);
|
||||||
IImage image = null;
|
IImage image = null;
|
||||||
|
@ -120,46 +118,40 @@ public class PlotModelGeneratorJob extends Job {
|
||||||
}
|
}
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (monitor.isCanceled()) {
|
if (monitor.isCanceled()) {
|
||||||
if(image != null){
|
if (image != null) {
|
||||||
image.dispose();
|
image.dispose();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
caller.modelGenerated(infos, image);
|
count++;
|
||||||
|
listener.modelGenerated(infos, image);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
statusHandler.error("Error creating plot", e);
|
statusHandler.error("Error creating plot with plotModel "
|
||||||
|
+ plotCreator.getPlotModelFilename(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plotCreator.disposeScript();
|
if (count > 0) {
|
||||||
System.out.println("Time spent creating plots: "
|
/*
|
||||||
+ (System.currentTimeMillis() - t0));
|
* if count is zero it means by the time this job was scheduled and
|
||||||
return Status.OK_STATUS;
|
* run, a different job took care of everything on the queue
|
||||||
}
|
*/
|
||||||
|
System.out.println("Time spent creating " + count + " plots: "
|
||||||
protected void enqueue(PlotInfo[] task) {
|
+ (System.currentTimeMillis() - t0));
|
||||||
this.taskQueue.add(task);
|
|
||||||
if (this.getState() != Job.RUNNING) {
|
|
||||||
this.schedule();
|
|
||||||
}
|
}
|
||||||
}
|
return Status.OK_STATUS;
|
||||||
|
|
||||||
protected int getQueueSize() {
|
|
||||||
return taskQueue.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void clearImageCache() {
|
protected void clearImageCache() {
|
||||||
imageCache.clear();
|
imageCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDone() {
|
@Override
|
||||||
return getState() != Job.RUNNING && getState() != Job.WAITING;
|
public boolean shutdown() {
|
||||||
}
|
boolean result = super.shutdown();
|
||||||
|
|
||||||
protected synchronized void shutdown() {
|
|
||||||
cancel();
|
|
||||||
taskQueue.clear();
|
|
||||||
clearImageCache();
|
clearImageCache();
|
||||||
|
plotCreator.dispose();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,22 +19,17 @@
|
||||||
**/
|
**/
|
||||||
package com.raytheon.viz.pointdata.thread;
|
package com.raytheon.viz.pointdata.thread;
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
|
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.core.runtime.jobs.Job;
|
|
||||||
|
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
|
||||||
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||||
import com.raytheon.viz.pointdata.PlotInfo;
|
import com.raytheon.viz.pointdata.PlotInfo;
|
||||||
import com.raytheon.viz.pointdata.PlotModelFactory2;
|
import com.raytheon.viz.pointdata.PlotModelFactory2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Job that uses the provided factory to generate a sampling message for a
|
* Job that uses the provided plot model factory to generate a sampling message
|
||||||
* particular plot.
|
* for a particular plot.
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
|
@ -44,6 +39,7 @@ import com.raytheon.viz.pointdata.PlotModelFactory2;
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Jul 13, 2011 njensen Initial creation
|
* Jul 13, 2011 njensen Initial creation
|
||||||
* Jun 25, 2013 1869 bsteffen Fix plot sampling.
|
* Jun 25, 2013 1869 bsteffen Fix plot sampling.
|
||||||
|
* Mar 21, 2014 2868 njensen Major refactor
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -51,22 +47,14 @@ import com.raytheon.viz.pointdata.PlotModelFactory2;
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class PlotSampleGeneratorJob extends Job {
|
public class PlotSampleGeneratorJob extends AbstractPlotCreationJob {
|
||||||
|
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
|
||||||
.getHandler(PlotSampleGeneratorJob.class);
|
|
||||||
|
|
||||||
private PlotModelFactory2 plotFactory;
|
private PlotModelFactory2 plotFactory;
|
||||||
|
|
||||||
private ConcurrentLinkedQueue<PlotInfo[]> queue = new ConcurrentLinkedQueue<PlotInfo[]>();
|
public PlotSampleGeneratorJob(PlotThreadOverseer parent,
|
||||||
|
IPlotModelGeneratorCaller caller, PlotModelFactory2 factory) {
|
||||||
private IPlotModelGeneratorCaller caller;
|
super("Generating samples", parent, caller);
|
||||||
|
|
||||||
public PlotSampleGeneratorJob(PlotModelFactory2 factory,
|
|
||||||
IPlotModelGeneratorCaller caller) {
|
|
||||||
super("Generating samples");
|
|
||||||
this.plotFactory = factory;
|
this.plotFactory = factory;
|
||||||
this.caller = caller;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -77,27 +65,29 @@ public class PlotSampleGeneratorJob extends Job {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected IStatus run(IProgressMonitor monitor) {
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
while (!queue.isEmpty()) {
|
while (!overseer.sampleTextQueue.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
PlotInfo[] infos = queue.poll();
|
PlotInfo[] infos = overseer.sampleTextQueue.poll();
|
||||||
|
if (infos == null) {
|
||||||
|
// possibility another thread got it first
|
||||||
|
continue;
|
||||||
|
}
|
||||||
String message = plotFactory.getStationMessage(infos[0].pdv,
|
String message = plotFactory.getStationMessage(infos[0].pdv,
|
||||||
infos[0].dataURI);
|
infos[0].dataURI);
|
||||||
|
listener.messageGenerated(infos, message);
|
||||||
caller.messageGenerated(infos, message);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
statusHandler.error("Error creating plot", e);
|
statusHandler.error("Error creating sample with plotModel "
|
||||||
|
+ plotFactory.getPlotModelFilename(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plotFactory.disposeSampleScript();
|
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enqueue(PlotInfo[] task) {
|
@Override
|
||||||
this.queue.add(task);
|
public boolean shutdown() {
|
||||||
if (this.getState() != Job.RUNNING) {
|
boolean result = super.shutdown();
|
||||||
this.schedule();
|
plotFactory.dispose();
|
||||||
}
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,365 @@
|
||||||
|
/**
|
||||||
|
* 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.pointdata.thread;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
import org.eclipse.swt.graphics.RGB;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||||
|
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||||
|
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
|
||||||
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
|
import com.raytheon.uf.viz.core.map.MapDescriptor;
|
||||||
|
import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
|
||||||
|
import com.raytheon.viz.pointdata.PlotInfo;
|
||||||
|
import com.raytheon.viz.pointdata.PlotModelFactory2;
|
||||||
|
import com.raytheon.viz.pointdata.PlotModelFactory2.PlotModelElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Oversees a variety of threads used to concurrently and quickly get plots on
|
||||||
|
* screen. There should be only one PlotThreadOverseer for each PlotResource2.
|
||||||
|
*
|
||||||
|
* This class oversees the pipeline of threads necessary for requesting plot
|
||||||
|
* data, generating plot images, and generating plot samples. Note that it does
|
||||||
|
* not involve itself with progressive disclosure, paint, or python threads.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Mar 21, 2014 2868 njensen Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author njensen
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PlotThreadOverseer {
|
||||||
|
|
||||||
|
private static final int DATA_THREADS = 2;
|
||||||
|
|
||||||
|
private static final int IMAGE_THREADS = DATA_THREADS;
|
||||||
|
|
||||||
|
private static final int SAMPLE_THREADS = 1;
|
||||||
|
|
||||||
|
protected ConcurrentLinkedQueue<GetDataTask> dataRetrievalQueue = new ConcurrentLinkedQueue<GetDataTask>();
|
||||||
|
|
||||||
|
protected List<PlotModelDataRequestJob> dataRetrievalJobList = new ArrayList<PlotModelDataRequestJob>(
|
||||||
|
DATA_THREADS);
|
||||||
|
|
||||||
|
protected ConcurrentLinkedQueue<PlotInfo[]> imageCreationQueue = new ConcurrentLinkedQueue<PlotInfo[]>();
|
||||||
|
|
||||||
|
protected List<PlotModelGeneratorJob> imageCreationJobList = new ArrayList<PlotModelGeneratorJob>(
|
||||||
|
IMAGE_THREADS);
|
||||||
|
|
||||||
|
protected List<PlotModelFactory2> plotCreatorList = new ArrayList<PlotModelFactory2>(
|
||||||
|
IMAGE_THREADS);
|
||||||
|
|
||||||
|
protected ConcurrentLinkedQueue<PlotInfo[]> sampleTextQueue = new ConcurrentLinkedQueue<PlotInfo[]>();
|
||||||
|
|
||||||
|
protected List<PlotSampleGeneratorJob> sampleTextJobList = new ArrayList<PlotSampleGeneratorJob>(
|
||||||
|
SAMPLE_THREADS);
|
||||||
|
|
||||||
|
private int plotModelWidth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* @param mapDescriptor
|
||||||
|
* @param plotModelFile
|
||||||
|
* @param levelKey
|
||||||
|
* @param plugin
|
||||||
|
* @param constraintMap
|
||||||
|
* @param caller
|
||||||
|
* @throws VizException
|
||||||
|
*/
|
||||||
|
public PlotThreadOverseer(IGraphicsTarget target,
|
||||||
|
MapDescriptor mapDescriptor, String plotModelFile, String levelKey,
|
||||||
|
String plugin, HashMap<String, RequestConstraint> constraintMap,
|
||||||
|
IPlotModelGeneratorCaller caller) throws VizException {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up image generation jobs first because the PlotModelFactory2
|
||||||
|
* initialization will parse the SVG to determine the parameters to
|
||||||
|
* request
|
||||||
|
*/
|
||||||
|
List<PlotModelElement> plotFields = null;
|
||||||
|
List<PlotModelElement> sampleFields = null;
|
||||||
|
for (int i = 0; i < IMAGE_THREADS; i++) {
|
||||||
|
PlotModelFactory2 plotModelFactory = new PlotModelFactory2(
|
||||||
|
mapDescriptor, plotModelFile);
|
||||||
|
plotCreatorList.add(plotModelFactory);
|
||||||
|
imageCreationJobList.add(new PlotModelGeneratorJob(this, caller,
|
||||||
|
plotModelFactory, target));
|
||||||
|
if (plotFields == null) {
|
||||||
|
/*
|
||||||
|
* data retrieval jobs need to know the plot and sample fields
|
||||||
|
* to request, which have now been parsed out of the SVG
|
||||||
|
*/
|
||||||
|
plotFields = plotModelFactory.getPlotFields();
|
||||||
|
sampleFields = plotModelFactory.getSampleFields();
|
||||||
|
plotModelWidth = plotModelFactory.getDefinedPlotModelWidth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the data retrieval jobs
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < DATA_THREADS; i++) {
|
||||||
|
dataRetrievalJobList.add(new PlotModelDataRequestJob(this, caller,
|
||||||
|
plotFields, sampleFields, levelKey, plugin, constraintMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the sample jobs. We could probably reuse the plot model
|
||||||
|
* factories of the image jobs, regardless, if it's a sample that uses
|
||||||
|
* python it will reuse the python job coordinator underneath, and if
|
||||||
|
* it's not...it's not clear if
|
||||||
|
* PlotModelFactory2.processSampleDirective() is thread safe
|
||||||
|
*
|
||||||
|
* TODO do we care?
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < SAMPLE_THREADS; i++) {
|
||||||
|
PlotModelFactory2 plotModelFactory = new PlotModelFactory2(
|
||||||
|
mapDescriptor, plotModelFile);
|
||||||
|
sampleTextJobList.add(new PlotSampleGeneratorJob(this, caller,
|
||||||
|
plotModelFactory));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueues a task of a batch of stations to retrieve data for
|
||||||
|
*
|
||||||
|
* @param task
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void enqueueDataRetrieval(GetDataTask task) {
|
||||||
|
List<PlotInfo[]> station = task.getStations();
|
||||||
|
|
||||||
|
Iterator<PlotInfo[]> itr = station.iterator();
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
PlotInfo[] infos = itr.next();
|
||||||
|
boolean allQueued = true;
|
||||||
|
for (PlotInfo info : infos) {
|
||||||
|
switch (task.getRequestType()) {
|
||||||
|
case PLOT_ONLY:
|
||||||
|
if (!info.plotQueued) {
|
||||||
|
allQueued = false;
|
||||||
|
info.plotQueued = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SAMPLE_ONLY:
|
||||||
|
if (!info.sampleQueued) {
|
||||||
|
allQueued = false;
|
||||||
|
info.sampleQueued = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PLOT_AND_SAMPLE:
|
||||||
|
if (!info.sampleQueued) {
|
||||||
|
allQueued = false;
|
||||||
|
info.sampleQueued = true;
|
||||||
|
}
|
||||||
|
if (!info.plotQueued) {
|
||||||
|
allQueued = false;
|
||||||
|
info.plotQueued = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allQueued) {
|
||||||
|
itr.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (station.size() > 0) {
|
||||||
|
task.setStations(station);
|
||||||
|
dataRetrievalQueue.add(task);
|
||||||
|
for (PlotModelDataRequestJob job : dataRetrievalJobList) {
|
||||||
|
if (job.getState() != Job.RUNNING) {
|
||||||
|
job.schedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a batch of PlotInfos to generate images for
|
||||||
|
*
|
||||||
|
* @param plotInfo
|
||||||
|
*/
|
||||||
|
public void enqueueImageGeneration(PlotInfo[] plotInfo) {
|
||||||
|
if (plotInfo.length > 0) {
|
||||||
|
imageCreationQueue.add(plotInfo);
|
||||||
|
for (PlotModelGeneratorJob job : imageCreationJobList) {
|
||||||
|
if (job.getState() != Job.RUNNING) {
|
||||||
|
job.schedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a batch of PlotInfos to generate sample messages for
|
||||||
|
*
|
||||||
|
* @param plotInfo
|
||||||
|
*/
|
||||||
|
public void enqueueSamplePlot(PlotInfo[] plotInfo) {
|
||||||
|
if (plotInfo.length > 0) {
|
||||||
|
sampleTextQueue.add(plotInfo);
|
||||||
|
for (PlotSampleGeneratorJob job : sampleTextJobList) {
|
||||||
|
if (job.getState() != Job.RUNNING) {
|
||||||
|
job.schedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlotModelColor(RGB color) {
|
||||||
|
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||||
|
pmf.setColor(color);
|
||||||
|
}
|
||||||
|
// don't clear the image cache, it's magic
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlotModelLineStyle(LineStyle lineStyle) {
|
||||||
|
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||||
|
pmf.setLineStyle(lineStyle);
|
||||||
|
}
|
||||||
|
for (PlotModelGeneratorJob job : imageCreationJobList) {
|
||||||
|
job.clearImageCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlotModelLineWidth(int outlineWidth) {
|
||||||
|
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||||
|
pmf.setLineWidth(outlineWidth);
|
||||||
|
}
|
||||||
|
for (PlotModelGeneratorJob job : imageCreationJobList) {
|
||||||
|
job.clearImageCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlotMissingData(boolean plotMissingData) {
|
||||||
|
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||||
|
pmf.setPlotMissingData(plotMissingData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLowerLimit(double lowerLimit) {
|
||||||
|
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||||
|
pmf.setLowerLimit(lowerLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpperLimit(double upperLimit) {
|
||||||
|
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||||
|
pmf.setUpperLimit(upperLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getOriginalPlotModelWidth() {
|
||||||
|
return plotModelWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlotModelSize(long round) {
|
||||||
|
for (PlotModelFactory2 pmf : plotCreatorList) {
|
||||||
|
pmf.setPlotDimensions(round, round);
|
||||||
|
}
|
||||||
|
for (PlotModelGeneratorJob job : imageCreationJobList) {
|
||||||
|
job.clearImageCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if all the jobs related to requesting data, creating plot images,
|
||||||
|
* and creating samples are done
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isDone() {
|
||||||
|
for (AbstractPlotCreationJob job : dataRetrievalJobList) {
|
||||||
|
if (!job.isDone()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AbstractPlotCreationJob job : imageCreationJobList) {
|
||||||
|
if (!job.isDone()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AbstractPlotCreationJob job : sampleTextJobList) {
|
||||||
|
if (!job.isDone()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuts down all the threads and clears their queues in a safe manner
|
||||||
|
*/
|
||||||
|
public void shutdown() {
|
||||||
|
/*
|
||||||
|
* by clearing the job lists first, nothing else can get queued, but we
|
||||||
|
* still need a copy of them to ensure they are shut down correctly
|
||||||
|
*/
|
||||||
|
List<AbstractPlotCreationJob> jobListCopy = null;
|
||||||
|
|
||||||
|
// shut down data requests first
|
||||||
|
jobListCopy = new ArrayList<AbstractPlotCreationJob>(
|
||||||
|
dataRetrievalJobList);
|
||||||
|
dataRetrievalJobList.clear();
|
||||||
|
for (AbstractPlotCreationJob job : jobListCopy) {
|
||||||
|
job.shutdown();
|
||||||
|
}
|
||||||
|
dataRetrievalQueue.clear();
|
||||||
|
|
||||||
|
// then shut down images
|
||||||
|
jobListCopy = new ArrayList<AbstractPlotCreationJob>(
|
||||||
|
imageCreationJobList);
|
||||||
|
imageCreationJobList.clear();
|
||||||
|
for (AbstractPlotCreationJob job : jobListCopy) {
|
||||||
|
job.shutdown();
|
||||||
|
}
|
||||||
|
imageCreationQueue.clear();
|
||||||
|
|
||||||
|
// and finally sampling
|
||||||
|
jobListCopy = new ArrayList<AbstractPlotCreationJob>(sampleTextJobList);
|
||||||
|
sampleTextJobList.clear();
|
||||||
|
for (AbstractPlotCreationJob job : jobListCopy) {
|
||||||
|
job.shutdown();
|
||||||
|
}
|
||||||
|
sampleTextQueue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import jep.JepException;
|
import jep.JepException;
|
||||||
|
|
||||||
|
@ -59,6 +60,9 @@ import com.raytheon.uf.common.python.PythonInterpreter;
|
||||||
* Jan 31, 2013 mnash Initial creation
|
* Jan 31, 2013 mnash Initial creation
|
||||||
* Jun 04, 2013 2041 bsteffen Improve exception handling for concurrent
|
* Jun 04, 2013 2041 bsteffen Improve exception handling for concurrent
|
||||||
* python.
|
* python.
|
||||||
|
* Mar 21, 2014 2868 njensen Changed getInstance() from throwing
|
||||||
|
* RuntimeException to IllegalArgumentException
|
||||||
|
* Added refCount
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -71,10 +75,17 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
||||||
|
|
||||||
private ThreadLocal<P> threadLocal = null;
|
private ThreadLocal<P> threadLocal = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks the number of times newInstance() vs shutdown() is called for an
|
||||||
|
* instance of a PythonJobCoordinator
|
||||||
|
*/
|
||||||
|
private AtomicInteger refCount;
|
||||||
|
|
||||||
private static Map<String, PythonJobCoordinator<? extends PythonInterpreter>> pools = new ConcurrentHashMap<String, PythonJobCoordinator<? extends PythonInterpreter>>();
|
private static Map<String, PythonJobCoordinator<? extends PythonInterpreter>> pools = new ConcurrentHashMap<String, PythonJobCoordinator<? extends PythonInterpreter>>();
|
||||||
|
|
||||||
private PythonJobCoordinator(final AbstractPythonScriptFactory<P> factory) {
|
private PythonJobCoordinator(final AbstractPythonScriptFactory<P> factory) {
|
||||||
threadLocal = new ThreadLocal<P>() {
|
threadLocal = new ThreadLocal<P>() {
|
||||||
|
@Override
|
||||||
protected P initialValue() {
|
protected P initialValue() {
|
||||||
try {
|
try {
|
||||||
return factory.createPythonScript();
|
return factory.createPythonScript();
|
||||||
|
@ -85,10 +96,11 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
||||||
};
|
};
|
||||||
execService = Executors.newFixedThreadPool(factory.getMaxThreads(),
|
execService = Executors.newFixedThreadPool(factory.getMaxThreads(),
|
||||||
new PythonThreadFactory(threadLocal, factory.getName()));
|
new PythonThreadFactory(threadLocal, factory.getName()));
|
||||||
|
refCount = new AtomicInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the instance by name, or throw a {@link RuntimeException}.
|
* Gets the instance by name, or throw a {@link IllegalArgumentException}.
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* @return
|
* @return
|
||||||
|
@ -99,7 +111,7 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
||||||
if (pools.containsKey(name)) {
|
if (pools.containsKey(name)) {
|
||||||
return (PythonJobCoordinator<S>) pools.get(name);
|
return (PythonJobCoordinator<S>) pools.get(name);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(
|
throw new IllegalArgumentException(
|
||||||
"Unable to find instance of PythonJobCoordinator named "
|
"Unable to find instance of PythonJobCoordinator named "
|
||||||
+ name
|
+ name
|
||||||
+ ", please call newInstance(AbstractPythonScriptFactory)");
|
+ ", please call newInstance(AbstractPythonScriptFactory)");
|
||||||
|
@ -110,7 +122,10 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of this class for a new application. If the same
|
* 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
|
* name already exists, it assumes that it is the same application and
|
||||||
* returns the existing instance.
|
* returns the existing instance. Also increments the reference count of
|
||||||
|
* applications using this PythonJobCoordinator. For each time that
|
||||||
|
* newInstance() is called, a corresponding call to shutdown() will be
|
||||||
|
* needed if you truly want to shut the job coordinator down.
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* @param numThreads
|
* @param numThreads
|
||||||
|
@ -119,14 +134,15 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
||||||
public static <S extends PythonInterpreter> PythonJobCoordinator<S> newInstance(
|
public static <S extends PythonInterpreter> PythonJobCoordinator<S> newInstance(
|
||||||
AbstractPythonScriptFactory<S> factory) {
|
AbstractPythonScriptFactory<S> factory) {
|
||||||
synchronized (pools) {
|
synchronized (pools) {
|
||||||
|
PythonJobCoordinator<S> pool = null;
|
||||||
if (pools.containsKey(factory.getName())) {
|
if (pools.containsKey(factory.getName())) {
|
||||||
return (PythonJobCoordinator<S>) pools.get(factory.getName());
|
pool = (PythonJobCoordinator<S>) pools.get(factory.getName());
|
||||||
} else {
|
} else {
|
||||||
PythonJobCoordinator<S> pool = new PythonJobCoordinator<S>(
|
pool = new PythonJobCoordinator<S>(factory);
|
||||||
factory);
|
|
||||||
pools.put(factory.getName(), pool);
|
pools.put(factory.getName(), pool);
|
||||||
return pool;
|
|
||||||
}
|
}
|
||||||
|
pool.refCount.getAndIncrement();
|
||||||
|
return pool;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,15 +187,20 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
||||||
/**
|
/**
|
||||||
* This function should take the {@link PythonInterpreter} on each thread in
|
* This function should take the {@link PythonInterpreter} on each thread in
|
||||||
* the thread pool and dispose of it and then shutdown the
|
* the thread pool and dispose of it and then shutdown the
|
||||||
* {@link ExecutorService}
|
* {@link ExecutorService}. This will reduce the reference count by 1, and
|
||||||
|
* will only shut down the underlying executor service and python
|
||||||
|
* interpreters if the refCount is less than 1.
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
*/
|
*/
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
synchronized (pools) {
|
synchronized (pools) {
|
||||||
pools.values().remove(this);
|
int count = refCount.decrementAndGet();
|
||||||
|
if (count < 1) {
|
||||||
|
pools.values().remove(this);
|
||||||
|
execService.shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
execService.shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -191,7 +212,9 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
|
||||||
*/
|
*/
|
||||||
public void shutdownTask(String name) {
|
public void shutdownTask(String name) {
|
||||||
/*
|
/*
|
||||||
* TODO need to add for future functionality
|
* TODO need to add for future functionality, arg should probably be an
|
||||||
|
* IPythonExecutor, not a String
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue