Statistics
| Revision:

gvsig-raster / org.gvsig.raster / branches / org.gvsig.raster.2.4 / org.gvsig.wmts / org.gvsig.wmts.provider / src / main / java / org / gvsig / wmts / provider / WMTSRasterProvider.java @ 8842

History | View | Annotate | Download (35.9 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2018 gvSIG Association
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.wmts.provider;
24

    
25
import java.awt.Image;
26
import java.awt.geom.Rectangle2D;
27
import java.awt.image.BufferedImage;
28
import java.io.File;
29
import java.io.IOException;
30
import java.net.URL;
31
import java.util.ArrayList;
32
import java.util.Collections;
33
import java.util.HashMap;
34
import java.util.Iterator;
35
import java.util.List;
36
import java.util.Map;
37
import java.util.Set;
38
import java.util.SortedSet;
39
import java.util.TreeSet;
40
import java.util.Map.Entry;
41

    
42
import javax.imageio.ImageIO;
43

    
44
import org.cresques.cts.ICoordTrans;
45
import org.cresques.cts.IProjection;
46
import org.slf4j.Logger;
47
import org.slf4j.LoggerFactory;
48

    
49
import org.gvsig.fmap.crs.CRSFactory;
50
import org.gvsig.fmap.dal.DALLocator;
51
import org.gvsig.fmap.dal.DataManager;
52
import org.gvsig.fmap.dal.DataServerExplorer;
53
import org.gvsig.fmap.dal.DataServerExplorerParameters;
54
import org.gvsig.fmap.dal.DataStore;
55
import org.gvsig.fmap.dal.DataStoreParameters;
56
import org.gvsig.fmap.dal.FileHelper;
57
import org.gvsig.fmap.dal.exception.DataException;
58
import org.gvsig.fmap.dal.exception.InitializeException;
59
import org.gvsig.fmap.dal.exception.OpenException;
60
import org.gvsig.fmap.dal.exception.ReadException;
61
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
62
import org.gvsig.fmap.dal.raster.api.BandQuery;
63
import org.gvsig.fmap.dal.raster.api.RasterQuery;
64
import org.gvsig.fmap.dal.raster.spi.AbstractRasterStoreProvider;
65
import org.gvsig.fmap.dal.raster.spi.BandDescriptorServices;
66
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
67
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
68
import org.gvsig.fmap.geom.Geometry;
69
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
70
import org.gvsig.fmap.geom.GeometryLocator;
71
import org.gvsig.fmap.geom.GeometryManager;
72
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
73
import org.gvsig.fmap.geom.primitive.Envelope;
74
import org.gvsig.metadata.MetadataLocator;
75
import org.gvsig.metadata.MetadataManager;
76
import org.gvsig.metadata.exceptions.MetadataException;
77
import org.gvsig.raster.lib.buffer.api.Buffer;
78
import org.gvsig.raster.lib.buffer.api.BufferDimensions;
79
import org.gvsig.raster.lib.buffer.api.BufferLocator;
80
import org.gvsig.raster.lib.buffer.api.BufferManager;
81
import org.gvsig.raster.lib.buffer.api.NoData;
82
import org.gvsig.raster.lib.buffer.api.PageManager;
83
import org.gvsig.raster.lib.buffer.api.TileStruct;
84
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
85
import org.gvsig.raster.lib.buffer.spi.DefaultTileStruct;
86
import org.gvsig.raster.wmts.ogc.WMTSClient;
87
import org.gvsig.raster.wmts.ogc.WMTSOGCLocator;
88
import org.gvsig.raster.wmts.ogc.WMTSStatus;
89
import org.gvsig.raster.wmts.ogc.exception.WMTSException;
90
import org.gvsig.raster.wmts.ogc.struct.WMTSLayer;
91
import org.gvsig.raster.wmts.ogc.struct.WMTSStyle;
92
import org.gvsig.raster.wmts.ogc.struct.WMTSTileMatrix;
93
import org.gvsig.raster.wmts.ogc.struct.WMTSTileMatrixSet;
94
import org.gvsig.tools.dataTypes.DataTypes;
95
import org.gvsig.tools.dispose.Disposable;
96
import org.gvsig.tools.dispose.DisposeUtils;
97
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
98
import org.gvsig.tools.exception.BaseException;
99
import org.gvsig.tools.locator.LocatorException;
100

    
101
/**
102
 * @author fdiaz
103
 *
104
 */
105
public class WMTSRasterProvider extends AbstractRasterStoreProvider {
106

    
107
    private static final Logger logger = LoggerFactory.getLogger(WMTSRasterProvider.class);
108

    
109
    public static String NAME = "WMTS";
110
    public static String DESCRIPTION = "WMTS Raster Provider";
111
    public static final String METADATA_DEFINITION_NAME = "WMTS";
112

    
113
    public static final int DEFAULT_BUFFER_SIZE = 256;
114
    public static final int DEFAULT_MAX_ZOOM_LEVEL = 22;
115

    
116
    // WMTS Parameters
117
    private WMTSClient wmtsClient;
118
    private WMTSStatus wmtsStatus;
119
    private String layerName;
120

    
121
    private Envelope envelope = null;
122

    
123
    private IProjection projection = null;
124

    
125
    private WMTSImage image;
126
    private TileStruct tileStruct = null;
127
    private Map<Integer,List<PageManager>> pageManagersPerZoomLevel = null;
128
    private Map<Integer, WMTSTileMatrix> tileMatrixPerZoomLevel = null;
129
    private int columnsPerTile;
130
    private int rowsPerTile;
131

    
132
    private int maxZoomLevel;
133

    
134
    protected WMTSRasterProvider(DataStoreParameters params, DataStoreProviderServices storeServices) throws InitializeException {
135
        super(params, storeServices, FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME));
136
        initParams();
137
    }
138

    
139
    private void initParams() throws InitializeException {
140
        WMTSRasterProviderParameters parameters = (WMTSRasterProviderParameters) getParameters();
141
        pageManagersPerZoomLevel = new HashMap<Integer, List<PageManager>>();
142

    
143
        envelope = getEnvelope();
144
        maxZoomLevel = DEFAULT_MAX_ZOOM_LEVEL;
145

    
146
    }
147

    
148
    protected WMTSStatus getWMTSStatus() throws InitializeException {
149
        if( this.wmtsStatus == null ){
150
            wmtsStatus = getWMTSClient().createStatus();
151

    
152
            WMTSLayer wmtsLayer = getWMTSClient().getLayer(getLayerName());
153
            wmtsStatus.setLayer(wmtsLayer.getIdentifier());
154

    
155
            wmtsStatus.setStyle((String)getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_STYLE_PARAMETER_NAME));
156
            wmtsStatus.setFormat((String) getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_FORMAT_PARAMETER_NAME));
157
            wmtsStatus.setInfoFormat((String) getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_INFO_FORMAT_PARAMETER_NAME));
