Revision 6520

View differences:

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/AbstractTileStructImage.java
1
package org.gvsig.raster.tilecache.provider;
2

  
3
import java.util.Iterator;
4
import java.util.Map;
5

  
6
import org.slf4j.Logger;
7
import org.slf4j.LoggerFactory;
8

  
9
import org.gvsig.fmap.dal.exception.DataException;
10
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
11
import org.gvsig.fmap.dal.raster.api.RasterQuery;
12
import org.gvsig.fmap.dal.raster.api.RasterStore;
13
import org.gvsig.fmap.dal.raster.spi.RasterStoreProvider;
14
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
15
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
16
import org.gvsig.fmap.geom.primitive.Envelope;
17
import org.gvsig.raster.lib.buffer.api.TileStruct;
18
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
19
import org.gvsig.tools.ToolsLocator;
20
import org.gvsig.tools.dispose.DisposeUtils;
21
import org.gvsig.tools.dispose.impl.AbstractDisposable;
22
import org.gvsig.tools.dynobject.exception.DynMethodException;
23
import org.gvsig.tools.exception.BaseException;
24

  
25
/**
26
 * @author fdiaz
27
 *
28
 */
29
public abstract class AbstractTileStructImage extends AbstractDisposable implements TileStructImage {
30

  
31
    private static final Logger logger = LoggerFactory.getLogger(AbstractTileStructImage.class);
32

  
33
    protected RasterStoreProvider innerProvider;
34
    protected RasterQuery query;
35
    protected TileStruct tileStruct;
36

  
37
    protected Object colorInterpretation;
38
    protected Object legend;
39
    protected Object colorTable;
40

  
41
    protected Map<String, Tile> recentAccededTiles;
42

  
43
    protected Integer bandNumber = null;
44

  
45
    protected int[] dataTypes;
46

  
47
    /**
48
     * @param innerProvider
49
     * @param query
50
     */
51
    public AbstractTileStructImage(RasterStoreProvider innerProvider, RasterQuery query) {
52
        super();
53
        this.innerProvider = innerProvider;
54
        this.query = query;
55
    }
56

  
57
    /**
58
     * @param pixelSize
59
     * @return The appropriate zoom level for the pizelSize
60
     */
61
    public int getZoomLvlForPixelSize(double pixelSize) {
62
        int zoom = 0;
63
        Map<Integer, Double> pixelSizePerZoomLevel = tileStruct.getPixelSizePerZoomLevel();
64
        for (int i : pixelSizePerZoomLevel.keySet()) {
65
            zoom = i;
66
            double levelPixelSize = pixelSizePerZoomLevel.get(zoom);
67
            if (pixelSize >= levelPixelSize) {
68
                return zoom;
69
            }
70
        }
71
        return zoom;
72
    }
73

  
74
    /**
75
     * @throws CloneNotSupportedException
76
     * @throws ValidateDataParametersException
77
     * @throws DynMethodException
78
     * @throws DataException
79
     * @throws BufferException
80
     * @throws CreateEnvelopeException
81
     *
82
     */
83
    protected void fillStoreInfo() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
84
        DataException, CloneNotSupportedException {
85
        this.bandNumber = this.innerProvider.getBands();
86
        this.dataTypes = new int[this.bandNumber];
87
        for (int i = 0; i < this.bandNumber; i++) {
88
            dataTypes[i] = this.innerProvider.getBandInfo(i).getDataType();
89
        }
90
        try {
91
            this.colorInterpretation =
92
                this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETCOLORINTERPRETATION_NAME, null);
93
            this.colorTable = this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETCOLORTABLE_NAME, null);
94
            this.legend = this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETLEGEND_NAME, null);
95
        } catch (DynMethodException e) {
96
            logger.warn("Can't fill legend info from store.");
97
        }
98
    }
99

  
100
    /* (non-Javadoc)
101
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getBandNumber()
102
     */
103
    @Override
104
    public int getBandNumber() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
105
        DataException, CloneNotSupportedException {
106
        if (this.bandNumber == null) {
107
            fillStoreInfo();
108
        }
109
        return this.bandNumber;
110
    }
111

  
112

  
113
    /* (non-Javadoc)
114
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getDataTypes()
115
     */
116
    @Override
117
    public int[] getDataTypes() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
118
        DataException, CloneNotSupportedException {
119
        if (this.dataTypes == null) {
120
            fillStoreInfo();
121
        }
122
        return this.dataTypes;
123
    }
124

  
125
    /* (non-Javadoc)
126
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getRows(int)
127
     */
128
    @Override
129
    public int getRows(int zoomLevel) {
130
        return (int) (Math.round(getEnvelope().getLength(DIMENSIONS.Y) / this.tileStruct.getPixelSizePerZoomLevel().get(zoomLevel)));
131
    }
132

  
133
    /* (non-Javadoc)
134
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getColumns(int)
135
     */
136
    @Override
137
    public int getColumns(int zoomLevel) {
138
        return (int) (Math.round(this.getEnvelope().getLength(DIMENSIONS.X) / this.tileStruct.getPixelSizePerZoomLevel().get(zoomLevel)));
139
    }
140

  
141
    /* (non-Javadoc)
142
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getEnvelope()
143
     */
144
    @Override
145
    public Envelope getEnvelope() {
146
        return this.tileStruct.getEnvelope();
147
    }
148

  
149
    /* (non-Javadoc)
150
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getRowsPerTile()
151
     */
152
    @Override
153
    public int getRowsPerTile() {
154
        return this.tileStruct.getRowsPerTile();
155
    }
156

  
157
    /* (non-Javadoc)
158
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getColumnsPerTile()
159
     */
160
    @Override
161
    public int getColumnsPerTile() {
162
        return this.tileStruct.getColumnsPerTile();
163
    }
164

  
165
    /* (non-Javadoc)
166
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getProviderName()
167
     */
168
    @Override
169
    public String getProviderName() {
170
        return this.tileStruct.getProviderName();
171
    }
172

  
173
    protected String composeKeyForRecentTiles(int zoomLevel, int structRow, int structCol) {
174
        StringBuilder builder = new StringBuilder();
175
        builder.append(zoomLevel);
176
        builder.append(":");
177
        builder.append(structCol);
178
        builder.append(":");
179
        builder.append(structRow);
180
        return builder.toString();
181
    }
182

  
183
    protected void removeOlderTile() {
184
        Tile olderTile = null;
185
        for (Iterator<Tile> iterator = recentAccededTiles.values().iterator(); iterator.hasNext();) {
186
            Tile tile = (Tile) iterator.next();
187
            if (olderTile == null || tile.getLastAccess() < olderTile.getLastAccess()) {
188
                olderTile = tile;
189
            }
190
        }
191
        if (olderTile != null) {
192
            recentAccededTiles.remove(olderTile.getKey());
193
            DisposeUtils.dispose(olderTile);
194
        }
195
    }
