Statistics
| Revision:

gvsig-raster / org.gvsig.raster / branches / org.gvsig.raster.2.4 / org.gvsig.wms / org.gvsig.wms.provider / src / main / java / org / gvsig / wms / provider / WMSRasterProvider.java @ 8690

History | View | Annotate | Download (16.8 KB)

1
package org.gvsig.wms.provider;
2

    
3
import java.awt.Image;
4
import java.awt.geom.Rectangle2D;
5
import java.awt.image.BufferedImage;
6
import java.io.File;
7
import java.io.IOException;
8
import java.net.URL;
9
import java.util.HashMap;
10
import java.util.Iterator;
11
import java.util.List;
12
import java.util.Map;
13
import java.util.Vector;
14

    
15
import javax.imageio.ImageIO;
16

    
17
import org.cresques.cts.ICoordTrans;
18
import org.cresques.cts.IProjection;
19
import org.slf4j.Logger;
20
import org.slf4j.LoggerFactory;
21

    
22
import org.gvsig.compat.CompatLocator;
23
import org.gvsig.compat.net.Downloader;
24
import org.gvsig.fmap.crs.CRSFactory;
25
import org.gvsig.fmap.dal.DALLocator;
26
import org.gvsig.fmap.dal.DataManager;
27
import org.gvsig.fmap.dal.DataServerExplorer;
28
import org.gvsig.fmap.dal.DataServerExplorerParameters;
29
import org.gvsig.fmap.dal.DataStore;
30
import org.gvsig.fmap.dal.DataStoreParameters;
31
import org.gvsig.fmap.dal.FileHelper;
32
import org.gvsig.fmap.dal.exception.InitializeException;
33
import org.gvsig.fmap.dal.exception.OpenException;
34
import org.gvsig.fmap.dal.exception.ReadException;
35
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
36
import org.gvsig.fmap.dal.raster.api.BandQuery;
37
import org.gvsig.fmap.dal.raster.api.RasterQuery;
38
import org.gvsig.fmap.dal.raster.spi.AbstractRasterStoreProvider;
39
import org.gvsig.fmap.dal.raster.spi.BandDescriptorServices;
40
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
41
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
42
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
43
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
44
import org.gvsig.fmap.geom.GeometryLocator;
45
import org.gvsig.fmap.geom.GeometryManager;
46
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
47
import org.gvsig.fmap.geom.primitive.Envelope;
48
import org.gvsig.metadata.MetadataLocator;
49
import org.gvsig.metadata.MetadataManager;
50
import org.gvsig.metadata.exceptions.MetadataException;
51
import org.gvsig.raster.lib.buffer.api.Buffer;
52
import org.gvsig.raster.lib.buffer.api.BufferDimensions;
53
import org.gvsig.raster.lib.buffer.api.BufferLocator;
54
import org.gvsig.raster.lib.buffer.api.BufferManager;
55
import org.gvsig.raster.lib.buffer.api.NoData;
56
import org.gvsig.raster.lib.buffer.api.TileStruct;
57
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
58
import org.gvsig.raster.lib.buffer.spi.DefaultTileStruct;
59
import org.gvsig.remoteclient.exceptions.ServerErrorException;
60
import org.gvsig.remoteclient.exceptions.WMSException;
61
import org.gvsig.remoteclient.wms.WMSClient;
62
import org.gvsig.remoteclient.wms.WMSStatus;
63
import org.gvsig.remoteclient.wms.WMSStyle;
64
import org.gvsig.tools.dataTypes.DataTypes;
65
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
66
import org.gvsig.tools.locator.LocatorException;
67

    
68
/**
69
 * @author fdiaz
70
 *
71
 */