158
            wmtsStatus.setSrs(getProjection().getAbrev());
159

    
160
            wmtsStatus.setTileMatrixSet(getTileMatrixSet().getIdentifier());
161

    
162

    
163
        }
164
        // TODO Auto-generated method stub
165
        return this.wmtsStatus;
166
    }
167

    
168
    private String getLayerName() {
169
        if( this.layerName == null){
170
            this.layerName = (String) getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_LAYER_PARAMETER_NAME);
171
        }
172
        return this.layerName;
173
    }
174

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

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

    
187
        try {
188
            BufferManager bufferManager = BufferLocator.getBufferManager();
189
            int[] bandDataTypes;
190
            List<PageManager> pageManagers = new ArrayList<PageManager>();
191
            NoData[] bandNoData;
192
            Envelope envelope = getTileStruct().getEnvelope();
193
            double pixelSize = rasterQuery.getPixelSize();
194
            int zoomLevel;
195
            if (pixelSize == 0) {
196
                zoomLevel = 0;
197
            } else {
198
                zoomLevel = getZoomLvlForPixelSize(pixelSize);
199
            }
200

    
201
                if (!rasterQuery.getBands().isEmpty()) {
202
                    List<BandQuery> bands;
203
                    bands = rasterQuery.getBands();
204
                    bandDataTypes = new int[bands.size()];
205
                    bandNoData = new NoData[bands.size()];
206

    
207
                    for (BandQuery bandQuery : bands) {
208
                        int band = bandQuery.getBand();
209
                        bandDataTypes[band] = this.getBandDescriptor(band).getDataType();
210
                        bandNoData[band] = this.getNoData(rasterQuery, band);
211
                        try {
212
                            pageManagers.add(getPageManagersInZoom(zoomLevel).get(band));
213
                        } catch (ValidateDataParametersException | CreateEnvelopeException | DataException
214
                            | CloneNotSupportedException e) {
215
                            // TODO Auto-generated catch block
216
                            throw new BufferException(e);
217
                        }
218
                    }
219
                } else {
220
                    int bands = getBands();
221
                    bandDataTypes = new int[bands];
222
                    bandNoData = new NoData[bands];
223
                    for (int i = 0; i < bands; i++) {
224
                        bandDataTypes[i] = this.getBandDescriptor(i).getDataType();
225
                        bandNoData[i] = this.getNoData(rasterQuery, i);
226
                        try {
227
                            pageManagers.add(getPageManagersInZoom(zoomLevel).get(i));
228
                        } catch (ValidateDataParametersException | CreateEnvelopeException | DataException
229
                            | CloneNotSupportedException e) {
230
                            throw new BufferException(e);
231
                        }
232
                    }
233
                }
234

    
235
            Buffer buffer =
236
                bufferManager.createBuffer(getRows(zoomLevel), getColumns(zoomLevel), bandDataTypes, bandNoData,
237
                    projection, envelope, pageManagers);
238

    
239
            if(rasterQuery.getClip()!=null){
240
                Buffer completeBuffer = buffer;
241
                envelope  = rasterQuery.getClip();
242
                buffer = completeBuffer.clip(envelope);
243
                DisposeUtils.dispose(completeBuffer);
244
            }
245

    
246
            return buffer;
247
        } catch (Exception e) {
248
            throw new BufferException(e);
249
        }