196

  
197
    /* (non-Javadoc)
198
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getColorInterpretation()
199
     */
200
    @Override
201
    public Object getColorInterpretation() throws DynMethodException, ValidateDataParametersException,
202
        CreateEnvelopeException, BufferException, DataException, CloneNotSupportedException {
203
        if (this.colorInterpretation == null) {
204
            fillStoreInfo();
205
        }
206
        return this.colorInterpretation;
207
    }
208

  
209
    /* (non-Javadoc)
210
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getColorTable()
211
     */
212
    @Override
213
    public Object getColorTable() throws DynMethodException, ValidateDataParametersException, CreateEnvelopeException,
214
        BufferException, DataException, CloneNotSupportedException {
215
        if (this.colorTable == null) {
216
            fillStoreInfo();
217
        }
218
        return this.colorTable;
219
    }
220

  
221
    /* (non-Javadoc)
222
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getLegend()
223
     */
224
    @Override
225
    public Object getLegend() throws DynMethodException, ValidateDataParametersException, CreateEnvelopeException,
226
        BufferException, DataException, CloneNotSupportedException {
227
        if (this.legend == null) {
228
            fillStoreInfo();
229
        }
230
        return this.legend;
231
    }
232

  
233
    public void forgetCache(){
234
        this.recentAccededTiles.clear();
235
    }
236

  
237

  
238
    protected class Tile extends AbstractDisposable {
239

  
240
        org.gvsig.raster.lib.buffer.api.Buffer buffer;
241
        long lastAccess;
242
        String key;
243

  
244
        public Tile(org.gvsig.raster.lib.buffer.api.Buffer buffer, String key) {
245
            logger
246
                .info("CONSTRUCTOR hashCode = " + this.hashCode() + " className = " + this.getClass().getSimpleName());
247
            ToolsLocator.getDisposableManager().bind(buffer);
248
            this.buffer = buffer;
249
            this.key = key;
250
            lastAccess = System.currentTimeMillis();
251
        }
252

  
253
        public String getKey() {
254
            return key;
255
        }
256

  
257
        public org.gvsig.raster.lib.buffer.api.Buffer getBuffer() {
258
            lastAccess = System.currentTimeMillis();
259
            return buffer;
260
        }
261

  
262
        public long getLastAccess() {
263
            return lastAccess;
264
        }
265

  
266
        @Override
267
        protected void finalize() throws Throwable {
268
            super.finalize();
269
            logger.info("CLEANED key " + this.key + " hashCode = " + this.hashCode());
270
        }
271

  
272
        @Override
273
        protected void doDispose() throws BaseException {
274
            DisposeUtils.dispose(buffer);
275
            buffer = null;
276
        }
277
    }
278
}
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/AbstractTileCacheStructImage.java
1
package org.gvsig.raster.tilecache.provider;
2

  
3
import java.util.Iterator;
4
import java.util.Map;
5

  
6
import org.slf4j.Logger;
7
import org.slf4j.LoggerFactory;
8

  
9
import org.gvsig.fmap.dal.exception.DataException;
10
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
11
import org.gvsig.fmap.dal.raster.api.RasterQuery;
12
import org.gvsig.fmap.dal.raster.api.RasterStore;
13
import org.gvsig.fmap.dal.raster.spi.RasterStoreProvider;
14
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
15
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
16
import org.gvsig.fmap.geom.primitive.Envelope;
17
import org.gvsig.raster.lib.buffer.api.TileStruct;
18
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
19
import org.gvsig.tools.ToolsLocator;
20
import org.gvsig.tools.dispose.DisposeUtils;
21
import org.gvsig.tools.dispose.impl.AbstractDisposable;
22
import org.gvsig.tools.dynobject.exception.DynMethodException;
23
import org.gvsig.tools.exception.BaseException;
24

  
25
/**
26
 * @author fdiaz
27
 *
28
 */
29
public abstract class AbstractTileCacheStructImage extends AbstractDisposable implements TileCacheStructImage {
30

  
31
    private static final Logger logger = LoggerFactory.getLogger(AbstractTileCacheStructImage.class);
32

  
33
    protected RasterStoreProvider innerProvider;
34
    protected RasterQuery query;
35
    protected TileStruct tileStruct;
36

  
37
    protected Object colorInterpretation;
38
    protected Object legend;
39
    protected Object colorTable;
40

  
41
    protected Map<String, Tile> recentAccededTiles;
42

  
43
    protected Integer bandNumber = null;
44

  
45
    protected int[] dataTypes;
46

  
47
    /**
48
     * @param innerProvider
49
     * @param query
50
     */
51
    public AbstractTileCacheStructImage(RasterStoreProvider innerProvider, RasterQuery query) {
52
        super();
53
        this.innerProvider = innerProvider;
54
        this.query = query;
55
    }
56

  
57
    /**
58
     * @param pixelSize
59
     * @return The appropriate zoom level for the pizelSize
60
     */
61
    public int getZoomLvlForPixelSize(double pixelSize) {
62
        int zoom = 0;
63
        Map<Integer, Double> pixelSizePerZoomLevel = tileStruct.getPixelSizePerZoomLevel();
64
        for (int i : pixelSizePerZoomLevel.keySet()) {
65
            zoom = i;
66
            double levelPixelSize = pixelSizePerZoomLevel.get(zoom);
67
            if (pixelSize >= levelPixelSize) {
68
                return zoom;
69
            }
70
        }
71
        return zoom;
72
    }
73

  
74
    /**
75
     * @throws CloneNotSupportedException
76
     * @throws ValidateDataParametersException
77
     * @throws DynMethodException
78
     * @throws DataException
79
     * @throws BufferException
80
     * @throws CreateEnvelopeException
81
     *
82
     */
83
    protected void fillStoreInfo() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
84
        DataException, CloneNotSupportedException {
85
        this.bandNumber = this.innerProvider.getBands();
86
        this.dataTypes = new int[this.bandNumber];
87
        for (int i = 0; i < this.bandNumber; i++) {
88
            dataTypes[i] = this.innerProvider.getBandInfo(i).getDataType();
89
        }
90
        try {
91
            this.colorInterpretation =
92
                this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETCOLORINTERPRETATION_NAME, null);
93
            this.colorTable = this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETCOLORTABLE_NAME, null);
94
            this.legend = this.innerProvider.invokeDynMethod(RasterStore.DYNMETHOD_GETLEGEND_NAME, null);
95
        } catch (DynMethodException e) {
96
            logger.warn("Can't fill legend info from store.");
97
        }
98
    }
99

  
100
    /* (non-Javadoc)
101
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getBandNumber()
102
     */
103
    @Override
104
    public int getBandNumber() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
105
        DataException, CloneNotSupportedException {
106
        if (this.bandNumber == null) {
107
            fillStoreInfo();
108
        }
109
        return this.bandNumber;
110
    }
111

  
112

  
113
    /* (non-Javadoc)
114
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getDataTypes()
115
     */
