Statistics
| Revision:

gvsig-raster / org.gvsig.raster / branches / org.gvsig.raster.2.4 / org.gvsig.raster / org.gvsig.raster.tilecache / org.gvsig.raster.tilecache.provider / src / main / java / org / gvsig / raster / tilecache / provider / TileStructImage.java @ 6506

History | View | Annotate | Download (25.8 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2016 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.raster.tilecache.provider;
24

    
25
import java.io.File;
26
import java.util.HashMap;
27
import java.util.Iterator;
28
import java.util.Map;
29
import java.util.Map.Entry;
30
import java.util.Set;
31
import java.util.SortedMap;
32
import java.util.TreeMap;
33

    
34
import javax.xml.parsers.DocumentBuilder;
35
import javax.xml.parsers.DocumentBuilderFactory;
36

    
37
import org.apache.commons.io.FilenameUtils;
38
import org.cresques.cts.IProjection;
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41
import org.w3c.dom.Document;
42
import org.w3c.dom.Element;
43
import org.w3c.dom.NamedNodeMap;
44
import org.w3c.dom.Node;
45
import org.w3c.dom.NodeList;
46

    
47
import org.gvsig.fmap.dal.DALFileLocator;
48
import org.gvsig.fmap.dal.DataServerExplorer;
49
import org.gvsig.fmap.dal.DataServerExplorerParameters;
50
import org.gvsig.fmap.dal.DataStoreProviderFactory;
51
import org.gvsig.fmap.dal.exception.DataException;
52
import org.gvsig.fmap.dal.exception.InitializeException;
53
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
54
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
55
import org.gvsig.fmap.dal.raster.api.RasterQuery;
56
import org.gvsig.fmap.dal.raster.api.RasterSet;
57
import org.gvsig.fmap.dal.raster.api.RasterStore;
58
import org.gvsig.fmap.dal.raster.spi.NewRasterStoreParameters;
59
import org.gvsig.fmap.dal.raster.spi.RasterStoreProvider;
60
import org.gvsig.fmap.dal.serverexplorer.filesystem.spi.FilesystemServerExplorerManager;
61
import org.gvsig.fmap.dal.serverexplorer.filesystem.spi.FilesystemServerExplorerProviderFactory;
62
import org.gvsig.fmap.dal.spi.DALSPILocator;
63
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
64
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
65
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
66
import org.gvsig.fmap.geom.GeometryLocator;
67
import org.gvsig.fmap.geom.GeometryManager;
68
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
69
import org.gvsig.fmap.geom.primitive.Envelope;
70
import org.gvsig.raster.lib.buffer.api.Band;
71
import org.gvsig.raster.lib.buffer.api.Buffer;
72
import org.gvsig.raster.lib.buffer.api.BufferLocator;
73
import org.gvsig.raster.lib.buffer.api.BufferManager;
74
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
75
import org.gvsig.tools.ToolsLocator;
76
import org.gvsig.tools.dispose.DisposeUtils;
77
import org.gvsig.tools.dispose.impl.AbstractDisposable;
78
import org.gvsig.tools.dynobject.DynObject;
79
import org.gvsig.tools.dynobject.exception.DynMethodException;
80
import org.gvsig.tools.exception.BaseException;
81
import org.gvsig.tools.extensionpoint.ExtensionPoint.Extension;
82

    
83
/**
84
 * Represents a tiled image
85
 *
86
 * @author dmartinezizquierdo
87
 *
88
 */
89
public class TileStructImage extends AbstractDisposable {
90

    
91
    private static final Logger logger = LoggerFactory.getLogger(TileStructImage.class);
92
    private static final int MAX_RECENT_ACCEDED_TILES_NUMBER = 50;
93

    
94
    private int rowsPerTile;
95
    private int columnsPerTile;
96
    private FilesystemServerExplorerProviderFactory factory;
97
    private String providerName;
98
    private String extension;
99
    private SortedMap<Integer, Double> pixelSizePerZoomLevel;
100
    // private SortedMap<Integer,Envelope> envelopePerZoomLevel;
101
    private File tilesFolder;
102
    private Map<String, Tile> recentAccededTiles;
103

    
104
    private Integer bandNumber = null;
105

    
106
    private int[] dataTypes;
107

    
108
    private IProjection crs;
109
    private Envelope structExtent;
110
    private Object colorInterpretation;
111
    private Object legend;
112
    private Object colorTable;
113

    
114
    private RasterStoreProvider innerProvider;
115
    private RasterQuery query;
116

    
117
    /**
118
     * @param folder
119
     * @param crs
120
     * @param innerProvider
121
     * @param innerStore
122
     */
123
    public TileStructImage(File folder, IProjection crs, RasterStoreProvider innerProvider, RasterQuery query) {
124
        this.crs = crs;
125
        this.innerProvider = innerProvider;
126
        this.query = query;
127
        GeometryManager geoManager = GeometryLocator.getGeometryManager();
128

    
129
        // envelopePerZoomLevel = new TreeMap<Integer, Envelope>();
130
        pixelSizePerZoomLevel = new TreeMap<Integer, Double>();
131
        recentAccededTiles = new HashMap<String, Tile>();
132

    
133
        // FIXME
134
        File tilePropertiesFile = new File(folder, "tileCacheStruct.xml");
135
        tilesFolder = new File(folder, "V" + File.separatorChar + "Z" + File.separatorChar + "T");
136
        if (!tilesFolder.exists()) {
137
            tilesFolder.mkdirs();
138
        }
139
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
140
        DocumentBuilder dBuilder;
141
        try {
142
            dBuilder = dbFactory.newDocumentBuilder();
143
            Document doc = dBuilder.parse(tilePropertiesFile);
144

    
145
            doc.getDocumentElement().normalize();
146

    
147
            NodeList nList = doc.getElementsByTagName("TileCacheStruct");
148
            for (int temp = 0; temp < nList.getLength(); temp++) {
149

    
150
                Node nNode = nList.item(temp);
151

    
152
                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
153
                    Element eElement = (Element) nNode;
154

    
155
                    NamedNodeMap tileSizeAttributes = eElement.getElementsByTagName("tileSize").item(0).getAttributes();
156
                    rowsPerTile = Integer.valueOf(tileSizeAttributes.getNamedItem("rows").getNodeValue());
157
                    columnsPerTile = Integer.valueOf(tileSizeAttributes.getNamedItem("columns").getNodeValue());
158

    
159
                    NodeList elementsByTagName = eElement.getElementsByTagName("format");
160
                    providerName = elementsByTagName.item(0).getTextContent();
161

    
162
                    NodeList structExtentList = eElement.getElementsByTagName("structExtent");
163
                    if (structExtentList.getLength() > 0) {
164
                        Element structExtentNode = (Element) structExtentList.item(0);
165
                        if (structExtentNode != null) {
166
                            Double minX =
167
                                Double.valueOf(structExtentNode.getElementsByTagName("minX").item(0).getTextContent());
168
                            Double minY =
169
                                Double.valueOf(structExtentNode.getElementsByTagName("minY").item(0).getTextContent());
170
                            Double maxX =
171
                                Double.valueOf(structExtentNode.getElementsByTagName("maxX").item(0).getTextContent());
172
                            Double maxY =
173
                                Double.valueOf(structExtentNode.getElementsByTagName("maxY").item(0).getTextContent());
174
                            structExtent = geoManager.createEnvelope(minX, minY, maxX, maxY, SUBTYPES.GEOM2D);
175
                        }
176
                    }
177

    
178
                    FilesystemServerExplorerManager explorerManager =
179
                        DALFileLocator.getFilesystemServerExplorerManager();
180
                    @SuppressWarnings("unchecked")
181
                    Iterator<Extension> it = explorerManager.getRegisteredProviders();
182
                    while (it.hasNext()) {
183

    
184
                        Extension ext = it.next();
185
                        FilesystemServerExplorerProviderFactory providerFactory;
186
                        try {
187
                            providerFactory = (FilesystemServerExplorerProviderFactory) ext.create();
188
                            if (providerFactory.getName().equalsIgnoreCase(providerName)) {
189
                                this.factory = providerFactory;
190
                                break;
191
                            }
192
                        } catch (Exception e) {
193
                            throw new RuntimeException(e);// FIXME !!!
194
                        }
195
                    }
196

    
197
                    NodeList levelsTag = eElement.getElementsByTagName("levels");
198
                    Element levels = (Element) levelsTag.item(0);
199
                    NodeList levelList = levels.getElementsByTagName("level");
200
                    for (int i = 0; i < levelList.getLength(); i++) {
201
                        Element level = (Element) levelList.item(i);
202

    
203
                        NamedNodeMap levelAttributes = level.getAttributes();
204
                        int zoomLevel = Integer.valueOf(levelAttributes.getNamedItem("index").getNodeValue());
205
                        double pixelSize = Double.valueOf(levelAttributes.getNamedItem("pixelSize").getNodeValue());
206

    
207
                        pixelSizePerZoomLevel.put(zoomLevel, pixelSize);
208

    
209
                    }
210
                }
211
            }
212
        } catch (Exception e) {
213
            throw new RuntimeException();
214
        }
215
    }
216

    
217
    /**
218
     * @param pixelSize
219
     * @return The appropiate zoom level for the pizelSize
220
     */
221
    public int getZoomLvlForPixelSize(double pixelSize) {
222
        int zoom = 0;
223
        for (int i : pixelSizePerZoomLevel.keySet()) {
224
            zoom = i;
225
            double levelPixelSize = pixelSizePerZoomLevel.get(zoom);
226
            if (pixelSize >= levelPixelSize) {
227
                return zoom;
228
            }
229
        }
230
        return zoom;
231
    }
232

    
233
    /**
234
     * @param buffer
235
     * @param bandNumber
236
     * @param zoomLevel
237
     * @param tileRow
238
     * @param tileCol
239
     * @return Band
240
     * @throws CreateEnvelopeException
241
     * @throws CloneNotSupportedException
242
     * @throws ValidateDataParametersException
243
     */
244
    public Band fetchTile(int bandNumber, int zoomLevel, int structRow, int structCol) throws CreateEnvelopeException,
245
        ValidateDataParametersException, CloneNotSupportedException {
246

    
247
        BufferManager bufferManager = BufferLocator.getBufferManager();
248

    
249
        String keyTile = composeKeyForRecentTiles(zoomLevel, structRow, structCol);
250
        Tile tile = recentAccededTiles.get(keyTile);
251

    
252
        if (tile != null) {
253
            // Devolver la banda del buffer del tile
254
            return tile.getBuffer().getBand(bandNumber);
255
        } else {
256
            // Cargar un tile nuevo
257
            Buffer rasterSet = null;
258
            RasterStore tileStore = null;
259
            RasterSet tileStoreRasterSet = null;
260
            try {
261
                tileStore = createTileStore(zoomLevel, structRow, structCol);
262
                tileStoreRasterSet = tileStore.getRasterSet();
263
                rasterSet = bufferManager.createBuffer(tileStoreRasterSet, false);
264

    
265
                if (recentAccededTiles.size() >= MAX_RECENT_ACCEDED_TILES_NUMBER) {
266
                    removeOlderTile();
267
                }
268
                recentAccededTiles.put(keyTile, new Tile(rasterSet, keyTile));
269

    
270
                Band band = rasterSet.getBand(bandNumber);
271
                ToolsLocator.getDisposableManager().bind(band);
272
                return band;
273
            } catch (DataException | BufferException e) {
274
                logger.warn("Can't fetch tile: zoomLevel = " + zoomLevel + ", tileRow = " + structRow + ", tileColumn = "
275
                    + structCol + ", band = " + bandNumber + ".", e);
276
                return null;
277
            } finally {
278
                if (tileStore != null) {
279
                    DisposeUtils.dispose(tileStore);
280
                    tileStore = null;
281
                }
282
                if (tileStoreRasterSet != null) {
283
                    DisposeUtils.dispose(tileStoreRasterSet);
284
                    tileStoreRasterSet = null;
285
                }
286
                if (rasterSet != null) {
287
                    DisposeUtils.dispose(rasterSet);
288
                    rasterSet = null;
289
                }
290
            }
291
        }
292
    }
293

    
294
    private RasterStore createTileStore(int zoomLevel, int structRow, int structCol)
295
        throws ValidateDataParametersException, CreateEnvelopeException, BufferException, DataException,
296
        CloneNotSupportedException {
297

    
298
        File tileFile = null;
299
        File zoomFolder = new File(tilesFolder, String.valueOf(zoomLevel));
300
        if (!zoomFolder.exists()) {
301
            zoomFolder.mkdirs();
302
        }
303
        File firstColumnFolder = new File(zoomFolder, String.valueOf(structCol));
304
        if (!firstColumnFolder.exists()) {
305
            tileFile = requestTileFile(zoomLevel, structRow, structCol);
306
            this.extension = FilenameUtils.getExtension(tileFile.getAbsolutePath());
307
        }
308
        String rowBaseName = String.valueOf(structRow);
309
        if (this.extension == null) {
310
            File[] providerAcceptedFiles = firstColumnFolder.listFiles(factory);
311
            for (int i = 0; i < providerAcceptedFiles.length; i++) {
312
                File providerAcceptedFile = providerAcceptedFiles[i];
313
                if (FilenameUtils.getBaseName(providerAcceptedFile.getAbsolutePath()).equalsIgnoreCase(rowBaseName)) {
314
                    tileFile = providerAcceptedFile;
315
                }
316
            }
317
            if (tileFile == null || !tileFile.exists()) {
318
                tileFile = requestTileFile(zoomLevel, structRow, structCol);
319
            }
320
            this.extension = FilenameUtils.getExtension(tileFile.getAbsolutePath());
321
        } else {
322
            if (tileFile == null) {
323
                tileFile =
324
                    new File(firstColumnFolder.getAbsolutePath() + File.separatorChar + rowBaseName + "."
325
                        + this.extension);
326
            }
327
        }
328
        if (!tileFile.exists()) {
329
            tileFile = requestTileFile(zoomLevel, structRow, structCol);
330
        }
331
        RasterStore tileStore = null;
332
        DataManagerProviderServices manager = DALSPILocator.getDataManagerProviderServices();
333
        DataStoreProviderFactory providerFactory = manager.getStoreProviderFactory(providerName);
334

    
335
        DynObject params = providerFactory.createParameters();
336
        if (params.getDynClass().getDynField("file") != null) {
337
            params.setDynValue("file", tileFile);
338
        }
339
        if (params.getDynClass().getDynField("crs") != null) {
340
            params.setDynValue("crs", this.crs);
341
        }
342

    
343
        tileStore = (RasterStore) manager.openStore(providerName, params);
344
        return tileStore;
345
    }
346

    
347
    private File requestTileFile(int zoomLevel, int structRow, int structCol) throws CreateEnvelopeException, CloneNotSupportedException, BufferException, ValidateDataParametersException, DataException {
348

    
349
        RasterQuery rasterQuery = (RasterQuery) this.query.clone();
350

    
351
        Double pixelSize = this.pixelSizePerZoomLevel.get(zoomLevel);
352
        rasterQuery.setPixelSize(pixelSize);
353

    
354
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
355

    
356
        double minX = structExtent.getMinimum(DIMENSIONS.X) + structCol * (pixelSize * columnsPerTile);
357
        double minY = structExtent.getMaximum(DIMENSIONS.Y) - ((structRow + 1) * (pixelSize * rowsPerTile));
358
        double maxX = minX + pixelSize * columnsPerTile;
359
        double maxY = minY + pixelSize * rowsPerTile;
360
        Envelope envelope = geomManager.createEnvelope(minX, minY, maxX, maxY, SUBTYPES.GEOM2D);
361

    
362
        Buffer buffer = null;
363
        Buffer clippedBuffer = null;
364
        Buffer interpolatedBuffer = null;
365
        File destFile = null;
366

    
367
        try {
368
            buffer = innerProvider.createBuffer(rasterQuery);
369
            clippedBuffer = buffer.clip(envelope);
370
            interpolatedBuffer =
371
                clippedBuffer.createInterpolated(
372
                    (int) (Math.round(clippedBuffer.getPixelSizeY() * clippedBuffer.getRows() / pixelSize)),
373
                    (int) (Math.round(clippedBuffer.getPixelSizeX() * clippedBuffer.getColumns() / pixelSize)),
374
                    Buffer.INTERPOLATION_NearestNeighbour, null);
375

    
376
            String providerName = "GTiff";
377
            String extension = "tif";
378

    
379
            DataManagerProviderServices manager = DALSPILocator.getDataManagerProviderServices();
380
            DataServerExplorerParameters eparams;
381
            eparams = manager.createServerExplorerParameters("FilesystemExplorer");
382

    
383
            StringBuilder builder = new StringBuilder();
384
            builder.append(tilesFolder);
385
            builder.append(File.separator);
386
            builder.append(zoomLevel);
387
            builder.append(File.separator);
388
            builder.append(structCol);
389
            builder.append(File.separator);
390
            builder.append(structRow);
391
            builder.append(".");
392
            builder.append(extension);
393
            String path = builder.toString();
394
            destFile = new File(path);
395
            File parent = destFile.getParentFile();
396
            if (!parent.exists()) {
397
                parent.mkdirs();
398
            }
399
            eparams.setDynValue("initialpath", path);
400
            DataServerExplorer serverExplorer = manager.createServerExplorer(eparams);
401

    
402
            NewRasterStoreParameters params = (NewRasterStoreParameters) serverExplorer.getAddParameters(providerName);
403
            params.setDynValue("file", destFile);
404

    
405
            params.setDynValue("compress", "NONE");
406
            params.setDynValue("tfw", false);
407

    
408
            //FIXME: Ver de coger estos dos valores del inner provider para que los tiles sean homog?neos con el raster original
409
            params.setDynValue("photometric", "RGB");
410
            params.setDynValue("alpha", "NON-PREMULTIPLIED");
411

    
412
            params.setBuffer(interpolatedBuffer);
413
            serverExplorer.add(providerName, params, true);
414
        } finally {
415
            if (buffer!=null){
416
                DisposeUtils.dispose(buffer);
417
            }
418
            if (clippedBuffer!=null){
419
                DisposeUtils.dispose(clippedBuffer);
420
            }
421
            if (interpolatedBuffer!=null){
422
                DisposeUtils.dispose(interpolatedBuffer);
423
            }
424
        }
425

    
426
        return destFile;
427
    }
428

    
429
    /**
430
     * @return the band number
431
     * @throws CloneNotSupportedException
432
     * @throws ValidateDataParametersException
433
     * @throws DataException
434
     * @throws BufferException
435
     * @throws CreateEnvelopeException
436
     * @throws DynMethodException
437
     */
438
    public int getBandNumber() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
439
        DataException, CloneNotSupportedException {
440
        if (this.bandNumber == null) {
441
            fillStoreInfo();
442
        }
443
        return this.bandNumber;
444
    }
445

    
446
    /**
447
     * @return the data types
448
     * @throws CloneNotSupportedException
449
     * @throws ValidateDataParametersException
450
     * @throws DataException
451
     * @throws BufferException
452
     * @throws CreateEnvelopeException
453
     * @throws DynMethodException
454
     */
455
    public int[] getDataTypes() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
456
        DataException, CloneNotSupportedException {
457
        if (this.dataTypes == null) {
458
            fillStoreInfo();
459
        }
460
        return this.dataTypes;
461
    }
462

    
463
    /**
464
     * @throws CloneNotSupportedException
465
     * @throws ValidateDataParametersException
466
     * @throws DynMethodException
467
     * @throws DataException
468
     * @throws BufferException
469
     * @throws CreateEnvelopeException
470
     *
471
     */
472
    private void fillStoreInfo() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
473
        DataException, CloneNotSupportedException {
474
        this.bandNumber = this.innerProvider.getBands();
475
        this.dataTypes = new int[this.bandNumber];
476
        for (int i = 0; i < this.bandNumber; i++) {
477
            dataTypes[i] = this.innerProvider.getBandInfo(i).getDataType();
478
        }
479
        try {
480
            this.colorInterpretation =
481
                this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETCOLORINTERPRETATION_NAME, null);
482
            this.colorTable = this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETCOLORTABLE_NAME, null);
483
            this.legend = this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETLEGEND_NAME, null);
