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 @ 8841

History | View | Annotate | Download (17.4 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.dispose.Disposable;
66
import org.gvsig.tools.dispose.DisposeUtils;
67
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
68
import org.gvsig.tools.exception.BaseException;
69
import org.gvsig.tools.locator.LocatorException;
70

    
71
/**
72
 * @author fdiaz
73
 *
74
 */
75
public class WMSRasterProvider extends AbstractRasterStoreProvider {
76

    
77
    private static final Logger logger = LoggerFactory.getLogger(WMSRasterProvider.class);
78

    
79
    public static String NAME = "WMS";
80
    public static String DESCRIPTION = "WMS Raster Provider";
81
    public static final String METADATA_DEFINITION_NAME = "WMS";
82

    
83
    public static final int DEFAULT_BUFFER_SIZE = 1024;
84
    public static final int MAX_ZOOM_LEVEL = 22;
85

    
86
    // WMS Parameters
87
    private WMSClient wmsClient;
88
    private WMSStatus wmsStatus;
89

    
90
    private Envelope envelope = null;
91

    
92
    private IProjection projection = null;
93

    
94
    private int calculatedMaxZoomLevel = MAX_ZOOM_LEVEL;
95

    
96
    private TileStruct tileStruct;
97

    
98
    protected WMSRasterProvider(DataStoreParameters params, DataStoreProviderServices storeServices) throws InitializeException {
99
        super(params, storeServices, FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME));
100
        initParams();
101
    }
102

    
103
    private void initParams() throws InitializeException {
104
        WMSRasterProviderParameters parameters = (WMSRasterProviderParameters) getParameters();
105

    
106
        URL service = parameters.getService();
107
        boolean override = (Boolean)(parameters.getDynValue(WMSRasterProviderParameters.WMS_OVERRIDE_CAPABILITIES_PARAMETER_NAME));
108

    
109
        try {
110
            wmsClient = new WMSClient(service.toString());
111
        } catch (IOException e) {
112
            throw new InitializeException("Can't create WMSClient with host '"+service+"'", e);
113
        }
114
        wmsStatus = new WMSStatus();
115

    
116
        // Setting the envelope for the layer
117
        wmsClient.getCapabilities(wmsStatus, override, null);
118

    
119
        @SuppressWarnings("unchecked")
120
        List<String> layerNames =
121
            (List<String>) parameters.getDynValue(WMSRasterProviderParameters.WMS_LAYERS_PARAMETER_NAME);
122
        for (Iterator<String> iterator = layerNames.iterator(); iterator.hasNext();) {
123
            String layerName = (String) iterator.next();
124
            wmsStatus.addLayerName(layerName);
125
        }
126

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

    
137
            IProjection reqProj = getProjection(); //CRSFactory.getCRS(p.getSRSCode());
138
            IProjection latLonProj = CRSFactory.getCRS(latLonID);
139
            if ((reqProj != null) && (latLonProj != null)) {
140
                ICoordTrans ct = latLonProj.getCT(reqProj);
141
                Rectangle2D reprojectedRect = ct.convert(extent);
142
                extent = reprojectedRect;
143
            }
144
        }
145

    
146
        if (extent != null) {
147
            try {
148
                this.envelope =
149
                    geomManager.createEnvelope(extent.getMinX(), extent.getMinY(), extent.getMaxX(), extent.getMaxY(),
150
                        SUBTYPES.GEOM2D);
151
            } catch (CreateEnvelopeException e) {
152
                throw new InitializeException("Can't create envenlope.", e);
153

    
154
            }
155
        }
156

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

    
174
    }
175

    
176
    protected static void registerMetadataDefinition() throws MetadataException {
177
        MetadataManager manager = MetadataLocator.getMetadataManager();
178
        if (manager.getDefinition(METADATA_DEFINITION_NAME) == null) {
179
            manager.addDefinition(METADATA_DEFINITION_NAME,
180
                WMSRasterProviderParameters.class.getResourceAsStream("WMSRasterMetadata.xml"),
181
                WMSRasterProviderParameters.class.getClassLoader());
182
        }
183
    }
184

    
185
    @Override