72
public class WMSRasterProvider extends AbstractRasterStoreProvider {
73

    
74
    private static final Logger logger = LoggerFactory.getLogger(WMSRasterProvider.class);
75

    
76
    public static String NAME = "WMS";
77
    public static String DESCRIPTION = "WMS Raster Provider";
78
    public static final String METADATA_DEFINITION_NAME = "WMS";
79

    
80
    public static final int DEFAULT_BUFFER_SIZE = 1024;
81
    public static final int MAX_ZOOM_LEVEL = 22;
82

    
83
    // WMS Parameters
84
    private WMSClient wmsClient;
85
    private WMSStatus wmsStatus;
86

    
87
    private Envelope envelope = null;
88

    
89
    private IProjection projection = null;
90

    
91
    private int calculatedMaxZoomLevel = MAX_ZOOM_LEVEL;
92

    
93
    protected WMSRasterProvider(DataStoreParameters params, DataStoreProviderServices storeServices) throws InitializeException {
94
        super(params, storeServices, FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME));
95
        initParams();
96
    }
97

    
98
    private void initParams() throws InitializeException {
99
        WMSRasterProviderParameters parameters = (WMSRasterProviderParameters) getParameters();
100

    
101
        URL service = parameters.getService();
102
        boolean override = (Boolean)(parameters.getDynValue(WMSRasterProviderParameters.WMS_OVERRIDE_CAPABILITIES_PARAMETER_NAME));
103

    
104
        try {
105
            wmsClient = new WMSClient(service.toString());
106
        } catch (IOException e) {
107
            throw new InitializeException("Can't create WMSClient with host '"+service+"'", e);
108
        }
109
        wmsStatus = new WMSStatus();
110

    
111
        // Setting the envelope for the layer
112
        wmsClient.getCapabilities(wmsStatus, override, null);
113

    
114
        @SuppressWarnings("unchecked")
115
        List<String> layerNames =
116
            (List<String>) parameters.getDynValue(WMSRasterProviderParameters.WMS_LAYERS_PARAMETER_NAME);
117
        for (Iterator<String> iterator = layerNames.iterator(); iterator.hasNext();) {
118
            String layerName = (String) iterator.next();
119
            wmsStatus.addLayerName(layerName);
120
        }
121

    
122
        String[] arrayLayerNames = layerNames.toArray(new String[layerNames.size()]);
123
        Rectangle2D extent = wmsClient.getLayersExtent(arrayLayerNames, getProjection().getAbrev());
124
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
125
        if (extent == null) {
126
            String latLonID = "EPSG:4326";
127
            extent = wmsClient.getLayersExtent(arrayLayerNames, latLonID);
128
            if (extent == null) {
129
                extent = wmsClient.getLayersExtent(arrayLayerNames, "CRS:84");
130
            }
131

    
132
            IProjection reqProj = getProjection(); //CRSFactory.getCRS(p.getSRSCode());
133
            IProjection latLonProj = CRSFactory.getCRS(latLonID);
134
            if ((reqProj != null) && (latLonProj != null)) {
135
                ICoordTrans ct = latLonProj.getCT(reqProj);
136
                Rectangle2D reprojectedRect = ct.convert(extent);
137
                extent = reprojectedRect;
138
            }
139
        }
140

    
141
        if (extent != null) {
142
            try {
143
                this.envelope =
144
                    geomManager.createEnvelope(extent.getMinX(), extent.getMinY(), extent.getMaxX(), extent.getMaxY(),
145
                        SUBTYPES.GEOM2D);
146
            } catch (CreateEnvelopeException e) {
147
                throw new InitializeException("Can't create envenlope.", e);
148

    
149
            }
150
        }
151

    
152
        @SuppressWarnings("unchecked")
153
        List<WMSStyle> wmsStyles =
154
            (List<WMSStyle>) parameters.getDynValue(WMSRasterProviderParameters.WMS_STYLES_PARAMETER_NAME);
155
        wmsStatus.setStyles(new Vector<WMSStyle>(wmsStyles));
156
        wmsStatus.setFormat((String) parameters.getDynValue(WMSRasterProviderParameters.WMS_FORMAT_PARAMETER_NAME));
157
        wmsStatus.setInfoFormat((String) parameters.getDynValue(WMSRasterProviderParameters.WMS_INFO_FORMAT_PARAMETER_NAME));
158
        Boolean xyAxisOrder = (Boolean) parameters.getDynValue(WMSRasterProviderParameters.WMS_XYAXISORDER_PARAMETER_NAME);
159
        if(xyAxisOrder!=null && xyAxisOrder.booleanValue()){
160
            wmsStatus.setXyAxisOrder(xyAxisOrder);
161
        }
162
        projection  = (IProjection) (parameters.getDynValue(WMSRasterProviderParameters.WMS_CRS_PARAMETER_NAME));
163
        wmsStatus.setSrs(projection.getAbrev());
164
        Boolean transparency = (Boolean) parameters.getDynValue(WMSRasterProviderParameters.WMS_TRANSPARENCY_PARAMETER_NAME);
165
        if(transparency!=null && transparency.booleanValue()){
166
            wmsStatus.setTransparency(transparency);
167
        }
168

    
169
    }
