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

History | View | Annotate | Download (25.2 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.RasterStore;
57
import org.gvsig.fmap.dal.raster.spi.NewRasterStoreParameters;
58
import org.gvsig.fmap.dal.raster.spi.RasterStoreProvider;
59
import org.gvsig.fmap.dal.serverexplorer.filesystem.spi.FilesystemServerExplorerManager;
60
import org.gvsig.fmap.dal.serverexplorer.filesystem.spi.FilesystemServerExplorerProviderFactory;
61
import org.gvsig.fmap.dal.spi.DALSPILocator;
62
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
63
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
64
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
65
import org.gvsig.fmap.geom.GeometryLocator;
66
import org.gvsig.fmap.geom.GeometryManager;
67
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
68
import org.gvsig.fmap.geom.primitive.Envelope;
69
import org.gvsig.raster.lib.buffer.api.Band;
70
import org.gvsig.raster.lib.buffer.api.Buffer;
71
import org.gvsig.raster.lib.buffer.api.BufferLocator;
72
import org.gvsig.raster.lib.buffer.api.BufferManager;
73
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
74
import org.gvsig.tools.ToolsLocator;
75
import org.gvsig.tools.dispose.DisposeUtils;
76
import org.gvsig.tools.dispose.impl.AbstractDisposable;
77
import org.gvsig.tools.dynobject.DynObject;
78
import org.gvsig.tools.dynobject.exception.DynMethodException;
79
import org.gvsig.tools.exception.BaseException;
80
import org.gvsig.tools.extensionpoint.ExtensionPoint.Extension;
81

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

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

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

    
103
    private Integer bandNumber = null;
104

    
105
    private int[] dataTypes;
106

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

    
113
    private RasterStoreProvider innerProvider;
114
    private RasterQuery query;
115

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
206
                        pixelSizePerZoomLevel.put(zoomLevel, pixelSize);
207

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

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

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

    
246
        BufferManager bufferManager = BufferLocator.getBufferManager();
247

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

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

    
262
                if (recentAccededTiles.size() >= MAX_RECENT_ACCEDED_TILES_NUMBER) {
263
                    removeOlderTile();
264
                }
265
                recentAccededTiles.put(keyTile, new Tile(rasterSet, keyTile));
266

    
267
                return rasterSet.getBand(band);
268
            } catch (DataException | BufferException e) {
269
                logger.warn("Can't fetch tile: zoomLevel = " + zoomLevel + ", tileRow = " + structRow + ", tileColumn = "
270
                    + structCol + ", band = " + band + ".", e);
271
                return null;
272
            } finally {
273
                if (tileStore != null) {
274
                    DisposeUtils.dispose(tileStore);
275
                }
276
            }
277
        }
278
    }
279

    
280
    private RasterStore createTileStore(int zoomLevel, int structRow, int structCol)
281
        throws ValidateDataParametersException, CreateEnvelopeException, BufferException, DataException,
282
        CloneNotSupportedException {
283

    
284
        File tileFile = null;
285
        File zoomFolder = new File(tilesFolder, String.valueOf(zoomLevel));
286
        if (!zoomFolder.exists()) {
287
            zoomFolder.mkdirs();
288
        }
289
        File firstColumnFolder = new File(zoomFolder, String.valueOf(structCol));
290
        if (!firstColumnFolder.exists()) {
291
            tileFile = requestTileFile(zoomLevel, structRow, structCol);
292
            this.extension = FilenameUtils.getExtension(tileFile.getAbsolutePath());
293
        }
294
        String rowBaseName = String.valueOf(structRow);
295
        if (this.extension == null) {
296
            File[] providerAcceptedFiles = firstColumnFolder.listFiles(factory);
297
            for (int i = 0; i < providerAcceptedFiles.length; i++) {
298
                File providerAcceptedFile = providerAcceptedFiles[i];
299
                if (FilenameUtils.getBaseName(providerAcceptedFile.getAbsolutePath()).equalsIgnoreCase(rowBaseName)) {
300
                    tileFile = providerAcceptedFile;
301
                }
302
            }
303
            if (tileFile == null || !tileFile.exists()) {
304
                tileFile = requestTileFile(zoomLevel, structRow, structCol);
305
            }
306
            this.extension = FilenameUtils.getExtension(tileFile.getAbsolutePath());
307
        } else {
308
            if (tileFile == null) {
309
                tileFile =
310
                    new File(firstColumnFolder.getAbsolutePath() + File.separatorChar + rowBaseName + "."
311
                        + this.extension);
312
            }
313
        }
314
        if (!tileFile.exists()) {
315
            tileFile = requestTileFile(zoomLevel, structRow, structCol);
316
        }
317
        RasterStore tileStore = null;
318
        DataManagerProviderServices manager = DALSPILocator.getDataManagerProviderServices();
319
        DataStoreProviderFactory providerFactory = manager.getStoreProviderFactory(providerName);
320

    
321
        DynObject params = providerFactory.createParameters();
322
        if (params.getDynClass().getDynField("file") != null) {
323
            params.setDynValue("file", tileFile);
324
        }
325
        if (params.getDynClass().getDynField("crs") != null) {
326
            params.setDynValue("crs", this.crs);
327
        }
328

    
329
        tileStore = (RasterStore) manager.openStore(providerName, params);
330
        return tileStore;
331
    }
