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

History | View | Annotate | Download (35.8 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.SortedSet;
38
import java.util.TreeSet;
39
import java.util.Map.Entry;
40

    
41
import javax.imageio.ImageIO;
42

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

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

    
98
/**
99
 * @author fdiaz
100
 *
101
 */
102
public class WMTSRasterProvider extends AbstractRasterStoreProvider {
103

    
104
    private static final Logger logger = LoggerFactory.getLogger(WMTSRasterProvider.class);
105

    
106
    public static String NAME = "WMTS";
107
    public static String DESCRIPTION = "WMTS Raster Provider";
108
    public static final String METADATA_DEFINITION_NAME = "WMTS";
109

    
110
    public static final int DEFAULT_BUFFER_SIZE = 256;
111
    public static final int DEFAULT_MAX_ZOOM_LEVEL = 22;
112

    
113
    // WMTS Parameters
114
    private WMTSClient wmtsClient;
115
    private WMTSStatus wmtsStatus;
116
    private String layerName;
117

    
118
    private Envelope envelope = null;
119

    
120
    private IProjection projection = null;
121

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

    
129
    private int maxZoomLevel;
130

    
131
    protected WMTSRasterProvider(DataStoreParameters params, DataStoreProviderServices storeServices) throws InitializeException {
132
        super(params, storeServices, FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME));
133
        initParams();
134
    }
135

    
136
    private void initParams() throws InitializeException {
137
        WMTSRasterProviderParameters parameters = (WMTSRasterProviderParameters) getParameters();
138
        pageManagersPerZoomLevel = new HashMap<Integer, List<PageManager>>();
139
//        this.projection = getProjection();
140
//        wmtsClient = getWMTSClient();
141
//        wmtsStatus = getWMTSStatus();
142
        envelope = getEnvelope();
143
        maxZoomLevel = DEFAULT_MAX_ZOOM_LEVEL;
144

    
145
        //PRUEBA
146
//        tileStruct = getTileStruct();
147

    
148
    }
149

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

    
154
            WMTSLayer wmtsLayer = getWMTSClient().getLayer(getLayerName());
155
            wmtsStatus.setLayer(wmtsLayer.getIdentifier());
156

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

    
162
            wmtsStatus.setTileMatrixSet(getTileMatrixSet().getIdentifier());
163

    
164

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

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

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

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

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

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

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

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

    
241
            if(rasterQuery.getClip()!=null){
242
                Buffer completeBuffer = buffer;
243
                envelope  = rasterQuery.getClip();
244
                buffer = bufferManager.createClippedBuffer(completeBuffer, envelope);
245
                DisposeUtils.dispose(completeBuffer);
246
            }
247

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

    
253
    }
254

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

    
278
    }
279

    
280

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

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

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

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

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

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

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

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

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

    
360
    @Override
361
    public Object getDynValue(String name) throws DynFieldNotFoundException {
362
        if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
363
            return this.getParameters().getDynValue(name);
364
        }
365
        if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
366
            try {
367
                return this.getEnvelope();
368
            } catch (InitializeException e) {
369
                throw new DynFieldNotFoundException(name, this.getClass().getName());
370
            }
371
        }
372
        return super.getDynValue(name);
373
    }
374

    
375
    private Envelope getEnvelope() throws InitializeException {
376
        if(this.envelope == null){
377
            GeometryManager geomManager = GeometryLocator.getGeometryManager();
378
            try {
379
                WMTSLayer wmtsLayer = getWMTSClient().getLayer(getLayerName());
380
                Rectangle2D rectangle2d = wmtsLayer.getWGS84BBox().toRectangle2D();
381
                Envelope envelopeWGS84 = geomManager.createEnvelope(rectangle2d.getMinX(), rectangle2d.getMinY(), rectangle2d.getMaxX(), rectangle2d.getMaxY(), Geometry.SUBTYPES.GEOM2D);
382
                ICoordTrans ct = CRSFactory.getCRS("EPSG:4326").getCT(getProjection());
383
                this.envelope = envelopeWGS84.convert(ct);
384
//                Rectangle2D extent = wmtsLayer.getWGS84BBoxTransformed(getProjection().getAbrev());
385
//
386
//                this.envelope =
387
//                    geomManager.createEnvelope(extent.getMinX(), extent.getMinY(), extent.getMaxX(), extent.getMaxY(),
388
//                        SUBTYPES.GEOM2D);
389
            } catch (CreateEnvelopeException e) {
390
                throw new InitializeException("Can't create envelope.", e);
391
            }
392
        }
393
        return this.envelope;
394
    }