250

    
251
    }
252

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

    
276
    }
277

    
278

    
279
    @Override
280
    public int getBands() {
281
        return 4;
282
    }
283

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

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

    
307
    @Override
308
    public ResourceProvider getResource() {
309
        return null;
310
    }
311

    
312
    @Override
313
    public Object getSourceId() {
314
        return getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_SERVICE_PARAMETER_NAME);
315
    }
316

    
317
    @Override
318
    public String getProviderName() {
319
        return NAME;
320
    }
321

    
322
    @Override
323
    public String getName() { //lista de capas
324
        @SuppressWarnings("unchecked")
325
        String layerName = (String) getParameters().getDynValue("layer");
326
        return layerName;
327
    }
328

    
329
    @Override
330
    public String getFullName() { // host:port - lista de capas
331

    
332
        StringBuilder builder = new StringBuilder();
333
        URL service = (URL)this.getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_SERVICE_PARAMETER_NAME);
334
        builder.append(service.getHost());
335
        int port = service.getPort();
336
        if(port < 0){
337
            int defaultPort = service.getDefaultPort();
338
            if(defaultPort>=0){
339
                builder.append(":");
340
                builder.append(service.getDefaultPort());
341
            }
342
        } else {
343
            builder.append(":");
344
            builder.append(port);
345
        }
346
        builder.append(" - ");
347
        builder.append(getName());
348
        return builder.toString();
349
    }
350

    
351
    @Override
352
    public Object getDynValue(String name) throws DynFieldNotFoundException {
353
        if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
354
            return this.getParameters().getDynValue(name);
355
        }
356
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
357
            try {
358
                return this.getEnvelope();
359
            } catch (InitializeException e) {
360
                throw new DynFieldNotFoundException(name, this.getClass().getName());
361
            }
362
        }
363
        return super.getDynValue(name);
364
    }
365

    
366
    private Envelope getEnvelope() throws InitializeException {
367
        if(this.envelope == null){
368
            GeometryManager geomManager = GeometryLocator.getGeometryManager();
369
            try {
370
                WMTSLayer wmtsLayer = getWMTSClient().getLayer(getLayerName());
371
                Rectangle2D rectangle2d = wmtsLayer.getWGS84BBox().toRectangle2D();
372
                Envelope envelopeWGS84 = geomManager.createEnvelope(rectangle2d.getMinX(), rectangle2d.getMinY(), rectangle2d.getMaxX(), rectangle2d.getMaxY(), Geometry.SUBTYPES.GEOM2D);
373
                ICoordTrans ct = CRSFactory.getCRS("EPSG:4326").getCT(getProjection());
374
                this.envelope = envelopeWGS84.convert(ct);
375
            } catch (CreateEnvelopeException e) {
376
                throw new InitializeException("Can't create envelope.", e);
377
            }
378
        }
379
        return this.envelope;
380
    }
381

    
382
    @Override