332

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

    
335
        RasterQuery rasterQuery = (RasterQuery) this.query.clone();
336

    
337
        Double pixelSize = this.pixelSizePerZoomLevel.get(zoomLevel);
338
        rasterQuery.setPixelSize(pixelSize);
339

    
340
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
341

    
342
        double minX = structExtent.getMinimum(DIMENSIONS.X) + structCol * (pixelSize * columnsPerTile);
343
        double minY = structExtent.getMaximum(DIMENSIONS.Y) - ((structRow + 1) * (pixelSize * rowsPerTile));
344
        double maxX = minX + pixelSize * columnsPerTile;
345
        double maxY = minY + pixelSize * rowsPerTile;
346
        Envelope envelope = geomManager.createEnvelope(minX, minY, maxX, maxY, SUBTYPES.GEOM2D);
347

    
348
        Buffer buffer = null;
349
        Buffer clippedBuffer = null;
350
        Buffer interpolatedBuffer = null;
351
        File destFile = null;
352

    
353
        try {
354
            buffer = innerProvider.createBuffer(rasterQuery);
355
            clippedBuffer = buffer.clip(envelope);
356
            interpolatedBuffer =
357
                clippedBuffer.createInterpolated(
358
                    (int) (Math.round(clippedBuffer.getPixelSizeY() * clippedBuffer.getRows() / pixelSize)),
359
                    (int) (Math.round(clippedBuffer.getPixelSizeX() * clippedBuffer.getColumns() / pixelSize)),
360
                    Buffer.INTERPOLATION_NearestNeighbour, null);
361

    
362
            String providerName = "GTiff";
363
            String extension = "tif";
364

    
365
            DataManagerProviderServices manager = DALSPILocator.getDataManagerProviderServices();
366
            DataServerExplorerParameters eparams;
367
            eparams = manager.createServerExplorerParameters("FilesystemExplorer");
368

    
369
            StringBuilder builder = new StringBuilder();
370
            builder.append(tilesFolder);
371
            builder.append(File.separator);
372
            builder.append(zoomLevel);
373
            builder.append(File.separator);
374
            builder.append(structCol);
375
            builder.append(File.separator);
376
            builder.append(structRow);
377
            builder.append(".");
378
            builder.append(extension);
379
            String path = builder.toString();
380
            destFile = new File(path);
381
            File parent = destFile.getParentFile();
382
            if (!parent.exists()) {
383
                parent.mkdirs();
384
            }
385
            eparams.setDynValue("initialpath", path);
386
            DataServerExplorer serverExplorer = manager.createServerExplorer(eparams);
387

    
388
            NewRasterStoreParameters params = (NewRasterStoreParameters) serverExplorer.getAddParameters(providerName);
389
            params.setDynValue("file", destFile);
390

    
391
            params.setDynValue("compress", "NONE");
392
            params.setDynValue("tfw", false);
393

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

    
398
            params.setBuffer(interpolatedBuffer);
399
            serverExplorer.add(providerName, params, true);
400
        } finally {
401
            if (buffer!=null){
402
                DisposeUtils.dispose(buffer);
403
            }
404
            if (clippedBuffer!=null){
405
                DisposeUtils.dispose(clippedBuffer);
406
            }
407
            if (interpolatedBuffer!=null){
408
                DisposeUtils.dispose(interpolatedBuffer);
409
            }
410
        }
