Issue #1551 - adding maps to the Data Access Framework

- initial commit of Maps Geometry Factory
- re-factored geometry factory code
- addressing peer review comments
- cast to Timestamp

Change-Id: Ie12177b5ae1a8d8d9151d061682730841cfcc807

Former-commit-id: 8155a2cc6dc16df4addf5b567c08890278dc48c3
This commit is contained in:
Bryan Kowal 2013-01-30 09:50:18 -06:00
parent 36272799c6
commit 964b30d5f2
18 changed files with 1444 additions and 194 deletions

View file

@ -187,6 +187,14 @@
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.raytheon.uf.common.dataplugin.maps"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.raytheon.uf.viz.core.maps"

View file

@ -17,7 +17,8 @@ Require-Bundle: org.eclipse.ui,
com.raytheon.uf.common.pointdata;bundle-version="1.12.1174",
com.raytheon.uf.viz.productbrowser;bundle-version="1.12.1152",
com.raytheon.uf.viz.core.rsc;bundle-version="1.0.0",
com.raytheon.uf.viz.ui.menus;bundle-version="1.12.1174"
com.raytheon.uf.viz.ui.menus;bundle-version="1.12.1174",
com.raytheon.uf.common.dataplugin.maps;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Eclipse-RegisterBuddy: com.raytheon.uf.viz.core

View file