383
    public TileStruct getTileStruct() {
384
        if (tileStruct == null) {
385
            /*
386
            StringBuilder builder = new StringBuilder();
387
            builder.append("\n");
388
            builder.append("****************** LAYER ************************");
389
            builder.append("\n");
390
            builder.append("projection = ");
391
            builder.append(projection.getAbrev());
392
            builder.append("\n");
393
            WMTSLayer layer = wmtsClient.getLayer(wmtsStatus.getLayer());
394
            String layerAbstract = layer.getAbstract();
395
            builder.append("layerAbstract = ");
396
            builder.append(layerAbstract);
397
            builder.append("\n");
398
            String layerIdentifier = layer.getIdentifier();
399
            builder.append("layerIdentifier = ");
400
            builder.append(layerIdentifier);
401
            builder.append("\n");
402
            String layerTitle = layer.getTitle();
403
            builder.append("layerTitle = ");
404
            builder.append(layerTitle);
405
            builder.append("\n");
406
            WMTSBoundingBox layerBbox = layer.getBBox();
407
            builder.append("layerBbox = ");
408
            if (layerBbox != null) {
409
                builder.append(layerBbox.getLowerCorner()[0]);
410
                builder.append(", ");
411
                builder.append(layerBbox.getLowerCorner()[1]);
412
                builder.append(" - ");
413
                builder.append(layerBbox.getUpperCorner()[0]);
414
                builder.append(", ");
415
                builder.append(layerBbox.getUpperCorner()[1]);
416
            } else {
417
                builder.append("null");
418
            }
419
            builder.append("\n");
420

421
            WMTSBoundingBox layerWGS84BBox = layer.getWGS84BBox();
422
            builder.append("layerWGS84BBox = ");
423
            if (layerWGS84BBox != null) {
424
                builder.append(layerWGS84BBox.getLowerCorner()[0]);
425
                builder.append(", ");
426
                builder.append(layerWGS84BBox.getLowerCorner()[1]);
427
                builder.append(" - ");
428
                builder.append(layerWGS84BBox.getUpperCorner()[0]);
429
                builder.append(", ");
430
                builder.append(layerWGS84BBox.getUpperCorner()[1]);
431
            } else {
432
                builder.append("null");
433
            }
434
            builder.append("\n");
435
            Rectangle2D layerWGS84BBoxProjected = layer.getWGS84BBoxTransformed(projection.getAbrev());
436
            builder.append("layerWGS84BBoxProjected = ");
437
            if (layerWGS84BBoxProjected != null) {
438
                builder.append(layerWGS84BBoxProjected.getMinX());
439
                builder.append(", ");
440
                builder.append(layerWGS84BBoxProjected.getMinY());
441
                builder.append(" - ");
442
                builder.append(layerWGS84BBoxProjected.getMaxX());
443
                builder.append(", ");
444
                builder.append(layerWGS84BBoxProjected.getMaxY());
445
            } else {
446
                builder.append("null");
447
            }
448
            builder.append("\n");
449

450
            List<WMTSTileMatrixSet> matrixSetsList = wmtsClient.getTileMatrixSet();
451
            builder.append("\n");
452
            builder.append("############ TILE MATRIX SET ITERATOR ###########");
453
            builder.append("\n");
454
            for (Iterator iterator = matrixSetsList.iterator(); iterator.hasNext();) {
455
                builder.append("================ MATRIX SET =====================");
456
                builder.append("\n");
457
                WMTSTileMatrixSet wmtsTileMatrixSet = (WMTSTileMatrixSet) iterator.next();
458
                String identifier = wmtsTileMatrixSet.getIdentifier();
459
                builder.append("wmtsTileMatrixSet.getIdentifier() = ");
460
                builder.append(identifier);
461
                builder.append("\n");
462
                int layerInitialLevel = layer.getInitialLevel(identifier);
463
                builder.append("*** layerInitialLevel = ");
464
                builder.append(layerInitialLevel);
465
                builder.append("\n");
466
                String wellKnownScaleSet = wmtsTileMatrixSet.getWellKnownScaleSet();
467
                builder.append("wmtsTileMatrixSet.getWellKnownScaleSet() = ");
468
                builder.append(wellKnownScaleSet);
469
                builder.append("\n");
470
                WMTSBoundingBox bounding = wmtsTileMatrixSet.getBoundingBox();
471
                builder.append("wmtsTileMatrixSet.getBoundingBox() = ");
472
                builder.append(bounding.getLowerCorner()[0]);
473
                builder.append(", ");
474
                builder.append(bounding.getLowerCorner()[1]);
475
                builder.append(" - ");
476
                builder.append(bounding.getUpperCorner()[0]);
477
                builder.append(", ");
478
                builder.append(bounding.getUpperCorner()[1]);
479
                builder.append("\n");
480
                String supportedCRS = wmtsTileMatrixSet.getSupportedCRS();
481
                builder.append("wmtsTileMatrixSet.getSupportedCRS() = ");
482
                builder.append(supportedCRS);
483
                builder.append("\n");
484
                List<WMTSTileMatrix> tileMatrix = wmtsTileMatrixSet.getTileMatrix();
485
                builder.append("???????????????? TILE MATRIX ????????????????????");
486
                builder.append("\n");
487
                for (Iterator iterator2 = tileMatrix.iterator(); iterator2.hasNext();) {
488
                    WMTSTileMatrix wmtsTileMatrix = (WMTSTileMatrix) iterator2.next();
489
                    String ident = wmtsTileMatrix.getIdentifier(); // 0 ?tal vez el zoom level?  parece que s?
490
                    builder.append("ident = ");
491
                    builder.append(ident);
492
                    builder.append("\n");
493
                    Rectangle2D bboxTileMatrixSet = wmtsTileMatrix.getBBoxTileMatrixSet(); // null
494
                    builder.append("bboxTileMatrixSet = ");
495
                    if (bboxTileMatrixSet != null) {
496
                        builder.append(bboxTileMatrixSet.getMinX());
497
                        builder.append(", ");
498
                        builder.append(bboxTileMatrixSet.getMinY());
499
                        builder.append(" - ");
500
                        builder.append(bboxTileMatrixSet.getMaxX());
501
                        builder.append(", ");
502
                        builder.append(bboxTileMatrixSet.getMaxY());
503
                    } else {
504
                        builder.append("null");
505
                    }
506
                    builder.append("\n");
507
                    double heightWCTile = wmtsTileMatrix.getHeightWCTile(false);
508
                    builder.append("heightWCTile = ");
509
                    builder.append(heightWCTile);
510
                    builder.append("\n");
511
                    double widthWCTile = wmtsTileMatrix.getWidthWCTile(false);
512
                    builder.append("widthWCTile = ");
513
                    builder.append(widthWCTile);
514
                    builder.append("\n");
515
                    double heightWCProjected = wmtsTileMatrix.getHeightWCTile(true);
516
                    builder.append("heightWCTileProjected [CHUNGO] = ");
517
                    builder.append(heightWCProjected);
518
                    builder.append("\n");
519
                    double widthWCProjected = wmtsTileMatrix.getWidthWCTile(true);
520
                    builder.append("widthWCTileProjected  [CHUNGO] = ");
521
                    builder.append(widthWCProjected);
522
                    builder.append("\n");
523
                    long matrixHeight = wmtsTileMatrix.getMatrixHeight();
524
                    builder.append("matrixHeight = ");
525
                    builder.append(matrixHeight);
526
                    builder.append("\n");
527
                    long matrixWidth = wmtsTileMatrix.getMatrixWidth();
528
                    builder.append("matrixWidth = ");
529
                    builder.append(matrixWidth);
530
                    builder.append("\n");
531
                    double scaleDenominator = wmtsTileMatrix.getScaleDenominator(); // 2.79541132014358E8
532
                                                                                    // puede ser el pixelSize
533
                    builder.append("scaleDenominator = ");
534
                    builder.append(scaleDenominator);
535
                    builder.append("\n");
536
                    int tileHeight = wmtsTileMatrix.getTileHeight(); // ??? rows in tile
537
                    builder.append("tileHeight = ");
538
                    builder.append(tileHeight);
539
                    builder.append("\n");
540
                    int tileWidth = wmtsTileMatrix.getTileWidth(); // ??? columns in tile
541
                    builder.append("tileWidth = ");
542
                    builder.append(tileWidth);
543
                    builder.append("\n");
544
                    double[] topLeftCorner = wmtsTileMatrix.getTopLeftCorner();
545
                    builder.append("topLeftCorner = ");
546
                    builder.append(topLeftCorner[0]);
547
                    builder.append(", ");
548
                    builder.append(topLeftCorner[1]);
549
                    builder.append("\n");
550

551
                    builder.append("-------------------------------------------------");
552
                    builder.append("\n");
553

554
                }
555
                builder.append("=================================================");
556
                builder.append("\n");
557
            }
558
            builder.append("#################################################");
559
            builder.append("\n");
560

561
            logger.info(builder.toString());
562
            */
563

    
564
            autoOpen();
565
            try {
566
                this.tileStruct = new DefaultTileStruct();
567
                this.columnsPerTile = DEFAULT_BUFFER_SIZE;
568
                this.rowsPerTile = DEFAULT_BUFFER_SIZE;
569
                this.tileStruct.setEnvelope(getEnvelope());
570
                tileMatrixPerZoomLevel = new HashMap<Integer, WMTSTileMatrix>();
571

    
572
                WMTSTileMatrixSet matrixSet = getTileMatrixSet();
573

    
574
                HashMap<Integer, Integer> tileWidthsCounter = new HashMap<Integer, Integer>();
575
                HashMap<Integer, Integer> tileHeightsCounter = new HashMap<Integer, Integer>();
576
                Map<Integer, Double> zoomLevels = new HashMap<Integer, Double>();
577
                int zoomLevel = 0;
578
                if(matrixSet!=null){
579
                    List<WMTSTileMatrix> tileMatrixList = matrixSet.getTileMatrix();
580
                    for (Iterator iterator = tileMatrixList.iterator(); iterator.hasNext();) {
581
                        WMTSTileMatrix wmtsTileMatrix = (WMTSTileMatrix) iterator.next();
582
                        long levelColumns = wmtsTileMatrix.getMatrixWidth()*wmtsTileMatrix.getTileWidth();
583

    
584
                        double levelWidth = wmtsTileMatrix.getMatrixWidth()*wmtsTileMatrix.getWidthWCTile(getProjection().isProjected());
585
                        double pixelSize = levelWidth/levelColumns;
586
                        zoomLevels.put(zoomLevel, pixelSize);
587
                        tileMatrixPerZoomLevel.put(zoomLevel, wmtsTileMatrix);
588
                        // Aprovechamos el bucle para contar los distintos
589
                        // valores que el servidor tiene para el tama?o de los
590
                        // tiles en cada nivel de zoom
591
                        int tileWidth = wmtsTileMatrix.getTileWidth();
592
                        if(!tileWidthsCounter.containsKey(tileWidth)){
593
                            tileWidthsCounter.put(tileWidth, 1);
594
                        } else {
595
                            tileWidthsCounter.put(tileWidth, tileWidthsCounter.get(tileWidth)+1);
596
                        }
597
                        int tileHeight = wmtsTileMatrix.getTileHeight();
598
                        if(!tileHeightsCounter.containsKey(tileHeight)){
599
                            tileHeightsCounter.put(tileHeight, 1);
600
                        } else {
601
                            tileHeightsCounter.put(tileHeight, tileHeightsCounter.get(tileHeight)+1);
602
                        }
603
                        maxZoomLevel = zoomLevel;
604
                        zoomLevel++;
605
                    }
606
                }
607
                //seleccionamos los m?s usados
608
                Integer aux = tileWidthsCounter.get(columnsPerTile);
609
                if(aux==null){
610
                    aux = 0;
611
                }
612
                Iterator<Entry<Integer, Integer>> it = tileWidthsCounter.entrySet().iterator();
613
                while (it.hasNext()) {
614
                    Entry<Integer, Integer> entry = it.next();
615
                    if(entry.getValue()>=aux){
616
                        aux = entry.getValue();
617
                        columnsPerTile = entry.getKey();
618
                    }
619
                }
620
                aux = tileHeightsCounter.get(rowsPerTile);
621
                if(aux==null){
622
                    aux = 0;
623
                }
624
                Iterator<Entry<Integer, Integer>> it2 = tileWidthsCounter.entrySet().iterator();
625
                while (it2.hasNext()) {
626
                    Entry<Integer, Integer> entry = it2.next();
627
                    if(entry.getValue()>=aux){
628
                        aux = entry.getValue();
629
                        rowsPerTile = entry.getKey();
630
                    }
631
                }
632

    
633
                //y los asignamos
634
                this.tileStruct.setColumnsPerTile(columnsPerTile);
635
                this.tileStruct.setRowsPerTile(rowsPerTile);
636

    
637
                //
638
                this.tileStruct.setPixelSizePerZoomLevel(zoomLevels);
639
            } catch (LocatorException | InitializeException e) {
640
                logger.warn("Can't create world extent of GoogleMaps", e);
641
            }
642
        }
643
        return this.tileStruct;
644
    }
