Issue #1409 Initial implementation of hydro data access
Change-Id: I309694f9477384446658520794e19ca9493473fb Former-commit-id:c236b4e1ad
[formerly817717fe0a
] [formerlyc236b4e1ad
[formerly817717fe0a
] [formerly85658e7e1d
[formerly ae7ac8a8bfc51d1c7dc3493c8fc036a87772f323]]] Former-commit-id:85658e7e1d
Former-commit-id:94b9d10c81
[formerly3c2865bbd7
] Former-commit-id:13dca3b784
This commit is contained in:
parent
4a539b10ce
commit
1aa8d304df
10 changed files with 697 additions and 26 deletions
|
@ -312,4 +312,11 @@
|
|||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.raytheon.uf.common.dataaccess"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
||||
|
|
|
@ -85,6 +85,7 @@ public class DataFactoryRegistry {
|
|||
*/
|
||||
public IDataFactory<?, ?> register(String datatype,
|
||||
Class<IDataRequest<?>> requestType, IDataFactory<?, ?> factory) {
|
||||
datatype = datatype.toLowerCase();
|
||||
Map<Class<IDataRequest<?>>, IDataFactory<?, ?>> requestTypeMap = datatypeMap
|
||||
.get(datatype);
|
||||
if (requestTypeMap == null) {
|
||||
|
@ -109,7 +110,7 @@ public class DataFactoryRegistry {
|
|||
@SuppressWarnings("unchecked")
|
||||
public <R extends IDataRequest<D>, D extends IData> IDataFactory<R, D> getFactory(
|
||||
R request) {
|
||||
String datatype = request.getDatatype();
|
||||
String datatype = request.getDatatype().toLowerCase();
|
||||
if (datatype != null) {
|
||||
Map<Class<IDataRequest<?>>, IDataFactory<?, ?>> requestTypeMap = datatypeMap
|
||||
.get(datatype);
|
||||
|
|
|
@ -24,7 +24,6 @@ import javax.measure.unit.Unit;
|
|||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
|
||||
import com.raytheon.uf.common.dataaccess.IData;
|
||||
import com.raytheon.uf.common.dataplugin.level.Level;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.DataDestination;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.data.UnitConvertingDataDestination;
|
||||
|
||||
|
@ -55,13 +54,6 @@ public interface IGridData extends IData {
|
|||
*/
|
||||
public String getParameter();
|
||||
|
||||
/**
|
||||
* Gets the level of the data
|
||||
*
|
||||
* @return the level of the data
|
||||
*/
|
||||
public Level getLevel();
|
||||
|
||||
/**
|
||||
* Gets the GridGeometry of the data
|
||||
*
|
||||
|
|
|
@ -4,11 +4,10 @@ Bundle-Name: Hydrocommon Plug-in
|
|||
Bundle-SymbolicName: com.raytheon.uf.common.hydro
|
||||
Bundle-Version: 1.12.1174.qualifier
|
||||
Bundle-Vendor: RAYTHEON
|
||||
Require-Bundle: org.eclipse.ui,
|
||||
org.eclipse.core.runtime,
|
||||
org.geotools;bundle-version="2.5.2",
|
||||
Require-Bundle: org.geotools;bundle-version="2.5.2",
|
||||
com.raytheon.uf.common.geospatial;bundle-version="1.11.9",
|
||||
com.raytheon.edex.common;bundle-version="1.11.9"
|
||||
com.raytheon.edex.common;bundle-version="1.11.9",
|
||||
com.raytheon.uf.common.dataaccess
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: com.raytheon.uf.common.hydro.service,
|
||||
|
@ -16,6 +15,7 @@ Export-Package: com.raytheon.uf.common.hydro.service,
|
|||
Import-Package: com.raytheon.uf.common.localization,
|
||||
com.raytheon.uf.common.menus,
|
||||
com.raytheon.uf.common.menus.xml,
|
||||
com.raytheon.uf.common.message.response,
|
||||
com.raytheon.uf.common.ohd,
|
||||
com.raytheon.uf.common.serialization.comm,
|
||||
org.apache.commons.logging
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
.,\
|
||||
res/
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
<project basedir="." default="deploy" name="com.raytheon.uf.common.hydro">
|
||||
|
||||
<available file="../build.edex" property="build.dir.location" value="../build.edex"/>
|
||||
<available file="../../../../../build.edex" property="build.dir.location" value="../../../../../build.edex"/>
|
||||
|
||||
<import file="${build.dir.location}/basebuilds/component_deploy_base.xml" />
|
||||
|
||||
</project>
|
|
@ -0,0 +1,13 @@
|
|||
<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="hydroDataFactory" class="com.raytheon.uf.common.hydro.dataaccess.HydroGeometryFactory" />
|
||||
|
||||
<bean factory-bean="dataAccessRegistry" factory-method="register">
|
||||
<constructor-arg value="ihfsData"/>
|
||||
<constructor-arg value="com.raytheon.uf.common.dataaccess.geom.IGeometryRequest"/>
|
||||
<constructor-arg ref="hydroDataFactory"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,251 @@
|
|||
/**
|
||||
* 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.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.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;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||
|
||||
/**
|
||||
* A data factory for getting data from the IHFS database. Requires that a
|
||||
* request have a table identifier that corresponds to the table it should
|
||||
* retrieve data from. Only works against tables that follow the SHEF PEDTSEP
|
||||
* pattern.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Nov 13, 2012 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class HydroGeometryFactory extends AbstractDataFactory implements
|
||||
IGeometryDataFactory {
|
||||
|
||||
// TODO always require at least one PE
|
||||
// TODO possibly take care of it for them and add value
|
||||
// TODO potentially limit big requests so that if too big of a result set,
|
||||
// throw error to
|
||||
// let the user know they need to reduce amount of data they request
|
||||
// test out on live data how slow it gets to determine max number
|
||||
// TODO add support for envelopes bounding the request
|
||||
private static final String[] REQUIRED = { HydroQueryAssembler.TABLE };
|
||||
|
||||
private GeometryFactory gisFactory = new GeometryFactory();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.common.dataaccess.IDataFactory#getAvailableTimes(com.
|
||||
* raytheon.uf.common.dataaccess.IDataRequest)
|
||||
*/
|
||||
@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 {
|
||||
return FactoryUtil.getAvailableTimes(this, request, binOffset);
|
||||
}
|
||||
|
||||
/*
|
||||
* (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) {
|
||||
validateRequest(request);
|
||||
String query = HydroQueryAssembler.assembleGetData(request, times);
|
||||
List<Object[]> result = sendServerRequest(query);
|
||||
return makeGeometries(result, request.getParameters(),
|
||||
request.getIdentifiers());
|
||||
}
|
||||
|
||||
/*
|
||||
* (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) {
|
||||
validateRequest(request);
|
||||
String query = HydroQueryAssembler.assembleGetData(request, timeRange);
|
||||
List<Object[]> result = sendServerRequest(query);
|
||||
return makeGeometries(result, request.getParameters(),
|
||||
request.getIdentifiers());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.common.dataaccess.geom.IGeometryDataFactory#
|
||||
* getAvailableLocationNames
|
||||
* (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;
|
||||
}
|
||||
|
||||
@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]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,407 @@
|
|||
/**
|
||||
* 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.hydro.dataaccess;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.raytheon.uf.common.dataaccess.exception.IncompatibleRequestException;
|
||||
import com.raytheon.uf.common.dataaccess.geom.IGeometryRequest;
|
||||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.common.time.TimeRange;
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
|
||||
/**
|
||||
* Utilities for assembling a SQL query based on an IGeometryRequest
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Nov 15, 2012 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class HydroQueryAssembler {
|
||||
|
||||
protected static final String TABLE = "table";
|
||||
|
||||
private static final String TIME_COL = "producttime";
|
||||
|
||||
private static final String LID_COL = "lid";
|
||||
|
||||
/**
|
||||
* Don't allow instantiation
|
||||
*/
|
||||
private HydroQueryAssembler() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a SQL query for data
|
||||
*
|
||||
* @param request
|
||||
* the request for data
|
||||
* @param times
|
||||
* the times of data to request
|
||||
* @return the SQL query
|
||||
*/
|
||||
public static String assembleGetData(IGeometryRequest request,
|
||||
DataTime[] times) {
|
||||
return assembleGetData(request, buildTimeConstraint(times)).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a SQL query for data
|
||||
*
|
||||
* @param request
|
||||
* the request for data
|
||||
* @param timeRange
|
||||
* the time range of data to request
|
||||
* @return the SQL query
|
||||
*/
|
||||
public static String assembleGetData(IGeometryRequest request,
|
||||
TimeRange timeRange) {
|
||||
return assembleGetData(request, buildTimeConstraint(timeRange))
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a SQL string to query corresponding to the request.
|
||||
*
|
||||
* @param request
|
||||
* the request to transform to SQL
|
||||
* @param timeConstraint
|
||||
* a time constraint to apply to the where clause, if applicable.
|
||||
* May be null.
|
||||
* @return a SQL string that corresponds to the request
|
||||
*/
|
||||
private static CharSequence assembleGetData(IGeometryRequest request,
|
||||
CharSequence timeConstraint) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// this method assembles a sql string such as:
|
||||
// select d.lid, d.productttime, d.value, l.lat, l.lon from height d,
|
||||
// location l where d.lid = 'ABRN1' and d.lid = l.lid;
|
||||
// It is requesting the lat/lons of the location every time which
|
||||
// could potentially be improved in efficiency.
|
||||
|
||||
// select
|
||||
sb.append(buildSelectParams(request));
|
||||
|
||||
// from table name
|
||||
sb.append(buildFromWithLocation(request));
|
||||
|
||||
// where
|
||||
CharSequence where = buildWhere(request, timeConstraint);
|
||||
if (where.length() > 0) {
|
||||
sb.append(where);
|
||||
sb.append(" and d.lid = l.lid");
|
||||
} else {
|
||||
sb.append("where d.lid = l.lid");
|
||||
}
|
||||
sb.append(buildOrderByTime());
|
||||
sb.append(";");
|
||||
|
||||
// TODO do i need a safety check to limit it, like at 5000 rows or
|
||||
// something like that?
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a SQL query for available times that match the request
|
||||
*
|
||||
* @param request
|
||||
* the request to find available times for
|
||||
* @return the SQL query
|
||||
*/
|
||||
public static String assembleGetTimes(IGeometryRequest request) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// select
|
||||
sb.append("select distinct ");
|
||||
sb.append(TIME_COL);
|
||||
|
||||
// from
|
||||
sb.append(buildFrom(request));
|
||||
|
||||
// where
|
||||
sb.append(buildWhere(request, null));
|
||||
sb.append(buildOrderByTime());
|
||||
sb.append(";");
|
||||
|
||||
// TODO do i need a safety check to limit it, like at 5000 rows or
|
||||
// something like that?
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a select statement of a query, such as
|
||||
* "select d.lid, d.producttime, l.lat, l.lon, d.value"
|
||||
*
|
||||
* @param request
|
||||
* the request to form a select statement on
|
||||
* @return the select statement
|
||||
*/
|
||||
private static CharSequence buildSelectParams(IGeometryRequest request) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// always want the location name and time even if they didn't request it
|
||||
// so that returned objects will have that information
|
||||
sb.append("select d.");
|
||||
sb.append(LID_COL);
|
||||
sb.append(", d.");
|
||||
sb.append(TIME_COL);
|
||||
// request lat and lon for the returned geometry objects
|
||||
sb.append(", l.lat, l.lon");
|
||||
|
||||
// request other columns
|
||||
for (String param : request.getParameters()) {
|
||||
sb.append(", d.");
|
||||
sb.append(param);
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a from statement, such as "from height"
|
||||
*
|
||||
* @param request
|
||||
* the request to determine the tablename from
|
||||
* @return the from statement
|
||||
*/
|
||||
private static CharSequence buildFrom(IGeometryRequest request) {
|
||||
return " from " + request.getIdentifiers().get(TABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a from statement with a location added, such as "from height,
|
||||
* location l"
|
||||
*
|
||||
* @param request
|
||||
* the request to determine the tablename from
|
||||
* @return the from statement
|
||||
*/
|
||||
private static CharSequence buildFromWithLocation(IGeometryRequest request) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(buildFrom(request));
|
||||
sb.append(" d, location l");
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a SQL where clause based on the request
|
||||
*
|
||||
* @param request
|
||||
* the request
|
||||
* @param timeConstraint
|
||||
* the time constraint String as produced by
|
||||
* buildTimeConstraint(), or null
|
||||
* @return the where clause
|
||||
*/
|
||||
private static CharSequence buildWhere(IGeometryRequest request,
|
||||
CharSequence timeConstraint) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
CharSequence locationConstraint = buildLocationConstraint(request
|
||||
.getLocationNames());
|
||||
CharSequence extraConstraints = buildIdentifierConstraint(request
|
||||
.getIdentifiers());
|
||||
if (locationConstraint != null || extraConstraints != null
|
||||
|| timeConstraint != null) {
|
||||
sb.append(" where ");
|
||||
if (locationConstraint != null) {
|
||||
sb.append(locationConstraint);
|
||||
if (extraConstraints != null || timeConstraint != null) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
}
|
||||
if (extraConstraints != null) {
|
||||
sb.append(extraConstraints);
|
||||
if (timeConstraint != null) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
}
|
||||
if (timeConstraint != null) {
|
||||
sb.append(timeConstraint);
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a SQL string that can be used as part of a where clause to
|
||||
* limit the locations returned.
|
||||
*
|
||||
* @param locationNames
|
||||
* the names of hydro gages to limit on
|
||||
* @return a SQL string based on lid, such as "lid = 'ABRN1'" or "lid in
|
||||
* ('ARBN1','ARBN2')"
|
||||
*/
|
||||
private static CharSequence buildLocationConstraint(String[] locationNames) {
|
||||
StringBuilder sb = null;
|
||||
if (locationNames != null && locationNames.length > 0) {
|
||||
sb = new StringBuilder();
|
||||
sb.append(LID_COL);
|
||||
if (locationNames.length == 1) {
|
||||
sb.append(" = '");
|
||||
sb.append(locationNames[0]);
|
||||
sb.append("'");
|
||||
} else {
|
||||
sb.append(" in (");
|
||||
for (int i = 0; i < locationNames.length; i++) {
|
||||
sb.append("'");
|
||||
sb.append(locationNames[i]);
|
||||
sb.append("'");
|
||||
if (i < locationNames.length - 1) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
}
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a SQL string that can be used as part of a where clause to
|
||||
* limit the data returned.
|
||||
*
|
||||
* @param identifiers
|
||||
* the constraints to use
|
||||
* @return a SQL string based on the map, such as "ts = 'RG'"
|
||||
*/
|
||||
private static CharSequence buildIdentifierConstraint(
|
||||
Map<String, Object> identifiers) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Map<String, Object> copy = new HashMap<String, Object>(identifiers);
|
||||
copy.remove(TABLE);
|
||||
Iterator<Map.Entry<String, Object>> itr = copy.entrySet().iterator();
|
||||
while (itr.hasNext()) {
|
||||
Map.Entry<String, Object> entry = itr.next();
|
||||
String key = entry.getKey();
|
||||
sb.append(entry.getKey());
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof Number) {
|
||||
sb.append(" = ");
|
||||
sb.append(value);
|
||||
} else if (value instanceof String) {
|
||||
sb.append(" = ");
|
||||
sb.append("'");
|
||||
sb.append(value);
|
||||
sb.append("'");
|
||||
} else if (value instanceof List) {
|
||||
sb.append(" in (");
|
||||
List<?> list = (List<?>) value;
|
||||
Iterator<?> itrList = list.iterator();
|
||||
while (itrList.hasNext()) {
|
||||
sb.append("'");
|
||||
sb.append(itrList.next().toString());
|
||||
sb.append("'");
|
||||
if (itrList.hasNext()) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
} else {
|
||||
throw new IncompatibleRequestException(
|
||||
"Unable to handle identifier " + key + " of type "
|
||||
+ value);
|
||||
}
|
||||
|
||||
if (itr.hasNext()) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
}
|
||||
|
||||
return ((sb.length() > 0) ? sb : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a SQL string that can be used as part of a where clause to
|
||||
* limit the data to between the start and end of a time range.
|
||||
*
|
||||
* @param timeRange
|
||||
* the time range to use to make the string
|
||||
* @return a SQL between statement corresponding to the time range, such as
|
||||
* "between '2012-09-29 09:00:00' and '2012-09-29 12:00:00'"
|
||||
*
|
||||
*/
|
||||
private static CharSequence buildTimeConstraint(TimeRange timeRange) {
|
||||
String result = null;
|
||||
if (timeRange != null) {
|
||||
result = TIME_COL + " between '"
|
||||
+ TimeUtil.formatToSqlTimestamp(timeRange.getStart())
|
||||
+ "' and '"
|
||||
+ TimeUtil.formatToSqlTimestamp(timeRange.getEnd()) + "'";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a SQL string that can be used as part of a where clause to
|
||||
* limit the data to a set of specific times.
|
||||
*
|
||||
* @param dataTimes
|
||||
* the time to limit it to.
|
||||
* @return a SQL in statement corresponding to the times as strings
|
||||
*/
|
||||
private static CharSequence buildTimeConstraint(DataTime[] dataTimes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (dataTimes != null && dataTimes.length > 0) {
|
||||
sb.append(TIME_COL);
|
||||
sb.append(" in (");
|
||||
for (int i = 0; i < dataTimes.length; i++) {
|
||||
sb.append("'");
|
||||
sb.append(TimeUtil.formatToSqlTimestamp(dataTimes[i]
|
||||
.getRefTime()));
|
||||
sb.append("'");
|
||||
if (i < dataTimes.length - 1) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
}
|
||||
return ((sb.length() > 0) ? sb : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles a SQL string to order results by time, such as
|
||||
* "order by producttime"
|
||||
*
|
||||
* @return a SQL statement that orders results by time
|
||||
*/
|
||||
private static CharSequence buildOrderByTime() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(" order by ");
|
||||
sb.append(TIME_COL);
|
||||
sb.append(" asc");
|
||||
return sb;
|
||||
}
|
||||
|
||||
}
|
|
@ -332,4 +332,11 @@
|
|||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.raytheon.uf.common.dataaccess"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
||||
|
|
Loading…
Add table
Reference in a new issue