186
    public Buffer createBuffer(RasterQuery rasterQuery) throws BufferException {
187

    
188
        BufferManager bufferManager = BufferLocator.getBufferManager();
189
        int[] bandDataTypes;
190
        NoData[] bandNoData;
191
        //
192
        if (!rasterQuery.getBands().isEmpty()) {
193
            List<BandQuery> bands;
194
            bands = rasterQuery.getBands();
195
            bandDataTypes = new int[bands.size()];
196
            bandNoData = new NoData[bands.size()];
197

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

    
223
        double ratio = Math.abs(envelope.getLength(DIMENSIONS.X)/envelope.getLength(DIMENSIONS.Y));
224

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

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

    
257
        Buffer buffer = bufferManager.createRGBABuffer(img, projection, envelope);
258

    
259
        return buffer;
260
    }
261

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

    
285
    }
286

    
287
    @Override
288
    public int getBands() {
289
        return 4;
290
    }
291

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

    
308
    @Override
309
    public void open() throws OpenException {
310
        for(int i=0; i<getBands(); i++){
311
            this.getBandDescriptor(i).setDataType(DataTypes.BYTE);
312
        }
313
    }
314

    
315
    @Override
316
    public ResourceProvider getResource() {
317
        return null;
318
    }
319

    
320
    @Override
321
    public Object getSourceId() {
322
        return getParameters().getDynValue(WMSRasterProviderParameters.WMS_SERVICE_PARAMETER_NAME);
323
    }
324

    
325
    @Override
326
    public String getProviderName() {
327
        return NAME;
328
    }
329

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

    
344
    @Override
345
    public String getFullName() { // host:port - lista de capas
346

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

    
366
    @Override
367
    public Object getDynValue(String name) throws DynFieldNotFoundException {
368
        if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
369
            return this.getParameters().getDynValue(name);
370
        }
371
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
372
            return this.getEnvelope();
373
        }
374
        return super.getDynValue(name);
375
    }
376

    
377
    private Envelope getEnvelope() {
378
        return this.envelope;
379
    }
380

    
381
    private IProjection getProjection() {
382
        return (IProjection) this.getParameters().getDynValue(WMSRasterProviderParameters.WMS_CRS_PARAMETER_NAME);
383
    }
384

    
385
    @Override
386
    public TileStruct getTileStruct() {
387
        if (tileStruct == null) {
388
            tileStruct = new DefaultTileStruct();
389
            tileStruct.setColumnsPerTile(DEFAULT_BUFFER_SIZE);
390
            tileStruct.setRowsPerTile(DEFAULT_BUFFER_SIZE);
391

    
392
            try {
393
                Envelope envelope = getEnvelope();
394
                tileStruct.setEnvelope(envelope);
395

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

    
411
                tileStruct.setPixelSizePerZoomLevel(zoomLevels);
412
            } catch (LocatorException e) {
413
                logger.warn("Can't create world extent of GoogleMaps", e);
414
            }
415
        }
416
        return tileStruct;
417
    }
418

    
419
    @Override
420
    public Image getImageLegend() {
421
        Vector layerNames = wmsStatus.getLayerNames();
422
        if(layerNames.size()>1){
423
            return null;
424
        }
425

    
426
        File file;
427
        BufferedImage img=null;
428
        try {
429
            file = wmsClient.getLegendGraphic(wmsStatus, layerNames.get(0).toString(), null);
430
            img = ImageIO.read(file);
431
        } catch (WMSException | ServerErrorException | IOException e) {
432
            logger.warn("Can't read image legend of WMS Provider", e);
433
        }
434
        return img;
435
    }
436

    
437
    @Override
438
    public BufferDimensions getDimensions() throws InitializeException {
439
        if(this.dimensions==null){;
440
            Double pixelSize = getTileStruct().getPixelSizePerZoomLevel().get(calculatedMaxZoomLevel);
441
            Envelope envelope = getEnvelope();
442
            int rows = (int)Math.round(envelope.getLength(DIMENSIONS.Y)/pixelSize);
443
            int columns = (int)Math.round(envelope.getLength(DIMENSIONS.X)/pixelSize);
444
            this.dimensions = BufferLocator.getBufferManager().createBufferDimensions(rows, columns, envelope);
445
        }
446
        return this.dimensions;
447
    }
448

    
449
    @Override
450
    protected void doDispose() throws BaseException {
451
        super.doDispose();
452
        if(this.tileStruct!=null) {
453
            DisposeUtils.dispose((Disposable) this.tileStruct);
454
            this.tileStruct = null;
455
        }
456
    }
457

    
458
}