484
        } catch (DynMethodException e) {
485
            logger.warn("Can't fill legend info from store.");
486
        }
487
    }
488

    
489
    /**
490
     * @param zoomLevel
491
     * @return rows per zoom level
492
     */
493
    public int getRows(int zoomLevel) {
494
        return (int) (Math.round(getEnvelope().getLength(DIMENSIONS.Y) / pixelSizePerZoomLevel.get(zoomLevel)));
495
    }
496

    
497
    /**
498
     * @param zoomLevel
499
     * @return columns per zoom level
500
     */
501
    public int getColumns(int zoomLevel) {
502
        return (int) (Math.round(this.getEnvelope().getLength(DIMENSIONS.X) / pixelSizePerZoomLevel.get(zoomLevel)));
503
    }
504

    
505
    /**
506
     * @return envelope per zoom level
507
     */
508
    public Envelope getEnvelope() {
509
        return structExtent;
510
    }
511

    
512
    /**
513
     * @return the rows number per tile
514
     */
515
    public int getRowsPerTile() {
516
        return rowsPerTile;
517
    }
518

    
519
    /**
520
     * @return the columns number per tile
521
     */
522
    public int getColumnsPerTile() {
523
        return columnsPerTile;
524
    }
525

    
526
    /**
527
     * @return the provider name
528
     */