395

    
396
    @Override
397
    public TileStruct getTileStruct() {
398
        if (tileStruct == null) {
399
            /*
400
            StringBuilder builder = new StringBuilder();
401
            builder.append("\n");
402
            builder.append("****************** LAYER ************************");
403
            builder.append("\n");
404
            builder.append("projection = ");
405
            builder.append(projection.getAbrev());
406
            builder.append("\n");
407
            WMTSLayer layer = wmtsClient.getLayer(wmtsStatus.getLayer());
408
            String layerAbstract = layer.getAbstract();
409
            builder.append("layerAbstract = ");
410
            builder.append(layerAbstract);
411
            builder.append("\n");
412
            String layerIdentifier = layer.getIdentifier();
413
            builder.append("layerIdentifier = ");
414
            builder.append(layerIdentifier);
415
            builder.append("\n");
416
            String layerTitle = layer.getTitle();
417
            builder.append("layerTitle = ");
418
            builder.append(layerTitle);
419
            builder.append("\n");
420
            WMTSBoundingBox layerBbox = layer.getBBox();
421
            builder.append("layerBbox = ");
422
            if (layerBbox != null) {
423
                builder.append(layerBbox.getLowerCorner()[0]);
424
                builder.append(", ");
425
                builder.append(layerBbox.getLowerCorner()[1]);
426
                builder.append(" - ");
427
                builder.append(layerBbox.getUpperCorner()[0]);
428
                builder.append(", ");
429
                builder.append(layerBbox.getUpperCorner()[1]);
430
            } else {
431
                builder.append("null");
432
            }
433
            builder.append("\n");
434

435
            WMTSBoundingBox layerWGS84BBox = layer.getWGS84BBox();
436
            builder.append("layerWGS84BBox = ");
437
            if (layerWGS84BBox != null) {
438
                builder.append(layerWGS84BBox.getLowerCorner()[0]);
439
                builder.append(", ");
440
                builder.append(layerWGS84BBox.getLowerCorner()[1]);
441
                builder.append(" - ");
442
                builder.append(layerWGS84BBox.getUpperCorner()[0]);
443
                builder.append(", ");
444
                builder.append(layerWGS84BBox.getUpperCorner()[1]);
445
            } else {
446
                builder.append("null");
447
            }
448
            builder.append("\n");
449
            Rectangle2D layerWGS84BBoxProjected = layer.getWGS84BBoxTransformed(projection.getAbrev());
450
            builder.append("layerWGS84BBoxProjected = ");
451
            if (layerWGS84BBoxProjected != null) {
452
                builder.append(layerWGS84BBoxProjected.getMinX());
453
                builder.append(", ");
454
                builder.append(layerWGS84BBoxProjected.getMinY());
455
                builder.append(" - ");
456
                builder.append(layerWGS84BBoxProjected.getMaxX());
457
                builder.append(", ");
458
                builder.append(layerWGS84BBoxProjected.getMaxY());
459
            } else {
460
                builder.append("null");
461
            }
462
            builder.append("\n");
463

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

565
                    builder.append("-------------------------------------------------");
566
                    builder.append("\n");
567

568
                }
569
                builder.append("=================================================");
570
                builder.append("\n");
571
            }
572
            builder.append("#################################################");
573
            builder.append("\n");
574

575
            logger.info(builder.toString());
576
            */
577

    
578
            autoOpen();
579
            try {
580
                this.tileStruct = new DefaultTileStruct();
581
                this.columnsPerTile = DEFAULT_BUFFER_SIZE;
582
                this.rowsPerTile = DEFAULT_BUFFER_SIZE;
583
                this.tileStruct.setEnvelope(getEnvelope());
584
                tileMatrixPerZoomLevel = new HashMap<Integer, WMTSTileMatrix>();
585

    
586
                WMTSTileMatrixSet matrixSet = getTileMatrixSet();
587

    
588
                HashMap<Integer, Integer> tileWidthsCounter = new HashMap<Integer, Integer>();
589
                HashMap<Integer, Integer> tileHeightsCounter = new HashMap<Integer, Integer>();
590
                Map<Integer, Double> zoomLevels = new HashMap<Integer, Double>();
591
                int zoomLevel = 0;
592
                if(matrixSet!=null){
593
                    List<WMTSTileMatrix> tileMatrixList = matrixSet.getTileMatrix();
594
                    for (Iterator iterator = tileMatrixList.iterator(); iterator.hasNext();) {
595
                        WMTSTileMatrix wmtsTileMatrix = (WMTSTileMatrix) iterator.next();
596
                        long levelColumns = wmtsTileMatrix.getMatrixWidth()*wmtsTileMatrix.getTileWidth();
597

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

    
647
                //y los asignamos
648
                this.tileStruct.setColumnsPerTile(columnsPerTile);
649
                this.tileStruct.setRowsPerTile(rowsPerTile);
650

    
651
                //
652
                this.tileStruct.setPixelSizePerZoomLevel(zoomLevels);
653
            } catch (LocatorException | InitializeException e) {
654
                logger.warn("Can't create world extent of GoogleMaps", e);
655
            }
656
        }
657
        return this.tileStruct;
658
    }
659

    
660
    /**
661
     * @return
662
     * @throws InitializeException
663
     */
664
    private WMTSTileMatrixSet getTileMatrixSet() throws InitializeException {
665
        WMTSTileMatrixSet matrixSet = null;
666
        List<WMTSTileMatrixSet> matrixSets = wmtsClient.getTileMatrixSet();
667
        for (Iterator<WMTSTileMatrixSet> iterator = matrixSets.iterator(); iterator.hasNext();) {
668
            WMTSTileMatrixSet wmtsTileMatrixSet = (WMTSTileMatrixSet) iterator.next();
669
            String supportedCrs = wmtsTileMatrixSet.getSupportedCRS();
670
            IProjection supportedProjection = null;
671
            try {
672
                supportedProjection = CRSFactory.getCRS(supportedCrs);
673
                if(supportedProjection==null){
674
                    continue;
675
                }
676

    
677
            } catch (Exception e) {
678
                continue;
679
            }
680
            if ( supportedProjection.equals(getProjection()) ){
681
                matrixSet = wmtsTileMatrixSet;
682
                break;
683
            }
684
        }
685
        return matrixSet;
686
    }
687

    
688
    private List<PageManager> getPageManagersInZoom(int zoomLevel) throws ValidateDataParametersException, CreateEnvelopeException, BufferException, DataException, CloneNotSupportedException {
689
        List<PageManager> pageManagersInZoom = this.pageManagersPerZoomLevel.get(zoomLevel);
690
        if (pageManagersInZoom == null) {
691
            pageManagersInZoom = new ArrayList<PageManager>();
692
            for (int i = 0; i < getBands(); i++) {
693
                //FIXME el getTileStruct no sirve para este bandTileManager
694
                pageManagersInZoom.add(new WMTSBandTileManager(getTileStruct(), this.getWMTSImage(), zoomLevel, i, this));
695
            }
696
            this.pageManagersPerZoomLevel.put(zoomLevel, pageManagersInZoom);
697
        }
698
        return pageManagersInZoom;
699
    }
700

    
701
    /**
702
     * @param zoomLevel
703
     * @return rows per zoom level
704
     */
705
    public int getRows(int zoomLevel) {
706
        return (int) (Math.round(getTileStruct().getEnvelope().getLength(DIMENSIONS.Y) / this.getTileStruct().getPixelSizePerZoomLevel().get(zoomLevel)));
707
    }
708

    
709
    /**
710
     * @param zoomLevel
711
     * @return columns per zoom level
712
     */
713
    public int getColumns(int zoomLevel) {
714
        return (int) (Math.round(getTileStruct().getEnvelope().getLength(DIMENSIONS.X) / this.getTileStruct().getPixelSizePerZoomLevel().get(zoomLevel)));
715
    }
716

    
717
    /**
718
     * @param pixelSize
719
     * @return The appropriate zoom level for the pizelSize
720
     */
721
    private int getZoomLvlForPixelSize(double pixelSize) {
722
        //FIXME: Elegir el c?digo id?neo
723
        // Este trozo de c?digo selecciona un zoom superior con lo que,
724
        // al hacer la interpolaci?n se generar?n p?xeles m?s gordos
725
        int zoom = 0;
726
        Map<Integer, Double> pixelSizePerZoomLevel = tileStruct.getPixelSizePerZoomLevel();
727

    
728
        SortedSet<Integer> keySet = new TreeSet<>(Collections.reverseOrder());
729
        keySet.addAll(pixelSizePerZoomLevel.keySet());
730
        Iterator<Integer> iterator = keySet.iterator();
731
        while(iterator.hasNext()){
732
            zoom = iterator.next();
733
            double levelPixelSize = pixelSizePerZoomLevel.get(zoom);
734
            if (pixelSize <= levelPixelSize) {
735
                return zoom;
736
            }
737
        }
738

    
739
        return zoom;
740

    
741
        // Este trozo de c?digo selecciona un zoom inferior con lo que,
742
        // al hacer la interpolaci?n se perder?n p?xeles
743
        // repercutiendo en la legibilidad de las leyendas
744
        /*
745
        int zoom = 0;
746
        Map<Integer, Double> pixelSizePerZoomLevel = getTileStruct().getPixelSizePerZoomLevel();
747
        for (int i : pixelSizePerZoomLevel.keySet()) {
748
            zoom = i;
749
            double levelPixelSize = pixelSizePerZoomLevel.get(zoom);
750
            if (pixelSize >= levelPixelSize) {
751
                return zoom;
752
            }
753
        }
754
        return zoom;
755
        */
756
    }
757

    
758
    private WMTSImage getWMTSImage() {
759
        if(this.image == null){
760
            this.image = new WMTSImage(getTileStruct(), this.tileMatrixPerZoomLevel, this);
761
        }
762
        return this.image;
763
    }
764

    
765
    protected IProjection getProjection(){
766
        if(this.projection==null){
767
            projection  = (IProjection) (getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_CRS_PARAMETER_NAME));
768
        }
769
        return this.projection;
770
    }
771

    
772
    protected WMTSClient getWMTSClient() throws InitializeException {
773
        if (wmtsClient == null) {
774
            WMTSRasterProviderParameters parameters = (WMTSRasterProviderParameters) getParameters();
775
            URL service = parameters.getService();
776
            try {
777
                wmtsClient = WMTSOGCLocator.getManager().createWMTSClient(service.toString());
778
                Boolean forceChangeAxisOrder = (Boolean) getParameters().getDynValue(WMTSRasterProviderParameters.WMTS_FORCECHANGEAXISORDER_PARAMETER_NAME);
779
                if(forceChangeAxisOrder!=null){
780
                    wmtsClient.setForceChangeAxisOrder(forceChangeAxisOrder.booleanValue());
781
                } else {
782
                    wmtsClient.setForceChangeAxisOrder(false);
783
                }
784
                wmtsClient.connect(true, null);
785
            } catch (IOException e) {
786
                throw new InitializeException("Can't create WMTSClient with from service '" + service.toString() + "'",
787
                    e);
788
            }
789
        }
790
        return wmtsClient;
791
    }
792

    
793
    protected int getRowsPerTile() {
794
        return this.rowsPerTile;
795
    };
796

    
797
    protected int getColumnsPerTile() {
798
        return this.columnsPerTile;
799
    };
800

    
801
    @Override
802
    public Image getImageLegend() {
803
        File file;
804
        BufferedImage img = null;
805
        try {
806
        WMTSLayer wmtsLayer = getWMTSClient().getLayer(getLayerName());
807
        WMTSStyle wmtsStyle = null;
808
        List<WMTSStyle> wmtsStyles = wmtsLayer.getStyle();
809
        for (Iterator iterator = wmtsStyles.iterator(); iterator.hasNext();) {
810
            wmtsStyle = (WMTSStyle) iterator.next();
811
            if (wmtsStyle.getIdentifier().equalsIgnoreCase(wmtsStatus.getStyle())) {
812
                break;
813
            }
814
            wmtsStyle = null;
815
        }
816

    
817
            file = getWMTSClient().getLegendGraphic(wmtsLayer, wmtsStyle, null);
818
            img = ImageIO.read(file);
819
        } catch (InitializeException | WMTSException | IOException e) {
820
            logger.warn("Can't read image legend of WMTS Provider", e);
821
        }
822
        return img;
823
    }
824

    
825
    @Override
826
    public BufferDimensions getDimensions() throws InitializeException {
827
        if(this.dimensions==null){;
828
            Double pixelSize = getTileStruct().getPixelSizePerZoomLevel().get(getMaxZoomLevel());
829
            Envelope envelope = this.getEnvelope();
830
            int rows = (int)Math.round(envelope.getLength(DIMENSIONS.Y)/pixelSize);
831
            int columns = (int)Math.round(envelope.getLength(DIMENSIONS.X)/pixelSize);
832
            this.dimensions = BufferLocator.getBufferManager().createBufferDimensions(rows, columns, envelope);
833
        }
834
        return this.dimensions;
835
    }
836

    
837
    /**
838
     * @return the maxZoomLevel
839
     */
840
    public int getMaxZoomLevel() {
841
        return maxZoomLevel;
842
    }
843

    
844
//    /**
845
//     * @param maxZoomLevel the maxZoomLevel to set
846
//     */
847
//    public void setMaxZoomLevel(int maxZoomLevel) {
848
//        this.maxZoomLevel = maxZoomLevel;
849
//    }
850

    
851
}