170

    
171
    protected static void registerMetadataDefinition() throws MetadataException {
172
        MetadataManager manager = MetadataLocator.getMetadataManager();
173
        if (manager.getDefinition(METADATA_DEFINITION_NAME) == null) {
174
            manager.addDefinition(METADATA_DEFINITION_NAME,
175
                WMSRasterProviderParameters.class.getResourceAsStream("WMSRasterMetadata.xml"),
176
                WMSRasterProviderParameters.class.getClassLoader());
177
        }
178
    }
179

    
180
    @Override
181
    public Buffer createBuffer(RasterQuery rasterQuery) throws BufferException {
182

    
183
        BufferManager bufferManager = BufferLocator.getBufferManager();
184
        int[] bandDataTypes;
185
        NoData[] bandNoData;
186
        //
187
        if (!rasterQuery.getBands().isEmpty()) {
188
            List<BandQuery> bands;
189
            bands = rasterQuery.getBands();
190
            bandDataTypes = new int[bands.size()];
191
            bandNoData = new NoData[bands.size()];
192

    
193
            for (BandQuery bandQuery : bands) {
194
                int band = bandQuery.getBand();
195
                bandDataTypes[band] = this.getBandDescriptor(band).getDataType();
196
                bandNoData[band] = null;
197
            }
198
        } else {
199
            int bands = getBands();
200
            bandDataTypes = new int[bands];
201
            bandNoData = new NoData[bands];
202
            for (int i = 0; i < bands; i++) {
203
                bandDataTypes[i] = this.getBandDescriptor(i).getDataType();
204
                bandNoData[i] = null;
205
            }
206
        }
207
        Envelope envelope = getEnvelope();
208
        if (rasterQuery.getClip() != null) {
209
            envelope = rasterQuery.getClip();
210
        }
211
        wmsStatus.setExtent(
212
            new Rectangle2D.Double(
213
                envelope.getMinimum(DIMENSIONS.X),
214
                envelope.getMinimum(DIMENSIONS.Y),
215
                envelope.getLength(DIMENSIONS.X),
216
                envelope.getLength(DIMENSIONS.Y)));
217

    
218
        double ratio = Math.abs(envelope.getLength(DIMENSIONS.X)/envelope.getLength(DIMENSIONS.Y));
219

    
220
        double pixelSize = rasterQuery.getPixelSize();
221
        int columns = WMSRasterProvider.DEFAULT_BUFFER_SIZE;
222
        int rows = WMSRasterProvider.DEFAULT_BUFFER_SIZE;
223
        if(pixelSize == 0){
224
            if(ratio >= 1){
225
                wmsStatus.setWidth(columns);
226
                rows = (int)Math.round(WMSRasterProvider.DEFAULT_BUFFER_SIZE/ratio);
227
                wmsStatus.setHeight((int)Math.round(WMSRasterProvider.DEFAULT_BUFFER_SIZE/ratio));
228
            } else {
229
                columns = (int)Math.round(WMSRasterProvider.DEFAULT_BUFFER_SIZE/ratio);
230
                wmsStatus.setWidth(columns);
231
                wmsStatus.setHeight(rows);
232
            }
233
        } else {
234
            columns = (int)Math.round(envelope.getLength(DIMENSIONS.X)/pixelSize);
235
            wmsStatus.setWidth(columns);
236
            rows = (int)Math.round(envelope.getLength(DIMENSIONS.Y)/pixelSize);
237
            wmsStatus.setHeight(rows);
238
        }
239

    
240
        URL url;
241
        Downloader downloader = CompatLocator.getDownloader();
242
        BufferedImage img;
243
        try {
244
            url = wmsClient.getGetMapURL(wmsStatus, null);
245
            logger.info("URL: "+url.toString());
246
            File file = downloader.downloadFile(url, "WMS_map", null);
247
            img = ImageIO.read(file);
248
        } catch (Exception e) {
249
            throw new BufferException(e);
250
        }
251

    
252
        Buffer buffer = bufferManager.createRGBABuffer(img, projection, envelope);
253

    
254
        return buffer;
255
    }