529
    public String getProviderName() {
530
        return providerName;
531
    }
532

    
533
    private String composeKeyForRecentTiles(int zoomLevel, int structRow, int structCol) {
534
        StringBuilder builder = new StringBuilder();
535
        builder.append(zoomLevel);
536
        builder.append(":");
537
        builder.append(structCol);
538
        builder.append(":");
539
        builder.append(structRow);
540
        return builder.toString();
541
    }
542

    
543
    private void removeOlderTile() {
544
        Tile olderTile = null;
545
        for (Iterator<Tile> iterator = recentAccededTiles.values().iterator(); iterator.hasNext();) {
546
            Tile tile = (Tile) iterator.next();
547
            if (olderTile == null || tile.getLastAccess() < olderTile.getLastAccess()) {
548
                olderTile = tile;
549
            }
550
        }
551
        if (olderTile != null) {
552
            recentAccededTiles.remove(olderTile.getKey());
553
            DisposeUtils.dispose(olderTile);
554
        }
555
    }
556

    
557
    /**
558
     * @return the color interpretation
559
     * @throws DynMethodException
560
     * @throws CloneNotSupportedException
561
     * @throws ValidateDataParametersException
562
     * @throws DataException
563
     * @throws BufferException
564
     * @throws CreateEnvelopeException
565
     */
