Merge "Issue #227 enhanced caching of maps for thin client" into 4-Thin_Client

Former-commit-id: fea5d27880 [formerly 866627aaf3] [formerly 6a49a1bec3] [formerly 6a49a1bec3 [formerly 0608677c67]] [formerly b1810ddd3f [formerly 6a49a1bec3 [formerly 0608677c67] [formerly b1810ddd3f [formerly 825ddae7e604056e254530e225118f92d88d4b5c]]]]
Former-commit-id: b1810ddd3f
Former-commit-id: 5402822ba4c1fb40e0700d6d29fff24d2c6d6322 [formerly 93d0e49a083e8ce8673d74d19d46357d1cf3406d] [formerly 84aa8509e4 [formerly 8a0c505bac]]
Former-commit-id: 84aa8509e4
Former-commit-id: e49feb41cd
This commit is contained in:
Nate Jensen 2012-02-01 08:45:42 -06:00 committed by Gerrit Code Review
commit fb1ca3dfa0
12 changed files with 1045 additions and 493 deletions

View file

@ -19,7 +19,6 @@
**/ **/
package com.raytheon.uf.viz.core.maps.rsc; package com.raytheon.uf.viz.core.maps.rsc;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.CoordinateReferenceSystem;
@ -29,7 +28,6 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.IGraphicsTarget; import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.PixelExtent; import com.raytheon.uf.viz.core.PixelExtent;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage;
import com.raytheon.uf.viz.core.drawables.IFont; import com.raytheon.uf.viz.core.drawables.IFont;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.IMapDescriptor; import com.raytheon.uf.viz.core.map.IMapDescriptor;
@ -152,25 +150,10 @@ public abstract class AbstractDbMapResource<T extends AbstractDbMapResourceData,
*/ */
public List<String> getLabelFields() { public List<String> getLabelFields() {
if (this.labelFields == null) { if (this.labelFields == null) {
List<String> labelFields = new ArrayList<String>();
try { try {
int p = resourceData.getTable().indexOf('.'); this.labelFields = DbMapQueryFactory.getMapQuery(
String schema = resourceData.getTable().substring(0, p); resourceData.getTable(), resourceData.getGeomField())
String table = resourceData.getTable().substring(p + 1); .getColumnNamesWithoutGeometries();
StringBuilder query = new StringBuilder(
"SELECT column_name FROM information_schema.columns WHERE table_schema = '");
query.append(schema);
query.append("' AND table_name='");
query.append(table);
query.append("' AND udt_name != 'geometry' ORDER BY ordinal_position;");
List<Object[]> results = MapQueryCache.executeQuery(
query.toString(), "maps", QueryLanguage.SQL);
for (Object[] obj : results) {
labelFields.add(obj[0].toString());
}
ColumnDefinition[] columns = resourceData.getColumns(); ColumnDefinition[] columns = resourceData.getColumns();
if (columns != null) { if (columns != null) {
for (ColumnDefinition col : columns) { for (ColumnDefinition col : columns) {
@ -181,7 +164,6 @@ public abstract class AbstractDbMapResource<T extends AbstractDbMapResourceData,
statusHandler.handle(Priority.PROBLEM, statusHandler.handle(Priority.PROBLEM,
"Error querying available label fields", e); "Error querying available label fields", e);
} }
this.labelFields = labelFields;
} }
return this.labelFields; return this.labelFields;
} }

View file

@ -0,0 +1,86 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.core.maps.rsc;
import java.util.List;
import com.raytheon.uf.common.dataquery.db.QueryResult;
import com.raytheon.uf.viz.core.exception.VizException;
import com.vividsolutions.jts.geom.Envelope;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 9, 2011 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class DbMapQueryFactory {
public interface DbMapQuery {
public QueryResult queryWithinEnvelope(Envelope env,
List<String> columns, List<String> additionalConstraints)
throws VizException;
public List<String> getColumnNamesWithoutGeometries()
throws VizException;
public String getGeometryType() throws VizException;
public List<Double> getLevels() throws VizException;
}
private static DbMapQueryFactory instance;
public static DbMapQuery getMapQuery(String table, String geomField) {
return getInstance().getMapQueryInternal(table, geomField);
}
protected static DbMapQueryFactory getInstance() {
if (instance == null) {
instance = new DbMapQueryFactory();
}
return instance;
}
protected static void setCustomInstance(DbMapQueryFactory factory) {
instance = factory;
}
protected DbMapQueryFactory() {
}
protected DbMapQuery getMapQueryInternal(String table, String geomField) {
return new DefaultDbMapQuery(table, geomField);
}
}

View file

@ -53,6 +53,7 @@ import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment; import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment;
import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment; import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment;
import com.raytheon.uf.viz.core.PixelExtent; import com.raytheon.uf.viz.core.PixelExtent;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage; import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage;
import com.raytheon.uf.viz.core.drawables.IShadedShape; import com.raytheon.uf.viz.core.drawables.IShadedShape;
import com.raytheon.uf.viz.core.drawables.IWireframeShape; import com.raytheon.uf.viz.core.drawables.IWireframeShape;
@ -161,18 +162,18 @@ public class DbMapResource extends
String shadingField; String shadingField;
String query; Envelope envelope;
Map<Object, RGB> colorMap; Map<Object, RGB> colorMap;
Request(IGraphicsTarget target, IMapDescriptor descriptor, Request(IGraphicsTarget target, IMapDescriptor descriptor,
DbMapResource rsc, String query, String geomField, DbMapResource rsc, Envelope envelope, String geomField,
String labelField, String shadingField, String labelField, String shadingField,
Map<Object, RGB> colorMap) { Map<Object, RGB> colorMap) {
this.target = target; this.target = target;
this.descriptor = descriptor; this.descriptor = descriptor;
this.rsc = rsc; this.rsc = rsc;
this.query = query; this.envelope = envelope;
this.geomField = geomField; this.geomField = geomField;
this.labelField = labelField; this.labelField = labelField;
this.shadingField = shadingField; this.shadingField = shadingField;
@ -207,9 +208,9 @@ public class DbMapResource extends
public Throwable cause; public Throwable cause;
public String query; public Envelope query;
private Result(String query) { private Result(Envelope query) {
this.query = query; this.query = query;
failed = true; failed = true;
} }
@ -228,7 +229,7 @@ public class DbMapResource extends
} }
public void request(IGraphicsTarget target, IMapDescriptor descriptor, public void request(IGraphicsTarget target, IMapDescriptor descriptor,
DbMapResource rsc, String query, String geomField, DbMapResource rsc, Envelope query, String geomField,
String labelField, String shadingField, String labelField, String shadingField,
Map<Object, RGB> colorMap) { Map<Object, RGB> colorMap) {
if (requestQueue.size() == QUEUE_LIMIT) { if (requestQueue.size() == QUEUE_LIMIT) {
@ -255,7 +256,7 @@ public class DbMapResource extends
protected IStatus run(IProgressMonitor monitor) { protected IStatus run(IProgressMonitor monitor) {
Request req = requestQueue.poll(); Request req = requestQueue.poll();
while (req != null) { while (req != null) {
Result result = new Result(req.query); Result result = new Result(req.envelope);
try { try {
String table = resourceData.getTable(); String table = resourceData.getTable();
if (canceled) { if (canceled) {
@ -263,10 +264,35 @@ public class DbMapResource extends
result = null; result = null;
return Status.CANCEL_STATUS; return Status.CANCEL_STATUS;
} }
QueryResult mappedResult = MapQueryCache List<String> constraints = new ArrayList<String>();
.executeMappedQuery(req.query, "maps", if (resourceData.getConstraints() != null) {
QueryLanguage.SQL); constraints.addAll(Arrays.asList(resourceData
.getConstraints()));
}
List<String> fields = new ArrayList<String>();
fields.add(GID);
if (req.labelField != null
&& !fields.contains(req.labelField)) {
fields.add(req.labelField);
}
if (req.shadingField != null
&& !fields.contains(req.shadingField)) {
fields.add(req.shadingField);
}
if (resourceData.getColumns() != null) {
for (ColumnDefinition column : resourceData
.getColumns()) {
if (fields.contains(column.getName())) {
fields.remove(column.getName());
}
fields.add(column.toString());
}
}
QueryResult mappedResult = DbMapQueryFactory.getMapQuery(
resourceData.getTable(),
resourceData.getGeomField()).queryWithinEnvelope(
req.envelope, fields, constraints);
Map<Integer, Geometry> gidMap = new HashMap<Integer, Geometry>( Map<Integer, Geometry> gidMap = new HashMap<Integer, Geometry>(
mappedResult.getResultCount() * 2); mappedResult.getResultCount() * 2);
List<Integer> toRequest = new ArrayList<Integer>( List<Integer> toRequest = new ArrayList<Integer>(
@ -309,7 +335,7 @@ public class DbMapResource extends
result = null; result = null;
return Status.CANCEL_STATUS; return Status.CANCEL_STATUS;
} }
QueryResult geomResults = MapQueryCache QueryResult geomResults = DirectDbQuery
.executeMappedQuery(geomQuery.toString(), .executeMappedQuery(geomQuery.toString(),
"maps", QueryLanguage.SQL); "maps", QueryLanguage.SQL);
for (int i = 0; i < geomResults.getResultCount(); ++i) { for (int i = 0; i < geomResults.getResultCount(); ++i) {
@ -330,7 +356,7 @@ public class DbMapResource extends
"Expected byte[] received " "Expected byte[] received "
+ obj.getClass().getName() + obj.getClass().getName()
+ ": " + obj.toString() + ": " + obj.toString()
+ "\n query=\"" + req.query + "\n query=\"" + req.envelope
+ "\""); + "\"");
} }
gidMap.put(gid, g); gidMap.put(gid, g);
@ -525,7 +551,7 @@ public class DbMapResource extends
getLabelFields().toArray(new String[0])); getLabelFields().toArray(new String[0]));
} }
private String buildQuery(PixelExtent extent) throws VizException { private Envelope buildEnvelope(PixelExtent extent) throws VizException {
Envelope env = null; Envelope env = null;
try { try {
Envelope e = descriptor.pixelToWorld(extent, descriptor.getCRS()); Envelope e = descriptor.pixelToWorld(extent, descriptor.getCRS());
@ -535,60 +561,7 @@ public class DbMapResource extends
} catch (Exception e) { } catch (Exception e) {
throw new VizException("Error transforming extent", e); throw new VizException("Error transforming extent", e);
} }
return env;
double[] levels = getLevels();
String geometryField = getGeomField(levels[levels.length - 1]);
// get the geometry field
StringBuilder query = new StringBuilder("SELECT ");
query.append(GID);
// add any additional columns
List<String> additionalColumns = new ArrayList<String>();
if (resourceData.getColumns() != null) {
for (ColumnDefinition column : resourceData.getColumns()) {
query.append(", ");
query.append(column);
additionalColumns.add(column.getName());
}
}
// add the label field
String labelField = getCapability(LabelableCapability.class)
.getLabelField();
if (labelField != null && !additionalColumns.contains(labelField)) {
query.append(", ");
query.append(labelField);
}
// add the shading field
String shadingField = getCapability(ShadeableCapability.class)
.getShadingField();
if (shadingField != null && !additionalColumns.contains(shadingField)) {
query.append(", ");
query.append(shadingField);
}
// add the geometry table
query.append(" FROM ");
query.append(resourceData.getTable());
// add the geospatial constraint
query.append(" WHERE ");
query.append(getGeospatialConstraint(geometryField, env));
// add any additional constraints
if (resourceData.getConstraints() != null) {
for (String constraint : resourceData.getConstraints()) {
query.append(" AND ");
query.append(constraint);
}
}
query.append(';');
return query.toString();
} }
protected String getGeomField(double simpLev) { protected String getGeomField(double simpLev) {
@ -599,18 +572,6 @@ public class DbMapResource extends
return resourceData.getGeomField() + suffix; return resourceData.getGeomField() + suffix;
} }
/**
* @return
*/
protected Object getGeospatialConstraint(String geometryField, Envelope env) {
// create the geospatial constraint from the envelope
String geoConstraint = String.format(
"%s && ST_SetSrid('BOX3D(%f %f, %f %f)'::box3d,4326)",
geometryField, env.getMinX(), env.getMinY(), env.getMaxX(),
env.getMaxY());
return geoConstraint;
}
/** /**
* @param dpp * @param dpp
* @return * @return
@ -665,7 +626,7 @@ public class DbMapResource extends
clipToProjExtent(screenExtent).getEnvelope())) { clipToProjExtent(screenExtent).getEnvelope())) {
if (!paintProps.isZooming()) { if (!paintProps.isZooming()) {
PixelExtent expandedExtent = getExpandedExtent(screenExtent); PixelExtent expandedExtent = getExpandedExtent(screenExtent);
String query = buildQuery(expandedExtent); Envelope query = buildEnvelope(expandedExtent);
queryJob.request(aTarget, descriptor, this, query, queryJob.request(aTarget, descriptor, this, query,
getGeomField(simpLev), labelField, shadingField, getGeomField(simpLev), labelField, shadingField,
colorMap); colorMap);
@ -856,27 +817,13 @@ public class DbMapResource extends
protected double[] getLevels() { protected double[] getLevels() {
if (levels == null) { if (levels == null) {
try { try {
int p = resourceData.getTable().indexOf('.'); List<Double> results = DbMapQueryFactory.getMapQuery(
String schema = resourceData.getTable().substring(0, p); resourceData.getTable(), resourceData.getGeomField())
String table = resourceData.getTable().substring(p + 1); .getLevels();
StringBuilder query = new StringBuilder(
"SELECT f_geometry_column FROM public.geometry_columns WHERE f_table_schema='");
query.append(schema);
query.append("' AND f_table_name='");
query.append(table);
query.append("' AND f_geometry_column LIKE '");
query.append(resourceData.getGeomField());
query.append("_%';");
List<Object[]> results = MapQueryCache.executeQuery(
query.toString(), "maps", QueryLanguage.SQL);
levels = new double[results.size()]; levels = new double[results.size()];
int i = 0; int i = 0;
for (Object[] objs : results) { for (Double d : results) {
String s = ((String) objs[0]).substring( levels[i++] = d;
resourceData.getGeomField().length() + 1).replace(
'_', '.');
levels[i++] = Double.parseDouble(s);
} }
Arrays.sort(levels); Arrays.sort(levels);
} catch (VizException e) { } catch (VizException e) {
@ -891,19 +838,9 @@ public class DbMapResource extends
protected String getGeometryType() { protected String getGeometryType() {
if (geometryType == null) { if (geometryType == null) {
try { try {
int p = resourceData.getTable().indexOf('.'); geometryType = DbMapQueryFactory.getMapQuery(
String schema = resourceData.getTable().substring(0, p); resourceData.getTable(), resourceData.getGeomField())
String table = resourceData.getTable().substring(p + 1); .getGeometryType();
StringBuilder query = new StringBuilder(
"SELECT type FROM geometry_columns WHERE f_table_schema='");
query.append(schema);
query.append("' AND f_table_name='");
query.append(table);
query.append("' LIMIT 1;");
List<Object[]> results = MapQueryCache.executeQuery(
query.toString(), "maps", QueryLanguage.SQL);
geometryType = (String) results.get(0)[0];
} catch (Throwable e) { } catch (Throwable e) {
statusHandler.handle(Priority.PROBLEM, statusHandler.handle(Priority.PROBLEM,
"Error querying geometry type", e); "Error querying geometry type", e);

View file

@ -22,6 +22,7 @@ package com.raytheon.uf.viz.core.maps.rsc;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
@ -32,6 +33,7 @@ import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.RGB;
import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.geometry.jts.ReferencedEnvelope;
import com.raytheon.uf.common.dataquery.db.QueryResult;
import com.raytheon.uf.common.geospatial.MapUtil; import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate; import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.pointdata.vadriver.VA_Advanced; import com.raytheon.uf.common.pointdata.vadriver.VA_Advanced;
@ -45,7 +47,6 @@ import com.raytheon.uf.viz.core.IGraphicsTarget.PointStyle;
import com.raytheon.uf.viz.core.IGraphicsTarget.TextStyle; import com.raytheon.uf.viz.core.IGraphicsTarget.TextStyle;
import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment; import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment;
import com.raytheon.uf.viz.core.PixelExtent; import com.raytheon.uf.viz.core.PixelExtent;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage;
import com.raytheon.uf.viz.core.drawables.PaintProperties; import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.MapDescriptor; import com.raytheon.uf.viz.core.map.MapDescriptor;
@ -158,18 +159,19 @@ public class DbPointMapResource extends
private class Request { private class Request {
DbPointMapResource rsc; DbPointMapResource rsc;
boolean labeled; String labelField;
boolean useGoodness; String goodnessField;
String query; Envelope env;
Request(DbPointMapResource rsc, String query, boolean labeled, public Request(DbPointMapResource rsc, String labelField,
boolean useGoodness) { String goodnessField, Envelope env) {
super();
this.rsc = rsc; this.rsc = rsc;
this.query = query; this.labelField = labelField;
this.labeled = labeled; this.goodnessField = goodnessField;
this.useGoodness = useGoodness; this.env = env;
} }
} }
@ -200,11 +202,12 @@ public class DbPointMapResource extends
} }
public void request(IGraphicsTarget target, DbPointMapResource rsc, public void request(IGraphicsTarget target, DbPointMapResource rsc,
String query, boolean labeled, boolean useGoodness) { Envelope envelope, String labelField, String goodnessField) {
if (requestQueue.size() == QUEUE_LIMIT) { if (requestQueue.size() == QUEUE_LIMIT) {
requestQueue.poll(); requestQueue.poll();
} }
requestQueue.add(new Request(rsc, query, labeled, useGoodness)); requestQueue.add(new Request(rsc, labelField, goodnessField,
envelope));
this.cancel(); this.cancel();
this.schedule(); this.schedule();
@ -226,10 +229,37 @@ public class DbPointMapResource extends
while (req != null) { while (req != null) {
Result result = new Result(); Result result = new Result();
try { try {
System.out.println(req.query);
long t0 = System.currentTimeMillis(); long t0 = System.currentTimeMillis();
List<Object[]> results = MapQueryCache.executeQuery( List<String> columns = new ArrayList<String>();
req.query, "maps", QueryLanguage.SQL); if (req.labelField != null) {
columns.add(req.labelField);
}
if (req.goodnessField != null
&& req.goodnessField != req.labelField) {
columns.add(req.goodnessField);
}
if (resourceData.getColumns() != null) {
for (ColumnDefinition column : resourceData
.getColumns()) {
if (columns.contains(column.getName())) {
columns.remove(column.getName());
}
columns.add(column.toString());
}
}
columns.add("AsBinary(" + resourceData.getGeomField()
+ ") as " + resourceData.getGeomField());
List<String> constraints = null;
if (resourceData.getConstraints() != null) {
constraints = Arrays.asList(resourceData
.getConstraints());
}
QueryResult results = DbMapQueryFactory.getMapQuery(
resourceData.getTable(),
resourceData.getGeomField()).queryWithinEnvelope(
req.env, columns, constraints);
long t1 = System.currentTimeMillis(); long t1 = System.currentTimeMillis();
System.out.println("Maps DB query took: " + (t1 - t0) System.out.println("Maps DB query took: " + (t1 - t0)
@ -238,41 +268,48 @@ public class DbPointMapResource extends
List<LabelNode> newLabels = new ArrayList<LabelNode>(); List<LabelNode> newLabels = new ArrayList<LabelNode>();
WKBReader wkbReader = new WKBReader(); WKBReader wkbReader = new WKBReader();
for (Object[] r : results) { for (int c = 0; c < results.getResultCount(); c++) {
if (canceled) { if (canceled) {
canceled = false; canceled = false;
result = null; result = null;
// System.out.println("MapQueryJob Canceled."); // System.out.println("MapQueryJob Canceled.");
return Status.CANCEL_STATUS; return Status.CANCEL_STATUS;
} }
int i = 0;
Geometry g = null; Geometry g = null;
if (r[i] instanceof byte[]) { Object geomObj = results.getRowColumnValue(c,
byte[] wkb = (byte[]) r[i++]; resourceData.getGeomField());
if (geomObj instanceof byte[]) {
byte[] wkb = (byte[]) geomObj;
g = wkbReader.read(wkb); g = wkbReader.read(wkb);
} else { } else {
statusHandler.handle(Priority.ERROR, statusHandler.handle(Priority.ERROR,
"Expected byte[] received " "Expected byte[] received "
+ r[i].getClass().getName() + ": " + geomObj.getClass().getName()
+ r[i].toString() + "\n query=\"" + ": " + geomObj.toString()
+ req.query + "\""); + "\n query=\"" + req.env + "\"");
} }
if (g != null) { if (g != null) {
String label = ""; String label = "";
if (req.labeled && r[i] != null) { if (req.labelField != null
if (r[i] instanceof BigDecimal) { && results.getRowColumnValue(c,
label = Double.toString(((Number) r[i++]) req.labelField) != null) {
Object r = results.getRowColumnValue(c,
req.labelField);
if (r instanceof BigDecimal) {
label = Double.toString(((Number) r)
.doubleValue()); .doubleValue());
} else { } else {
label = r[i++].toString(); label = r.toString();
} }
} }
LabelNode node = new LabelNode(label, LabelNode node = new LabelNode(label,
g.getCentroid()); g.getCentroid());
if (req.useGoodness) { if (req.goodnessField != null) {
node.setGoodness(((Number) r[i++]).intValue()); node.setGoodness(((Number) results
.getRowColumnValue(c, req.goodnessField))
.intValue());
} }
newLabels.add(node); newLabels.add(node);
} }
@ -293,7 +330,7 @@ public class DbPointMapResource extends
} }
Double[] distances; Double[] distances;
if (req.useGoodness) { if (req.goodnessField != null) {
distances = distanceCalc.getVaAdvanced(coords, distances = distanceCalc.getVaAdvanced(coords,
goodness, dst); goodness, dst);
} else { } else {
@ -358,7 +395,7 @@ public class DbPointMapResource extends
queryJob = new MapQueryJob(); queryJob = new MapQueryJob();
} }
private String buildQuery(IGraphicsTarget target, PixelExtent extent) private void requestData(IGraphicsTarget target, PixelExtent extent)
throws VizException { throws VizException {
Envelope env = null; Envelope env = null;
@ -370,62 +407,13 @@ public class DbPointMapResource extends
} catch (Exception e) { } catch (Exception e) {
throw new VizException("Error transforming extent", e); throw new VizException("Error transforming extent", e);
} }
// System.out.println(env);
String geometryField = resourceData.getGeomField();
// create the geospatial constraint from the envelope
String geoConstraint = String.format(
"%s && ST_SetSrid('BOX3D(%f %f, %f %f)'::box3d,4326)",
geometryField, env.getMinX(), env.getMinY(), env.getMaxX(),
env.getMaxY());
// get the geometry field
StringBuilder query = new StringBuilder("SELECT AsBinary(");
query.append(geometryField);
query.append(")");
// add the label field // add the label field
String labelField = getCapability(LabelableCapability.class) String labelField = getCapability(LabelableCapability.class)
.getLabelField(); .getLabelField();
if (labelField != null) {
query.append(", ");
query.append(labelField);
}
// add the goodness field queryJob.request(target, this, env, labelField,
if (resourceData.getGoodnessField() != null) { resourceData.getGoodnessField());
query.append(", ");
query.append(resourceData.getGoodnessField());
}
// add any additional columns
if (resourceData.getColumns() != null) {
for (ColumnDefinition column : resourceData.getColumns()) {
query.append(", ");
query.append(column);
}
}
// add the geometry table
query.append(" FROM ");
query.append(resourceData.getTable());
// add the geo constraint
query.append(" WHERE ");
query.append(geoConstraint);
// add any addtional constraints
if (resourceData.getConstraints() != null) {
for (String constraint : resourceData.getConstraints()) {
query.append(" AND ");
query.append(constraint);
}
}
query.append(';');
return query.toString();
} }
@Override @Override
@ -454,9 +442,7 @@ public class DbPointMapResource extends
clipToProjExtent(screenExtent).getEnvelope())) { clipToProjExtent(screenExtent).getEnvelope())) {
if (!paintProps.isZooming()) { if (!paintProps.isZooming()) {
PixelExtent expandedExtent = getExpandedExtent(screenExtent); PixelExtent expandedExtent = getExpandedExtent(screenExtent);
String query = buildQuery(aTarget, expandedExtent); requestData(aTarget, expandedExtent);
queryJob.request(aTarget, this, query, isLabeled,
resourceData.getGoodnessField() != null);
lastExtent = expandedExtent; lastExtent = expandedExtent;
lastLabelField = labelField; lastLabelField = labelField;
} }

View file

@ -0,0 +1,178 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.core.maps.rsc;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.raytheon.uf.common.dataquery.db.QueryResult;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.maps.rsc.DbMapQueryFactory.DbMapQuery;
import com.vividsolutions.jts.geom.Envelope;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 9, 2011 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class DefaultDbMapQuery implements DbMapQuery {
protected static final String MAPS = "maps";
protected final String table;
protected final String geomField;
protected DefaultDbMapQuery(String table, String geomField) {
this.table = table;
this.geomField = geomField;
}
@Override
public QueryResult queryWithinEnvelope(Envelope env, List<String> columns,
List<String> additionalConstraints) throws VizException {
// add the geospatial constraint
if (env != null) {
// copy before modifying
if (additionalConstraints == null) {
additionalConstraints = new ArrayList<String>();
} else {
additionalConstraints = new ArrayList<String>(
additionalConstraints);
}
// geospatial constraint will be first
additionalConstraints.add(0, String.format(
"%s && ST_SetSrid('BOX3D(%f %f, %f %f)'::box3d,4326)",
geomField, env.getMinX(), env.getMinY(), env.getMaxX(),
env.getMaxY()));
}
StringBuilder query = new StringBuilder("SELECT ");
if (columns != null && !columns.isEmpty()) {
Iterator<String> iter = columns.iterator();
query.append(iter.next());
while (iter.hasNext()) {
query.append(", ");
query.append(iter.next());
}
}
query.append(" FROM ");
query.append(table);
// add any additional constraints
if (additionalConstraints != null && !additionalConstraints.isEmpty()) {
query.append(" WHERE ");
Iterator<String> iter = additionalConstraints.iterator();
query.append(iter.next());
while (iter.hasNext()) {
query.append(" AND ");
query.append(iter.next());
}
}
query.append(';');
return DirectDbQuery.executeMappedQuery(query.toString(), MAPS,
QueryLanguage.SQL);
}
@Override
public List<String> getColumnNamesWithoutGeometries() throws VizException {
List<String> labelFields = new ArrayList<String>();
int p = table.indexOf('.');
String schema = table.substring(0, p);
String table = this.table.substring(p + 1);
StringBuilder query = new StringBuilder(
"SELECT column_name FROM information_schema.columns WHERE table_schema = '");
query.append(schema);
query.append("' AND table_name='");
query.append(table);
query.append("' ");
query.append("AND udt_name != 'geometry' ");
query.append("ORDER BY ordinal_position;");
List<Object[]> results = DirectDbQuery.executeQuery(query.toString(),
MAPS, QueryLanguage.SQL);
for (Object[] obj : results) {
labelFields.add(obj[0].toString());
}
return labelFields;
}
@Override
public String getGeometryType() throws VizException {
int p = table.indexOf('.');
String schema = table.substring(0, p);
String table = this.table.substring(p + 1);
StringBuilder query = new StringBuilder(
"SELECT type FROM geometry_columns WHERE f_table_schema='");
query.append(schema);
query.append("' AND f_table_name='");
query.append(table);
query.append("' LIMIT 1;");
List<Object[]> results = DirectDbQuery.executeQuery(query.toString(),
MAPS, QueryLanguage.SQL);
return (String) results.get(0)[0];
}
@Override
public List<Double> getLevels() throws VizException {
int p = table.indexOf('.');
String schema = table.substring(0, p);
String table = this.table.substring(p + 1);
StringBuilder query = new StringBuilder(
"SELECT f_geometry_column FROM public.geometry_columns WHERE f_table_schema='");
query.append(schema);
query.append("' AND f_table_name='");
query.append(table);
query.append("' AND f_geometry_column LIKE '");
query.append(geomField);
query.append("_%';");
List<Object[]> results = DirectDbQuery.executeQuery(query.toString(),
MAPS, QueryLanguage.SQL);
List<Double> levels = new ArrayList<Double>(results.size());
for (Object[] objs : results) {
String s = (String) objs[0];
s = s.replace(geomField + "_", "");
s = s.replace('_', '.');
levels.add(Double.parseDouble(s));
}
return levels;
}
}

View file

@ -1,269 +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.uf.viz.core.maps.rsc;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import com.raytheon.uf.common.dataquery.db.QueryResult;
import com.raytheon.uf.common.dataquery.db.QueryResultRow;
import com.raytheon.uf.common.localization.FileLocker;
import com.raytheon.uf.common.localization.FileLocker.Type;
import com.raytheon.uf.common.serialization.DynamicSerializationManager;
import com.raytheon.uf.common.serialization.DynamicSerializationManager.SerializationType;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.util.cache.ICacheObject;
import com.raytheon.uf.common.util.cache.LRUCache;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.maps.rsc.MapQueryCache.QueryCacheable;
/**
* Map query caching derived from Erik Magnuson's code changes to DirectDbQuery
* to keep map results around on the client and not waste time/bandwidth
* querying.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 9, 2011 njensen Initial creation
*
* </pre>
*
* @author njensen
* @version 1.0
*/
public class MapQueryCache extends LRUCache<String, QueryCacheable> {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(MapQueryCache.class);
private static MapQueryCache mapQueryCache = new MapQueryCache(
64 * 1024 * 1024);
private static boolean cache = false;
@DynamicSerialize
protected static class QueryCacheable implements ICacheObject {
@DynamicSerializeElement
QueryResult queryResult;
public QueryCacheable() {
}
protected QueryCacheable(QueryResult result) {
queryResult = result;
}
@Override
public int getSize() {
// TODO get better number or move this off LRU
return queryResult.getColumnCount() * queryResult.getRows().length
* 4;
}
public QueryResult getQueryResult() {
return queryResult;
}
public void setQueryResult(QueryResult queryResult) {
this.queryResult = queryResult;
}
}
@DynamicSerialize
protected static class CachePair {
@DynamicSerializeElement
String queryKey;
@DynamicSerializeElement
QueryCacheable cacheable;
public CachePair() {
}
protected CachePair(String key, QueryCacheable obj) {
this.queryKey = key;
this.cacheable = obj;
}
public String getQueryKey() {
return queryKey;
}
public void setQueryKey(String queryKey) {
this.queryKey = queryKey;
}
public QueryCacheable getCacheable() {
return cacheable;
}
public void setCacheable(QueryCacheable cacheable) {
this.cacheable = cacheable;
}
}
/**
* Private constructor
*
* @param maxSize
*/
private MapQueryCache(long maxSize) {
super(maxSize);
}
/**
* Executes a mapped query against DirectDbQuery API. If cache is enabled
* will check the cache before sending a query and if sending a query, will
* store the result in the cache.
*
* @param query
* @param database
* @param language
* @return
* @throws VizException
*/
public static QueryResult executeMappedQuery(String query, String database,
QueryLanguage language) throws VizException {
QueryResult queryResult = null;
String key = query + database + language;
if (cache) {
QueryCacheable cacheResult = mapQueryCache.get(key);
if (cacheResult != null) {
queryResult = cacheResult.queryResult;
}
}
if (queryResult == null) {
// either cache was disabled, it wasn't in cache, or reading cache
// failed, so send the query
queryResult = DirectDbQuery.executeMappedQuery(query, database,
language);
if (cache) {
mapQueryCache.put(key, new QueryCacheable(queryResult));
}
}
return queryResult;
}
/**
* Executes a query against DirectDbQuery API. If cache is enabled will
* check the cache before sending a query and if sending a query, will store
* the result in the cache.
*
* @param query
* @param database
* @param language
* @return
* @throws VizException
*/
public static List<Object[]> executeQuery(String query, String database,
QueryLanguage language) throws VizException {
QueryResult result = executeMappedQuery(query, database, language);
List<Object[]> unmappedResults = new ArrayList<Object[]>();
for (QueryResultRow row : result.getRows()) {
unmappedResults.add(row.getColumnValues());
}
return unmappedResults;
}
public static void setCaching(boolean caching) {
cache = caching;
}
private Collection<CachePair> getCacheables() {
List<CachePair> pairs = new ArrayList<CachePair>(lruMap.size());
synchronized (this) {
for (Entry<String, Item> entry : lruMap.entrySet()) {
pairs.add(new CachePair(entry.getKey(), entry.getValue().value));
}
}
return pairs;
}
private void setCacheables(Collection<CachePair> pairs) {
for (CachePair pair : pairs) {
put(pair.queryKey, pair.cacheable);
}
}
/**
* Restore the geometry cache from the file system
*/
@SuppressWarnings("unchecked")
public static synchronized void restoreCache(File cacheFile) {
try {
FileLocker.lock(MapQueryCache.class, cacheFile, Type.READ);
if (cacheFile.exists() && cacheFile.length() > 0) {
FileInputStream fin = new FileInputStream(cacheFile);
Collection<CachePair> pairs = (Collection<CachePair>) DynamicSerializationManager
.getManager(SerializationType.Thrift).deserialize(fin);
mapQueryCache.setCacheables(pairs);
}
} catch (Exception e) {
statusHandler.error("Error restoring cache from file system", e);
e.printStackTrace();
} finally {
FileLocker.unlock(MapQueryCache.class, cacheFile);
}
}
/**
* Store the geometry cache to the file system
*/
public static synchronized void storeCache(File cacheFile) {
try {
FileLocker.lock(MapQueryCache.class, cacheFile, Type.WRITE);
FileOutputStream out = new FileOutputStream(cacheFile);
DynamicSerializationManager.getManager(SerializationType.Thrift)
.serialize(mapQueryCache.getCacheables(), out);
out.close();
} catch (Exception e) {
statusHandler.error("Error storing cache to file system", e);
e.printStackTrace();
} finally {
FileLocker.unlock(MapQueryCache.class, cacheFile);
}
}
}

View file

@ -17,6 +17,10 @@ Require-Bundle: com.raytheon.uf.viz.core,
Import-Package: com.raytheon.uf.common.comm, Import-Package: com.raytheon.uf.common.comm,
com.raytheon.uf.common.datastorage, com.raytheon.uf.common.datastorage,
com.raytheon.uf.viz.core.maps.rsc, com.raytheon.uf.viz.core.maps.rsc,
com.vividsolutions.jts.geom,
com.vividsolutions.jts.index.strtree,
com.vividsolutions.jts.io,
javax.jms javax.jms
Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy Bundle-ActivationPolicy: lazy
Export-Package: com.raytheon.uf.viz.thinclient.cave.cache.map

View file

@ -21,8 +21,8 @@ package com.raytheon.uf.viz.thinclient.cave.cache;
import java.io.File; import java.io.File;
import com.raytheon.uf.viz.core.maps.rsc.MapQueryCache;
import com.raytheon.uf.viz.thinclient.cache.AbstractCachePersistance; import com.raytheon.uf.viz.thinclient.cache.AbstractCachePersistance;
import com.raytheon.uf.viz.thinclient.cave.cache.map.CacheDbMapQueryFactory;
import com.raytheon.uf.viz.thinclient.preferences.ThinClientPreferenceConstants; import com.raytheon.uf.viz.thinclient.preferences.ThinClientPreferenceConstants;
/** /**
@ -57,7 +57,8 @@ public class MapQueryCachePersistence extends AbstractCachePersistance {
*/ */
@Override @Override
public void store(File cacheFile) { public void store(File cacheFile) {
MapQueryCache.storeCache(cacheFile); CacheDbMapQueryFactory.storeCache(cacheFile);
// MapQueryCache.storeCache(cacheFile);
} }
/* /*
@ -69,7 +70,8 @@ public class MapQueryCachePersistence extends AbstractCachePersistance {
*/ */
@Override @Override
public void restore(File cacheFile) { public void restore(File cacheFile) {
MapQueryCache.restoreCache(cacheFile); CacheDbMapQueryFactory.restoreCache(cacheFile);
// MapQueryCache.restoreCache(cacheFile);
} }
@ -81,7 +83,7 @@ public class MapQueryCachePersistence extends AbstractCachePersistance {
*/ */
@Override @Override
protected void enable() { protected void enable() {
MapQueryCache.setCaching(true); CacheDbMapQueryFactory.setEnableCaching(true);
} }
/* /*
@ -92,7 +94,7 @@ public class MapQueryCachePersistence extends AbstractCachePersistance {
*/ */
@Override @Override
protected void disable() { protected void disable() {
MapQueryCache.setCaching(false); CacheDbMapQueryFactory.setEnableCaching(false);
} }
} }

View file

@ -0,0 +1,327 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.thinclient.cave.cache.map;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.dataquery.db.QueryResult;
import com.raytheon.uf.common.dataquery.db.QueryResultRow;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery;
import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.maps.rsc.DefaultDbMapQuery;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.index.strtree.STRtree;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKBReader;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 9, 2011 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class CacheDbMapQuery extends DefaultDbMapQuery {
private static final String GID = "gid";
private static final String GEOM_ENV = "geom_env";
// Used for spatial lookups, returns a list of indexes into the data
private STRtree tree;
// all database columns for every row, this is the primary cached data.
private QueryResult data = null;
// a specific list of indexes which are returned for any given constraint
private Map<String, List<Integer>> constraint2indices = new HashMap<String, List<Integer>>();
// The column names available without any geometry columns.
private List<String> columnNames = null;
// the geometry type
private String geometryType = null;;
// all levels for a the geometry
private List<Double> levels = null;
private Object columnNamesLock = new Object();
private Object geometryTypeLock = new Object();
private Object levelsLock = new Object();
protected CacheDbMapQuery(String table, String geomField) {
super(table, geomField);
}
protected CacheDbMapQuery(CacheDbMapQuerySerializeable s)
throws VizException {
super(s.getTable(), s.getGeomField());
geometryType = s.getGeometryType();
columnNames = s.getColumnNames();
levels = s.getLevels();
constraint2indices = s.getConstraint2indices();
data = s.getData();
if (data != null) {
createTree();
}
}
@Override
public QueryResult queryWithinEnvelope(Envelope env, List<String> columns,
List<String> additionalConstraints) throws VizException {
fillCache(geomField, columns);
List<?> items = tree.query(env);
List<Integer> validGIDs = null;
if (additionalConstraints != null) {
for (String constraint : additionalConstraints) {
items.retainAll(getIndices(constraint));
}
}
List<QueryResultRow> rows = new ArrayList<QueryResultRow>();
for (int i = 0; i < items.size(); i++) {
int rowNumber = (Integer) items.get(i);
if (validGIDs != null
&& !validGIDs.contains(data.getRowColumnValue(rowNumber,
GID))) {
continue;
}
Object[] columnValues = new Object[columns.size()];
for (int j = 0; j < columns.size(); j++) {
columnValues[j] = data.getRowColumnValue(rowNumber,
columns.get(j));
}
rows.add(new QueryResultRow(columnValues));
}
Map<String, Integer> columnNames = new HashMap<String, Integer>();
for (int i = 0; i < columns.size(); i++) {
columnNames.put(doAs(columns.get(i)), i);
}
return new QueryResult(columnNames, rows.toArray(new QueryResultRow[0]));
}
private List<Integer> getIndices(String constraint) throws VizException {
synchronized (constraint2indices) {
List<Integer> indices = constraint2indices.get(constraint);
if (indices != null) {
return indices;
}
StringBuilder query = new StringBuilder("SELECT ");
query.append(GID);
query.append(" FROM ");
query.append(table);
query.append(" WHERE ");
query.append(constraint);
query.append(";");
List<Object[]> results = DirectDbQuery.executeQuery(
query.toString(), MAPS, QueryLanguage.SQL);
ArrayList<Integer> gids = new ArrayList<Integer>(results.size());
for (Object[] result : results) {
gids.add((Integer) result[0]);
}
indices = new ArrayList<Integer>(gids.size());
for (int i = 0; i < data.getResultCount(); ++i) {
int gid = (Integer) data.getRowColumnValue(i, "gid");
if (gids.contains(gid)) {
indices.add(i);
}
}
constraint2indices.put(constraint, indices);
return indices;
}
}
private QueryResult getColumns(List<String> columns) throws VizException {
StringBuilder query = new StringBuilder("SELECT ");
Iterator<String> iter = columns.iterator();
query.append(iter.next());
while (iter.hasNext()) {
query.append(", ");
query.append(iter.next());
}
query.append(" from ");
query.append(table);
query.append(";");
QueryResult result = DirectDbQuery.executeMappedQuery(query.toString(),
MAPS, QueryLanguage.SQL);
for (String column : columns) {
String as = doAs(column);
if (as.equals(column)) {
continue;
}
if (GEOM_ENV.equals(as)) {
continue;
}
int index = result.getColumnNames().remove(doAs(column));
result.getColumnNames().put(column, index);
}
return result;
}
private synchronized void fillCache(String geomField, List<String> columns)
throws VizException {
columns = new ArrayList<String>(columns);
if (data != null) {
for (String column : data.getColumnNames().keySet()) {
columns.remove(column);
}
}
if (columns.isEmpty()) {
return;
}
// we correlate data based off gid so make sure it is in there.
if (!columns.contains("gid")) {
columns.add("gid");
}
if (tree == null) {
// request the envelope
String envColumn = "AsBinary(ST_Envelope(" + geomField + ")) as "
+ GEOM_ENV;
columns.add(envColumn);
QueryResult result = getColumns(columns);
columns.remove(envColumn);
data = result;
createTree();
} else {
QueryResult result = getColumns(columns);
// gid should already be in the result set.
columns.remove("gid");
Map<Integer, QueryResultRow> gid2row = new HashMap<Integer, QueryResultRow>();
for (int i = 0; i < result.getResultCount(); ++i) {
int gid = (Integer) result.getRowColumnValue(i, "gid");
gid2row.put(gid, result.getRows()[i]);
}
int index = data.getColumnNames().size();
for (String column : columns) {
data.getColumnNames().put(column, index++);
}
for (int i = 0; i < data.getResultCount(); ++i) {
int gid = (Integer) data.getRowColumnValue(i, "gid");
QueryResultRow existRow = data.getRows()[i];
QueryResultRow resultRow = gid2row.get(gid);
Object[] columnValues = existRow.getColumnValues();
columnValues = Arrays.copyOf(columnValues, columnValues.length
+ columns.size());
for (String column : columns) {
int resultIndex = result.getColumnNames().get(column);
int newIndex = data.getColumnNames().get(column);
columnValues[newIndex] = resultRow.getColumn(resultIndex);
}
existRow.setColumnValues(columnValues);
}
}
}
private void createTree() throws VizException {
WKBReader wkbReader = new WKBReader();
tree = new STRtree();
try {
for (int i = 0; i < data.getResultCount(); ++i) {
Object obj = data.getRowColumnValue(i, GEOM_ENV);
if (obj instanceof byte[]) {
byte[] wkb = (byte[]) obj;
Geometry g = wkbReader.read(wkb);
Envelope e = g.getEnvelopeInternal();
tree.insert(e, i);
} else {
throw new VizException("Error populating GID Cache.");
}
}
} catch (ParseException e) {
throw new VizException(e);
}
}
private String doAs(String string) {
String[] split = string.split("\\s[aA][sS]\\s");
return split[split.length - 1].trim().toLowerCase();
}
@Override
public List<String> getColumnNamesWithoutGeometries() throws VizException {
synchronized (columnNamesLock) {
if (columnNames == null) {
columnNames = super.getColumnNamesWithoutGeometries();
}
return new ArrayList<String>(columnNames);
}
}
@Override
public String getGeometryType() throws VizException {
synchronized (geometryTypeLock) {
if (geometryType == null) {
geometryType = super.getGeometryType();
}
return geometryType;
}
}
@Override
public List<Double> getLevels() throws VizException {
synchronized (levelsLock) {
if (levels == null) {
levels = super.getLevels();
}
return levels;
}
}
protected CacheDbMapQuerySerializeable getSerializeable() {
CacheDbMapQuerySerializeable s = new CacheDbMapQuerySerializeable();
s.setTable(table);
s.setGeomField(geomField);
s.setGeometryType(geometryType);
s.setColumnNames(columnNames);
s.setLevels(levels);
s.setConstraint2indices(constraint2indices);
s.setData(data);
return s;
}
protected String getTable() {
return table;
}
protected String getGeomField() {
return geomField;
}
}

View file

@ -0,0 +1,145 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.thinclient.cave.cache.map;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.localization.FileLocker;
import com.raytheon.uf.common.localization.FileLocker.Type;
import com.raytheon.uf.common.serialization.DynamicSerializationManager;
import com.raytheon.uf.common.serialization.DynamicSerializationManager.SerializationType;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.viz.core.maps.rsc.DbMapQueryFactory;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 9, 2011 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class CacheDbMapQueryFactory extends DbMapQueryFactory {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(CacheDbMapQueryFactory.class);
private static CacheDbMapQueryFactory instance;
private Map<String, CacheDbMapQuery> cache = new HashMap<String, CacheDbMapQuery>();
@Override
protected CacheDbMapQuery getMapQueryInternal(String table, String geomField) {
String key = table + ":::" + geomField;
synchronized (cache) {
CacheDbMapQuery query = cache.get(key);
if (query == null) {
query = new CacheDbMapQuery(table, geomField);
cache.put(key, query);
}
return query;
}
}
public static synchronized void setEnableCaching(boolean enabled) {
if (enabled) {
if (instance == null) {
instance = new CacheDbMapQueryFactory();
}
setCustomInstance(instance);
} else {
setCustomInstance(null);
}
}
public static synchronized void restoreCache(File cacheFile) {
if (instance == null) {
setCustomInstance(instance = new CacheDbMapQueryFactory());
}
synchronized (instance.cache) {
try {
FileLocker.lock(CacheDbMapQuery.class, cacheFile, Type.READ);
if (cacheFile.exists() && cacheFile.length() > 0) {
FileInputStream fin = new FileInputStream(cacheFile);
List<CacheDbMapQuerySerializeable> list = (List<CacheDbMapQuerySerializeable>) DynamicSerializationManager
.getManager(SerializationType.Thrift).deserialize(
fin);
for (CacheDbMapQuerySerializeable s : list) {
CacheDbMapQuery c = new CacheDbMapQuery(s);
String key = c.getTable() + ":::" + c.getGeomField();
instance.cache.put(key, c);
}
}
} catch (Exception e) {
statusHandler
.error("Error restoring cache from file system", e);
e.printStackTrace();
} finally {
FileLocker.unlock(CacheDbMapQuery.class, cacheFile);
}
}
}
/**
* Store the geometry cache to the file system
*/
public static synchronized void storeCache(File cacheFile) {
if (instance == null) {
return;
}
synchronized (instance.cache) {
try {
FileLocker.lock(CacheDbMapQuery.class, cacheFile, Type.WRITE);
FileOutputStream out = new FileOutputStream(cacheFile);
List<CacheDbMapQuerySerializeable> list = new ArrayList<CacheDbMapQuerySerializeable>(
instance.cache.size());
for (CacheDbMapQuery value : instance.cache.values()) {
list.add(value.getSerializeable());
}
DynamicSerializationManager
.getManager(SerializationType.Thrift).serialize(list,
out);
out.close();
} catch (Exception e) {
statusHandler.error("Error storing cache to file system", e);
e.printStackTrace();
} finally {
FileLocker.unlock(CacheDbMapQuery.class, cacheFile);
}
}
}
}

View file

@ -0,0 +1,176 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.thinclient.cave.cache.map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.raytheon.uf.common.dataquery.db.QueryResult;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 9, 2011 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
@DynamicSerialize
public class CacheDbMapQuerySerializeable {
@DynamicSerialize
public static class ConstraintAndIndices {
@DynamicSerializeElement
private String constraint;
@DynamicSerializeElement
private List<Integer> indices;
public String getConstraint() {
return constraint;
}
public void setConstraint(String constraint) {
this.constraint = constraint;
}
public List<Integer> getIndices() {
return indices;
}
public void setIndices(List<Integer> indices) {
this.indices = indices;
}
}
@DynamicSerializeElement
private String table;
@DynamicSerializeElement
private String geomField;
@DynamicSerializeElement
private QueryResult data;
@DynamicSerializeElement
private List<ConstraintAndIndices> constraintAndIndices;
@DynamicSerializeElement
private List<String> columnNames;
@DynamicSerializeElement
private String geometryType;;
@DynamicSerializeElement
private List<Double> levels;
public String getTable() {
return table;
}
public void setTable(String table) {
this.table = table;
}
public String getGeomField() {
return geomField;
}
public void setGeomField(String geomField) {
this.geomField = geomField;
}
public QueryResult getData() {
return data;
}
public void setData(QueryResult data) {
this.data = data;
}
public Map<String, List<Integer>> getConstraint2indices() {
Map<String, List<Integer>> m = new HashMap<String, List<Integer>>();
for (ConstraintAndIndices c : constraintAndIndices) {
m.put(c.getConstraint(), c.getIndices());
}
return m;
}
public void setConstraint2indices(
Map<String, List<Integer>> constraint2indices) {
constraintAndIndices = new ArrayList<ConstraintAndIndices>(
constraint2indices.size());
for (Entry<String, List<Integer>> entry : constraint2indices.entrySet()) {
ConstraintAndIndices c = new ConstraintAndIndices();
c.setConstraint(entry.getKey());
c.setIndices(entry.getValue());
constraintAndIndices.add(c);
}
}
public List<ConstraintAndIndices> getConstraintAndIndices() {
return constraintAndIndices;
}
public void setConstraintAndIndices(
List<ConstraintAndIndices> constraintAndIndices) {
this.constraintAndIndices = constraintAndIndices;
}
public List<String> getColumnNames() {
return columnNames;
}
public void setColumnNames(List<String> columnNames) {
this.columnNames = columnNames;
}
public String getGeometryType() {
return geometryType;
}
public void setGeometryType(String geometryType) {
this.geometryType = geometryType;
}
public List<Double> getLevels() {
return levels;
}
public void setLevels(List<Double> levels) {
this.levels = levels;
}
}

View file

@ -60,7 +60,6 @@ import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.IMapDescriptor; import com.raytheon.uf.viz.core.map.IMapDescriptor;
import com.raytheon.uf.viz.core.maps.rsc.AbstractDbMapResourceData.ColumnDefinition; import com.raytheon.uf.viz.core.maps.rsc.AbstractDbMapResourceData.ColumnDefinition;
import com.raytheon.uf.viz.core.maps.rsc.MapQueryCache;
import com.raytheon.uf.viz.core.maps.rsc.DbMapResource; import com.raytheon.uf.viz.core.maps.rsc.DbMapResource;
import com.raytheon.uf.viz.core.maps.rsc.DbMapResourceData; import com.raytheon.uf.viz.core.maps.rsc.DbMapResourceData;
import com.raytheon.uf.viz.core.rsc.LoadProperties; import com.raytheon.uf.viz.core.rsc.LoadProperties;
@ -203,7 +202,7 @@ public class ZoneSelectorResource extends DbMapResource {
// System.out.println(req.query); // System.out.println(req.query);
// long t0 = System.currentTimeMillis(); // long t0 = System.currentTimeMillis();
QueryResult mappedResult = MapQueryCache QueryResult mappedResult = DirectDbQuery
.executeMappedQuery(req.query, "maps", .executeMappedQuery(req.query, "maps",
QueryLanguage.SQL); QueryLanguage.SQL);
@ -984,7 +983,6 @@ public class ZoneSelectorResource extends DbMapResource {
return zoneNames; return zoneNames;
} }
@Override
protected String getGeospatialConstraint(String geometryField, Envelope env) { protected String getGeospatialConstraint(String geometryField, Envelope env) {
StringBuilder constraint = new StringBuilder(); StringBuilder constraint = new StringBuilder();