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

History | View | Annotate | Download (24.9 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.SortedMap;
30
import java.util.TreeMap;
31

    
32
import javax.xml.parsers.DocumentBuilder;
33
import javax.xml.parsers.DocumentBuilderFactory;
34

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

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

    
80
/**
81
 * Represents a tiled image
82
 *
83
 * @author dmartinezizquierdo
84
 *
85
 */
86
public class TileStructImage {
87

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

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

    
101
    private Integer bandNumber = null;
102

    
103
    private int[] dataTypes;
104

    
105
    private IProjection crs;
106
    private Envelope structExtent;
107
    private Object colorInterpretation;
108
    private Object legend;
109
    private Object colorTable;
110

    
111
    private RasterStoreProvider innerProvider;
112
    private RasterQuery query;
113

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

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

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

    
142
            doc.getDocumentElement().normalize();
143

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

    
147
                Node nNode = nList.item(temp);
148

    
149
                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
150
                    Element eElement = (Element) nNode;
151

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

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

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

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

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

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

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

    
204
                        pixelSizePerZoomLevel.put(zoomLevel, pixelSize);
205

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

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

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

    
244
        BufferManager bufferManager = BufferLocator.getBufferManager();
245

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

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

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

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

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

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

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

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

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

    
333
        RasterQuery rasterQuery = (RasterQuery) this.query.clone();
334

    
335
        Double pixelSize = this.pixelSizePerZoomLevel.get(zoomLevel);
336
        rasterQuery.setPixelSize(pixelSize);
337

    
338
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
339

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

    
346
        Buffer buffer = null;
347
        Buffer clippedBuffer = null;
348
        Buffer interpolatedBuffer = null;
349
        File destFile = null;
350

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

    
360
            String providerName = "GTiff";
361
            String extension = "tif";
362

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

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

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

    
389
            params.setDynValue("compress", "NONE");
390
            params.setDynValue("tfw", false);
391
            params.setDynValue("photometric", "RGB");
392
            params.setDynValue("alpha", "NON-PREMULTIPLIED");
393

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

    
408
        return destFile;
409
    }
410

    
411
    /**
412
     * @return delegatedRasterStore
413
     * @throws CloneNotSupportedException
414
     * @throws ValidateDataParametersException
415
     * @throws DataException
416
     * @throws BufferException
417
     * @throws CreateEnvelopeException
418
     */
419
    private RasterStore getDelegatedRasterStore() throws ValidateDataParametersException, CreateEnvelopeException,
420
        BufferException, DataException, CloneNotSupportedException {
421
        return createTileStore(0, 0, 0);
422
    }
423

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

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

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

    
486
        } finally {
487
            if (rasterStore != null) {
488
                DisposeUtils.dispose(rasterStore);
489
            }
490
        }
491
    }
492

    
493
    /**
494
     * @param zoomLevel
495
     * @return rows per zoom level
496
     */
497
    public int getRows(int zoomLevel) {
498
        return (int) (Math.round(getEnvelope().getLength(DIMENSIONS.Y) / pixelSizePerZoomLevel.get(zoomLevel)));
499
    }
500

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

    
509
    /**
510
     * @return envelope per zoom level
511
     */
512
    public Envelope getEnvelope() {
513
        return structExtent;
514
    }
515

    
516
    /**
517
     * @return the rows number per tile
518
     */
519
    public int getRowsPerTile() {
520
        return rowsPerTile;
521
    }
522

    
523
    /**
524
     * @return the columns number per tile
525
     */
526
    public int getColumnsPerTile() {
527
        return columnsPerTile;
528
    }
529

    
530
    /**
531
     * @return the provider name
532
     */
533
    public String getProviderName() {
534
        return providerName;
535
    }
536

    
537
    private String composeKeyForRecentTiles(int zoomLevel, int structRow, int structCol) {
538
        StringBuilder builder = new StringBuilder();
539
        builder.append(zoomLevel);
540
        builder.append(":");
541
        builder.append(structCol);
542
        builder.append(":");
543
        builder.append(structRow);
544
        return builder.toString();
545
    }
546

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

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

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

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

    
616
    private class Tile extends AbstractDisposable {
617

    
618
        org.gvsig.raster.lib.buffer.api.Buffer buffer;
619
        long lastAccess;
620
        String key;
621

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

    
630
        public String getKey() {
631
            return key;
632
        }
633

    
634
        public org.gvsig.raster.lib.buffer.api.Buffer getBuffer() {
635
            lastAccess = System.currentTimeMillis();
636
            return buffer;
637
        }
638

    
639
        public long getLastAccess() {
640
            return lastAccess;
641
        }
642

    
643
        @Override
644
        protected void finalize() throws Throwable {
645
            super.finalize();
646
            logger.info("CLEANED key " + this.key +" hashCode = "+this.hashCode());
647
        }
648

    
649
        @Override
650
        protected void doDispose() throws BaseException {
651
            DisposeUtils.dispose(buffer);
652
            buffer = null;
653
        }
654
    }
655

    
656
}