116
    @Override
117
    public int[] getDataTypes() throws ValidateDataParametersException, CreateEnvelopeException, BufferException,
118
        DataException, CloneNotSupportedException {
119
        if (this.dataTypes == null) {
120
            fillStoreInfo();
121
        }
122
        return this.dataTypes;
123
    }
124

  
125
    /* (non-Javadoc)
126
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getRows(int)
127
     */
128
    @Override
129
    public int getRows(int zoomLevel) {
130
        return (int) (Math.round(getEnvelope().getLength(DIMENSIONS.Y) / this.tileStruct.getPixelSizePerZoomLevel().get(zoomLevel)));
131
    }
132

  
133
    /* (non-Javadoc)
134
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getColumns(int)
135
     */
136
    @Override
137
    public int getColumns(int zoomLevel) {
138
        return (int) (Math.round(this.getEnvelope().getLength(DIMENSIONS.X) / this.tileStruct.getPixelSizePerZoomLevel().get(zoomLevel)));
139
    }
140

  
141
    /* (non-Javadoc)
142
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getEnvelope()
143
     */
144
    @Override
145
    public Envelope getEnvelope() {
146
        return this.tileStruct.getEnvelope();
147
    }
148

  
149
    /* (non-Javadoc)
150
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getRowsPerTile()
151
     */
152
    @Override
153
    public int getRowsPerTile() {
154
        return this.tileStruct.getRowsPerTile();
155
    }
156

  
157
    /* (non-Javadoc)
158
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getColumnsPerTile()
159
     */
160
    @Override
161
    public int getColumnsPerTile() {
162
        return this.tileStruct.getColumnsPerTile();
163
    }
164

  
165
    /* (non-Javadoc)
166
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getProviderName()
167
     */
168
    @Override
169
    public String getProviderName() {
170
        return this.tileStruct.getProviderName();
171
    }
172

  
173
    protected String composeKeyForRecentTiles(int zoomLevel, int structRow, int structCol) {
174
        StringBuilder builder = new StringBuilder();
175
        builder.append(zoomLevel);
176
        builder.append(":");
177
        builder.append(structCol);
178
        builder.append(":");
179
        builder.append(structRow);
180
        return builder.toString();
181
    }
182

  
183
    protected void removeOlderTile() {
184
        Tile olderTile = null;
185
        for (Iterator<Tile> iterator = recentAccededTiles.values().iterator(); iterator.hasNext();) {
186
            Tile tile = (Tile) iterator.next();
187
            if (olderTile == null || tile.getLastAccess() < olderTile.getLastAccess()) {
188
                olderTile = tile;
189
            }
190
        }
191
        if (olderTile != null) {
192
            recentAccededTiles.remove(olderTile.getKey());
193
            DisposeUtils.dispose(olderTile);
194
        }
195
    }
196

  
197
    /* (non-Javadoc)
198
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getColorInterpretation()
199
     */
200
    @Override
201
    public Object getColorInterpretation() throws DynMethodException, ValidateDataParametersException,
202
        CreateEnvelopeException, BufferException, DataException, CloneNotSupportedException {
203
        if (this.colorInterpretation == null) {
204
            fillStoreInfo();
205
        }
206
        return this.colorInterpretation;
207
    }
208

  
209
    /* (non-Javadoc)
210
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getColorTable()
211
     */
212
    @Override
213
    public Object getColorTable() throws DynMethodException, ValidateDataParametersException, CreateEnvelopeException,
214
        BufferException, DataException, CloneNotSupportedException {
215
        if (this.colorTable == null) {
216
            fillStoreInfo();
217
        }
218
        return this.colorTable;
219
    }
220

  
221
    /* (non-Javadoc)
222
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getLegend()
223
     */
224
    @Override
225
    public Object getLegend() throws DynMethodException, ValidateDataParametersException, CreateEnvelopeException,
226
        BufferException, DataException, CloneNotSupportedException {
227
        if (this.legend == null) {
228
            fillStoreInfo();
229
        }
230
        return this.legend;
231
    }
232

  
233
    /**
234
     *
235
     */
236
    public void forgetCache(){
237
        this.recentAccededTiles.clear();
238
    }
239

  
240

  
241
    protected class Tile extends AbstractDisposable {
242

  
243
        org.gvsig.raster.lib.buffer.api.Buffer buffer;
244
        long lastAccess;
245
        String key;
246

  
247
        public Tile(org.gvsig.raster.lib.buffer.api.Buffer buffer, String key) {
248
            logger
249
                .info("CONSTRUCTOR hashCode = " + this.hashCode() + " className = " + this.getClass().getSimpleName());
250
            ToolsLocator.getDisposableManager().bind(buffer);
251
            this.buffer = buffer;
252
            this.key = key;
253
            lastAccess = System.currentTimeMillis();
254
        }
255

  
256
        public String getKey() {
257
            return key;
258
        }
259

  
260
        public org.gvsig.raster.lib.buffer.api.Buffer getBuffer() {
261
            lastAccess = System.currentTimeMillis();
262
            return buffer;
263
        }
264

  
265
        public long getLastAccess() {
266
            return lastAccess;
267
        }
268

  
269
        @Override
270
        protected void finalize() throws Throwable {
271
            super.finalize();
272
            logger.info("CLEANED key " + this.key + " hashCode = " + this.hashCode());
273
        }
274

  
275
        @Override
276
        protected void doDispose() throws BaseException {
277
            DisposeUtils.dispose(buffer);
278
            buffer = null;
279
        }
280
    }
281
}
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/MemoryTileStructImage.java
56 56
 * @author dmartinezizquierdo
57 57
 *
58 58
 */
59
public class MemoryTileStructImage extends AbstractTileStructImage {
59
public class MemoryTileStructImage extends AbstractTileCacheStructImage {
60 60

  
61 61
    private static final Logger logger = LoggerFactory.getLogger(MemoryTileStructImage.class);
62 62
    private static final int MAX_RECENT_ACCEDED_TILES_NUMBER = 50;
......
197 197
        }
198 198
        return this.tileStruct;
199 199
    }
200

  
200 201
}
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/MemoryTileCacheStoreProvider.java
91 91

  
92 92
    private final SimpleTaskStatus taskStatus;
93 93

  
94
    private TileStructImage tileStructImage = null;
94
    private TileCacheStructImage tileStructImage = null;
95 95

  
96 96
    private Envelope envelope = null;
97 97
    private IProjection projection = null;
......
331 331

  
332 332
    @Override
333 333
    public void forgetCache() {
334
        // Do nothing
334
        this.tileStructImage.forgetCache();
335 335
    }