256

    
257
    @Override
258
    public BandDescriptorServices getBandDescriptor(int band) {
259
        BandDescriptorServices descriptor = super.getBandDescriptor(band);
260
      switch (band) {
261
      case 0:
262
          descriptor.setName("RED");
263
          descriptor.setDescription("RED");
264
          descriptor.setDataType(BufferManager.TYPE_BYTE);
265
      case 1:
266
          descriptor.setName("GREEN");
267
          descriptor.setDescription("GREEN");
268
          descriptor.setDataType(BufferManager.TYPE_BYTE);
269
      case 2:
270
          descriptor.setName("BLUE");
271
          descriptor.setDescription("BLUE");
272
          descriptor.setDataType(BufferManager.TYPE_BYTE);
273
      case 3:
274
          descriptor.setName("ALPHA");
275
          descriptor.setDescription("ALPHA");
276
          descriptor.setDataType(BufferManager.TYPE_BYTE);
277
      }
278
      return descriptor;
279

    
280
    }
281

    
282
    @Override
283
    public int getBands() {
284
        return 4;
285
    }
286

    
287
    @Override
288
    public DataServerExplorer getExplorer() throws ReadException, ValidateDataParametersException {
289
        DataManager manager = DALLocator.getDataManager();
290
        WMSRasterServerExplorerParameters params;
291
        try {
292
            params =
293
                (WMSRasterServerExplorerParameters) manager
294
                    .createServerExplorerParameters(WMSRasterServerExplorer.NAME);
295
            params.setService(((WMSRasterProviderParameters) getParameters()).getService());
296
//            params.setXYAxisOrder(((WMSRasterProviderParameters) getParameters()).getXYAxisOrder());
297
            return manager.openServerExplorer(WMSRasterServerExplorer.NAME, (DataServerExplorerParameters) params);
298
        } catch (Exception e) {
299
            throw new ReadException(this.getName(), e);
300
        }
301
    }
302

    
303
    @Override
304
    public void open() throws OpenException {
305
        for(int i=0; i<getBands(); i++){
306
            this.getBandDescriptor(i).setDataType(DataTypes.BYTE);
307
        }
308
    }
309

    
310
    @Override
311
    public ResourceProvider getResource() {
312
        return null;
313
    }
314

    
315
    @Override
316
    public Object getSourceId() {
317
        return getParameters().getDynValue(WMSRasterProviderParameters.WMS_SERVICE_PARAMETER_NAME);
318
    }
319

    
320
    @Override
321
    public String getProviderName() {
322
        return NAME;
323
    }
324

    
325
    @Override
326
    public String getName() { //lista de capas
327
        @SuppressWarnings("unchecked")
328
        List<String> layers = (List<String>) getParameters().getDynValue("layers");
329
        StringBuilder builder = new StringBuilder();
330
        for (int i = 0; i < layers.size(); i++) {
331
            if (i != 0) {
332
                builder.append(",");
333
            }
334
            builder.append(layers.get(i));
335
        }
336
        return builder.toString();
337
    }
338

    
339
    @Override