645

    
646
    /**
647
     * @return
648
     * @throws InitializeException
649
     */
650
    private WMTSTileMatrixSet getTileMatrixSet() throws InitializeException {
651
        WMTSTileMatrixSet matrixSet = null;
652
        List<WMTSTileMatrixSet> matrixSets = wmtsClient.getTileMatrixSet();
653
        for (Iterator<WMTSTileMatrixSet> iterator = matrixSets.iterator(); iterator.hasNext();) {
654
            WMTSTileMatrixSet wmtsTileMatrixSet = (WMTSTileMatrixSet) iterator.next();
655
            String supportedCrs = wmtsTileMatrixSet.getSupportedCRS();
656
            IProjection supportedProjection = null;
657
            try {
658
                supportedProjection = CRSFactory.getCRS(supportedCrs);
659
                if(supportedProjection==null){
660
                    continue;
661
                }
662

    
663
            } catch (Exception e) {
664
                continue;
665
            }
666
            if ( supportedProjection.equals(getProjection()) ){
667
                matrixSet = wmtsTileMatrixSet;
668
                break;
669
            }
670
        }
671
        return matrixSet;
672
    }
673

    
674
    private List<PageManager> getPageManagersInZoom(int zoomLevel) throws ValidateDataParametersException, CreateEnvelopeException, BufferException, DataException, CloneNotSupportedException {
675
        List<PageManager> pageManagersInZoom = this.pageManagersPerZoomLevel.get(zoomLevel);
676
        if (pageManagersInZoom == null) {
677
            pageManagersInZoom = new ArrayList<PageManager>();
678
            for (int i = 0; i < getBands(); i++) {
679
                //FIXME el getTileStruct no sirve para este bandTileManager
680
                pageManagersInZoom.add(new WMTSBandTileManager(getTileStruct(), this.getWMTSImage(), zoomLevel, i));
681
            }
682
            this.pageManagersPerZoomLevel.put(zoomLevel, pageManagersInZoom);
683
        }
684
        return pageManagersInZoom;
685
    }