336 336

  
337 337
}
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/FileTileCacheStructImage.java
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.io.IOException;
27
import java.util.ArrayList;
28
import java.util.HashMap;
29
import java.util.Iterator;
30
import java.util.List;
31
import java.util.Map;
32
import java.util.Map.Entry;
33
import java.util.Set;
34
import java.util.TreeMap;
35

  
36
import javax.xml.parsers.DocumentBuilder;
37
import javax.xml.parsers.DocumentBuilderFactory;
38
import javax.xml.parsers.ParserConfigurationException;
39
import javax.xml.transform.OutputKeys;
40
import javax.xml.transform.Transformer;
41
import javax.xml.transform.TransformerException;
42
import javax.xml.transform.TransformerFactory;
43
import javax.xml.transform.dom.DOMSource;
44
import javax.xml.transform.stream.StreamResult;
45

  
46
import org.apache.commons.io.FileUtils;
47
import org.apache.commons.io.FilenameUtils;
48
import org.apache.commons.lang3.StringUtils;
49
import org.cresques.cts.IProjection;
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52
import org.w3c.dom.Attr;
53
import org.w3c.dom.Document;
54
import org.w3c.dom.Element;
55
import org.w3c.dom.NamedNodeMap;
56
import org.w3c.dom.Node;
57
import org.w3c.dom.NodeList;
58

  
59
import org.gvsig.fmap.dal.DALFileLocator;
60
import org.gvsig.fmap.dal.DataServerExplorer;
61
import org.gvsig.fmap.dal.DataServerExplorerParameters;
62
import org.gvsig.fmap.dal.DataStore;
63
import org.gvsig.fmap.dal.DataStoreProviderFactory;
64
import org.gvsig.fmap.dal.exception.DataException;
65
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
66
import org.gvsig.fmap.dal.raster.api.RasterQuery;
67
import org.gvsig.fmap.dal.raster.api.RasterSet;
68
import org.gvsig.fmap.dal.raster.api.RasterStore;
69
import org.gvsig.fmap.dal.raster.spi.NewRasterStoreParameters;
70
import org.gvsig.fmap.dal.raster.spi.RasterStoreProvider;
71
import org.gvsig.fmap.dal.raster.spi.TiledRasterStoreProvider;
72
import org.gvsig.fmap.dal.serverexplorer.filesystem.spi.FilesystemServerExplorerManager;
73
import org.gvsig.fmap.dal.serverexplorer.filesystem.spi.FilesystemServerExplorerProviderFactory;
74
import org.gvsig.fmap.dal.spi.DALSPILocator;
75
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
76
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
77
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
78
import org.gvsig.fmap.geom.GeometryLocator;
79
import org.gvsig.fmap.geom.GeometryManager;
80
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
81
import org.gvsig.fmap.geom.primitive.Envelope;
82
import org.gvsig.raster.lib.buffer.api.Band;
83
import org.gvsig.raster.lib.buffer.api.Buffer;
84
import org.gvsig.raster.lib.buffer.api.BufferLocator;
85
import org.gvsig.raster.lib.buffer.api.BufferManager;
86
import org.gvsig.raster.lib.buffer.api.TileStruct;
87
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
88
import org.gvsig.raster.lib.buffer.spi.DefaultTileStruct;
89
import org.gvsig.tools.ToolsLocator;
90
import org.gvsig.tools.dispose.Disposable;
91
import org.gvsig.tools.dispose.DisposeUtils;
92
import org.gvsig.tools.dynobject.DynObject;
93
import org.gvsig.tools.exception.BaseException;
94
import org.gvsig.tools.extensionpoint.ExtensionPoint.Extension;
95

  
96
/**
97
 * Represents a tiled image
98
 *
99
 * @author dmartinezizquierdo
100
 *
101
 */
102
public class FileTileCacheStructImage extends AbstractTileCacheStructImage {
103

  
104
    private static final Logger logger = LoggerFactory.getLogger(FileTileCacheStructImage.class);
105
    private static final int MAX_RECENT_ACCEDED_TILES_NUMBER = 50;
106

  
107
    private FilesystemServerExplorerProviderFactory factory;
108
    private String extension;
109
    private File tilesFolder;
110

  
111
    private IProjection crs;
112

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

  
125
        // FIXME
126
        File tilePropertiesFile = new File(folder, "tileCacheStruct.xml");
127
        if (!tilePropertiesFile.exists()) {
128
            createTileCacheStructXMLFile(folder);
129
        }
130

  
131
        TreeMap<Integer, Double> pixelSizePerZoomLevel = new TreeMap<Integer, Double>();
132
        recentAccededTiles = new HashMap<String, Tile>();
133

  
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
                    tileStruct.setRowsPerTile(Integer.valueOf(tileSizeAttributes.getNamedItem("rows").getNodeValue()));
156
                    tileStruct.setColumnsPerTile(Integer.valueOf(tileSizeAttributes.getNamedItem("columns").getNodeValue()));
157

  
158
                    NodeList elementsByTagName = eElement.getElementsByTagName("format");
159
                    tileStruct.setProviderName(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
                            tileStruct.setEnvelope(geoManager.createEnvelope(minX, minY, maxX, maxY, SUBTYPES.GEOM2D));                        }
174
                    }
175

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

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

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

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

  
205
                        pixelSizePerZoomLevel.put(zoomLevel, pixelSize);
206

  
207
                    }
208
                    this.tileStruct.setPixelSizePerZoomLevel(pixelSizePerZoomLevel);
209
                }
210
            }
211
        } catch (Exception e) {
212
            throw new RuntimeException();
213
        }
214
    }
215

  
216
    /* (non-Javadoc)
217
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#fetchTile(int, int, int, int)
218
     */
219
    @Override
220
    public Band fetchTile(int bandNumber, int zoomLevel, int structRow, int structCol) throws CreateEnvelopeException,
221
        ValidateDataParametersException, CloneNotSupportedException {
222

  
223
        BufferManager bufferManager = BufferLocator.getBufferManager();
224

  
225
        String keyTile = composeKeyForRecentTiles(zoomLevel, structRow, structCol);
226
        Tile tile = recentAccededTiles.get(keyTile);
227

  
228
        if (tile != null) {
229
            // Devolver la banda del buffer del tile
230
            return tile.getBuffer().getBand(bandNumber);
231
        } else {
232
            // Cargar un tile nuevo
233
            Buffer rasterSet = null;
234
            RasterStore tileStore = null;
235
            RasterSet tileStoreRasterSet = null;
236
            try {
237
                tileStore = createTileStore(zoomLevel, structRow, structCol);
238
                tileStoreRasterSet = tileStore.getRasterSet();
239
                rasterSet = bufferManager.createBuffer(tileStoreRasterSet, false);
240

  
241
                if (recentAccededTiles.size() >= MAX_RECENT_ACCEDED_TILES_NUMBER) {
242
                    removeOlderTile();
243
                }
244
                recentAccededTiles.put(keyTile, new Tile(rasterSet, keyTile));
245

  
246
                Band band = rasterSet.getBand(bandNumber);
247
                ToolsLocator.getDisposableManager().bind(band);
248
                return band;
249
            } catch (DataException | BufferException e) {
250
                logger.warn("Can't fetch tile: zoomLevel = " + zoomLevel + ", tileRow = " + structRow
251
                    + ", tileColumn = " + structCol + ", band = " + bandNumber + ".", e);
252
                return null;
253
            } finally {
254
                DisposeUtils.dispose(tileStore);
255
                tileStore = null;
256
                DisposeUtils.dispose(tileStoreRasterSet);
257
                tileStoreRasterSet = null;
258
                DisposeUtils.dispose(rasterSet);
259
                rasterSet = null;
260
            }
261
        }
262
    }
