Issue #189 Make Derived parameters spatially aware

Former-commit-id: 317696c66f [formerly 317696c66f [formerly f7919f7bfc3f631cc76e19710ea18feb6faf35f9]]
Former-commit-id: 8682b30383
Former-commit-id: 2f6b9f6188
This commit is contained in:
Ben Steffensmeier 2012-09-27 16:36:12 -05:00
parent d9fb077943
commit c866f23a03
60 changed files with 2977 additions and 2613 deletions

View file

@ -49,6 +49,25 @@ import com.raytheon.uf.viz.derivparam.library.DerivedParameterGenerator;
import com.raytheon.viz.pointdata.util.AbstractPointDataInventory;
import com.raytheon.viz.pointdata.util.PointDataCubeAdapter;
/**
*
* Acarssounding data does not use the point data api, to get derived parameters
* to work with acarssounding data this class will intercept point data
* requests, and request all sounding layers from the db and reconstruct the
* data to fit in a PointDataContainer.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 26, 2012 bsteffen Initial javadoc
*
* </pre>
*
* @version 1.0
*/
public class ACARSSoundingDataCubeAdapter extends PointDataCubeAdapter {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ACARSSoundingDataCubeAdapter.class);
@ -120,8 +139,7 @@ public class ACARSSoundingDataCubeAdapter extends PointDataCubeAdapter {
}
@Override
protected PointDataContainer getBaseRecords(
Collection<String> baseParameters,
public PointDataContainer getBaseRecords(Collection<String> baseParameters,
Map<String, RequestConstraint> queryParams) throws VizException {
List<String> baseParams = new ArrayList<String>(baseParameters);
String script = ScriptCreator.createScript(queryParams, 1000, "select");

View file

@ -7,26 +7,24 @@ Bundle-Activator: com.raytheon.uf.viz.derivparam.Activator
Bundle-Vendor: RAYTHEON
Require-Bundle: org.eclipse.core.runtime,
javax.measure,
com.raytheon.uf.common.dataquery,
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.uf.common.datastorage;bundle-version="1.12.1174",
com.raytheon.uf.common.pointdata;bundle-version="1.12.1174"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Import-Package: com.raytheon.edex.meteoLib,
com.raytheon.edex.util,
com.raytheon.uf.common.comm,
Import-Package: com.raytheon.uf.common.comm,
com.raytheon.uf.common.dataplugin,
com.raytheon.uf.common.dataplugin.level,
com.raytheon.uf.common.dataplugin.persist,
com.raytheon.uf.common.derivparam.tree,
com.raytheon.uf.common.geospatial,
com.raytheon.uf.common.localization,
com.raytheon.uf.common.message.response,
com.raytheon.uf.common.serialization,
com.raytheon.uf.common.serialization.adapters,
com.raytheon.uf.common.status,
com.raytheon.uf.common.time
com.raytheon.uf.common.time,
com.vividsolutions.jts.geom,
org.opengis.referencing.crs
Export-Package: com.raytheon.uf.viz.derivparam,
com.raytheon.uf.viz.derivparam.data,
com.raytheon.uf.viz.derivparam.inv,

View file

@ -22,23 +22,14 @@ package com.raytheon.uf.viz.derivparam.data;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequestSet;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequestSet;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponseSet;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.pointdata.PointDataContainer;
@ -47,9 +38,10 @@ import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.datastructure.IDataCubeAdapter;
import com.raytheon.uf.viz.core.datastructure.VizDataCubeException;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode.Dependency;
import com.raytheon.uf.viz.derivparam.inv.AvailabilityContainer;
import com.raytheon.uf.viz.derivparam.inv.MetadataContainer;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
/**
* Abstract data cube adapter for standard data type that uses derived
@ -99,55 +91,38 @@ public abstract class AbstractDataCubeAdapter implements IDataCubeAdapter {
@Override
public List<List<DataTime>> timeQuery(List<TimeQueryRequest> requests)
throws VizException {
int mapSize = (int) (requests.size() * 1) + 1;
Map<AbstractRequestableLevelNode, Set<DataTime>> cache = new HashMap<AbstractRequestableLevelNode, Set<DataTime>>(
mapSize);
LinkedHashMap<AbstractRequestableLevelNode, TimeQueryRequest> queries = new LinkedHashMap<AbstractRequestableLevelNode, TimeQueryRequest>(
mapSize);
AvailabilityContainer container = createAvailabilityContainer();
for (TimeQueryRequest request : requests) {
List<AbstractRequestableLevelNode> requestNodes = evaluateRequestConstraints(request
List<AbstractRequestableNode> requestNodes = evaluateRequestConstraints(request
.getQueryTerms());
// pull out time queries and bulk submit
for (AbstractRequestableLevelNode requestNode : requestNodes) {
getTimeQuery(request, requestNode, false, queries, cache, null);
for (AbstractRequestableNode requestNode : requestNodes) {
container.prepareRequests(requestNode);
}
}
// set the results back into the cache's
TimeQueryRequestSet reqSet = new TimeQueryRequestSet();
reqSet.setRequests(queries.values().toArray(
new TimeQueryRequest[queries.size()]));
@SuppressWarnings("unchecked")
List<List<DataTime>> qResponses = (List<List<DataTime>>) ThriftClient
.sendRequest(reqSet);
int index = 0;
for (AbstractRequestableLevelNode node : queries.keySet()) {
// put results into cache
node.setTimeQueryResults(false, qResponses.get(index++), cache,
null);
}
List<List<DataTime>> finalResponse = new ArrayList<List<DataTime>>(
requests.size());
for (TimeQueryRequest request : requests) {
List<AbstractRequestableLevelNode> requestNodes = evaluateRequestConstraints(request
List<AbstractRequestableNode> requestNodes = evaluateRequestConstraints(request
.getQueryTerms());
// pull the actual results from the cache
Set<DataTime> results = new HashSet<DataTime>(64);
for (AbstractRequestableLevelNode requestNode : requestNodes) {
Set<DataTime> times = requestNode.timeQuery(request, false,
cache, null);
if (times == AbstractRequestableLevelNode.TIME_AGNOSTIC) {
// TODO: include time agnostic query in main bulk query as
// each pressure level will cause a separate query
List<DataTime> temp = timeAgnosticQuery(request
.getQueryTerms());
if (temp != null) {
results.addAll(temp);
for (AbstractRequestableNode requestNode : requestNodes) {
Set<TimeAndSpace> avialability = container
.getAvailability(requestNode);
for (TimeAndSpace ast : avialability) {
if (ast.isTimeAgnostic()) {
List<DataTime> temp = timeAgnosticQuery(request
.getQueryTerms());
if (temp != null) {
results.addAll(temp);
}
break;
} else {
results.add(ast.getTime());
}
break;
} else {
results.addAll(times);
}
}
if (!request.isMaxQuery() || results.isEmpty()) {
@ -162,35 +137,6 @@ public abstract class AbstractDataCubeAdapter implements IDataCubeAdapter {
return finalResponse;
}
protected void getTimeQuery(
TimeQueryRequest originalRequest,
AbstractRequestableLevelNode req,
boolean latestOnly,
LinkedHashMap<AbstractRequestableLevelNode, TimeQueryRequest> queries,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
throws VizException {
List<Dependency> depends = req.getDependencies();
if (depends.isEmpty()) {
// is source node
TimeQueryRequest myQ = req.getTimeQuery(originalRequest,
latestOnly, cache, latestOnlyCache);
if (myQ != null) {
queries.put(req, myQ);
}
} else {
for (Dependency dep : depends) {
// TODO: Optimize dTime/fTime to use bulk query mechanism,
// small case that is a not easy to get right with a bulk
// query
if (dep.timeOffset == 0 || !latestOnly) {
getTimeQuery(originalRequest, dep.node, latestOnly,
queries, cache, latestOnlyCache);
}
}
}
}
/*
* (non-Javadoc)
*
@ -232,94 +178,40 @@ public abstract class AbstractDataCubeAdapter implements IDataCubeAdapter {
@Override
public List<Object> getData(LayerProperty property, int timeOut)
throws VizException {
List<AbstractRequestableLevelNode> requests = evaluateRequestConstraints(property
List<AbstractRequestableNode> requests = evaluateRequestConstraints(property
.getEntryQueryParameters(false));
int mapSize = (int) (requests.size() * 1.25) + 1;
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache = new HashMap<AbstractRequestableLevelNode, List<AbstractRequestableData>>(
mapSize);
LinkedHashMap<AbstractRequestableLevelNode, DbQueryRequest> queries = new LinkedHashMap<AbstractRequestableLevelNode, DbQueryRequest>(
mapSize);
for (AbstractRequestableLevelNode req : requests) {
getDataQuery(req, property, timeOut, queries, cache);
}
DbQueryRequestSet reqSet = new DbQueryRequestSet();
reqSet.setQueries(queries.values().toArray(
new DbQueryRequest[queries.size()]));
DbQueryResponseSet qSetResponse = (DbQueryResponseSet) ThriftClient
.sendRequest(reqSet);
DbQueryResponse[] qResponses = qSetResponse.getResults();
int index = 0;
for (AbstractRequestableLevelNode node : queries.keySet()) {
// put results into cache
node.setDataQueryResults(qResponses[index++], cache);
Set<TimeAndSpace> availability = null;
if (property.getSelectedEntryTime() != null) {
availability = new HashSet<TimeAndSpace>();
for (DataTime time : property.getSelectedEntryTime()) {
availability.add(new TimeAndSpace(time));
}
} else {
availability = AvailabilityContainer.AGNOSTIC_SET;
}
// pull the actual results from the cache
List<AbstractRequestableData> requesters = new ArrayList<AbstractRequestableData>(
requests.size());
for (AbstractRequestableLevelNode request : requests) {
requesters.addAll(request.getData(property, timeOut, cache));
List<AbstractRequestableData> requesters = new ArrayList<AbstractRequestableData>();
MetadataContainer container = createMetadataContainer(property
.getEntryQueryParameters(false));
for (AbstractRequestableNode request : requests) {
container.prepareRequests(request, availability);
}
for (AbstractRequestableNode request : requests) {
requesters.addAll(container.getData(request, availability));
}
return getData(property, requesters);
}
protected void getDataQuery(
AbstractRequestableLevelNode req,
LayerProperty property,
int timeOut,
LinkedHashMap<AbstractRequestableLevelNode, DbQueryRequest> queries,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
List<Dependency> depends = req.getDependencies();
if (depends.isEmpty()) {
// is source node
DbQueryRequest myQ = req.getDataQuery(property, timeOut, cache);
if (myQ != null) {
addDataQuery(req, myQ, queries);
}
} else {
for (Dependency dep : depends) {
// TODO: Optimize dTime/fTime to use bulk query mechanism,
// small case that is a not easy to get right with a bulk
// query
if (dep.timeOffset == 0) {
getDataQuery(dep.node, property, timeOut, queries, cache);
}
}
}
protected MetadataContainer createMetadataContainer(
Map<String, RequestConstraint> constraints) {
return new MetadataContainer(constraints);
}
private void addDataQuery(AbstractRequestableLevelNode req,
DbQueryRequest query,
LinkedHashMap<AbstractRequestableLevelNode, DbQueryRequest> queries) {
DbQueryRequest curQuery = queries.get(req);
if (curQuery == null) {
queries.put(req, query);
} else {
// merge
// assume same DB, fields, etc, should only be different
// time constraints since its the same node
RequestConstraint curDTs = curQuery.getConstraints()
.get("dataTime");
RequestConstraint myDTs = query.getConstraints().get("dataTime");
if (curDTs != null && myDTs != null) {
// only merge if both require dataTimes, otherwise one
// would be constrained when it needs everything, also
// assuming both to be in lists and needing to be merged
curDTs.setConstraintType(ConstraintType.IN);
Pattern split = Pattern.compile(",");
String[] curVals = split.split(curDTs.getConstraintValue());
String[] myVals = split.split(myDTs.getConstraintValue());
HashSet<String> dups = new HashSet<String>(curVals.length
+ myVals.length);
dups.addAll(Arrays.asList(curVals));
dups.addAll(Arrays.asList(myVals));
curDTs.setConstraintValueList(dups.toArray(new String[dups
.size()]));
}
}
protected AvailabilityContainer createAvailabilityContainer() {
return new AvailabilityContainer();
}
/*
@ -374,7 +266,7 @@ public abstract class AbstractDataCubeAdapter implements IDataCubeAdapter {
* @param constraints
* @return
*/
protected abstract List<AbstractRequestableLevelNode> evaluateRequestConstraints(
protected abstract List<AbstractRequestableNode> evaluateRequestConstraints(
Map<String, RequestConstraint> constraints);
/**

View file

@ -25,11 +25,17 @@ import java.util.List;
import javax.measure.unit.Unit;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
/**
* TODO Add Description
* AbstractRequestableData is the base metadata class for derived parameters. It
* represents a single data value for a given source/parameter/level/time/space
* combination. As well as representing the metadata it also provides a
* getDataValue method which should return a dataValue that can be used in
* derived parameters to calculate other parameters.
*
* <pre>
*
@ -56,7 +62,9 @@ public abstract class AbstractRequestableData {
protected Level level;
protected DataTime dataTime;
protected DataTime dataTime = TimeAndSpace.TIME_AGNOSTIC;
protected ISpatialObject space = TimeAndSpace.SPACE_AGNOSTIC;
public AbstractRequestableData() {
@ -69,6 +77,7 @@ public abstract class AbstractRequestableData {
this.unit = that.unit;
this.level = that.level;
this.dataTime = that.dataTime;
this.space = that.space;
}
// Object can be a plugin specific argument that will be passed through the
@ -153,6 +162,14 @@ public abstract class AbstractRequestableData {
this.level = level;
}
public ISpatialObject getSpace() {
return space;
}
public void setSpace(ISpatialObject space) {
this.space = space;
}
/**
* @return the dataTime
*/
@ -168,6 +185,10 @@ public abstract class AbstractRequestableData {
this.dataTime = dataTime;
}
public TimeAndSpace getTimeAndSpace() {
return new TimeAndSpace(dataTime, space);
}
public List<AbstractRequestableData> getDependencies() {
return Collections.emptyList();
}

View file

@ -31,7 +31,9 @@ import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.viz.core.exception.VizException;
/**
* TODO Add Description
* Represents a simple alias, where a parameter represents the same data as
* another parameter. This does automatic unit conversion if the source data is
* in a different unit than this object.
*
* <pre>
*
@ -53,6 +55,7 @@ public class AliasRequestableData extends AbstractRequestableData {
public AliasRequestableData(AbstractRequestableData sourceRecord) {
this.sourceRecord = sourceRecord;
this.dataTime = sourceRecord.getDataTime();
this.space = sourceRecord.space;
}
public Object getDataValue(Object arg) throws VizException {

View file

@ -19,8 +19,10 @@
**/
package com.raytheon.uf.viz.derivparam.data;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
/**
* TODO Add Description
* RequestableData object for a single constant float value.
*
* <pre>
*
@ -41,6 +43,8 @@ public class FloatRequestableData extends AbstractRequestableData {
public FloatRequestableData(Float value) {
this.value = value;
this.dataTime = TimeAndSpace.TIME_AGNOSTIC;
this.space = TimeAndSpace.SPACE_AGNOSTIC;
}
public Float getDataValue() {

View file

@ -60,12 +60,11 @@ import com.raytheon.uf.viz.derivparam.library.DerivedParameterGenerator;
import com.raytheon.uf.viz.derivparam.library.DerivedParameterGenerator.DerivParamUpdateListener;
import com.raytheon.uf.viz.derivparam.library.IDerivParamField;
import com.raytheon.uf.viz.derivparam.library.LevelType;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.uf.viz.derivparam.tree.AliasLevelNode;
import com.raytheon.uf.viz.derivparam.tree.CompositeAverageLevelNode;
import com.raytheon.uf.viz.derivparam.tree.DerivedLevelNode;
import com.raytheon.uf.viz.derivparam.tree.ModelRunLevelNode;
import com.raytheon.uf.viz.derivparam.tree.OrLevelNode;
import com.raytheon.uf.viz.derivparam.tree.StaticDataLevelNode;
import com.raytheon.uf.viz.derivparam.tree.TimeRangeLevelNode;
@ -73,7 +72,10 @@ import com.raytheon.uf.viz.derivparam.tree.UnionLevelNode;
/**
*
* TODO Add Description
* The Inventory is responsible for managing what parameters can be derived. It
* maintains a dataTree which contains all the base parameter as well as any
* previously used derived parameters. It can dynamically calculate what
* parameters can be derived using the walk tree method.
*
* <pre>
*
@ -310,7 +312,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
request.add(result);
}
}
AbstractDerivedLevelNode newNode = createDerivedNode(desc,
AbstractDerivedDataNode newNode = createDerivedNode(desc,
method, lNode.getLevel(), request, sNode);
pNode.getChildNodes().put(lNode.getValue(), newNode);
}
@ -568,7 +570,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
* @throws InterruptedException
* thrown if the thread was interupted during execution.
*/
protected synchronized List<AbstractRequestableLevelNode> walkTree(
protected synchronized List<AbstractRequestableNode> walkTree(
Class<? extends AbstractNode<?>> clazz,
Collection<String> sourcesToProcess,
Collection<String> paramsToProcess,
@ -604,7 +606,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
}
}
}
List<AbstractRequestableLevelNode> results = new ArrayList<AbstractRequestableLevelNode>();
List<AbstractRequestableNode> results = new ArrayList<AbstractRequestableNode>();
Set<StackEntry> nodata = new HashSet<StackEntry>(derParLibrary.size());
Deque<StackEntry> stack = new ArrayDeque<StackEntry>();
Iterator<String> sit = sourcesToProcess.iterator();
@ -630,7 +632,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
Iterator<Level> lit = levelsToProcess.iterator();
while (lit.hasNext()) {
Level level = lit.next();
AbstractRequestableLevelNode result = null;
AbstractRequestableNode result = null;
if (derive) {
try {
result = resolveNode(node, param, level, stack,
@ -641,7 +643,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
}
} else {
ParameterNode pNode = node.getChildNode(param);
result = (AbstractRequestableLevelNode) (pNode == null ? null
result = (AbstractRequestableNode) (pNode == null ? null
: pNode.getChildNode(Long.toString(level
.getId())));
}
@ -652,10 +654,10 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
if (!includeConstant) {
if (result.isConstant()) {
continue;
} else if (result instanceof AbstractDerivedLevelNode) {
} else if (result instanceof AbstractDerivedDataNode) {
// if we don't want constant fields I assume we
// also don't want internal fields
if (((AbstractDerivedLevelNode) result)
if (((AbstractDerivedDataNode) result)
.getDesc().isInternal()) {
continue;
}
@ -683,10 +685,10 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
} else {
if (sourceAliases.containsKey(source)) {
boolean supplement = false;
List<AbstractRequestableLevelNode> choices = new ArrayList<AbstractRequestableLevelNode>();
List<AbstractRequestableNode> choices = new ArrayList<AbstractRequestableNode>();
for (String aliasModel : sourceAliases
.get(source)) {
AbstractRequestableLevelNode alias = null;
AbstractRequestableNode alias = null;
if (derive) {
try {
alias = resolveNode(
@ -700,7 +702,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
} else {
ParameterNode pNode = node
.getChildNode(param);
alias = (AbstractRequestableLevelNode) (pNode == null ? null
alias = (AbstractRequestableNode) (pNode == null ? null
: pNode.getChildNode(Long
.toString(level.getId())));
}
@ -762,7 +764,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
* @return
* @throws VizCommunicationException
*/
protected synchronized AbstractRequestableLevelNode resolveNode(
protected synchronized AbstractRequestableNode resolveNode(
SourceNode sourceNode, String param, Level level,
Deque<StackEntry> stack, Set<StackEntry> nodata)
throws VizCommunicationException {
@ -774,7 +776,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
&& !stack.isEmpty()) {
stack.getFirst().autoAverage = true;
}
return (AbstractRequestableLevelNode) lNode;
return (AbstractRequestableNode) lNode;
}
DerivParamDesc desc = derParLibrary.get(param);
if (desc == null) {
@ -799,7 +801,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
}
// Any time this function returns after this point it must pop se, or
// else!
AbstractDerivedLevelNode autoAveragedNode = null;
AbstractDerivedDataNode autoAveragedNode = null;
stack.push(se);
List<DerivParamMethod> methods = desc.getMethods();
if (methods != null) {
@ -871,7 +873,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
|| ((method.getFrameworkMethod() == FrameworkMethod.UNION || method
.getFrameworkMethod() == FrameworkMethod.OR) && request
.size() > 0)) {
AbstractDerivedLevelNode newNode = createDerivedNode(
AbstractDerivedDataNode newNode = createDerivedNode(
desc, method, level, request, sourceNode);
if (newNode != null) {
pNode = sourceNode.getChildNode(param);
@ -910,10 +912,10 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
throw new VizCommunicationException(e);
}
List<AbstractRequestableLevelNode> nodes = new ArrayList<AbstractRequestableLevelNode>();
List<AbstractRequestableNode> nodes = new ArrayList<AbstractRequestableNode>();
int endCount = 0;
AbstractRequestableLevelNode target = resolveNode(sourceNode,
param, upperLevel, stack, nodata);
AbstractRequestableNode target = resolveNode(sourceNode, param,
upperLevel, stack, nodata);
if (target != null) {
endCount += 1;
nodes.add(target);
@ -1120,12 +1122,12 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
DerivParamField field, Deque<StackEntry> stack,
Set<StackEntry> nodata) throws VizCommunicationException;
protected abstract AbstractDerivedLevelNode getImportNode(
protected abstract AbstractDerivedDataNode getImportNode(
AbstractRequestableData nodeToImport, SourceNode destSourceNode,
DerivParamDesc desc, DerivParamMethod method, Level level);
protected abstract AbstractDerivedLevelNode getImportNode(
AbstractRequestableLevelNode nodeToImport,
protected abstract AbstractDerivedDataNode getImportNode(
AbstractRequestableNode nodeToImport,
String nodeToImportSourceName, SourceNode destSourceNode,
DerivParamDesc desc, DerivParamMethod method, Level level);
@ -1142,7 +1144,7 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
* @param source
* @return
*/
protected AbstractDerivedLevelNode createDerivedNode(DerivParamDesc desc,
protected AbstractDerivedDataNode createDerivedNode(DerivParamDesc desc,
DerivParamMethod method, Level level, List<Object> fields,
SourceNode source) {
switch (method.getMethodType()) {
@ -1158,9 +1160,9 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
node.putStaticField(method.getFields().get(k),
(AbstractRequestableData) obj);
}
if (obj instanceof AbstractRequestableLevelNode) {
if (obj instanceof AbstractRequestableNode) {
node.putField((DerivParamField) method.getFields().get(k),
(AbstractRequestableLevelNode) obj);
(AbstractRequestableNode) obj);
}
}
return node;
@ -1177,10 +1179,9 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
data.setUnit(desc.getUnit());
return new StaticDataLevelNode(level, desc, method, data,
source.getValue());
} else if (field instanceof AbstractRequestableLevelNode) {
return new AliasLevelNode(
(AbstractRequestableLevelNode) field, desc, method,
source.getValue(), level);
} else if (field instanceof AbstractRequestableNode) {
return new AliasLevelNode((AbstractRequestableNode) field,
desc, method, source.getValue(), level);
}
return null;
}
@ -1201,21 +1202,26 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
if (field instanceof AbstractRequestableData) {
return getImportNode((AbstractRequestableData) field,
source, desc, method, level);
} else if (field instanceof AbstractRequestableLevelNode) {
return getImportNode((AbstractRequestableLevelNode) field,
} else if (field instanceof AbstractRequestableNode) {
return getImportNode((AbstractRequestableNode) field,
importSource, source, desc, method, level);
}
return null;
}
case MODELRUN:
return new ModelRunLevelNode(
(AbstractRequestableLevelNode) fields.get(0), desc,
method, source.getValue(), level);
if (source.getDt() <= 0) {
return null;
}
AbstractRequestableNode sourceLevelNode = (AbstractRequestableNode) fields
.get(0);
return new TimeRangeLevelNode(sourceLevelNode, desc, method,
source.getValue(), (Integer) null, 0, source.getDt(),
level);
case TIMERANGE:
if (source.getDt() <= 0) {
return null;
}
AbstractRequestableLevelNode sourceNode = (AbstractRequestableLevelNode) fields
AbstractRequestableNode sourceNode = (AbstractRequestableNode) fields
.get(0);
Float startTime = ((FloatRequestableData) fields.get(1))
.getDataValue();
@ -1226,18 +1232,18 @@ public abstract class AbstractInventory implements DerivParamUpdateListener {
endTime.intValue(), source.getDt(), level);
case SUPPLEMENT:
case OR:
List<AbstractRequestableLevelNode> choices = new ArrayList<AbstractRequestableLevelNode>(
List<AbstractRequestableNode> choices = new ArrayList<AbstractRequestableNode>(
fields.size());
for (Object obj : fields) {
choices.add((AbstractRequestableLevelNode) obj);
choices.add((AbstractRequestableNode) obj);
}
return new OrLevelNode(level, desc, method, source.getValue(),
choices);
case UNION:
List<AbstractRequestableLevelNode> nodes = new ArrayList<AbstractRequestableLevelNode>(
List<AbstractRequestableNode> nodes = new ArrayList<AbstractRequestableNode>(
fields.size());
for (Object obj : fields) {
nodes.add((AbstractRequestableLevelNode) obj);
nodes.add((AbstractRequestableNode) obj);
}
return new UnionLevelNode(level, desc, method,
source.getValue(), nodes);

View file

@ -0,0 +1,190 @@
/**
* 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.derivparam.inv;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequestSet;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponseSet;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.derivparam.tree.AbstractBaseDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode.Dependency;
/**
* Object for determining the vailability(in time and space) when a
* AbstractRequestableNode can provide data. Specifically the node recursively
* determines all dependencies and bulks requests for performance reason,
* maintaining a cache of time to avoid any redundant requests.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 11, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AvailabilityContainer {
public static final Set<TimeAndSpace> AGNOSTIC_SET = Collections
.unmodifiableSet(new HashSet<TimeAndSpace>(Arrays
.asList(new TimeAndSpace())));
protected Map<AbstractBaseDataNode, DbQueryRequest> requestCache = new HashMap<AbstractBaseDataNode, DbQueryRequest>();
protected Map<AbstractRequestableNode, Set<TimeAndSpace>> availabilityCache = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
/**
* Get the availability in Time and space for a given node.
*
* @param node
* @return
* @throws VizException
*/
public synchronized Set<TimeAndSpace> getAvailability(
AbstractRequestableNode node) throws VizException {
return getAvailability(node, true);
}
/**
* recursively determine avaialbilty for a node and its dependencies,
* doRequests should only be true for the first call, after that all
* requests will have already been handled.
*
* @param node
* @param doRequests
* @return
* @throws VizException
*/
private Set<TimeAndSpace> getAvailability(AbstractRequestableNode node,
boolean doRequests) throws VizException {
if (availabilityCache.containsKey(node)) {
return availabilityCache.get(node);
}
if (doRequests) {
prepareRequests(node);
processRequests();
}
if (node instanceof AbstractBaseDataNode) {
if (availabilityCache.containsKey(node)) {
return availabilityCache.get(node);
} else {
throw new IllegalStateException(
"DataNode should have been handled in processRequests");
}
} else if (node instanceof AbstractDerivedDataNode) {
AbstractDerivedDataNode dataNode = (AbstractDerivedDataNode) node;
for (Dependency d : dataNode.getDependencies()) {
getAvailability(d.node, false);
}
Set<TimeAndSpace> availability = dataNode
.getAvailability(availabilityCache);
availabilityCache.put(node, availability);
return availability;
} else {
throw new IllegalStateException(
"Cannot determine availability of unknown Unknown node type : "
+ node.getClass().getSimpleName());
}
}
/**
* This will prepare the container to request availability for the given
* node. If this node is a derived node it will evaluate what data is needed
* so that when getData is called it can bulk request all data. If
* availability is needed for multiple nodes than calling this multiple
* times before ever calling getAvailability will maximize the efficiency of
* bulk requests.
*
* @param node
* @param availability
* @throws VizException
*/
public synchronized void prepareRequests(AbstractRequestableNode node) {
if (availabilityCache.containsKey(node)
|| requestCache.containsKey(node)) {
return;
}
if (node instanceof AbstractBaseDataNode) {
AbstractBaseDataNode dataNode = (AbstractBaseDataNode) node;
requestCache.put(dataNode, dataNode.getAvailabilityRequest());
} else if (node instanceof AbstractDerivedDataNode) {
AbstractDerivedDataNode dataNode = (AbstractDerivedDataNode) node;
for (Dependency d : dataNode.getDependencies()) {
prepareRequests(d.node);
}
}
}
/**
* process all requests, in bulk if possible.
*
* @throws VizException
*/
protected void processRequests() throws VizException {
List<AbstractBaseDataNode> nodes = new ArrayList<AbstractBaseDataNode>();
List<DbQueryRequest> requests = new ArrayList<DbQueryRequest>();
for (Entry<AbstractBaseDataNode, DbQueryRequest> entry : requestCache
.entrySet()) {
if (availabilityCache.containsKey(entry.getKey())) {
continue;
} else if (entry.getValue() == null) {
availabilityCache.put(entry.getKey(), entry.getKey()
.getAvailability(null));
} else {
nodes.add(entry.getKey());
requests.add(entry.getValue());
}
}
if (nodes.isEmpty()) {
return;
}
DbQueryRequestSet requestSet = new DbQueryRequestSet();
requestSet.setQueries(requests.toArray(new DbQueryRequest[0]));
DbQueryResponseSet responseSet = (DbQueryResponseSet) ThriftClient
.sendRequest(requestSet);
for (int i = 0; i < nodes.size(); i++) {
availabilityCache.put(nodes.get(i),
nodes.get(i).getAvailability(responseSet.getResults()[i]));
}
}
}

View file

@ -0,0 +1,223 @@
/**
* 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.derivparam.inv;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequestSet;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponseSet;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.tree.AbstractBaseDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode.Dependency;
/**
* Class is responsible for pulling AbstractRequestableData out of
* AbstractRequestableNode objects. This class manages caching and bulk
* requesting to ensure that derived parameter requests are fully optimized.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 11, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class MetadataContainer {
protected final Map<String, RequestConstraint> originalConstraints;
protected Map<AbstractRequestableNode, Set<TimeAndSpace>> availCache = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
protected Map<AbstractRequestableNode, Set<AbstractRequestableData>> dataCache = new HashMap<AbstractRequestableNode, Set<AbstractRequestableData>>();
public MetadataContainer(Map<String, RequestConstraint> originalConstraints) {
this.originalConstraints = originalConstraints;
}
/**
* This will prepare the container to request data for the given node. If
* this node is a derived node it will evaluate what data is needed so that
* when getData is called it can bulk request all data. If data is needed
* for multiple nodes than calling this multiple times before ever calling
* getData will maximize the efficiency of bulk requests.
*
* @param node
* @param availability
* @throws VizException
*/
public synchronized void prepareRequests(AbstractRequestableNode node,
Set<TimeAndSpace> availability) throws VizException {
generateAvailability(node, availability);
}
/**
* get the requestable data for a node with the given availability. For
* non-derived nodes this is simple, for derived nodes this container will
* attempt to fully optimize and cache all data requests.
*
* @param node
* @param availability
* @return
* @throws VizException
*/
public synchronized Set<AbstractRequestableData> getData(
AbstractRequestableNode node, Set<TimeAndSpace> availability)
throws VizException {
return getData(node, availability, true);
}
/**
* recursively called to get data, but don't reprocess availability at every
* level, only for the first in the chain of recursive calls.
*
* @param node
* @param availability
* @param doRequests
* @return
* @throws VizException
*/
private Set<AbstractRequestableData> getData(AbstractRequestableNode node,
Set<TimeAndSpace> availability, boolean doRequests)
throws VizException {
if (dataCache.containsKey(node)) {
return dataCache.get(node);
}
if (doRequests) {
generateAvailability(node, availability);
processRequests();
}
if (node instanceof AbstractBaseDataNode) {
if (dataCache.containsKey(node)) {
return dataCache.get(node);
} else {
throw new IllegalStateException(
"DataNode should have been handled in processRequests");
}
} else if (node instanceof AbstractDerivedDataNode) {
AbstractDerivedDataNode dataNode = (AbstractDerivedDataNode) node;
for (Dependency d : dataNode.getDependencies()) {
getData(d.node, availCache.get(d.node), false);
}
Set<AbstractRequestableData> data = dataNode.getData(availability,
dataCache);
dataCache.put(node, data);
return data;
} else {
throw new IllegalStateException(
"Cannot determine availability of unknown Unknown node type : "
+ node.getClass().getSimpleName());
}
}
/**
* Walk through all dependencies for a node and calculate the TimeAndSpace
* where data is needed to get data for the requested TimeAndSpace.
*
* @param node
* @param availability
* @throws VizException
*/
private void generateAvailability(AbstractRequestableNode node,
Set<TimeAndSpace> availability) throws VizException {
Set<TimeAndSpace> c = availCache.get(node);
if (c != null) {
if (c.containsAll(availability)) {
return;
}
c.addAll(availability);
} else {
c = new HashSet<TimeAndSpace>(availability);
availCache.put(node, c);
}
if (node instanceof AbstractDerivedDataNode) {
AbstractDerivedDataNode derivedNode = (AbstractDerivedDataNode) node;
Map<AbstractRequestableNode, Set<TimeAndSpace>> avail = derivedNode
.getDataDependency(new HashSet<TimeAndSpace>(availability));
for (Entry<AbstractRequestableNode, Set<TimeAndSpace>> entry : avail
.entrySet()) {
AbstractRequestableNode n = entry.getKey();
Set<TimeAndSpace> a = entry.getValue();
generateAvailability(n, a);
}
}
}
/**
* use the availCache to determine what nodes need data and attempt to bulk
* all requests.
*
* @throws VizException
*/
protected void processRequests() throws VizException {
List<AbstractBaseDataNode> nodes = new ArrayList<AbstractBaseDataNode>();
List<DbQueryRequest> requests = new ArrayList<DbQueryRequest>();
for (AbstractRequestableNode node : availCache.keySet()) {
if (dataCache.containsKey(node)) {
continue;
}
if (node instanceof AbstractBaseDataNode) {
AbstractBaseDataNode dataNode = (AbstractBaseDataNode) node;
DbQueryRequest request = dataNode.getDataRequest(
originalConstraints, availCache.get(node));
if (request != null) {
nodes.add(dataNode);
requests.add(request);
} else {
dataCache.put(
node,
dataNode.getData(originalConstraints,
availCache.get(node), null));
}
}
}
if (requests.isEmpty()) {
return;
}
DbQueryRequestSet requestSet = new DbQueryRequestSet();
requestSet.setQueries(requests.toArray(new DbQueryRequest[0]));
DbQueryResponseSet responseSet = (DbQueryResponseSet) ThriftClient
.sendRequest(requestSet);
for (int i = 0; i < nodes.size(); i++) {
AbstractBaseDataNode node = nodes.get(i);
dataCache.put(node, node.getData(originalConstraints,
availCache.get(node), responseSet.getResults()[i]));
}
}
}

View file

@ -0,0 +1,186 @@
/**
* 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.derivparam.inv;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.time.DataTime;
import com.vividsolutions.jts.geom.Geometry;
/**
* Represents a time and space(location) where data can exist. This is used in
* derived parameters for data types to report when and where data can be
* loaded.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 11, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class TimeAndSpace {
/**
* A constant to represent the time for data that does not change over time
* or that is available for all times, an example would be topography which
* generally does not change on a day to day basis.
*/
public static final DataTime TIME_AGNOSTIC = new DataTime() {
private static final long serialVersionUID = 1L;
@Override
public boolean equals(Object obj) {
return this == obj;
}
@Override
public String toString() {
return "TIME_AGNOSTIC";
}
};
/**
* A constant to represent the space for data that does not change over
* space or that is available for all spaces, an example would be radar
* elevation angle for a grid coverage, this can be calculated for any
* gridcoverage.
*/
public static final ISpatialObject SPACE_AGNOSTIC = new ISpatialObject() {
private static final long serialVersionUID = 1L;
@Override
public Integer getNy() {
return null;
}
@Override
public Integer getNx() {
return null;
}
@Override
public Geometry getGeometry() {
return null;
}
@Override
public CoordinateReferenceSystem getCrs() {
return null;
}
@Override
public String toString() {
return "SPACE_AGNOSTIC";
}
};
private final DataTime time;
private final ISpatialObject space;
public TimeAndSpace() {
this(TIME_AGNOSTIC, SPACE_AGNOSTIC);
}
public TimeAndSpace(DataTime time) {
this(time, SPACE_AGNOSTIC);
}
public TimeAndSpace(ISpatialObject space) {
this(TIME_AGNOSTIC, space);
}
public TimeAndSpace(DataTime time, ISpatialObject space) {
this.time = time;
this.space = space;
}
public DataTime getTime() {
return time;
}
public ISpatialObject getSpace() {
return space;
}
public boolean isTimeAgnostic() {
return this.time == TIME_AGNOSTIC;
}
public boolean isSpaceAgnostic() {
return space == SPACE_AGNOSTIC;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((space == null) ? 0 : space.hashCode());
result = prime * result + ((time == null) ? 0 : time.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TimeAndSpace other = (TimeAndSpace) obj;
if (space == null) {
if (other.space != null)
return false;
} else if (!space.equals(other.space))
return false;
if (time == null) {
if (other.time != null)
return false;
} else if (!time.equals(other.time))
return false;
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("AvailSpT: Time: ");
sb.append(time);
sb.append(", Space: ");
sb.append(space);
return sb.toString();
}
}

View file

@ -0,0 +1,348 @@
/**
* 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.derivparam.inv;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.time.DataTime;
/**
* The primary function of this class is two find the intersection between two
* collections of TimeAndSpace objects. This will compare all the TimeAndSpace
* objects in each collection and find "matches". The simplest matches are when
* both time and space objects are equal. More complex matches can be created
* when times are equal but one is time agnostic or spaces are equal and one is
* space agnostic. Finally if for one of the Collections contains a time and
* space agnostic TimeAndSpace than it will match everything.
*
* Time matching is a little more complex than space because you can configure
* ignoreRange and validMatch so that times can be considered matching even if
* they aren't identical, as long as they are referencing a similar time, for
* more information see the setters for those flags.
*
* When determining matches this will choose the most specific match. For
* example if a TimeAndSpace object can match an object that matches space but
* only matches validTime or it can match an object that matches space but is
* time agnostic, then it will choose the valid time match since that is more
* specific than the agnostic. This order is defined by the natural order of the
* MatchType enum.
*
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 8, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class TimeAndSpaceMatcher {
private boolean ignoreRange = false;
private boolean matchValid = false;
/**
* When ignore range is true then times with different ranges are considered
* matching if they are the same in all other ways, when false times are
* considered nonmatching if the range is not identical.
*
* @param ignoreRange
*/
public void setIgnoreRange(boolean ignoreRange) {
this.ignoreRange = ignoreRange;
}
/**
* When match valid is true then dataTimes are compared based off valid
* time, when it is false the refTime and forecast time are considered
* sperately and both must match to create a match. Even when matchValid is
* true, if there is a time where forecast and refTime amtch it will be
* prefered to a time where only validTime matches
*
* @param matchValid
*/
public void setMatchValid(boolean matchValid) {
this.matchValid = matchValid;
}
/**
* Perform the match operation. The result is returned as a map, where the
* key is the intersected TimeAndSpace and the values are a MatchResult that
* contains the SpaceAndTime needed from each collection to represent that
* time.
*
* @param times1
* @param times2
* @return
*/
public Map<TimeAndSpace, MatchResult> match(
Collection<TimeAndSpace> times1, Collection<TimeAndSpace> times2) {
Map<TimeAndSpace, MatchResult> result = new HashMap<TimeAndSpace, MatchResult>();
for (TimeAndSpace t1 : times1) {
for (TimeAndSpace t2 : times2) {
MatchResult res = createMatchResult(t1, t2);
if (res != null) {
MatchResult prev = result.get(res.getMerge());
if (prev == null
|| prev.getMatchValue().compareTo(
res.getMatchValue()) > 0) {
result.put(res.getMerge(), res);
}
}
}
}
return result;
}
/**
* Given two TimeAndSpace objects attempts to determine what they have in
* common, if anything and return a MatchResult or null if there is no
* match.
*
* @param t1
* @param t2
* @return
*/
private MatchResult createMatchResult(TimeAndSpace t1, TimeAndSpace t2) {
MatchType matchValue;
DataTime time = null;
ISpatialObject space = null;
// first determine what space a match between these two times would have
boolean spaceAgn = false;
if (t1.getSpace().equals(t2.getSpace())) {
// If they match that is best
space = t1.getSpace();
} else if (t1.isSpaceAgnostic()) {
// space agnostic will match something with space.
spaceAgn = true;
space = t2.getSpace();
} else if (t2.isSpaceAgnostic()) {
// again one is agnostic
spaceAgn = true;
space = t1.getSpace();
} else {
// no spatial match, means no match at all.
return null;
}
// Next determine how well the times match
if (t1.isTimeAgnostic()) {
// When one is agnostic it will match anything.
time = t2.getTime();
matchValue = spaceAgn ? MatchType.AGNOSTIC_MATCH
: MatchType.SPACE_MATCH;
} else if (t2.isTimeAgnostic()) {
// again one is agnostic
time = t1.getTime();
matchValue = spaceAgn ? MatchType.AGNOSTIC_MATCH
: MatchType.SPACE_MATCH;
} else if (t1.getTime().equals(t2.getTime())) {
// A perfect time match is always best.
time = t1.getTime();
matchValue = spaceAgn ? MatchType.TIME_MATCH : MatchType.BOTH_MATCH;
} else if (ignoreRange
&& t1.getTime().getMatchRef() == t2.getTime().getMatchRef()
&& t1.getTime().getMatchFcst() == t2.getTime().getMatchFcst()) {
// If the ignoreRanfe flag is set then it is still considered a
// match even if the ranges are different.
time = new DataTime(t1.getTime().getRefTime(), t1.getTime()
.getFcstTime());
matchValue = spaceAgn ? MatchType.TIME_IGNORE_RANGE
: MatchType.BOTH_IGNORE_RANGE;
} else if (matchValid
&& t1.getTime().getMatchValid() == t2.getTime().getMatchValid()) {
// finally last valid allows us to mix different
// refTime/forecastTimes as long as valid matches.
if (t1.getTime().getMatchRef() > t2.getTime().getMatchRef()) {
time = new DataTime(t1.getTime().getRefTime(), t1.getTime()
.getFcstTime());
} else {
time = new DataTime(t2.getTime().getRefTime(), t2.getTime()
.getFcstTime());
}
matchValue = spaceAgn ? MatchType.TIME_VALID : MatchType.BOTH_VALID;
} else {
return null;
}
return new MatchResult(t1, t2, new TimeAndSpace(time, space),
matchValue);
}
/**
*
* Class to contain the result of a match operation for 2 matching
* TimeAndSpace objects
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 27, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public static class MatchResult {
/**
* The TimeAndSpace from the first collection that matches
*/
private final TimeAndSpace t1;
/**
* The TimeAndSpace from the second collection that matches
*/
private final TimeAndSpace t2;
/**
* The TimeAndSpace from the first collection that matches
*/
private final TimeAndSpace merge;
/**
* How good of a match is this.
*/
private final MatchType matchValue;
public MatchResult(TimeAndSpace t1, TimeAndSpace t2,
TimeAndSpace merge, MatchType matchValue) {
this.t1 = t1;
this.t2 = t2;
this.merge = merge;
this.matchValue = matchValue;
}
public TimeAndSpace get1() {
return t1;
}
public TimeAndSpace get2() {
return t2;
}
public TimeAndSpace getMerge() {
return merge;
}
public MatchType getMatchValue() {
return matchValue;
}
}
/**
*
* An enum which represents the quality of the match, The best matches are
* when both Time and Space objects are matches, but there are other
* matches, usually involving either Time or Space agnostic that are not as
* ideal but are suitable.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 27, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public static enum MatchType {
// Time and space match perfectly
BOTH_MATCH,
// Space matches perfectly but time only matches if you ignore range
BOTH_IGNORE_RANGE,
// Space matches perfectly but time only matches valid time
BOTH_VALID,
// one is space agnostic and time matches
TIME_MATCH,
// one is space agnostic but time only matches if you ignore range
TIME_IGNORE_RANGE,
// one is space agnostic but time only matches valid time
TIME_VALID,
// space matches perfectly and one is time agnostic
SPACE_MATCH,
// one is both time and space agnostic so they match even though
// they have nothing in common
AGNOSTIC_MATCH;
}
/**
* Given the result of a match this will pull out the unique SpaceAndTime
* objects that matched from the second Collection passed to match.
*
* @param matchResults
* @return
*/
public static Set<TimeAndSpace> getAll2(
Map<TimeAndSpace, MatchResult> matchResults) {
Set<TimeAndSpace> result = new HashSet<TimeAndSpace>(
matchResults.size());
for (MatchResult mr : matchResults.values()) {
result.add(mr.get2());
}
return result;
}
/**
* Given the result of a match this will pull out the unique SpaceAndTime
* objects that matched from the first Collection passed to match.
*
* @param matchResults
* @return
*/
public static Set<TimeAndSpace> getAll1(
Map<TimeAndSpace, MatchResult> matchResults) {
Set<TimeAndSpace> result = new HashSet<TimeAndSpace>(
matchResults.size());
for (MatchResult mr : matchResults.values()) {
result.add(mr.get1());
}
return result;
}
}

View file

@ -20,15 +20,14 @@
package com.raytheon.uf.viz.derivparam.tree;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
@ -50,16 +49,16 @@ import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
* @author bsteffen
* @version 1.0
*/
public abstract class AbstractAliasLevelNode extends AbstractDerivedLevelNode {
public abstract class AbstractAliasLevelNode extends AbstractDerivedDataNode {
protected AbstractRequestableLevelNode sourceNode;
protected AbstractRequestableNode sourceNode;
public AbstractAliasLevelNode(AbstractAliasLevelNode that) {
super(that);
this.sourceNode = that.sourceNode;
}
public AbstractAliasLevelNode(AbstractRequestableLevelNode sourceNode,
public AbstractAliasLevelNode(AbstractRequestableNode sourceNode,
DerivParamDesc desc, DerivParamMethod method, String modelName,
Level level) {
super(sourceNode, desc, method, modelName);
@ -67,32 +66,6 @@ public abstract class AbstractAliasLevelNode extends AbstractDerivedLevelNode {
setLevel(level);
}
@Override
public Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
throws VizException {
return sourceNode.timeQuery(originalRequest, latestOnly, cache,
latestOnlyCache);
}
@Override
public boolean isTimeAgnostic() {
return sourceNode.isTimeAgnostic();
}
@Override
public Map<String, RequestConstraint> getRequestConstraintMap() {
// TODO Auto-generated method stub
return sourceNode.getRequestConstraintMap();
}
@Override
public boolean hasRequestConstraints() {
return sourceNode.hasRequestConstraints();
}
@Override
public List<Dependency> getDependencies() {
return Arrays.asList(new Dependency(sourceNode, 0));
@ -134,4 +107,19 @@ public abstract class AbstractAliasLevelNode extends AbstractDerivedLevelNode {
return true;
}
@Override
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
return availability.get(sourceNode);
}
@Override
public Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> times) {
Map<AbstractRequestableNode, Set<TimeAndSpace>> result = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
result.put(sourceNode, times);
return result;
}
}

View file

@ -0,0 +1,129 @@
/**
* 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.derivparam.tree;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.derivparam.tree.LevelNode;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 10, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public abstract class AbstractBaseDataNode extends AbstractRequestableNode {
public AbstractBaseDataNode() {
super();
}
public AbstractBaseDataNode(Level level) {
super(level);
}
public AbstractBaseDataNode(LevelNode that) {
super(that);
}
/**
* Optional method to provide a request to the AvailabilityContainer so that
* it can bulk all requests to edex to save time. The result of the request
* will be passed to getAvailability. If the return value is null then the
* response passed to getAvailability will be null also.
*
* @param originalConstraints
* the original constraints passed to the data cube container
*
* @return
*/
public abstract DbQueryRequest getAvailabilityRequest();
/**
* Optional method to provide a request to the DataContainer so that it can
* bulk all requests to edex to save time. The result of the request will be
* passed to getData. If the return value is null then the response passed
* to getData will be null also.
*
*
* @param originalConstraints
* the original constraints passed to the data cube container
* @param availability
* the TimeAndSpace objects where data is being requested
* @return
*/
public abstract DbQueryRequest getDataRequest(
Map<String, RequestConstraint> originalConstraints,
Set<TimeAndSpace> availability);
/**
* Determine where and when data is available for this node.
*
* @param originalConstraints
* the original constraints passed to the data cube container
* @param response
* if getAvailabilityRequest() returned a request then this will
* have the response to that request.
* @return the TimeAndSpace when this node has available data.
* @throws VizException
*/
public abstract Set<TimeAndSpace> getAvailability(Object response)
throws VizException;
/**
* Get data from this node.
*
* @param originalConstraints
* the original constraints passed to the data cube container
* @param availability
* the TimeAndSpace objects where data is being requested
* @param response
* response to the server request returned by getDataRequest.
* @return
*/
public abstract Set<AbstractRequestableData> getData(
Map<String, RequestConstraint> orignalConstraints,
Set<TimeAndSpace> availability, Object response)
throws VizException;
@Override
public boolean isConstant() {
return false;
}
}

View file

@ -20,26 +20,20 @@
package com.raytheon.uf.viz.derivparam.tree;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.CatalogQuery;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.catalog.ScriptCreator;
import com.raytheon.uf.viz.core.comm.Loader;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.data.CubeRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpaceMatcher;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpaceMatcher.MatchResult;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
@ -66,9 +60,9 @@ import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
* @author bsteffen
* @version 1.0
*/
public abstract class AbstractCubeLevelNode extends AbstractDerivedLevelNode {
public abstract class AbstractCubeLevelNode extends AbstractDerivedDataNode {
protected List<CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode>> levels;
protected List<CubeLevel<AbstractRequestableNode, AbstractRequestableNode>> levels;
public AbstractCubeLevelNode(AbstractCubeLevelNode that) {
super(that);
@ -77,7 +71,7 @@ public abstract class AbstractCubeLevelNode extends AbstractDerivedLevelNode {
}
public AbstractCubeLevelNode(
List<CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode>> levels,
List<CubeLevel<AbstractRequestableNode, AbstractRequestableNode>> levels,
String modelName) {
this.levels = levels;
this.modelName = modelName;
@ -87,7 +81,7 @@ public abstract class AbstractCubeLevelNode extends AbstractDerivedLevelNode {
public AbstractCubeLevelNode(
Level level,
String modelName,
List<CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode>> levels) {
List<CubeLevel<AbstractRequestableNode, AbstractRequestableNode>> levels) {
this.setLevel(level);
this.levels = levels;
this.modelName = modelName;
@ -99,7 +93,7 @@ public abstract class AbstractCubeLevelNode extends AbstractDerivedLevelNode {
DerivParamDesc desc,
DerivParamMethod method,
String modelName,
List<CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode>> levels) {
List<CubeLevel<AbstractRequestableNode, AbstractRequestableNode>> levels) {
super(level, desc, method, modelName);
this.levels = levels;
this.setValue("3D");
@ -111,90 +105,68 @@ public abstract class AbstractCubeLevelNode extends AbstractDerivedLevelNode {
}
@Override
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
public Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> availability) throws VizException {
Map<AbstractRequestableNode, Set<TimeAndSpace>> result = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
for (CubeLevel<AbstractRequestableNode, AbstractRequestableNode> level : levels) {
result.put(level.getParam(), availability);
result.put(level.getPressure(), availability);
}
return result;
}
@Override
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
List<AbstractRequestableLevelNode> requests = new ArrayList<AbstractRequestableLevelNode>(
levels.size());
List<AbstractRequestableLevelNode> timeAgnosticRequests = new ArrayList<AbstractRequestableLevelNode>();
List<AbstractRequestableData> rawRecords = new ArrayList<AbstractRequestableData>(
levels.size());
List<AbstractRequestableData> timeAgnosticRecords = new ArrayList<AbstractRequestableData>();
for (CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode> level : levels) {
AbstractRequestableLevelNode node = level.getParam();
if (cache.containsKey(node)) {
List<AbstractRequestableData> cachedRecords = cache.get(node);
if (node.isTimeAgnostic()) {
timeAgnosticRecords.addAll(cachedRecords);
} else {
boolean foundMissingTime = false;
Set<DataTime> selectedTimes = new HashSet<DataTime>(
Arrays.asList(property.getSelectedEntryTime()));
for (AbstractRequestableData cRec : cachedRecords) {
if (!selectedTimes.contains(cRec.getDataTime())) {
foundMissingTime = true;
break;
}
}
if (foundMissingTime) {
requests.add(node);
} else {
rawRecords.addAll(cachedRecords);
}
}
} else {
if (node.isTimeAgnostic()) {
timeAgnosticRequests.add(node);
} else {
requests.add(node);
Map<TimeAndSpace, List<AbstractRequestableData>> paramMap = new HashMap<TimeAndSpace, List<AbstractRequestableData>>();
Map<TimeAndSpace, List<AbstractRequestableData>> presMap = new HashMap<TimeAndSpace, List<AbstractRequestableData>>();
for (CubeLevel<AbstractRequestableNode, AbstractRequestableNode> level : levels) {
Set<AbstractRequestableData> paramRecs = dependencyData.get(level
.getParam());
for (AbstractRequestableData paramRec : paramRecs) {
TimeAndSpace ast = paramRec.getTimeAndSpace();
List<AbstractRequestableData> paramList = paramMap.get(ast);
if (paramList == null) {
paramList = new ArrayList<AbstractRequestableData>();
paramMap.put(ast, paramList);
}
paramList.add(paramRec);
}
}
retrieveRecords(requests, property, timeOut, cache, rawRecords);
retrieveRecords(timeAgnosticRequests, property, timeOut, cache,
timeAgnosticRecords);
Map<DataTime, CubeRequestableData> bins = new HashMap<DataTime, CubeRequestableData>(
(int) (property.getSelectedEntryTime().length * 1.3));
processRecords(rawRecords, property, true, false, bins);
processRecords(timeAgnosticRecords, property, true, true, bins);
requests.clear();
timeAgnosticRequests.clear();
rawRecords.clear();
timeAgnosticRecords.clear();
for (CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode> level : levels) {
AbstractRequestableLevelNode node = level.getPressure();
if (cache.containsKey(node)) {
List<AbstractRequestableData> cachedRecords = cache.get(node);
if (node.isTimeAgnostic()) {
timeAgnosticRecords.addAll(cachedRecords);
} else {
rawRecords.addAll(cachedRecords);
}
} else {
if (node.isTimeAgnostic()) {
timeAgnosticRequests.add(node);
} else {
requests.add(node);
Set<AbstractRequestableData> presRecs = dependencyData.get(level
.getPressure());
for (AbstractRequestableData presRec : presRecs) {
TimeAndSpace ast = presRec.getTimeAndSpace();
List<AbstractRequestableData> presList = presMap.get(ast);
if (presList == null) {
presList = new ArrayList<AbstractRequestableData>();
presMap.put(ast, presList);
}
presList.add(presRec);
}
}
retrieveRecords(requests, property, timeOut, cache, rawRecords);
retrieveRecords(timeAgnosticRequests, property, timeOut, cache,
timeAgnosticRecords);
processRecords(rawRecords, property, false, false, bins);
processRecords(timeAgnosticRecords, property, false, true, bins);
List<AbstractRequestableData> records = new ArrayList<AbstractRequestableData>(
bins.size());
for (Entry<DataTime, CubeRequestableData> entry : bins.entrySet()) {
CubeRequestableData record = entry.getValue();
}
Map<TimeAndSpace, MatchResult> matches = new TimeAndSpaceMatcher()
.match(paramMap.keySet(), presMap.keySet());
Set<AbstractRequestableData> records = new HashSet<AbstractRequestableData>();
for (Entry<TimeAndSpace, MatchResult> match : matches.entrySet()) {
List<AbstractRequestableData> paramList = paramMap.get(match
.getValue().get1());
CubeRequestableData record = new CubeRequestableData(
paramList.get(0));
for (AbstractRequestableData paramRec : paramList) {
record.addParam(paramRec);
}
List<AbstractRequestableData> presList = presMap.get(match
.getValue().get2());
for (AbstractRequestableData presRec : presList) {
record.addPressure(presRec);
}
record.validate();
if (record.size() >= 2) {
record.setDataTime(entry.getKey());
record.setDataTime(match.getKey().getTime());
record.setSpace(match.getKey().getSpace());
modifyRequest(record);
records.add(record);
}
@ -202,183 +174,25 @@ public abstract class AbstractCubeLevelNode extends AbstractDerivedLevelNode {
return records;
}
private void retrieveRecords(
List<AbstractRequestableLevelNode> requests,
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache,
List<AbstractRequestableData> retrievedRecords) throws VizException {
retrievedRecords.addAll(mergedGetData(merge(requests), property,
timeOut));
for (AbstractRequestableLevelNode request : requests) {
retrievedRecords.addAll(request.getData(property, timeOut, cache));
}
}
@Override
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
// things in one are available for one level
Set<TimeAndSpace> one = new HashSet<TimeAndSpace>();
// things in two are available for two levels.
Set<TimeAndSpace> two = new HashSet<TimeAndSpace>();
private void processRecords(List<AbstractRequestableData> records,
LayerProperty property, boolean isParam, boolean isTimeAgnostic,
Map<DataTime, CubeRequestableData> bins) {
DataTime[] keys = new DataTime[1];
if (isTimeAgnostic) {
keys = property.getSelectedEntryTime();
}
for (AbstractRequestableData record : records) {
if (!isTimeAgnostic) {
keys[0] = record.getDataTime();
}
for (DataTime dt : keys) {
if (dt != null) {
CubeRequestableData bin = bins.get(dt);
if (bin == null) {
bin = new CubeRequestableData(record);
bins.put(dt, bin);
}
if (isParam) {
bin.addParam(record);
} else {
bin.addPressure(record);
}
for (CubeLevel<AbstractRequestableNode, AbstractRequestableNode> level : levels) {
for (TimeAndSpace time : availability.get(level.getParam())) {
if (one.contains(time)) {
two.add(time);
} else {
one.add(time);
}
}
}
}
@Override
public boolean isTimeAgnostic() {
boolean timeAgnostic = true;
for (CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode> level : levels) {
if (!level.getPressure().isTimeAgnostic()
|| !level.getParam().isTimeAgnostic()) {
timeAgnostic = false;
break;
}
}
return timeAgnostic;
}
/**
* Perform any filtering on the requestContraintsToFilter based on the
* baseRequestConstraints.
*
* @param baseRequestConstraints
* @param requestContraintsToFilter
*/
protected abstract void filter(
Map<String, RequestConstraint> baseRequestConstraints,
Map<String, RequestConstraint> requestContraintsToFilter);
@Override
public Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
throws VizException {
Set<DataTime> results = new HashSet<DataTime>();
List<AbstractRequestableLevelNode> requests = new ArrayList<AbstractRequestableLevelNode>(
levels.size() * 2);
for (CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode> level : levels) {
AbstractRequestableLevelNode node = level.getPressure();
if (cache.containsKey(node)) {
results.addAll(cache.get(node));
} else if (!node.isTimeAgnostic()) {
requests.add(node);
}
node = level.getParam();
if (cache.containsKey(node)) {
results.addAll(cache.get(node));
} else if (!node.isTimeAgnostic()) {
requests.add(node);
}
}
if (requests.size() == 0 && results.size() == 0) {
return TIME_AGNOSTIC;
}
results.addAll(mergedTimeQuery(merge(requests), latestOnly));
for (AbstractRequestableLevelNode request : requests) {
results.addAll(request.timeQuery(originalRequest, latestOnly,
cache, latestOnlyCache));
}
return results;
}
/**
* A merged time query performs a single time query from multiple requests
* when possible and removes those requests from the list.
*
* @param requests
* @param latestOnly
* @return
* @throws VizException
*/
protected Set<DataTime> mergedTimeQuery(
List<Map<String, RequestConstraint>> requests, boolean latestOnly)
throws VizException {
Set<DataTime> results = new HashSet<DataTime>();
for (Map<String, RequestConstraint> mergeMap : requests) {
DataTime[] resultsArr = CatalogQuery.performTimeQuery(mergeMap,
latestOnly, null);
if (resultsArr != null) {
for (int i = 0; i < resultsArr.length; i++) {
results.add(resultsArr[i]);
}
}
}
return results;
}
protected List<AbstractRequestableData> mergedGetData(
List<Map<String, RequestConstraint>> requests,
LayerProperty property, int timeOut) throws VizException {
List<Object> results = new ArrayList<Object>();
Map<String, RequestConstraint> oldQuery = property
.getEntryQueryParameters(false);
int numberOfImages = property.getNumberOfImages();
if (numberOfImages < 9999) {
property.setNumberOfImages(9999);
}
try {
for (Map<String, RequestConstraint> mergeMap : requests) {
Map<String, RequestConstraint> newQuery = new HashMap<String, RequestConstraint>(
mergeMap);
filter(oldQuery, newQuery);
property.setEntryQueryParameters(newQuery, false);
// TODO: replace
String scriptToExecute = ScriptCreator.createScript(property);
results.addAll(Loader.loadScripts(
new String[] { scriptToExecute }, timeOut));
}
} finally {
property.setNumberOfImages(numberOfImages);
property.setEntryQueryParameters(oldQuery, false);
}
return wrapRawRecord(results);
}
protected abstract List<AbstractRequestableData> wrapRawRecord(
List<Object> objs) throws VizException;
protected List<Map<String, RequestConstraint>> merge(
List<AbstractRequestableLevelNode> requests) {
List<Map<String, RequestConstraint>> mergeMaps = new ArrayList<Map<String, RequestConstraint>>(
requests.size());
Iterator<AbstractRequestableLevelNode> iter = requests.iterator();
while (iter.hasNext()) {
AbstractRequestableLevelNode request = iter.next();
if (request.hasRequestConstraints()) {
mergeMaps.add(request.getRequestConstraintMap());
iter.remove();
}
}
return mergeConstraints(mergeMaps);
return two;
}
/*
@ -390,7 +204,7 @@ public abstract class AbstractCubeLevelNode extends AbstractDerivedLevelNode {
public List<Dependency> getDependencies() {
List<Dependency> dependencies = new ArrayList<Dependency>(
levels.size() * 2);
for (CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode> level : levels) {
for (CubeLevel<AbstractRequestableNode, AbstractRequestableNode> level : levels) {
dependencies.add(new Dependency(level.getPressure(), 0));
dependencies.add(new Dependency(level.getParam(), 0));
}

View file

@ -24,15 +24,10 @@ import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.derivparam.tree.LevelNode;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
@ -55,8 +50,7 @@ import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
* @author bsteffen
* @version 1.0
*/
public abstract class AbstractDerivedLevelNode extends
AbstractRequestableLevelNode {
public abstract class AbstractDerivedDataNode extends AbstractRequestableNode {
protected DerivParamDesc desc;
@ -64,15 +58,15 @@ public abstract class AbstractDerivedLevelNode extends
protected String modelName;
public AbstractDerivedLevelNode() {
public AbstractDerivedDataNode() {
}
public AbstractDerivedLevelNode(Level level, DerivParamDesc desc,
public AbstractDerivedDataNode(Level level, DerivParamDesc desc,
String modelName) {
this(level, desc, null, modelName);
}
public AbstractDerivedLevelNode(Level level, DerivParamDesc desc,
public AbstractDerivedDataNode(Level level, DerivParamDesc desc,
DerivParamMethod method, String modelName) {
super(level);
this.desc = desc;
@ -80,7 +74,7 @@ public abstract class AbstractDerivedLevelNode extends
this.modelName = modelName;
}
public AbstractDerivedLevelNode(LevelNode that, DerivParamDesc desc,
public AbstractDerivedDataNode(LevelNode that, DerivParamDesc desc,
DerivParamMethod method, String modelName) {
super(that);
this.desc = desc;
@ -88,7 +82,7 @@ public abstract class AbstractDerivedLevelNode extends
this.modelName = modelName;
}
public AbstractDerivedLevelNode(AbstractDerivedLevelNode that) {
public AbstractDerivedDataNode(AbstractDerivedDataNode that) {
super(that);
this.desc = that.desc;
this.method = that.method;
@ -133,16 +127,6 @@ public abstract class AbstractDerivedLevelNode extends
this.method = method;
}
@Override
public Map<String, RequestConstraint> getRequestConstraintMap() {
return null;
}
@Override
public boolean hasRequestConstraints() {
return false;
}
/**
* Sets the vector, abbreviation, name, unit, and level to match the desc
* and level in this node
@ -191,7 +175,7 @@ public abstract class AbstractDerivedLevelNode extends
return false;
if (getClass() != obj.getClass())
return false;
AbstractDerivedLevelNode other = (AbstractDerivedLevelNode) obj;
AbstractDerivedDataNode other = (AbstractDerivedDataNode) obj;
if (desc == null) {
if (other.desc != null)
return false;
@ -211,43 +195,54 @@ public abstract class AbstractDerivedLevelNode extends
}
/**
* Should only be called on final nodes, not derived nodes.
* Given the availability of all dependency nodes determine when this node
* is available.
*
* @param availability
* @return
* @throws VizException
*/
@Override
protected DbQueryRequest getDataQueryInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
throw new UnsupportedOperationException(
"Derived nodes do not support retrieving data query, call on dependencies");
}
public abstract Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException;
/**
* Should only be called on final nodes, not derived nodes.
* If this node has dependency on other nodes then this method should return
* what data is needed for the dependencies to get data from this node for
* the provided availability.
*
* @param availability
* @return
*/
@Override
public void setDataQueryResults(
DbQueryResponse queryResponse,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
throw new UnsupportedOperationException(
"Derived nodes do not support processing data query, call on dependencies");
}
public abstract Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> availability) throws VizException;
/**
* Get data from this node.
*
* @param availability
* The time and spatial area where data is needed
* @return
*/
public abstract Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException;
public abstract List<Dependency> getDependencies();
@Override
protected List<AbstractRequestableData> processDataQueryResults(
DbQueryResponse queryResponse) throws VizException {
throw new UnsupportedOperationException(
"Derived nodes do not support processing data query, call on dependencies");
}
@Override
protected TimeQueryRequest getTimeQueryInternal(
TimeQueryRequest originalRequest, boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache)
throws VizException {
throw new UnsupportedOperationException(
"Derived nodes do not support retrieving time query, call on dependencies");
public boolean isConstant() {
List<Dependency> dependencies = getDependencies();
if (dependencies.isEmpty()) {
return false;
}
for (Dependency dep : getDependencies()) {
if (!dep.node.isConstant()) {
return false;
}
}
// All dependencies must be constant
return true;
}
}

View file

@ -1,421 +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.derivparam.tree;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.derivparam.tree.LevelNode;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
/**
*
* The base level node for Cave, each Level Node should be able to handle time
* queries and metadata requests. This class attempts to handle
* caching(currently very limited) for all subclasses.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 19, 2010 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public abstract class AbstractRequestableLevelNode extends LevelNode {
@SuppressWarnings("unchecked")
public static final Set<DataTime> TIME_AGNOSTIC = Collections.EMPTY_SET;
public static class Dependency {
public Dependency(AbstractRequestableLevelNode node, int timeOffset) {
super();
this.node = node;
this.timeOffset = timeOffset;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((node == null) ? 0 : node.hashCode());
result = prime * result + timeOffset;
return result;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dependency other = (Dependency) obj;
if (node == null) {
if (other.node != null)
return false;
} else if (!node.equals(other.node))
return false;
if (timeOffset != other.timeOffset)
return false;
return true;
}
public AbstractRequestableLevelNode node;
public int timeOffset;
}
public AbstractRequestableLevelNode() {
}
public AbstractRequestableLevelNode(Level level) {
super(level);
}
public AbstractRequestableLevelNode(LevelNode that) {
super(that);
}
public List<AbstractRequestableData> getData(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
DataTime[] origTimes = property.getSelectedEntryTime();
List<AbstractRequestableData> rval = new ArrayList<AbstractRequestableData>();
if (cache != null && cache.containsKey(this) && origTimes != null) {
List<AbstractRequestableData> cachedRecords = cache.get(this);
List<DataTime> selectedTimes = Arrays.asList(origTimes);
List<DataTime> newTimes = new ArrayList<DataTime>(selectedTimes);
for (AbstractRequestableData record : cachedRecords) {
if (selectedTimes.contains(record.getDataTime())) {
rval.add(record);
newTimes.remove(record.getDataTime());
}
}
property.setSelectedEntryTimes(newTimes.toArray(new DataTime[0]));
}
if (origTimes == null || property.getSelectedEntryTime().length > 0) {
List<AbstractRequestableData> newRecords = getDataInternal(
property, timeOut, cache);
rval.addAll(newRecords);
List<AbstractRequestableData> cachedRecords = cache.get(this);
if (cachedRecords == null) {
cache.put(this, new ArrayList<AbstractRequestableData>(
newRecords));
} else {
cachedRecords.addAll(newRecords);
}
}
property.setSelectedEntryTimes(origTimes);
return rval;
}
public DbQueryRequest getDataQuery(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
DataTime[] origTimes = property.getSelectedEntryTime();
DbQueryRequest rval = null;
if (cache != null && cache.containsKey(this) && origTimes != null) {
List<AbstractRequestableData> cachedRecords = cache.get(this);
List<DataTime> selectedTimes = Arrays.asList(origTimes);
List<DataTime> newTimes = new ArrayList<DataTime>(selectedTimes);
for (AbstractRequestableData record : cachedRecords) {
if (selectedTimes.contains(record.getDataTime())) {
newTimes.remove(record.getDataTime());
}
}
property.setSelectedEntryTimes(newTimes
.toArray(new DataTime[newTimes.size()]));
}
if (origTimes == null || property.getSelectedEntryTime().length > 0) {
rval = getDataQueryInternal(property, timeOut, cache);
}
property.setSelectedEntryTimes(origTimes);
return rval;
}
public void setDataQueryResults(
DbQueryResponse queryResponse,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
// need transform method
List<AbstractRequestableData> records = processDataQueryResults(queryResponse);
if (records == null || records.size() > 0) {
List<AbstractRequestableData> cachedRecords = cache.get(this);
if (cachedRecords == null) {
cache.put(this, records);
} else {
// dups?
cachedRecords.addAll(records);
}
}
}
protected abstract List<AbstractRequestableData> processDataQueryResults(
DbQueryResponse queryResponse) throws VizException;
public Set<DataTime> timeQuery(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
throws VizException {
if (cache != null && cache.containsKey(this)) {
return cache.get(this);
} else if (latestOnly && latestOnlyCache.containsKey(this)) {
return latestOnlyCache.get(this);
}
Set<DataTime> results = timeQueryInternal(originalRequest, latestOnly,
cache, latestOnlyCache);
if (cache != null && !latestOnly) {
cache.put(this, results);
}
return results;
}
public TimeQueryRequest getTimeQuery(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
throws VizException {
if (cache != null && cache.containsKey(this)) {
return null;
} else if (latestOnly && latestOnlyCache.containsKey(this)) {
return null;
}
return getTimeQueryInternal(originalRequest, latestOnly, cache);
}
public void setTimeQueryResults(boolean latestOnly,
List<DataTime> queryResponse,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
throws VizException {
// perform any node specific processing
processTimeQueryResults(latestOnly, queryResponse);
if (latestOnly) {
Set<DataTime> cachedRecords = latestOnlyCache.get(this);
if (cachedRecords == null) {
latestOnlyCache.put(this, new HashSet<DataTime>(queryResponse));
} else {
cachedRecords.addAll(queryResponse);
}
} else {
Set<DataTime> cachedRecords = cache.get(this);
if (cachedRecords == null) {
cache.put(this, new HashSet<DataTime>(queryResponse));
} else {
cachedRecords.addAll(queryResponse);
}
}
}
protected void processTimeQueryResults(boolean latestOnly,
List<DataTime> queryResponse) throws VizException {
// default has no internal processing to add
}
public abstract List<Dependency> getDependencies();
public abstract boolean isTimeAgnostic();
public abstract boolean hasRequestConstraints();
public abstract Map<String, RequestConstraint> getRequestConstraintMap();
public boolean isConstant() {
List<Dependency> dependencies = getDependencies();
if (dependencies.isEmpty()) {
return false;
}
for (Dependency dep : getDependencies()) {
if (!dep.node.isConstant()) {
return false;
}
}
// All dependencies must be constant
return true;
}
/**
* Takes the list of constraintMaps and merges the constraint maps that
* different by only one key into a new list of constraint maps. EX: 5
* RequestConstraint Maps for GFS40 Temp on 5 MB levels will be consolidated
* into a single RequestConstraint Map using an IN List for the MB levels.
*
* @param constraintMaps
* @return
*/
public List<Map<String, RequestConstraint>> mergeConstraints(
List<Map<String, RequestConstraint>> constraintMaps) {
List<Map<String, RequestConstraint>> rval = new ArrayList<Map<String, RequestConstraint>>();
if (constraintMaps != null && constraintMaps.size() > 0) {
List<String> mergeKeyList = new ArrayList<String>();
for (Map<String, RequestConstraint> constraintMap : constraintMaps) {
boolean merged = false;
int index = 0;
MERGE_MAP_LOOP: for (index = 0; index < rval.size(); index++) {
Map<String, RequestConstraint> mergeMap = rval.get(index);
// maps must be of same size
if (mergeMap.size() == constraintMap.size()) {
String mergeKey = mergeKeyList.get(index);
if (mergeKey != null) {
// determine if it matches map except for uniqueKey
for (String key : mergeMap.keySet()) {
boolean isUniqueKey = mergeKey.equals(key);
boolean constraintEquals = mergeMap.get(key)
.equals(constraintMap.get(key));
if (!constraintEquals && !isUniqueKey) {
continue MERGE_MAP_LOOP;
}
}
// map differs except for key
boolean constraintMerged = mergeMap.get(mergeKey)
.merge(constraintMap.get(mergeKey));
if (!constraintMerged) {
continue MERGE_MAP_LOOP;
} else {
merged = true;
break MERGE_MAP_LOOP;
}
} else {
// current mergeMap has never been merged with,
// double check that only one key is different
// between maps
for (String key : mergeMap.keySet()) {
if (!mergeMap.get(key).equals(
constraintMap.get(key))) {
if (mergeKey == null) {
// possible merge key, continue checking
// map
mergeKey = key;
} else {
// two merge keys found, go to next
// merge map
continue MERGE_MAP_LOOP;
}
}
}
merged = true;
// found mergeKey, add to mergeKeyList. If mergeKey
// still being null is only possible of mergeMap and
// constraintMap contain the exact same constraints,
// consider them merged
if (mergeKey != null) {
mergeKeyList.set(index, mergeKey);
}
break MERGE_MAP_LOOP;
}
} // maps same size check
} // MERGE_MAP_LOOP
if (!merged) {
Map<String, RequestConstraint> mergeMap = new HashMap<String, RequestConstraint>();
// deep copy the map
for (Map.Entry<String, RequestConstraint> entry : constraintMap
.entrySet()) {
mergeMap.put(entry.getKey(), entry.getValue().clone());
}
rval.add(mergeMap);
mergeKeyList.add(null);
}
}
}
return rval;
}
protected abstract Set<DataTime> timeQueryInternal(
TimeQueryRequest originalRequest, boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
throws VizException;
protected abstract TimeQueryRequest getTimeQueryInternal(
TimeQueryRequest originalRequest, boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache)
throws VizException;
protected abstract List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException;
protected abstract DbQueryRequest getDataQueryInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException;
protected Set<DataTime> timeQuery(TimeQueryRequest originalRequest,
boolean latestOnly) throws VizException {
return timeQuery(originalRequest, latestOnly,
new HashMap<AbstractRequestableLevelNode, Set<DataTime>>(),
new HashMap<AbstractRequestableLevelNode, Set<DataTime>>());
}
}

View file

@ -0,0 +1,109 @@
/**
* 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.derivparam.tree;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.derivparam.tree.LevelNode;
/**
*
* The base level node for Cave, each Level Node should be able to handle time
* queries and metadata requests. This class attempts to handle
* caching(currently very limited) for all subclasses.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 19, 2010 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public abstract class AbstractRequestableNode extends LevelNode {
public static class Dependency {
public Dependency(AbstractRequestableNode node, int timeOffset) {
super();
this.node = node;
this.timeOffset = timeOffset;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((node == null) ? 0 : node.hashCode());
result = prime * result + timeOffset;
return result;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dependency other = (Dependency) obj;
if (node == null) {
if (other.node != null)
return false;
} else if (!node.equals(other.node))
return false;
if (timeOffset != other.timeOffset)
return false;
return true;
}
public AbstractRequestableNode node;
public int timeOffset;
}
public AbstractRequestableNode() {
}
public AbstractRequestableNode(Level level) {
super(level);
}
public AbstractRequestableNode(LevelNode that) {
super(that);
}
public abstract boolean isConstant();
}

View file

@ -19,15 +19,15 @@
**/
package com.raytheon.uf.viz.derivparam.tree;
import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.data.AliasRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
@ -56,20 +56,19 @@ public class AliasLevelNode extends AbstractAliasLevelNode {
super(that);
}
public AliasLevelNode(AbstractRequestableLevelNode sourceNode,
public AliasLevelNode(AbstractRequestableNode sourceNode,
DerivParamDesc desc, DerivParamMethod method, String modelName,
Level level) {
super(sourceNode, desc, method, modelName, level);
}
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
@Override
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
List<AbstractRequestableData> origs = sourceNode.getData(property,
timeOut, cache);
List<AbstractRequestableData> results = new ArrayList<AbstractRequestableData>(
Set<AbstractRequestableData> origs = dependencyData.get(sourceNode);
Set<AbstractRequestableData> results = new HashSet<AbstractRequestableData>(
origs.size());
for (AbstractRequestableData orig : origs) {
AbstractRequestableData result = new AliasRequestableData(orig);

View file

@ -26,13 +26,11 @@ import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.data.AggregateRequestableData;
import com.raytheon.uf.viz.derivparam.data.DerivedRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivedParameterRequest;
@ -64,19 +62,19 @@ public class CompositeAverageLevelNode extends UnionLevelNode {
}
public CompositeAverageLevelNode(Level level, DerivParamDesc desc,
String modelName, List<AbstractRequestableLevelNode> nodes) {
String modelName, List<AbstractRequestableNode> nodes) {
super(level, desc, null, modelName, nodes);
}
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
@Override
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
List<AbstractRequestableData> result = new ArrayList<AbstractRequestableData>();
Set<AbstractRequestableData> result = new HashSet<AbstractRequestableData>();
for (AbstractRequestableData record : super.getDataInternal(property,
timeOut, cache)) {
for (AbstractRequestableData record : super.getData(availability,
dependencyData)) {
AggregateRequestableData aRec = (AggregateRequestableData) record;
if (aRec.getSourceRecords().size() == nodes.size()) {
DerivedParameterRequest request = new DerivedParameterRequest();
@ -95,33 +93,22 @@ public class CompositeAverageLevelNode extends UnionLevelNode {
return result;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.derivparam.tree.UnionLevelNode#timeQueryInternal(
* boolean, java.util.Map)
*/
@Override
public Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
// We should only have times if all our nodes have times
Set<DataTime> results = TIME_AGNOSTIC;
Set<TimeAndSpace> results = null;
List<AbstractRequestableLevelNode> requests = new ArrayList<AbstractRequestableLevelNode>(
List<AbstractRequestableNode> requests = new ArrayList<AbstractRequestableNode>(
nodes);
for (AbstractRequestableLevelNode request : requests) {
for (AbstractRequestableNode request : requests) {
// Do not request just latest only because if two nodes have
// different latests than this will return no times
Set<DataTime> times = request.timeQuery(originalRequest, false,
cache, latestOnlyCache);
if (times == TIME_AGNOSTIC) {
Set<TimeAndSpace> times = availability.get(request);
if (times == null) {
continue;
} else if (results == TIME_AGNOSTIC) {
results = new HashSet<DataTime>(times);
} else if (results == null) {
results = new HashSet<TimeAndSpace>(times);
} else {
results.retainAll(times);
}

View file

@ -22,6 +22,7 @@ package com.raytheon.uf.viz.derivparam.tree;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@ -32,14 +33,15 @@ import java.util.Map.Entry;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.DataTime.FLAG;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.data.AliasRequestableData;
import com.raytheon.uf.viz.derivparam.data.DerivedRequestableData;
import com.raytheon.uf.viz.derivparam.inv.AvailabilityContainer;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpaceMatcher;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpaceMatcher.MatchResult;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamField;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
@ -64,19 +66,19 @@ import com.raytheon.uf.viz.derivparam.library.IDerivParamField;
* @version 1.0
*/
public class DerivedLevelNode extends AbstractDerivedLevelNode {
public class DerivedLevelNode extends AbstractDerivedDataNode {
private static final int TIME_QUERY_CACHE_TIME = 30000;
private Map<IDerivParamField, AbstractRequestableData> fieldStaticData = null;
private Map<DerivParamField, AbstractRequestableLevelNode> fields = null;
private Map<DerivParamField, AbstractRequestableNode> fields = null;
/**
* Time cache should be reset every time a time query is performed and then
* it can be used to correlate times when requesting data.
*/
private Map<DerivParamField, Set<DataTime>> timeCache = null;
private Map<DerivParamField, Set<TimeAndSpace>> availCache = null;
private long lastTimeQuery = 0;
@ -91,7 +93,7 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
public DerivedLevelNode(DerivedLevelNode that) {
super(that);
if (that.fields != null) {
fields = new HashMap<DerivParamField, AbstractRequestableLevelNode>(
fields = new HashMap<DerivParamField, AbstractRequestableNode>(
that.fields);
}
if (that.fieldStaticData != null) {
@ -111,7 +113,7 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
/**
* @return the fields
*/
public Map<DerivParamField, AbstractRequestableLevelNode> getFields() {
public Map<DerivParamField, AbstractRequestableNode> getFields() {
return fields;
}
@ -130,10 +132,9 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
this.fieldStaticData.put(field, requestableData);
}
public void putField(DerivParamField field,
AbstractRequestableLevelNode object) {
public void putField(DerivParamField field, AbstractRequestableNode object) {
if (fields == null) {
fields = new HashMap<DerivParamField, AbstractRequestableLevelNode>();
fields = new HashMap<DerivParamField, AbstractRequestableNode>();
}
this.fields.put(field, object);
}
@ -149,99 +150,75 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
return getFieldsSize() == method.getFields().size();
}
private TimeAndSpaceMatcher getMatcher() {
TimeAndSpaceMatcher matcher = new TimeAndSpaceMatcher();
matcher.setIgnoreRange(true);
if (method.isFtime()) {
matcher.setMatchValid(false);
} else {
matcher.setMatchValid(true);
}
return matcher;
}
private Map<TimeAndSpace, TimeAndSpace> shiftTime(DerivParamField field,
Set<TimeAndSpace> dataTimes) {
int timeShift = getDTimeInSeconds(field);
if (timeShift != 0) {
Map<TimeAndSpace, TimeAndSpace> result = new HashMap<TimeAndSpace, TimeAndSpace>();
for (TimeAndSpace t : dataTimes) {
if (t.isTimeAgnostic()) {
result.put(t, t);
} else {
DataTime time = t.getTime();
long rTime = time.getRefTime().getTime();
int fTime = time.getFcstTime();
// Shift valid time back rather than having a
// negative forecast time.
fTime -= timeShift;
while (method.isDtime() && fTime < 0) {
rTime -= dt * 1000;
fTime += dt;
}
time = new DataTime(new Date(rTime), fTime);
result.put(new TimeAndSpace(time, t.getSpace()), t);
}
}
return result;
}
return null;
}
@Override
public Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
this.lastTimeQuery = System.currentTimeMillis();
Map<DerivParamField, Set<DataTime>> timeCache = new HashMap<DerivParamField, Set<DataTime>>();
TimeAndSpaceMatcher matcher = getMatcher();
Map<DerivParamField, Set<TimeAndSpace>> availCache = new HashMap<DerivParamField, Set<TimeAndSpace>>();
// We have a derived parameter for the requested grid
Set<DataTime> availableDataTimes = null;
Set<TimeAndSpace> availableDataTimes = null;
if (fields == null) {
timeCache.put(null, TIME_AGNOSTIC);
this.timeCache = timeCache;
return TIME_AGNOSTIC;
availableDataTimes = AvailabilityContainer.AGNOSTIC_SET;
availCache.put(null, availableDataTimes);
this.availCache = availCache;
return availableDataTimes;
}
Collection<DerivParamField> fieldsKeys = fields.keySet();
if (method.isDtime()) {
// Attempt to use 0 time shift data first.
List<DerivParamField> fieldsList = new ArrayList<DerivParamField>(
fieldsKeys);
for (int i = 1; i < fieldsList.size(); i++) {
if (fieldsList.get(i).getTimeShift() == 0) {
fieldsList.set(i, fieldsList.set(0, fieldsList.get(i)));
}
}
fieldsKeys = fieldsList;
}
for (DerivParamField field : fieldsKeys) {
AbstractRequestableLevelNode node = fields.get(field);
Set<DataTime> queryDataTimes = node.timeQuery(originalRequest,
false, cache, latestOnlyCache);
timeCache.put(field, queryDataTimes);
if (queryDataTimes == TIME_AGNOSTIC) {
if (availableDataTimes == null) {
availableDataTimes = TIME_AGNOSTIC;
}
continue;
}
for (DerivParamField field : fields.keySet()) {
AbstractRequestableNode node = fields.get(field);
Set<TimeAndSpace> queryDataTimes = availability.get(node);
availCache.put(field, queryDataTimes);
if (queryDataTimes != null && queryDataTimes.size() > 0) {
if (availableDataTimes != null
&& availableDataTimes != TIME_AGNOSTIC) {
availableDataTimes.retainAll(timeMatch(availableDataTimes,
queryDataTimes, field).keySet());
} else {
// populate initial data times
if (method.isDtime()) {
// if dT required handle now
int dTimeInSeconds = getDTimeInSeconds(field);
if (dTimeInSeconds == -1) {
return new HashSet<DataTime>(0);
}
// handle valid time shift
availableDataTimes = new HashSet<DataTime>((64));
// generate all possible valid times
for (DataTime dataTime : queryDataTimes) {
if (field.getTimeShift() == 0) {
// Strip any validPeriodInfo
availableDataTimes.add(new DataTime(dataTime
.getRefTime(), dataTime.getFcstTime()));
} else {
availableDataTimes
.addAll(generatePossibleDataTimes(
dataTime, field));
}
}
} else if (method.isFtime()) {
// handle forecast time shift
availableDataTimes = new HashSet<DataTime>();
int fcstShift = field.getTimeShift();
for (DataTime dataTime : queryDataTimes) {
int fcstTime = dataTime.getFcstTime() - fcstShift;
if (fcstTime >= 0) {
availableDataTimes.add(new DataTime(dataTime
.getRefTime(), fcstTime));
}
}
} else {
availableDataTimes = new HashSet<DataTime>();
for (DataTime time : queryDataTimes) {
if (time.getUtilityFlags().contains(FLAG.FCST_USED))
availableDataTimes.add(new DataTime(time
.getRefTime(), time.getFcstTime()));
else
availableDataTimes.add(new DataTime(time
.getRefTime()));
}
}
Map<TimeAndSpace, TimeAndSpace> shiftMap = shiftTime(field,
queryDataTimes);
if (shiftMap != null) {
queryDataTimes = shiftMap.keySet();
}
if (availableDataTimes == null) {
availableDataTimes = AvailabilityContainer.AGNOSTIC_SET;
}
availableDataTimes = matcher.match(availableDataTimes,
queryDataTimes).keySet();
} else {
// no data for this query, clear times and return
availableDataTimes = null;
@ -254,71 +231,100 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
}// FIELD_LOOP
if (availableDataTimes != null) {
timeCache.put(null, availableDataTimes);
this.timeCache = timeCache;
availCache.put(null, availableDataTimes);
this.availCache = availCache;
} else {
timeCache = new HashMap<DerivParamField, Set<DataTime>>();
availableDataTimes = new HashSet<DataTime>(0);
timeCache.put(null, availableDataTimes);
this.timeCache = timeCache;
availCache = new HashMap<DerivParamField, Set<TimeAndSpace>>();
availableDataTimes = new HashSet<TimeAndSpace>(0);
availCache.put(null, availableDataTimes);
this.availCache = availCache;
}
return availableDataTimes;
}
@Override
public boolean isTimeAgnostic() {
boolean timeAgnostic = true;
for (AbstractRequestableLevelNode node : fields.values()) {
if (!node.isTimeAgnostic()) {
timeAgnostic = false;
break;
}
}
return timeAgnostic;
}
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
if (this.timeCache == null
public Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> availability) throws VizException {
if (this.availCache == null
|| this.lastTimeQuery + TIME_QUERY_CACHE_TIME < System
.currentTimeMillis()) {
this.timeQuery(null, false);
new AvailabilityContainer().getAvailability(this);
}
// keep a reference for scope of method
Map<DerivParamField, Set<DataTime>> myTimeCache = this.timeCache;
Set<DataTime> thisAvailableTimes = myTimeCache.get(null);
if (thisAvailableTimes == TIME_AGNOSTIC) {
thisAvailableTimes = new HashSet<DataTime>();
thisAvailableTimes.add(null);
} else {
if (property.getSelectedEntryTime() != null) {
thisAvailableTimes = new HashSet<DataTime>(thisAvailableTimes);
thisAvailableTimes.retainAll(Arrays.asList(property
.getSelectedEntryTime()));
TimeAndSpaceMatcher matcher = getMatcher();
Map<DerivParamField, Set<TimeAndSpace>> availCache = this.availCache;
availability = matcher.match(availability, availCache.get(null))
.keySet();
if (availability.isEmpty()) {
return Collections.emptyMap();
}
Map<AbstractRequestableNode, Set<TimeAndSpace>> result = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
if (fields != null) {
for (Entry<DerivParamField, AbstractRequestableNode> field : fields
.entrySet()) {
Set<TimeAndSpace> queryTimes = availCache.get(field.getKey());
Map<TimeAndSpace, TimeAndSpace> shiftMap = shiftTime(
field.getKey(), queryTimes);
if (shiftMap != null) {
queryTimes = shiftMap.keySet();
}
Set<TimeAndSpace> fieldResult = TimeAndSpaceMatcher
.getAll2(matcher.match(availability, queryTimes));
if (shiftMap != null) {
Set<TimeAndSpace> newFieldResult = new HashSet<TimeAndSpace>();
for (TimeAndSpace t : fieldResult) {
newFieldResult.add(shiftMap.get(t));
}
fieldResult = newFieldResult;
}
Set<TimeAndSpace> oldSet = result.put(field.getValue(),
fieldResult);
if (oldSet != null) {
fieldResult.addAll(oldSet);
}
}
}
Map<DataTime, DerivedParameterRequest> mapOfRequests = new HashMap<DataTime, DerivedParameterRequest>(
thisAvailableTimes.size());
List<DerivedRequestableData> initResponses = new ArrayList<DerivedRequestableData>(
thisAvailableTimes.size());
if (fieldStaticData != null) {
for (Entry<IDerivParamField, AbstractRequestableData> entry : fieldStaticData
.entrySet()) {
StaticDataLevelNode node = new StaticDataLevelNode(level, desc,
entry.getValue(), modelName);
result.put(node, AvailabilityContainer.AGNOSTIC_SET);
}
}
return result;
}
for (DataTime time : thisAvailableTimes) {
@Override
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
if (this.availCache == null
|| this.lastTimeQuery + TIME_QUERY_CACHE_TIME < System
.currentTimeMillis()) {
new AvailabilityContainer().getAvailability(this);
}
TimeAndSpaceMatcher matcher = getMatcher();
Map<DerivParamField, Set<TimeAndSpace>> availCache = this.availCache;
availability = matcher.match(availability, availCache.get(null))
.keySet();
Map<TimeAndSpace, DerivedParameterRequest> mapOfRequests = new HashMap<TimeAndSpace, DerivedParameterRequest>(
availability.size());
List<DerivedRequestableData> initResponses = new ArrayList<DerivedRequestableData>(
availability.size());
for (TimeAndSpace ast : availability) {
DerivedParameterRequest derivRequest = new DerivedParameterRequest();
DerivedRequestableData newRecord = new DerivedRequestableData(
derivRequest);
newRecord.setDataTime(time);
newRecord.setDataTime(ast.getTime());
newRecord.setSpace(ast.getSpace());
derivRequest.setParameterAbbreviation(desc.getAbbreviation());
derivRequest.setMethod(method.getName());
// get data time for this field
derivRequest.setBaseTime(time);
derivRequest.setBaseTime(ast.getTime());
initResponses.add(newRecord);
mapOfRequests.put(time, derivRequest);
mapOfRequests.put(ast, derivRequest);
}
for (IDerivParamField ifield : method.getFields()) {
@ -326,64 +332,48 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
AbstractRequestableData data = fieldStaticData.get(ifield);
if (ifield instanceof DerivParamField) {
data = checkFieldUnits((DerivParamField) ifield,
Arrays.asList(data)).get(0);
Arrays.asList(data)).iterator().next();
}
for (DerivedParameterRequest request : mapOfRequests.values()) {
request.addBaseParam(data);
}
} else if (fields != null && fields.containsKey(ifield)) {
DerivParamField field = (DerivParamField) ifield;
AbstractRequestableLevelNode fieldNode = fields.get(field);
Collection<DataTime> availableTimes = myTimeCache.get(field);
if (availableTimes == TIME_AGNOSTIC) {
List<AbstractRequestableData> responses = fieldNode
.getData(property, timeOut, cache);
responses = checkFieldUnits(field, responses);
for (DerivedParameterRequest request : mapOfRequests
.values()) {
for (AbstractRequestableData response : responses) {
if (response.getDataTime() == null
|| response.getDataTime().equals(
response.getDataTime())) {
request.addBaseParam(response);
break;
}
}
}
} else {
DataTime[] oldEntryTimes = property.getSelectedEntryTime();
Map<DataTime, DataTime> matchTimes = timeMatch(
mapOfRequests.keySet(), availableTimes, field);
Set<DataTime> newEntryTimes = new HashSet<DataTime>(
matchTimes.values());
property.setSelectedEntryTimes(newEntryTimes
.toArray(new DataTime[newEntryTimes.size()]));
List<AbstractRequestableData> responses = fieldNode
.getData(property, timeOut, cache);
property.setSelectedEntryTimes(oldEntryTimes);
responses = checkFieldUnits(field, responses);
Map<DataTime, AbstractRequestableData> responseMap = new HashMap<DataTime, AbstractRequestableData>();
for (AbstractRequestableData record : responses) {
responseMap.put(record.getDataTime(), record);
}
Iterator<Entry<DataTime, DerivedParameterRequest>> it = mapOfRequests
.entrySet().iterator();
while (it.hasNext()) {
Entry<DataTime, DerivedParameterRequest> entry = it
.next();
DataTime requestTime = matchTimes.get(entry.getKey());
AbstractRequestableData data = responseMap
.get(requestTime);
if (data != null) {
entry.getValue().addBaseParam(data);
} else {
it.remove();
}
}
AbstractRequestableNode fieldNode = fields.get(field);
Set<TimeAndSpace> fieldAvailability = availCache.get(field);
Map<TimeAndSpace, TimeAndSpace> shiftMap = shiftTime(field,
fieldAvailability);
if (shiftMap != null) {
fieldAvailability = shiftMap.keySet();
}
Map<TimeAndSpace, MatchResult> matchTimes = matcher.match(
availability, fieldAvailability);
Collection<AbstractRequestableData> responses = dependencyData
.get(fieldNode);
responses = checkFieldUnits(field, responses);
Map<TimeAndSpace, AbstractRequestableData> responseMap = new HashMap<TimeAndSpace, AbstractRequestableData>();
for (AbstractRequestableData record : responses) {
responseMap.put(record.getTimeAndSpace(), record);
}
Iterator<Entry<TimeAndSpace, DerivedParameterRequest>> it = mapOfRequests
.entrySet().iterator();
while (it.hasNext()) {
Entry<TimeAndSpace, DerivedParameterRequest> entry = it
.next();
TimeAndSpace requestTime = matchTimes.get(entry.getKey())
.get2();
if (shiftMap != null) {
requestTime = shiftMap.get(requestTime);
}
AbstractRequestableData data = responseMap.get(requestTime);
if (data != null) {
entry.getValue().addBaseParam(data);
} else {
it.remove();
}
}
} else {
throw new VizException("Error processing Derived parameter:"
+ desc.getAbbreviation() + ":" + method.getName() + ":"
@ -391,11 +381,17 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
}
}
List<AbstractRequestableData> finalResponses = new ArrayList<AbstractRequestableData>();
Set<AbstractRequestableData> finalResponses = new HashSet<AbstractRequestableData>();
for (DerivedRequestableData record : initResponses) {
if (record.getRequest().getBaseParams().size() == method
.getFields().size()) {
modifyRequest(record);
if (record.getLevel().getMasterLevel().getName().equals("BL")
&& record.getLevel().getLevelOneValueAsString()
.equals("0.0")
&& !record.getLevel().getLevelTwoValueAsString()
.equals("30.0"))
continue;
finalResponses.add(record);
}
@ -403,61 +399,6 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
return finalResponses;
}
/**
* Given a set of times to load, and the available times for a field
* generate a map from one to the other, taking into account dTime and fTime
*
* @param timesToLaod
* @param availableTimes
* @param field
* @return
*/
private Map<DataTime, DataTime> timeMatch(Collection<DataTime> timesToLaod,
Collection<DataTime> availableTimes, DerivParamField field) {
// First step is to sort the available times by valid time
Map<Long, Set<DataTime>> validMap = new HashMap<Long, Set<DataTime>>();
for (DataTime time : availableTimes) {
Long validTime = time.getMatchValid();
Set<DataTime> timeSet = validMap.get(validTime);
if (timeSet == null) {
timeSet = new HashSet<DataTime>();
validMap.put(validTime, timeSet);
}
timeSet.add(time);
}
// For each requested time we find the best available time
Map<DataTime, DataTime> results = new HashMap<DataTime, DataTime>();
int dTimeInSeconds = getDTimeInSeconds(field);
if (dTimeInSeconds == -1) {
return results;
}
for (DataTime entryTime : timesToLaod) {
Long validTime = entryTime.getMatchValid() + dTimeInSeconds * 1000;
if (!validMap.containsKey(validTime)) {
// This means we have no data for this field at this
// time
continue;
}
DataTime latest = null;
for (DataTime time : validMap.get(validTime)) {
if (time.getMatchRef() == entryTime.getMatchRef()) {
// Prefer a matching ref time
latest = time;
break;
} else if (!method.isFtime()
&& (latest == null || latest.getMatchRef() < time
.getMatchRef())) {
latest = time;
}
}
if (latest != null) {
results.put(entryTime, latest);
}
}
return results;
}
private int getDTimeInSeconds(DerivParamField field) {
int dTimeInSeconds = 0;
@ -474,9 +415,9 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
return dTimeInSeconds;
}
private List<AbstractRequestableData> checkFieldUnits(
DerivParamField field, List<AbstractRequestableData> records) {
List<AbstractRequestableData> newRecs = new ArrayList<AbstractRequestableData>(
private Collection<AbstractRequestableData> checkFieldUnits(
DerivParamField field, Collection<AbstractRequestableData> records) {
Set<AbstractRequestableData> newRecs = new HashSet<AbstractRequestableData>(
records.size());
for (AbstractRequestableData record : records) {
if (record.getUnit() != null
@ -492,44 +433,6 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
return newRecs;
}
/**
* Generates the possible data times for a dTime option.
*
* @param dataTime
* The original data time
* @param dTimeInSeconds
* The dTime offset in seconds
* @param dTinSeconds
* The intrinsic time spacing of the current model.
* @return A list of possible data times.
*/
private List<DataTime> generatePossibleDataTimes(DataTime dataTime,
DerivParamField field) {
int dTimeInSeconds = getDTimeInSeconds(field);
int sign = 1;
if (dTimeInSeconds < 0) {
dTimeInSeconds *= -1;
sign = -1;
}
int fTimeInSeconds = dataTime.getFcstTime();
long vTimeInMillis = dataTime.getValidTime().getTimeInMillis()
- (dTimeInSeconds * 1000 * sign);
List<DataTime> rval = new ArrayList<DataTime>(
(dTimeInSeconds * 2 / dt) + 1);
for (int fInSeconds = fTimeInSeconds - dTimeInSeconds; fInSeconds <= fTimeInSeconds
+ dTimeInSeconds; fInSeconds += dt) {
if (fInSeconds >= 0) {
rval.add(new DataTime(new Date(vTimeInMillis
- (fInSeconds * 1000)), fInSeconds));
}
}
return rval;
}
/*
* (non-Javadoc)
*
@ -540,7 +443,7 @@ public class DerivedLevelNode extends AbstractDerivedLevelNode {
public List<Dependency> getDependencies() {
List<Dependency> dependencies = new ArrayList<Dependency>();
if (fields != null) {
for (Entry<DerivParamField, AbstractRequestableLevelNode> entry : fields
for (Entry<DerivParamField, AbstractRequestableNode> entry : fields
.entrySet()) {
dependencies.add(new Dependency(entry.getValue(),
getDTimeInSeconds(entry.getKey())));

View file

@ -1,136 +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.derivparam.tree;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.data.AggregateRequestableData;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
/**
*
* Builds AggregateRecords which contain all forecast times up to the requested
* time.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 8, 2010 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class ModelRunLevelNode extends AbstractAliasLevelNode {
public ModelRunLevelNode(ModelRunLevelNode that) {
super(that);
}
public ModelRunLevelNode(AbstractRequestableLevelNode sourceNode,
DerivParamDesc desc, DerivParamMethod method, String modelName,
Level level) {
super(sourceNode, desc, method, modelName, level);
}
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
Set<DataTime> allTimes = this.timeQuery(null, false);
Set<DataTime> neededTimes = null;
DataTime[] requestedTimes = property.getSelectedEntryTime();
if (requestedTimes == null) {
neededTimes = allTimes;
} else {
neededTimes = new HashSet<DataTime>();
for (DataTime time : allTimes) {
for (DataTime rTime : property.getSelectedEntryTime()) {
if (rTime.getRefTime().equals(time.getRefTime())
&& rTime.getFcstTime() >= time.getFcstTime()) {
neededTimes.add(time);
break;
}
}
}
}
Map<DataTime, List<AbstractRequestableData>> timeBins = new HashMap<DataTime, List<AbstractRequestableData>>();
if (requestedTimes == null) {
for (DataTime time : allTimes) {
timeBins.put(time, new ArrayList<AbstractRequestableData>());
}
} else {
for (DataTime time : requestedTimes) {
timeBins.put(time, new ArrayList<AbstractRequestableData>());
}
}
property.setSelectedEntryTimes(neededTimes
.toArray(new DataTime[neededTimes.size()]));
for (AbstractRequestableData record : sourceNode.getData(property,
timeOut, cache)) {
for (Entry<DataTime, List<AbstractRequestableData>> entry : timeBins
.entrySet()) {
DataTime keyTime = entry.getKey();
DataTime recordTime = record.getDataTime();
if (keyTime.getRefTime().getTime() == recordTime.getRefTime()
.getTime()
&& keyTime.getFcstTime() >= recordTime.getFcstTime()) {
entry.getValue().add(record);
}
}
}
List<AbstractRequestableData> records = new ArrayList<AbstractRequestableData>();
for (Entry<DataTime, List<AbstractRequestableData>> entry : timeBins
.entrySet()) {
if (!entry.getValue().isEmpty()) {
AggregateRequestableData newRecord = new AggregateRequestableData(
entry.getValue());
newRecord.setDataTime(entry.getKey());
modifyRequest(newRecord);
records.add(newRecord);
}
}
return records;
}
@Override
public ModelRunLevelNode clone() {
return new ModelRunLevelNode(this);
}
}

View file

@ -20,19 +20,16 @@
package com.raytheon.uf.viz.derivparam.tree;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
@ -54,20 +51,20 @@ import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
* @author bsteffen
* @version 1.0
*/
public class OrLevelNode extends AbstractDerivedLevelNode {
public class OrLevelNode extends AbstractDerivedDataNode {
private List<AbstractRequestableLevelNode> nodes;
private List<AbstractRequestableNode> nodes;
public OrLevelNode(OrLevelNode that) {
super(that);
if (that.nodes != null) {
this.nodes = new ArrayList<AbstractRequestableLevelNode>(that.nodes);
this.nodes = new ArrayList<AbstractRequestableNode>(that.nodes);
}
}
public OrLevelNode(Level level, DerivParamDesc desc,
DerivParamMethod method, String modelName,
List<AbstractRequestableLevelNode> nodes) {
List<AbstractRequestableNode> nodes) {
this(level, desc, method, modelName, nodes, true);
}
@ -90,146 +87,49 @@ public class OrLevelNode extends AbstractDerivedLevelNode {
*/
public OrLevelNode(Level level, DerivParamDesc desc,
DerivParamMethod method, String modelName,
List<AbstractRequestableLevelNode> nodes, boolean alias) {
List<AbstractRequestableNode> nodes, boolean alias) {
super(level, desc, method, modelName);
if (alias) {
this.nodes = new ArrayList<AbstractRequestableLevelNode>(
nodes.size());
for (AbstractRequestableLevelNode node : nodes) {
this.nodes = new ArrayList<AbstractRequestableNode>(nodes.size());
for (AbstractRequestableNode node : nodes) {
this.nodes.add(new AliasLevelNode(node, desc, method,
modelName, level));
}
} else {
this.nodes = new ArrayList<AbstractRequestableLevelNode>(nodes);
this.nodes = new ArrayList<AbstractRequestableNode>(nodes);
}
}
public void addNodeToOrList(AbstractRequestableLevelNode node) {
public void addNodeToOrList(AbstractRequestableNode node) {
nodes.add(node);
}
@Override
protected List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
Set<DataTime> requestedTimes = null;
DataTime[] requestedTimesArr = property.getSelectedEntryTime();
if (requestedTimesArr == null) {
requestedTimes = this.timeQuery(null, false);
} else {
requestedTimes = new HashSet<DataTime>(
Arrays.asList(requestedTimesArr));
public Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> availability) throws VizException {
Map<AbstractRequestableNode, Set<TimeAndSpace>> result = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
for (AbstractRequestableNode node : nodes) {
result.put(node, availability);
}
List<AbstractRequestableData> records = new ArrayList<AbstractRequestableData>(
requestedTimes.size());
for (AbstractRequestableLevelNode node : nodes) {
List<AbstractRequestableData> newRecords = node.getData(property,
timeOut, cache);
for (AbstractRequestableData record : newRecords) {
if (record.getDataTime() == null) {
requestedTimes.clear();
} else {
requestedTimes.remove(record.getDataTime());
}
}
records.addAll(newRecords);
if (requestedTimes.isEmpty()) {
break;
}
property.setSelectedEntryTimes(requestedTimes
.toArray(new DataTime[requestedTimes.size()]));
}
return records;
return result;
}
@Override
protected Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
Set<DataTime> results = new HashSet<DataTime>();
for (AbstractRequestableLevelNode node : nodes) {
Set<DataTime> times = node.timeQuery(originalRequest, latestOnly,
cache, latestOnlyCache);
if (times == AbstractRequestableLevelNode.TIME_AGNOSTIC) {
return times;
} else {
for (DataTime time : times) {
boolean good = true;
for (DataTime result : results) {
if (result.getMatchRef() == time.getMatchRef()
&& result.getMatchFcst() == time.getMatchFcst()) {
good = false;
break;
}
}
if (good) {
results.add(time);
}
Map<TimeAndSpace, AbstractRequestableData> dataMap = new HashMap<TimeAndSpace, AbstractRequestableData>();
for (AbstractRequestableNode node : nodes) {
Set<AbstractRequestableData> dataSet = dependencyData.get(node);
for (AbstractRequestableData data : dataSet) {
TimeAndSpace ast = data.getTimeAndSpace();
if (!dataMap.containsKey(ast)) {
dataMap.put(ast, data);
}
}
}
return results;
}
@Override
public boolean isTimeAgnostic() {
for (AbstractRequestableLevelNode node : nodes) {
if (node.isTimeAgnostic()) {
return true;
}
}
return false;
}
@Override
public Map<String, RequestConstraint> getRequestConstraintMap() {
Map<String, RequestConstraint> rval = null;
List<Map<String, RequestConstraint>> list = new ArrayList<Map<String, RequestConstraint>>(
nodes.size());
for (AbstractRequestableLevelNode node : nodes) {
Map<String, RequestConstraint> rcMap = node
.getRequestConstraintMap();
if (rcMap == null) {
// sub node has no request constraint short circuit and exit now
return null;
}
list.add(node.getRequestConstraintMap());
}
list = mergeConstraints(list);
if (list.size() == 1) {
rval = list.get(0);
} else {
// not directly combinable until this method is updated to
// return a list of rcMaps
rval = null;
}
return rval;
}
@Override
public boolean hasRequestConstraints() {
boolean rval = true;
for (AbstractRequestableLevelNode node : nodes) {
if (!node.hasRequestConstraints()) {
rval = false;
break;
}
}
if (rval) {
// handle the maps not being directly combinable
rval = getRequestConstraintMap() != null;
}
return rval;
return new HashSet<AbstractRequestableData>(dataMap.values());
}
/*
@ -240,7 +140,7 @@ public class OrLevelNode extends AbstractDerivedLevelNode {
*/
public List<Dependency> getDependencies() {
List<Dependency> dependencies = new ArrayList<Dependency>(nodes.size());
for (AbstractRequestableLevelNode node : nodes) {
for (AbstractRequestableNode node : nodes) {
dependencies.add(new Dependency(node, 0));
}
return dependencies;
@ -286,4 +186,15 @@ public class OrLevelNode extends AbstractDerivedLevelNode {
return true;
}
@Override
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
Set<TimeAndSpace> myAvailability = new HashSet<TimeAndSpace>();
for (AbstractRequestableNode node : nodes) {
myAvailability.addAll(availability.get(node));
}
return myAvailability;
}
}

View file

@ -21,17 +21,15 @@ package com.raytheon.uf.viz.derivparam.tree;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
@ -57,16 +55,7 @@ import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
* @author bsteffen
* @version 1.0
*/
public class StaticDataLevelNode extends AbstractDerivedLevelNode {
@Override
protected DbQueryRequest getDataQueryInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
return null;
}
public class StaticDataLevelNode extends AbstractDerivedDataNode {
protected static final String TIME_FIELD = "dataTime";
@ -90,29 +79,18 @@ public class StaticDataLevelNode extends AbstractDerivedLevelNode {
this.source = source;
}
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
return Arrays.asList(source);
@Override
public Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> availability) throws VizException {
return Collections.emptyMap();
}
@Override
public Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
return TIME_AGNOSTIC;
}
@Override
protected TimeQueryRequest getTimeQueryInternal(
TimeQueryRequest originalRequest, boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache)
throws VizException {
return null;
return new HashSet<AbstractRequestableData>(Arrays.asList(source));
}
@Override
@ -120,11 +98,6 @@ public class StaticDataLevelNode extends AbstractDerivedLevelNode {
return true;
}
@Override
public boolean isTimeAgnostic() {
return true;
}
/*
* (non-Javadoc)
*
@ -176,4 +149,13 @@ public class StaticDataLevelNode extends AbstractDerivedLevelNode {
return true;
}
@Override
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
Set<TimeAndSpace> result = new HashSet<TimeAndSpace>();
result.add(source.getTimeAndSpace());
return result;
}
}

View file

@ -24,16 +24,16 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.data.AggregateRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpaceMatcher;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpaceMatcher.MatchResult;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
@ -69,56 +69,42 @@ public class TimeRangeLevelNode extends AbstractAliasLevelNode {
this.dt = that.dt;
}
public TimeRangeLevelNode(AbstractRequestableLevelNode sourceNode,
public TimeRangeLevelNode(AbstractRequestableNode sourceNode,
DerivParamDesc desc, DerivParamMethod method, String modelName,
int startTime, int endTime, int dt, Level level) {
Integer startTime, int endTime, int dt, Level level) {
super(sourceNode, desc, method, modelName, level);
this.startTime = startTime;
this.endTime = endTime;
this.dt = dt;
}
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
@Override
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
Set<DataTime> allTime = sourceNode.timeQuery(null, false);
Map<DataTime, List<DataTime>> goodTimes = new HashMap<DataTime, List<DataTime>>();
Set<DataTime> timesToRequest = new HashSet<DataTime>();
for (DataTime time : allTime) {
List<DataTime> neededTimes = calculateNeededTimes(time);
if (allTime.containsAll(neededTimes)) {
goodTimes.put(time, neededTimes);
timesToRequest.addAll(neededTimes);
}
TimeAndSpaceMatcher matcher = new TimeAndSpaceMatcher();
matcher.setIgnoreRange(true);
Map<TimeAndSpace, AbstractRequestableData> dataMap = new HashMap<TimeAndSpace, AbstractRequestableData>();
for (AbstractRequestableData data : dependencyData.get(sourceNode)) {
dataMap.put(data.getTimeAndSpace(), data);
}
Set<AbstractRequestableData> records = new HashSet<AbstractRequestableData>();
for (TimeAndSpace ast : availability) {
Set<TimeAndSpace> needed = calculateNeededAvailability(ast);
Map<TimeAndSpace, MatchResult> matched = matcher.match(needed,
dataMap.keySet());
if (TimeAndSpaceMatcher.getAll1(matched).containsAll(needed)) {
List<AbstractRequestableData> dataList = new ArrayList<AbstractRequestableData>();
for (TimeAndSpace dataTime : TimeAndSpaceMatcher
.getAll2(matched)) {
dataList.add(dataMap.get(dataTime));
}
property.setSelectedEntryTimes(timesToRequest
.toArray(new DataTime[timesToRequest.size()]));
Map<DataTime, List<AbstractRequestableData>> timeBins = new HashMap<DataTime, List<AbstractRequestableData>>();
for (AbstractRequestableData record : sourceNode.getData(property,
timeOut, cache)) {
for (Entry<DataTime, List<DataTime>> entry : goodTimes.entrySet()) {
if (entry.getValue().contains(record.getDataTime())) {
List<AbstractRequestableData> records = timeBins.get(entry
.getKey());
if (records == null) {
records = new ArrayList<AbstractRequestableData>(entry
.getValue().size());
timeBins.put(entry.getKey(), records);
}
records.add(record);
}
}
}
List<AbstractRequestableData> records = new ArrayList<AbstractRequestableData>();
for (Entry<DataTime, List<AbstractRequestableData>> entry : timeBins
.entrySet()) {
if (entry.getValue().size() == goodTimes.get(entry.getKey()).size()) {
AggregateRequestableData newRecord = new AggregateRequestableData(
entry.getValue());
newRecord.setDataTime(entry.getKey());
dataList);
newRecord.setDataTime(ast.getTime());
newRecord.setSpace(ast.getSpace());
modifyRequest(newRecord);
records.add(newRecord);
}
@ -127,31 +113,60 @@ public class TimeRangeLevelNode extends AbstractAliasLevelNode {
}
@Override
public Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
Set<DataTime> allTime = sourceNode.timeQuery(originalRequest, false,
cache, latestOnlyCache);
Set<DataTime> goodTimes = new HashSet<DataTime>();
for (DataTime time : allTime) {
if (allTime.containsAll(calculateNeededTimes(time))) {
goodTimes.add(time);
TimeAndSpaceMatcher matcher = new TimeAndSpaceMatcher();
matcher.setIgnoreRange(true);
Set<TimeAndSpace> allAvail = availability.get(sourceNode);
Set<TimeAndSpace> goodAvail = new HashSet<TimeAndSpace>();
for (TimeAndSpace ast : allAvail) {
Set<TimeAndSpace> needed = calculateNeededAvailability(ast);
Set<TimeAndSpace> matchedNeeded = TimeAndSpaceMatcher
.getAll1(matcher.match(needed, allAvail));
if (matchedNeeded.containsAll(needed)) {
goodAvail.add(ast);
}
}
return goodTimes;
return goodAvail;
}
private List<DataTime> calculateNeededTimes(DataTime time) {
List<DataTime> times = new ArrayList<DataTime>();
for (int i = time.getFcstTime() + this.startTime; i <= time
.getFcstTime() + this.endTime; i += dt) {
times.add(new DataTime(time.getRefTime(), i));
@Override
public Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> availability) {
TimeAndSpaceMatcher matcher = new TimeAndSpaceMatcher();
matcher.setIgnoreRange(true);
Set<TimeAndSpace> sourceAvailability = new HashSet<TimeAndSpace>(
availability);
for (TimeAndSpace ast : availability) {
Set<TimeAndSpace> needed = calculateNeededAvailability(ast);
Set<TimeAndSpace> matchedAvail = TimeAndSpaceMatcher
.getAll1(matcher.match(needed, availability));
sourceAvailability.addAll(matchedAvail);
}
return times;
Map<AbstractRequestableNode, Set<TimeAndSpace>> result = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
result.put(sourceNode, sourceAvailability);
return result;
}
@Override
public boolean isConstant() {
return super.isConstant();
}
private Set<TimeAndSpace> calculateNeededAvailability(TimeAndSpace ast) {
Set<TimeAndSpace> result = new HashSet<TimeAndSpace>();
int start = dt;
if (startTime != null) {
start = ast.getTime().getFcstTime() + this.startTime;
}
for (int i = start; i <= ast.getTime().getFcstTime() + this.endTime; i += dt) {
DataTime time = new DataTime(ast.getTime().getRefTime(), i);
result.add(new TimeAndSpace(time, ast.getSpace()));
}
return result;
}
@Override

View file

@ -30,12 +30,10 @@ import java.util.Map.Entry;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.data.AggregateRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
@ -63,7 +61,7 @@ import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
* @author bsteffen
* @version 1.0
*/
public class UnionLevelNode extends AbstractDerivedLevelNode {
public class UnionLevelNode extends AbstractDerivedDataNode {
private static final Comparator<AbstractRequestableData> requestComp = new Comparator<AbstractRequestableData>() {
@ -76,21 +74,20 @@ public class UnionLevelNode extends AbstractDerivedLevelNode {
};
protected List<AbstractRequestableLevelNode> nodes;
protected List<AbstractRequestableNode> nodes;
public UnionLevelNode(UnionLevelNode that) {
super(that);
this.nodes = that.nodes;
}
public UnionLevelNode(List<AbstractRequestableLevelNode> nodes,
String modelName) {
public UnionLevelNode(List<AbstractRequestableNode> nodes, String modelName) {
this.nodes = nodes;
this.modelName = modelName;
}
public UnionLevelNode(Level level, String modelName,
List<AbstractRequestableLevelNode> nodes) {
List<AbstractRequestableNode> nodes) {
this.setLevel(level);
this.nodes = nodes;
this.modelName = modelName;
@ -98,43 +95,54 @@ public class UnionLevelNode extends AbstractDerivedLevelNode {
public UnionLevelNode(Level level, DerivParamDesc desc,
DerivParamMethod method, String modelName,
List<AbstractRequestableLevelNode> nodes) {
List<AbstractRequestableNode> nodes) {
super(level, desc, method, modelName);
this.nodes = nodes;
}
@Override
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
public Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> availability) throws VizException {
Map<AbstractRequestableNode, Set<TimeAndSpace>> result = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
for (AbstractRequestableNode node : nodes) {
result.put(node, availability);
}
return result;
}
@Override
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
List<AbstractRequestableData> rawRecords = new ArrayList<AbstractRequestableData>();
List<AbstractRequestableLevelNode> requests = new ArrayList<AbstractRequestableLevelNode>(
List<AbstractRequestableNode> requests = new ArrayList<AbstractRequestableNode>(
nodes);
for (AbstractRequestableLevelNode request : requests) {
rawRecords.addAll(request.getData(property, timeOut, cache));
for (AbstractRequestableNode request : requests) {
rawRecords.addAll(dependencyData.get(request));
}
Map<DataTime, List<AbstractRequestableData>> bins = new HashMap<DataTime, List<AbstractRequestableData>>();
Map<TimeAndSpace, List<AbstractRequestableData>> bins = new HashMap<TimeAndSpace, List<AbstractRequestableData>>();
for (AbstractRequestableData record : rawRecords) {
List<AbstractRequestableData> bin = bins.get(record.getDataTime());
List<AbstractRequestableData> bin = bins.get(record
.getTimeAndSpace());
if (bin == null) {
bin = new ArrayList<AbstractRequestableData>();
bins.put(record.getDataTime(), bin);
bins.put(record.getTimeAndSpace(), bin);
}
bin.add(record);
}
List<AbstractRequestableData> records = new ArrayList<AbstractRequestableData>(
Set<AbstractRequestableData> records = new HashSet<AbstractRequestableData>(
bins.size());
for (Entry<DataTime, List<AbstractRequestableData>> entry : bins
for (Entry<TimeAndSpace, List<AbstractRequestableData>> entry : bins
.entrySet()) {
if (entry.getValue().size() >= 2) {
Collections.sort(entry.getValue(), requestComp);
AggregateRequestableData newRecord = new AggregateRequestableData(
entry.getValue());
newRecord.setDataTime(entry.getKey());
newRecord.setDataTime(entry.getKey().getTime());
newRecord.setSpace(entry.getKey().getSpace());
modifyRequest(newRecord);
records.add(newRecord);
}
@ -143,49 +151,28 @@ public class UnionLevelNode extends AbstractDerivedLevelNode {
}
@Override
public Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
// Any time in results should have at least 2 nodes with that time
Set<DataTime> results = TIME_AGNOSTIC;
// Any time in single has at least one node available at that time
Set<DataTime> single = new HashSet<DataTime>();
List<AbstractRequestableLevelNode> requests = new ArrayList<AbstractRequestableLevelNode>(
// things in one are available for one level
Set<TimeAndSpace> one = new HashSet<TimeAndSpace>();
// things in two are available for two levels.
Set<TimeAndSpace> two = new HashSet<TimeAndSpace>();
List<AbstractRequestableNode> requests = new ArrayList<AbstractRequestableNode>(
nodes);
for (AbstractRequestableLevelNode request : requests) {
Set<DataTime> times = request.timeQuery(originalRequest,
latestOnly, cache, latestOnlyCache);
if (times == TIME_AGNOSTIC) {
continue;
} else if (results == TIME_AGNOSTIC) {
results = new HashSet<DataTime>();
single.addAll(times);
} else {
// We must have at least two resources with times. The first
// node with times will add only to single, after that any
// time in single will also be added to results
results.addAll(times);
results.retainAll(single);
single.addAll(times);
for (AbstractRequestableNode request : requests) {
// Do not request just latest only because if two nodes have
// different latests than this will return no times
for (TimeAndSpace time : availability.get(request)) {
if (one.contains(time)) {
two.add(time);
} else {
one.add(time);
}
}
}
return results;
}
@Override
public boolean isTimeAgnostic() {
boolean timeAgnostic = true;
for (AbstractRequestableLevelNode node : nodes) {
if (!node.isTimeAgnostic()) {
timeAgnostic = false;
break;
}
}
return timeAgnostic;
return two;
}
/*
@ -197,7 +184,7 @@ public class UnionLevelNode extends AbstractDerivedLevelNode {
@Override
public List<Dependency> getDependencies() {
List<Dependency> dependencies = new ArrayList<Dependency>(nodes.size());
for (AbstractRequestableLevelNode node : nodes) {
for (AbstractRequestableNode node : nodes) {
dependencies.add(new Dependency(node, 0));
}
return dependencies;

View file

@ -66,6 +66,7 @@ public class GridRequestableData extends AbstractRequestableData {
this.gridSource = source;
this.source = source.getDatasetId();
this.dataTime = source.getDataTime();
this.space = source.getLocation();
this.level = source.getLevel();
this.parameter = source.getParameter().getAbbreviation();
this.unit = source.getParameter().getUnit();

View file

@ -115,8 +115,8 @@ public class ImportRequestableData extends AliasRequestableData {
}
CoverageUtils covUtil = CoverageUtils.getInstance();
GridCoverage sourceGrid = covUtil.getCoverage(sourceRecord.getSource());
GridCoverage destGrid = covUtil.getCoverage(this.getSource());
GridCoverage sourceGrid = (GridCoverage) sourceRecord.getSpace();
GridCoverage destGrid = (GridCoverage) getSpace();
Interpolation interpolation = Interpolation
.getInstance(Interpolation.INTERP_BICUBIC);
if (rval instanceof FloatDataRecord) {

View file

@ -88,6 +88,7 @@ public class RadarRequestableData extends GridRequestableData {
RadarAdapter.getGridSpacing());
this.source = "radar";
this.dataTime = source.getDataTime();
this.space = RadarAdapter.getInstance().getCoverage();
try {
this.level = LevelFactory.getInstance().getLevel("TILT",
source.getPrimaryElevationAngle());

View file

@ -35,11 +35,12 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.viz.grid.util.CoverageUtils;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.viz.grid.util.SliceUtil;
/**
* TODO Add Description
* Requestable data object that returns static data for a GridCoverage dx,dy, or
* coriolis.
*
* <pre>
*
@ -60,11 +61,14 @@ public class StaticGridRequestableData extends AbstractRequestableData {
private StaticGridDataType dataType;
public StaticGridRequestableData(StaticGridDataType dataType, String source) {
public StaticGridRequestableData(StaticGridDataType dataType,
String source, GridCoverage coverage) {
this.dataType = dataType;
this.source = source;
this.parameter = dataType.toString();
this.parameterName = dataType.toString();
this.space = coverage;
this.dataTime = TimeAndSpace.TIME_AGNOSTIC;
if (StaticGridDataType._dt.equals(dataType)) {
this.unit = SI.SECOND;
} else {
@ -101,21 +105,25 @@ public class StaticGridRequestableData extends AbstractRequestableData {
return new Float(dTinSeconds);
} else {
GridCoverage coverage = CoverageUtils.getInstance().getCoverage(
source);
StaticGridData data = StaticGridData.getInstance(coverage);
switch (dataType) {
case coriolis:
rval = data.getCoriolis();
break;
case dx:
rval = data.getDx();
break;
case dy:
rval = data.getDy();
break;
if (this.space instanceof GridCoverage) {
StaticGridData data = StaticGridData
.getInstance((GridCoverage) this.space);
switch (dataType) {
case coriolis:
rval = data.getCoriolis();
break;
case dx:
rval = data.getDx();
break;
case dy:
rval = data.getDy();
break;
}
} else {
throw new IllegalStateException("Cannot get static topo for: "
+ this.space);
}
}
if (arg instanceof Request) {
return SliceUtil.slice(rval, (Request) arg);

View file

@ -27,13 +27,12 @@ import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.viz.grid.util.CoverageUtils;
import com.raytheon.viz.grid.util.SliceUtil;
import com.raytheon.viz.grid.util.TiltUtils;
import com.vividsolutions.jts.geom.Coordinate;
/**
* TODO Add Description
* Requestable Data that generated tilt elevation.
*
* <pre>
*
@ -59,18 +58,20 @@ public class TiltRequestableData extends AbstractRequestableData {
}
public TiltRequestableData(String modelName, Level tiltAngle) {
public TiltRequestableData(String modelName, Level tiltAngle,
GridCoverage coverage) {
this.source = modelName;
this.unit = SI.METER;
this.parameter = "TILT";
this.parameterName = "TILT";
this.level = tiltAngle;
this.space = coverage;
}
@Override
public FloatDataRecord getDataValue(Object arg) throws VizException {
GridCoverage coverage = CoverageUtils.getInstance().getCoverage(source);
GridCoverage coverage = (GridCoverage) getSpace();
FloatDataRecord fdr = null;
if (arg instanceof TiltCenterPoint) {
Coordinate tiltLoc = ((TiltCenterPoint) arg).latLon;

View file

@ -37,11 +37,11 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.topo.TopoQuery;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.viz.grid.util.CoverageUtils;
import com.raytheon.viz.grid.util.SliceUtil;
/**
* TODO Add Description
* requestable data that queries the topo datastore and transforms the data into
* the correct coverage.
*
* <pre>
*
@ -82,7 +82,7 @@ public class TopoRequestableData extends AbstractRequestableData {
*/
@Override
public FloatDataRecord getDataValue(Object arg) throws VizException {
GridCoverage coverage = CoverageUtils.getInstance().getCoverage(source);
GridCoverage coverage = (GridCoverage) this.getSpace();
FloatDataRecord rval = topoCache.get(coverage);
if (rval == null) {

View file

@ -19,19 +19,11 @@
**/
package com.raytheon.viz.grid.inv;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.tree.AbstractCubeLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.uf.viz.derivparam.tree.CubeLevel;
import com.raytheon.viz.grid.data.GridRequestableDataFactory;
/**
*
@ -63,35 +55,9 @@ public class CubeLevelNode extends AbstractCubeLevelNode {
}
public CubeLevelNode(
List<CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode>> levels,
List<CubeLevel<AbstractRequestableNode, AbstractRequestableNode>> levels,
String modelName) {
super(levels, modelName);
}
protected List<AbstractRequestableData> wrapRawRecord(List<Object> objs)
throws VizException {
List<AbstractRequestableData> gribResults = new ArrayList<AbstractRequestableData>(
objs.size());
GridRequestableDataFactory factory = GridRequestableDataFactory
.getInstance();
for (Object obj : objs) {
AbstractRequestableData record = factory
.getGridRequestableData((GridRecord) obj);
gribResults.add(record);
}
return gribResults;
}
@Override
protected void filter(
Map<String, RequestConstraint> baseRequestConstraints,
Map<String, RequestConstraint> requestContraintsToFilter) {
for (Entry<String, RequestConstraint> e : baseRequestConstraints
.entrySet()) {
if (!requestContraintsToFilter.containsKey(e.getKey())) {
requestContraintsToFilter.put(e.getKey(), e.getValue());
}
}
}
}

View file

@ -21,20 +21,20 @@ package com.raytheon.viz.grid.inv;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.data.AggregateRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
import com.raytheon.uf.viz.derivparam.tree.AbstractAliasLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
/**
*
@ -58,41 +58,29 @@ public class GatherLevelNode extends AbstractAliasLevelNode {
super(that);
}
public GatherLevelNode(AbstractRequestableLevelNode sourceNode,
public GatherLevelNode(AbstractRequestableNode sourceNode,
DerivParamDesc desc, DerivParamMethod method, String modelName,
Level level) {
super(sourceNode, desc, method, modelName, level);
}
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
@Override
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
Map<DataTime, List<AbstractRequestableData>> recordMap = new HashMap<DataTime, List<AbstractRequestableData>>();
HashMap<String, RequestConstraint> rcMap = property
.getEntryQueryParameters(false);
for (String pert : GridInventory.getEnsembles(sourceNode)) {
rcMap.put(GridInventory.ENSEMBLE_QUERY,
new RequestConstraint(pert.toString()));
property.setEntryQueryParameters(rcMap, false);
cache.clear();
for (AbstractRequestableData record : sourceNode.getData(property,
timeOut, cache)) {
List<AbstractRequestableData> records = recordMap.get(record
.getDataTime());
if (records == null) {
records = new ArrayList<AbstractRequestableData>();
recordMap.put(record.getDataTime(), records);
}
records.add(record);
Map<TimeAndSpace, List<AbstractRequestableData>> availMap = new HashMap<TimeAndSpace, List<AbstractRequestableData>>();
for (AbstractRequestableData data : dependencyData.get(sourceNode)) {
TimeAndSpace ast = data.getTimeAndSpace();
List<AbstractRequestableData> avail = availMap.get(ast);
if (avail == null) {
avail = new ArrayList<AbstractRequestableData>();
availMap.put(ast, avail);
}
avail.add(data);
}
rcMap.remove(GridInventory.ENSEMBLE_QUERY);
property.setEntryQueryParameters(rcMap, false);
List<AbstractRequestableData> result = new ArrayList<AbstractRequestableData>(
recordMap.size());
for (List<AbstractRequestableData> records : recordMap.values()) {
Set<AbstractRequestableData> result = new HashSet<AbstractRequestableData>();
for (List<AbstractRequestableData> records : availMap.values()) {
AggregateRequestableData record = new AggregateRequestableData(
records);
modifyRequest(record);

View file

@ -66,16 +66,14 @@ import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamField;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod.MethodType;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode.Dependency;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode.Dependency;
import com.raytheon.uf.viz.derivparam.tree.CubeLevel;
import com.raytheon.uf.viz.derivparam.tree.StaticDataLevelNode;
import com.raytheon.uf.viz.points.IPointChangedListener;
import com.raytheon.uf.viz.points.PointsDataManager;
import com.raytheon.viz.grid.data.ImportRequestableData;
import com.raytheon.viz.grid.data.StaticGridRequestableData;
import com.raytheon.viz.grid.data.TiltRequestableData;
import com.raytheon.viz.grid.util.CoverageUtils;
import com.raytheon.viz.grid.util.RadarAdapter;
@ -214,8 +212,10 @@ public class GridInventory extends AbstractInventory implements
ensembles = new ArrayList<String>(1);
ensembles.add(ensemble);
} else if (!ensembles.contains(ensemble)) {
ensembles = new ArrayList<String>(ensembles);
ensembles.add(ensemble);
}
gribNode.setEnsembles(ensembles);
}
if (!modelsWithPerts.contains(model)) {
modelsWithPerts.add(model);
@ -242,15 +242,15 @@ public class GridInventory extends AbstractInventory implements
*/
public LevelNode getNode(String source, String parameter, Level level) {
try {
List<AbstractRequestableLevelNode> nodes = walkTree(null,
List<AbstractRequestableNode> nodes = walkTree(null,
Arrays.asList(source), Arrays.asList(parameter),
Arrays.asList(level), true, true, null);
if (nodes == null || nodes.isEmpty()) {
return null;
}
if (nodes.get(0) instanceof AbstractDerivedLevelNode) {
if (nodes.get(0) instanceof AbstractDerivedDataNode) {
try {
updater.addNode((AbstractDerivedLevelNode) nodes.get(0));
updater.addNode((AbstractDerivedDataNode) nodes.get(0));
} catch (VizException e) {
statusHandler
.handle(Priority.PROBLEM,
@ -415,8 +415,8 @@ public class GridInventory extends AbstractInventory implements
public Set<Level> getAvailableLevels(Map<String, RequestConstraint> query) {
Set<Level> levels = new HashSet<Level>();
List<AbstractRequestableLevelNode> nodes = evaluateRequestConstraints(query);
for (AbstractRequestableLevelNode node : nodes) {
List<AbstractRequestableNode> nodes = evaluateRequestConstraints(query);
for (AbstractRequestableNode node : nodes) {
levels.add(node.getLevel());
}
return levels;
@ -429,7 +429,7 @@ public class GridInventory extends AbstractInventory implements
* @param query
* @return
*/
public List<AbstractRequestableLevelNode> evaluateRequestConstraints(
public List<AbstractRequestableNode> evaluateRequestConstraints(
Map<String, RequestConstraint> query) {
List<String> sourcesToProcess = getSourcesToProcess(query);
List<String> paramsToProcess = getParametersToProcess(query);
@ -437,14 +437,14 @@ public class GridInventory extends AbstractInventory implements
if (!levelsToProcess.isEmpty() && !sourcesToProcess.isEmpty()
&& !paramsToProcess.isEmpty()) {
try {
List<AbstractRequestableLevelNode> nodes = walkTree(null,
List<AbstractRequestableNode> nodes = walkTree(null,
sourcesToProcess, paramsToProcess, levelsToProcess,
true, true, null);
try {
for (AbstractRequestableLevelNode node : nodes) {
if (node instanceof AbstractDerivedLevelNode) {
updater.addNode((AbstractDerivedLevelNode) node);
for (AbstractRequestableNode node : nodes) {
if (node instanceof AbstractDerivedDataNode) {
updater.addNode((AbstractDerivedDataNode) node);
}
}
} catch (VizException e) {
@ -465,7 +465,7 @@ public class GridInventory extends AbstractInventory implements
}
}
return new ArrayList<AbstractRequestableLevelNode>(0);
return new ArrayList<AbstractRequestableNode>(0);
}
public List<String> getEnsembles(Map<String, RequestConstraint> query)
@ -474,7 +474,8 @@ public class GridInventory extends AbstractInventory implements
if (nameRC == null) {
// Only bother grabbing nodes with perts
nameRC = new RequestConstraint(null, ConstraintType.IN);
nameRC.setConstraintValueList(modelsWithPerts);
nameRC.setConstraintValueList(modelsWithPerts
.toArray(new String[0]));
query = new HashMap<String, RequestConstraint>(query);
query.put(MODEL_NAME_QUERY, nameRC);
} else {
@ -492,14 +493,14 @@ public class GridInventory extends AbstractInventory implements
}
}
Set<String> ensembles = new HashSet<String>();
for (AbstractRequestableLevelNode node : evaluateRequestConstraints(query)) {
for (AbstractRequestableNode node : evaluateRequestConstraints(query)) {
ensembles.addAll(getEnsembles(node));
}
return new ArrayList<String>(ensembles);
}
public static List<String> getEnsembles(AbstractRequestableLevelNode node)
protected static List<String> getEnsembles(AbstractRequestableNode node)
throws VizException {
if (node instanceof GridRequestableNode) {
@ -514,17 +515,16 @@ public class GridInventory extends AbstractInventory implements
for (Entry<String, RequestConstraint> entry : rcMap.entrySet()) {
dbQuery.addConstraint(entry.getKey(), entry.getValue());
}
List<Object[]> results = dbQuery.performQuery();
List<String> ensembles = new ArrayList<String>(results.size());
for (Object[] ensemble : results) {
List<String> ensembles = new ArrayList<String>();
for (Object[] ensemble : dbQuery.performQuery()) {
ensembles.add((String) ensemble[0]);
}
gNode.setEnsembles(ensembles);
return ensembles;
} else if (node instanceof GatherLevelNode) {
return Collections.emptyList();
} else if (node instanceof AbstractDerivedLevelNode) {
AbstractDerivedLevelNode dataNode = (AbstractDerivedLevelNode) node;
} else if (node instanceof AbstractDerivedDataNode) {
AbstractDerivedDataNode dataNode = (AbstractDerivedDataNode) node;
Set<String> ensembles = new HashSet<String>();
for (Dependency dep : dataNode.getDependencies()) {
@ -626,7 +626,7 @@ public class GridInventory extends AbstractInventory implements
}
@Override
protected AbstractDerivedLevelNode getImportNode(
protected AbstractDerivedDataNode getImportNode(
AbstractRequestableData nodeToImport, SourceNode destSourceNode,
DerivParamDesc desc, DerivParamMethod method, Level level) {
AbstractRequestableData data = new ImportRequestableData(nodeToImport,
@ -641,8 +641,8 @@ public class GridInventory extends AbstractInventory implements
}
@Override
protected AbstractDerivedLevelNode getImportNode(
AbstractRequestableLevelNode nodeToImport,
protected AbstractDerivedDataNode getImportNode(
AbstractRequestableNode nodeToImport,
String nodeToImportSourceName, SourceNode destSourceNode,
DerivParamDesc desc, DerivParamMethod method, Level level) {
return new ImportLevelNode(nodeToImport, nodeToImportSourceName, desc,
@ -676,18 +676,18 @@ public class GridInventory extends AbstractInventory implements
NavigableSet<Level> levels = LevelUtilities
.getOrderedSetOfStandardLevels(masterLevelName);
List<CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode>> cubeLevels = new ArrayList<CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode>>(
List<CubeLevel<AbstractRequestableNode, AbstractRequestableNode>> cubeLevels = new ArrayList<CubeLevel<AbstractRequestableNode, AbstractRequestableNode>>(
levels.size());
for (Level fieldLevel : levels) {
AbstractRequestableLevelNode pressure = resolveNode(sNode, "P",
AbstractRequestableNode pressure = resolveNode(sNode, "P",
fieldLevel, stack, nodata);
if (pressure != null) {
AbstractRequestableLevelNode param = resolveNode(sNode,
AbstractRequestableNode param = resolveNode(sNode,
field.getParam(), fieldLevel, stack, nodata);
if (param != null) {
CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode> cl = new CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode>(
CubeLevel<AbstractRequestableNode, AbstractRequestableNode> cl = new CubeLevel<AbstractRequestableNode, AbstractRequestableNode>(
pressure, param);
cubeLevels.add(cl);
}
@ -716,27 +716,26 @@ public class GridInventory extends AbstractInventory implements
DerivParamField field, Level level) {
String fieldParamAbbrev = field.getParam();
if (StaticGridDataType.getStringValues().contains(fieldParamAbbrev)) {
StaticGridDataType staticGridDataType = StaticGridDataType
.valueOf(fieldParamAbbrev);
return new StaticGridRequestableData(staticGridDataType,
sNode.getValue());
return new StaticGridDataLevelNode(sNode.getValue(),
fieldParamAbbrev);
}
// Check to see if we can set the field from the
// masterlevel name
if (level.getMasterLevel().getName().equals(fieldParamAbbrev)) {
if ("TILT".equals(fieldParamAbbrev)) {
return new TiltRequestableData(sNode.getValue(), level);
return new StaticGridDataLevelNode(sNode.getValue(),
fieldParamAbbrev, level);
}
}
return null;
}
protected AbstractDerivedLevelNode createDerivedNode(DerivParamDesc desc,
protected AbstractDerivedDataNode createDerivedNode(DerivParamDesc desc,
DerivParamMethod method, Level level, List<Object> fields,
SourceNode source) {
if (method.getMethodType() == MethodType.OTHER
&& method.getName().equalsIgnoreCase("Gather")) {
AbstractRequestableLevelNode lNode = (AbstractRequestableLevelNode) fields
AbstractRequestableNode lNode = (AbstractRequestableNode) fields
.get(0);
try {
@ -764,5 +763,4 @@ public class GridInventory extends AbstractInventory implements
public void pointChanged() {
reinitTree();
}
}

View file

@ -0,0 +1,240 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.grid.inv;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequestSet;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponseSet;
import com.raytheon.uf.viz.core.RecordFactory;
import com.raytheon.uf.viz.core.datastructure.DecisionTree;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.MetadataContainer;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.viz.grid.data.GridRequestableData;
import com.raytheon.viz.grid.data.GridRequestableDataFactory;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 10, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class GridMetadataContainer extends MetadataContainer {
/**
* @param originalConstraints
*/
public GridMetadataContainer(
Map<String, RequestConstraint> originalConstraints) {
super(originalConstraints);
}
@Override
protected void processRequests() throws VizException {
DecisionTree<GridRequestableNode> tree = new DecisionTree<GridRequestableNode>();
List<Map<String, RequestConstraint>> constraintMaps = new ArrayList<Map<String, RequestConstraint>>();
for (AbstractRequestableNode node : availCache.keySet()) {
if (dataCache.containsKey(node)) {
continue;
}
if (node instanceof GridRequestableNode) {
GridRequestableNode dataNode = (GridRequestableNode) node;
DbQueryRequest request = dataNode.getDataRequest(
originalConstraints, availCache.get(node));
Map<String, RequestConstraint> constraints = request
.getConstraints();
tree.insertCriteria(constraints, dataNode, false);
constraintMaps.add(constraints);
}
}
if (constraintMaps.isEmpty()) {
super.processRequests();
return;
} else if (constraintMaps.size() == 1) {
super.processRequests();
return;
}
List<DbQueryRequest> requests = new ArrayList<DbQueryRequest>();
constraintMaps = mergeConstraints(constraintMaps);
for (Map<String, RequestConstraint> constraintMap : constraintMaps) {
DbQueryRequest dbRequest = new DbQueryRequest();
dbRequest.setEntityClass(GridRecord.class.getName());
dbRequest.setConstraints(constraintMap);
requests.add(dbRequest);
}
DbQueryRequestSet requestSet = new DbQueryRequestSet();
requestSet.setQueries(requests.toArray(new DbQueryRequest[0]));
DbQueryResponseSet responseSet = (DbQueryResponseSet) ThriftClient
.sendRequest(requestSet);
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dataCache = new HashMap<AbstractRequestableNode, Set<AbstractRequestableData>>();
GridRequestableDataFactory grdf = GridRequestableDataFactory
.getInstance();
tree.rebuildTree();
for (DbQueryResponse response : responseSet.getResults()) {
for (Map<String, Object> result : response.getResults()) {
GridRecord record = (GridRecord) result.get(null);
Map<String, Object> recordMap = RecordFactory.getInstance()
.loadMapFromUri(record.getDataURI());
GridRequestableData data = grdf.getGridRequestableData(record);
for (GridRequestableNode node : tree.searchTree(recordMap)) {
Set<AbstractRequestableData> set = dataCache.get(node);
if (set == null) {
set = new HashSet<AbstractRequestableData>();
dataCache.put(node, set);
}
set.add(data);
}
}
}
this.dataCache.putAll(dataCache);
super.processRequests();
}
/**
* Takes the list of constraintMaps and merges the constraint maps that
* different by only one key into a new list of constraint maps. EX: 5
* RequestConstraint Maps for GFS40 Temp on 5 MB levels will be consolidated
* into a single RequestConstraint Map using an IN List for the MB levels.
*
* @param constraintMaps
* @return
*/
public static List<Map<String, RequestConstraint>> mergeConstraints(
List<Map<String, RequestConstraint>> constraintMaps) {
List<Map<String, RequestConstraint>> rval = new ArrayList<Map<String, RequestConstraint>>();
if (constraintMaps != null && constraintMaps.size() > 0) {
List<String> mergeKeyList = new ArrayList<String>();
for (Map<String, RequestConstraint> constraintMap : constraintMaps) {
boolean merged = false;
int index = 0;
MERGE_MAP_LOOP: for (index = 0; index < rval.size(); index++) {
Map<String, RequestConstraint> mergeMap = rval.get(index);
// maps must be of same size
if (mergeMap.size() == constraintMap.size()) {
String mergeKey = mergeKeyList.get(index);
if (mergeKey != null) {
// determine if it matches map except for uniqueKey
for (String key : mergeMap.keySet()) {
boolean isUniqueKey = mergeKey.equals(key);
boolean constraintEquals = mergeMap.get(key)
.equals(constraintMap.get(key));
if (!constraintEquals && !isUniqueKey) {
continue MERGE_MAP_LOOP;
}
}
// map differs except for key
boolean constraintMerged = mergeMap.get(mergeKey)
.merge(constraintMap.get(mergeKey));
if (!constraintMerged) {
continue MERGE_MAP_LOOP;
} else {
merged = true;
break MERGE_MAP_LOOP;
}
} else {
// current mergeMap has never been merged with,
// double check that only one key is different
// between maps
for (String key : mergeMap.keySet()) {
if (!mergeMap.get(key).equals(
constraintMap.get(key))) {
if (mergeKey == null) {
// possible merge key, continue checking
// map
mergeKey = key;
} else {
// two merge keys found, go to next
// merge map
continue MERGE_MAP_LOOP;
}
}
}
// found mergeKey, add to mergeKeyList. If mergeKey
// still being null is only possible of mergeMap and
// constraintMap contain the exact same constraints,
// consider them merged
if (mergeKey == null) {
merged = true;
break MERGE_MAP_LOOP;
}
boolean constraintMerged = mergeMap.get(mergeKey)
.merge(constraintMap.get(mergeKey));
if (!constraintMerged) {
continue MERGE_MAP_LOOP;
} else {
merged = true;
mergeKeyList.set(index, mergeKey);
break MERGE_MAP_LOOP;
}
}
} // maps same size check
} // MERGE_MAP_LOOP
if (!merged) {
Map<String, RequestConstraint> mergeMap = new HashMap<String, RequestConstraint>();
// deep copy the map
for (Map.Entry<String, RequestConstraint> entry : constraintMap
.entrySet()) {
mergeMap.put(entry.getKey(), entry.getValue().clone());
}
rval.add(mergeMap);
mergeKeyList.add(null);
}
}
}
return rval;
}
}

View file

@ -19,9 +19,6 @@
**/
package com.raytheon.viz.grid.inv;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -34,17 +31,21 @@ import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.derivparam.tree.LevelNode;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.common.gridcoverage.lookup.GridCoverageLookup;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.CatalogQuery;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.tree.AbstractBaseDataNode;
import com.raytheon.viz.grid.data.GridRequestableDataFactory;
import com.raytheon.viz.grid.util.CoverageUtils;
/**
*
@ -62,7 +63,7 @@ import com.raytheon.viz.grid.data.GridRequestableDataFactory;
* @author bsteffen
* @version 1.0
*/
public class GridRequestableNode extends AbstractRequestableLevelNode {
public class GridRequestableNode extends AbstractBaseDataNode {
protected static final String TIME_FIELD = "dataTime";
@ -101,155 +102,77 @@ public class GridRequestableNode extends AbstractRequestableLevelNode {
this.rcMap = rcMap;
}
@Override
public boolean isTimeAgnostic() {
return false;
}
@Override
public Map<String, RequestConstraint> getRequestConstraintMap() {
return rcMap;
}
@Override
public boolean hasRequestConstraints() {
return true;
}
@Override
public Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Set<AbstractRequestableData> getData(
Map<String, RequestConstraint> orignalConstraints,
Set<TimeAndSpace> availability, Object response)
throws VizException {
Set<DataTime> resultsSet = GridTimeCache.getInstance().getTimes(this);
if (resultsSet != null) {
return resultsSet;
}
DataTime[] results = CatalogQuery.performTimeQuery(rcMap, latestOnly,
null);
if (results != null) {
resultsSet = new HashSet<DataTime>(Arrays.asList(results));
if (!latestOnly) {
GridTimeCache.getInstance().setTimes(this, resultsSet);
}
return resultsSet;
} else {
return null;
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* getTimeQueryInternal(boolean, java.util.Map)
*/
@Override
protected TimeQueryRequest getTimeQueryInternal(
TimeQueryRequest originalRequest, boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache)
throws VizException {
Set<DataTime> resultsSet = GridTimeCache.getInstance().getTimes(this);
if (resultsSet != null) {
return null;
}
return CatalogQuery.getTimeQuery(rcMap, latestOnly, null);
}
@Override
protected void processTimeQueryResults(boolean latestOnly,
List<DataTime> queryResponse) throws VizException {
if (!latestOnly) {
Set<DataTime> resultsSet = new HashSet<DataTime>(queryResponse);
GridTimeCache.getInstance().setTimes(this, resultsSet);
}
}
@Override
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
DbQueryRequest dbRequest = getDataQueryInternal(property, timeOut,
cache);
DbQueryResponse response = (DbQueryResponse) ThriftClient
.sendRequest(dbRequest);
return processDataQueryResults(response);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* getDataQueryInternal(com.raytheon.uf.viz.core.catalog.LayerProperty, int)
*/
@Override
protected DbQueryRequest getDataQueryInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
Map<String, RequestConstraint> oldQuery = property
.getEntryQueryParameters(false);
Map<String, RequestConstraint> newQuery = new HashMap<String, RequestConstraint>(
rcMap);
for (Entry<String, RequestConstraint> e : oldQuery.entrySet()) {
if (!newQuery.containsKey(e.getKey())) {
newQuery.put(e.getKey(), e.getValue());
}
}
DbQueryRequest dbRequest = new DbQueryRequest();
DataTime[] times = property.getSelectedEntryTime();
if (times != null && times.length > 0) {
RequestConstraint dtRC = new RequestConstraint();
dtRC.setConstraintType(ConstraintType.IN);
for (DataTime t : times) {
dtRC.addToConstraintValueList(t.toString());
}
newQuery.put("dataTime", dtRC);
}
newQuery.put(GridConstants.PLUGIN_NAME, new RequestConstraint(
GridConstants.GRID));
dbRequest.setConstraints(newQuery);
return dbRequest;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* processQueryResults
* (com.raytheon.uf.common.dataquery.responses.DbQueryResponse)
*/
@Override
protected List<AbstractRequestableData> processDataQueryResults(
DbQueryResponse response) throws VizException {
List<Map<String, Object>> rows = response.getResults();
List<AbstractRequestableData> rval = new ArrayList<AbstractRequestableData>(
rows.size());
GridRequestableDataFactory factory = GridRequestableDataFactory
DbQueryResponse dbresponse = (DbQueryResponse) response;
GridRequestableDataFactory grdf = GridRequestableDataFactory
.getInstance();
for (Map<String, Object> objMap : rows) {
rval.add(factory.getGridRequestableData((GridRecord) objMap
.get(null)));
Set<AbstractRequestableData> ards = new HashSet<AbstractRequestableData>();
for (Map<String, Object> result : dbresponse.getResults()) {
GridRecord record = (GridRecord) result.get(null);
ards.add(grdf.getGridRequestableData(record));
}
return rval;
return ards;
}
/*
* (non-Javadoc)
*
* @seecom.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* getDependencies()
*/
@Override
public List<Dependency> getDependencies() {
return Collections.emptyList();
public DbQueryRequest getDataRequest(
Map<String, RequestConstraint> orignalConstraints,
Set<TimeAndSpace> availability) {
boolean timeAgnostic = false;
boolean spaceAgnostic = false;
Set<DataTime> times = new HashSet<DataTime>();
Set<ISpatialObject> spaces = new HashSet<ISpatialObject>();
for (TimeAndSpace ast : availability) {
if (ast.isTimeAgnostic()) {
timeAgnostic = true;
} else {
times.add(ast.getTime());
}
if (ast.isSpaceAgnostic()) {
spaceAgnostic = true;
} else {
spaces.add(ast.getSpace());
}
}
DbQueryRequest dbRequest = new DbQueryRequest();
dbRequest.setEntityClass(GridRecord.class.getName());
dbRequest.setConstraints(new HashMap<String, RequestConstraint>(rcMap));
for (Entry<String, RequestConstraint> e : orignalConstraints.entrySet()) {
if (!rcMap.containsKey(e.getKey())) {
dbRequest.addConstraint(e.getKey(), e.getValue());
}
}
if (!timeAgnostic) {
RequestConstraint timeRc = new RequestConstraint();
timeRc.setConstraintType(ConstraintType.IN);
for (DataTime time : times) {
timeRc.addToConstraintValueList(time.toString());
}
dbRequest.addConstraint(TIME_FIELD, timeRc);
}
if (!spaceAgnostic) {
RequestConstraint spaceRc = new RequestConstraint();
spaceRc.setConstraintType(ConstraintType.IN);
for (ISpatialObject space : spaces) {
if (space instanceof GridCoverage) {
spaceRc.addToConstraintValueList(Integer
.toString(((GridCoverage) space).getId()));
} else {
// TODO figure out the intersection of my spatial object
// with this spatial object.
}
}
dbRequest.addConstraint(GridConstants.LOCATION_ID, spaceRc);
}
return dbRequest;
}
@Override
@ -300,4 +223,64 @@ public class GridRequestableNode extends AbstractRequestableLevelNode {
this.ensembles = ensembles;
}
private String getSource() {
return rcMap.get(GridConstants.DATASET_ID).getConstraintValue();
}
@Override
public DbQueryRequest getAvailabilityRequest() {
if (GridTimeCache.getInstance().getTimes(this) != null) {
return null;
}
DbQueryRequest request = new DbQueryRequest();
request.setEntityClass(GridRecord.class.getName());
request.addRequestField(TIME_FIELD);
try {
if (CoverageUtils.getInstance().getCoverages(getSource()).size() > 1) {
request.addRequestField(GridConstants.LOCATION_ID);
}
} catch (VizException e) {
// not really a problem, just request the location from db.
UFStatus.getHandler().handle(Priority.VERBOSE,
e.getLocalizedMessage(), e);
request.addRequestField(GridConstants.LOCATION_ID);
}
request.setDistinct(true);
request.setConstraints(rcMap);
return request;
}
@Override
public Set<TimeAndSpace> getAvailability(Object response)
throws VizException {
Set<TimeAndSpace> result = new HashSet<TimeAndSpace>();
if (response == null) {
result = GridTimeCache.getInstance().getTimes(this);
if (result == null) {
// Oh No! the cache has been cleared since we made our request.
response = ThriftClient.sendRequest(getAvailabilityRequest());
return getAvailability(response);
}
GridTimeCache.getInstance().setTimes(this, result);
} else if (response instanceof DbQueryResponse) {
DbQueryResponse dbresponse = (DbQueryResponse) response;
for (Map<String, Object> map : dbresponse.getResults()) {
DataTime time = (DataTime) map.get(TIME_FIELD);
GridCoverage coverage = null;
if (map.containsKey(GridConstants.LOCATION_ID)) {
Number locationId = (Number) map
.get(GridConstants.LOCATION_ID);
coverage = GridCoverageLookup.getInstance().getCoverage(
locationId.intValue());
} else {
coverage = CoverageUtils.getInstance()
.getCoverages(getSource()).iterator().next();
}
result.add(new TimeAndSpace(time, coverage));
}
GridTimeCache.getInstance().setTimes(this, result);
}
return result;
}
}

View file

@ -24,7 +24,7 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
/**
* Cache times for GridRequestableNode's to avoid multiple trips to edex for the
@ -67,14 +67,14 @@ public class GridTimeCache {
private class CacheEntry {
public CacheEntry(Set<DataTime> times) {
public CacheEntry(Set<TimeAndSpace> times) {
this.insertTime = System.currentTimeMillis();
this.times = times;
}
public long insertTime;
public Set<DataTime> times;
public Set<TimeAndSpace> times;
}
@ -121,12 +121,12 @@ public class GridTimeCache {
};
public synchronized void setTimes(GridRequestableNode gNode,
Set<DataTime> times) {
Set<TimeAndSpace> times) {
cache.put(new GridMapKey(gNode.getRequestConstraintMap()),
new CacheEntry(times));
}
public synchronized Set<DataTime> getTimes(GridRequestableNode gNode) {
public synchronized Set<TimeAndSpace> getTimes(GridRequestableNode gNode) {
GridMapKey key = new GridMapKey(gNode.getRequestConstraintMap());
CacheEntry entry = cache.get(key);
if (entry == null) {

View file

@ -44,8 +44,8 @@ import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.alerts.AlertMessage;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode.Dependency;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode.Dependency;
import com.raytheon.uf.viz.derivparam.tree.OrLevelNode;
import com.raytheon.viz.alerts.IAlertObserver;
import com.raytheon.viz.alerts.observers.ProductAlertObserver;
@ -73,9 +73,9 @@ public class GridUpdater implements IAlertObserver {
private class UpdateValue {
public int timeOffset;
public AbstractDerivedLevelNode node;
public AbstractDerivedDataNode node;
public UpdateValue(Integer timeOffset, AbstractDerivedLevelNode node) {
public UpdateValue(Integer timeOffset, AbstractDerivedDataNode node) {
this.timeOffset = timeOffset == null ? 0 : timeOffset;
this.node = node;
}
@ -147,7 +147,7 @@ public class GridUpdater implements IAlertObserver {
ProductAlertObserver.removeObserver(GridInventory.PLUGIN_NAME, this);
}
public synchronized void addNode(AbstractDerivedLevelNode node)
public synchronized void addNode(AbstractDerivedDataNode node)
throws VizException {
List<Dependency> dependencies = node.getDependencies();
if (dependencies == null || dependencies.isEmpty()) {
@ -189,8 +189,8 @@ public class GridUpdater implements IAlertObserver {
updateMap.put(updateKey, set);
}
set.add(new UpdateValue(dependency.timeOffset, node));
} else if (dependency.node instanceof AbstractDerivedLevelNode) {
AbstractDerivedLevelNode dataNode = (AbstractDerivedLevelNode) dependency.node;
} else if (dependency.node instanceof AbstractDerivedDataNode) {
AbstractDerivedDataNode dataNode = (AbstractDerivedDataNode) dependency.node;
for (Dependency d : dataNode.getDependencies()) {
d.timeOffset += dependency.timeOffset;
if (!dep.contains(d)) {
@ -309,14 +309,14 @@ public class GridUpdater implements IAlertObserver {
*/
public synchronized void refreshNodes() {
GridTimeCache.getInstance().flush();
Set<AbstractDerivedLevelNode> oldNodes = new HashSet<AbstractDerivedLevelNode>();
Set<AbstractDerivedDataNode> oldNodes = new HashSet<AbstractDerivedDataNode>();
for (Set<UpdateValue> values : updateMap.values()) {
for (UpdateValue value : values) {
oldNodes.add(value.node);
}
}
updateMap.clear();
for (AbstractDerivedLevelNode node : oldNodes) {
for (AbstractDerivedDataNode node : oldNodes) {
// Get Node will automatically add this to the updater.
inventory.getNode(node.getModelName(), node.getDesc()
.getAbbreviation(), node.getLevel());

View file

@ -19,10 +19,8 @@
**/
package com.raytheon.viz.grid.inv;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Set;
@ -31,16 +29,17 @@ import java.util.TreeSet;
import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfo;
import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfoLookup;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
import com.raytheon.uf.viz.derivparam.tree.AbstractAliasLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.viz.grid.data.ImportRequestableData;
import com.raytheon.viz.grid.util.CoverageUtils;
import com.raytheon.viz.grid.util.RadarAdapter;
/**
@ -71,7 +70,7 @@ public class ImportLevelNode extends AbstractAliasLevelNode {
this.sourceNodeModelName = that.sourceNodeModelName;
}
public ImportLevelNode(AbstractRequestableLevelNode sourceNode,
public ImportLevelNode(AbstractRequestableNode sourceNode,
String sourceNodeModelName, DerivParamDesc desc,
DerivParamMethod method, String modelName, Level level) {
super(sourceNode, desc, method, modelName, level);
@ -79,89 +78,86 @@ public class ImportLevelNode extends AbstractAliasLevelNode {
}
@Override
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
// change out the time queries
DataTime[] selectedTimes = property.getSelectedEntryTime();
int numberOfImages = property.getNumberOfImages();
try {
Set<DataTime> newSelectedTimes = new HashSet<DataTime>(
(int) (selectedTimes.length * 2.5));
for (DataTime time : selectedTimes) {
DataTime[] timesToAdd = boundingSourceTimes.get(time);
Set<AbstractRequestableData> origs = dependencyData.get(sourceNode);
Set<AbstractRequestableData> results = new HashSet<AbstractRequestableData>(
origs.size());
Map<DataTime, AbstractRequestableData> timeMap = new HashMap<DataTime, AbstractRequestableData>(
(int) (origs.size() * 1.25) + 1);
for (AbstractRequestableData orig : origs) {
timeMap.put(orig.getDataTime(), orig);
}
// sanity check
if (timesToAdd != null) {
for (DataTime t : timesToAdd) {
newSelectedTimes.add(t);
}
// need to build ImportRequestableData by bounding nodes
for (TimeAndSpace time : availability) {
DataTime[] timesToAdd = boundingSourceTimes.get(time.getTime());
if (timesToAdd != null) {
AbstractRequestableData beforeData = timeMap.get(timesToAdd[0]);
AbstractRequestableData afterData = null;
if (beforeData == null) {
continue;
}
}
property.setSelectedEntryTimes(newSelectedTimes
.toArray(new DataTime[0]));
property.setNumberOfImages(Math.max(newSelectedTimes.size(),
numberOfImages));
List<AbstractRequestableData> origs = sourceNode.getData(property,
timeOut, cache);
List<AbstractRequestableData> results = new ArrayList<AbstractRequestableData>(
origs.size());
Map<DataTime, AbstractRequestableData> timeMap = new HashMap<DataTime, AbstractRequestableData>(
(int) (origs.size() * 1.25) + 1);
for (AbstractRequestableData orig : origs) {
timeMap.put(orig.getDataTime(), orig);
}
// need to build ImportRequestableData by bounding nodes
for (DataTime time : selectedTimes) {
DataTime[] timesToAdd = boundingSourceTimes.get(time);
if (timesToAdd != null) {
AbstractRequestableData beforeData = timeMap
.get(timesToAdd[0]);
AbstractRequestableData afterData = null;
if (beforeData == null) {
if (timesToAdd.length == 2) {
afterData = timeMap.get(timesToAdd[1]);
if (afterData == null) {
continue;
}
if (timesToAdd.length == 2) {
afterData = timeMap.get(timesToAdd[1]);
if (afterData == null) {
continue;
}
}
AbstractRequestableData result = new ImportRequestableData(
beforeData, afterData, time);
modifyRequest(result);
results.add(result);
}
AbstractRequestableData result = new ImportRequestableData(
beforeData, afterData, time.getTime());
result.setSpace(time.getSpace());
modifyRequest(result);
results.add(result);
}
return results;
} finally {
// make sure to return the selectedEntryTimes to proper value
property.setSelectedEntryTimes(selectedTimes);
property.setNumberOfImages(numberOfImages);
}
return results;
}
@Override
public Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> times) {
Map<AbstractRequestableNode, Set<TimeAndSpace>> result = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
result.put(sourceNode, getSourceAvailability(times));
return result;
}
private Set<TimeAndSpace> getSourceAvailability(Set<TimeAndSpace> times) {
Set<TimeAndSpace> neededTimes = new HashSet<TimeAndSpace>();
for (TimeAndSpace time : times) {
if (time.isTimeAgnostic()) {
for (DataTime[] dtarr : boundingSourceTimes.values()) {
for (DataTime dt : dtarr) {
neededTimes.add(new TimeAndSpace(dt));
}
}
break;
} else {
for (DataTime dt : boundingSourceTimes.get(time.getTime())) {
neededTimes.add(new TimeAndSpace(dt));
}
}
}
return neededTimes;
}
@Override
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
boundingSourceTimes.clear();
// grab this source and discover all available times ala time agnostic,
// then see what is available in the imported source, use time
// interpolation to verify what data can be achieved
NavigableSet<DataTime> sourceDataTimes = new TreeSet<DataTime>(
sourceNode.timeQuery(originalRequest, latestOnly, cache,
latestOnlyCache));
NavigableSet<DataTime> sourceDataTimes = new TreeSet<DataTime>();
for (TimeAndSpace ast : availability.get(sourceNode)) {
sourceDataTimes.add(ast.getTime());
}
DatasetInfo sourceInfo = DatasetInfoLookup.getInstance().getInfo(
sourceNodeModelName);
long sourceDt = 0;
@ -197,8 +193,14 @@ public class ImportLevelNode extends AbstractAliasLevelNode {
boundingSourceTimes.put(time, new DataTime[] { time });
}
}
return boundingSourceTimes.keySet();
Set<TimeAndSpace> result = new HashSet<TimeAndSpace>();
for (DataTime time : boundingSourceTimes.keySet()) {
for (GridCoverage coverage : CoverageUtils.getInstance()
.getCoverages(modelName)) {
result.add(new TimeAndSpace(time, coverage));
}
}
return result;
}
@Override

View file

@ -19,26 +19,12 @@
**/
package com.raytheon.viz.grid.inv;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.radar.RadarRecord;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.library.DerivParamField;
import com.raytheon.uf.viz.derivparam.tree.AbstractCubeLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.uf.viz.derivparam.tree.CubeLevel;
import com.raytheon.viz.grid.data.RadarRequestableData;
/**
*
@ -65,78 +51,14 @@ import com.raytheon.viz.grid.data.RadarRequestableData;
* @version 1.0
*/
public class RadarCubeLevelNode extends AbstractCubeLevelNode {
private String paramAbbrev = null;
public RadarCubeLevelNode(AbstractCubeLevelNode that) {
super(that);
}
public RadarCubeLevelNode(
List<CubeLevel<AbstractRequestableLevelNode, AbstractRequestableLevelNode>> levels,
List<CubeLevel<AbstractRequestableNode, AbstractRequestableNode>> levels,
String modelName, DerivParamField field) {
super(levels, modelName);
paramAbbrev = field.getParam();
}
protected List<AbstractRequestableData> wrapRawRecord(List<Object> objs)
throws VizException {
List<AbstractRequestableData> gribResults = new ArrayList<AbstractRequestableData>(
objs.size());
for (Object obj : objs) {
AbstractRequestableData record = new RadarRequestableData(
(RadarRecord) obj, paramAbbrev);
gribResults.add(record);
}
return gribResults;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.derivparam.tree.AbstractCubeLevelNode#mergedTimeQuery
* (java.util.List, boolean)
*/
@Override
protected Set<DataTime> mergedTimeQuery(
List<Map<String, RequestConstraint>> requests, boolean latestOnly)
throws VizException {
// Make sure we have data on at least two levels
Map<DataTime, Double> single = new HashMap<DataTime, Double>();
Set<DataTime> results = new HashSet<DataTime>();
for (Map<String, RequestConstraint> mergeMap : requests) {
DbQueryRequest request = new DbQueryRequest();
request.setConstraints(mergeMap);
String field = "dataTime";
String levelField = "primaryElevationAngle";
request.addFields(new String[] { field, levelField });
DbQueryResponse response = (DbQueryResponse) ThriftClient
.sendRequest(request);
if (response.getResults() == null) {
continue;
}
for (Map<String, Object> map : response.getResults()) {
DataTime time = (DataTime) map.get(field);
Double level = (Double) map.get(levelField);
if (results.contains(time)) {
continue;
}
if (!single.containsKey(time)) {
single.put(time, level);
} else if (!level.equals(single.get(time))) {
single.remove(time);
results.add(time);
}
}
}
return results;
}
@Override
protected void filter(
Map<String, RequestConstraint> baseRequestConstraints,
Map<String, RequestConstraint> requestContraintsToFilter) {
// do nothing, no filtering necessary for radar
}
}

View file

@ -19,8 +19,6 @@
**/
package com.raytheon.viz.grid.inv;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -31,17 +29,16 @@ import com.raytheon.uf.common.dataplugin.radar.RadarRecord;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.derivparam.tree.LevelNode;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.CatalogQuery;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.tree.AbstractBaseDataNode;
import com.raytheon.viz.grid.data.RadarRequestableData;
import com.raytheon.viz.grid.util.RadarAdapter;
/**
*
@ -59,7 +56,7 @@ import com.raytheon.viz.grid.data.RadarRequestableData;
* @author bsteffen
* @version 1.0
*/
public class RadarRequestableLevelNode extends AbstractRequestableLevelNode {
public class RadarRequestableLevelNode extends AbstractBaseDataNode {
protected static final String TIME_FIELD = "dataTime";
@ -105,42 +102,32 @@ public class RadarRequestableLevelNode extends AbstractRequestableLevelNode {
this.rcMap = rcMap;
}
@Override
public boolean isTimeAgnostic() {
return false;
}
@Override
public Map<String, RequestConstraint> getRequestConstraintMap() {
return rcMap;
}
@Override
public boolean hasRequestConstraints() {
return true;
public DbQueryRequest getAvailabilityRequest() {
return null;
}
@Override
public Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Set<TimeAndSpace> getAvailability(Object response)
throws VizException {
Set<DataTime> resultsSet = RadarUpdater.getInstance().getTimes(this);
Set<TimeAndSpace> resultsSet = RadarUpdater.getInstance()
.getTimes(this);
if (resultsSet != null) {
return resultsSet;
}
DataTime[] results = CatalogQuery.performTimeQuery(rcMap, latestOnly,
null);
DataTime[] results = CatalogQuery.performTimeQuery(rcMap, false, null);
if (results != null) {
resultsSet = new HashSet<DataTime>(results.length);
resultsSet = new HashSet<TimeAndSpace>(results.length);
for (int i = 0; i < results.length; i++) {
resultsSet.add(results[i]);
}
if (!latestOnly) {
RadarUpdater.getInstance().setTimes(this, resultsSet);
resultsSet.add(new TimeAndSpace(results[i], RadarAdapter
.getInstance().getCoverage()));
}
RadarUpdater.getInstance().setTimes(this, resultsSet);
return resultsSet;
} else {
return null;
@ -148,69 +135,31 @@ public class RadarRequestableLevelNode extends AbstractRequestableLevelNode {
}
@Override
protected TimeQueryRequest getTimeQueryInternal(
TimeQueryRequest originalRequest, boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache)
throws VizException {
// TODO Auto-generated method stub
return null;
}
@Override
public List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
DbQueryRequest dbRequest = getDataQueryInternal(property, timeOut,
cache);
DbQueryResponse response = (DbQueryResponse) ThriftClient
.sendRequest(dbRequest);
return processDataQueryResults(response);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* getDataQueryInternal(com.raytheon.uf.viz.core.catalog.LayerProperty, int,
* java.util.Map)
*/
@Override
protected DbQueryRequest getDataQueryInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
public DbQueryRequest getDataRequest(
Map<String, RequestConstraint> orignalConstraints,
Set<TimeAndSpace> availability) {
Map<String, RequestConstraint> newQuery = new HashMap<String, RequestConstraint>(
rcMap);
DbQueryRequest dbRequest = new DbQueryRequest();
DataTime[] times = property.getSelectedEntryTime();
if (times != null && times.length > 0) {
RequestConstraint dtRC = new RequestConstraint();
dtRC.setConstraintType(ConstraintType.IN);
for (DataTime t : times) {
dtRC.addToConstraintValueList(t.toString());
}
newQuery.put("dataTime", dtRC);
RequestConstraint dtRC = new RequestConstraint();
dtRC.setConstraintType(ConstraintType.IN);
for (TimeAndSpace ast : availability) {
dtRC.addToConstraintValueList(ast.getTime().toString());
}
newQuery.put("dataTime", dtRC);
newQuery.put("pluginName", new RequestConstraint("radar"));
dbRequest.setConstraints(newQuery);
return dbRequest;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* processQueryResults
* (com.raytheon.uf.common.dataquery.responses.DbQueryResponse)
*/
@Override
protected List<AbstractRequestableData> processDataQueryResults(
DbQueryResponse response) throws VizException {
List<Map<String, Object>> rows = response.getResults();
List<AbstractRequestableData> rval = new ArrayList<AbstractRequestableData>(
public Set<AbstractRequestableData> getData(
Map<String, RequestConstraint> orignalConstraints,
Set<TimeAndSpace> availability, Object response)
throws VizException {
List<Map<String, Object>> rows = ((DbQueryResponse) response)
.getResults();
Set<AbstractRequestableData> rval = new HashSet<AbstractRequestableData>(
rows.size());
// switch to GribRequestableData and build a grib record from the radar
// record... won't work because of the get data call, can't be a
@ -222,11 +171,6 @@ public class RadarRequestableLevelNode extends AbstractRequestableLevelNode {
return rval;
}
@Override
public List<Dependency> getDependencies() {
return Collections.emptyList();
}
public String getParamAbbrev() {
return paramAbbrev;
}

View file

@ -1,22 +1,3 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.grid.inv;
import java.util.Collection;
@ -40,6 +21,7 @@ import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.alerts.AlertMessage;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.viz.alerts.IAlertObserver;
import com.raytheon.viz.alerts.observers.ProductAlertObserver;
import com.raytheon.viz.grid.util.RadarAdapter;
@ -129,14 +111,14 @@ public class RadarUpdater implements IAlertObserver {
private class CacheEntry {
public CacheEntry(Set<DataTime> times) {
public CacheEntry(Set<TimeAndSpace> times) {
this.insertTime = System.currentTimeMillis();
this.times = times;
}
public long insertTime;
public Set<DataTime> times;
public Set<TimeAndSpace> times;
}
@ -151,7 +133,9 @@ public class RadarUpdater implements IAlertObserver {
}
};
private CacheEntry globalTimes;
private Set<DataTime> globalTimes;
private long globalInsertTime;
private RadarUpdater() {
ProductAlertObserver.addObserver("radar", this);
@ -237,11 +221,12 @@ public class RadarUpdater implements IAlertObserver {
return new CacheKey(productCode, elevationAngle);
}
public void setTimes(RadarRequestableLevelNode rNode, Set<DataTime> times) {
public void setTimes(RadarRequestableLevelNode rNode,
Set<TimeAndSpace> times) {
cache.put(getCacheKey(rNode), new CacheEntry(times));
}
public Set<DataTime> getTimes(RadarRequestableLevelNode rNode) {
public Set<TimeAndSpace> getTimes(RadarRequestableLevelNode rNode) {
CacheKey cacheKey = getCacheKey(rNode);
CacheEntry entry = cache.get(cacheKey);
if (entry == null) {
@ -255,18 +240,19 @@ public class RadarUpdater implements IAlertObserver {
}
public void setGlobalTimes(Set<DataTime> times) {
globalTimes = new CacheEntry(times);
globalTimes = times;
globalInsertTime = System.currentTimeMillis();
}
public Set<DataTime> getGlobalTimes() {
if (globalTimes == null) {
return null;
}
if (globalTimes.insertTime + CACHE_TIME < System.currentTimeMillis()) {
if (globalInsertTime + CACHE_TIME < System.currentTimeMillis()) {
globalTimes = null;
return null;
}
return globalTimes.times;
return globalTimes;
}
public void clearCache() {

View file

@ -0,0 +1,137 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.grid.inv;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.grid.util.StaticGridDataType;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.tree.AbstractBaseDataNode;
import com.raytheon.viz.grid.data.StaticGridRequestableData;
import com.raytheon.viz.grid.data.TiltRequestableData;
import com.raytheon.viz.grid.util.CoverageUtils;
/**
* A LevelNode for static grid data that is either constant or can be calculated
* based off the coverage.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 13, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class StaticGridDataLevelNode extends AbstractBaseDataNode {
private String dataType;
private String source;
public StaticGridDataLevelNode(String source, String dataType) {
this.source = source;
this.dataType = dataType;
}
public StaticGridDataLevelNode(String source, String dataType, Level level) {
this(source, dataType);
setLevel(level);
}
@Override
public DbQueryRequest getAvailabilityRequest() {
return null;
}
@Override
public Set<TimeAndSpace> getAvailability(Object response)
throws VizException {
Set<TimeAndSpace> result = new HashSet<TimeAndSpace>();
for (GridCoverage coverage : CoverageUtils.getInstance().getCoverages(
source)) {
result.add(new TimeAndSpace(coverage));
}
return result;
}
@Override
public DbQueryRequest getDataRequest(
Map<String, RequestConstraint> orignalConstraints,
Set<TimeAndSpace> availability) {
return null;
}
@Override
public Set<AbstractRequestableData> getData(
Map<String, RequestConstraint> orignalConstraints,
Set<TimeAndSpace> availability, Object response)
throws VizException {
Set<AbstractRequestableData> results = new HashSet<AbstractRequestableData>();
for (TimeAndSpace ast : availability) {
if (ast.getSpace() instanceof GridCoverage) {
GridCoverage coverage = (GridCoverage) ast.getSpace();
AbstractRequestableData data = createRequestableData(coverage);
data.setDataTime(ast.getTime());
results.add(data);
} else {
for (GridCoverage coverage : CoverageUtils.getInstance()
.getCoverages(source)) {
AbstractRequestableData data = createRequestableData(coverage);
data.setDataTime(ast.getTime());
results.add(data);
}
}
}
return results;
}
private AbstractRequestableData createRequestableData(GridCoverage coverage) {
if (StaticGridDataType.getStringValues().contains(dataType)) {
StaticGridDataType staticGridDataType = StaticGridDataType
.valueOf(dataType);
return new StaticGridRequestableData(staticGridDataType, source,
coverage);
} else if ("TILT".equals(dataType)) {
return new TiltRequestableData(source, level, coverage);
}
return null;
}
@Override
public boolean isConstant() {
return true;
}
}

View file

@ -35,7 +35,6 @@ import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.viz.grid.data.GridRequestableData;
import com.raytheon.viz.grid.data.TiltRequestableData.TiltCenterPoint;
import com.raytheon.viz.grid.util.CoverageUtils;
import com.raytheon.viz.grid.util.TiltRequest;
/**
@ -64,13 +63,9 @@ public class RequestableDataRecord extends GridRecord {
public RequestableDataRecord(AbstractRequestableData requester)
throws VizException {
this.requester = requester;
GridCoverage coverage = CoverageUtils.getInstance().getCoverage(
requester.getSource());
if (coverage == null && requester instanceof GridRequestableData) {
coverage = ((GridRequestableData) requester).getGridSource()
.getLocation();
CoverageUtils.getInstance().setCoverage(requester.getSource(),
coverage);
GridCoverage coverage = null;
if (requester.getSpace() instanceof GridCoverage) {
coverage = (GridCoverage) requester.getSpace();
}
setDatasetId(requester.getSource());
setLocation(coverage);

View file

@ -913,7 +913,14 @@ public abstract class AbstractGridResource<T extends AbstractResourceData>
}
protected List<PluginDataObject> getPluginDataObjects(DataTime time) {
return new ArrayList<PluginDataObject>(pdoMap.get(time));
if (time == null) {
return null;
}
List<PluginDataObject> list = pdoMap.get(time);
if (list == null) {
return null;
}
return new ArrayList<PluginDataObject>(list);
}
}

View file

@ -333,14 +333,4 @@ public class CoverageUtils implements IAlertObserver {
}
}
// use getCoverages to work with moving grids.
@Deprecated
public GridCoverage getCoverage(String modelName) throws VizException {
Collection<GridCoverage> coverages = getCoverages(modelName);
if (coverages == null || coverages.isEmpty()) {
return null;
}
return coverages.iterator().next();
}
}

View file

@ -24,6 +24,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -46,6 +47,7 @@ import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.ISpatialEnabled;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
@ -57,14 +59,18 @@ import com.raytheon.uf.viz.core.datastructure.VizDataCubeException;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractDataCubeAdapter;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.AvailabilityContainer;
import com.raytheon.uf.viz.derivparam.inv.MetadataContainer;
import com.raytheon.uf.viz.derivparam.library.DerivedParameterGenerator;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.viz.grid.data.GridRequestableData;
import com.raytheon.viz.grid.inv.GridInventory;
import com.raytheon.viz.grid.inv.GridMetadataContainer;
import com.raytheon.viz.grid.record.RequestableDataRecord;
/**
* A DataCubeAdapter that handles all access to the grid plugin.
* DataCubeAdapter for Grid, the primary role is to link the grid datatype into
* derived parameters.
*
* <pre>
*
@ -380,7 +386,7 @@ public class GridDataCubeAdapter extends AbstractDataCubeAdapter {
* evaluateRequestConstraints(java.util.Map)
*/
@Override
protected List<AbstractRequestableLevelNode> evaluateRequestConstraints(
protected List<AbstractRequestableNode> evaluateRequestConstraints(
Map<String, RequestConstraint> constraints) {
return gridInventory.evaluateRequestConstraints(constraints);
}
@ -411,7 +417,8 @@ public class GridDataCubeAdapter extends AbstractDataCubeAdapter {
List<Object> results = new ArrayList<Object>(requesters.size());
for (AbstractRequestableData requester : requesters) {
List<RequestableDataRecord> records = new ArrayList<RequestableDataRecord>();
if (requester.getDataTime() == null) {
if (requester.getDataTime() == null
|| requester.getTimeAndSpace().isTimeAgnostic()) {
DataTime[] entryTime = property.getSelectedEntryTime();
if (entryTime != null && entryTime.length > 0) {
List<DataTime> entryTimes = new ArrayList<DataTime>(
@ -448,6 +455,28 @@ public class GridDataCubeAdapter extends AbstractDataCubeAdapter {
RequestableDataRecord rec = new RequestableDataRecord(requester);
records.add(rec);
}
if (requester.getSpace() == null
|| requester.getTimeAndSpace().isSpaceAgnostic()) {
Collection<GridCoverage> coverages = CoverageUtils
.getInstance().getCoverages(requester.getSource());
if (coverages != null && !coverages.isEmpty()) {
List<RequestableDataRecord> spaceRecords = new ArrayList<RequestableDataRecord>();
for (RequestableDataRecord record : records) {
for (GridCoverage coverage : coverages) {
record = new RequestableDataRecord(record);
record.setLocation(coverage);
try {
record.setDataURI(null);
record.constructDataURI();
} catch (PluginException e) {
throw new VizException(e);
}
spaceRecords.add(record);
}
}
records = spaceRecords;
}
}
results.addAll(records);
}
if (property.getEntryQueryParameters(false).containsKey(
@ -463,4 +492,19 @@ public class GridDataCubeAdapter extends AbstractDataCubeAdapter {
return results;
}
@Override
protected MetadataContainer createMetadataContainer(
Map<String, RequestConstraint> constraints) {
return new GridMetadataContainer(constraints);
}
@Override
protected AvailabilityContainer createAvailabilityContainer() {
// using a grid specific container which is able to merge constraints
// will result in faster database queries, however the extra processing
// time it takes to route the times to the correct nodes is larger than
// the time saved.
return super.createAvailabilityContainer();
}
}

View file

@ -20,20 +20,17 @@
package com.raytheon.viz.grid.util;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.derivparam.tree.LevelNode;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.data.FloatRequestableData;
import com.raytheon.uf.viz.derivparam.library.IDerivParamField;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode.Dependency;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode.Dependency;
import com.raytheon.uf.viz.derivparam.tree.DerivedLevelNode;
import com.raytheon.uf.viz.derivparam.tree.StaticDataLevelNode;
import com.raytheon.viz.grid.inv.GridInventory;
@ -114,12 +111,8 @@ public class GridTreeGrapher {
}
} else if (node instanceof StaticDataLevelNode) {
StaticDataLevelNode cNode = (StaticDataLevelNode) node;
AbstractRequestableData staticData = cNode
.getData(
new LayerProperty(),
0,
new HashMap<AbstractRequestableLevelNode, List<AbstractRequestableData>>())
.get(0);
AbstractRequestableData staticData = cNode.getData(null, null)
.iterator().next();
if (staticData instanceof FloatRequestableData) {
String abbr = node.getClass().getSimpleName();
if (cNode.getDesc() != null) {
@ -142,8 +135,8 @@ public class GridTreeGrapher {
System.out.println("node" + i + " -> node" + that);
}
}
} else if (node instanceof AbstractDerivedLevelNode) {
AbstractDerivedLevelNode cNode = (AbstractDerivedLevelNode) node;
} else if (node instanceof AbstractDerivedDataNode) {
AbstractDerivedDataNode cNode = (AbstractDerivedDataNode) node;
String abbr = node.getClass().getSimpleName();
if (cNode.getDesc() != null) {
abbr = cNode.getDesc().getAbbreviation();

View file

@ -59,7 +59,7 @@ import com.raytheon.uf.viz.core.style.level.Level.LevelType;
import com.raytheon.uf.viz.core.style.level.SingleLevel;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.uf.viz.derivparam.tree.OrLevelNode;
import com.raytheon.uf.viz.derivparam.tree.StaticDataLevelNode;
import com.raytheon.viz.core.drawables.ColorMapParameterFactory;
@ -271,7 +271,7 @@ public class RadarAdapter {
desc,
method,
RADAR_SOURCE,
new ArrayList<AbstractRequestableLevelNode>(
new ArrayList<AbstractRequestableNode>(
productCodes.size()), false);
gridParameterNode.addChildNode(gridLevelNode);
}
@ -326,9 +326,11 @@ public class RadarAdapter {
topoParam.setParameterUnit("m");
topoParam.setValue("Topo");
StaticDataLevelNode topoNode = new StaticDataLevelNode(sfc, topo,
new TopoRequestableData(modelNameNode.getValue()),
TopoRequestableData topoData = new TopoRequestableData(
modelNameNode.getValue());
topoData.setSpace(getCoverage());
StaticDataLevelNode topoNode = new StaticDataLevelNode(sfc, topo,
topoData, modelNameNode.getValue());
topoNode.setLevel(sfc);
topoParam.addChildNode(topoNode);
modelNameNode.addChildNode(topoParam);

View file

@ -10,8 +10,6 @@ Require-Bundle: org.apache.batik,
org.eclipse.ui,
org.eclipse.core.runtime,
com.raytheon.viz.core,
com.raytheon.uf.viz.core,
org.geotools,
com.raytheon.viz.ui,
org.apache.commons.lang,
javax.measure,
@ -28,12 +26,12 @@ Export-Package: com.raytheon.viz.pointdata,
com.raytheon.viz.pointdata.util
Import-Package: com.raytheon.edex.meteoLib,
com.raytheon.uf.common.comm,
com.raytheon.uf.common.dataplugin.grid,
com.raytheon.uf.common.dataplugin.level,
com.raytheon.uf.common.derivparam.tree,
com.raytheon.uf.common.message.response,
com.raytheon.uf.common.pointdata,
com.raytheon.uf.common.pointdata.accumulate,
com.raytheon.uf.common.serialization.comm,
com.raytheon.uf.viz.derivparam.data,
com.raytheon.uf.viz.derivparam.inv,
com.raytheon.uf.viz.derivparam.library,

View file

@ -49,11 +49,12 @@ import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamField;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod.MethodType;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
/**
* TODO Add Description
* Abstract implementation of a point data inventory that can be used by
* datatypes that have point data but don't adhere fully to the point data api.
*
* <pre>
*
@ -95,7 +96,7 @@ public abstract class AbstractPointDataInventory extends AbstractInventory {
}
}
public List<AbstractRequestableLevelNode> getNodes(String source,
public List<AbstractRequestableNode> getNodes(String source,
List<String> parameters, List<Level> levels) throws VizException {
parameters = new ArrayList<String>(parameters);
try {
@ -176,15 +177,15 @@ public abstract class AbstractPointDataInventory extends AbstractInventory {
}
@Override
protected AbstractDerivedLevelNode getImportNode(
protected AbstractDerivedDataNode getImportNode(
AbstractRequestableData nodeToImport, SourceNode destSourceNode,
DerivParamDesc desc, DerivParamMethod method, Level level) {
return null;
}
@Override
protected AbstractDerivedLevelNode getImportNode(
AbstractRequestableLevelNode nodeToImport,
protected AbstractDerivedDataNode getImportNode(
AbstractRequestableNode nodeToImport,
String nodeToImportSourceName, SourceNode destSourceNode,
DerivParamDesc desc, DerivParamMethod method, Level level) {
return null;
@ -212,7 +213,7 @@ public abstract class AbstractPointDataInventory extends AbstractInventory {
}
@Override
protected AbstractDerivedLevelNode createDerivedNode(DerivParamDesc desc,
protected AbstractDerivedDataNode createDerivedNode(DerivParamDesc desc,
DerivParamMethod method, Level level, List<Object> fields,
SourceNode source) {
if (method.getMethodType() == MethodType.OTHER) {
@ -220,22 +221,23 @@ public abstract class AbstractPointDataInventory extends AbstractInventory {
int index = fields.size() - 1;
index -= 4; // The last 4 fields in order are time, paramName,
// totalTime, time increment
AbstractRequestableLevelNode tNode = (AbstractRequestableLevelNode) fields
AbstractRequestableNode tNode = (AbstractRequestableNode) fields
.get(index + 1);
List<AbstractRequestableLevelNode> idNodes = new ArrayList<AbstractRequestableLevelNode>(
List<AbstractRequestableNode> idNodes = new ArrayList<AbstractRequestableNode>(
index + 1);
for (int i = 0; i <= index; i++) {
idNodes.add((AbstractRequestableLevelNode) fields.get(i));
idNodes.add((AbstractRequestableNode) fields.get(i));
}
return new PointAccumLevelNode(desc, method, idNodes, tNode);
return new PointAccumLevelNode(desc, method, idNodes, tNode,
source.getValue());
} else if (method.getName().equalsIgnoreCase("HeightOf")) {
AbstractRequestableLevelNode latNode = (AbstractRequestableLevelNode) fields
AbstractRequestableNode latNode = (AbstractRequestableNode) fields
.get(0);
AbstractRequestableLevelNode lonNode = (AbstractRequestableLevelNode) fields
AbstractRequestableNode lonNode = (AbstractRequestableNode) fields
.get(1);
AbstractRequestableLevelNode timeNode = null;
AbstractRequestableNode timeNode = null;
if (fields.size() > 2) {
timeNode = (AbstractRequestableLevelNode) fields.get(2);
timeNode = (AbstractRequestableNode) fields.get(2);
}
return new HeightOfLevelNode(level, desc, method, latNode,
lonNode, timeNode);

View file

@ -20,23 +20,24 @@
package com.raytheon.viz.pointdata.util;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.AvailabilityContainer;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
/**
* TODO Add Description
* Node for the HeightOf point data derived parameter
*
* <pre>
*
@ -51,13 +52,13 @@ import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
* @version 1.0
*/
public class HeightOfLevelNode extends AbstractDerivedLevelNode {
public class HeightOfLevelNode extends AbstractDerivedDataNode {
private AbstractRequestableLevelNode latNode;
private AbstractRequestableNode latNode;
private AbstractRequestableLevelNode lonNode;
private AbstractRequestableNode lonNode;
private AbstractRequestableLevelNode timeNode;
private AbstractRequestableNode timeNode;
/**
* @param desc
@ -66,40 +67,43 @@ public class HeightOfLevelNode extends AbstractDerivedLevelNode {
* @param lonNode
*/
public HeightOfLevelNode(Level level, DerivParamDesc desc,
DerivParamMethod method, AbstractRequestableLevelNode latNode,
AbstractRequestableLevelNode lonNode,
AbstractRequestableLevelNode timeNode) {
DerivParamMethod method, AbstractRequestableNode latNode,
AbstractRequestableNode lonNode, AbstractRequestableNode timeNode) {
super(level, desc, method, null);
this.latNode = latNode;
this.lonNode = lonNode;
this.timeNode = timeNode;
}
/*
* (non-Javadoc)
*
* @seecom.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* getDataInternal(com.raytheon.uf.viz.core.catalog.LayerProperty, int,
* java.util.Map)
*/
@Override
protected List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
public Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> availability) throws VizException {
Map<AbstractRequestableNode, Set<TimeAndSpace>> result = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
result.put(latNode, availability);
result.put(lonNode, availability);
if (timeNode != null) {
result.put(timeNode, availability);
}
return result;
}
@Override
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
AbstractRequestableData latRequest = latNode.getData(property, timeOut,
cache).get(0);
AbstractRequestableData lonRequest = lonNode.getData(property, timeOut,
cache).get(0);
AbstractRequestableData latRequest = dependencyData.get(latNode)
.iterator().next();
AbstractRequestableData lonRequest = dependencyData.get(lonNode)
.iterator().next();
AbstractRequestableData timeRequest = null;
if (timeNode != null) {
timeRequest = timeNode.getData(property, timeOut, cache).get(0);
timeRequest = dependencyData.get(timeNode).iterator().next();
}
AbstractRequestableData heightOf = new HeightOfRequestableData(
this.getLevel(), this.desc.getAbbreviation(), latRequest,
lonRequest, timeRequest);
return Arrays.asList(heightOf);
return new HashSet<AbstractRequestableData>(Arrays.asList(heightOf));
}
/*
@ -119,23 +123,10 @@ public class HeightOfLevelNode extends AbstractDerivedLevelNode {
}
}
/*
* (non-Javadoc)
*
* @seecom.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* timeQueryInternal(boolean, java.util.Map)
*/
@Override
protected Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
return TIME_AGNOSTIC;
}
@Override
public boolean isTimeAgnostic() {
return true;
return AvailabilityContainer.AGNOSTIC_SET;
}
}

View file

@ -31,6 +31,7 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.edex.meteoLib.Controller;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
@ -48,7 +49,7 @@ import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.vividsolutions.jts.geom.Coordinate;
/**
* TODO Add Description
* Determines the height of a point using gridded data if it is available.
*
* <pre>
*
@ -185,16 +186,18 @@ public class HeightOfRequestableData extends AbstractRequestableData {
private Map<String, RequestConstraint> getConstraints() {
Map<String, RequestConstraint> constraints = new HashMap<String, RequestConstraint>();
constraints.put("pluginName", new RequestConstraint("grib"));
constraints.put("modelInfo.parameterAbbreviation",
constraints.put(GridConstants.PLUGIN_NAME, new RequestConstraint(
GridConstants.GRID));
constraints.put(GridConstants.PARAMETER_ABBREVIATION,
new RequestConstraint("GH"));
constraints.put("modelInfo.modelName", new RequestConstraint("GFS212"));
constraints.put("modelInfo.level.masterLevel.name",
new RequestConstraint(level.getMasterLevel().getName()));
constraints.put("modelInfo.level.levelonevalue", new RequestConstraint(
level.getLevelOneValueAsString().toString()));
constraints.put("modelInfo.level.leveltwovalue", new RequestConstraint(
Level.getInvalidLevelValueAsString()));
constraints.put(GridConstants.DATASET_ID, new RequestConstraint(
"GFS212"));
constraints.put(GridConstants.MASTER_LEVEL_NAME, new RequestConstraint(
level.getMasterLevel().getName()));
constraints.put(GridConstants.LEVEL_ONE, new RequestConstraint(level
.getLevelOneValueAsString().toString()));
constraints.put(GridConstants.LEVEL_TWO,
new RequestConstraint(Level.getInvalidLevelValueAsString()));
return constraints;
}

View file

@ -21,22 +21,24 @@ package com.raytheon.viz.pointdata.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.AvailabilityContainer;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.library.DerivParamDesc;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractDerivedDataNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
/**
* TODO Add Description
* A Node representing the Accum derived paramteer method which is used by point
* data to generate accumulations over time.
*
* <pre>
*
@ -51,52 +53,61 @@ import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
* @version 1.0
*/
public class PointAccumLevelNode extends AbstractDerivedLevelNode {
public class PointAccumLevelNode extends AbstractDerivedDataNode {
private List<AbstractRequestableLevelNode> idNodes;
private List<AbstractRequestableNode> idNodes;
private AbstractRequestableLevelNode timeNode;
private AbstractRequestableNode timeNode;
private String plugin;
public PointAccumLevelNode(PointAccumLevelNode that) {
super(that);
this.idNodes = that.idNodes;
this.timeNode = that.timeNode;
this.plugin = that.plugin;
}
public PointAccumLevelNode(DerivParamDesc desc, DerivParamMethod method,
List<AbstractRequestableLevelNode> idNodes,
AbstractRequestableLevelNode timeNode) {
List<AbstractRequestableNode> idNodes,
AbstractRequestableNode timeNode, String plugin) {
super(PointDataInventory.getStationLevel(), desc, method, null);
this.idNodes = idNodes;
this.timeNode = timeNode;
this.plugin = plugin;
}
/*
* (non-Javadoc)
*
* @seecom.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* getDataInternal(com.raytheon.uf.viz.core.catalog.LayerProperty, int,
* java.util.Map)
*/
@Override
protected List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
public Map<AbstractRequestableNode, Set<TimeAndSpace>> getDataDependency(
Set<TimeAndSpace> availability) throws VizException {
Map<AbstractRequestableNode, Set<TimeAndSpace>> rval = new HashMap<AbstractRequestableNode, Set<TimeAndSpace>>();
for (AbstractRequestableNode idNode : idNodes) {
rval.put(idNode, availability);
}
rval.put(timeNode, availability);
return rval;
}
@Override
public Set<AbstractRequestableData> getData(
Set<TimeAndSpace> availability,
Map<AbstractRequestableNode, Set<AbstractRequestableData>> dependencyData)
throws VizException {
List<AbstractRequestableData> idRequesters = new ArrayList<AbstractRequestableData>(
idNodes.size());
for (AbstractRequestableLevelNode idNode : idNodes) {
idRequesters.add(idNode.getData(property, timeOut, cache).get(0));
for (AbstractRequestableNode idNode : idNodes) {
AbstractRequestableData idRequester = dependencyData.get(idNode)
.iterator().next();
idRequesters.add(idRequester);
}
AbstractRequestableData rData = new PointAccumRequestableData(
idRequesters,
timeNode.getData(property, timeOut, cache).get(0), method,
property);
idRequesters, dependencyData.get(timeNode).iterator().next(),
method, plugin);
rData.setParameter(desc.getAbbreviation());
rData.setParameterName(desc.getName());
rData.setUnit(desc.getUnit());
return Arrays.asList(rData);
return new HashSet<AbstractRequestableData>(Arrays.asList(rData));
}
/*
@ -109,30 +120,17 @@ public class PointAccumLevelNode extends AbstractDerivedLevelNode {
public List<Dependency> getDependencies() {
List<Dependency> dependencies = new ArrayList<Dependency>();
dependencies.add(new Dependency(timeNode, 0));
for (AbstractRequestableLevelNode idNode : idNodes) {
for (AbstractRequestableNode idNode : idNodes) {
dependencies.add(new Dependency(idNode, 0));
}
return dependencies;
}
/*
* (non-Javadoc)
*
* @seecom.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* timeQueryInternal(boolean, java.util.Map)
*/
@Override
protected Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
public Set<TimeAndSpace> getAvailability(
Map<AbstractRequestableNode, Set<TimeAndSpace>> availability)
throws VizException {
return TIME_AGNOSTIC;
}
@Override
public boolean isTimeAgnostic() {
return true;
return AvailabilityContainer.AGNOSTIC_SET;
}
public PointAccumLevelNode clone() {

View file

@ -30,7 +30,6 @@ import com.raytheon.uf.common.datastorage.records.IntegerDataRecord;
import com.raytheon.uf.common.datastorage.records.LongDataRecord;
import com.raytheon.uf.common.datastorage.records.StringDataRecord;
import com.raytheon.uf.common.pointdata.accumulate.AccumDataRequestMessage;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
@ -39,7 +38,8 @@ import com.raytheon.uf.viz.derivparam.library.DerivParamField;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod;
/**
* TODO Add Description
* Carries out the Accum derived parameter method by sending an accum request to
* edex.
*
* <pre>
*
@ -65,12 +65,10 @@ public class PointAccumRequestableData extends AbstractRequestableData {
public PointAccumRequestableData(
List<AbstractRequestableData> idRequesters,
AbstractRequestableData timeRequester, DerivParamMethod method,
LayerProperty property) throws VizException {
String plugin) throws VizException {
this.idRequesters = idRequesters;
this.timeRequester = timeRequester;
this.request = new AccumDataRequestMessage();
String plugin = property.getEntryQueryParameters(false)
.get("pluginName").getConstraintValue();
int index = method.getFields().size() - 1;
int minutes = ((DerivParamConstantField) method.getFields()
.get(index--)).getValue().intValue();

View file

@ -22,11 +22,8 @@ package com.raytheon.viz.pointdata.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.level.Level;
@ -52,17 +49,19 @@ import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.level.LevelMappingFactory;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.AvailabilityContainer;
import com.raytheon.uf.viz.derivparam.library.DerivedParameterGenerator;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode.Dependency;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
import com.raytheon.viz.pointdata.PointDataRequest;
/**
* This adapter allows a user to request derived parameters from point data
* sets. It is important to note that the parameter names differ between grid
* and point datasets so any derived parameter writer will need to provide
* execute methods for both data types. An obvious example would be Wind Chill
* but would easily apply to other derived parameters.
* sets. It is important to note that derived parameters for point data is much
* different than grid. The primary difference is that while grid is combining
* multiple records that represent different parameters, point data is combining
* multiple paramters within a single record. As a result point data does not
* use the time and space matching functions of derived parameters since they
* are guaranteed to match for all parameters within a record.
*
* <pre>
*
@ -146,51 +145,22 @@ public class PointDataCubeAdapter implements IDataCubeAdapter {
List<Level> levels = LevelMappingFactory.getInstance()
.getLevelMappingForKey(levelKey).getLevels();
List<AbstractRequestableLevelNode> nodes = inventory.getNodes(source,
List<AbstractRequestableNode> nodes = inventory.getNodes(source,
Arrays.asList(parameters), levels);
// Now we have the nodes, rig the dependencies
List<AbstractRequestableLevelNode> deps = new ArrayList<AbstractRequestableLevelNode>(
nodes);
Set<PointDataLevelNode> baseNodes = new HashSet<PointDataLevelNode>();
Set<String> baseParams = new HashSet<String>();
for (int i = 0; i < deps.size(); i++) {
AbstractRequestableLevelNode node = deps.get(i);
if (node instanceof PointDataLevelNode) {
baseNodes.add((PointDataLevelNode) node);
baseParams.add(((PointDataLevelNode) node).getParameter());
} else {
for (Dependency dep : node.getDependencies()) {
deps.add(dep.node);
}
}
PointMetadataContainer pmc = new PointMetadataContainer(queryParams,
Arrays.asList(parameters), this);
for (AbstractRequestableNode node : nodes) {
pmc.prepareRequests(node, AvailabilityContainer.AGNOSTIC_SET);
}
if (Arrays.asList(parameters).contains("dataURI")) {
baseParams.add("dataURI");
}
PointDataContainer pdc = getBaseRecords(baseParams, queryParams);
if (pdc == null) {
return pdc;
}
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache = new HashMap<AbstractRequestableLevelNode, List<AbstractRequestableData>>();
for (PointDataLevelNode node : baseNodes) {
IDataRecord rec = pdc.getParameterRecord(node.getParameter());
cache.put(node, Arrays
.asList((AbstractRequestableData) new PointRequestableData(
rec, pdc.getDescription(node.getParameter())
.getUnitObject())));
if (nodes.contains(node)) {
nodes.remove(node);
} else if (!Arrays.asList("id", "latitude", "longitude", "dataURI")
.contains(rec.getName())) {
pdc.remove(rec.getName());
}
}
LayerProperty lp = new LayerProperty();
lp.setEntryQueryParameters(queryParams, false);
List<AbstractRequestableData> requests = new ArrayList<AbstractRequestableData>();
for (AbstractRequestableLevelNode node : nodes) {
requests.addAll(node.getData(lp, 60000, cache));
for (AbstractRequestableNode node : nodes) {
requests.addAll(pmc.getData(node,
AvailabilityContainer.AGNOSTIC_SET));
}
PointDataContainer pdc = pmc.getContainer();
if (pdc == null) {
return null;
}
for (AbstractRequestableData request : requests) {
String unit = request.getUnit() == null ? null : request.getUnit()
@ -253,7 +223,7 @@ public class PointDataCubeAdapter implements IDataCubeAdapter {
return type;
}
protected PointDataContainer getBaseRecords(Collection<String> baseParams,
public PointDataContainer getBaseRecords(Collection<String> baseParams,
Map<String, RequestConstraint> queryParams) throws VizException {
String plugin = queryParams.get(PLUGIN_NAME).getConstraintValue();
return PointDataRequest.requestPointDataAllLevels(null, plugin,

View file

@ -19,24 +19,21 @@
**/
package com.raytheon.viz.pointdata.util;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.derivparam.tree.LevelNode;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
import com.raytheon.uf.viz.derivparam.inv.AvailabilityContainer;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
import com.raytheon.uf.viz.derivparam.tree.AbstractBaseDataNode;
/**
* TODO Add Description
* A BaseDataNode for PointData types so that they can be used within derived
* parameters.
*
* <pre>
*
@ -51,7 +48,7 @@ import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode;
* @version 1.0
*/
public class PointDataLevelNode extends AbstractRequestableLevelNode {
public class PointDataLevelNode extends AbstractBaseDataNode {
private String parameter;
@ -72,101 +69,19 @@ public class PointDataLevelNode extends AbstractRequestableLevelNode {
return parameter;
}
/*
* (non-Javadoc)
*
* @seecom.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* getDataInternal(com.raytheon.uf.viz.core.catalog.LayerProperty, int,
* java.util.Map)
*/
@Override
protected List<AbstractRequestableData> getDataInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
return cache.remove(this);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* getDataQueryInternal(com.raytheon.uf.viz.core.catalog.LayerProperty, int,
* java.util.Map)
*/
@Override
protected DbQueryRequest getDataQueryInternal(
LayerProperty property,
int timeOut,
Map<AbstractRequestableLevelNode, List<AbstractRequestableData>> cache)
throws VizException {
throw new UnsupportedOperationException(
"PointData nodes do not support returning data query");
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* processQueryResults
* (com.raytheon.uf.common.dataquery.responses.DbQueryResponse)
*/
@Override
protected List<AbstractRequestableData> processDataQueryResults(
DbQueryResponse queryResponse) throws VizException {
throw new UnsupportedOperationException(
"PointData nodes do not support processing data query");
}
@Override
protected TimeQueryRequest getTimeQueryInternal(
TimeQueryRequest originalRequest, boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache)
throws VizException {
throw new UnsupportedOperationException(
"PointData nodes do not support returning time query");
}
/*
* (non-Javadoc)
*
* @seecom.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* getDependencies()
*/
@Override
public List<Dependency> getDependencies() {
return Collections.emptyList();
}
/*
* (non-Javadoc)
*
* @seecom.raytheon.uf.viz.derivparam.tree.AbstractRequestableLevelNode#
* timeQueryInternal(boolean, java.util.Map)
*/
@Override
protected Set<DataTime> timeQueryInternal(TimeQueryRequest originalRequest,
boolean latestOnly,
Map<AbstractRequestableLevelNode, Set<DataTime>> cache,
Map<AbstractRequestableLevelNode, Set<DataTime>> latestOnlyCache)
throws VizException {
return TIME_AGNOSTIC;
}
@Override
public boolean isTimeAgnostic() {
return true;
}
@Override
public Map<String, RequestConstraint> getRequestConstraintMap() {
public DbQueryRequest getDataRequest(
Map<String, RequestConstraint> orignalConstraints,
Set<TimeAndSpace> availability) {
return null;
}
@Override
public boolean hasRequestConstraints() {
return false;
public Set<AbstractRequestableData> getData(
Map<String, RequestConstraint> orignalConstraints,
Set<TimeAndSpace> availability, Object response)
throws VizException {
return null;
}
/*
@ -209,4 +124,15 @@ public class PointDataLevelNode extends AbstractRequestableLevelNode {
public PointDataLevelNode clone() {
return new PointDataLevelNode(this);
}
@Override
public DbQueryRequest getAvailabilityRequest() {
return null;
}
@Override
public Set<TimeAndSpace> getAvailability(Object response) {
return AvailabilityContainer.AGNOSTIC_SET;
}
}

View file

@ -0,0 +1,115 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.pointdata.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.pointdata.PointDataContainer;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.MetadataContainer;
import com.raytheon.uf.viz.derivparam.tree.AbstractRequestableNode;
/**
* A MetadataContainer that is optimized for point data. This container ensures
* that the point data api is used properly to bulk request all the base
* parameters at once.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 13, 2012 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class PointMetadataContainer extends MetadataContainer {
private final PointDataCubeAdapter pdca;
private final List<String> requestedParameters;
private PointDataContainer pdc;
public PointMetadataContainer(
Map<String, RequestConstraint> originalConstraints,
List<String> requestedParameters, PointDataCubeAdapter pdca) {
super(originalConstraints);
this.requestedParameters = requestedParameters;
this.pdca = pdca;
}
public PointDataContainer getContainer() {
return pdc;
}
/**
* For point data need the full data record instead of just a simple db
* request, this method handles requesting all the parameters using the
* point data API at one time.
*/
@Override
protected void processRequests() throws VizException {
List<PointDataLevelNode> nodes = new ArrayList<PointDataLevelNode>();
List<String> baseParams = new ArrayList<String>();
for (AbstractRequestableNode node : availCache.keySet()) {
if (dataCache.containsKey(node)) {
continue;
}
if (node instanceof PointDataLevelNode) {
PointDataLevelNode dataNode = (PointDataLevelNode) node;
nodes.add(dataNode);
baseParams.add(dataNode.getParameter());
}
}
if (baseParams.isEmpty()) {
return;
}
if (requestedParameters.contains("dataURI")) {
baseParams.add("dataURI");
}
pdc = pdca.getBaseRecords(baseParams, originalConstraints);
for (PointDataLevelNode node : nodes) {
IDataRecord rec = pdc.getParameterRecord(node.getParameter());
Set<AbstractRequestableData> cacheSet = new HashSet<AbstractRequestableData>();
cacheSet.add(new PointRequestableData(rec, pdc.getDescription(
node.getParameter()).getUnitObject()));
dataCache.put(node, cacheSet);
if (!Arrays.asList("id", "latitude", "longitude", "dataURI")
.contains(rec.getName())) {
pdc.remove(rec.getName());
}
}
}
}

View file

@ -24,9 +24,11 @@ import javax.measure.unit.Unit;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.derivparam.data.AbstractRequestableData;
import com.raytheon.uf.viz.derivparam.inv.TimeAndSpace;
/**
* TODO Add Description
* Wraps a data record from a PointDataContainer in the AbstractRequestableData
* api so it can be used in Derived Parameters
*
* <pre>
*
@ -50,6 +52,8 @@ public class PointRequestableData extends AbstractRequestableData {
this.rec = rec;
this.level = PointDataInventory.getStationLevel();
this.parameter = rec.getName();
this.dataTime = TimeAndSpace.TIME_AGNOSTIC;
this.space = TimeAndSpace.SPACE_AGNOSTIC;
}
/*

View file

@ -110,7 +110,7 @@ public class RadarDataCubeAdapter extends PointDataCubeAdapter {
}
@Override
protected PointDataContainer getBaseRecords(
public PointDataContainer getBaseRecords(
Collection<String> baseParameters,
Map<String, RequestConstraint> queryParams) throws VizException {
return ((VwpInventory) inventory).getBaseRecords(baseParameters,