411

    
412
        return destFile;
413
    }
414

    
415
    /**
416
     * @return the band number
417
     * @throws CloneNotSupportedException
418
     * @throws ValidateDataParametersException
419
     * @throws DataException
420
     * @throws BufferException
421
     * @throws CreateEnvelopeException
422
     * @throws DynMethodException
423
     */
424
    public int getBandNumber() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
425
        DataException, CloneNotSupportedException {
426
        if (this.bandNumber == null) {
427
            fillStoreInfo();
428
        }
429
        return this.bandNumber;
430
    }
431

    
432
    /**
433
     * @return the data types
434
     * @throws CloneNotSupportedException
435
     * @throws ValidateDataParametersException
436
     * @throws DataException
437
     * @throws BufferException
438
     * @throws CreateEnvelopeException
439
     * @throws DynMethodException
440
     */
441
    public int[] getDataTypes() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
442
        DataException, CloneNotSupportedException {
443
        if (this.dataTypes == null) {
444
            fillStoreInfo();
445
        }
446
        return this.dataTypes;
447
    }
448

    
449
    /**
450
     * @throws CloneNotSupportedException
451
     * @throws ValidateDataParametersException
452
     * @throws DynMethodException
453
     * @throws DataException
454
     * @throws BufferException
455
     * @throws CreateEnvelopeException
456
     *
457
     */
458
    private void fillStoreInfo() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
459
        DataException, CloneNotSupportedException {
460
        this.bandNumber = this.innerProvider.getBands();
461
        this.dataTypes = new int[this.bandNumber];
462
        for (int i = 0; i < this.bandNumber; i++) {
463
            dataTypes[i] = this.innerProvider.getBandInfo(i).getDataType();
464
        }
465
        try {
466
            this.colorInterpretation =
467
                this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETCOLORINTERPRETATION_NAME, null);
468
            this.colorTable = this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETCOLORTABLE_NAME, null);
469
            this.legend = this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETLEGEND_NAME, null);
470
        } catch (DynMethodException e) {
471
            logger.warn("Can't fill legend info from store.");
472
        }
473
    }
474

    
475
    /**
476
     * @param zoomLevel
477
     * @return rows per zoom level
478
     */
479
    public int getRows(int zoomLevel) {
480
        return (int) (Math.round(getEnvelope().getLength(DIMENSIONS.Y) / pixelSizePerZoomLevel.get(zoomLevel)));
481
    }
482

    
483
    /**
484
     * @param zoomLevel
485
     * @return columns per zoom level
486
     */
487
    public int getColumns(int zoomLevel) {
488
        return (int) (Math.round(this.getEnvelope().getLength(DIMENSIONS.X) / pixelSizePerZoomLevel.get(zoomLevel)));
489
    }
490

    
491
    /**
492
     * @return envelope per zoom level
493
     */
494
    public Envelope getEnvelope() {
495
        return structExtent;
496
    }
497

    
498
    /**
499
     * @return the rows number per tile
500
     */
501
    public int getRowsPerTile() {
502
        return rowsPerTile;
503
    }
504

    
505
    /**
506
     * @return the columns number per tile
507
     */
508
    public int getColumnsPerTile() {
509
        return columnsPerTile;
510
    }
511

    
512
    /**
513
     * @return the provider name
514
     */
515
    public String getProviderName() {
516
        return providerName;
517
    }
518

    
519
    private String composeKeyForRecentTiles(int zoomLevel, int structRow, int structCol) {
520
        StringBuilder builder = new StringBuilder();
521
        builder.append(zoomLevel);
522
        builder.append(":");
523
        builder.append(structCol);
524
        builder.append(":");
525
        builder.append(structRow);
526
        return builder.toString();
527
    }
528

    
529
    private void removeOlderTile() {
530
        Tile olderTile = null;
531
        for (Iterator<Tile> iterator = recentAccededTiles.values().iterator(); iterator.hasNext();) {
532
            Tile tile = (Tile) iterator.next();
533
            if (olderTile == null || tile.getLastAccess() < olderTile.getLastAccess()) {
534
                olderTile = tile;
535
            }
536
        }
537
        if (olderTile != null) {
538
            recentAccededTiles.remove(olderTile.getKey());
539
            DisposeUtils.dispose(olderTile);
540
        }
541
    }