263

  
264
    private RasterStore createTileStore(int zoomLevel, int structRow, int structCol)
265
        throws ValidateDataParametersException, CreateEnvelopeException, BufferException, DataException,
266
        CloneNotSupportedException {
267

  
268
        File tileFile = null;
269
        File zoomFolder = new File(tilesFolder, String.valueOf(zoomLevel));
270
        if (!zoomFolder.exists()) {
271
            zoomFolder.mkdirs();
272
        }
273
        File firstColumnFolder = new File(zoomFolder, String.valueOf(structCol));
274
        if (!firstColumnFolder.exists()) {
275
            tileFile = requestTileFile(zoomLevel, structRow, structCol);
276
            this.extension = FilenameUtils.getExtension(tileFile.getAbsolutePath());
277
        }
278
        String rowBaseName = String.valueOf(structRow);
279
        if (this.extension == null) {
280
            File[] providerAcceptedFiles = firstColumnFolder.listFiles(factory);
281
            for (int i = 0; i < providerAcceptedFiles.length; i++) {
282
                File providerAcceptedFile = providerAcceptedFiles[i];
283
                if (FilenameUtils.getBaseName(providerAcceptedFile.getAbsolutePath()).equalsIgnoreCase(rowBaseName)) {
284
                    tileFile = providerAcceptedFile;
285
                }
286
            }
287
            if (tileFile == null || !tileFile.exists()) {
288
                tileFile = requestTileFile(zoomLevel, structRow, structCol);
289
            }
290
            this.extension = FilenameUtils.getExtension(tileFile.getAbsolutePath());
291
        } else {
292
            if (tileFile == null) {
293
                tileFile =
294
                    new File(firstColumnFolder.getAbsolutePath() + File.separatorChar + rowBaseName + "."
295
                        + this.extension);
296
            }
297
        }
298
        if (!tileFile.exists()) {
299
            tileFile = requestTileFile(zoomLevel, structRow, structCol);
300
        }
301
        RasterStore tileStore = null;
302
        DataManagerProviderServices manager = DALSPILocator.getDataManagerProviderServices();
303
        DataStoreProviderFactory providerFactory = manager.getStoreProviderFactory(this.tileStruct.getProviderName());
304

  
305
        DynObject params = providerFactory.createParameters();
306
        if (params.getDynClass().getDynField("file") != null) {
307
            params.setDynValue("file", tileFile);
308
        }
309
        if (params.getDynClass().getDynField("crs") != null) {
310
            params.setDynValue("crs", this.crs);
311
        }
312

  
313
        tileStore = (RasterStore) manager.openStore(this.tileStruct.getProviderName(), params);
314
        return tileStore;
315
    }
316

  
317
    private File requestTileFile(int zoomLevel, int structRow, int structCol) throws CreateEnvelopeException,
318
        CloneNotSupportedException, BufferException, ValidateDataParametersException, DataException {
319

  
320
        RasterQuery rasterQuery = (RasterQuery) this.query.clone();
321

  
322
        Double pixelSize = this.tileStruct.getPixelSizePerZoomLevel().get(zoomLevel);
323
        rasterQuery.setPixelSize(pixelSize);
324

  
325
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
326

  
327
        Envelope structExtent = this.tileStruct.getEnvelope();
328
        int rowsPerTile = this.tileStruct.getRowsPerTile();
329
        int columnsPerTile = this.tileStruct.getColumnsPerTile();
330
        double minX = structExtent.getMinimum(DIMENSIONS.X) + structCol * (pixelSize * columnsPerTile);
331
        double minY = structExtent.getMaximum(DIMENSIONS.Y) - ((structRow + 1) * (pixelSize * rowsPerTile));
332
        double maxX = minX + pixelSize * columnsPerTile;
333
        double maxY = minY + pixelSize * rowsPerTile;
334
        Envelope envelope = geomManager.createEnvelope(minX, minY, maxX, maxY, SUBTYPES.GEOM2D);
335

  
336
        Buffer buffer = null;
337
        Buffer clippedBuffer = null;
338
        Buffer interpolatedBuffer = null;
339
        File destFile = null;
340

  
341
        try {
342
            buffer = innerProvider.createBuffer(rasterQuery);
343
            clippedBuffer = buffer.clip(envelope);
344
            interpolatedBuffer =
345
                clippedBuffer.createInterpolated(
346
                    (int) (Math.round(clippedBuffer.getPixelSizeY() * clippedBuffer.getRows() / pixelSize)),
347
                    (int) (Math.round(clippedBuffer.getPixelSizeX() * clippedBuffer.getColumns() / pixelSize)),
348
                    Buffer.INTERPOLATION_NearestNeighbour, null);
349

  
350
            String providerName = "GTiff";
351
            String extension = "tif";
352

  
353
            DataManagerProviderServices manager = DALSPILocator.getDataManagerProviderServices();
354
            DataServerExplorerParameters eparams;
355
            eparams = manager.createServerExplorerParameters("FilesystemExplorer");
356

  
357
            StringBuilder builder = new StringBuilder();
358
            builder.append(tilesFolder);
359
            builder.append(File.separator);
360
            builder.append(zoomLevel);
361
            builder.append(File.separator);
362
            builder.append(structCol);
363
            builder.append(File.separator);
364
            builder.append(structRow);
365
            builder.append(".");
366
            builder.append(extension);
367
            String path = builder.toString();
368
            destFile = new File(path);
369
            File parent = destFile.getParentFile();
370
            if (!parent.exists()) {
371
                parent.mkdirs();
372
            }
373
            eparams.setDynValue("initialpath", path);
374
            DataServerExplorer serverExplorer = manager.createServerExplorer(eparams);
375

  
376
            NewRasterStoreParameters params = (NewRasterStoreParameters) serverExplorer.getAddParameters(providerName);
377
            params.setDynValue("file", destFile);
378

  
379
            params.setDynValue("compress", "NONE");
380
            params.setDynValue("tfw", false);
381

  
382
            // FIXME: Ver de coger estos dos valores del inner provider para que
383
            // los tiles sean homog?neos con el raster original
384
            int bands = innerProvider.getBands();
385
            switch (bands) {
386
            case 3:
387
                params.setDynValue("photometric", "RGB");
388
                break;
389
            case 4:
390
                params.setDynValue("photometric", "RGB");
391
                params.setDynValue("alpha", "NON-PREMULTIPLIED");
392
                break;
393
            default:
394
                params.setDynValue("photometric", "MIN_IS_BLACK");
395
                break;
396
            }
397

  
398
            params.setBuffer(interpolatedBuffer);
399
            serverExplorer.add(providerName, params, true);
400
        } finally {
401
            DisposeUtils.dispose(buffer);
402
            DisposeUtils.dispose(clippedBuffer);
403
            DisposeUtils.dispose(interpolatedBuffer);
404
        }
405

  
406
        return destFile;
407
    }