686

    
687
    /**
688
     * @param zoomLevel
689
     * @return rows per zoom level
690
     */
691
    public int getRows(int zoomLevel) {
692
        return (int) (Math.round(getTileStruct().getEnvelope().getLength(DIMENSIONS.Y) / this.getTileStruct().getPixelSizePerZoomLevel().get(zoomLevel)));
693
    }
694

    
695
    /**
696
     * @param zoomLevel
697
     * @return columns per zoom level
698
     */
699
    public int getColumns(int zoomLevel) {
700
        return (int) (Math.round(getTileStruct().getEnvelope().getLength(DIMENSIONS.X) / this.getTileStruct().getPixelSizePerZoomLevel().get(zoomLevel)));
701
    }
702

    
703
    /**
704
     * @param pixelSize
705
     * @return The appropriate zoom level for the pizelSize
706
     */
707
    private int getZoomLvlForPixelSize(double pixelSize) {
708
        //FIXME: Elegir el c?digo id?neo
709
        // Este trozo de c?digo selecciona un zoom superior con lo que,
710
        // al hacer la interpolaci?n se generar?n p?xeles m?s gordos
711
        int zoom = 0;
712
        Map<Integer, Double> pixelSizePerZoomLevel = tileStruct.getPixelSizePerZoomLevel();
713

    
714
        SortedSet<Integer> keySet = new TreeSet<>(Collections.reverseOrder());
715
        keySet.addAll(pixelSizePerZoomLevel.keySet());
716
        Iterator<Integer> iterator = keySet.iterator();
717
        while(iterator.hasNext()){
718
            zoom = iterator.next();
719
            double levelPixelSize = pixelSizePerZoomLevel.get(zoom);
720
            if (pixelSize <= levelPixelSize) {
721
                return zoom;
722
            }
723
        }
724

    
725
        return zoom;
726

    
727
        // Este trozo de c?digo selecciona un zoom inferior con lo que,
728
        // al hacer la interpolaci?n se perder?n p?xeles
729
        // repercutiendo en la legibilidad de las leyendas
730
        /*
731
        int zoom = 0;
732
        Map<Integer, Double> pixelSizePerZoomLevel = getTileStruct().getPixelSizePerZoomLevel();
733
        for (int i : pixelSizePerZoomLevel.keySet()) {
734
            zoom = i;
735
            double levelPixelSize = pixelSizePerZoomLevel.get(zoom);
736
            if (pixelSize >= levelPixelSize) {
737
                return zoom;
738
            }
739
        }
740
        return zoom;
741
        */
742
    }