542

    
543
    /**
544
     * @return the color interpretation
545
     * @throws DynMethodException
546
     * @throws CloneNotSupportedException
547
     * @throws ValidateDataParametersException
548
     * @throws DataException
549
     * @throws BufferException
550
     * @throws CreateEnvelopeException
551
     */
552
    public Object getColorInterpretation() throws DynMethodException, ValidateDataParametersException,
553
        CreateEnvelopeException, BufferException, DataException, CloneNotSupportedException {
554
        if (this.colorInterpretation == null) {
555
            fillStoreInfo();
556
        }
557
        return this.colorInterpretation;
558
    }
559

    
560
    /**
561
     * @return the color table
562
     * @throws ValidateDataParametersException
563
     * @throws DynMethodException
564
     * @throws CloneNotSupportedException
565
     * @throws DataException
566
     * @throws BufferException
567
     * @throws CreateEnvelopeException
568
     * @throws InitializeException
569
     * @throws ProviderNotRegisteredException
570
     */
571
    public Object getColorTable() throws DynMethodException, ValidateDataParametersException, CreateEnvelopeException,
572
        BufferException, DataException, CloneNotSupportedException {
573
        if (this.colorTable == null) {
574
            fillStoreInfo();
575
        }
576
        return this.colorTable;
577
    }
578

    
579
    /**
580
     * @return the legend
581
     * @throws ValidateDataParametersException
582
     * @throws DynMethodException
583
     * @throws CloneNotSupportedException
584
     * @throws DataException
585
     * @throws BufferException
586
     * @throws CreateEnvelopeException
587
     * @throws InitializeException
588
     * @throws ProviderNotRegisteredException
589
     */
590
    public Object getLegend() throws DynMethodException, ValidateDataParametersException, CreateEnvelopeException,
591
        BufferException, DataException, CloneNotSupportedException {
592
        if (this.legend == null) {
593
            fillStoreInfo();
594
        }
595
        return this.legend;
596
    }
597

    
598
    private class Tile extends AbstractDisposable {
599

    
600
        org.gvsig.raster.lib.buffer.api.Buffer buffer;
601
        long lastAccess;
602
        String key;
603

    
604
        public Tile(org.gvsig.raster.lib.buffer.api.Buffer buffer, String key) {
605
            logger.info("CONSTRUCTOR hashCode = "+this.hashCode()+ " className = "+this.getClass().getSimpleName());
606
            ToolsLocator.getDisposableManager().bind(buffer);
607
            this.buffer = buffer;
608
            this.key = key;
609
            lastAccess = System.currentTimeMillis();
610
        }
611

    
612
        public String getKey() {
613
            return key;
614
        }
615

    
616
        public org.gvsig.raster.lib.buffer.api.Buffer getBuffer() {
617
            lastAccess = System.currentTimeMillis();
618
            return buffer;
619
        }
620

    
621
        public long getLastAccess() {
622
            return lastAccess;
623
        }
624

    
625
        @Override
626
        protected void finalize() throws Throwable {
627
            super.finalize();
628
            logger.info("CLEANED key " + this.key +" hashCode = "+this.hashCode());
629
        }
630

    
631
        @Override
632
        protected void doDispose() throws BaseException {
633
            DisposeUtils.dispose(buffer);
634
            buffer = null;
635
        }
636
    }
637

    
638
    @Override
639
    protected void doDispose() throws BaseException {
640
        if(recentAccededTiles!=null){
641
            Set<Entry<String, Tile>> entrySet = recentAccededTiles.entrySet();
642
            for (Iterator iterator = entrySet.iterator(); iterator.hasNext();) {
643
                Entry<String, Tile> entry = (Entry<String, Tile>) iterator.next();
644
                DisposeUtils.dispose(entry.getValue());
645
            }
646
            recentAccededTiles.clear();
647
        }
648
        if(innerProvider!=null){
649
            DisposeUtils.dispose(innerProvider);
650
            innerProvider=null;
651
        }
652
        query=null;
653
        factory=null;
654
        crs=null;
655
        structExtent=null;
656
        colorInterpretation=null;
657
        legend=null;
658
        colorTable=null;
659
    }
660

    
661
}