Issue #2947 Switch derived parameter space amtching to use IGridGeometryProvider.

Former-commit-id: c5c0dcaab8e495970438f134625ac2847f9bcf9f
This commit is contained in:
Ben Steffensmeier 2014-04-11 17:31:00 -05:00
parent e911a4c917
commit 1ad8396366
7 changed files with 234 additions and 177 deletions

View file

@ -26,10 +26,6 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.raytheon.uf.common.inventory.data.AbstractRequestableData;
import com.raytheon.uf.common.inventory.exception.DataCubeException;
import com.raytheon.uf.common.inventory.TimeAndSpace;
import com.raytheon.uf.common.inventory.tree.LevelNode;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
@ -37,9 +33,13 @@ import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.derivparam.tree.AbstractBaseDataNode;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.common.gridcoverage.lookup.GridCoverageLookup;
import com.raytheon.uf.common.inventory.TimeAndSpace;
import com.raytheon.uf.common.inventory.data.AbstractRequestableData;
import com.raytheon.uf.common.inventory.exception.DataCubeException;
import com.raytheon.uf.common.inventory.tree.LevelNode;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
@ -55,9 +55,11 @@ import com.raytheon.viz.grid.util.CoverageUtils;
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 19, 2010 bsteffen Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jan 19, 2010 bsteffen Initial creation
* Apr 11, 2014 2947 bsteffen Switch spatial matching to use
* IGridGeometryProvider
*
* </pre>
*
@ -130,7 +132,7 @@ public class GridRequestableNode extends AbstractBaseDataNode {
boolean timeAgnostic = false;
boolean spaceAgnostic = false;
Set<DataTime> times = new HashSet<DataTime>();
Set<ISpatialObject> spaces = new HashSet<ISpatialObject>();
Set<IGridGeometryProvider> spaces = new HashSet<IGridGeometryProvider>();
for (TimeAndSpace ast : availability) {
if (ast.isTimeAgnostic()) {
timeAgnostic = true;
@ -162,7 +164,7 @@ public class GridRequestableNode extends AbstractBaseDataNode {
if (!spaceAgnostic) {
RequestConstraint spaceRc = new RequestConstraint();
spaceRc.setConstraintType(ConstraintType.IN);
for (ISpatialObject space : spaces) {
for (IGridGeometryProvider space : spaces) {
if (space instanceof GridCoverage) {
spaceRc.addToConstraintValueList(Integer
.toString(((GridCoverage) space).getId()));

View file

@ -28,10 +28,6 @@ import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeSet;
import com.raytheon.uf.common.inventory.data.AbstractRequestableData;
import com.raytheon.uf.common.inventory.exception.DataCubeException;
import com.raytheon.uf.common.inventory.TimeAndSpace;
import com.raytheon.uf.common.inventory.tree.AbstractRequestableNode;
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;
@ -39,8 +35,12 @@ import com.raytheon.uf.common.derivparam.inv.AvailabilityContainer;
import com.raytheon.uf.common.derivparam.library.DerivParamDesc;
import com.raytheon.uf.common.derivparam.library.DerivParamMethod;
import com.raytheon.uf.common.derivparam.tree.AbstractAliasLevelNode;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.common.inventory.TimeAndSpace;
import com.raytheon.uf.common.inventory.data.AbstractRequestableData;
import com.raytheon.uf.common.inventory.exception.DataCubeException;
import com.raytheon.uf.common.inventory.tree.AbstractRequestableNode;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.grid.data.ImportRequestableData;
@ -50,15 +50,17 @@ import com.raytheon.viz.grid.util.RadarAdapter;
/**
* This node handles all Alias derived parameters which includes Import in AWIPS
* I. Data requests and Time queries are simply forwarded to the source nodes.
* Returned records are wrapped in an ALiasRecord which can handle unit
* Returned records are wrapped in an AliasRecord which can handle unit
* conversion and model conversion if necessary.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 15, 2010 #3965 rjpeter Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jan 15, 2010 3965 rjpeter Initial creation
* Apr 11, 2014 2947 bsteffen Switch spatial matching to use
* IGridGeometryProvider
*
* </pre>
*
@ -113,7 +115,7 @@ public class ImportLevelNode extends AbstractAliasLevelNode {
}
}
Collection<GridCoverage> spaces = null;
ISpatialObject space = time.getSpace();
IGridGeometryProvider space = time.getSpace();
if (space.equals(TimeAndSpace.SPACE_AGNOSTIC)) {
try {
spaces = CoverageUtils.getInstance().getCoverages(

View file

@ -27,17 +27,17 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.inventory.data.AbstractRequestableData;
import com.raytheon.uf.common.inventory.exception.DataCubeException;
import com.raytheon.uf.common.inventory.TimeAndSpace;
import com.raytheon.uf.common.inventory.TimeAndSpaceMatcher;
import com.raytheon.uf.common.inventory.TimeAndSpaceMatcher.MatchResult;
import com.raytheon.uf.common.inventory.tree.AbstractRequestableNode;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.derivparam.inv.AvailabilityContainer;
import com.raytheon.uf.common.derivparam.library.DerivParamDesc;
import com.raytheon.uf.common.derivparam.library.DerivParamMethod;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.inventory.TimeAndSpace;
import com.raytheon.uf.common.inventory.TimeAndSpaceMatcher;
import com.raytheon.uf.common.inventory.TimeAndSpaceMatcher.MatchResult;
import com.raytheon.uf.common.inventory.data.AbstractRequestableData;
import com.raytheon.uf.common.inventory.exception.DataCubeException;
import com.raytheon.uf.common.inventory.tree.AbstractRequestableNode;
/**
*
@ -50,9 +50,11 @@ import com.raytheon.uf.common.geospatial.ISpatialObject;
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 29, 2010 bsteffen Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Jan 29, 2010 bsteffen Initial creation
* Apr 11, 2014 2947 bsteffen Switch spatial matching to use
* IGridGeometryProvider
*
* </pre>
*
@ -214,8 +216,8 @@ public class OrLevelNode extends AbstractDerivedDataNode {
Collection<MatchResult> matches = matcher.match(myAvailability,
nodeAvail).values();
for (MatchResult match : matches) {
ISpatialObject space1 = match.get1().getSpace();
ISpatialObject space2 = match.get2().getSpace();
IGridGeometryProvider space1 = match.get1().getSpace();
IGridGeometryProvider space2 = match.get2().getSpace();
// if the spaces are equal then remove the new time so it is not
// added. This will remove identical times and times that match
// ignoring range.

View file

@ -0,0 +1,59 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.inventory;
import org.geotools.coverage.grid.GridGeometry2D;
import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
/**
* Interace for {@link IGridGeometryProvider} that can compare itself to other
* IGridGeometryProviders and provide an intersecting IGridGeometryProvider.
* This method can be used by the {@link TimeAndSpaceMatcher} to match different
* spaces.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Apr 11, 2014 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public interface IGridGeometryProviderComparable extends IGridGeometryProvider {
/**
* Compare another IGridGeometryProvider to this one. If the two are
* compatible return a provider that will generate a {@link GridGeometry2D}
* representing the intersection. If the two are incompatible or
* nonintersecting null should be returned to indicate no space matching is
* possible.
*
* @param other
* @return
*/
public IGridGeometryProvider compare(IGridGeometryProvider other);
}

View file

@ -19,11 +19,10 @@
**/
package com.raytheon.uf.common.inventory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.geotools.coverage.grid.GridGeometry2D;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
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
@ -34,9 +33,10 @@ import com.vividsolutions.jts.geom.Geometry;
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 11, 2012 bsteffen Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Apr 11, 2012 bsteffen Initial creation
* Apr 11, 2014 2947 bsteffen Switch space to use IGridGeometryProvider
*
* </pre>
*
@ -73,40 +73,23 @@ public class TimeAndSpace {
* 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;
}
public static final IGridGeometryProvider SPACE_AGNOSTIC = new IGridGeometryProvider() {
@Override
public String toString() {
return "SPACE_AGNOSTIC";
}
@Override
public GridGeometry2D getGridGeometry() {
return null;
}
};
private final DataTime time;
private final ISpatialObject space;
private final IGridGeometryProvider space;
public TimeAndSpace() {
this(TIME_AGNOSTIC, SPACE_AGNOSTIC);
@ -117,11 +100,11 @@ public class TimeAndSpace {
}
public TimeAndSpace(ISpatialObject space) {
public TimeAndSpace(IGridGeometryProvider space) {
this(TIME_AGNOSTIC, space);
}
public TimeAndSpace(DataTime time, ISpatialObject space) {
public TimeAndSpace(DataTime time, IGridGeometryProvider space) {
this.time = time;
this.space = space;
}
@ -130,7 +113,7 @@ public class TimeAndSpace {
return time;
}
public ISpatialObject getSpace() {
public IGridGeometryProvider getSpace() {
return space;
}

View file

@ -25,7 +25,7 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.time.DataTime;
/**
@ -54,9 +54,11 @@ import com.raytheon.uf.common.time.DataTime;
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 8, 2012 bsteffen Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* May 08, 2012 bsteffen Initial creation
* Apr 11, 2014 2947 bsteffen Switch spatial matching to use
* IGridGeometryProvider
*
* </pre>
*
@ -112,9 +114,7 @@ public class TimeAndSpaceMatcher {
MatchResult res = createMatchResult(t1, t2);
if (res != null) {
MatchResult prev = result.get(res.getMerge());
if (prev == null
|| prev.getMatchValue().compareTo(
res.getMatchValue()) > 0) {
if (prev == null || prev.compareTo(res) > 0) {
result.put(res.getMerge(), res);
}
}
@ -133,55 +133,38 @@ public class TimeAndSpaceMatcher {
* @return
*/
private MatchResult createMatchResult(TimeAndSpace t1, TimeAndSpace t2) {
MatchType matchValue;
TimeMatchType timeMatchType;
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
/* Determine how well the times match */
if (t1.isTimeAgnostic()) {
// When one is agnostic it will match anything.
/* When one is agnostic it will match anything. */
time = t2.getTime();
matchValue = spaceAgn ? MatchType.AGNOSTIC_MATCH
: MatchType.SPACE_MATCH;
timeMatchType = TimeMatchType.AGNOSTIC;
} else if (t2.isTimeAgnostic()) {
// again one is agnostic
/* again one is agnostic */
time = t1.getTime();
matchValue = spaceAgn ? MatchType.AGNOSTIC_MATCH
: MatchType.SPACE_MATCH;
timeMatchType = TimeMatchType.AGNOSTIC;
} else if (t1.getTime().equals(t2.getTime())) {
// A perfect time match is always best.
/* A perfect time match is always best. */
time = t1.getTime();
matchValue = spaceAgn ? MatchType.TIME_MATCH : MatchType.BOTH_MATCH;
timeMatchType = TimeMatchType.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.
/*
* 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;
timeMatchType = TimeMatchType.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.
/*
* 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());
@ -189,12 +172,46 @@ public class TimeAndSpaceMatcher {
time = new DataTime(t2.getTime().getRefTime(), t2.getTime()
.getFcstTime());
}
matchValue = spaceAgn ? MatchType.TIME_VALID : MatchType.BOTH_VALID;
timeMatchType = TimeMatchType.VALID_TIME;
} else {
/* no time match, means no match at all. */
return null;
}
SpaceMatchType spaceMatchType = null;
IGridGeometryProvider space = null;
/* Determine how well the spaces match */
if (t1.isSpaceAgnostic()) {
/* When one is agnostic it will match anything. */
space = t2.getSpace();
spaceMatchType = SpaceMatchType.AGNOSTIC;
} else if (t2.isSpaceAgnostic()) {
/* again one is agnostic */
space = t1.getSpace();
spaceMatchType = SpaceMatchType.AGNOSTIC;
} else if (t1.getSpace().equals(t2.getSpace())) {
/* A perfect space match is always best. */
space = t1.getSpace();
spaceMatchType = SpaceMatchType.MATCH;
} else {
if(t1.getSpace() instanceof IGridGeometryProviderComparable){
space = ((IGridGeometryProviderComparable) t1.getSpace())
.compare(t2.getSpace());
}
if (space == null
&& (t2.getSpace() instanceof IGridGeometryProviderComparable)) {
space = ((IGridGeometryProviderComparable) t2.getSpace())
.compare(t1.getSpace());
}
if(space != null){
spaceMatchType = SpaceMatchType.COMPARABLE;
}else{
return null;
}
}
return new MatchResult(t1, t2, new TimeAndSpace(time, space),
matchValue);
timeMatchType, spaceMatchType);
}
/**
@ -215,34 +232,32 @@ public class TimeAndSpaceMatcher {
* @author bsteffen
* @version 1.0
*/
public static class MatchResult {
public static class MatchResult implements Comparable<MatchResult> {
/**
* The TimeAndSpace from the first collection that matches
*/
/** The TimeAndSpace from the first collection that matches */
private final TimeAndSpace t1;
/**
* The TimeAndSpace from the second collection that matches
*/
/** The TimeAndSpace from the second collection that matches */
private final TimeAndSpace t2;
/**
* The TimeAndSpace from the first collection that matches
*/
/** The TimeAndSpace from the first collection that matches */
private final TimeAndSpace merge;
/**
* How good of a match is this.
*/
private final MatchType matchValue;
/** How good of a time match is this. */
private final TimeMatchType timeMatchType;
public MatchResult(TimeAndSpace t1, TimeAndSpace t2,
TimeAndSpace merge, MatchType matchValue) {
/** How good of a space match is this. */
private final SpaceMatchType spaceMatchType;
private MatchResult(TimeAndSpace t1, TimeAndSpace t2,
TimeAndSpace merge, TimeMatchType timeMatchType,
SpaceMatchType spaceMatchType) {
super();
this.t1 = t1;
this.t2 = t2;
this.merge = merge;
this.matchValue = matchValue;
this.timeMatchType = timeMatchType;
this.spaceMatchType = spaceMatchType;
}
public TimeAndSpace get1() {
@ -257,59 +272,51 @@ public class TimeAndSpaceMatcher {
return merge;
}
public MatchType getMatchValue() {
return matchValue;
public TimeMatchType getTimeMatchType() {
return timeMatchType;
}
public SpaceMatchType getSpaceMatchType() {
return spaceMatchType;
}
@Override
public int compareTo(MatchResult o) {
int result = timeMatchType.compareTo(o.getTimeMatchType());
if (result == 0) {
result = spaceMatchType.compareTo(o.getSpaceMatchType());
}
return result;
}
}
/**
*
* 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 {
public static enum TimeMatchType {
/* Perfect match */
MATCH,
// Time and space match perfectly
BOTH_MATCH,
/* Reftime and forecast time match but ranges do not */
IGNORE_RANGE,
// Space matches perfectly but time only matches if you ignore range
BOTH_IGNORE_RANGE,
/* Only valid time matches, not ref/forectast time. */
VALID_TIME,
// Space matches perfectly but time only matches valid time
BOTH_VALID,
/* One is time or both are time agnostic so it matches everything. */
AGNOSTIC
}
// one is space agnostic and time matches
TIME_MATCH,
public static enum SpaceMatchType {
/* Perfect match */
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;
/*
* One or both implements IGridGeometryProviderComparable and found a
* suitable intersection
*/
COMPARABLE,
/* One is time or both are space agnostic so it matches everything. */
AGNOSTIC
}
/**

View file

@ -24,10 +24,10 @@ import java.util.List;
import javax.measure.unit.Unit;
import com.raytheon.uf.common.inventory.exception.DataCubeException;
import com.raytheon.uf.common.inventory.TimeAndSpace;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.IGridGeometryProvider;
import com.raytheon.uf.common.inventory.TimeAndSpace;
import com.raytheon.uf.common.inventory.exception.DataCubeException;
import com.raytheon.uf.common.time.DataTime;
/**
@ -40,9 +40,11 @@ import com.raytheon.uf.common.time.DataTime;
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 17, 2010 bsteffen Initial creation
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Mar 17, 2010 bsteffen Initial creation
* Apr 11, 2014 2947 bsteffen Switch spatial matching to use
* IGridGeometryProvider
*
* </pre>
*
@ -64,7 +66,7 @@ public abstract class AbstractRequestableData {
protected DataTime dataTime = TimeAndSpace.TIME_AGNOSTIC;
protected ISpatialObject space = TimeAndSpace.SPACE_AGNOSTIC;
protected IGridGeometryProvider space = TimeAndSpace.SPACE_AGNOSTIC;
public AbstractRequestableData() {
@ -162,11 +164,11 @@ public abstract class AbstractRequestableData {
this.level = level;
}
public ISpatialObject getSpace() {
public IGridGeometryProvider getSpace() {
return space;
}
public void setSpace(ISpatialObject space) {
public void setSpace(IGridGeometryProvider space) {
this.space = space;
}