diff --git a/cave/com.raytheon.uf.viz.vaa/src/com/raytheon/uf/viz/vaa/rsc/VAAResource.java b/cave/com.raytheon.uf.viz.vaa/src/com/raytheon/uf/viz/vaa/rsc/VAAResource.java
index 7c75ea941d..f9ca715b1f 100644
--- a/cave/com.raytheon.uf.viz.vaa/src/com/raytheon/uf/viz/vaa/rsc/VAAResource.java
+++ b/cave/com.raytheon.uf.viz.vaa/src/com/raytheon/uf/viz/vaa/rsc/VAAResource.java
@@ -55,9 +55,7 @@ import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
-import com.raytheon.uf.viz.core.status.StatusConstants;
import com.raytheon.uf.viz.vaa.util.CommonUtil;
-import com.raytheon.viz.pointdata.Activator;
import com.raytheon.viz.pointdata.util.SymbolLoader;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
@@ -70,9 +68,10 @@ import com.vividsolutions.jts.geom.Polygon;
*
*
* SOFTWARE HISTORY
- * Date Ticket# Engineer Description
- * ------------ ---------- ----------- --------------------------
- * Nov 23, 2009 3268 jsanchez Initial creation
+ * Date Ticket# Engineer Description
+ * ------------- -------- ----------- --------------------------
+ * Nov 23, 2009 3268 jsanchez Initial creation
+ * Jun 06, 2014 2061 bsteffen Remove unneccessary imports
*
*
*
diff --git a/cave/com.raytheon.viz.pointdata/META-INF/MANIFEST.MF b/cave/com.raytheon.viz.pointdata/META-INF/MANIFEST.MF
index 66cfca8ad5..304eb0568d 100644
--- a/cave/com.raytheon.viz.pointdata/META-INF/MANIFEST.MF
+++ b/cave/com.raytheon.viz.pointdata/META-INF/MANIFEST.MF
@@ -2,44 +2,39 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Pointdata Plug-in
Bundle-SymbolicName: com.raytheon.viz.pointdata;singleton:=true
-Bundle-Version: 1.14.0.qualifier
-Bundle-Activator: com.raytheon.viz.pointdata.Activator
+Bundle-Version: 1.14.1.qualifier
Bundle-Vendor: Raytheon
-Eclipse-RegisterBuddy: com.raytheon.viz.core, com.raytheon.uf.viz.core
-Require-Bundle: org.apache.batik,
- org.eclipse.ui,
- org.eclipse.core.runtime,
- com.raytheon.viz.core,
- com.raytheon.uf.viz.core,
- com.raytheon.viz.ui,
- org.apache.commons.lang,
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.apache.batik;bundle-version="1.6",
+ org.eclipse.ui;bundle-version="3.8",
+ org.eclipse.core.runtime;bundle-version="3.8",
+ com.raytheon.uf.viz.core;bundle-version="1.14.3",
+ com.raytheon.viz.ui;bundle-version="1.14.0",
+ org.apache.commons.lang;bundle-version="2.3.0",
javax.measure,
- com.raytheon.uf.viz.localization;bundle-version="1.12.1174",
- org.jep;bundle-version="1.0.0",
- com.raytheon.uf.common.python;bundle-version="1.12.1161",
- 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.colormap;bundle-version="1.12.1174",
+ com.raytheon.uf.viz.localization,
+ org.jep;bundle-version="2.3.0",
+ com.raytheon.uf.common.python,
+ com.raytheon.uf.common.pointdata;bundle-version="1.13.0",
+ com.raytheon.uf.common.dataplugin.level;bundle-version="1.14.0",
+ com.raytheon.uf.common.colormap,
com.raytheon.uf.common.wxmath,
com.raytheon.uf.common.python.concurrent,
com.raytheon.uf.common.derivparam;bundle-version="1.14.0",
- com.raytheon.uf.viz.datacube;bundle-version="1.14.0"
-Bundle-ActivationPolicy: lazy
+ com.raytheon.uf.viz.datacube;bundle-version="1.14.0",
+ com.raytheon.uf.common.inventory;bundle-version="1.14.0",
+ com.raytheon.uf.common.datastorage;bundle-version="1.14.0",
+ com.raytheon.uf.common.time,
+ com.raytheon.uf.common.geospatial;bundle-version="1.14.1",
+ com.raytheon.uf.common.dataplugin,
+ com.raytheon.uf.common.dataplugin.grid;bundle-version="1.13.0",
+ com.raytheon.uf.common.message;bundle-version="1.14.0",
+ com.raytheon.uf.viz.productbrowser;bundle-version="1.14.0",
+ com.raytheon.viz.alerts,
+ com.raytheon.uf.common.comm
Export-Package: com.raytheon.viz.pointdata,
com.raytheon.viz.pointdata.drawables,
com.raytheon.viz.pointdata.rsc,
com.raytheon.viz.pointdata.rsc.retrieve,
com.raytheon.viz.pointdata.util
-Import-Package: com.raytheon.uf.common.comm,
- com.raytheon.uf.common.inventory.data,
- com.raytheon.uf.common.inventory.exception,
- com.raytheon.uf.common.inventory,
- com.raytheon.uf.common.inventory.tree,
- com.raytheon.uf.common.dataplugin.grid,
- com.raytheon.uf.common.message.response,
- com.raytheon.uf.common.pointdata,
- com.raytheon.uf.common.pointdata.accumulate,
- com.raytheon.uf.viz.productbrowser,
- com.raytheon.viz.alerts,
- com.raytheon.viz.alerts.observers
-Bundle-RequiredExecutionEnvironment: JavaSE-1.6
diff --git a/cave/com.raytheon.viz.pointdata/localization/plotModels/acarsPlotDesign.svg b/cave/com.raytheon.viz.pointdata/localization/plotModels/acarsPlotDesign.svg
index e0c8a1262d..3888b59ffe 100644
--- a/cave/com.raytheon.viz.pointdata/localization/plotModels/acarsPlotDesign.svg
+++ b/cave/com.raytheon.viz.pointdata/localization/plotModels/acarsPlotDesign.svg
@@ -56,10 +56,12 @@ xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
]]>
- 75
- 75
- 75
-
+ 0
+ 0
+ 75
+ 75
+ 75
+
0
arrow
diff --git a/cave/com.raytheon.viz.pointdata/plugin.xml b/cave/com.raytheon.viz.pointdata/plugin.xml
index 4933c46302..daf3914888 100644
--- a/cave/com.raytheon.viz.pointdata/plugin.xml
+++ b/cave/com.raytheon.viz.pointdata/plugin.xml
@@ -42,12 +42,6 @@
renderingOrderId="PLOT"
resourceType="PLAN_VIEW">
-
-
- *
- * SOFTWARE HISTORY
- *
- * Date Ticket# Engineer Description
- * ---------- ---------- ----------- --------------------------
- * 20090513 2338 jsanchez Initial creation.
- *
- *
- * @author jsanchez
- * @version 1
- */
-public class ParamLookup {
- private static TreeMap PRECIP_MAP = new TreeMap();
- private static TreeMap VIS_MAP = new TreeMap();
- static {
- VIS_MAP.put(0.0000f,"0");
- VIS_MAP.put(0.03125f,"0");
- VIS_MAP.put(0.09375f,"1/16");
- VIS_MAP.put(0.15625f,"1/8");
- VIS_MAP.put(0.21875f,"3/16");
- VIS_MAP.put(0.28125f,"1/4");
- VIS_MAP.put(0.34375f,"5/16");
- VIS_MAP.put(0.40625f,"3/8");
- VIS_MAP.put(0.46875f,"7/16");
- VIS_MAP.put(0.53125f,"1/2");
- VIS_MAP.put(0.59375f,"9/16");
- VIS_MAP.put(0.65625f,"5/8");
- VIS_MAP.put(0.71875f,"11/16");
- VIS_MAP.put(0.78125f,"3/4");
- VIS_MAP.put(0.84375f,"13/16");
- VIS_MAP.put(0.90625f,"7/8");
- VIS_MAP.put(0.96875f,"15/16");
- VIS_MAP.put(1.03125f,"1");
- VIS_MAP.put(1.09375f,"1~1/16");
- VIS_MAP.put(1.15625f,"1~1/8");
- VIS_MAP.put(1.21875f,"1~3/16");
- VIS_MAP.put(1.28125f,"1~1/4");
- VIS_MAP.put(1.34375f,"1~5/16");
- VIS_MAP.put(1.40625f,"1~3/8");
- VIS_MAP.put(1.46875f,"1~7/16");
- VIS_MAP.put(1.53125f,"1~1/2");
- VIS_MAP.put(1.59375f,"1~9/16");
- VIS_MAP.put(1.65625f,"1~5/8");
- VIS_MAP.put(1.71875f,"1~11/16");
- VIS_MAP.put(1.78125f,"1~3/4");
- VIS_MAP.put(1.84375f,"1~13/16");
- VIS_MAP.put(1.90625f,"1~7/8");
- VIS_MAP.put(1.96875f,"1~15/16");
- VIS_MAP.put(2.0625f,"2");
- VIS_MAP.put(2.1875f,"2~1/8");
- VIS_MAP.put(2.3125f,"2~1/4");
- VIS_MAP.put(2.4375f,"2~3/8");
- VIS_MAP.put(2.5625f,"2~1/2");
- VIS_MAP.put(2.6875f,"2~5/8");
- VIS_MAP.put(2.8125f,"2~3/4");
- VIS_MAP.put(2.9375f,"2~7/8");
- VIS_MAP.put(3.0625f,"3");
- VIS_MAP.put(3.1875f,"3~1/8");
- VIS_MAP.put(3.3125f,"3~1/4");
- VIS_MAP.put(3.4375f,"3~3/8");
- VIS_MAP.put(3.5625f,"3~1/2");
- VIS_MAP.put(3.6875f,"3~5/8");
- VIS_MAP.put(3.8125f,"3~3/4");
- VIS_MAP.put(3.9375f,"3~7/8");
- VIS_MAP.put(4.125f,"4");
- VIS_MAP.put(4.375f,"4~1/4");
- VIS_MAP.put(4.625f,"4~1/2");
- VIS_MAP.put(4.875f,"4~3/4");
- VIS_MAP.put(5.125f,"5");
- VIS_MAP.put(5.375f,"5~1/4");
- VIS_MAP.put(5.625f,"5~1/2");
- VIS_MAP.put(5.875f,"5~3/4");
- VIS_MAP.put( 6.5f,"6");
- VIS_MAP.put(.5f,"7");
- VIS_MAP.put(8.5f,"8");
- VIS_MAP.put(9.5f,"9");
- VIS_MAP.put(0.5f,"10");
- VIS_MAP.put(11.5f,"11");
- VIS_MAP.put(12.5f,"12");
- VIS_MAP.put(13.5f,"13");
- VIS_MAP.put(14.5f,"14");
- VIS_MAP.put(15.5f,"15");
- VIS_MAP.put(16.5f,"16");
- VIS_MAP.put(17.5f,"17");
- VIS_MAP.put(18.5f,"18");
- VIS_MAP.put(19.5f,"19");
- VIS_MAP.put(22.5f,"20");
- VIS_MAP.put(27.5f,"25");
- VIS_MAP.put(32.5f,"30");
- VIS_MAP.put(37.5f,"35");
- VIS_MAP.put(42.5f,"40");
- VIS_MAP.put(47.5f,"45");
- VIS_MAP.put(52.5f,"50");
- VIS_MAP.put(57.5f,"55");
- VIS_MAP.put(62.5f,"60");
- VIS_MAP.put(67.5f,"65");
- VIS_MAP.put(72.5f,"70");
- VIS_MAP.put(77.5f,"75");
- VIS_MAP.put(82.5f,"80");
- VIS_MAP.put(87.5f,"85");
- VIS_MAP.put(92.5f,"90");
- VIS_MAP.put(97.5f,"95");
- VIS_MAP.put(110f,"100");
-
- PRECIP_MAP.put(-0.005f,"T");
- PRECIP_MAP.put(0.005f,"T");
- PRECIP_MAP.put(0.015f,".01");
- PRECIP_MAP.put(0.025f,".02");
- PRECIP_MAP.put(0.035f,".03");
- PRECIP_MAP.put(0.045f,".04");
- PRECIP_MAP.put(0.055f,".05");
- PRECIP_MAP.put(0.065f,".06");
- PRECIP_MAP.put(0.075f,".07");
- PRECIP_MAP.put(0.085f,".08");
- PRECIP_MAP.put(0.095f,".09");
- }
-
- private static String getVisibiiltyFormat(float vis) {
- String retVal = "";
- if (vis < 97.5) {
- retVal = VIS_MAP.ceilingEntry(vis).getValue();
- } else if (vis <= 110) {
- retVal = VIS_MAP.floorEntry(vis).getValue();
- }
-
- return retVal;
- }
-
- private static String getPrecipFormat(double precip) {
- String retVal = "";
- if (precip < 0.085) {
- retVal = PRECIP_MAP.ceilingEntry((float) precip).getValue();
- } else if (precip < 0.095) {
- retVal = PRECIP_MAP.floorEntry((float) precip).getValue();
- } else {
- DecimalFormat p = new DecimalFormat("####.00");
- retVal = p.format(precip);
- }
-
- return retVal;
- }
-
- public static String get(String param, String value) {
- String retVal = value;
-
- if (param.matches("VIS")) {
- retVal = getVisibiiltyFormat(Float.parseFloat(value));
- } else if (param.startsWith("PR")) {
- retVal = getPrecipFormat(Double.parseDouble(value));
- }
- return retVal;
- }
-
-}
-
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelFactory.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelFactory.java
index 3c95efb47b..e08ba93a99 100644
--- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelFactory.java
+++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelFactory.java
@@ -24,12 +24,18 @@ import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
import java.text.ParseException;
import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
import java.util.Formatter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.Unit;
@@ -47,28 +53,45 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
-import com.raytheon.uf.common.dataplugin.IDecoderGettable;
-import com.raytheon.uf.common.dataplugin.IDecoderGettable.Amount;
-import com.raytheon.uf.common.dataplugin.PluginDataObject;
+import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.PathManagerFactory;
+import com.raytheon.uf.common.python.concurrent.PythonJobCoordinator;
+import com.raytheon.uf.common.status.IUFStatusHandler;
+import com.raytheon.uf.common.status.UFStatus;
+import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.IMapDescriptor;
+import com.raytheon.viz.pointdata.lookup.IAbstractLookupTable;
+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.PlotResource;
+import com.raytheon.viz.pointdata.rsc.PlotResourceData;
/**
- * A singleton that will create a plot model texture based on a passed in
- * MetarRecord object.
+ * A factory for generating plot images and sample messages by parsing the
+ * associated plotModel SVG file.
*
*
*
* SOFTWARE HISTORY
*
- * Date Ticket# Engineer Description
- * ------------ ---------- ----------- --------------------------
- * 11/20/2006 brockwoo Initial creation.
- * 03/16/2009 jsanchez Added processAvailDirective.
- * 05/15/2009 2338 jsanchez Updated processTextDirective.
+ * Date Ticket# Engineer Description
+ * ------------- -------- ----------- --------------------------
+ * Nov 20, 2006 brockwoo Initial creation.
+ * Mar 16, 2009 jsanchez Added processAvailDirective.
+ * Jun 29, 2009 2538 jsanchez Implemented pointdata.
+ * Aug 09, 2012 1085 jkorman Corrected data construction.
+ * Sep 05, 2013 2316 bsteffen Unify pirep and ncpirep.
+ * Sep 05, 2013 2307 dgilling Use better PythonScript constructor.
+ * Nov 20, 2013 2033 njensen Fix detecting plotModels dirs from multiple plugins
+ * Mar 21, 2014 2868 njensen Refactored python usage to PythonJobCoordinator
+ * Jun 06, 2014 2061 bsteffen Rename and add support for data formats in sampling.
*
*
*
@@ -76,8 +99,10 @@ import com.raytheon.uf.viz.core.map.IMapDescriptor;
* @version 1.0
*/
public class PlotModelFactory {
+ private static final transient IUFStatusHandler statusHandler = UFStatus
+ .getHandler(PlotModelFactory.class);
- private static final String plotmodelDir = "plotModels";
+ public static final String PLOT_MODEL_DIR = "plotModels";
private static final String DM_ATTRIBUTE = "plotMode";
@@ -87,19 +112,31 @@ public class PlotModelFactory {
private static final String UNIT_ATTRIBUTE = "plotUnit";
+ private static final String SYMBOL_ATTRIBUTE = "plotSymbol";
+
private static final String TRIM_ATTRIBUTE = "plotTrim";
private static final String PFT_ATTRIBUTE = "plotFunctionTable";
private static final String PLT_ATTRIBUTE = "plotLookupTable";
+ private static final String PLT_INDEX = "plotIndex";
+
+ private static final String REQUIRED = "required";
+
+ private final SimpleDateFormat SAMPLE_DATE = new SimpleDateFormat("HHmm");
+
// Need to include attribute and code to allow for String2String lookups and
// String2Number lookups
// to support clouds and present weather
- private Document document;
+ private int width = 1;
- private GraphicsNode theGraphicsNode;
+ private LineStyle lineStyle = LineStyle.DEFAULT;
+
+ private String currentStyleStr;
+
+ private Document document;
private final GVTBuilder builder;
@@ -109,12 +146,6 @@ public class PlotModelFactory {
private int plotModelHeight;
- private int width = 1;
-
- private LineStyle lineStyle = LineStyle.DEFAULT;
-
- private String currentStyleStr;
-
private final int originalPlotModelWidth;
private final int originalPlotModelHeight;
@@ -127,10 +158,24 @@ public class PlotModelFactory {
private IndexColorModel tm;
- private final ArrayList plotFields;
+ private final List plotFields;
+
+ private final List sampleFields;
+
+ private double lowerLimit = -9999.0;
+
+ private double upperLimit = -9999.0;
+
+ private boolean plotMissingData = false;
+
+ private Map imageCache = null;
+
+ protected final String plotModelFile;
+
+ protected PythonJobCoordinator python;
public static enum DisplayMode {
- TEXT, BARB, TABLE, AVAIL, RANGE
+ TEXT, BARB, TABLE, AVAIL, RANGE, NULL, SAMPLE, ARROW
}
public class PlotModelElement {
@@ -142,8 +187,12 @@ public class PlotModelFactory {
String unit = null;
+ String symbol = null;
+
int trim = 0;
+ int index = -1;
+
UnitConverter converter = null;
Element plotElement = null;
@@ -152,9 +201,19 @@ public class PlotModelFactory {
S2N ranking = null;
- StringLookup lookup = null;
+ IAbstractLookupTable lookup = null;
PlotWindElement winds = null;
+
+ boolean required = false;
+
+ public Node getPlotNode() {
+ return plotNode;
+ }
+
+ public String getParameter() {
+ return parameter;
+ }
}
public class PlotWindElement {
@@ -181,8 +240,10 @@ public class PlotModelFactory {
byte[] red = { 0, zero };
byte[] blue = { 0, full };
byte[] green = { 0, zero };
-
+ regenerateStyle();
+ this.plotModelFile = plotModelFile;
this.plotFields = new ArrayList();
+ this.sampleFields = new ArrayList();
tm = new IndexColorModel(8, 2, red, blue, green, 0);
this.gc = new GeodeticCalculator(mapDescriptor.getCRS());
@@ -190,17 +251,11 @@ public class PlotModelFactory {
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
try {
- document = f.createDocument(PathManagerFactory
- .getPathManager()
- .getStaticFile(
- plotmodelDir + File.separator + plotModelFile)
+ document = f.createDocument(PathManagerFactory.getPathManager()
+ .getStaticFile(PlotResourceData.PLOT_DIR + plotModelFile)
.toURI().toString());
- } catch (MalformedURLException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- } catch (IOException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
+ } catch (Exception e) {
+ statusHandler.handle(Priority.PROBLEM, "Error parsing svg file", e);
}
this.svgRoot = document.getDocumentElement();
this.originalPlotModelWidth = Integer.parseInt(svgRoot.getAttributeNS(
@@ -210,6 +265,8 @@ public class PlotModelFactory {
this.plotModelWidth = this.originalPlotModelWidth;
this.plotModelHeight = this.originalPlotModelHeight;
+ int displayedElementCount = 0;
+
Element plot = document.getElementById("plotData");
NodeList plotElements = plot.getChildNodes();
@@ -223,6 +280,7 @@ public class PlotModelFactory {
if (plotElement.getAttribute(DM_ATTRIBUTE).equals("text")) {
thisElement.mode = DisplayMode.TEXT;
plotElement.setAttribute("class", "text");
+ displayedElementCount++;
} else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
"barb")) {
thisElement.mode = DisplayMode.BARB;
@@ -255,35 +313,103 @@ public class PlotModelFactory {
}
}
}
+ displayedElementCount++;
} else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "table")) {
+ "arrowuv")) {
+ thisElement.mode = DisplayMode.ARROW;
+ thisElement.winds = new PlotWindElement();
+ NodeList windElements = plotElement.getChildNodes();
+ for (int j = 0; j < windElements.getLength(); j++) {
+ if (Node.ELEMENT_NODE == windElements.item(j)
+ .getNodeType()) {
+ Element windElement = (Element) windElements
+ .item(j);
+ String attrClass = windElement
+ .getAttribute("class");
+ if ("arrow".matches(attrClass)) {
+ thisElement.winds.arrowElement = windElement;
+ thisElement.winds.arrowNode = windElement
+ .getChildNodes().item(0);
+ } else if ("arrow1".matches(attrClass)) {
+ thisElement.winds.arrowElement = windElement;
+ thisElement.winds.arrowNode = windElement
+ .getChildNodes().item(0);
+ thisElement.winds.arrowElement
+ .setAttribute("arrowtype",
+ attrClass);
+ } else if ("arrow2".matches(attrClass)) {
+ thisElement.winds.arrowElement = windElement;
+ thisElement.winds.arrowNode = windElement
+ .getChildNodes().item(0);
+ thisElement.winds.arrowElement
+ .setAttribute("arrowtype",
+ attrClass);
+ } else if ("text".matches(attrClass)) {
+ thisElement.winds.gustElement = windElement;
+ thisElement.winds.gustNode = windElement
+ .getChildNodes().item(0);
+ thisElement.winds.gustX = windElement
+ .getAttribute("x");
+ thisElement.winds.gustY = windElement
+ .getAttribute("y");
+ }
+ }
+ }
+ displayedElementCount++;
+ } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
+ "table")
+ || plotElement.getAttribute(DM_ATTRIBUTE).equals(
+ "recursive_translation")) {
thisElement.mode = DisplayMode.TABLE;
if (plotElement.hasAttribute(PFT_ATTRIBUTE)) {
thisElement.ranking = S2N.readS2NFile(plotElement
.getAttribute(PFT_ATTRIBUTE));
}
if (plotElement.hasAttribute(PLT_ATTRIBUTE)) {
- thisElement.lookup = StringLookup
- .readS2SFile(plotElement
- .getAttribute(PLT_ATTRIBUTE));
- }
- } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "range")) {
- thisElement.mode = DisplayMode.RANGE;
- if (plotElement.hasAttribute(PLT_ATTRIBUTE)) {
- thisElement.lookup = StringLookup
- .readR2SFile(plotElement
- .getAttribute(PLT_ATTRIBUTE));
+ File table = getTableFile(plotElement
+ .getAttribute(PLT_ATTRIBUTE));
+ thisElement.lookup = LookupUtils
+ .buildLookupTable(table);
+ thisElement.lookup.setMode(plotElement
+ .getAttribute(DM_ATTRIBUTE));
}
+ displayedElementCount++;
} else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
"arrow")) {
plotElement.setAttribute("class", "text");
thisElement.mode = DisplayMode.BARB;
+ displayedElementCount++;
} else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
"available")) {
- // for plotMode="available"
thisElement.mode = DisplayMode.AVAIL;
plotElement.setAttribute("class", "text");
+ displayedElementCount++;
+ } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
+ "range")) {
+ thisElement.mode = DisplayMode.RANGE;
+ if (plotElement.hasAttribute(PLT_ATTRIBUTE)) {
+ File table = getTableFile(plotElement
+ .getAttribute(PLT_ATTRIBUTE));
+ thisElement.lookup = LookupUtils
+ .buildLookupTable(table);
+ thisElement.lookup.setMode(plotElement
+ .getAttribute(DM_ATTRIBUTE));
+ }
+ displayedElementCount++;
+ } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
+ "null")) {
+ thisElement.mode = DisplayMode.NULL;
+ } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
+ "sample")) {
+ thisElement.mode = DisplayMode.SAMPLE;
+ if (plotElement.hasAttribute(PLT_ATTRIBUTE)) {
+ File table = getTableFile(plotElement
+ .getAttribute(PLT_ATTRIBUTE));
+ thisElement.lookup = LookupUtils
+ .buildLookupTable(table);
+ thisElement.lookup.setMode(plotElement
+ .getAttribute(DM_ATTRIBUTE));
+ }
}
thisElement.parameter = plotElement
.getAttribute(P_ATTRIBUTE);
@@ -295,41 +421,106 @@ public class PlotModelFactory {
thisElement.unit = plotElement
.getAttribute(UNIT_ATTRIBUTE);
}
+ if (plotElement.hasAttribute(SYMBOL_ATTRIBUTE)) {
+ thisElement.symbol = plotElement
+ .getAttribute(SYMBOL_ATTRIBUTE);
+ }
if (plotElement.hasAttribute(TRIM_ATTRIBUTE)) {
thisElement.trim = Integer.parseInt(plotElement
.getAttribute(TRIM_ATTRIBUTE));
}
- this.plotFields.add(thisElement);
+ if (plotElement.hasAttribute(PLT_INDEX)) {
+ thisElement.index = Integer.parseInt(plotElement
+ .getAttribute(PLT_INDEX));
+ }
+ if (plotElement.hasAttribute(REQUIRED)) {
+ thisElement.required = Boolean.parseBoolean(plotElement
+ .getAttribute(REQUIRED));
+ }
+ if (thisElement.mode != DisplayMode.SAMPLE) {
+ this.plotFields.add(thisElement);
+ } else {
+ this.sampleFields.add(thisElement);
+ thisElement.plotNode.setNodeValue("");
+ }
}
}
}
+ if (displayedElementCount <= 3) {
+ // Dont use image caching if more then 3 elements are used, with
+ // very few elements the hit rate is good enought to risk keeping
+ // the images in memory, but with more elements the hit rate drops
+ // and the cache size increases. 3 elements might not be the optimal
+ // way of detecting complexity but it is better than nothing.
+ imageCache = new HashMap();
+ }
+ NodeList scriptNodes = document.getElementsByTagName("script");
+
+ // Only one script node supported
+ 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);
+ String plotDelegateName = scriptNode.getAttribute("plotDelegate");
+ NodeList childNodes = scriptNode.getChildNodes();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node child = childNodes.item(i);
+ if (Node.TEXT_NODE == child.getNodeType()) {
+ sb.append(((Text) child).getData());
+ }
+ }
+ String scriptText = sb.toString().trim();
+ if (scriptText.length() > 0) {
+ PlotPythonScriptFactory pythonFactory = new PlotPythonScriptFactory(
+ plotModelFile, scriptText, plotDelegateName);
+ python = PythonJobCoordinator.newInstance(pythonFactory);
+ }
+
+ // remove the scriptNode in memory so time isn't wasted
+ // later attempting to render it
+ scriptNode.getParentNode().removeChild(scriptNode);
+ }
+
UserAgentAdapter userAgentAdapter = new UserAgentAdapter();
this.bridgeContext = new BridgeContext(userAgentAdapter);
this.builder = new GVTBuilder();
}
public void setColor(RGB color) {
+ if (imageCache != null) {
+ imageCache.clear();
+ }
byte fullr = (byte) color.red;
byte fullg = (byte) color.green;
byte fullb = (byte) color.blue;
- String style = "stroke: rgb(" + color.red + "," + color.green + ","
- + color.blue + ");";
+ // String style = "stroke: rgb(" + color.red + "," + color.green + ","
+ // + color.blue + ");";
// this.svgRoot.setAttribute("style", style);
// System.out.println(style);
byte[] red = { 0, fullr };
byte[] blue = { 0, fullb };
byte[] green = { 0, fullg };
tm = new IndexColorModel(8, 2, red, green, blue, 0);
- System.out.println(style);
+ // System.out.println(style);
}
public void setLineWidth(int width) {
+ if (imageCache != null) {
+ imageCache.clear();
+ }
this.width = width;
regenerateStyle();
}
public void setLineStyle(LineStyle style) {
+ if (imageCache != null) {
+ imageCache.clear();
+ }
this.lineStyle = style;
regenerateStyle();
}
@@ -365,6 +556,9 @@ public class PlotModelFactory {
}
public void setPlotDimensions(long x, long y) {
+ if (imageCache != null) {
+ imageCache.clear();
+ }
this.svgRoot.setAttributeNS(null, "width", Long.toString(x));
this.svgRoot.setAttributeNS(null, "height", Long.toString(y));
this.plotModelWidth = (int) x;
@@ -380,8 +574,7 @@ public class PlotModelFactory {
}
/**
- * Takes the station name and its MetarRecord object and produces a buffered
- * image.
+ * Takes the station data object and produces a buffered image.
*
* @param station
* The station name
@@ -389,207 +582,452 @@ public class PlotModelFactory {
* A metar record for that station
* @return A buffered image representing the station data
*/
- public BufferedImage getStationPlot(PluginDataObject stationData)
- throws VizException {
+ public synchronized BufferedImage getStationPlot(PlotData stationData,
+ double latitude, double longitude) {
+ double[] stationLocation = { longitude, latitude };
+ double[] stationPixelLocation = this.mapDescriptor
+ .worldToPixel(stationLocation);
+
+ if (stationPixelLocation != null) {
+ stationPixelLocation[1]--;
+ double[] newWorldLocation = this.mapDescriptor
+ .pixelToWorld(stationPixelLocation);
+ this.gc.setStartingGeographicPoint(stationLocation[0],
+ stationLocation[1]);
+ this.gc.setDestinationGeographicPoint(newWorldLocation[0],
+ newWorldLocation[1]);
+ }
+
try {
- if (stationData != null
- && (stationData instanceof IDecoderGettable)) {
-
- IDecoderGettable observation = (IDecoderGettable) stationData;
-
- double[] stationLocation = {
- observation.getValue("NLON").doubleValue(),
- observation.getValue("NLAT").doubleValue() };
- double[] stationPixelLocation = this.mapDescriptor
- .worldToPixel(stationLocation);
- if (stationPixelLocation != null) {
- stationPixelLocation[1]--;
- double[] newWorldLocation = this.mapDescriptor
- .pixelToWorld(stationPixelLocation);
- this.gc.setStartingGeographicPoint(stationLocation[0],
- stationLocation[1]);
- this.gc.setDestinationGeographicPoint(newWorldLocation[0],
- newWorldLocation[1]);
- }
-
- for (PlotModelElement element : this.plotFields) {
- switch (element.mode) {
- case TEXT:
- this.processTextDirective(observation, element);
- break;
- case BARB:
- element.plotElement.setAttribute("style",
- currentStyleStr);
- this.processBarbDirective(observation, element);
- break;
- case TABLE:
- this.processTableDirective(observation, element);
- break;
- case RANGE:
- this.processRangeDirective(observation, element);
- break;
- case AVAIL:
- this.processAvailDirective(observation, element);
- break;
+ boolean discard = false;
+ if (python != null) {
+ Boolean result = false;
+ CheckPlotValidityExecutor task = new CheckPlotValidityExecutor(
+ stationData);
+ try {
+ result = python.submitSyncJob(task);
+ } catch (Exception e) {
+ statusHandler.handle(Priority.PROBLEM,
+ "Error checking if plot is valid for plot model "
+ + getPlotModelFilename(), e);
+ } finally {
+ if (result.booleanValue() == false) {
+ return null;
}
-
}
- BufferedImage bufferedImage = new BufferedImage(
- this.plotModelWidth, this.plotModelHeight,
- BufferedImage.TYPE_BYTE_INDEXED, tm);
- Graphics2D g2d = bufferedImage.createGraphics();
-
- this.theGraphicsNode = builder.build(this.bridgeContext,
- this.document);
- this.theGraphicsNode.primitivePaint(g2d);
- // Cleanup and return image
- g2d.dispose();
-
- return bufferedImage;
}
+
+ StringBuilder imageId = new StringBuilder();
+
+ for (PlotModelElement element : this.plotFields) {
+ boolean valid = true;
+ boolean required = element.required;
+ switch (element.mode) {
+ case TEXT:
+ this.processTextDirective(stationData, element);
+ addToImageId(stationData, element.parameter, imageId);
+ break;
+ case BARB:
+ element.plotElement.setAttribute("style", currentStyleStr);
+ valid = this.processBarbDirective(stationData, element);
+ // normalize speed before adding to id so all identical
+ // barbs will share plots
+ String[] windParams = element.parameter.split(",");
+ double speed = stationData.getNumber(windParams[0])
+ .doubleValue();
+ double dir = stationData.getNumber(windParams[1])
+ .doubleValue();
+ if (element.converter != null) {
+ speed = element.converter.convert(speed);
+ }
+ imageId.append(windNormalizer(speed));
+ // Accurate to a fourth a degree.
+ imageId.append((int) (dir - gc.getAzimuth()) * 4);
+ if (windParams.length == 3) {
+ imageId.append(stationData.getNumber(windParams[2]));
+ }
+ addToImageId(stationData,
+ element.parameter.split(",", 2)[1], imageId);
+ break;
+ case ARROW:
+ element.plotElement.setAttribute("style", currentStyleStr);
+ addToImageId(stationData, element.parameter, imageId);
+ this.processArrowDirective(stationData, element);
+ break;
+ case TABLE:
+ this.processTableDirective(stationData, element);
+ addToImageId(stationData, element.parameter, imageId);
+ break;
+ case AVAIL:
+ this.processAvailDirective(element);
+ break;
+ case RANGE:
+ valid = this.processRangeDirective(stationData, element);
+ addToImageId(stationData, element.parameter, imageId);
+ break;
+ case NULL:
+ this.processNullDirective(element);
+ break;
+ }
+ if (!valid && required) {
+ discard = true;
+ }
+ }
+
+ if (discard) {
+ return null;
+ }
+
+ if (imageCache != null
+ && imageCache.containsKey(imageId.toString())) {
+ return imageCache.get(imageId.toString());
+ }
+
+ BufferedImage bufferedImage = new BufferedImage(
+ this.plotModelWidth, this.plotModelHeight,
+ BufferedImage.TYPE_BYTE_INDEXED, tm);
+
+ // long t0 = System.currentTimeMillis();
+ GraphicsNode graphicsNode = builder.build(this.bridgeContext,
+ this.document);
+ Graphics2D g2d = null;
+ try {
+ g2d = bufferedImage.createGraphics();
+ graphicsNode.primitivePaint(g2d);
+ } finally {
+ if (g2d != null) {
+ g2d.dispose();
+ }
+ }
+ // System.out.println("Time building and creating graphics: "
+ // + (System.currentTimeMillis() - t0));
+ if (imageCache != null) {
+ imageCache.put(imageId.toString(), bufferedImage);
+ }
+ return bufferedImage;
+
} catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ statusHandler.handle(Priority.PROBLEM,
+ "Error:" + e.getLocalizedMessage(), e);
}
return null;
}
- private void processTextDirective(IDecoderGettable ob,
- PlotModelElement element) throws VizException {
- Amount value = ob.getValue(element.parameter);
- String sValue = null;
- if (value != null && value.doubleValue() != -9999.0) {
- double displayValue = 0.0;
- if (element.unit != null) {
+ public synchronized String getStationMessage(PlotData stationData,
+ String dataURI) {
+ StringBuilder sampleMessage = new StringBuilder();
+ try {
+ if (python != null) {
+ String result = null;
+ SampleTextExecutor task = new SampleTextExecutor(stationData);
try {
- Unit> unit = UnitFormat
- .getUCUMInstance()
- .parseSingleUnit(element.unit, new ParsePosition(0));
- element.converter = value.getUnit().getConverterTo(unit);
- } catch (ParseException e) {
- throw new VizException("Unable parse units ", e);
+ result = python.submitSyncJob(task);
+ } catch (Exception e) {
+ statusHandler.handle(Priority.PROBLEM,
+ "Error getting sample text for plot model "
+ + getPlotModelFilename(), e);
+ } finally {
+ if (result != null) {
+ sampleMessage.append(result);
+ }
}
- displayValue = element.converter.convert(value.doubleValue());
} else {
- displayValue = value.doubleValue();
+ for (PlotModelElement element : this.sampleFields) {
+ sampleMessage.append(processSampleDirective(stationData,
+ element));
+ }
}
- if (element.format != null) {
- StringBuilder sb = new StringBuilder();
- Formatter testing = new Formatter(sb);
- testing.format(element.format, displayValue);
- sValue = sb.toString();
+
+ } catch (Exception e) {
+ statusHandler.handle(Priority.PROBLEM,
+ "Error generating sample text with " + plotModelFile, e);
+ }
+
+ String message = sampleMessage.toString();
+ if (message.length() == 0) {
+ message = PlotResource.NO_DATA;
+ }
+
+ return message;
+ }
+
+ private void addToImageId(PlotData stationData, String parameters,
+ StringBuilder imageId) {
+ for (String parameter : parameters.split(",")) {
+ switch (stationData.getType(parameter)) {
+ case STRING:
+ imageId.append(stationData.getString(parameter));
+ break;
+ default:
+ imageId.append(stationData.getNumber(parameter).floatValue());
+ }
+ }
+ }
+
+ private void processTextDirective(PlotData ob, PlotModelElement element)
+ throws VizException {
+ int dimensions = -1;
+ String sValue = null;
+ String param = element.parameter;
+ Number value = null;
+ dimensions = ob.getDimensions(param);
+ switch (ob.getType(param)) {
+ case FLOAT:
+ case DOUBLE:
+ case INT:
+ case LONG:
+ if (dimensions == 1) {
+ value = ob.getNumber(param);
+ } else if (dimensions == 2) {
+ Number[] values = ob.getNumberAllLevels(param);
+ if (element.index != -1 && values != null
+ && element.index < values.length) {
+ value = values[element.index];
+ }
+ }
+ if (isValidValue(value)) {
+ double displayValue = 0.0;
+ if (element.unit != null) {
+ if (element.converter == null) {
+ try {
+ Unit> unit = UnitFormat.getUCUMInstance()
+ .parseProductUnit(element.unit,
+ new ParsePosition(0));
+ element.converter = ob.getUnit(param)
+ .getConverterTo(unit);
+ } catch (ParseException e) {
+ throw new VizException("Unable parse units ", e);
+ }
+ }
+ displayValue = element.converter.convert(value
+ .doubleValue());
+ } else {
+ displayValue = value.doubleValue();
+ }
+ if (element.format != null) {
+ StringBuilder sb = new StringBuilder();
+ Formatter testing = new Formatter(sb);
+ testing.format(element.format, displayValue);
+ sValue = sb.toString();
+ testing.close();
+ } else {
+ sValue = Double.toString(displayValue);
+ }
+ sValue = sValue.substring(element.trim);
+ element.plotNode.setNodeValue(sValue);
+ } else if (plotMissingData) {
+ element.plotNode.setNodeValue("m");
} else {
- sValue = Double.toString(displayValue);
+ element.plotNode.setNodeValue("");
}
- element.plotNode.setNodeValue(sValue.substring(element.trim));
- } else if ((sValue = ob.getString(element.parameter)) != null) {
- element.plotNode.setNodeValue(ob.getString(element.parameter));
- } else {
+ break;
+ case STRING:
+ element.plotNode.setNodeValue(ob.getString(param));
+ break;
+ default:
element.plotNode.setNodeValue(" ");
}
}
- private void processBarbDirective(IDecoderGettable ob,
- PlotModelElement element) throws VizException {
+ private boolean processBarbDirective(PlotData ob, PlotModelElement element)
+ throws VizException {
String[] windParams = element.parameter.split(",");
- Amount windSpeed = ob.getValue(windParams[0]);
- Amount windDir = ob.getValue(windParams[1]);
- Amount windGust = null;
+ Number windSpeed = ob.getNumber(windParams[0]);
+ Unit> speedUnit = ob.getUnit(windParams[0]);
+ Number windDir = ob.getNumber(windParams[1]);
+ Number windGust = null;
if (windParams.length == 3) {
- windGust = ob.getValue(windParams[2]);
+ windGust = ob.getNumber(windParams[2]);
}
double dWindDir = -9999.0;
double cWindSpeed = -9999.0;
- double cWindGust = -9999.0;
- if (element.unit != null && windSpeed != null) {
+
+ if (element.unit != null && isValidValue(windSpeed)
+ && windSpeed.intValue() != -9999) {
+ if (element.converter == null) {
+ try {
+ Unit> unit = UnitFormat.getUCUMInstance()
+ .parseProductUnit(element.unit,
+ new ParsePosition(0));
+ element.converter = speedUnit.getConverterTo(unit);
+ } catch (ParseException e) {
+ throw new VizException("Unable parse units ", e);
+ }
+ }
+ cWindSpeed = element.converter.convert(windSpeed.doubleValue());
+ } else if (windSpeed != null) {
+ cWindSpeed = windSpeed.doubleValue();
+ }
+ if (windDir != null) {
+ dWindDir = windDir.doubleValue();
+ }
+
+ if (isValidValue(cWindSpeed)) {
+ // Element eWindSpeed =
+ // (Element)element.plotElement.getChildNodes().item(0)
+ if (element.winds.barbElement != null) {
+ if (cWindSpeed == -9999.0 && plotMissingData) {
+ element.winds.barbElement.removeAttribute("transform");
+ element.winds.barbNode.setNodeValue("m");
+ } else if (cWindSpeed >= 0 && cWindSpeed < 2.5) {
+ element.winds.barbElement.removeAttribute("transform");
+ element.winds.barbNode.setNodeValue("0");
+ } else if (cWindSpeed >= 2.5 && dWindDir != -9999.0) {
+ dWindDir -= this.gc.getAzimuth();
+ int iWindSpeed = this.windNormalizer(cWindSpeed);
+ element.winds.barbElement.setAttribute("transform",
+ "rotate(" + dWindDir + ",0,0)");
+ element.winds.barbNode.setNodeValue(Integer
+ .toString(iWindSpeed));
+ } else {
+
+ element.winds.barbElement.removeAttribute("transform");
+ element.winds.barbNode.setNodeValue(" ");
+ }
+ }
+ renderArrow(windGust, windDir, speedUnit, element);
+ } else {
+ if (element.winds.barbElement != null) {
+ element.winds.barbNode.setNodeValue(" ");
+ }
+ renderArrow(windGust, windDir, speedUnit, element);
+ return false;
+ }
+ return true;
+ }
+
+ private void processArrowDirective(PlotData ob, PlotModelElement element)
+ throws VizException {
+ String[] params = element.parameter.split(",");
+ Number magnitude = ob.getNumber(params[0]);
+ Unit> speedUnit = ob.getUnit(params[0]);
+ Number direction = ob.getNumber(params[1]);
+ renderArrow(magnitude, direction, speedUnit, element);
+ }
+
+ private void renderArrow(Number magnitude, Number direction,
+ Unit> speedUnit, PlotModelElement element) throws VizException {
+ double dDir = -9999.0;
+ double cMag = -9999.0;
+ if (element.unit != null && magnitude != null) {
if (element.converter == null) {
try {
Unit> unit = UnitFormat
.getUCUMInstance()
.parseSingleUnit(element.unit, new ParsePosition(0));
- element.converter = windSpeed.getUnit()
- .getConverterTo(unit);
+ element.converter = speedUnit.getConverterTo(unit);
} catch (ParseException e) {
throw new VizException("Unable parse units ", e);
}
}
- if (windSpeed != null && windSpeed.doubleValue() != -9999.0) {
- cWindSpeed = element.converter.convert(windSpeed.doubleValue());
- }
- if (windGust != null && windGust.doubleValue() != -9999.0) {
- cWindGust = element.converter.convert(windGust.doubleValue());
- }
- } else if (windSpeed != null) {
- if (windSpeed != null) {
- cWindSpeed = windSpeed.doubleValue();
- }
- if (windGust != null) {
- cWindGust = windGust.doubleValue();
+ if (isValidValue(magnitude)) {
+ cMag = element.converter.convert(magnitude.doubleValue());
}
+ } else if (magnitude != null) {
+ cMag = magnitude.doubleValue();
}
- if (windDir != null) {
- dWindDir = windDir.doubleValue();
+ if (direction != null) {
+ dDir = direction.doubleValue();
}
- // Element eWindSpeed =
- // (Element)element.plotElement.getChildNodes().item(0)
- if (element.winds.barbElement != null) {
- if (cWindSpeed >= 0 && cWindSpeed < 3.0) {
- element.winds.barbElement.removeAttribute("transform");
- element.winds.barbNode.setNodeValue("0");
- } else if (cWindSpeed >= 3.0 && dWindDir != -9999.0) {
- dWindDir -= this.gc.getAzimuth();
- int iWindSpeed = this.windNormalizer(cWindSpeed);
- element.winds.barbElement.setAttribute("transform", "rotate("
- + dWindDir + ",0,0)");
- element.winds.barbNode.setNodeValue(Integer
- .toString(iWindSpeed));
- } else {
- element.winds.barbElement.removeAttribute("transform");
- element.winds.barbNode.setNodeValue(" ");
- }
- }
- if (element.winds.arrowElement != null) {
- if (dWindDir != -9999.0 && cWindGust != -9999.0) {
- dWindDir -= this.gc.getAzimuth();
+ if (dDir != -9999.0 && cMag != -9999.0) {
+ dDir -= this.gc.getAzimuth();
+ String arrowType = null;
+ if (element.winds.arrowElement != null) {
element.winds.arrowElement.setAttribute("transform", "rotate("
- + dWindDir + ",0,0)");
- element.winds.arrowNode.setNodeValue("arrow");
- } else {
- element.winds.arrowElement.removeAttribute("transform");
- element.winds.arrowNode.setNodeValue(" ");
+ + dDir + ",0,0)");
+ arrowType = element.winds.arrowElement
+ .getAttribute("arrowtype");
+ if ("arrow1".equals(arrowType) || "arrow2".equals(arrowType)) {
+ element.winds.arrowNode.setNodeValue(arrowType);
+ } else {
+ element.winds.arrowNode.setNodeValue("arrow");
+ }
}
- }
- if (element.winds.gustElement != null) {
- if (dWindDir != -9999.0 && cWindGust != -9999.0) {
- dWindDir -= this.gc.getAzimuth();
- double rWindDir = Math.toRadians(dWindDir + 180.0);
- long x = Math.round(32.0 * Math.sin(rWindDir));
- long y = Math.round(32.0 * Math.cos(rWindDir)) * -1;
+ if (element.winds.gustElement != null) {
+ double len = 32.0;
+ if ("arrow1".equals(arrowType) || "arrow2".equals(arrowType)) {
+ try {
+ len = Double.parseDouble(element.winds.gustY);
+ } catch (NumberFormatException nfe) {
+ len = 32.0;
+ }
+ }
+
+ double rWindDir = Math.toRadians(dDir + 180.0);
+
+ long x = Math.round(len * Math.sin(rWindDir));
+ long y = Math.round(len * Math.cos(rWindDir)) * -1;
+
element.winds.gustElement.setAttribute("x", Long.toString(x));
element.winds.gustElement.setAttribute("y", Long.toString(y));
element.winds.gustNode.setNodeValue(Integer
- .toString(((int) cWindGust)));
- } else {
+ .toString(((int) Math.round(cMag))));
+ }
+
+ } else {
+ if (element.winds.arrowElement != null) {
+ element.winds.arrowElement.removeAttribute("transform");
+ element.winds.arrowNode.setNodeValue(" ");
+ }
+ if (element.winds.gustElement != null) {
element.winds.gustNode.setNodeValue(" ");
}
}
}
- private void processTableDirective(IDecoderGettable ob,
- PlotModelElement element) {
- String[] fields = ob.getStrings(element.parameter);
+ private void processTableDirective(PlotData ob, PlotModelElement element) {
+
+ int dimensions = ob.getDimensions(element.parameter);
String display = null;
- if (element.ranking != null && fields != null) {
+ String[] fields = null;
+ switch (ob.getType(element.parameter)) {
+ case FLOAT:
+ case DOUBLE:
+ case INT:
+ case LONG:
+ if (dimensions == 1) {
+ Number n = ob.getNumber(element.parameter);
+ if ((n != null) && (n.doubleValue() != -9999)) {
+ if ((n.doubleValue() != -9999)
+ && (!Double.isNaN(n.doubleValue()))) {
+ display = n.toString();
+ }
+ }
+ } else if (dimensions == 2) {
+ Number[] values = ob.getNumberAllLevels(element.parameter);
+ fields = numberToStringArray(values);
+ }
+ break;
+ case STRING:
+ if (dimensions == 1) {
+ display = ob.getString(element.parameter);
+ } else if (dimensions == 2) {
+ fields = ob.getStringAllLevels(element.parameter);
+ }
+ break;
+ default:
+ element.plotNode.setNodeValue(" ");
+ }
+ if (element.index != -1 && element.index < fields.length) {
+ display = fields[element.index];
+ } else if (element.ranking != null && fields != null) {
display = element.ranking.getRankedField(fields);
- } else if (fields != null) {
- display = fields[0];
+ } else if ((fields != null) && (fields.length > 0)) {
+ StringBuilder sb = new StringBuilder(fields[fields.length - 1]);
+ for (int i = fields.length - 2; i >= 0; i--) {
+ sb.append(" ");
+ sb.append(fields[i]);
+ }
+ display = sb.toString().trim();
}
+
if (element.lookup != null) {
- display = element.lookup.recursiveTranslation(display);
+ display = element.lookup.lookup(display);
}
+
if (display != null) {
element.plotNode.setNodeValue(display);
} else {
@@ -597,45 +1035,143 @@ public class PlotModelFactory {
}
}
- private void processRangeDirective(IDecoderGettable ob,
- PlotModelElement element) throws VizException {
- Amount value = ob.getValue(element.parameter);
+ private String processSampleDirective(PlotData ob, PlotModelElement element)
+ throws VizException {
String sValue = null;
- if (value != null && value.doubleValue() != -9999.0) {
- double displayValue = 0.0;
- if (element.unit != null) {
- if (element.converter == null) {
- try {
- Unit> unit = UnitFormat.getUCUMInstance()
- .parseSingleUnit(element.unit,
- new ParsePosition(0));
- element.converter = value.getUnit()
- .getConverterTo(unit);
- } catch (ParseException e) {
- throw new VizException("Unable parse units ", e);
+ String parameter = element.parameter;
+ switch (ob.getType(parameter)) {
+ case FLOAT:
+ case DOUBLE:
+ case INT:
+ case LONG:
+ Number value = ob.getNumber(parameter);
+ if (value != null && value.doubleValue() != -9999.0) {
+ double displayValue = 0.0;
+
+ if (element.unit != null) {
+ if (element.converter == null) {
+ try {
+ Unit> unit = UnitFormat.getUCUMInstance()
+ .parseSingleUnit(element.unit,
+ new ParsePosition(0));
+ element.converter = ob.getUnit(parameter)
+ .getConverterTo(unit);
+ } catch (ParseException e) {
+ throw new VizException("Unable parse units ", e);
+ }
}
+ displayValue = element.converter.convert(value
+ .doubleValue());
+ } else {
+ displayValue = value.doubleValue();
}
- displayValue = element.converter.convert(value.doubleValue());
+ if (element.format != null) {
+ if (element.format.equals("time")) {
+ Date d = new Date(new Double(displayValue).longValue());
+ SAMPLE_DATE.setTimeZone(TimeZone.getTimeZone("UTC"));
+ sValue = SAMPLE_DATE.format(d);
+ } else if (element.format.startsWith("time:")) {
+ Date d = new Date(new Double(displayValue).longValue());
+ SimpleDateFormat sampleData = new SimpleDateFormat(
+ element.format.substring(5));
+ sampleData.setTimeZone(TimeZone.getTimeZone("UTC"));
+ sValue = sampleData.format(d);
+ } else {
+ StringBuilder sb = new StringBuilder();
+ Formatter testing = new Formatter(sb);
+ testing.format(element.format, displayValue);
+ sValue = sb.toString();
+ testing.close();
+ }
+ } else {
+ sValue = Double.toString(displayValue);
+ }
+ sValue = sValue.substring(element.trim);
} else {
- displayValue = value.doubleValue();
+ sValue = "?";
}
- if (element.format != null) {
- StringBuilder sb = new StringBuilder();
- Formatter testing = new Formatter(sb);
- testing.format(element.format, displayValue);
- sValue = sb.toString();
- } else {
- sValue = Double.toString(displayValue);
+ break;
+ case STRING:
+ sValue = ob.getString(parameter);
+ break;
+ }
+
+ if (element.lookup != null && sValue != null) {
+ String lu = null;
+ lu = element.lookup.lookup(sValue);
+ if (lu != null) {
+ sValue = lu.trim();
}
}
+ if (sValue != null && element.symbol != null) {
+ sValue = sValue + element.symbol;
+ }
+
+ return sValue + " ";
+ }
+
+ private boolean processRangeDirective(PlotData ob, PlotModelElement element)
+ throws VizException {
+
+ String sValue = null;
+ switch (ob.getType(element.parameter)) {
+ case FLOAT:
+ case DOUBLE:
+ case INT:
+ case LONG:
+ Number value = ob.getNumber(element.parameter);
+ if (value != null && value.doubleValue() != -9999.0) {
+ if (value.doubleValue() >= lowerLimit
+ && value.doubleValue() <= upperLimit) {
+ double displayValue = 0.0;
+ if (element.unit != null) {
+ if (element.converter == null) {
+ try {
+ Unit> unit = UnitFormat.getUCUMInstance()
+ .parseProductUnit(element.unit,
+ new ParsePosition(0));
+ element.converter = ob.getUnit(
+ element.parameter).getConverterTo(unit);
+ } catch (ParseException e) {
+ throw new VizException("Unable parse units ", e);
+ }
+ }
+ displayValue = element.converter.convert(value
+ .doubleValue());
+ } else {
+ displayValue = value.doubleValue();
+ }
+ if (element.format != null) {
+ StringBuilder sb = new StringBuilder();
+ Formatter testing = new Formatter(sb);
+ testing.format(element.format, displayValue);
+ sValue = sb.toString();
+ testing.close();
+ } else {
+ sValue = Double.toString(displayValue);
+ }
+ }
+ }
+ break;
+ case STRING:
+ sValue = ob.getString(element.parameter);
+ break;
+ default:
+ element.plotNode.setNodeValue(" ");
+ }
if (element.lookup != null) {
- sValue = element.lookup.determineRange(sValue);
+ sValue = element.lookup.lookup(sValue);
}
if (sValue != null) {
element.plotNode.setNodeValue(sValue.substring(element.trim));
+ return !sValue.trim().isEmpty();
+ } else if (plotMissingData) {
+ element.plotNode.setNodeValue("m");
+ return true;
} else {
element.plotNode.setNodeValue(" ");
+ return false;
}
}
@@ -647,11 +1183,14 @@ public class PlotModelFactory {
* @param element
* PlotModelElement object
*/
- private void processAvailDirective(IDecoderGettable ob,
- PlotModelElement element) {
+ private void processAvailDirective(PlotModelElement element) {
element.plotNode.setNodeValue("*");
}
+ private void processNullDirective(PlotModelElement element) {
+ element.plotNode.setNodeValue(" ");
+ }
+
/**
* Returns the corresponding windbarb character to the actual speed
*
@@ -659,7 +1198,7 @@ public class PlotModelFactory {
* @return The character that corresponds to the nearest 5 knot speed
*/
private int windNormalizer(double dWindSpeed) {
- int windSpeed = (int) dWindSpeed;
+ int windSpeed = (int) Math.round(dWindSpeed);
int major = windSpeed / 5;
int minor = windSpeed % 5;
if (minor >= 3) {
@@ -667,4 +1206,79 @@ public class PlotModelFactory {
}
return major * 5;
}
+
+ public List getPlotFields() {
+ return Collections.unmodifiableList(this.plotFields);
+ }
+
+ /**
+ * Convert an array of Numbers to their String representation. Note that
+ * indexing may be used on the return array so the output size must match
+ * the input size.
+ *
+ * @param values
+ * An array of Number to convert.
+ * @return The converted data. If the input is null, the return will be
+ * null.
+ */
+ private String[] numberToStringArray(Number[] values) {
+ String[] retVal = null;
+ if (values != null) {
+ retVal = new String[values.length];
+ Arrays.fill(retVal, "");
+ for (int i = 0; i < values.length; i++) {
+ Number n = values[i];
+ if ((n.doubleValue() != -9999)
+ && (!Double.isNaN(n.doubleValue()))) {
+ retVal[i] = n.toString();
+ }
+ }
+ }
+ return retVal;
+ }
+
+ public void setLowerLimit(double lowerLimit) {
+ this.lowerLimit = lowerLimit;
+ }
+
+ public void setUpperLimit(double upperLimit) {
+ this.upperLimit = upperLimit;
+ }
+
+ private boolean isValidValue(Number value) {
+ return value != null && value.doubleValue() > lowerLimit
+ && value.doubleValue() <= upperLimit;
+ }
+
+ public void setPlotMissingData(boolean b) {
+ this.plotMissingData = b;
+ }
+
+ private File getTableFile(String fileName) {
+ File rval = PathManagerFactory.getPathManager().getStaticFile(
+ PLOT_MODEL_DIR + IPathManager.SEPARATOR + fileName);
+ return rval;
+ }
+
+ public List getSampleFields() {
+ return Collections.unmodifiableList(this.sampleFields);
+ }
+
+ public boolean isCachingImages() {
+ return imageCache != null;
+ }
+
+ public String getPlotModelFilename() {
+ return this.plotModelFile;
+ }
+
+ /**
+ * Disposes of the plot model
+ */
+ public void dispose() {
+ if (python != null) {
+ python.shutdown();
+ }
+ }
+
}
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelFactory2.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelFactory2.java
deleted file mode 100644
index b247391ff5..0000000000
--- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelFactory2.java
+++ /dev/null
@@ -1,1277 +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.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.IndexColorModel;
-import java.io.File;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Formatter;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TimeZone;
-
-import javax.measure.converter.UnitConverter;
-import javax.measure.unit.Unit;
-import javax.measure.unit.UnitFormat;
-
-import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.bridge.GVTBuilder;
-import org.apache.batik.bridge.UserAgentAdapter;
-import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
-import org.apache.batik.gvt.GraphicsNode;
-import org.apache.batik.util.XMLResourceDescriptor;
-import org.eclipse.swt.graphics.RGB;
-import org.geotools.referencing.GeodeticCalculator;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Text;
-
-import com.raytheon.uf.common.localization.IPathManager;
-import com.raytheon.uf.common.localization.PathManagerFactory;
-import com.raytheon.uf.common.python.concurrent.PythonJobCoordinator;
-import com.raytheon.uf.common.status.IUFStatusHandler;
-import com.raytheon.uf.common.status.UFStatus;
-import com.raytheon.uf.common.status.UFStatus.Priority;
-import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
-import com.raytheon.uf.viz.core.exception.VizException;
-import com.raytheon.uf.viz.core.map.IMapDescriptor;
-import com.raytheon.viz.pointdata.lookup.IAbstractLookupTable;
-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.PlotResourceData;
-
-/**
- * A factory for generating plot images and sample messages by parsing the
- * associated plotModel SVG file.
- *
- *
- *
- * SOFTWARE HISTORY
- *
- * Date Ticket# Engineer Description
- * ------------- -------- ----------- --------------------------
- * Nov 20, 2006 brockwoo Initial creation.
- * Mar 16, 2009 jsanchez Added processAvailDirective.
- * Jun 29, 2009 2538 jsanchez Implemented pointdata.
- * Aug 09, 2012 1085 jkorman Corrected data construction.
- * Sep 05, 2013 2316 bsteffen Unify pirep and ncpirep.
- * Sep 05, 2013 2307 dgilling Use better PythonScript constructor.
- * Nov 20, 2013 2033 njensen Fix detecting plotModels dirs from multiple plugins
- * Mar 21, 2014 2868 njensen Refactored python usage to PythonJobCoordinator
- *
- *
- *
- * @author BRock97
- * @version 1.0
- */
-public class PlotModelFactory2 {
- private static final transient IUFStatusHandler statusHandler = UFStatus
- .getHandler(PlotModelFactory2.class);
-
- public static final String PLOT_MODEL_DIR = "plotModels";
-
- private static final String DM_ATTRIBUTE = "plotMode";
-
- private static final String P_ATTRIBUTE = "plotParam";
-
- private static final String FMT_ATTRIBUTE = "plotFormat";
-
- private static final String UNIT_ATTRIBUTE = "plotUnit";
-
- private static final String SYMBOL_ATTRIBUTE = "plotSymbol";
-
- private static final String TRIM_ATTRIBUTE = "plotTrim";
-
- private static final String PFT_ATTRIBUTE = "plotFunctionTable";
-
- private static final String PLT_ATTRIBUTE = "plotLookupTable";
-
- private static final String PLT_INDEX = "plotIndex";
-
- private static final String REQUIRED = "required";
-
- private final SimpleDateFormat SAMPLE_DATE = new SimpleDateFormat("HHmm");
-
- // Need to include attribute and code to allow for String2String lookups and
- // String2Number lookups
- // to support clouds and present weather
-
- private int width = 1;
-
- private LineStyle lineStyle = LineStyle.DEFAULT;
-
- private String currentStyleStr;
-
- private Document document;
-
- private final GVTBuilder builder;
-
- private final BridgeContext bridgeContext;
-
- private int plotModelWidth;
-
- private int plotModelHeight;
-
- private final int originalPlotModelWidth;
-
- private final int originalPlotModelHeight;
-
- private final Element svgRoot;
-
- private final GeodeticCalculator gc;
-
- private final IMapDescriptor mapDescriptor;
-
- private IndexColorModel tm;
-
- private final List plotFields;
-
- private final List sampleFields;
-
- private double lowerLimit = -9999.0;
-
- private double upperLimit = -9999.0;
-
- private boolean plotMissingData = false;
-
- private Map imageCache = null;
-
- protected final String plotModelFile;
-
- protected PythonJobCoordinator python;
-
- public static enum DisplayMode {
- TEXT, BARB, TABLE, AVAIL, RANGE, NULL, SAMPLE, ARROW
- }
-
- public class PlotModelElement {
- DisplayMode mode = DisplayMode.TEXT;
-
- String format = null;
-
- String parameter = null;
-
- String unit = null;
-
- String symbol = null;
-
- int trim = 0;
-
- int index = -1;
-
- UnitConverter converter = null;
-
- Element plotElement = null;
-
- Node plotNode = null;
-
- S2N ranking = null;
-
- IAbstractLookupTable lookup = null;
-
- PlotWindElement winds = null;
-
- boolean required = false;
-
- public Node getPlotNode() {
- return plotNode;
- }
-
- public String getParameter() {
- return parameter;
- }
- }
-
- public class PlotWindElement {
- Node barbNode = null;
-
- Element barbElement = null;
-
- Node arrowNode = null;
-
- Element arrowElement = null;
-
- Node gustNode = null;
-
- Element gustElement = null;
-
- String gustX = null;
-
- String gustY = null;
- }
-
- public PlotModelFactory2(IMapDescriptor mapDescriptor, String plotModelFile) {
- byte full = (byte) 255;
- byte zero = (byte) 0;
- byte[] red = { 0, zero };
- byte[] blue = { 0, full };
- byte[] green = { 0, zero };
- regenerateStyle();
- this.plotModelFile = plotModelFile;
- this.plotFields = new ArrayList();
- this.sampleFields = new ArrayList();
-
- tm = new IndexColorModel(8, 2, red, blue, green, 0);
- this.gc = new GeodeticCalculator(mapDescriptor.getCRS());
- this.mapDescriptor = mapDescriptor;
- String parser = XMLResourceDescriptor.getXMLParserClassName();
- SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
- try {
- document = f.createDocument(PathManagerFactory.getPathManager()
- .getStaticFile(PlotResourceData.PLOT_DIR + plotModelFile)
- .toURI().toString());
- } catch (Exception e) {
- statusHandler.handle(Priority.PROBLEM, "Error parsing svg file", e);
- }
- this.svgRoot = document.getDocumentElement();
- this.originalPlotModelWidth = Integer.parseInt(svgRoot.getAttributeNS(
- null, "width"));
- this.originalPlotModelHeight = Integer.parseInt(svgRoot.getAttributeNS(
- null, "height"));
- this.plotModelWidth = this.originalPlotModelWidth;
- this.plotModelHeight = this.originalPlotModelHeight;
-
- int displayedElementCount = 0;
-
- Element plot = document.getElementById("plotData");
- NodeList plotElements = plot.getChildNodes();
-
- for (int i = 0; i < plotElements.getLength(); i++) {
- if (Node.ELEMENT_NODE == plotElements.item(i).getNodeType()) {
- Element plotElement = (Element) plotElements.item(i);
- if (plotElement.hasAttribute(DM_ATTRIBUTE)) {
- PlotModelElement thisElement = new PlotModelElement();
- thisElement.plotElement = plotElement;
- thisElement.plotNode = plotElement.getChildNodes().item(0);
- if (plotElement.getAttribute(DM_ATTRIBUTE).equals("text")) {
- thisElement.mode = DisplayMode.TEXT;
- plotElement.setAttribute("class", "text");
- displayedElementCount++;
- } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "barb")) {
- thisElement.mode = DisplayMode.BARB;
- thisElement.winds = new PlotWindElement();
- NodeList windElements = plotElement.getChildNodes();
- for (int j = 0; j < windElements.getLength(); j++) {
- if (Node.ELEMENT_NODE == windElements.item(j)
- .getNodeType()) {
- Element windElement = (Element) windElements
- .item(j);
- if (windElement.getAttribute("class").matches(
- "arrow")) {
- thisElement.winds.arrowElement = windElement;
- thisElement.winds.arrowNode = windElement
- .getChildNodes().item(0);
- } else if (windElement.getAttribute("class")
- .matches("barb")) {
- thisElement.winds.barbElement = windElement;
- thisElement.winds.barbNode = windElement
- .getChildNodes().item(0);
- } else if (windElement.getAttribute("class")
- .matches("text")) {
- thisElement.winds.gustElement = windElement;
- thisElement.winds.gustNode = windElement
- .getChildNodes().item(0);
- thisElement.winds.gustX = windElement
- .getAttribute("x");
- thisElement.winds.gustY = windElement
- .getAttribute("y");
- }
- }
- }
- displayedElementCount++;
- } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "arrowuv")) {
- thisElement.mode = DisplayMode.ARROW;
- thisElement.winds = new PlotWindElement();
- NodeList windElements = plotElement.getChildNodes();
- for (int j = 0; j < windElements.getLength(); j++) {
- if (Node.ELEMENT_NODE == windElements.item(j)
- .getNodeType()) {
- Element windElement = (Element) windElements
- .item(j);
- String attrClass = windElement
- .getAttribute("class");
- if ("arrow".matches(attrClass)) {
- thisElement.winds.arrowElement = windElement;
- thisElement.winds.arrowNode = windElement
- .getChildNodes().item(0);
- } else if ("arrow1".matches(attrClass)) {
- thisElement.winds.arrowElement = windElement;
- thisElement.winds.arrowNode = windElement
- .getChildNodes().item(0);
- thisElement.winds.arrowElement
- .setAttribute("arrowtype",
- attrClass);
- } else if ("arrow2".matches(attrClass)) {
- thisElement.winds.arrowElement = windElement;
- thisElement.winds.arrowNode = windElement
- .getChildNodes().item(0);
- thisElement.winds.arrowElement
- .setAttribute("arrowtype",
- attrClass);
- } else if ("text".matches(attrClass)) {
- thisElement.winds.gustElement = windElement;
- thisElement.winds.gustNode = windElement
- .getChildNodes().item(0);
- thisElement.winds.gustX = windElement
- .getAttribute("x");
- thisElement.winds.gustY = windElement
- .getAttribute("y");
- }
- }
- }
- displayedElementCount++;
- } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "table")
- || plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "recursive_translation")) {
- thisElement.mode = DisplayMode.TABLE;
- if (plotElement.hasAttribute(PFT_ATTRIBUTE)) {
- thisElement.ranking = S2N.readS2NFile(plotElement
- .getAttribute(PFT_ATTRIBUTE));
- }
- if (plotElement.hasAttribute(PLT_ATTRIBUTE)) {
- File table = getTableFile(plotElement
- .getAttribute(PLT_ATTRIBUTE));
- thisElement.lookup = LookupUtils
- .buildLookupTable(table);
- thisElement.lookup.setMode(plotElement
- .getAttribute(DM_ATTRIBUTE));
- }
- displayedElementCount++;
- } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "arrow")) {
- plotElement.setAttribute("class", "text");
- thisElement.mode = DisplayMode.BARB;
- displayedElementCount++;
- } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "available")) {
- thisElement.mode = DisplayMode.AVAIL;
- plotElement.setAttribute("class", "text");
- displayedElementCount++;
- } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "range")) {
- thisElement.mode = DisplayMode.RANGE;
- if (plotElement.hasAttribute(PLT_ATTRIBUTE)) {
- File table = getTableFile(plotElement
- .getAttribute(PLT_ATTRIBUTE));
- thisElement.lookup = LookupUtils
- .buildLookupTable(table);
- thisElement.lookup.setMode(plotElement
- .getAttribute(DM_ATTRIBUTE));
- }
- displayedElementCount++;
- } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "null")) {
- thisElement.mode = DisplayMode.NULL;
- } else if (plotElement.getAttribute(DM_ATTRIBUTE).equals(
- "sample")) {
- thisElement.mode = DisplayMode.SAMPLE;
- if (plotElement.hasAttribute(PLT_ATTRIBUTE)) {
- File table = getTableFile(plotElement
- .getAttribute(PLT_ATTRIBUTE));
- thisElement.lookup = LookupUtils
- .buildLookupTable(table);
- thisElement.lookup.setMode(plotElement
- .getAttribute(DM_ATTRIBUTE));
- }
- }
- thisElement.parameter = plotElement
- .getAttribute(P_ATTRIBUTE);
- if (plotElement.hasAttribute(FMT_ATTRIBUTE)) {
- thisElement.format = plotElement
- .getAttribute(FMT_ATTRIBUTE);
- }
- if (plotElement.hasAttribute(UNIT_ATTRIBUTE)) {
- thisElement.unit = plotElement
- .getAttribute(UNIT_ATTRIBUTE);
- }
- if (plotElement.hasAttribute(SYMBOL_ATTRIBUTE)) {
- thisElement.symbol = plotElement
- .getAttribute(SYMBOL_ATTRIBUTE);
- }
- if (plotElement.hasAttribute(TRIM_ATTRIBUTE)) {
- thisElement.trim = Integer.parseInt(plotElement
- .getAttribute(TRIM_ATTRIBUTE));
- }
- if (plotElement.hasAttribute(PLT_INDEX)) {
- thisElement.index = Integer.parseInt(plotElement
- .getAttribute(PLT_INDEX));
- }
- if (plotElement.hasAttribute(REQUIRED)) {
- thisElement.required = Boolean.parseBoolean(plotElement
- .getAttribute(REQUIRED));
- }
- if (thisElement.mode != DisplayMode.SAMPLE) {
- this.plotFields.add(thisElement);
- } else {
- this.sampleFields.add(thisElement);
- thisElement.plotNode.setNodeValue("");
- }
- }
- }
- }
-
- if (displayedElementCount <= 3) {
- // Dont use image caching if more then 3 elements are used, with
- // very few elements the hit rate is good enought to risk keeping
- // the images in memory, but with more elements the hit rate drops
- // and the cache size increases. 3 elements might not be the optimal
- // way of detecting complexity but it is better than nothing.
- imageCache = new HashMap();
- }
- NodeList scriptNodes = document.getElementsByTagName("script");
-
- // Only one script node supported
- 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);
- String plotDelegateName = scriptNode.getAttribute("plotDelegate");
- NodeList childNodes = scriptNode.getChildNodes();
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < childNodes.getLength(); i++) {
- Node child = childNodes.item(i);
- if (Node.TEXT_NODE == child.getNodeType()) {
- sb.append(((Text) child).getData());
- }
- }
- String scriptText = sb.toString().trim();
- if (scriptText.length() > 0) {
- PlotPythonScriptFactory pythonFactory = new PlotPythonScriptFactory(
- plotModelFile, scriptText, plotDelegateName);
- python = PythonJobCoordinator.newInstance(pythonFactory);
- }
-
- // remove the scriptNode in memory so time isn't wasted
- // later attempting to render it
- scriptNode.getParentNode().removeChild(scriptNode);
- }
-
- UserAgentAdapter userAgentAdapter = new UserAgentAdapter();
- this.bridgeContext = new BridgeContext(userAgentAdapter);
- this.builder = new GVTBuilder();
- }
-
- public void setColor(RGB color) {
- if (imageCache != null) {
- imageCache.clear();
- }
- byte fullr = (byte) color.red;
- byte fullg = (byte) color.green;
- byte fullb = (byte) color.blue;
- // String style = "stroke: rgb(" + color.red + "," + color.green + ","
- // + color.blue + ");";
- // this.svgRoot.setAttribute("style", style);
- // System.out.println(style);
- byte[] red = { 0, fullr };
- byte[] blue = { 0, fullb };
- byte[] green = { 0, fullg };
- tm = new IndexColorModel(8, 2, red, green, blue, 0);
- // System.out.println(style);
- }
-
- public void setLineWidth(int width) {
- if (imageCache != null) {
- imageCache.clear();
- }
- this.width = width;
- regenerateStyle();
- }
-
- public void setLineStyle(LineStyle style) {
- if (imageCache != null) {
- imageCache.clear();
- }
- this.lineStyle = style;
- regenerateStyle();
- }
-
- private void regenerateStyle() {
- String strokeStart = "stroke-dasharray: ";
- switch (lineStyle) {
- case DASH_DOTTED: {
- strokeStart += "3, 2, 1, 2";
- break;
- }
- case DASHED: {
- strokeStart += "4, 4";
- break;
- }
- case DASHED_LARGE: {
- strokeStart += "12, 4";
- break;
- }
- case DOTTED: {
- strokeStart += "1, 1";
- break;
- }
- default: {
- strokeStart += "1, 0";
- break;
- }
- }
-
- strokeStart += "; stroke-width: " + width + ";";
-
- currentStyleStr = strokeStart;
- }
-
- public void setPlotDimensions(long x, long y) {
- if (imageCache != null) {
- imageCache.clear();
- }
- this.svgRoot.setAttributeNS(null, "width", Long.toString(x));
- this.svgRoot.setAttributeNS(null, "height", Long.toString(y));
- this.plotModelWidth = (int) x;
- this.plotModelHeight = (int) y;
- }
-
- public int getDefinedPlotModelWidth() {
- return this.originalPlotModelWidth;
- }
-
- public int getDefinedPlotModelHeight() {
- return this.originalPlotModelHeight;
- }
-
- /**
- * Takes the station data object and produces a buffered image.
- *
- * @param station
- * The station name
- * @param stationData
- * A metar record for that station
- * @return A buffered image representing the station data
- */
- public synchronized BufferedImage getStationPlot(PlotData stationData,
- double latitude, double longitude) {
- double[] stationLocation = { longitude, latitude };
- double[] stationPixelLocation = this.mapDescriptor
- .worldToPixel(stationLocation);
-
- if (stationPixelLocation != null) {
- stationPixelLocation[1]--;
- double[] newWorldLocation = this.mapDescriptor
- .pixelToWorld(stationPixelLocation);
- this.gc.setStartingGeographicPoint(stationLocation[0],
- stationLocation[1]);
- this.gc.setDestinationGeographicPoint(newWorldLocation[0],
- newWorldLocation[1]);
- }
-
- try {
- boolean discard = false;
- if (python != null) {
- Boolean result = false;
- CheckPlotValidityExecutor task = new CheckPlotValidityExecutor(
- stationData);
- try {
- result = python.submitSyncJob(task);
- } catch (Exception e) {
- statusHandler.handle(Priority.PROBLEM,
- "Error checking if plot is valid for plot model "
- + getPlotModelFilename(), e);
- } finally {
- if (result.booleanValue() == false) {
- return null;
- }
- }
- }
-
- StringBuilder imageId = new StringBuilder();
-
- for (PlotModelElement element : this.plotFields) {
- boolean valid = true;
- boolean required = element.required;
- switch (element.mode) {
- case TEXT:
- this.processTextDirective(stationData, element);
- addToImageId(stationData, element.parameter, imageId);
- break;
- case BARB:
- element.plotElement.setAttribute("style", currentStyleStr);
- valid = this.processBarbDirective(stationData, element);
- // normalize speed before adding to id so all identical
- // barbs will share plots
- String[] windParams = element.parameter.split(",");
- double speed = stationData.getNumber(windParams[0])
- .doubleValue();
- double dir = stationData.getNumber(windParams[1])
- .doubleValue();
- if (element.converter != null) {
- speed = element.converter.convert(speed);
- }
- imageId.append(windNormalizer(speed));
- // Accurate to a fourth a degree.
- imageId.append((int) (dir - gc.getAzimuth()) * 4);
- if (windParams.length == 3) {
- imageId.append(stationData.getNumber(windParams[2]));
- }
- addToImageId(stationData,
- element.parameter.split(",", 2)[1], imageId);
- break;
- case ARROW:
- element.plotElement.setAttribute("style", currentStyleStr);
- addToImageId(stationData, element.parameter, imageId);
- this.processArrowDirective(stationData, element);
- break;
- case TABLE:
- this.processTableDirective(stationData, element);
- addToImageId(stationData, element.parameter, imageId);
- break;
- case AVAIL:
- this.processAvailDirective(element);
- break;
- case RANGE:
- valid = this.processRangeDirective(stationData, element);
- addToImageId(stationData, element.parameter, imageId);
- break;
- case NULL:
- this.processNullDirective(element);
- break;
- }
- if (!valid && required) {
- discard = true;
- }
- }
-
- if (discard) {
- return null;
- }
-
- if (imageCache != null
- && imageCache.containsKey(imageId.toString())) {
- return imageCache.get(imageId.toString());
- }
-
- BufferedImage bufferedImage = new BufferedImage(
- this.plotModelWidth, this.plotModelHeight,
- BufferedImage.TYPE_BYTE_INDEXED, tm);
-
- // long t0 = System.currentTimeMillis();
- GraphicsNode graphicsNode = builder.build(this.bridgeContext,
- this.document);
- Graphics2D g2d = null;
- try {
- g2d = bufferedImage.createGraphics();
- graphicsNode.primitivePaint(g2d);
- } finally {
- if (g2d != null) {
- g2d.dispose();
- }
- }
- // System.out.println("Time building and creating graphics: "
- // + (System.currentTimeMillis() - t0));
- if (imageCache != null) {
- imageCache.put(imageId.toString(), bufferedImage);
- }
- return bufferedImage;
-
- } catch (Exception e) {
- statusHandler.handle(Priority.PROBLEM,
- "Error:" + e.getLocalizedMessage(), e);
- }
-
- return null;
- }
-
- public synchronized String getStationMessage(PlotData stationData,
- String dataURI) {
- StringBuilder sampleMessage = new StringBuilder();
- try {
- if (python != null) {
- String result = null;
- SampleTextExecutor task = new SampleTextExecutor(stationData);
- try {
- result = python.submitSyncJob(task);
- } catch (Exception e) {
- statusHandler.handle(Priority.PROBLEM,
- "Error getting sample text for plot model "
- + getPlotModelFilename(), e);
- } finally {
- if (result != null) {
- sampleMessage.append(result);
- }
- }
- } else {
- for (PlotModelElement element : this.sampleFields) {
- sampleMessage.append(processSampleDirective(stationData,
- element));
- }
- }
-
- } catch (Exception e) {
- statusHandler.handle(Priority.PROBLEM,
- "Error generating sample text with " + plotModelFile, e);
- }
-
- String message = sampleMessage.toString();
- if (message.length() == 0) {
- message = PlotResource2.NO_DATA;
- }
-
- return message;
- }
-
- private void addToImageId(PlotData stationData, String parameters,
- StringBuilder imageId) {
- for (String parameter : parameters.split(",")) {
- switch (stationData.getType(parameter)) {
- case STRING:
- imageId.append(stationData.getString(parameter));
- break;
- default:
- imageId.append(stationData.getNumber(parameter).floatValue());
- }
- }
- }
-
- private void processTextDirective(PlotData ob, PlotModelElement element)
- throws VizException {
- int dimensions = -1;
- String sValue = null;
- String param = element.parameter;
- Number value = null;
- dimensions = ob.getDimensions(param);
- switch (ob.getType(param)) {
- case FLOAT:
- case DOUBLE:
- case INT:
- case LONG:
- if (dimensions == 1) {
- value = ob.getNumber(param);
- } else if (dimensions == 2) {
- Number[] values = ob.getNumberAllLevels(param);
- if (element.index != -1 && values != null
- && element.index < values.length) {
- value = values[element.index];
- }
- }
- if (isValidValue(value)) {
- double displayValue = 0.0;
- if (element.unit != null) {
- if (element.converter == null) {
- try {
- Unit> unit = UnitFormat.getUCUMInstance()
- .parseProductUnit(element.unit,
- new ParsePosition(0));
- element.converter = ob.getUnit(param)
- .getConverterTo(unit);
- } catch (ParseException e) {
- throw new VizException("Unable parse units ", e);
- }
- }
- displayValue = element.converter.convert(value
- .doubleValue());
- } else {
- displayValue = value.doubleValue();
- }
- if (element.format != null) {
- StringBuilder sb = new StringBuilder();
- Formatter testing = new Formatter(sb);
- testing.format(element.format, displayValue);
- sValue = sb.toString();
- testing.close();
- } else {
- sValue = Double.toString(displayValue);
- }
- sValue = sValue.substring(element.trim);
- element.plotNode.setNodeValue(sValue);
- } else if (plotMissingData) {
- element.plotNode.setNodeValue("m");
- } else {
- element.plotNode.setNodeValue("");
- }
- break;
- case STRING:
- element.plotNode.setNodeValue(ob.getString(param));
- break;
- default:
- element.plotNode.setNodeValue(" ");
- }
- }
-
- private boolean processBarbDirective(PlotData ob, PlotModelElement element)
- throws VizException {
- String[] windParams = element.parameter.split(",");
- Number windSpeed = ob.getNumber(windParams[0]);
- Unit> speedUnit = ob.getUnit(windParams[0]);
- Number windDir = ob.getNumber(windParams[1]);
- Number windGust = null;
- if (windParams.length == 3) {
- windGust = ob.getNumber(windParams[2]);
- }
- double dWindDir = -9999.0;
- double cWindSpeed = -9999.0;
-
- if (element.unit != null && isValidValue(windSpeed)
- && windSpeed.intValue() != -9999) {
- if (element.converter == null) {
- try {
- Unit> unit = UnitFormat.getUCUMInstance()
- .parseProductUnit(element.unit,
- new ParsePosition(0));
- element.converter = speedUnit.getConverterTo(unit);
- } catch (ParseException e) {
- throw new VizException("Unable parse units ", e);
- }
- }
- cWindSpeed = element.converter.convert(windSpeed.doubleValue());
- } else if (windSpeed != null) {
- cWindSpeed = windSpeed.doubleValue();
- }
- if (windDir != null) {
- dWindDir = windDir.doubleValue();
- }
-
- if (isValidValue(cWindSpeed)) {
- // Element eWindSpeed =
- // (Element)element.plotElement.getChildNodes().item(0)
- if (element.winds.barbElement != null) {
- if (cWindSpeed == -9999.0 && plotMissingData) {
- element.winds.barbElement.removeAttribute("transform");
- element.winds.barbNode.setNodeValue("m");
- } else if (cWindSpeed >= 0 && cWindSpeed < 2.5) {
- element.winds.barbElement.removeAttribute("transform");
- element.winds.barbNode.setNodeValue("0");
- } else if (cWindSpeed >= 2.5 && dWindDir != -9999.0) {
- dWindDir -= this.gc.getAzimuth();
- int iWindSpeed = this.windNormalizer(cWindSpeed);
- element.winds.barbElement.setAttribute("transform",
- "rotate(" + dWindDir + ",0,0)");
- element.winds.barbNode.setNodeValue(Integer
- .toString(iWindSpeed));
- } else {
-
- element.winds.barbElement.removeAttribute("transform");
- element.winds.barbNode.setNodeValue(" ");
- }
- }
- renderArrow(windGust, windDir, speedUnit, element);
- } else {
- if (element.winds.barbElement != null) {
- element.winds.barbNode.setNodeValue(" ");
- }
- renderArrow(windGust, windDir, speedUnit, element);
- return false;
- }
- return true;
- }
-
- private void processArrowDirective(PlotData ob, PlotModelElement element)
- throws VizException {
- String[] params = element.parameter.split(",");
- Number magnitude = ob.getNumber(params[0]);
- Unit> speedUnit = ob.getUnit(params[0]);
- Number direction = ob.getNumber(params[1]);
- renderArrow(magnitude, direction, speedUnit, element);
- }
-
- private void renderArrow(Number magnitude, Number direction,
- Unit> speedUnit, PlotModelElement element) throws VizException {
- double dDir = -9999.0;
- double cMag = -9999.0;
- if (element.unit != null && magnitude != null) {
- if (element.converter == null) {
- try {
- Unit> unit = UnitFormat
- .getUCUMInstance()
- .parseSingleUnit(element.unit, new ParsePosition(0));
- element.converter = speedUnit.getConverterTo(unit);
- } catch (ParseException e) {
- throw new VizException("Unable parse units ", e);
- }
- }
- if (isValidValue(magnitude)) {
- cMag = element.converter.convert(magnitude.doubleValue());
- }
- } else if (magnitude != null) {
- cMag = magnitude.doubleValue();
- }
- if (direction != null) {
- dDir = direction.doubleValue();
- }
-
- if (dDir != -9999.0 && cMag != -9999.0) {
- dDir -= this.gc.getAzimuth();
-
- String arrowType = null;
- if (element.winds.arrowElement != null) {
- element.winds.arrowElement.setAttribute("transform", "rotate("
- + dDir + ",0,0)");
- arrowType = element.winds.arrowElement
- .getAttribute("arrowtype");
- if ("arrow1".equals(arrowType) || "arrow2".equals(arrowType)) {
- element.winds.arrowNode.setNodeValue(arrowType);
- } else {
- element.winds.arrowNode.setNodeValue("arrow");
- }
- }
- if (element.winds.gustElement != null) {
- double len = 32.0;
- if ("arrow1".equals(arrowType) || "arrow2".equals(arrowType)) {
- try {
- len = Double.parseDouble(element.winds.gustY);
- } catch (NumberFormatException nfe) {
- len = 32.0;
- }
- }
-
- double rWindDir = Math.toRadians(dDir + 180.0);
-
- long x = Math.round(len * Math.sin(rWindDir));
- long y = Math.round(len * Math.cos(rWindDir)) * -1;
-
- element.winds.gustElement.setAttribute("x", Long.toString(x));
- element.winds.gustElement.setAttribute("y", Long.toString(y));
- element.winds.gustNode.setNodeValue(Integer
- .toString(((int) Math.round(cMag))));
- }
-
- } else {
- if (element.winds.arrowElement != null) {
- element.winds.arrowElement.removeAttribute("transform");
- element.winds.arrowNode.setNodeValue(" ");
- }
- if (element.winds.gustElement != null) {
- element.winds.gustNode.setNodeValue(" ");
- }
- }
- }
-
- private void processTableDirective(PlotData ob, PlotModelElement element) {
-
- int dimensions = ob.getDimensions(element.parameter);
- String display = null;
- String[] fields = null;
- switch (ob.getType(element.parameter)) {
- case FLOAT:
- case DOUBLE:
- case INT:
- case LONG:
- if (dimensions == 1) {
- Number n = ob.getNumber(element.parameter);
- if ((n != null) && (n.doubleValue() != -9999)) {
- if ((n.doubleValue() != -9999)
- && (!Double.isNaN(n.doubleValue()))) {
- display = n.toString();
- }
- }
- } else if (dimensions == 2) {
- Number[] values = ob.getNumberAllLevels(element.parameter);
- fields = numberToStringArray(values);
- }
- break;
- case STRING:
- if (dimensions == 1) {
- display = ob.getString(element.parameter);
- } else if (dimensions == 2) {
- fields = ob.getStringAllLevels(element.parameter);
- }
- break;
- default:
- element.plotNode.setNodeValue(" ");
- }
- if (element.index != -1 && element.index < fields.length) {
- display = fields[element.index];
- } else if (element.ranking != null && fields != null) {
- display = element.ranking.getRankedField(fields);
- } else if ((fields != null) && (fields.length > 0)) {
- StringBuilder sb = new StringBuilder(fields[fields.length - 1]);
- for (int i = fields.length - 2; i >= 0; i--) {
- sb.append(" ");
- sb.append(fields[i]);
- }
- display = sb.toString().trim();
- }
-
- if (element.lookup != null) {
- display = element.lookup.lookup(display);
- }
-
- if (display != null) {
- element.plotNode.setNodeValue(display);
- } else {
- element.plotNode.setNodeValue(" ");
- }
- }
-
- private String processSampleDirective(PlotData ob, PlotModelElement element)
- throws VizException {
- String sValue = null;
- String parameter = element.parameter;
- switch (ob.getType(parameter)) {
- case FLOAT:
- case DOUBLE:
- case INT:
- case LONG:
- Number value = ob.getNumber(parameter);
- if (value != null && value.doubleValue() != -9999.0) {
- double displayValue = 0.0;
-
- if (element.unit != null) {
- if (element.converter == null) {
- try {
- Unit> unit = UnitFormat.getUCUMInstance()
- .parseSingleUnit(element.unit,
- new ParsePosition(0));
- element.converter = ob.getUnit(parameter)
- .getConverterTo(unit);
- } catch (ParseException e) {
- throw new VizException("Unable parse units ", e);
- }
- }
- displayValue = element.converter.convert(value
- .doubleValue());
- } else {
- displayValue = value.doubleValue();
- }
- if (element.format != null) {
- if (element.format.equals("time")) {
- Date d = new Date(new Double(displayValue).longValue());
- SAMPLE_DATE.setTimeZone(TimeZone.getTimeZone("UTC"));
- sValue = SAMPLE_DATE.format(d);
- } else {
- StringBuilder sb = new StringBuilder();
- Formatter testing = new Formatter(sb);
- testing.format(element.format, displayValue);
- sValue = sb.toString();
- testing.close();
- }
- } else {
- sValue = Double.toString(displayValue);
- }
- sValue = sValue.substring(element.trim);
- } else {
- sValue = "?";
- }
- break;
- case STRING:
- sValue = ob.getString(parameter);
- break;
- }
-
- if (element.lookup != null && sValue != null) {
- String lu = null;
- lu = element.lookup.lookup(sValue);
- if (lu != null) {
- sValue = lu.trim();
- }
- }
-
- if (sValue != null && element.symbol != null) {
- sValue = sValue + element.symbol;
- }
-
- return sValue + " ";
- }
-
- private boolean processRangeDirective(PlotData ob, PlotModelElement element)
- throws VizException {
-
- String sValue = null;
- switch (ob.getType(element.parameter)) {
- case FLOAT:
- case DOUBLE:
- case INT:
- case LONG:
- Number value = ob.getNumber(element.parameter);
- if (value != null && value.doubleValue() != -9999.0) {
- if (value.doubleValue() >= lowerLimit
- && value.doubleValue() <= upperLimit) {
- double displayValue = 0.0;
- if (element.unit != null) {
- if (element.converter == null) {
- try {
- Unit> unit = UnitFormat.getUCUMInstance()
- .parseProductUnit(element.unit,
- new ParsePosition(0));
- element.converter = ob.getUnit(
- element.parameter).getConverterTo(unit);
- } catch (ParseException e) {
- throw new VizException("Unable parse units ", e);
- }
- }
- displayValue = element.converter.convert(value
- .doubleValue());
- } else {
- displayValue = value.doubleValue();
- }
- if (element.format != null) {
- StringBuilder sb = new StringBuilder();
- Formatter testing = new Formatter(sb);
- testing.format(element.format, displayValue);
- sValue = sb.toString();
- testing.close();
- } else {
- sValue = Double.toString(displayValue);
- }
- }
- }
- break;
- case STRING:
- sValue = ob.getString(element.parameter);
- break;
- default:
- element.plotNode.setNodeValue(" ");
- }
- if (element.lookup != null) {
- sValue = element.lookup.lookup(sValue);
- }
- if (sValue != null) {
- element.plotNode.setNodeValue(sValue.substring(element.trim));
- return !sValue.trim().isEmpty();
- } else if (plotMissingData) {
- element.plotNode.setNodeValue("m");
- return true;
- } else {
- element.plotNode.setNodeValue(" ");
- return false;
- }
- }
-
- /**
- * Displays an asterisks (*) to all available plot locations
- *
- * @param ob
- * IDecoderGettable object
- * @param element
- * PlotModelElement object
- */
- private void processAvailDirective(PlotModelElement element) {
- element.plotNode.setNodeValue("*");
- }
-
- private void processNullDirective(PlotModelElement element) {
- element.plotNode.setNodeValue(" ");
- }
-
- /**
- * Returns the corresponding windbarb character to the actual speed
- *
- * @param windSpeed
- * @return The character that corresponds to the nearest 5 knot speed
- */
- private int windNormalizer(double dWindSpeed) {
- int windSpeed = (int) Math.round(dWindSpeed);
- int major = windSpeed / 5;
- int minor = windSpeed % 5;
- if (minor >= 3) {
- major++;
- }
- return major * 5;
- }
-
- public List getPlotFields() {
- return Collections.unmodifiableList(this.plotFields);
- }
-
- /**
- * Convert an array of Numbers to their String representation. Note that
- * indexing may be used on the return array so the output size must match
- * the input size.
- *
- * @param values
- * An array of Number to convert.
- * @return The converted data. If the input is null, the return will be
- * null.
- */
- private String[] numberToStringArray(Number[] values) {
- String[] retVal = null;
- if (values != null) {
- retVal = new String[values.length];
- Arrays.fill(retVal, "");
- for (int i = 0; i < values.length; i++) {
- Number n = values[i];
- if ((n.doubleValue() != -9999)
- && (!Double.isNaN(n.doubleValue()))) {
- retVal[i] = n.toString();
- }
- }
- }
- return retVal;
- }
-
- public void setLowerLimit(double lowerLimit) {
- this.lowerLimit = lowerLimit;
- }
-
- public void setUpperLimit(double upperLimit) {
- this.upperLimit = upperLimit;
- }
-
- private boolean isValidValue(Number value) {
- return value != null && value.doubleValue() > lowerLimit
- && value.doubleValue() <= upperLimit;
- }
-
- public void setPlotMissingData(boolean b) {
- this.plotMissingData = b;
- }
-
- private File getTableFile(String fileName) {
- File rval = PathManagerFactory.getPathManager().getStaticFile(
- PLOT_MODEL_DIR + IPathManager.SEPARATOR + fileName);
- return rval;
- }
-
- public List getSampleFields() {
- return Collections.unmodifiableList(this.sampleFields);
- }
-
- public boolean isCachingImages() {
- return imageCache != null;
- }
-
- public String getPlotModelFilename() {
- return this.plotModelFile;
- }
-
- /**
- * Disposes of the plot model
- */
- public void dispose() {
- if (python != null) {
- python.shutdown();
- }
- }
-
-}
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelGenerator.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelGenerator.java
deleted file mode 100644
index 69088fd33b..0000000000
--- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModelGenerator.java
+++ /dev/null
@@ -1,393 +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.awt.image.BufferedImage;
-import java.util.ArrayList;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.swt.graphics.RGB;
-
-import com.raytheon.uf.common.dataplugin.PluginDataObject;
-import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
-import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
-import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
-import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
-import com.raytheon.uf.viz.core.IGraphicsTarget;
-import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
-import com.raytheon.uf.viz.core.comm.Connector;
-import com.raytheon.uf.viz.core.data.prep.IODataPreparer;
-import com.raytheon.uf.viz.core.drawables.IImage;
-import com.raytheon.uf.viz.core.exception.VizException;
-import com.raytheon.uf.viz.core.map.IMapDescriptor;
-import com.raytheon.uf.viz.core.requests.ThriftClient;
-
-/**
- * A Eclipse Job thread that will listen for new stations on a queue and request
- * the data to create the plots.
- *
- *
- *
- * SOFTWARE HISTORY
- *
- * Date Ticket# Engineer Description
- * ------------ ---------- ----------- --------------------------
- * 11/20/2006 brockwoo Initial creation
- * 12/06/2006 brockwoo Implemented code review changes
- * 05/11/2007 #273 brockwoo Implemented JavaScript obs request
- * 04/16/2008 njensen createActionASCII uses ScriptCreator
- *
- *
- * @author brockwoo
- * @version 1.0
- */
-public class PlotModelGenerator extends Job {
-
- private final ConcurrentLinkedQueue stationQueue;
-
- private String inspectUri = null;
-
- // private boolean isRunning = true;
- private final Connector asciiConnection;
-
- private final ConcurrentHashMap icaoImageMap;
-
- private final ConcurrentHashMap icaoImages;
-
- private boolean looping;
-
- private final PlotModelFactory plotCreator;
-
- private final IGraphicsTarget target;
-
- private final String plugin;
-
- private class ImageContainer {
- public PluginDataObject record = null;
-
- public boolean queued = false;
-
- public boolean available = false;
- }
-
- /**
- * Initializes the thread with the station's reference time and the target
- * to create textures for.
- *
- * @param refTime
- * A string with the reference time needed to get the station out
- * of Lucene
- * @param target
- * The graphic target to create the tiles for
- * @throws VizException
- */
- public PlotModelGenerator(IGraphicsTarget aTarget,
- IMapDescriptor mapDescriptor, String plotModelFile, String plugin)
- throws VizException {
- super("Creating Plots...");
- stationQueue = new ConcurrentLinkedQueue();
- asciiConnection = Connector.getInstance();
- icaoImageMap = new ConcurrentHashMap();
- this.icaoImages = new ConcurrentHashMap();
- plotCreator = new PlotModelFactory(mapDescriptor, plotModelFile);
- this.target = aTarget;
- this.plugin = plugin;
- this.looping = false;
- }
-
- public int getPlotModelWidth() {
- return this.plotCreator.getDefinedPlotModelWidth();
- }
-
- public void setPlotModelSize(long width) {
- this.plotCreator.setPlotDimensions(width, width);
- this.cleanImages();
- }
-
- public void setPlotModelColor(RGB color) {
- this.plotCreator.setColor(color);
- this.cleanImages();
- }
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- // while (isRunning) {
- while (stationQueue.size() > 0 || inspectUri != null) {
- IImage image = null;
- ArrayList queuePurgeList = new ArrayList();
- ArrayList stationQuery = new ArrayList();
-
- synchronized (this) {
- if (inspectUri != null) {
- if (!icaoImageMap.containsKey(inspectUri)) {
- ImageContainer newPlot = new ImageContainer();
- newPlot.queued = true;
- icaoImageMap.put(inspectUri, newPlot);
- this.stationQueue.add(inspectUri);
- } else {
- if (!this.icaoImageMap.get(inspectUri).queued) {
- this.icaoImageMap.get(inspectUri).queued = true;
- this.stationQueue.add(inspectUri);
- }
- }
- if (icaoImageMap.get(inspectUri).record == null) {
- stationQuery.add(inspectUri);
- }
- inspectUri = null;
- } else {
- String[] stationList = stationQueue
- .toArray(new String[stationQueue.size()]);
- int stationCounter;
- for (stationCounter = 0; stationCounter < stationList.length; stationCounter++) {
- queuePurgeList.add(stationList[stationCounter]);
- if (this.icaoImageMap.get(stationList[stationCounter]).record == null) {
- stationQuery.add(stationList[stationCounter]);
- }
- if (stationCounter == 74) {
- break;
- }
- }
- }
- }
-
- if (stationQuery.size() > 0) {
- try {
- PluginDataObject[] obs = requestPluginDataObjects(stationQuery
- .toArray(new String[0]));
- for (PluginDataObject ob : obs) {
- ImageContainer ic = icaoImageMap.get(ob.getDataURI());
- if (ic != null) {
- ic.record = ob;
- } else {
- System.out.println("Missing: " + ob.getDataURI());
- }
- }
- } catch (VizException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- int counter = 0;
- for (int uriCounter = 0; uriCounter < queuePurgeList.size(); uriCounter++) {
- try {
- String dataUri = queuePurgeList.get(uriCounter);
- PluginDataObject ob = this.icaoImageMap.get(dataUri).record;
- if (ob != null && !this.icaoImageMap.get(dataUri).available) {
- image = target.initializeRaster(new IODataPreparer(
- plotCreator.getStationPlot(ob),
- ob.getDataURI(), 0), null);
- icaoImages.put(ob.getDataURI(), image);
- icaoImageMap.get(ob.getDataURI()).available = true;
- icaoImageMap.get(ob.getDataURI()).queued = false;
- } else { // For what ever reason, the datauri did not
- // return a PluginDataObject
- // System.out.println(dataUri);
- BufferedImage bufferedImage = new BufferedImage(10, 10,
- BufferedImage.TYPE_BYTE_INDEXED);
- image = target.initializeRaster(new IODataPreparer(
- bufferedImage, dataUri, 0), null);
- icaoImages.put(dataUri, image);
- icaoImageMap.get(dataUri).available = true;
- icaoImageMap.get(dataUri).queued = false;
- }
-
- } catch (VizException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- counter++;
- }
- if (queuePurgeList.size() > 0) {
- stationQueue.removeAll(queuePurgeList);
- queuePurgeList.clear();
- if (!this.looping) {
- target.setNeedsRefresh(true);
- }
- }
- }
- /*
- * try { Thread.sleep(5); } catch (InterruptedException e) { }
- */
- // this.schedule(5);
- // }
- return Status.OK_STATUS;
- }
-
- /**
- * Adds a station to the queue
- *
- * @param station
- * A string for a valid station within Lucene
- * @return If the station was added to the queue properly
- */
- public void queueStations(ArrayList stationList, boolean looping) {
- for (String dataUri : stationList) {
- if (!icaoImageMap.containsKey(dataUri)) {
- ImageContainer newPlot = new ImageContainer();
- newPlot.queued = true;
- icaoImageMap.put(dataUri, newPlot);
- this.stationQueue.add(dataUri);
- } else {
- if (!this.icaoImageMap.get(dataUri).queued) {
- this.icaoImageMap.get(dataUri).queued = true;
- this.stationQueue.add(dataUri);
- }
- }
- }
- if (!(this.getState() == Job.RUNNING)) {
- this.schedule();
- }
- this.looping = looping;
- }
-
- public void setStation(String dataUri) {
- icaoImageMap.put(dataUri, new ImageContainer());
- }
-
- public void setStation(PluginDataObject pdo) {
- ImageContainer newDataUri = new ImageContainer();
- newDataUri.record = pdo;
- this.icaoImageMap.put(pdo.getDataURI(), newDataUri);
- }
-
- public String getStationMessage(String dataUri) {
-
- String message = null;
- if (icaoImageMap.get(dataUri) != null
- && icaoImageMap.get(dataUri).record != null) {
- message = (String) icaoImageMap.get(dataUri).record
- .getMessageData();
- } else {
- message = "Generating...";
- synchronized (this) {
- if (dataUri != null && !dataUri.equals(inspectUri)) {
- inspectUri = dataUri;
- if (!(this.getState() == Job.RUNNING)) {
- this.schedule();
- }
- }
- }
- }
-
- return message;
- }
-
- public PluginDataObject getStationObject(String dataUri) {
- if (!this.icaoImageMap.containsKey(dataUri)) {
- return null;
- } else {
- return this.icaoImageMap.get(dataUri).record;
- }
- }
-
- /**
- * Will return the texture for a station.
- *
- * @param station
- * The station to get the texture for
- * @return The texture
- */
- public IImage getStation(String dataUri) {
- return icaoImages.get(dataUri);
- }
-
- /**
- * Checks to see if the station is in the queue. This can be called to make
- * sure that a station is not added twice to be created.
- *
- * @param station
- * The station to check for
- * @return A boolean indicating if the station is already set to be
- * processed
- */
- public boolean isQueued(String dataUri) {
- if (!this.icaoImageMap.containsKey(dataUri)) {
- return false;
- }
- return icaoImageMap.get(dataUri).queued;
- }
-
- /**
- * Will check to see if the station already has a texture available.
- *
- * @param station
- * The station to check for
- * @return A boolean indicating the texture status
- */
- public boolean hasImage(String dataUri) {
- if (!this.icaoImageMap.containsKey(dataUri)) {
- return false;
- }
- return icaoImageMap.get(dataUri).available;
- }
-
- /**
- * Kills the thread.
- *
- */
- public void shutdown() {
- this.cancel();
- cleanImages();
- }
-
- public void cleanImages() {
- // Clean up images
- Set imageDataUris = icaoImages.keySet();
- for (String imageDataUri : imageDataUris) {
- icaoImages.get(imageDataUri).dispose();
- icaoImages.remove(imageDataUri);
- this.icaoImageMap.get(imageDataUri).available = false;
- this.icaoImageMap.get(imageDataUri).queued = false;
- }
- }
-
- private PluginDataObject[] requestPluginDataObjects(String[] uris)
- throws VizException {
- DbQueryRequest request = new DbQueryRequest();
- request.addConstraint("pluginName", new RequestConstraint(plugin));
- RequestConstraint ids = new RequestConstraint();
- ids.setConstraintType(ConstraintType.IN);
- ids.setConstraintValueList(uris);
- request.addConstraint("dataURI", ids);
- request.setLimit(uris.length);
-
- DbQueryResponse response = (DbQueryResponse) ThriftClient
- .sendRequest(request);
- return response.getEntityObjects(PluginDataObject.class);
- }
-
- public void setPlotModelLineStyle(LineStyle lineStyle) {
- plotCreator.setLineStyle(lineStyle);
- cleanImages();
- }
-
- public void setPlotModelLineWidth(int outlineWidth) {
- plotCreator.setLineWidth(outlineWidth);
- cleanImages();
- }
-
-}
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModels.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModels.java
index 75deaec63a..f87ab963c2 100644
--- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModels.java
+++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/PlotModels.java
@@ -44,7 +44,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.MapDescriptor;
import com.raytheon.uf.viz.datacube.DataCubeContainer;
-import com.raytheon.viz.pointdata.PlotModelFactory2.PlotModelElement;
+import com.raytheon.viz.pointdata.PlotModelFactory.PlotModelElement;
import com.raytheon.viz.pointdata.util.PointDataInventory;
/**
@@ -54,9 +54,10 @@ import com.raytheon.viz.pointdata.util.PointDataInventory;
*
* SOFTWARE HISTORY
*
- * Date Ticket# Engineer Description
- * ------------ ---------- ----------- --------------------------
- * Sep 18, 2013 2391 mpduff Initial creation
+ * Date Ticket# Engineer Description
+ * ------------- -------- ----------- --------------------------
+ * Sep 18, 2013 2391 mpduff Initial creation
+ * Jun 06, 2014 2061 bsteffen Remove old PlotResource
*
*
*
@@ -137,7 +138,7 @@ public class PlotModels {
try {
if (!models.containsKey(fileName)) {
List params = new ArrayList();
- List fields = new PlotModelFactory2(
+ List fields = new PlotModelFactory(
fakeDescriptor, fileName).getPlotFields();
for (PlotModelElement p : fields) {
if (!p.parameter.equals("")
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/StringLookup.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/StringLookup.java
deleted file mode 100644
index 1633a7ecc4..0000000000
--- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/StringLookup.java
+++ /dev/null
@@ -1,388 +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.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.TreeMap;
-
-import com.raytheon.uf.common.localization.IPathManager;
-import com.raytheon.uf.common.localization.PathManagerFactory;
-
-public class StringLookup {
-
- private static final String plotmodelDir = "plotModels";
-
- private final String filename;
-
- private final HashMap lookup;
-
- private final TreeMap rangeLookup;
-
- private float firstValue = -9999;
-
- private float secondValue = -9999;
-
- private String defLookup;
-
- private String splitValue;
-
- private int splitValueIndex = -1;
-
- protected StringLookup(String filename) {
- this.filename = filename;
- this.lookup = new HashMap();
- this.rangeLookup = new TreeMap();
- }
-
- public String getFilename() {
- return this.filename;
- }
-
- public String recursiveTranslation(String field) {
- /*
- * if(splitValue != null && field != null){ String[] tempFields =
- * field.split(splitValue); if(tempFields.length == 2){ field =
- * tempFields[this.splitValueIndex]; } }
- * if(this.lookup.containsKey(field)){ return this.lookup.get(field); }
- * else if(this.defLookup != null){ return this.defLookup; } else{
- * return null; }
- */
-
- // Initialize.
- int j, k, c, n, m;
- // int pos;
- String txtstr;
- // char cp = 0;
- // char cp0;
-
- // Empty input, empty output.
- if (field == null || field.length() == 0 || field.equals("-9999")) {
- if (this.defLookup != null) {
- return this.defLookup;
- }
- return null;
- }
-
- // Simple case of being able to translate the whole string.
- if (this.lookup.containsKey(field)) {
- return this.lookup.get(field);
- }
-
- // If required, perform an edit operation where we replace everthing
- // from the substring _left to the beginning of the string with the
- // string _leftTrans.
- n = field.length();
- if (splitValue != null && field != null) {
- String[] tempFields = field.split(splitValue);
- if (tempFields.length == 2) {
- field = tempFields[this.splitValueIndex];
- n = field.length();
- }
- }
-
- // Try to translate the whole thing again.
- if (this.lookup.containsKey(field)) {
- return this.lookup.get(field);
- }
-
- // Initialize the output with an invisible string the same length as
- // the input, loop through each possible substring size.
- int nLeft = n; // number of untranslated characters
- boolean none = true; // true if nothing has been translated.
- String output = this.invisibleString(n);
- for (m = n - 1; m >= 1; m--) {
-
- // If we have enough untranslated characters to translate a
- // substring
- // of this size, loop through each possible substring.
- if (nLeft < m || m > n - 1)
- continue;
- for (c = 0; c <= n - m; c++) {
-
- // If a translation for this substring is not found, go on.
- if (!this.lookup.containsKey(this.mid(field, c, m))) {
- continue;
- } else {
- txtstr = this.lookup.get(this.mid(field, c, m));
- }
-
- // Replace input substring with unprintable characters, put
- // the translation in the output string.
- j = txtstr.length();
- k = n - (c + m);
- field = this.left(field, c) + this.invisibleString(j)
- + this.right(field, k);
- output = this.left(output, c) + txtstr + this.right(output, k);
-
- // Update next substring position, number untranslated and total
- // string length.
- c += j - 1;
- nLeft -= m;
- none = false;
- n = field.length();
- if (nLeft < m)
- break;
- }
- }
-
- // Make anything that is all unprintable an empty string.
- if (nLeft == 0)
- field = "";
- else if (none)
- return defLookup;
- return output;
- }
-
- public String determineRange(String field) {
- String retVal = field;
-
- if (retVal != null) {
- try {
- float value = Float.parseFloat(field);
- if (value < this.firstValue) {
- retVal = rangeLookup.ceilingEntry(value).getValue();
- } else if (value <= this.secondValue) {
- retVal = rangeLookup.ceilingEntry(value).getValue();
- }
- } catch (Exception e) {
- // use default value
- if (this.defLookup != null) {
- retVal = this.defLookup;
- }
- }
- }
- if (retVal == null) {
- if (this.defLookup != null) {
- retVal = this.defLookup;
- } else {
- retVal = " ";
- }
- }
- if (retVal.contains("~")) {
- retVal = retVal.replace('~', ' ');
- }
- return retVal;
- }
-
- private String mid(String stringToParse, int start, int length) {
- int lStart = start;
- int lLength = length;
- if (lStart >= stringToParse.length()) {
- lStart = stringToParse.length();
- }
- lLength = Math.min(stringToParse.length() - lStart, lLength);
- String returnString = null;
- try {
- returnString = stringToParse.substring(lStart, lStart + lLength);
- } catch (Exception e) {
- System.out.println(start + " " + lStart + " " + length + " "
- + lLength + " " + stringToParse);
- }
- return returnString;
-
- }
-
- private String left(String stringToParse, int length) {
- if (length >= stringToParse.length()) {
- return stringToParse;
- } else {
- return stringToParse.substring(0, length);
- }
- }
-
- private String right(String stringToParse, int length) {
- if (length >= stringToParse.length()) {
- return stringToParse;
- } else {
- return stringToParse.substring(stringToParse.length() - length,
- stringToParse.length());
- }
- }
-
- public void setLookupEntry(String field, String value) {
- this.lookup.put(field, value);
- }
-
- public void setRangeEntry(float field, String value) {
- this.rangeLookup.put(field, value);
- }
-
- public void setDefaultValue(String value) {
- this.defLookup = value;
- }
-
- public void setSplitValueIndex(int value) {
- this.splitValueIndex = value;
- }
-
- public void setSplitValue(String value) {
- this.splitValue = value;
- }
-
- public static StringLookup readS2SFile(String s2nFilename) {
- BufferedReader input = null;
- StringLookup lookup = new StringLookup(s2nFilename);
- File s2nFile = PathManagerFactory.getPathManager().getStaticFile(
- StringLookup.plotmodelDir + IPathManager.SEPARATOR
- + s2nFilename);
- try {
- input = new BufferedReader(new FileReader(s2nFile));
- String line = null;
- while ((line = input.readLine()) != null) {
- if (line.matches("s2s")) {
- continue;
- } else if (line.contains("left") || line.contains("right")) {
- if (line.contains("left")) {
- lookup.setSplitValueIndex(1);
- } else if (line.contains("right")) {
- lookup.setSplitValueIndex(0);
- }
- String[] splitValue = line.split("\\s");
- lookup.setSplitValue("\\s*" + splitValue[1] + "\\s*");
- continue;
- }
- String[] lookupValues = null;
- if (line.contains(":")) {
- lookupValues = line.split("\\s*:\\s*");
- } else {
- lookupValues = line.split("\\s");
- }
- if (lookupValues != null && lookupValues.length == 2) {
- if (lookupValues[0].matches("default")) {
- lookup.setDefaultValue(lookupValues[1]);
- } else {
- lookup.setLookupEntry(lookupValues[0], lookupValues[1]);
- }
- } else if (lookupValues != null && lookupValues.length == 1) {
- if (lookupValues[0].matches("default")) {
- lookup.setDefaultValue(" ");
- } else {
- lookup.setLookupEntry(lookupValues[0], " ");
- }
- }
- }
- input.close();
- } catch (FileNotFoundException ex) {
- ex.printStackTrace();
- return null;
- } catch (IOException ex) {
- ex.printStackTrace();
- return null;
- }
- return lookup;
- }
-
- public static StringLookup readR2SFile(String r2nFilename) {
- BufferedReader input = null;
- StringLookup lookup = new StringLookup(r2nFilename);
- File r2nFile = PathManagerFactory.getPathManager().getStaticFile(
- StringLookup.plotmodelDir + IPathManager.SEPARATOR
- + r2nFilename);
- try {
- input = new BufferedReader(new FileReader(r2nFile));
- String line = null;
- ArrayList tempLookupValues;
- boolean firstEntry = true;
- float first = -9999;
- float second = -9999;
- while ((line = input.readLine()) != null) {
- if (line.matches("r2s") || line.startsWith("#")) {
- continue;
- }
- String[] lookupValues = null;
- if (line.contains(" ")) {
- lookupValues = line.split(" ");
- }
-
- if (lookupValues != null) {
- tempLookupValues = new ArrayList();
- for (int i = 0; i < lookupValues.length; i++) {
- if (!lookupValues[i].equals(" ")
- && !lookupValues[i].equals("")) {
- tempLookupValues.add(lookupValues[i]);
- }
- }
- lookupValues = tempLookupValues
- .toArray(new String[tempLookupValues.size()]);
- if (lookupValues.length == 2
- && lookupValues[0].matches("default")) {
- lookup.setDefaultValue(lookupValues[1]);
- } else if (lookupValues.length == 3) {
- try {
-
- if (firstEntry) {
- firstEntry = false;
- second = Float.parseFloat(lookupValues[1]);
- lookup.setRangeEntry(
- Float.parseFloat(lookupValues[0]),
- lookupValues[2]);
- lookup.setRangeEntry(
- Float.parseFloat(lookupValues[1]),
- lookupValues[2]);
-
- } else {
- first = second;
- second = Float.parseFloat(lookupValues[1]);
- lookup.setRangeEntry(
- Float.parseFloat(lookupValues[1]),
- lookupValues[2]);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }
- lookup.setFirstValue(first);
- lookup.setSecondValue(second);
- input.close();
- } catch (FileNotFoundException ex) {
- ex.printStackTrace();
- return null;
- } catch (IOException ex) {
- ex.printStackTrace();
- return null;
- }
- return lookup;
- }
-
- private String invisibleString(int length) {
- char character = ' ';
- char[] toReturn = new char[length];
- for (int i = 0; i < length; i++) {
- toReturn[i] = character;
- }
- return new String(toReturn);
- }
-
- private void setFirstValue(float firstValue) {
- this.firstValue = firstValue;
- }
-
- private void setSecondValue(float secondValue) {
- this.secondValue = secondValue;
- }
-}
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/package-info.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/package-info.java
deleted file mode 100644
index f883ff55a5..0000000000
--- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/package-info.java
+++ /dev/null
@@ -1,23 +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.
- **/
-/**
- * Provides support for point data
- */
-package com.raytheon.viz.pointdata;
\ No newline at end of file
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/python/PlotPythonScriptFactory.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/python/PlotPythonScriptFactory.java
index 85bdc074bf..36262a7f96 100644
--- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/python/PlotPythonScriptFactory.java
+++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/python/PlotPythonScriptFactory.java
@@ -28,7 +28,7 @@ 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;
+import com.raytheon.viz.pointdata.PlotModelFactory;
/**
* Builds a plot delegate python script based on the script text extracted from
@@ -40,9 +40,10 @@ import com.raytheon.viz.pointdata.PlotModelFactory2;
*
* SOFTWARE HISTORY
*
- * Date Ticket# Engineer Description
- * ------------ ---------- ----------- --------------------------
- * Mar 14, 2014 2868 njensen Initial creation
+ * Date Ticket# Engineer Description
+ * ------------- -------- ----------- --------------------------
+ * Mar 14, 2014 2868 njensen Initial creation
+ * Jun 06, 2014 2061 bsteffen Remove old PlotResource
*
*
*
@@ -87,7 +88,7 @@ public class PlotPythonScriptFactory extends
IPathManager pm = PathManagerFactory.getPathManager();
LocalizationFile[] files = pm.listFiles(pm
.getLocalSearchHierarchy(LocalizationType.CAVE_STATIC),
- PlotModelFactory2.PLOT_MODEL_DIR, null, false, false);
+ PlotModelFactory.PLOT_MODEL_DIR, null, false, false);
StringBuilder includeBuilder = new StringBuilder();
for (LocalizationFile lf : files) {
if (lf.exists() && lf.isDirectory()) {
@@ -103,7 +104,7 @@ public class PlotPythonScriptFactory extends
if (baseFilePath == null) {
File baseFile = PathManagerFactory.getPathManager()
.getStaticFile(
- PlotModelFactory2.PLOT_MODEL_DIR
+ PlotModelFactory.PLOT_MODEL_DIR
+ IPathManager.SEPARATOR
+ "PlotModelInterface.py");
baseFilePath = baseFile.getAbsolutePath();
diff --git a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java
index 97f497775c..b32f27fb19 100644
--- a/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java
+++ b/cave/com.raytheon.viz.pointdata/src/com/raytheon/viz/pointdata/rsc/PlotResource.java
@@ -22,36 +22,35 @@ package com.raytheon.viz.pointdata.rsc;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang.Validate;
import org.eclipse.swt.graphics.RGB;
+import org.opengis.coverage.grid.GridEnvelope;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import com.raytheon.uf.common.dataplugin.PluginDataObject;
-import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
-import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
-import com.raytheon.uf.common.pointdata.vadriver.VA_Advanced;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
+import com.raytheon.uf.common.time.BinOffset;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
-import com.raytheon.uf.viz.core.IExtent;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.PixelExtent;
-import com.raytheon.uf.viz.core.catalog.CatalogQuery;
+import com.raytheon.uf.viz.core.drawables.IImage;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
+import com.raytheon.uf.viz.core.drawables.ext.ISingleColorImageExtension.ISingleColorImage;
import com.raytheon.uf.viz.core.exception.VizException;
+import com.raytheon.uf.viz.core.jobs.JobPool;
import com.raytheon.uf.viz.core.map.MapDescriptor;
-import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
@@ -59,14 +58,20 @@ import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.DensityCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.OutlineCapability;
-import com.raytheon.viz.pointdata.PlotModelGenerator;
-import com.raytheon.viz.pointdata.StaticPlotInfoPV;
-import com.raytheon.viz.pointdata.StaticPlotInfoPV.SPIEntry;
+import com.raytheon.viz.pointdata.IPlotModelGeneratorCaller;
+import com.raytheon.viz.pointdata.PlotAlertParser;
+import com.raytheon.viz.pointdata.PlotInfo;
import com.raytheon.viz.pointdata.drawables.IPointImageExtension;
import com.raytheon.viz.pointdata.drawables.IPointImageExtension.PointImage;
+import com.raytheon.viz.pointdata.rsc.progdisc.AbstractProgDisclosure;
+import com.raytheon.viz.pointdata.rsc.progdisc.AbstractProgDisclosure.IProgDiscListener;
+import com.raytheon.viz.pointdata.rsc.progdisc.DynamicProgDisclosure;
+import com.raytheon.viz.pointdata.rsc.progdisc.SpiProgDisclosure;
+import com.raytheon.viz.pointdata.thread.GetDataTask;
+import com.raytheon.viz.pointdata.thread.GetDataTask.Params;
+import com.raytheon.viz.pointdata.thread.PlotThreadOverseer;
import com.raytheon.viz.pointdata.units.PlotUnits;
import com.vividsolutions.jts.geom.Coordinate;
-import com.vividsolutions.jts.geom.Envelope;
/**
* Provides a resource that will display plot data for a given reference time.
@@ -81,17 +86,20 @@ import com.vividsolutions.jts.geom.Envelope;
* Mar 17, 2009 2105 jsanchez Plot goessounding/poessounding
* availability.
* Mar 30, 2009 2169 jsanchez Updated initNewFrame.
- * Apr 09, 2009 952 jsanchez Plot acars.
+ * Apr 09, 2009 952 jsanchez Plot acars.
* Apr 13, 2009 2251 jsanchez Plot profilers.
- * May 12, 2009 2338 jsanchez Updated resourceChanged. Registered
- * units.
- * Jun 08, 2009 2450 jsanchez Updated inpsect method to find closest
- * plot.
- * Aug 09, 2012 1011 jkorman Added screenToWorldRatio calc to
- * paintInternal.
- * Nov 06, 2013 2493 bsteffen Removed IPlotDataResource
- *
- *
+ * Apr 21, 2009 chammack Refactor to common pointData model
+ * Feb 01, 2013 1567 njensen Refactor handling of updates
+ * May 14, 2013 1869 bsteffen Get plots working without dataURI
+ * May 23, 2013 14996 snaples Updated processUpdatedPlot to handle AWOS
+ * stations updates properly
+ * Jun 06, 2013 2072 bsteffen Fix concurrency problems when init is
+ * called before time matching is done.
+ * Jun 25, 2013 1869 bsteffen Fix plot sampling.
+ * Sep 04, 2013 16519 kshresth Fix Metar Display Problem
+ * Dec 02, 2013 2473 njensen Prog Disclose paint frames at high priority
+ * Mar 21, 2014 2868 njensen Use PlotThreadOverseer for increased efficiency
+ * Jun 06, 2014 2061 bsteffen Rename and remove old PlotResource
*
*
*
@@ -100,88 +108,84 @@ import com.vividsolutions.jts.geom.Envelope;
*/
public class PlotResource extends
AbstractVizResource implements
- IResourceDataChanged {
+ IResourceDataChanged, IPlotModelGeneratorCaller, IProgDiscListener {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(PlotResource.class);
- private boolean hasInited = false;
+ private static final double MAX_SAMPLE_DISANCE = 2;
- private PixelExtent worldExtent;
+ public static final String NO_DATA = "NO DATA";
- private PlotModelGenerator generator;
+ private AbstractProgDisclosure progressiveDisclosure;
- private DataTime displayedObsTime;
-
- private VA_Advanced progDisc;
-
- private double actualPlotWidth;
+ private PlotThreadOverseer generator;
private double plotWidth;
- private static final double MAX_SAMPLE_DISANCE = 2;
+ private final Map frameMap;
- private HashMap frameInfo;
+ private DataTime displayedTime;
- private ArrayList stationsToParse;
+ private RGB imageColor = null;
- HashMap queryList;
+ private JobPool frameRetrievalPool = new JobPool("Retrieving plot frame",
+ 8, true);
- private StaticPlotInfoPV spi;
+ private class FrameRetriever implements Runnable {
- // private int range;
+ private DataTime dataTime;
- private int dynProgDisc;
+ @Override
+ public void run() {
+ try {
+ initNewFrame(dataTime);
+ } catch (VizException e) {
+ statusHandler.handle(Priority.PROBLEM,
+ "Error retrieving frame information for time: "
+ + dataTime, e);
+ }
+ }
- private double distFloor;
-
- private double screenToWorldRatio;
-
- private static final String PLUGIN_GOESSOUNDING = "goessounding";
-
- private static final String PLUGIN_POESSOUNDING = "poessounding";
-
- private static final String PLUGIN_ACARSSOUNDING = "acarssounding";
-
- private static final String PLUGIN_PROFILER = "profiler";
-
- private static final String PLUGIN_ACARS = "acars";
-
- private static final String PLUGIN_PIREP = "pirep";
-
- public class FrameInformation {
- boolean computeProgDisc = true;
-
- int uniqueueStations = 0;
-
- int dynStations = 0;
-
- double minDist = 22222.0;
-
- ArrayList frameDistValues;
-
- ArrayList origFrameDistValues;
-
- ArrayList frameDataUris;
-
- ArrayList frameStationLocations;
-
- ArrayList frameStationPixelLocations;
-
- ArrayList frameGoodnessValues;
-
- HashMap frameStations;
-
- ArrayList currentStationList = new ArrayList();
}
- public class ObsInformation {
- String id;
+ /**
+ * A station represents all the data for a single location(station) for a
+ * single frame
+ *
+ */
+ public static class Station {
+ /*
+ * Contains all PlotInfo objects for the same stationId with the same
+ * normalized time(real time will be different)
+ */
+ public PlotInfo[] info;
- String icao;
+ /*
+ * The image to display for this plot
+ */
+ public PointImage plotImage;
- String datauri;
+ /*
+ * Sampling text for this plot
+ */
+ public String rawMessage;
- Coordinate latLon;
+ /*
+ * Information used be the progressive disclosure algorithm
+ */
+ public Object progDiscInfo;
+
+ /*
+ * Location of the plot in descriptor grid space.
+ */
+ public Coordinate pixelLocation;
+
+ }
+
+ public class FrameInformation {
+ Map stationMap = new ConcurrentHashMap();
+
+ List lastComputed = Collections.emptyList();
}
/**
@@ -195,23 +199,12 @@ public class PlotResource extends
*/
public PlotResource(PlotResourceData data, LoadProperties props) {
super(data, props);
+ if (data.getAlertParser() == null) {
+ data.setAlertParser(new PlotAlertParser());
+ }
this.dataTimes = new ArrayList();
- this.progDisc = new VA_Advanced();
- this.stationsToParse = new ArrayList();
- this.frameInfo = new HashMap();
- this.dynProgDisc = 1;
-
- if (!hasCapability(ColorableCapability.class)) {
- // default
- getCapability(ColorableCapability.class).setColor(
- new RGB(0, 255, 0));
- // this.range = resourceData.getBinOffset().getInterval() * 1000;
- }
+ this.frameMap = new ConcurrentHashMap();
data.addChangeListener(this);
- if (resourceData.getSpiFile() != null) {
- this.spi = StaticPlotInfoPV.readStaticPlotInfoPV(resourceData
- .getSpiFile());
- }
}
@Override
@@ -222,534 +215,320 @@ public class PlotResource extends
@Override
protected void paintInternal(IGraphicsTarget aTarget,
PaintProperties paintProps) throws VizException {
- if (!hasInited) {
+ DataTime curTime = paintProps.getDataTime();
+ if (curTime == null) {
return;
}
- displayedObsTime = paintProps.getDataTime();
- if (this.stationsToParse.size() > 0) {
- this.updateRecords();
+ FrameInformation curFrame = frameMap.get(curTime);
+ if (curFrame == null) {
+ curFrame = startFrameInit(curTime);
}
- this.screenToWorldRatio = paintProps.getCanvasBounds().width
- / paintProps.getView().getExtent().getWidth();
- boolean delayLoop = false;
- DataTime thisFrameTime = this.displayedObsTime;
- if (thisFrameTime != null) {
- String thisFrameTimeString = thisFrameTime.toString();
- if (!this.frameInfo.containsKey(thisFrameTimeString)) {
- this.initNewFrame(thisFrameTime);
- delayLoop = paintProps.getLoopProperties().isLooping();
- }
- FrameInformation thisFrameInfo = this.frameInfo
- .get(thisFrameTimeString);
-
- IExtent extent = paintProps.getView().getExtent();
-
- double maxX = extent.getMaxX();
- double minX = extent.getMinX();
- double maxY = extent.getMaxY();
- double minY = extent.getMinY();
- if (maxX < 0) {
- maxX = 0;
- }
- if (maxX > 19999) {
- maxX = 19999;
- }
- if (minX < 0) {
- minX = 0;
- }
- if (minX > 19999) {
- minX = 19999;
- }
- if (maxY < 0) {
- maxY = 0;
- }
- if (maxY > 9999) {
- maxY = 9999;
- }
- if (minY < 0) {
- minY = 0;
- }
- if (minY > 9999) {
- minY = 9999;
- }
-
- PixelExtent correctedExtent = new PixelExtent(minX, maxX, minY,
- maxY);
-
- double magnification = getCapability(MagnificationCapability.class)
- .getMagnification();
-
- int displayWidth = (int) (descriptor.getMapWidth() * paintProps
- .getZoomLevel());
- double kmPerPixel = (displayWidth / paintProps.getCanvasBounds().width) / 1000.0;
- if (this.plotWidth != this.actualPlotWidth * magnification) {
- this.plotWidth = this.actualPlotWidth * magnification;
- this.generator.setPlotModelSize(Math.round(this.plotWidth));
- }
- double displayHintSize = this.resourceData.getPixelSizeHint()
- * magnification;
- double threshold = (displayHintSize * kmPerPixel)
- / getCapability(DensityCapability.class).getDensity();
-
- // Load Information about current frame
- ArrayList currentDistValues = thisFrameInfo.frameDistValues;
- ArrayList currentDataUris = thisFrameInfo.frameDataUris;
- ArrayList currentFrameStationLocations = thisFrameInfo.frameStationLocations;
- ArrayList currentFrameStationPixels = thisFrameInfo.frameStationPixelLocations;
-
- ArrayList stationList = new ArrayList();
-
- for (int counter = 0; counter < currentDistValues.size(); counter++) {
- Coordinate location = currentFrameStationPixels.get(counter);
- if (!correctedExtent.contains(location.x, location.y)) {
- continue;
- }
- if (currentDistValues.get(counter) >= threshold) {
- stationList.add(counter);
- }
- }
- thisFrameInfo.currentStationList = stationList;
- ArrayList newStations = new ArrayList();
- int queuedStations = 0;
- long paintStart = System.currentTimeMillis();
- do {
- queuedStations = 0;
- for (int station : stationList) {
- String currentDataUri = currentDataUris.get(station);
- double[] stationLocation = {
- currentFrameStationLocations.get(station).x,
- currentFrameStationLocations.get(station).y };
- double[] stationPixelLocation = descriptor
- .worldToPixel(stationLocation);
- if (!generator.hasImage(currentDataUri)) {
- queuedStations++;
- if (!generator.isQueued(currentDataUri)) {
- newStations.add(currentDataUri);
- }
- continue;
- }
-
- PointImage image = new PointImage(
- generator.getStation(currentDataUri),
- stationPixelLocation[0], stationPixelLocation[1]);
- image.setHeight(this.plotWidth);
- image.setWidth(this.plotWidth);
- aTarget.getExtension(IPointImageExtension.class)
- .drawPointImages(paintProps, image);
- }
- if (newStations.size() > 0) {
- generator.queueStations(newStations, paintProps
- .getLoopProperties().isLooping());
- newStations.clear();
- }
- if ((delayLoop && queuedStations == 0)
- || (System.currentTimeMillis() - paintStart > 5000)) {
- delayLoop = false;
- queuedStations = -9999;
- }
- } while ((queuedStations > 0 && delayLoop));
+ if (progressiveDisclosure.updateProperties(paintProps)
+ || !curTime.equals(displayedTime)) {
+ displayedTime = paintProps.getDataTime();
+ progressiveDisclosure.update(curFrame.stationMap.values(),
+ displayedTime, true);
+ resourceData.getPlotInfoRetriever().updateActiveFrame(
+ paintProps.getDataTime(),
+ descriptor.pixelToWorld(paintProps.getView().getExtent(),
+ descriptor.getCRS()), descriptor.getCRS());
}
+
+ if (!progressiveDisclosure.isDone() || !generator.isDone()
+ || frameRetrievalPool.isActive()) {
+ issueRefresh();
+ }
+
+ List stationList = curFrame.lastComputed;
+
+ if (stationList.isEmpty()) {
+ return;
+ }
+
+ List images = new ArrayList(stationList.size());
+ for (Station station : stationList) {
+ if (station.plotImage == null) {
+ continue;
+ }
+ // set image color so shader can draw in appropriate color
+ ((ISingleColorImage) station.plotImage.getImage())
+ .setColor(imageColor);
+ images.add(station.plotImage);
+ }
+
+ aTarget.getExtension(IPointImageExtension.class).drawPointImages(
+ paintProps, images);
}
@Override
protected void initInternal(IGraphicsTarget aTarget) throws VizException {
- if (!hasInited) {
- Map request = resourceData
- .getMetadataMap();
- RequestConstraint plugin = request.get("pluginName");
- PlotUnits.register();
- generator = new PlotModelGenerator(aTarget, descriptor,
- this.resourceData.getPlotModelFile(),
- plugin.getConstraintValue());
- this.generator.setPlotModelColor(getCapability(
- ColorableCapability.class).getColor());
- this.generator.setPlotModelLineStyle(getCapability(
- OutlineCapability.class).getLineStyle());
- this.generator.setPlotModelLineWidth(getCapability(
- OutlineCapability.class).getOutlineWidth());
- // generator.schedule();
- this.actualPlotWidth = this.plotWidth = generator
- .getPlotModelWidth();
- this.distFloor = (descriptor.getMapWidth() / 1000.0)
- * this.resourceData.getPixelSizeHint() / 32000.0;
- this.worldExtent = new PixelExtent(0, descriptor.getGridGeometry()
- .getGridRange().getHigh(0), 0, descriptor.getGridGeometry()
- .getGridRange().getHigh(1));
- hasInited = true;
- getCapability(MagnificationCapability.class);
- getCapability(DensityCapability.class);
+ Map request = resourceData.getMetadataMap();
+ RequestConstraint plugin = request.get("pluginName");
+ PlotUnits.register();
+ generator = new PlotThreadOverseer(aTarget, descriptor,
+ this.resourceData.getPlotModelFile(),
+ this.resourceData.getLevelKey(), plugin.getConstraintValue(),
+ this.resourceData.getMetadataMap(), this);
+ this.generator.setPlotModelColor(getCapability(
+ ColorableCapability.class).getColor());
+ this.imageColor = getCapability(ColorableCapability.class).getColor();
+ this.generator.setPlotModelLineStyle(getCapability(
+ OutlineCapability.class).getLineStyle());
+ this.generator.setPlotModelLineWidth(getCapability(
+ OutlineCapability.class).getOutlineWidth());
+ this.generator.setPlotMissingData(resourceData.isPlotMissingData());
+ this.generator.setLowerLimit(resourceData.getLowerLimit());
+ this.generator.setUpperLimit(resourceData.getUpperLimit());
+ this.plotWidth = generator.getOriginalPlotModelWidth();
+ this.plotWidth *= getCapability(MagnificationCapability.class)
+ .getMagnification();
+ generator.setPlotModelSize(Math.round(plotWidth));
+
+ // TODO this should be in a factory or something
+ if (resourceData.getSpiFile() != null) {
+ progressiveDisclosure = new SpiProgDisclosure(this, descriptor,
+ resourceData.getSpiFile());
+ } else {
+ progressiveDisclosure = new DynamicProgDisclosure(this, descriptor);
}
- }
+ progressiveDisclosure.setMagnification(this.getCapability(
+ MagnificationCapability.class).getMagnification());
+ progressiveDisclosure.setDensity(this.getCapability(
+ DensityCapability.class).getDensity());
+ progressiveDisclosure.setPixelSizeHint(resourceData.getPixelSizeHint());
+ progressiveDisclosure.setPlotWidth(plotWidth);
- protected synchronized void updateRecords() throws VizException {
- if (this.stationsToParse.size() > 0) {
- FrameInformation targetFrame = null;
- for (PluginDataObject ob : this.stationsToParse) {
- DataTime normalized = this.getNormalizedTime(ob.getDataTime());
- if (!this.dataTimes.contains(normalized)) {
- this.dataTimes.add(normalized);
- } else if ((targetFrame = this.frameInfo.get(normalized
- .toString())) != null) {
- ObsInformation station = this.parseDataUri(ob.getDataURI(),
- String.valueOf(ob.getId()));
- Integer stationIndex = null;
- if ((stationIndex = targetFrame.frameStations
- .get(station.icao)) != null) {
- PluginDataObject storedOb = this.generator
- .getStationObject(targetFrame.frameDataUris
- .get(stationIndex));
- if (storedOb == null) {
- targetFrame.frameDataUris.set(stationIndex,
- ob.getDataURI());
- } else if (storedOb.getDataTime().compareTo(
- ob.getDataTime()) < 1) {
- targetFrame.frameDataUris.set(stationIndex,
- ob.getDataURI());
- }
- } else {
- // new station!
- this.calcStaticStationInfo(station, targetFrame);
- this.generator.setStation(ob.getDataURI());
- this.calculateProgDisc(targetFrame);
+ DataTime[] dts = this.descriptor.getFramesInfo().getTimeMap().get(this);
+ // if this is null then the time matcher has not yet had time to time
+ // match this, in which case frames will have to load when they are
+ // first painted.
+ if (dts != null) {
+ // init backwards
+ for (int i = dts.length - 1; i > -1; i--) {
+ DataTime time = dts[i];
+ if (time != null) {
+ FrameInformation curFrame = frameMap.get(time);
+ if (curFrame == null) {
+ curFrame = startFrameInit(time);
}
-
}
}
- this.stationsToParse.clear();
}
}
- public void addRecord(PluginDataObject record) throws VizException {
- Validate.notNull(record);
- // Validate.isTrue(record instanceof MetarRecord);
- // this.recordsToParse.add((MetarRecord) record);
- this.stationsToParse.add(record);
+ private synchronized FrameInformation startFrameInit(DataTime time) {
+ FrameInformation frame = new FrameInformation();
+ dataTimes.add(time);
+ frameMap.put(time, frame);
+ FrameRetriever retriever = new FrameRetriever();
+ retriever.dataTime = time;
+ frameRetrievalPool.schedule(retriever);
+ return frame;
+ }
+ /**
+ * Checks the plots to ensure they are displayable, ie a frame exists that
+ * matches their time and they are within the descriptor's world extent. If
+ * so, schedules them for disclosure. Also checks if a plot already exists
+ * and this is an update, and if so, updates the plot.
+ *
+ * @param stationsToParse
+ * stations to potentially process and display
+ * @throws VizException
+ */
+ protected void updateRecords(PlotInfo[] stationsToParse)
+ throws VizException {
+ Validate.notNull(stationsToParse);
+ Map> plots = new HashMap>();
+ // Sort plots into normalized datatimes that should match frames
+ for (PlotInfo info : stationsToParse) {
+ DataTime normTime = getNormalizedTime(info.dataTime);
+ if (frameMap.containsKey(normTime)) {
+ List list = plots.get(normTime);
+ if (list == null) {
+ list = new ArrayList();
+ plots.put(normTime, list);
+ }
+ list.add(info);
+
+ }
+ }
+
+ GridEnvelope range = descriptor.getGridGeometry().getGridRange();
+ PixelExtent worldExtent = new PixelExtent(range.getLow(0),
+ range.getHigh(0), range.getLow(1), range.getHigh(1));
+
+ for (Entry> entry : plots.entrySet()) {
+ DataTime time = entry.getKey();
+ List info = entry.getValue();
+ FrameInformation frameInfo = frameMap.get(time);
+
+ // Sort this data in "backwards" so that the most recent observation
+ // for a particular station display correctly
+ if (info.size() > 1) {
+ Collections.sort(info, new Comparator() {
+
+ @Override
+ public int compare(PlotInfo o1, PlotInfo o2) {
+ return o2.dataTime.compareTo(o1.dataTime);
+ }
+ });
+ }
+
+ if (frameInfo != null) {
+ Map stationMap = frameInfo.stationMap;
+ for (PlotInfo plot : info) {
+ if (plot.stationId == null) {
+ plot.stationId = plot.latitude + "#" + plot.longitude;
+ }
+ synchronized (stationMap) {
+ if (stationMap.containsKey(plot.stationId)) {
+ processUpdatedPlot(stationMap.get(plot.stationId),
+ plot);
+ } else {
+ double[] thisLocationPixel = descriptor
+ .worldToPixel(new double[] {
+ plot.longitude, plot.latitude });
+ if ((thisLocationPixel != null)
+ && worldExtent.contains(
+ thisLocationPixel[0],
+ thisLocationPixel[1])) {
+ Station station = new Station();
+ station.info = new PlotInfo[] { plot };
+ station.pixelLocation = new Coordinate(
+ thisLocationPixel[0],
+ thisLocationPixel[1]);
+ stationMap.put(plot.stationId, station);
+ }
+ }
+ }
+ }
+
+ progressiveDisclosure.update(stationMap.values(), time);
+ }
+ }
+ issueRefresh();
+ }
+
+ /**
+ * Updates an existing station with a new plot.
+ *
+ * @param existingStation
+ * the existing station
+ * @param plot
+ * the newly received plot
+ */
+ protected void processUpdatedPlot(Station existingStation, PlotInfo plot) {
+ if (existingStation.plotImage != null) {
+ existingStation.plotImage.getImage().dispose();
+ existingStation.plotImage = null;
+ // DR14966
+ existingStation.rawMessage = null;
+ PlotInfo[] samplePlot = new PlotInfo[1];
+ samplePlot[0] = new PlotInfo();
+ samplePlot[0] = plot;
+ List list = new ArrayList();
+ list.add(samplePlot);
+ Params params = Params.PLOT_AND_SAMPLE;
+ GetDataTask task = new GetDataTask(list, params);
+ generator.enqueueDataRetrieval(task);
+ // End DR14996
+ }
+ boolean dup = false;
+ for (PlotInfo element : existingStation.info) {
+ String curUri = element.dataURI;
+ String newUri = plot.dataURI;
+ if ((curUri == null) || curUri.equals(newUri)) {
+ dup = true;
+ break;
+ }
+ }
+ if (!dup) {
+ // Added for DR14996
+ existingStation.info = Arrays.copyOf(existingStation.info, 1);
+ existingStation.info[0] = plot;
+ Arrays.sort(existingStation.info, new Comparator() {
+ @Override
+ public int compare(PlotInfo o1, PlotInfo o2) {
+ return o1.dataTime.compareTo(o2.dataTime);
+ }
+ });
+ }
}
private DataTime getNormalizedTime(DataTime time) {
- // long millis = time.getValidTime().getTimeInMillis();
- // millis -= this.resourceData.getBinOffset().negOffset;
- // millis = ((millis / this.range) * this.range) + this.range;
- // return new DataTime(new Date(millis));
-
- return this.resourceData.getBinOffset().getNormalizedTime(time);
+ if (this.resourceData.getBinOffset() != null) {
+ return this.resourceData.getBinOffset().getNormalizedTime(time);
+ } else {
+ return time;
+ }
}
@Override
protected void disposeInternal() {
- generator.shutdown();
- }
-
- @Override
- public DataTime[] getDataTimes() {
- try {
- if (this.dataTimes == null || this.dataTimes.size() < 1) {
- this.initDataTimeArray();
- }
- if (this.stationsToParse.size() > 0) {
- this.updateRecords();
- }
- } catch (VizException e) {
- e.printStackTrace();
+ resourceData.getPlotInfoRetriever().cancel();
+ progressiveDisclosure.shutdown();
+ if (generator != null) {
+ generator.shutdown();
}
- Collections.sort(this.dataTimes);
- DataTime[] returnTimes = new DataTime[this.dataTimes.size()];
- return this.dataTimes.toArray(returnTimes);
- }
-
- public void setDynProgDisc(String progDisc) {
- if ("none".matches(progDisc)) {
- this.dynProgDisc = 0;
- } else if ("missing".matches(progDisc)) {
- this.dynProgDisc = 2;
- } else if ("all".matches(progDisc)) {
- this.dynProgDisc = 3;
- } else if ("off".matches(progDisc)) {
- this.dynProgDisc = 4;
- }
- }
-
- public String getDynProgDisc() {
- switch (this.dynProgDisc) {
- case 0:
- return "none";
- case 2:
- return "missing";
- case 3:
- return "all";
- case 4:
- return "off";
- }
- return null;
- }
-
- private void initDataTimeArray() throws VizException {
- HashMap queryParams = new HashMap(
- resourceData.getMetadataMap());
- DataTime[] times = CatalogQuery.performTimeQuery(queryParams, false,
- this.resourceData.getBinOffset());
- this.dataTimes = new ArrayList(Arrays.asList(times));
- }
-
- private void calculateProgDisc(FrameInformation fi) {
- // long startProcess = System.currentTimeMillis();
- boolean progressiveDisclosure = fi.dynStations > 0
- && ((fi.uniqueueStations * fi.uniqueueStations / fi.dynStations) < 3000);
- progressiveDisclosure = this.dynProgDisc > 1
- || (progressiveDisclosure && this.dynProgDisc > 0);
-
- if (progressiveDisclosure) {
- Coordinate[] latLonArray = fi.frameStationLocations
- .toArray(new Coordinate[fi.frameStationLocations.size()]);
- Integer[] goodnessArray = fi.frameGoodnessValues
- .toArray(new Integer[fi.frameGoodnessValues.size()]);
- Double[] distArray = fi.origFrameDistValues
- .toArray(new Double[fi.origFrameDistValues.size()]);
- this.progDisc.setVaJustGoodness(false);
- this.progDisc.setVaDistPass(this.dynProgDisc < 3);
- this.progDisc.getVaAdvanced(latLonArray, goodnessArray, distArray);
- fi.frameDistValues = new ArrayList(Arrays.asList(distArray));
- } else {
- fi.frameDistValues = new ArrayList(fi.origFrameDistValues);
- for (int i = 0; i < fi.uniqueueStations; i++) {
- if (fi.frameDistValues.get(i) < 0) {
- fi.frameDistValues.set(i, fi.minDist);
- }
- }
- }
- fi.computeProgDisc = false;
- // System.out.println("Total time to perform progressive disclosure: " +
- // (System.currentTimeMillis() - startProcess));
-
+ clearImages();
}
private void initNewFrame(DataTime thisFrameTime) throws VizException {
- boolean useId = false;
- String thisFrameTimeString = thisFrameTime.toString();
- HashMap queryList = new HashMap(
+ RequestConstraint time = new RequestConstraint();
+
+ BinOffset tmpBinOffset = this.resourceData.getBinOffset();
+ if (tmpBinOffset == null) {
+ // do not set the bin offset in the resource data, it is probably
+ // null for a reason. non-null binOffset can cause problems with
+ // time matching for some products.
+ tmpBinOffset = new BinOffset();
+ }
+ TimeRange tr = null;
+
+ if (this.resourceData.isTopOfTheHour()) {
+ long offset = tmpBinOffset.getNegOffset() * 1000l;
+ long frameInMillis = thisFrameTime.getValidTime().getTimeInMillis();
+ tr = new TimeRange(frameInMillis - offset, frameInMillis);
+ } else if (this.resourceData.getDefaultPeriod() != null) {
+ tr = this.resourceData.getDefaultPeriod().getTimeRange(
+ thisFrameTime);
+ } else {
+ tr = tmpBinOffset.getTimeRange(thisFrameTime);
+ }
+ if (tr.getDuration() > 0) {
+ // handle binning
+ DataTime start = new DataTime(tr.getStart());
+ DataTime end = new DataTime(tr.getEnd());
+ String[] constraintList = { start.toString(), end.toString() };
+ time.setBetweenValueList(constraintList);
+ time.setConstraintType(RequestConstraint.ConstraintType.BETWEEN);
+
+ } else {
+ // handle exact times
+ time.setConstraintValue(thisFrameTime.toString());
+ }
+
+ HashMap metadataMap = new HashMap(
resourceData.getMetadataMap());
+ metadataMap.put("dataTime", time);
- // long frameMillis = thisFrameTime.getValidTime().getTimeInMillis();
- // DataTime start = new DataTime(new Date(frameMillis
- // - this.resourceData.getBinOffset().negOffset * 1000 + 1));
- // DataTime end = new DataTime(new Date(frameMillis
- // + (this.resourceData.getBinOffset().posOffset * 1000)));
-
- TimeRange tr = this.resourceData.getBinOffset().getTimeRange(
- thisFrameTime);
- DataTime start = new DataTime(tr.getStart());
- DataTime end = new DataTime(tr.getEnd());
-
- RequestConstraint timeRange = new RequestConstraint();
- String[] constraintList = { start.toString(), end.toString() };
- timeRange.setBetweenValueList(constraintList);
- timeRange.setConstraintType(RequestConstraint.ConstraintType.BETWEEN);
-
- queryList.put("dataTime", timeRange);
-
- DbQueryRequest request = new DbQueryRequest();
- request.setConstraints(queryList);
- request.addFields(new String[] { "dataURI", "id" });
- DbQueryResponse response = (DbQueryResponse) ThriftClient
- .sendRequest(request);
-
- // extract list of results
- List