408

  
409
    @Override
410
    protected void doDispose() throws BaseException {
411
        if (recentAccededTiles != null) {
412
            Set<Entry<String, Tile>> entrySet = recentAccededTiles.entrySet();
413
            for (Iterator<Entry<String, Tile>> iterator = entrySet.iterator(); iterator.hasNext();) {
414
                Entry<String, Tile> entry = (Entry<String, Tile>) iterator.next();
415
                DisposeUtils.dispose(entry.getValue());
416
            }
417
            recentAccededTiles.clear();
418
        }
419
        DisposeUtils.dispose(innerProvider);
420
        innerProvider = null;
421
        DisposeUtils.dispose((Disposable) tileStruct);
422
        tileStruct = null;
423

  
424
        query = null;
425
        factory = null;
426
        crs = null;
427
        colorInterpretation = null;
428
        legend = null;
429
        colorTable = null;
430
    }
431

  
432
    private void createTileCacheStructXMLFile(File folder) {
433

  
434
        TileStruct tileStructProvider = null;
435

  
436
        if (innerProvider != null && innerProvider instanceof TiledRasterStoreProvider) {
437
            tileStructProvider = ((TiledRasterStoreProvider) innerProvider).getTileStruct();
438
        }
439

  
440
        int tileSizeX = TileCacheLibrary.DEFAULT_TILEWIDTH;
441
        if(tileStructProvider!=null && tileStructProvider.getColumnsPerTile()!=0){
442
            tileSizeX = tileStructProvider.getColumnsPerTile();
443
        }
444

  
445
        int tileSizeY = TileCacheLibrary.DEFAULT_TILEHEIGHT;
446
        if(tileStructProvider!=null && tileStructProvider.getRowsPerTile()!=0){
447
            tileSizeY = tileStructProvider.getRowsPerTile();
448
        }
449

  
450
        File file = new File(folder, "tileCacheStruct.xml");
451

  
452
        if (!file.exists()) {
453
            Buffer auxBuffer = null;
454
            try {
455
                DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
456
                DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
457

  
458
                // root elements
459
                Document doc = (Document) docBuilder.newDocument();
460
                Element rootElement = doc.createElement("TileCacheStruct");
461
                doc.appendChild(rootElement);
462

  
463
                // tileSize
464
                Element tileSize = doc.createElement("tileSize");
465
                rootElement.appendChild(tileSize);
466

  
467
                // tileSize Rows
468
                Attr rows = doc.createAttribute("rows");
469
                rows.setValue(String.valueOf(tileSizeY));
470
                tileSize.setAttributeNode(rows);
471

  
472
                // tileSize Columns
473
                Attr columns = doc.createAttribute("columns");
474
                columns.setValue(String.valueOf(tileSizeX));
475
                tileSize.setAttributeNode(columns);
476

  
477
                // format
478
                Element format = doc.createElement("format");
479
                if(tileStructProvider==null || StringUtils.isEmpty(tileStructProvider.getProviderName())){
480
                    format.setTextContent("GTiff");
481
                }
482
                rootElement.appendChild(format);
483

  
484
                // structExtent
485
                Element structExtent = doc.createElement("structExtent");
486
                rootElement.appendChild(structExtent);
487

  
488
                Envelope envelope = (Envelope) innerProvider.getDynValue(DataStore.METADATA_ENVELOPE);
489

  
490
                // structExtent minX
491
                Element minX = doc.createElement("minX");
492
                minX.setTextContent(String.valueOf(envelope.getMinimum(DIMENSIONS.X)));
493
                structExtent.appendChild(minX);
494

  
495
                // structExtent minY
496
                Element minY = doc.createElement("minY");
497
                minY.setTextContent(String.valueOf(envelope.getMinimum(DIMENSIONS.Y)));
498
                structExtent.appendChild(minY);
499

  
500
                // structExtent maxX
501
                Element maxX = doc.createElement("maxX");
502
                maxX.setTextContent(String.valueOf(envelope.getMaximum(DIMENSIONS.X)));
503
                structExtent.appendChild(maxX);
504

  
505
                // structExtent maxY
506
                Element maxY = doc.createElement("maxY");
507
                maxY.setTextContent(String.valueOf(envelope.getMaximum(DIMENSIONS.Y)));
508
                structExtent.appendChild(maxY);
509

  
510
                Element levels = doc.createElement("levels");
511
                rootElement.appendChild(levels);
512

  
513
                List<Double> pixelSizes = new ArrayList<Double>();
514
                Map<Integer, Double> zoomLevels = new HashMap<Integer, Double>();
515

  
516
                if (tileStructProvider==null || tileStructProvider.getPixelSizePerZoomLevel() == null) {
517
                    // FIXME: ?alguna otra forma de obtener el pixelSize del store completo?
518
                    auxBuffer = innerProvider.createBuffer(null);
519
                    int completeRows = auxBuffer.getRows();
520
                    int completeColumns = auxBuffer.getColumns();
521
                    double completePixelSizeX = auxBuffer.getPixelSizeX();
522
                    double completePixelSizeY = auxBuffer.getPixelSizeY();
523

  
524
                    int maximumLength = completeColumns;
525
                    int tileMaximumLength = tileSizeX;
526
                    double maximumPixelSize = completePixelSizeX;
527

  
528
                    if (completeRows * tileSizeY > completeColumns * tileSizeX) {
529
                        maximumLength = completeRows;
530
                        tileMaximumLength = tileSizeY;
531
                        maximumPixelSize = completePixelSizeY;
532
                    }
533

  
534
                    double pixelSize = maximumPixelSize;
535
                    while (maximumLength * maximumPixelSize / pixelSize > tileMaximumLength) {
536
                        pixelSizes.add(pixelSize);
537
                        pixelSize = pixelSize * 2;
538
                    }
539
                    pixelSizes.add(pixelSize);
540
                    int i = 0;
541
                    for (int zoomLevel = pixelSizes.size() - 1; zoomLevel >= 0; zoomLevel--) {
542
                        zoomLevels.put(i, pixelSizes.get(zoomLevel));
543
                        appendZoomLevel(doc, levels, i, pixelSizes.get(zoomLevel));
544
                        i++;
545
                    }
546
                } else {
547
                    zoomLevels = tileStructProvider.getPixelSizePerZoomLevel();
548
                }
549

  
550
                for (Entry<Integer, Double> entry : zoomLevels.entrySet()) {
551
                    appendZoomLevel(doc, levels, entry.getKey(), entry.getValue());
552
                }
553

  
554
                // write the content into xml file
555

  
556
                DOMSource source = new DOMSource(doc);
557
                File parent = file.getParentFile();
558
                if (!parent.exists()) {
559
                    parent.mkdirs();
560
                }
561
                file.createNewFile();
562
                StreamResult result = new StreamResult(file.toURI().getPath());
563

  
564
                TransformerFactory transformerFactory = TransformerFactory.newInstance();
565
                Transformer transformer = transformerFactory.newTransformer();
566
                transformer.setOutputProperty(OutputKeys.INDENT, "yes");
567
                transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
568
                transformer.transform(source, result);
569

  
570
            } catch (ParserConfigurationException | TransformerException | IOException | BufferException e) {
571
                logger.warn("Can't create tileCacheStruct.xml file", e);
572
            } finally {
573
                DisposeUtils.dispose(auxBuffer);
574
                auxBuffer = null;
575
            }
576
        }
577
    }
