tim@455: package de.intevation.gnv.math;
tim@455: 
sascha@779: import com.vividsolutions.jts.geom.Coordinate;
sascha@779: 
sascha@779: import de.intevation.gnv.geobackend.base.Result;
sascha@779: 
sascha@779: import de.intevation.gnv.geobackend.base.query.QueryExecutor;
sascha@779: import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory;
sascha@779: 
sascha@779: import de.intevation.gnv.geobackend.base.query.exception.QueryException;
sascha@779: 
sascha@779: import de.intevation.gnv.geobackend.sde.datasources.RasterObject;
sascha@779: 
sascha@779: import de.intevation.gnv.utils.WKTUtils;
sascha@779: 
sascha@779: import java.lang.ref.SoftReference;
sascha@779: 
tim@457: import java.util.ArrayList;
tim@455: import java.util.Collection;
tim@455: 
tim@455: import org.apache.log4j.Logger;
tim@455: 
tim@455: /**
sascha@805:  * This implementation uses the geo backend to query a depth via
sascha@805:  * a raster layer stored in the database.
sascha@805:  *
sascha@780:  * @author <a href="mailto:tim.englich@intevation.de">Tim Englich</a>
sascha@780:  * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a>
tim@455:  */
sascha@805: public class QueriedXYDepth
sascha@805: implements   XYDepth
sascha@805: {
tim@455:     private static Logger log = Logger.getLogger(QueriedXYDepth.class);
sascha@778: 
sascha@458:     private static final String queryID = "rasterQuery";
sascha@778: 
sascha@458:     private QueryExecutor queryExecutor;
sascha@778: 
sascha@458:     private ArrayList<SoftReference<RasterObject>> rasterData;
sascha@462: 
sascha@462:     private RasterObject last;
sascha@463: 
sascha@463:     private int interpolation;
sascha@778: 
sascha@805:     /**
sascha@805:      * Default construtor. Interpolation method is bilinear.
sascha@805:      */
tim@455:     public QueriedXYDepth() {
sascha@463:         this(RasterObject.BILINEAR);
sascha@463:     }
sascha@463: 
sascha@805:     /**
sascha@805:      * Constructor to create a QueriedXYDepth with a given interpolation
sascha@805:      * method.
sascha@805:      * @param interpolation The interpolation method.
sascha@805:      */
sascha@463:     public QueriedXYDepth(int interpolation) {
sascha@463:         this.interpolation = interpolation;
sascha@458:         rasterData    = new ArrayList<SoftReference<RasterObject>>();
sascha@458:         queryExecutor = QueryExecutorFactory.getInstance().getQueryExecutor();
tim@455:     }
tim@455: 
tim@455:     public double depth(Coordinate coordinate) {
tim@457:         double resultValue = Double.NaN;
sascha@778: 
sascha@458:         RasterObject ro = getRasterObject(coordinate);
sascha@778: 
sascha@458:         if (ro == null) {
tim@457:             try {
sascha@801:                 String[] filterValues =
sascha@801:                     new String[] { WKTUtils.toWKT(coordinate) };
sascha@801:                 Collection<Result> result = queryExecutor.executeQuery(
sascha@801:                     queryID, filterValues);
sascha@458:                 for (Result row: result) {
sascha@458:                     if ((ro = (RasterObject)row.getObject(0)) != null) {
sascha@801:                         rasterData.add(
sascha@801:                             new SoftReference<RasterObject>(last = ro));
sascha@458:                     }
sascha@458:                     break;
sascha@458:                 }
tim@457:             } catch (QueryException e) {
sascha@458:                 log.error(e, e);
tim@457:             }
tim@457:         }
sascha@458:         return ro != null
sascha@463:             ? ro.getValue(coordinate, interpolation)
sascha@778:             : Double.NaN;
tim@455:     }
sascha@778: 
sascha@463:     private RasterObject getRasterObject(Coordinate coordinate) {
sascha@462:         if (last != null && last.contains(coordinate)) {
sascha@462:             return last;
sascha@462:         }
sascha@458:         for (int i = rasterData.size()-1; i >= 0; --i) {
sascha@458:             SoftReference<RasterObject> ref = rasterData.get(i);
sascha@458:             RasterObject ro = ref.get();
sascha@462:             if (ro != null && ro.contains(coordinate)) {
sascha@462:                 return last = ro;
tim@457:             }
tim@457:         }
tim@457:         return null;
tim@457:     }
sascha@836: }