566
    public Object getColorInterpretation() throws DynMethodException, ValidateDataParametersException,
567
        CreateEnvelopeException, BufferException, DataException, CloneNotSupportedException {
568
        if (this.colorInterpretation == null) {
569
            fillStoreInfo();
570
        }
571
        return this.colorInterpretation;
572
    }
573

    
574
    /**
575
     * @return the color table
576
     * @throws ValidateDataParametersException
577
     * @throws DynMethodException
578
     * @throws CloneNotSupportedException
579
     * @throws DataException
580
     * @throws BufferException
581
     * @throws CreateEnvelopeException
582
     * @throws InitializeException
583
     * @throws ProviderNotRegisteredException
584
     */
585
    public Object getColorTable() throws DynMethodException, ValidateDataParametersException, CreateEnvelopeException,
586
        BufferException, DataException, CloneNotSupportedException {
587
        if (this.colorTable == null) {
588
            fillStoreInfo();
589
        }
590
        return this.colorTable;
591
    }
592

    
593
    /**
594
     * @return the legend
595
     * @throws ValidateDataParametersException
596
     * @throws DynMethodException
597
     * @throws CloneNotSupportedException
598
     * @throws DataException
599
     * @throws BufferException
600
     * @throws CreateEnvelopeException
601
     * @throws InitializeException
602
     * @throws ProviderNotRegisteredException
603
     */