340
    public String getFullName() { // host:port - lista de capas
341

    
342
        StringBuilder builder = new StringBuilder();
343
        URL service = (URL)this.getParameters().getDynValue(WMSRasterProviderParameters.WMS_SERVICE_PARAMETER_NAME);
344
        builder.append(service.getHost());
345
        int port = service.getPort();
346
        if(port < 0){
347
            int defaultPort = service.getDefaultPort();
348
            if(defaultPort>=0){
349
                builder.append(":");
350
                builder.append(service.getDefaultPort());
351
            }
352
        } else {
353
            builder.append(":");
354
            builder.append(port);
355
        }
356
        builder.append(" - ");
357
        builder.append(getName());
358
        return builder.toString();
359
    }
360

    
361
    @Override
362
    public Object getDynValue(String name) throws DynFieldNotFoundException {
363
        if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
364
            return this.getParameters().getDynValue(name);
365
        }
366
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
367
            return this.getEnvelope();
368
        }
369
        return super.getDynValue(name);
370
    }
371

    
372
    private Envelope getEnvelope() {
373
        return this.envelope;
374
    }
375

    
376
    private IProjection getProjection() {
377
        return (IProjection) this.getParameters().getDynValue(WMSRasterProviderParameters.WMS_CRS_PARAMETER_NAME);
378
    }
379

    
380
    @Override
381
    public TileStruct getTileStruct() {
382
        TileStruct tileStruct = new DefaultTileStruct();
383
        tileStruct.setColumnsPerTile(DEFAULT_BUFFER_SIZE);
384
        tileStruct.setRowsPerTile(DEFAULT_BUFFER_SIZE);
385

    
386
        try {
387
            Envelope envelope = getEnvelope();
388
            tileStruct.setEnvelope(envelope);
389

    
390
            Map<Integer, Double> zoomLevels = new HashMap<Integer, Double>();
391
            double pixelSize;
392
            double length;
393
            if (envelope.getLength(DIMENSIONS.X) >= envelope.getLength(DIMENSIONS.Y)) {
394
                length = envelope.getLength(DIMENSIONS.X);
395
            } else {
396
                length = envelope.getLength(DIMENSIONS.Y);
397
            }
398
            pixelSize = length / DEFAULT_BUFFER_SIZE;
399
            for (int zoomLevel = 0; (zoomLevel <= MAX_ZOOM_LEVEL) && ((length/pixelSize)<Integer.MAX_VALUE); zoomLevel++) {
400
                zoomLevels.put(zoomLevel, pixelSize);
401
                pixelSize = pixelSize / 2;
402
                calculatedMaxZoomLevel = zoomLevel;
403
            }
404

    
405
            tileStruct.setPixelSizePerZoomLevel(zoomLevels);
406
        } catch (LocatorException e) {
407
            logger.warn("Can't create world extent of GoogleMaps", e);
408
        }
409
        return tileStruct;
410
    }
411

    
412
    @Override
413
    public Image getImageLegend() {
414
        Vector layerNames = wmsStatus.getLayerNames();
415
        if(layerNames.size()>1){
416
            return null;
417
        }
418

    
419
        File file;
420
        BufferedImage img=null;
421
        try {
422
            file = wmsClient.getLegendGraphic(wmsStatus, layerNames.get(0).toString(), null);
423
            img = ImageIO.read(file);
424
        } catch (WMSException | ServerErrorException | IOException e) {
425
            logger.warn("Can't read image legend of WMS Provider", e);
426
        }
427
        return img;
428
    }
429

    
430
    @Override
431
    public BufferDimensions getDimensions() throws InitializeException {
432
        if(this.dimensions==null){;
433
            Double pixelSize = getTileStruct().getPixelSizePerZoomLevel().get(calculatedMaxZoomLevel);
434
            Envelope envelope = getEnvelope();
435
            int rows = (int)Math.round(envelope.getLength(DIMENSIONS.Y)/pixelSize);
436
            int columns = (int)Math.round(envelope.getLength(DIMENSIONS.X)/pixelSize);
437
            this.dimensions = BufferLocator.getBufferManager().createBufferDimensions(rows, columns, envelope);
438
        }
439
        return this.dimensions;
440
    }
441

    
442
}