578

  
579
    /**
580
     * @param doc
581
     * @param rootElement
582
     * @param levels
583
     * @param zoomLevel
584
     * @param pixelSize
585
     */
586
    private void appendZoomLevel(Document doc, Element levels, int zoomLevel, double pixelSize) {
587
        Element level = doc.createElement("level");
588
        levels.appendChild(level);
589

  
590
        // level zoomLevel
591
        Attr index = doc.createAttribute("index");
592
        index.setValue(String.valueOf(zoomLevel));
593
        level.setAttributeNode(index);
594

  
595
        // level pixelSize
596
        Attr pxSize = doc.createAttribute("pixelSize");
597
        pxSize.setValue(String.valueOf(pixelSize));
598
        level.setAttributeNode(pxSize);
599
    }
600

  
601
    /* (non-Javadoc)
602
     * @see org.gvsig.raster.tilecache.provider.ITileStructImage#getTileStruct()
603
     */
604
    @Override
605
    public TileStruct getTileStruct() {
606
        if(this.tileStruct==null){
607
            this.tileStruct = new DefaultTileStruct();
608
        }
609
        return this.tileStruct;
610
    }
611

  
612
    public void forgetCache() {
613
        super.forgetCache();
614
        if(tilesFolder.exists() && tilesFolder.isDirectory()){
615
            File[] files = tilesFolder.listFiles();
616
            for(int i=0; i<files.length; i++){
617
                try {
618
                    FileUtils.forceDelete(files[i]);
619
                } catch (IOException e) {
620
                    logger.warn("Can't delete the file "+files[i].getAbsolutePath(), e);
621
                }
622
            }
623
        }
624
    }
625
}
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/TileCacheStoreProvider.java
68 68
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
69 69
import org.gvsig.tools.ToolsLocator;
70 70
import org.gvsig.tools.dispose.DisposeUtils;
71
import org.gvsig.tools.dispose.impl.AbstractDisposable;
71 72
import org.gvsig.tools.dynobject.DynObject;
72 73
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
73 74
import org.gvsig.tools.exception.BaseException;
......
93 94
    private ResourceProvider resource;
94 95
    private final SimpleTaskStatus taskStatus;
95 96

  
96
    private TileCacheStructImage tileCacheStructImage = null;
97
    private TileCacheStructImage fileTileCacheStructImage = null;
97 98

  
98 99
    private Envelope envelope = null;
99 100
    private IProjection projection = null;
......
184 185
        bandDataTypes = new int[bandsNumber];
185 186
        bandNoData = new NoData[bandsNumber];
186 187

  
187
        int zoomLevel = tileCacheStructImage.getZoomLvlForPixelSize(rasterQuery.getPixelSize());
188
        int zoomLevel = fileTileCacheStructImage.getZoomLvlForPixelSize(rasterQuery.getPixelSize());
188 189
        List<PageManager> pageManagersInZoom;
189 190
        int[] tileStructDataTypes;
190 191
        try {
191 192
            pageManagersInZoom = getPageManagersInZoom(zoomLevel);
192
            tileStructDataTypes = tileCacheStructImage.getDataTypes();
193
            tileStructDataTypes = fileTileCacheStructImage.getDataTypes();
193 194
        } catch (ValidateDataParametersException | CreateEnvelopeException | DataException | CloneNotSupportedException e) {
194 195
            throw new BufferException(e);
195 196
        }