743

    
744
    private WMTSImage getWMTSImage() {
745
        if(this.image == null){
746
            this.image = new WMTSImage(getTileStruct(), this.tileMatrixPerZoomLevel, this);
747
        }
748
        return this.image;
749
    }
750

    
751
    protected IProjection getProjection(){
752
        if(this.projection==null){
753
            projection  = (IProjection) (getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_CRS_PARAMETER_NAME));
754
        }
755
        return this.projection;
756
    }
757

    
758
    protected WMTSClient getWMTSClient() throws InitializeException {
759
        if (wmtsClient == null) {
760
            WMTSRasterProviderParameters parameters = (WMTSRasterProviderParameters) getParameters();
761
            URL service = parameters.getService();
762
            try {
763
                wmtsClient = WMTSOGCLocator.getManager().createWMTSClient(service.toString());
764
                Boolean forceChangeAxisOrder = (Boolean) getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_FORCECHANGEAXISORDER_PARAMETER_NAME);
765
                if(forceChangeAxisOrder!=null){
766
                    wmtsClient.setForceChangeAxisOrder(forceChangeAxisOrder.booleanValue());
767
                } else {
768
                    wmtsClient.setForceChangeAxisOrder(false);
769
                }
770
                wmtsClient.connect(true, null);
771
            } catch (IOException e) {
772
                throw new InitializeException("Can't create WMTSClient with from service '" + service.toString() + "'",
773
                    e);
774
            }
775
        }