604
    public Object getLegend() throws DynMethodException, ValidateDataParametersException, CreateEnvelopeException,
605
        BufferException, DataException, CloneNotSupportedException {
606
        if (this.legend == null) {
607
            fillStoreInfo();
608
        }
609
        return this.legend;
610
    }
611

    
612
    private class Tile extends AbstractDisposable {
613

    
614
        org.gvsig.raster.lib.buffer.api.Buffer buffer;
615
        long lastAccess;
616
        String key;
617

    
618
        public Tile(org.gvsig.raster.lib.buffer.api.Buffer buffer, String key) {
619
            logger.info("CONSTRUCTOR hashCode = "+this.hashCode()+ " className = "+this.getClass().getSimpleName());
620
            ToolsLocator.getDisposableManager().bind(buffer);
621
            this.buffer = buffer;
622
            this.key = key;
623
            lastAccess = System.currentTimeMillis();
624
        }
625

    
626
        public String getKey() {
627
            return key;
628
        }
629

    
630
        public org.gvsig.raster.lib.buffer.api.Buffer getBuffer() {
631
            lastAccess = System.currentTimeMillis();
632
            return buffer;
633
        }
634

    
635
        public long getLastAccess() {
636
            return lastAccess;
637
        }
638

    
639
        @Override
640
        protected void finalize() throws Throwable {
641
            super.finalize();
642
            logger.info("CLEANED key " + this.key +" hashCode = "+this.hashCode());
643
        }
644

    
645
        @Override
646
        protected void doDispose() throws BaseException {
647
            DisposeUtils.dispose(buffer);
648
            buffer = null;
649
        }
650
    }
651

    
652
    @Override
653
    protected void doDispose() throws BaseException {
654
        if(recentAccededTiles!=null){
655
            Set<Entry<String, Tile>> entrySet = recentAccededTiles.entrySet();
656
            for (Iterator iterator = entrySet.iterator(); iterator.hasNext();) {
657
                Entry<String, Tile> entry = (Entry<String, Tile>) iterator.next();
658
                DisposeUtils.dispose(entry.getValue());
659
            }
660
            recentAccededTiles.clear();
661
        }
662
        if(innerProvider!=null){
663
            DisposeUtils.dispose(innerProvider);
664
            innerProvider=null;
665
        }
666
        query=null;
667
        factory=null;
668
        crs=null;
669
        structExtent=null;
670
        colorInterpretation=null;
671
        legend=null;
672
        colorTable=null;
673
    }
674

    
675
}