/* * Copyright (c) 1998 - 2010. University Corporation for Atmospheric Research/Unidata * Portions of this software were developed by the Unidata Program at the * University Corporation for Atmospheric Research. * * Access and use of this software shall impose the following obligations * and understandings on the user. The user is granted the right, without * any fee or cost, to use, copy, modify, alter, enhance and distribute * this software, and any derivative works thereof, and its supporting * documentation for any purpose whatsoever, provided that this entire * notice appears in all copies of the software, derivative works and * supporting documentation. Further, UCAR requests that the user credit * UCAR/Unidata in any publications that result from the use of this * software or in any product that includes this software. The names UCAR * and/or Unidata, however, may not be used in any advertising or publicity * to endorse or promote any products or commercial entity unless specific * written permission is obtained from UCAR/Unidata. The user also * understands that UCAR/Unidata is not obligated to provide the user with * any support, consulting, training or assistance of any kind with regard * to the use, operation and performance of this software nor to provide * the user with any updates, revisions, new versions or "bug fixes." * * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package thredds.server.wms; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.joda.time.Chronology; import org.joda.time.DateTime; import thredds.server.wms.config.LayerSettings; import thredds.server.wms.config.WmsDetailedConfig; import ucar.nc2.Attribute; import ucar.nc2.dt.GridDatatype; import uk.ac.rdg.resc.edal.cdm.CdmUtils; import uk.ac.rdg.resc.edal.cdm.DataReadingStrategy; import uk.ac.rdg.resc.edal.cdm.PixelMap; import uk.ac.rdg.resc.edal.coverage.CoverageMetadata; import uk.ac.rdg.resc.edal.coverage.domain.Domain; import uk.ac.rdg.resc.edal.coverage.domain.impl.HorizontalDomain; import uk.ac.rdg.resc.edal.coverage.grid.HorizontalGrid; import uk.ac.rdg.resc.edal.geometry.HorizontalPosition; import uk.ac.rdg.resc.edal.util.Range; import uk.ac.rdg.resc.ncwms.exceptions.InvalidDimensionValueException; import uk.ac.rdg.resc.ncwms.graphics.ColorPalette; import uk.ac.rdg.resc.ncwms.wms.AbstractScalarLayer; /** * Wraps a GridDatatype as a ScalarLayer object * * @author Jon * @todo Implement more efficient getTimeseries() */ class ThreddsScalarLayer extends AbstractScalarLayer implements ThreddsLayer { //private static Logger log = LoggerFactory.getLogger(ThreddsScalarLayer.class); private GridDatatype grid; private ThreddsDataset dataset; private List<DateTime> times; private DataReadingStrategy dataReadingStrategy; // Will be set in ThreddsWmsController.ThreddsLayerFactory private LayerSettings layerSettings; public ThreddsScalarLayer(CoverageMetadata cm) { super(cm); } public List<List<Float>> readVerticalSection(DateTime dt, List<Double> list, Domain<HorizontalPosition> domain) throws InvalidDimensionValueException, IOException { int tIndex = this.findAndCheckTimeIndex(dt); // Defend against null values List<Integer> zIndices; if (list == null) { zIndices = Arrays.asList(-1); } else { zIndices = new ArrayList<>(list.size()); for (Double el : list) { zIndices.add(this.findAndCheckElevationIndex(el)); } } HorizontalGrid hg = CdmUtils.createHorizontalGrid(grid.getCoordinateSystem()); PixelMap pixelMap = new PixelMap(hg, domain); return CdmUtils.readVerticalSection(null, grid, tIndex, zIndices, pixelMap, dataReadingStrategy, (int) domain.size()); } /** * Static factory method. Builds a new ThreddsScalarLayer and set several properties */ public static ThreddsScalarLayer getNewLayer(CoverageMetadata cm, GridDatatype gdt, DataReadingStrategy drStrategy, ThreddsDataset ds, WmsDetailedConfig wmsConfig) { ThreddsScalarLayer tsl = new ThreddsScalarLayer(cm); tsl.setGridDatatype(gdt); tsl.setTimeValues(cm.getTimeValues()); tsl.setDataReadingStrategy(drStrategy); tsl.setDataset(ds); tsl.setLayerSettings(wmsConfig.getSettings(tsl)); return tsl; } @Override public String getName() { return this.getId(); } @Override public ThreddsDataset getDataset() { return this.dataset; } public void setDataset(ThreddsDataset dataset) { this.dataset = dataset; } public void setGridDatatype(GridDatatype grid) { this.grid = grid; } @Override public Chronology getChronology() { if (this.times == null || this.times.isEmpty()) return null; return this.times.get(0).getChronology(); } @Override public List<DateTime> getTimeValues() { return this.times; } public void setTimeValues(List<DateTime> timeValues) { this.times = timeValues; } public void setDataReadingStrategy(DataReadingStrategy dataReadingStrategy) { this.dataReadingStrategy = dataReadingStrategy; } @Override public Float readSinglePoint(DateTime time, double elevation, HorizontalPosition xy) throws InvalidDimensionValueException, IOException { //Domain singlePoint = (Domain<HorizontalPosition>)xy; Domain<HorizontalPosition> singlePoint = new HorizontalDomain(xy); return this.readHorizontalPoints(time, elevation, singlePoint).get(0); } @Override public List<Float> readHorizontalPoints(DateTime time, double elevation, Domain<HorizontalPosition> points) throws InvalidDimensionValueException, IOException { int tIndex = this.findAndCheckTimeIndex(time); int zIndex = this.findAndCheckElevationIndex(elevation); HorizontalGrid hg = CdmUtils.createHorizontalGrid(grid.getCoordinateSystem()); PixelMap pixelMap = new PixelMap(hg, points); List<Float> horizontalPoints; try { horizontalPoints = CdmUtils.readHorizontalPoints(null, grid, tIndex, zIndex, pixelMap, this.dataReadingStrategy, (int) points.size()); } catch (Exception e) { //Catching and wrapping any exception reading data into a new IOException throw new IOException(e); } return horizontalPoints; } @Override public List<Float> readTimeseries(List<DateTime> times, double elevation, HorizontalPosition xy) throws InvalidDimensionValueException, IOException { HorizontalGrid horizGrid = CdmUtils.createHorizontalGrid(grid.getCoordinateSystem()); List<Integer> tIndices = new ArrayList<Integer>(times.size()); for (DateTime time : times) tIndices.add(this.findAndCheckTimeIndex(time)); int zIndex = this.findAndCheckElevationIndex(elevation); return CdmUtils.readTimeseries(null, grid, horizGrid, tIndices, zIndex, xy); } public String getStandardName() { if (this.grid == null) return null; Attribute stdNameAtt = this.grid.findAttributeIgnoreCase("standard_name"); if (stdNameAtt == null || stdNameAtt.getStringValue().trim().equals("")) { return null; } return stdNameAtt.getStringValue(); } public void setLayerSettings(LayerSettings layerSettings) { this.layerSettings = layerSettings; } /// The properties below are taken from the LayerSettings @Override public boolean isQueryable() { return this.layerSettings.isAllowFeatureInfo(); } //@Override public boolean isIntervalTime() { return this.layerSettings.isIntervalTime(); } @Override public Range<Float> getApproxValueRange() { return this.layerSettings.getDefaultColorScaleRange(); } @Override public boolean isLogScaling() { return this.layerSettings.isLogScaling(); } @Override public ColorPalette getDefaultColorPalette() { return ColorPalette.get(this.layerSettings.getDefaultPaletteName()); } @Override public int getDefaultNumColorBands() { return this.layerSettings.getDefaultNumColorBands(); } }