776
        return wmtsClient;
777
    }
778

    
779
    protected int getRowsPerTile() {
780
        return this.rowsPerTile;
781
    };
782

    
783
    protected int getColumnsPerTile() {
784
        return this.columnsPerTile;
785
    };
786

    
787
    @Override
788
    public Image getImageLegend() {
789
        File file;
790
        BufferedImage img = null;
791
        try {
792
        WMTSLayer wmtsLayer = getWMTSClient().getLayer(getLayerName());
793
        WMTSStyle wmtsStyle = null;
794
        List<WMTSStyle> wmtsStyles = wmtsLayer.getStyle();
795
        for (Iterator<WMTSStyle> iterator = wmtsStyles.iterator(); iterator.hasNext();) {
796
            wmtsStyle = (WMTSStyle) iterator.next();
797
            if (wmtsStyle.getIdentifier().equalsIgnoreCase(wmtsStatus.getStyle())) {
798
                break;
799
            }
800
            wmtsStyle = null;
801
        }
802

    
803
            file = getWMTSClient().getLegendGraphic(wmtsLayer, wmtsStyle, null);
804
            img = ImageIO.read(file);
805
        } catch (InitializeException | WMTSException | IOException e) {
806
            logger.warn("Can't read image legend of WMTS Provider", e);
807
        }
808
        return img;
809
    }
810

    
811
    @Override
812
    public BufferDimensions getDimensions() throws InitializeException {
813
        if(this.dimensions==null){;
814
            Double pixelSize = getTileStruct().getPixelSizePerZoomLevel().get(getMaxZoomLevel());
815
            Envelope envelope = this.getEnvelope();
816
            int rows = (int)Math.round(envelope.getLength(DIMENSIONS.Y)/pixelSize);
817
            int columns = (int)Math.round(envelope.getLength(DIMENSIONS.X)/pixelSize);
818
            this.dimensions = BufferLocator.getBufferManager().createBufferDimensions(rows, columns, envelope);
819
        }
820
        return this.dimensions;
821
    }
822

    
823
    /**
824
     * @return the maxZoomLevel
825
     */
826
    public int getMaxZoomLevel() {
827
        return maxZoomLevel;
828
    }
829

    
830
    @Override
831
    protected void doDispose() throws BaseException {
832
        super.doDispose();
833
        DisposeUtils.dispose((Disposable) this.tileStruct);
834
        tileStruct = null;
835
        DisposeUtils.dispose(this.image);
836
        this.image = null;
837

    
838
        Set<Entry<Integer, List<PageManager>>> entries = this.pageManagersPerZoomLevel.entrySet();
839
        for (Iterator<Entry<Integer, List<PageManager>>> iterator = entries.iterator(); iterator.hasNext();) {
840
            Entry<Integer, List<PageManager>> entry = (Entry<Integer, List<PageManager>>) iterator.next();
841
            List<PageManager> pageManagers = entry.getValue();
842
            for (Iterator iterator2 = pageManagers.iterator(); iterator2.hasNext();) {
843
                PageManager pageManager = (PageManager) iterator2.next();
844
                DisposeUtils.dispose(pageManager);
845
                iterator2.remove();
846
            }
847
            iterator.remove();
848
        }
849
        pageManagersPerZoomLevel = null;
850

    
851

    
852
    }
853

    
854
}