@ -20,9 +20,9 @@
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.dataplugin.maps.dataaccess.util.MapsQueryUtil;
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;
@ -41,6 +41,7 @@ import com.vividsolutions.jts.geom.Envelope;
* ------------ ---------- ----------- --------------------------
* Dec 9, 2011 bsteffen Initial creation
* Sep 18, 2012 #1019 randerso cleaned up geometry type query
* Jan 30, 2013 #1551 bkowal Refactored
*
* </pre>
*
@ -64,47 +65,12 @@ public class DefaultDbMapQuery implements DbMapQuery {
@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(';');
/*
* Build the query using the common method.
*/
final String query = MapsQueryUtil.assembleMapsTableQuery(env, columns,
additionalConstraints, this.table, this.geomField);
return DirectDbQuery.executeMappedQuery(query.toString(), MAPS,
QueryLanguage.SQL);

View file

@ -14,7 +14,8 @@ Require-Bundle: com.raytheon.uf.common.time;visibility:=reexport,
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.localization;bundle-version="1.12.1174",
com.raytheon.uf.common.dataquery;bundle-version="1.0.0",
com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174"
com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174",
com.raytheon.uf.common.message;bundle-version="1.12.1174"
Export-Package: com.raytheon.uf.common.dataaccess,
com.raytheon.uf.common.dataaccess.exception,
com.raytheon.uf.common.dataaccess.geom,

View file

@ -0,0 +1,416 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataaccess.impl;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.sql.Timestamp;
import com.raytheon.uf.common.dataaccess.exception.DataRetrievalException;
import com.raytheon.uf.common.dataaccess.exception.TimeAgnosticDataException;
import com.raytheon.uf.common.dataaccess.geom.IGeometryData;
import com.raytheon.uf.common.dataaccess.geom.IGeometryDataFactory;
import com.raytheon.uf.common.dataaccess.geom.IGeometryRequest;
import com.raytheon.uf.common.dataaccess.util.DatabaseQueryUtil;
import com.raytheon.uf.common.dataaccess.util.DatabaseQueryUtil.QUERY_MODE;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.time.BinOffset;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
import com.vividsolutions.jts.geom.Geometry;
/**
* Abstracts the retrieval of geometry data by running queries directly against
* the database. Maybe this class could also be further abstracted and extended
* to Grid data types?
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 29, 2013 bkowal Initial creation
*
* </pre>
*
* @author bkowal
* @version 1.0
*/
public abstract class AbstractGeometryDatabaseFactory extends
AbstractDataFactory implements IGeometryDataFactory {
/*
* for now, we will assume that we will always be executing sql queries. If
* this assumption ever becomes invalid, the type of query that will be
* executed could be passed to the constructor or methods could be
* overridden.
*/
private static final QUERY_MODE queryMode = QUERY_MODE.MODE_SQLQUERY;
private String databaseName;
private String[] requiredIdentifiers;
/**
* Constructor
*
* @param databaseName
* the name of the database to execute queries against
* @param requiredIdentifiers
* the identifiers that need to be included in the request
* (ifdef)
*/
public AbstractGeometryDatabaseFactory(String databaseName,
String[] requiredIdentifiers) {
this.databaseName = databaseName;
this.requiredIdentifiers = requiredIdentifiers;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getAvailableTimes(com.
* raytheon.uf.common.dataaccess.IDataRequest)
*/
@Override
public DataTime[] getAvailableTimes(IGeometryRequest request)
throws TimeAgnosticDataException {
this.validateRequest(request);
return this.executeTimeQuery(this.assembleGetTimes(request), request);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getAvailableTimes(com.
* raytheon.uf.common.dataaccess.IDataRequest,
* com.raytheon.uf.common.time.BinOffset)
*/
@Override
public DataTime[] getAvailableTimes(IGeometryRequest request,
BinOffset binOffset) throws TimeAgnosticDataException {
this.validateRequest(request);
return this.executeTimeQuery(this.assembleGetTimes(request, binOffset),
request);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getData(com.raytheon.uf
* .common.dataaccess.IDataRequest, com.raytheon.uf.common.time.DataTime[])
*/
@Override
public IGeometryData[] getData(IGeometryRequest request, DataTime... times) {
this.validateRequest(request);
return this.executeDataQuery(this.assembleGetData(request, times),
request);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getData(com.raytheon.uf
* .common.dataaccess.IDataRequest, com.raytheon.uf.common.time.TimeRange)
*/
@Override
public IGeometryData[] getData(IGeometryRequest request, TimeRange timeRange) {
this.validateRequest(request);
return this.executeDataQuery(this.assembleGetData(request, timeRange),
request);
}
/**
* Runs a query to retrieve Data Times from the database.
*
* @param query
* the query to execute
* @param request
* the original request that we are processing
* @return an array of DataTimes
*/
protected final DataTime[] executeTimeQuery(String query,
IGeometryRequest request) {
List<Object[]> results = this.executeQuery(query, request);
List<DataTime> dataTimes = new ArrayList<DataTime>();
for (Object[] objects : results) {
/*
* verify that the object is one of the data types we are expecting.
*/
if (objects[0] instanceof Timestamp) {
dataTimes.add(new DataTime((Timestamp) objects[0]));
} else if (objects[0] instanceof DataTime) {
dataTimes.add((DataTime) objects[0]);
} else {
throw new DataRetrievalException(
"Unrecognized temporal object: "
+ objects[0].getClass().getName());
}
}
Collections.sort(dataTimes);
return dataTimes.toArray(new DataTime[dataTimes.size()]);
}
/**
* Runs a query to retrieve IGeometryData from the database.
*
* @param query
* the query to execute
* @param request
* the original request that we are processing
* @return an array of IGeometryData
*/
protected final IGeometryData[] executeDataQuery(String query,
IGeometryRequest request) {
List<Object[]> results = this.executeQuery(query, request);
return this.makeGeometries(results, request.getParameters(),
request.getIdentifiers());
}
/**
* Runs a query to retrieve raw data from the database.
*
* @param query
* the query to execute
* @param request
* the original request that we are processing
* @return the raw data retrieved from the database
*/
protected final List<Object[]> executeQuery(String query,
IGeometryRequest request) {
return DatabaseQueryUtil.executeDatabaseQuery(queryMode, query,
this.databaseName, request.getDatatype());
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.dataaccess.geom.IGeometryDataFactory#
* getAvailableLocationNames
* (com.raytheon.uf.common.dataaccess.geom.IGeometryRequest)
*/
@Override
public String[] getAvailableLocationNames(IGeometryRequest request) {
this.validateRequest(request);
List<Object[]> results = this.executeQuery(
this.assembleGetAvailableLocationNames(request), request);
List<String> locations = new ArrayList<String>();
for (Object[] objects : results) {
locations.add((String) objects[0]);
}
Collections.sort(locations, String.CASE_INSENSITIVE_ORDER);
return locations.toArray(new String[locations.size()]);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.dataaccess.impl.AbstractDataFactory#
* getRequiredIdentifiers()
*/
@Override
public String[] getRequiredIdentifiers() {
return this.requiredIdentifiers;
}
/*
* invoked to build the queries that will be executed.
*/
/**
* Builds a query that will be used to retrieve time from the database based
* on the provided request.
*
* @param request
* the original request that we are processing
* @return the query
*/
protected abstract String assembleGetTimes(IGeometryRequest request);
/**
* Builds a query that will be used to retrieve time from the database based
* on the provided request and the provided BinOffset. Necessary?
*
* @param request
* the original request that we are processing
* @param binOffset
* the BinOffset to apply to the retrieved DataTimes
* @return the query
*/
protected abstract String assembleGetTimes(IGeometryRequest request,
BinOffset binOffset);
/**
* Builds a query used to retrieve data from the database based on the
* provided request and a list of DataTimes.
*
* @param request
* the original request that we are processing
* @param times
* DataTimes to use when building the query; will most likely
* manifest as constraints
* @return the query
*/
protected abstract String assembleGetData(IGeometryRequest request,
DataTime... times);
/**
* Builds a query used to retrieve data from the database based on the
* provided request and the specified TimeRange.
*
* @param request
* the original request that we are processing
* @param timeRange
* a TimeRange to use when building the query; will most likely
* manifest as a BETWEEN constraint
* @return the query
*/
protected abstract String assembleGetData(IGeometryRequest request,
TimeRange timeRange);
/**
* Builds a query used to retrieve location information from the database
* based on the provided request
*
* @param request
* the original request that we are processing
* @return the query
*/
protected abstract String assembleGetAvailableLocationNames(
IGeometryRequest request);
/**
* Builds the data objects that will be returned by calls to getData() on
* the factory
*
* @param serverResult
* the results from the query run on the server
* @param paramNames
* the names of the parameters that were requested
* @param identifiers
* the identifiers from the data request
* @return the IGeometryData based on the results of the query
*/
protected IGeometryData[] makeGeometries(List<Object[]> serverResult,
String[] paramNames, Map<String, Object> identifiers) {
List<IGeometryData> resultList = new ArrayList<IGeometryData>();
Map<String, Object> attrs = Collections.unmodifiableMap(identifiers);
// loop over each db row
for (Object[] row : serverResult) {
resultList.add(this.makeGeometry(row, paramNames, attrs));
}
return resultList.toArray(new DefaultGeometryData[resultList.size()]);
}
/**
* Constructs a single IGeometryData
*
* @param data
* the raw data associated with a single row retrieved from the
* database
* @param paramNames
* the parameters specified in the original IGeometryRequest
* @param attrs
* the identifiers specified in the original IGeometryRequest
* @return the constructed IGeometryData
*/
protected abstract IGeometryData makeGeometry(Object[] data,
String[] paramNames, Map<String, Object> attrs);
/**
* Constructs a DefaultGeometryData based on the provided information
*
* @param time
* the provided DataTime
* @param level
* the provided Level
* @param geometry
* the provided Geometry
* @param locationName
* the provided Location
* @param attributes
* the identifiers specified in the original IGeometryRequest
* @param paramNames
* the parameters specified in the original IGeometryRequest
* @return the constructed DefaultGeometryData
*/
protected DefaultGeometryData buildGeometryData(DataTime time, Level level,
Geometry geometry, String locationName,
Map<String, Object> attributes, String[] paramNames) {
return this.buildGeometryData(time, level, geometry, locationName,
attributes, Integer.MAX_VALUE, null, paramNames);
}
/**
* Constructs a DefaultGeometryData based on the provided information
*
* @param time
* the provided DataTime
* @param level
* the provided Level
* @param geometry
* the provided Geometry
* @param locationName
* the provided Location
* @param attributes
* identifiers specified in the original IGeometryRequest
* @param dataIndex
* a numerical index indicating where user-specified parameters
* may start in the provided row of raw data
* @param data
* a row of row data retrieved from the database; all
* user-specified parameters are extracted from it and added to
* the DefaultGeometryData using the addData method
* @param paramNames
* the parameters specified in the original IGeometryRequest
* @return the constructed DefaultGeometryData
*/
protected DefaultGeometryData buildGeometryData(DataTime time, Level level,
Geometry geometry, String locationName,
Map<String, Object> attributes, int dataIndex, Object[] data,
String[] paramNames) {
DefaultGeometryData geometryData = new DefaultGeometryData();
geometryData.setDataTime(time);
geometryData.setLevel(level);
geometryData.setGeometry(geometry);
geometryData.setLocationName(locationName);
geometryData.setAttributes(attributes);
if ((data == null) == false && data.length > dataIndex) {
for (int i = dataIndex; i < data.length; i++) {
String name = paramNames[i - dataIndex];
geometryData.addData(name, data[i]);
}
}
return geometryData;
}
}

View file

@ -0,0 +1,174 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataaccess.impl;
import com.raytheon.uf.common.dataaccess.exception.TimeAgnosticDataException;
import com.raytheon.uf.common.dataaccess.geom.IGeometryData;
import com.raytheon.uf.common.dataaccess.geom.IGeometryRequest;
import com.raytheon.uf.common.time.BinOffset;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
/**
* Abstracts the retrieval of time agnostic geometry data by building on and/or
* extending AbstractGeometryDatabaseFactory.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 29, 2013 bkowal Initial creation
*
* </pre>
*
* @author bkowal
* @version 1.0
*/
public abstract class AbstractGeometryTimeAgnosticDatabaseFactory extends
AbstractGeometryDatabaseFactory {
/**
* Constructor
*
* @param databaseName
* the name of the database to execute queries against
* @param requiredIdentifiers
* the identifiers that need to be included in the request
* (ifdef)
*/
public AbstractGeometryTimeAgnosticDatabaseFactory(String databaseName,
String[] requiredIdentifiers) {
super(databaseName, requiredIdentifiers);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getAvailableTimes(com.
* raytheon.uf.common.dataaccess.IDataRequest)
*/
@Override
public DataTime[] getAvailableTimes(IGeometryRequest request)
throws TimeAgnosticDataException {
throw new TimeAgnosticDataException(this.buildExceptionMessage(request));
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getData(com.raytheon.uf
* .common.dataaccess.IDataRequest, com.raytheon.uf.common.time.DataTime[])
*/
@Override
public IGeometryData[] getData(IGeometryRequest request, DataTime... times) {
return this.getData(request);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getData(com.raytheon.uf
* .common.dataaccess.IDataRequest, com.raytheon.uf.common.time.TimeRange)
*/
@Override
public IGeometryData[] getData(IGeometryRequest request, TimeRange timeRange) {
return this.getData(request);
}
/**
* Retrieves data in a time agnostic way.
*
* @param request the original request that we are processing
* @return an array of IGeometryData
*/
protected IGeometryData[] getData(IGeometryRequest request) {
return super.executeDataQuery(this.assembleGetData(request), request);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getAvailableTimes(com.
* raytheon.uf.common.dataaccess.IDataRequest,
* com.raytheon.uf.common.time.BinOffset)
*/
@Override
public DataTime[] getAvailableTimes(IGeometryRequest request,
BinOffset binOffset) throws TimeAgnosticDataException {
throw new TimeAgnosticDataException(this.buildExceptionMessage(request));
}
/**
* Constructs the message that will be included in the TimeAgnosticException
*
* @param request the original request that we are processing
* @return the constructed exception message
*/
private String buildExceptionMessage(IGeometryRequest request) {
StringBuilder stringBuilder = new StringBuilder(
"This operation is unsupported for data type: ");
stringBuilder.append(request.getDatatype());
return stringBuilder.toString();
}
/**
* Builds a time agnostic version of the query that will be used to retrieve data from the database.
*
* @param request the original request that we are processing
* @return the query
*/
protected abstract String assembleGetData(IGeometryRequest request);
/**
* The following methods are no longer applicable to us.
*
* Should we be throwing an exception
*/
@Override
protected String assembleGetTimes(IGeometryRequest request) {
return null;
}
@Override
protected String assembleGetTimes(IGeometryRequest request,
BinOffset binOffset) {
return null;
}
@Override
protected String assembleGetData(IGeometryRequest request,
DataTime... times) {
return null;
}
@Override
protected String assembleGetData(IGeometryRequest request,
TimeRange timeRange) {
return null;
}
}

View file

@ -0,0 +1,136 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataaccess.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.dataaccess.exception.DataRetrievalException;
import com.raytheon.uf.common.dataquery.db.QueryResult;
import com.raytheon.uf.common.dataquery.db.QueryResultRow;
import com.raytheon.uf.common.dataquery.requests.QlServerRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.message.response.AbstractResponseMessage;
import com.raytheon.uf.common.message.response.ResponseMessageError;
import com.raytheon.uf.common.message.response.ResponseMessageGeneric;
import com.raytheon.uf.common.serialization.comm.RequestRouter;
/**
* A utility used to run queries against a specified database.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 29, 2013 bkowal Initial creation
*
* </pre>
*
* @author bkowal
* @version 1.0
*/
public class DatabaseQueryUtil {
/*
* should this enum actually be provided by the QlServerRequest?
*/
public static enum QUERY_MODE {
MODE_SQLQUERY("sqlquery"), MODE_HQLQUERY("hqlquery"), MODE_SQL_STATEMENT(
"sqlstatement"), MODE_HSQL_STATEMENT("hqlstatement"), MODE_SAVE_OR_UPDATE(
"saveOrUpdateObject");
private String modeText;
QUERY_MODE(String modeText) {
this.modeText = modeText;
}
protected String getModeText() {
return this.modeText;
}
}
private static final String CONSTRAINT_QUERY = "query";
private static final String CONSTRAINT_DATABASE = "database";
private static final String CONSTRAINT_MODE = "mode";
/**
* Constructor
*/
private DatabaseQueryUtil() {
}
/**
* Executes the provided query against the specified database and returns the results of the query execution.
*
* @param mode the request mode
* @param query the query to execute
* @param database the database to execute the query against
* @param dataType the Data Access Framework factory data type
* @return the information retrieved from the database
*/
public static List<Object[]> executeDatabaseQuery(QUERY_MODE mode,
String query, String database, String dataType) {
Map<String, RequestConstraint> requestConstraintMap = new HashMap<String, RequestConstraint>();
requestConstraintMap
.put(CONSTRAINT_QUERY, new RequestConstraint(query));
requestConstraintMap.put(CONSTRAINT_DATABASE, new RequestConstraint(
database));
requestConstraintMap.put(CONSTRAINT_MODE,
new RequestConstraint(mode.getModeText()));
QlServerRequest serverRequest = new QlServerRequest(
requestConstraintMap);
final String errorMessage = "Error retrieving " + dataType + " data";
// Execute the request.
AbstractResponseMessage response = null;
try {
response = (AbstractResponseMessage) RequestRouter
.route(serverRequest);
} catch (Exception e) {
throw new DataRetrievalException(errorMessage, e);
}
QueryResult result = null;
if (response instanceof ResponseMessageError) {
throw new DataRetrievalException(errorMessage + ": "
+ response.toString());
} else if (response instanceof ResponseMessageGeneric) {
result = (QueryResult) ((ResponseMessageGeneric) response)
.getContents();
} else {
throw new DataRetrievalException(
"Unable to process response of type" + response.getClass());
}
List<Object[]> unmappedResults = new ArrayList<Object[]>();
for (QueryResultRow row : result.getRows()) {
unmappedResults.add(row.getColumnValues());
}
return unmappedResults;
}
}

View file

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

View file

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

View file

@ -0,0 +1,8 @@
#Mon Jan 28 15:41:42 CST 2013
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,16 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Common Maps Dataplugin
Bundle-SymbolicName: com.raytheon.uf.common.dataplugin.maps
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: org.apache.commons.lang;bundle-version="2.3.0",
com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174",
org.geotools;bundle-version="2.6.4",
com.raytheon.uf.common.dataaccess;bundle-version="1.0.0",
com.raytheon.uf.common.dataquery;bundle-version="1.0.0",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174",
com.raytheon.uf.common.message;bundle-version="1.12.1174"
Export-Package: com.raytheon.uf.common.dataplugin.maps.dataaccess.util

View file

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

View file

@ -0,0 +1,18 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="mapsPluginName" class="java.lang.String">
<constructor-arg type="java.lang.String" value="maps" />
</bean>
<bean id="mapsDataFactory" class="com.raytheon.uf.common.dataplugin.maps.dataaccess.MapsGeometryFactory" />
<bean factory-bean="dataAccessRegistry" factory-method="register"
depends-on="mapsPluginName, mapsDataFactory">
<constructor-arg ref="mapsPluginName"/>
<constructor-arg value="com.raytheon.uf.common.dataaccess.geom.IGeometryRequest"/>
<constructor-arg ref="mapsDataFactory"/>
</bean>
</beans>

View file

@ -0,0 +1,128 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.maps.dataaccess;
import java.util.Map;
import com.vividsolutions.jts.geom.Geometry;
import com.raytheon.uf.common.dataaccess.exception.DataRetrievalException;
import com.raytheon.uf.common.dataaccess.geom.IGeometryData;
import com.raytheon.uf.common.dataaccess.geom.IGeometryRequest;
import com.raytheon.uf.common.dataaccess.impl.AbstractGeometryTimeAgnosticDatabaseFactory;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKBReader;
/**
* A data factory for retrieving data from the maps database. Currently, the
* name of the table to retrieve data from and the name of the geometry field of
* interest are required identifiers.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 28, 2013 bkowal Initial creation
*
* </pre>
*
* @author bkowal
* @version 1.0
*/
public class MapsGeometryFactory extends
AbstractGeometryTimeAgnosticDatabaseFactory {
private static final String[] REQUIRED_IDENTIFIERS = new String[] {
MapsQueryAssembler.REQUIRED_IDENTIFIERS.IDENTIFIER_TABLE,
MapsQueryAssembler.REQUIRED_IDENTIFIERS.IDENTIFIER_GEOM_FIELD };
private static final String MAPS_DATABASE = "maps";
private static final ThreadLocal<WKBReader> wkbReaderWrapper = new ThreadLocal<WKBReader>() {
@Override
protected WKBReader initialValue() {
return new WKBReader();
}
};
/**
* Constructor
*/
public MapsGeometryFactory() {
super(MAPS_DATABASE, REQUIRED_IDENTIFIERS);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.impl.AbstractGeometryDatabaseFactory
* #makeGeometry(java.lang.Object[], java.lang.String[], java.util.Map)
*/
@Override
protected IGeometryData makeGeometry(Object[] data, String[] paramNames,
Map<String, Object> attrs) {
// order selected geom field, location, and other parameters
// build the geometry
Geometry geometry = null;
Object object = data[0];
if ((object instanceof byte[]) == false) {
throw new DataRetrievalException(
"Retrieved Geometry was not the expected type; was expecting byte[], received: "
+ object.getClass().getName());
}
try {
geometry = (wkbReaderWrapper.get()).read((byte[]) object);
} catch (ParseException e) {
throw new DataRetrievalException("Failed to parse the geometry.", e);
}
String location = (String) data[1];
return super.buildGeometryData(null, null, geometry, location, attrs,
2, data, paramNames);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.dataaccess.impl.
* AbstractGeometryTimeAgnosticDatabaseFactory
* #assembleGetData(com.raytheon.uf.common.dataaccess.geom.IGeometryRequest)
*/
@Override
protected String assembleGetData(IGeometryRequest request) {
return MapsQueryAssembler.assembleGetData(request);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.impl.AbstractGeometryDatabaseFactory
* #assembleGetAvailableLocationNames
* (com.raytheon.uf.common.dataaccess.geom.IGeometryRequest)
*/
@Override
protected String assembleGetAvailableLocationNames(IGeometryRequest request) {
return MapsQueryAssembler.assembleGetAvailableLocationNames(request);
}
}

View file

@ -0,0 +1,275 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.maps.dataaccess;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Iterator;
import org.apache.commons.lang.BooleanUtils;
import com.raytheon.uf.common.dataaccess.geom.IGeometryRequest;
import com.raytheon.uf.common.dataplugin.maps.dataaccess.util.MapsQueryUtil;
import com.vividsolutions.jts.geom.Envelope;
/**
* Constructs a query to retrieve information from the maps database based on
* the supplied information.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 28, 2013 bkowal Initial creation
*
* </pre>
*
* @author bkowal
* @version 1.0
*/
public class MapsQueryAssembler {
public static final class REQUIRED_IDENTIFIERS {
/*
* The table to retrieve the data from.
*/
public static final String IDENTIFIER_TABLE = "table";
/*
* The first field that will be selected - the geometry that we would
* like to retrieve. We will verify that it is not already in the column
* list.
*/
public static final String IDENTIFIER_GEOM_FIELD = "geomField";
}
/*
* Other common identifiers we may encounter.
*/
public static final class IDENTIFIERS {
/*
* Used to specify if the factory should look for information that is
* within the specified locations or information that excludes the
* specified locations. If this identifier is not specified, the default
* will be to look for information within the specified location.
*/
public static final String IDENTIFIER_IN_LOCATION = "inLocation";
/*
* The name of the location field, defaults to "name".
*/
public static final String IDENTIFIER_LOCATION_FIELD = "locationField";
}
private static final List<String> RESERVED_IDENTIFIERS = Arrays.asList(
REQUIRED_IDENTIFIERS.IDENTIFIER_TABLE,
REQUIRED_IDENTIFIERS.IDENTIFIER_GEOM_FIELD,
IDENTIFIERS.IDENTIFIER_IN_LOCATION,
IDENTIFIERS.IDENTIFIER_LOCATION_FIELD);
private static final String DEFAULT_LOCATION_FIELD = "name";
/**
* Constructor
*/
private MapsQueryAssembler() {
}
/**
* Retrieves a named identifier from the request
*
* @param request
* the original request that we are processing
* @param identifierName
* the name of the identifier to extract
* @return the identifier
*/
public static String extractIdentifier(IGeometryRequest request,
String identifierName) {
return request.getIdentifiers().get(identifierName).toString();
}
/**
* Retrieves the table identifier
*
* @param request
* the original request that we are processing
* @return the table identifier
*/
public static String extractTable(IGeometryRequest request) {
return extractIdentifier(request, REQUIRED_IDENTIFIERS.IDENTIFIER_TABLE);
}
/**
* Retrieves the geometry field identifier
*
* @param request
* the original request that we are processing
* @return the geometry identifier
*/
public static String extractGeomField(IGeometryRequest request) {
return extractIdentifier(request,
REQUIRED_IDENTIFIERS.IDENTIFIER_GEOM_FIELD);
}
/**
* Constructs a query to retrieve data from the maps database
*
* @param request
* the original request that we are processing
* @return the query
*/
public static String assembleGetData(IGeometryRequest request) {
return assembleQuery(request, Boolean.FALSE);
}
/**
* Constructs a query to retrieve locations from the database
*
* @param request
* the original request that we are processing
* @return the query
*/
public static String assembleGetAvailableLocationNames(
IGeometryRequest request) {
return assembleQuery(request, Boolean.TRUE);
}
/**
* Constructs a query to retrieve information from the database
*
* @param request
* the original request that we are processing
* @param locationQuery
* indicates whether or not this query will be used to retrieve
* location information
* @return the query
*/
private static String assembleQuery(IGeometryRequest request,
boolean locationQuery) {
Envelope envelope = request.getEnvelope();
String table = extractTable(request);
String geomField = extractGeomField(request);
String locationField = DEFAULT_LOCATION_FIELD;
if (request.getIdentifiers().containsKey(
IDENTIFIERS.IDENTIFIER_LOCATION_FIELD)) {
locationField = request.getIdentifiers()
.get(IDENTIFIERS.IDENTIFIER_LOCATION_FIELD).toString();
}
List<String> columns = new ArrayList<String>();
if (locationQuery == false) {
// the first column will always be the geometry.
columns.add("AsBinary(" + geomField + ")");
}
// the second column will always be the location name
columns.add(locationField);
if (locationQuery == false) {
// add any additional database columns the user has specified as
// parameters
// for additional information, refer to: http://tinyurl.com/arnayco
for (String parameter : request.getParameters()) {
columns.add(parameter);
}
}
List<String> constraints = new ArrayList<String>();
// add location constraint (ifdef)
if ((request.getLocationNames() == null) == false
&& request.getLocationNames().length > 0) {
boolean inLocation = Boolean.TRUE;
if (request.getIdentifiers().containsKey(
IDENTIFIERS.IDENTIFIER_IN_LOCATION)) {
inLocation = BooleanUtils.toBoolean(request.getIdentifiers()
.get(IDENTIFIERS.IDENTIFIER_IN_LOCATION).toString());
}
constraints.add(buildInConstraint(request.getLocationNames(),
locationField, inLocation));
}
// add remaining identifiers to constraints (ifdef)
Iterator<String> identifiersIterator = request.getIdentifiers()
.keySet().iterator();
while (identifiersIterator.hasNext()) {
String identifierKey = identifiersIterator.next();
if (RESERVED_IDENTIFIERS.contains(identifierKey)) {
continue;
}
constraints.add(buildEqualsConstraint(identifierKey, request
.getIdentifiers().get(identifierKey).toString()));
}
return MapsQueryUtil.assembleMapsTableQuery(envelope, columns,
constraints, table, geomField);
}
/**
* Constructs an equality constraint
*
* @param key
* the operand
* @param value
* the expected result
* @return the equality constraint
*/
private static String buildEqualsConstraint(String key, String value) {
StringBuilder stringBuilder = new StringBuilder(key);
stringBuilder.append(" = '");
stringBuilder.append(value);
stringBuilder.append("'");
return stringBuilder.toString();
}
/**
* Constructs an IN or NOT IN constraint
*
* @param elements
* a list of elements to include in the constraint
* @param fieldName
* the database column name
* @param in
* indicates whether this is an IN constraint or a NOT IN
* constraint
* @return the constraint
*/
private static String buildInConstraint(Object[] elements,
String fieldName, boolean in) {
StringBuilder stringBuilder = new StringBuilder(fieldName);
if (in) {
stringBuilder.append(" IN ('");
} else {
stringBuilder.append(" NOT IN ('");
}
// add the 0th location
stringBuilder.append(elements[0]);
stringBuilder.append("'");
for (int i = 1; i < elements.length; i++) {
stringBuilder.append(", '");
stringBuilder.append(elements[i]);
stringBuilder.append("'");
}
stringBuilder.append(")");
return stringBuilder.toString();
}
}

View file

@ -0,0 +1,119 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.maps.dataaccess.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.vividsolutions.jts.geom.Envelope;
/**
* A utility to construct a query that will be used to retrieve information from
* the maps table based on the supplied information.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 28, 2013 bkowal Initial creation
*
* </pre>
*
* @author bkowal
* @version 1.0
*/
public class MapsQueryUtil {
/**
*
*/
private MapsQueryUtil() {
}
/**
* Builds a query that can be used to query the maps table based on the
* provided information.
*
* @param env
* used to limit the selected information to a certain
* geographical area
* @param columns
* the list of columns that will be included in the SELECT
* statement
* @param additionalConstraints
* the list of constraints that will become part of the AND
* statement
* @param table
* the table to select data from
* @param geomField
* the name of the geometry field of interest
* @return the query
*/
public static String assembleMapsTableQuery(Envelope env,
List<String> columns, List<String> additionalConstraints,
String table, String geomField) {
// 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 query.toString();
}
}

View file

@ -20,28 +20,13 @@
package com.raytheon.uf.common.hydro.dataaccess;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.dataaccess.exception.DataRetrievalException;
import com.raytheon.uf.common.dataaccess.exception.TimeAgnosticDataException;
import com.raytheon.uf.common.dataaccess.geom.IGeometryData;
import com.raytheon.uf.common.dataaccess.geom.IGeometryDataFactory;
import com.raytheon.uf.common.dataaccess.geom.IGeometryRequest;
import com.raytheon.uf.common.dataaccess.impl.AbstractDataFactory;
import com.raytheon.uf.common.dataaccess.impl.DefaultGeometryData;
import com.raytheon.uf.common.dataaccess.impl.AbstractGeometryDatabaseFactory;
import com.raytheon.uf.common.dataaccess.impl.FactoryUtil;
import com.raytheon.uf.common.dataquery.db.QueryResult;
import com.raytheon.uf.common.dataquery.db.QueryResultRow;
import com.raytheon.uf.common.dataquery.requests.QlServerRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.message.response.AbstractResponseMessage;
import com.raytheon.uf.common.message.response.ResponseMessageError;
import com.raytheon.uf.common.message.response.ResponseMessageGeneric;
import com.raytheon.uf.common.serialization.comm.RequestRouter;
import com.raytheon.uf.common.time.BinOffset;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
@ -61,6 +46,7 @@ import com.vividsolutions.jts.geom.GeometryFactory;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 13, 2012 njensen Initial creation
* Jan 30, 2012 1551 bkowal Refactored
*
* </pre>
*
@ -68,8 +54,7 @@ import com.vividsolutions.jts.geom.GeometryFactory;
* @version 1.0
*/
public class HydroGeometryFactory extends AbstractDataFactory implements
IGeometryDataFactory {
public class HydroGeometryFactory extends AbstractGeometryDatabaseFactory {
// TODO always require at least one PE
// TODO possibly take care of it for them and add value
@ -82,26 +67,26 @@ public class HydroGeometryFactory extends AbstractDataFactory implements
private GeometryFactory gisFactory = new GeometryFactory();
private static final String IHFS_DATABASE = "ihfs";
public HydroGeometryFactory() {
super(IHFS_DATABASE, REQUIRED);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getAvailableTimes(com.
* raytheon.uf.common.dataaccess.IDataRequest)
* com.raytheon.uf.common.dataaccess.impl.AbstractGeometryDatabaseFactory
* #getAvailableTimes
* (com.raytheon.uf.common.dataaccess.geom.IGeometryRequest,
* com.raytheon.uf.common.time.BinOffset)
*/
/*
* For now this will remain as a method override; maybe this is the standard
* way to retrieve the times based on a BinOffset when the database is
* accessed directly?
*/
@Override
public DataTime[] getAvailableTimes(IGeometryRequest request)
throws TimeAgnosticDataException {
validateRequest(request);
String query = HydroQueryAssembler.assembleGetTimes(request);
List<Object[]> result = sendServerRequest(query);
DataTime[] dts = new DataTime[result.size()];
for (int i = 0; i < dts.length; i++) {
dts[i] = new DataTime((Timestamp) result.get(i)[0]);
}
return dts;
}
@Override
public DataTime[] getAvailableTimes(IGeometryRequest request,
BinOffset binOffset) throws TimeAgnosticDataException {
@ -112,140 +97,92 @@ public class HydroGeometryFactory extends AbstractDataFactory implements
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getData(com.raytheon.uf
* .common.dataaccess.IDataRequest, com.raytheon.uf.common.time.DataTime[])
* com.raytheon.uf.common.dataaccess.impl.AbstractGeometryDatabaseFactory
* #makeGeometry(java.lang.Object[], java.lang.String[], java.util.Map)
*/
@Override
public IGeometryData[] getData(IGeometryRequest request, DataTime... times) {
validateRequest(request);
String query = HydroQueryAssembler.assembleGetData(request, times);
List<Object[]> result = sendServerRequest(query);
return makeGeometries(result, request.getParameters(),
request.getIdentifiers());
protected IGeometryData makeGeometry(Object[] data, String[] paramNames,
Map<String, Object> attrs) {
// order is lid, producttime, lat, lon, other params
String lid = (String) data[0];
Timestamp date = (Timestamp) data[1];
double lat = (Double) data[2];
double lon = (Double) data[3];
// intentionally setting level as null until hydrologists determine
// something better
return super.buildGeometryData(new DataTime(date), null,
gisFactory.createPoint(new Coordinate(lon, lat)), lid, attrs,
4, data, paramNames);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.IDataFactory#getData(com.raytheon.uf
* .common.dataaccess.IDataRequest, com.raytheon.uf.common.time.TimeRange)
* com.raytheon.uf.common.dataaccess.impl.AbstractGeometryDatabaseFactory
* #assembleGetTimes
* (com.raytheon.uf.common.dataaccess.geom.IGeometryRequest)
*/
@Override
public IGeometryData[] getData(IGeometryRequest request, TimeRange timeRange) {
validateRequest(request);
String query = HydroQueryAssembler.assembleGetData(request, timeRange);
List<Object[]> result = sendServerRequest(query);
return makeGeometries(result, request.getParameters(),
request.getIdentifiers());
protected String assembleGetTimes(IGeometryRequest request) {
return HydroQueryAssembler.assembleGetTimes(request);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.dataaccess.geom.IGeometryDataFactory#
* getAvailableLocationNames
* @see
* com.raytheon.uf.common.dataaccess.impl.AbstractGeometryDatabaseFactory
* #assembleGetTimes
* (com.raytheon.uf.common.dataaccess.geom.IGeometryRequest,
* com.raytheon.uf.common.time.BinOffset)
*/
@Override
protected String assembleGetTimes(IGeometryRequest request,
BinOffset binOffset) {
return null;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.impl.AbstractGeometryDatabaseFactory
* #assembleGetData(com.raytheon.uf.common.dataaccess.geom.IGeometryRequest,
* com.raytheon.uf.common.time.DataTime[])
*/
@Override
protected String assembleGetData(IGeometryRequest request,
DataTime... times) {
return HydroQueryAssembler.assembleGetData(request, times);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.impl.AbstractGeometryDatabaseFactory
* #assembleGetData(com.raytheon.uf.common.dataaccess.geom.IGeometryRequest,
* com.raytheon.uf.common.time.TimeRange)
*/
@Override
protected String assembleGetData(IGeometryRequest request,
TimeRange timeRange) {
return HydroQueryAssembler.assembleGetData(request, timeRange);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.dataaccess.impl.AbstractGeometryDatabaseFactory
* #assembleGetAvailableLocationNames
* (com.raytheon.uf.common.dataaccess.geom.IGeometryRequest)
*/
@Override
public String[] getAvailableLocationNames(IGeometryRequest request) {
String query = "select lid from location;";
List<Object[]> results = sendServerRequest(query);
int size = results.size();
String[] locations = new String[size];
for (int i = 0; i < size; i++) {
locations[i] = (String) results.get(i)[0];
}
return locations;
protected String assembleGetAvailableLocationNames(IGeometryRequest request) {
return "select lid from location;";
}
@Override
public String[] getRequiredIdentifiers() {
return REQUIRED;
}
/**
* Sends the query to the server and returns the results
*
* @param query
* the query to run
* @return the results of the query
*/
private List<Object[]> sendServerRequest(String query) {
Map<String, RequestConstraint> rcMap = new HashMap<String, RequestConstraint>();
rcMap.put("query", new RequestConstraint(query));
rcMap.put("database", new RequestConstraint("ihfs"));
rcMap.put("mode", new RequestConstraint("sqlquery"));
QlServerRequest qsr = new QlServerRequest(rcMap);
AbstractResponseMessage response = null;
try {
response = (AbstractResponseMessage) RequestRouter.route(qsr);
} catch (Exception e) {
throw new DataRetrievalException("Error retrieving IHFS data", e);
}
QueryResult result = null;
if (response instanceof ResponseMessageError) {
throw new DataRetrievalException("Error retrieving IHFS data: "
+ response.toString());
} else if (response instanceof ResponseMessageGeneric) {
result = (QueryResult) ((ResponseMessageGeneric) response)
.getContents();
} else {
throw new DataRetrievalException(
"Unable to process response of type" + response.getClass());
}
List<Object[]> unmappedResults = new ArrayList<Object[]>();
for (QueryResultRow row : result.getRows()) {
unmappedResults.add(row.getColumnValues());
}
return unmappedResults;
}
/**
* Builds the data objects that will be returned by calls to getData() on
* the factory
*
* @param serverResult
* the results from the query run on the server
* @param paramNames
* the names of the parameters that were requested
* @param identifiers
* the identifiers from the data request
* @return the IGeometryData based on the results of the query
*/
private IGeometryData[] makeGeometries(List<Object[]> serverResult,
String[] paramNames, Map<String, Object> identifiers) {
List<IGeometryData> resultList = new ArrayList<IGeometryData>();
Map<String, Object> attrs = Collections.unmodifiableMap(identifiers);
// loop over each db row
for (Object[] row : serverResult) {
DefaultGeometryData geom = new DefaultGeometryData();
// order is lid, producttime, lat, lon, other params
String lid = (String) row[0];
Timestamp date = (Timestamp) row[1];
double lat = (Double) row[2];
double lon = (Double) row[3];
if (row.length > 4) {
for (int i = 4; i < row.length; i++) {
String name = paramNames[i - 4];
geom.addData(name, row[i]);
}
}
geom.setLocationName(lid);
geom.setDataTime(new DataTime(date));
// intentionally setting level as null until hydrologists determine
// something better
geom.setLevel(null);
geom.setGeometry(gisFactory.createPoint(new Coordinate(lon, lat)));
geom.setAttributes(attrs);
resultList.add(geom);
}
return resultList.toArray(new DefaultGeometryData[0]);
}
}
}

View file

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