196 197
        try {
197
            for(int i = 0; i<tileCacheStructImage.getBandNumber(); i++){
198
            for(int i = 0; i<fileTileCacheStructImage.getBandNumber(); i++){
198 199
                bandDataTypes[i] = tileStructDataTypes[i];
199 200
                bandNoData[i] = null;
200 201
                pageManagers.add(pageManagersInZoom.get(i));
......
203 204
            throw new BufferException(e);
204 205
        }
205 206

  
206
        envelope = tileCacheStructImage.getEnvelope();
207
        envelope = fileTileCacheStructImage.getEnvelope();
207 208
        Buffer buffer =
208
            bufferManager.createBuffer(tileCacheStructImage.getRows(zoomLevel), tileCacheStructImage.getColumns(zoomLevel),
209
            bufferManager.createBuffer(fileTileCacheStructImage.getRows(zoomLevel), fileTileCacheStructImage.getColumns(zoomLevel),
209 210
                bandDataTypes, bandNoData, projection, envelope, pageManagers);
210 211

  
211 212
        return buffer;
......
215 216
        List<PageManager> pageManagersInZoom = this.pageManagersPerZoomLevel.get(zoomLevel);
216 217
        if (pageManagersInZoom == null) {
217 218
            pageManagersInZoom = new ArrayList<PageManager>();
218
            for (int i = 0; i < tileCacheStructImage.getBandNumber(); i++) {
219
                pageManagersInZoom.add(new TileCacheBandPageManager(tileCacheStructImage, zoomLevel, i));
219
            for (int i = 0; i < fileTileCacheStructImage.getBandNumber(); i++) {
220
                pageManagersInZoom.add(new TileCacheBandPageManager(fileTileCacheStructImage, zoomLevel, i));
220 221
            }
221 222
            this.pageManagersPerZoomLevel.put(zoomLevel, pageManagersInZoom);
222 223
        }
......
235 236
    }
236 237

  
237 238
    public void open() throws OpenException {
238
        if (this.tileCacheStructImage != null) {
239
        if (this.fileTileCacheStructImage != null) {
239 240
            return;
240 241
        }
241 242
    }
......
255 256

  
256 257
    @Override
257 258
    public void close() throws CloseException {
258
        this.tileCacheStructImage = null;
259
        this.fileTileCacheStructImage = null;
259 260
    }
260 261

  
261 262
    @Override
......
312 313
    protected void doDispose() throws BaseException {
313 314
        super.doDispose();
314 315
        resource.removeConsumer(this);
315
        if(this.tileCacheStructImage!=null){
316
            DisposeUtils.dispose(tileCacheStructImage);
317
            this.tileCacheStructImage = null;
316
        if(this.fileTileCacheStructImage!=null){
317
            DisposeUtils.dispose((AbstractDisposable)fileTileCacheStructImage);
318
            this.fileTileCacheStructImage = null;
318 319
        }
319 320
    }
320 321

  
......
322 323
     * @return TileStructImage
323 324
     */
324 325
    public TileStructImage getTileStructImage() {
325
        return tileCacheStructImage;
326
        return fileTileCacheStructImage;
326 327
    }
327 328

  
328 329
    @Override
......
331 332
        this.innerProvider = provider;
332 333
        pageManagersPerZoomLevel = new HashMap<Integer, List<PageManager>>();
333 334

  
334
        this.tileCacheStructImage =
335
            new TileCacheStructImage(((FileResource)resource).getFile(), crs, provider, query);
335
        this.fileTileCacheStructImage =
336
            new FileTileCacheStructImage(((FileResource)resource).getFile(), crs, provider, query);
336 337
    }
337 338

  
338 339
    @Override
......
342 343

  
343 344
    @Override
344 345
    public void forgetCache() {
345
        tileCacheStructImage.forgetCache();
346
        fileTileCacheStructImage.forgetCache();
346 347

  
347 348
    }
348 349
}
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/TileCacheStructImage.java
22 22
 */
23 23
package org.gvsig.raster.tilecache.provider;
24 24

  
25
import java.io.File;
26
import java.io.IOException;
27
import java.util.ArrayList;
28
import java.util.HashMap;
29
import java.util.Iterator;
30
import java.util.List;
31
import java.util.Map;
32
import java.util.Map.Entry;
33
import java.util.Set;
34
import java.util.TreeMap;
35 25

  
36
import javax.xml.parsers.DocumentBuilder;
37
import javax.xml.parsers.DocumentBuilderFactory;
38
import javax.xml.parsers.ParserConfigurationException;
39
import javax.xml.transform.OutputKeys;
40
import javax.xml.transform.Transformer;
41
import javax.xml.transform.TransformerException;
42
import javax.xml.transform.TransformerFactory;
43
import javax.xml.transform.dom.DOMSource;
44
import javax.xml.transform.stream.StreamResult;
45

  
46
import org.apache.commons.io.FileUtils;
47
import org.apache.commons.io.FilenameUtils;
48
import org.apache.commons.lang3.StringUtils;
49
import org.cresques.cts.IProjection;
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52
import org.w3c.dom.Attr;
53
import org.w3c.dom.Document;
54
import org.w3c.dom.Element;
55
import org.w3c.dom.NamedNodeMap;
56
import org.w3c.dom.Node;
57
import org.w3c.dom.NodeList;
58

  
59
import org.gvsig.fmap.dal.DALFileLocator;
60
import org.gvsig.fmap.dal.DataServerExplorer;
61
import org.gvsig.fmap.dal.DataServerExplorerParameters;
62
import org.gvsig.fmap.dal.DataStore;
63
import org.gvsig.fmap.dal.DataStoreProviderFactory;
64
import org.gvsig.fmap.dal.exception.DataException;
65
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
66
import org.gvsig.fmap.dal.raster.api.RasterQuery;
67
import org.gvsig.fmap.dal.raster.api.RasterSet;
68
import org.gvsig.fmap.dal.raster.api.RasterStore;
69
import org.gvsig.fmap.dal.raster.spi.NewRasterStoreParameters;
70
import org.gvsig.fmap.dal.raster.spi.RasterStoreProvider;
71
import org.gvsig.fmap.dal.raster.spi.TiledRasterStoreProvider;
72
import org.gvsig.fmap.dal.serverexplorer.filesystem.spi.FilesystemServerExplorerManager;
73
import org.gvsig.fmap.dal.serverexplorer.filesystem.spi.FilesystemServerExplorerProviderFactory;
74
import org.gvsig.fmap.dal.spi.DALSPILocator;
75
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
76
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
77
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
78
import org.gvsig.fmap.geom.GeometryLocator;
79
import org.gvsig.fmap.geom.GeometryManager;
80
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
81
import org.gvsig.fmap.geom.primitive.Envelope;
82
import org.gvsig.raster.lib.buffer.api.Band;
83
import org.gvsig.raster.lib.buffer.api.Buffer;
84
import org.gvsig.raster.lib.buffer.api.BufferLocator;
85
import org.gvsig.raster.lib.buffer.api.BufferManager;
86
import org.gvsig.raster.lib.buffer.api.TileStruct;
87
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
88
import org.gvsig.raster.lib.buffer.spi.DefaultTileStruct;
89
import org.gvsig.raster.tilecache.provider.AbstractTileStructImage.Tile;
90
import org.gvsig.tools.ToolsLocator;
91
import org.gvsig.tools.dispose.Disposable;
92
import org.gvsig.tools.dispose.DisposeUtils;
93
import org.gvsig.tools.dynobject.DynObject;
94
import org.gvsig.tools.exception.BaseException;
95
import org.gvsig.tools.extensionpoint.ExtensionPoint.Extension;
96

  
97 26
/**
98
 * Represents a tiled image
27
 * @author fdiaz
99 28
 *
100
 * @author dmartinezizquierdo
101
 *
102 29
 */
103
public class TileCacheStructImage extends AbstractTileStructImage {
30
public interface TileCacheStructImage extends TileStructImage {
104 31

  
105
    private static final Logger logger = LoggerFactory.getLogger(TileCacheStructImage.class);
106
    private static final int MAX_RECENT_ACCEDED_TILES_NUMBER = 50;
107

  
108
    private FilesystemServerExplorerProviderFactory factory;
109
    private String extension;
110
    private File tilesFolder;
111
//    private Map<String, Tile> recentAccededTiles;
112

  
113
    private IProjection crs;
114

  
115 32
    /**
116
     * @param folder
117
     * @param crs
118
     * @param innerProvider
119
     * @param query
33
     * Clear previous cache.
120 34
     */
121
    public TileCacheStructImage(File folder, IProjection crs, RasterStoreProvider innerProvider, RasterQuery query) {
122
        super(innerProvider, query);
123
        this.crs = crs;
124
        GeometryManager geoManager = GeometryLocator.getGeometryManager();
125
        getTileStruct();
35
    public void forgetCache();
126 36

  
127
        // FIXME
128
        File tilePropertiesFile = new File(folder, "tileCacheStruct.xml");
129
        if (!tilePropertiesFile.exists()) {
130
            createTileCacheStructXMLFile(folder);
131
        }
132

  
133
        TreeMap<Integer, Double> pixelSizePerZoomLevel = new TreeMap<Integer, Double>();
134
        recentAccededTiles = new HashMap<String, Tile>();
135

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

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

  
148
            NodeList nList = doc.getElementsByTagName("TileCacheStruct");
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff