Statistics
| Revision:

gvsig-raster / org.gvsig.raster.postgis / trunk / org.gvsig.raster.postgis / org.gvsig.raster.postgis.io / src / main / java / org / gvsig / raster / postgis / io / PostGISRasterProvider.java @ 1057

History | View | Annotate | Download (18.1 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22
package org.gvsig.raster.postgis.io;
23

    
24
import java.awt.geom.AffineTransform;
25
import java.util.ArrayList;
26
import java.util.Collections;
27
import java.util.Iterator;
28
import java.util.List;
29

    
30
import org.gvsig.fmap.dal.DALLocator;
31
import org.gvsig.fmap.dal.DataManager;
32
import org.gvsig.fmap.dal.DataStore;
33
import org.gvsig.fmap.dal.coverage.RasterLocator;
34
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
35
import org.gvsig.fmap.dal.coverage.datastruct.BandList;
36
import org.gvsig.fmap.dal.coverage.datastruct.DatasetBand;
37
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
38
import org.gvsig.fmap.dal.coverage.exception.BandNotFoundInListException;
39
import org.gvsig.fmap.dal.coverage.exception.NotSupportedExtensionException;
40
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
41
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
42
import org.gvsig.fmap.dal.coverage.store.parameter.RasterDataParameters;
43
import org.gvsig.fmap.dal.exception.DataException;
44
import org.gvsig.fmap.dal.exception.InitializeException;
45
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
46
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
47
import org.gvsig.fmap.dal.serverexplorer.db.DBServerExplorer;
48
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
49
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
50
import org.gvsig.fmap.dal.store.db.DBStoreParameters;
51
import org.gvsig.metadata.MetadataLocator;
52
import org.gvsig.raster.cache.tile.provider.TileListener;
53
import org.gvsig.raster.gdal.io.GdalDataParameters;
54
import org.gvsig.raster.gdal.io.GdalProvider;
55
import org.gvsig.raster.impl.buffer.DefaultRasterQuery;
56
import org.gvsig.raster.impl.datastruct.BandListImpl;
57
import org.gvsig.raster.impl.datastruct.DatasetBandImpl;
58
import org.gvsig.raster.impl.provider.DefaultRasterProvider;
59
import org.gvsig.raster.impl.store.AbstractRasterDataParameters;
60
import org.gvsig.raster.impl.store.DefaultStoreFactory;
61
import org.gvsig.tools.ToolsLocator;
62
import org.gvsig.tools.extensionpoint.ExtensionPoint;
63
import org.gvsig.tools.extensionpoint.ExtensionPointManager;
64
import org.gvsig.tools.task.Cancellable;
65
import org.gvsig.tools.task.TaskStatus;
66
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
68
/**
69
 * This class represents the data access just for PostGIS raster databases.
70
 * @author Nacho Brodin (nachobrodin@gmail.com)
71
 */
72
public class PostGISRasterProvider extends GdalProvider {
73
        public static String           NAME                     = "PostGIS Raster Store";
74
        public static String           DESCRIPTION              = "PostGIS Raster file";
75
        public static final String     METADATA_DEFINITION_NAME = "PostGISRasterStore";
76
        private static final String    OVERVIEW_PREFIX          = "o_";
77
        
78
        private DBServerExplorer       dbServerExplorer         = null;
79
        private DBStoreParameters      dbParameters             = null;
80
        private ArrayList<Overview>    overviews                = null;
81
        private DataManager            dataManager              = DALLocator.getDataManager();
82
        private DefaultRasterProvider  selectedProvider         = null;
83
        private Overview               mainOverview             = null;
84
        private static Logger          logger                   = LoggerFactory.getLogger(PostGISRasterProvider.class.getName());
85
        
86
        class Overview implements Comparable<Overview> {
87
                public int                         width               = 0;
88
                public int                         height              = 0;
89
                public int                         factor              = 0;
90
                public double                      pxSizeOverview      = 0;
91
                public DefaultRasterProvider       provider            = null;
92
                
93
                public Overview() {
94
                        
95
                }
96
                
97
                public Overview(int f, int w, int h, PostGISRasterDataParameters p) throws NotSupportedExtensionException {
98
                        this.width = w;
99
                        this.height = h;
100
                        this.factor = f;
101
                        if(p != null)
102
                                createProvider(p);
103
                        this.pxSizeOverview = getExtent().width() / (double)w;
104
                }
105
                
106
                public void createProvider(PostGISRasterDataParameters p) throws NotSupportedExtensionException {
107
                        GdalDataParameters gdalParams = new GdalDataParameters();
108
                        gdalParams.setURI(p.getURI());
109
                        try {
110
                                this.provider = new GdalProvider(gdalParams, storeServices);
111
                        } catch (NotSupportedExtensionException e) {
112
                                logger.info("===>" + gdalParams.getURI() + " " + e.getMessage(), e);
113
                        }
114
                        this.width = (int)provider.getWidth();
115
                        this.height = (int)provider.getHeight();
116
                        this.pxSizeOverview = provider.getExtent().width() / (double)this.width;
117
                }
118
                
119
                public int compareTo(Overview o) {
120
                        if(factor < o.factor)
121
                                return -1;
122
                        if(factor > o.factor)
123
                                return 1;
124
                        return 0;
125
                }
126
        }
127
        
128
        public static void register() {
129
                ExtensionPointManager extensionPoints = ToolsLocator.getExtensionPointManager();
130
                ExtensionPoint point = extensionPoints.get("DefaultDriver");
131
                point.append("reader", PostGISRasterProvider.NAME, PostGISRasterProvider.class);
132
                
133
                RasterLocator.getManager().registerFileProvidersTiled(PostGISRasterProvider.class);
134
                
135
                DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
136
                if (dataman != null && !dataman.getStoreProviders().contains(NAME)) {
137
                        dataman.registerStoreProvider(NAME,
138
                                        PostGISRasterProvider.class, PostGISRasterDataParameters.class);
139
                }
140

    
141
                if (!dataman.getExplorerProviders().contains(PostGISRasterProvider.NAME)) {
142
                        dataman.registerExplorerProvider(PostGISRasterServerExplorer.NAME, PostGISRasterServerExplorer.class, PostGISRasterServerExplorerParameters.class);
143
                }
144
                dataman.registerStoreFactory(NAME, DefaultStoreFactory.class);
145
        }
146
        
147
        public PostGISRasterProvider() {
148
                
149
        }
150
        
151
        public PostGISRasterProvider (PostGISRasterDataParameters params,
152
                        DataStoreProviderServices storeServices) throws NotSupportedExtensionException {
153
                super(params, storeServices, ToolsLocator.getDynObjectManager()
154
                                .createDynObject(
155
                                                MetadataLocator.getMetadataManager().getDefinition(
156
                                                                DataStore.METADATA_DEFINITION_NAME)));
157
                init(params, storeServices);
158
        }
159
        
160
        /**
161
         * Creates data base references and loads structures with the information and metadata
162
         * @param params load parameters
163
         * @throws NotSupportedExtensionException
164
         */
165
        public void init (AbstractRasterDataParameters params,
166
                        DataStoreProviderServices storeServices) throws NotSupportedExtensionException {
167
                try {
168
                        setParam(storeServices, params);
169
                        mainOverview = new Overview();
170
                        mainOverview.createProvider((PostGISRasterDataParameters)param);
171
                        mainOverview.factor = 1;
172
                        file = ((GdalProvider)mainOverview.provider).getNative();
173
                        setColorInterpretation(file.getColorInterpretation());
174
                        setColorTable(file.getColorTable());
175
                        noData = file.getNoDataValue();
176
                        wktProjection = file.getProjectionRef();
177
                        //CrsWkt crs = new CrsWkt(wktProjection);
178
                        //IProjection proj = CRSFactory.getCRS("EPSG:23030");
179
                        ownTransformation = file.getOwnTransformation();
180
                        externalTransformation = (AffineTransform)ownTransformation.clone();
181
                        bandCount = file.getRasterCount();
182
                        load();
183
                } catch (Exception e) {
184
                        throw new NotSupportedExtensionException("Gdal library can't be initialized with this PostGIS raster parameters", e);
185
                } 
186

    
187
                //Obtenemos el tipo de dato de gdal y lo convertimos el de RasterBuf
188
                int[] dt = new int[file.getDataType().length];
189
                for (int i = 0; i < dt.length; i++)
190
                        dt[i] = rasterUtil.getRasterBufTypeFromGdalType(file.getDataType()[i]);
191
                setDataType(dt);
192
                
193
                PostGISRasterDataParameters p = (PostGISRasterDataParameters)params;
194
                //Object obj = p.getDynValue(PostGISRasterDataParameters.FIELD_DBPARAMS);
195
                dbParameters = (DBStoreParameters)p.getDynValue(PostGISRasterDataParameters.FIELD_DBPARAMS);
196
                dbServerExplorer = (DBServerExplorer)p.getDynValue(PostGISRasterDataParameters.FIELD_DBEXPLORER);
197
        }
198
        
199
        /*
200
         * (non-Javadoc)
201
         * @see org.gvsig.raster.impl.provider.RasterProvider#getRMFFile()
202
         */
203
        public String getRMFFile() {
204
                if(uri.startsWith("PG:host=")) {
205
                        String uri = getURI().replace("'", "");
206
                        return uri + ".rmf";
207
                } else 
208
                        return fileUtil.getNameWithoutExtension(uri) + ".rmf";
209
        }
210
        
211
        /**
212
         * Reads overviews from database. The overviews in PostGIS raster are loaded 
213
         * in separated tables. The name of those tables is the same that the original table
214
         * with a overview prefix. Now this prefix is "o_X_" where the X is a factor scale.
215
         * 
216
         * For that reason the overview object contains the DataParameter which correspond
217
         * to each table.
218
         * @throws DataException 
219
         * @throws DataException
220
         */
221
        @SuppressWarnings("unchecked")
222
        private void readOverviews() throws DataException  {
223
                if(overviews == null) {
224
                        overviews = new ArrayList<Overview>();
225
                        String mainHost = ((PostGISRasterDataParameters)param).getURI();
226

    
227
                        String mainTable = dbParameters.getTable();
228
                        List parameters = dbServerExplorer.list();
229

    
230
                        int mainFactor = 1; 
231
                                
232
                        if(isOverview(mainTable, mainTable)) {
233
                                mainFactor = getFactor(mainTable);
234
                        }
235
                        overviews.add(mainOverview);
236
                        
237
                        Iterator iter = parameters.iterator();
238
                        while (iter.hasNext()) {
239
                                DBStoreParameters p = (DBStoreParameters) iter.next();
240
                                String tname = p.getTable();
241

    
242
                                try {
243
                                        if(isOverview(mainTable, tname)) {
244
                                                Overview o = new Overview();
245
                                                o.factor = (getFactor(tname) / mainFactor);
246
                                                o.width = (int)(getWidth() / o.factor);
247
                                                o.height = (int)(getHeight() / o.factor);
248
                                                o.pxSizeOverview = getExtent().width() / (double)o.width;
249
                                                o.createProvider(createParameters(mainHost, mainTable, tname));
250
                                                overviews.add(o);
251
                                        }
252
                                } catch (NumberFormatException e) {
253
                                } catch (PostGISRasterCoreException e) {
254
                                } catch (ValidateDataParametersException e) {
255
                                } catch (NotSupportedExtensionException e) {
256
                                }
257
                        }
258
                        Collections.sort(overviews);
259
                }
260
        }
261
        
262
        /**
263
         * Returns true if tname is an overview of mainTable
264
         * @param mainTable
265
         * @param tname
266
         * @return
267
         */
268
        private boolean isOverview(String mainTable, String tname) throws NumberFormatException {
269
                if(mainTable.compareTo(tname) != 0) {
270
                        return ((tname.endsWith(mainTable) && tname.startsWith(OVERVIEW_PREFIX)) ||
271
                                        (tname.startsWith(OVERVIEW_PREFIX) && mainTable.startsWith(OVERVIEW_PREFIX) && getFactor(tname) > getFactor(mainTable)));
272
                }
273
                return false;
274
        }
275
        
276
        /**
277
         * Gets the overview factor number reading the name of the table
278
         * @param tname
279
         * @return
280
         * @throws NumberFormatException
281
         */
282
        private int getFactor(String tname) throws NumberFormatException {
283
                String factor = tname.substring(tname.indexOf('_') + 1);
284
                factor = factor.substring(0, factor.indexOf('_'));
285
                return new Integer(factor);
286
        }
287
        
288
        /**
289
         * Creates the list of parameters
290
         * @param mainHost
291
         * @param mainTable
292
         * @param tableName
293
         * @return
294
         * @throws PostGISRasterCoreException 
295
         * @throws PostGISRasterCoreException
296
         * @throws ProviderNotRegisteredException 
297
         * @throws InitializeException 
298
         * @throws ValidateDataParametersException 
299
         */
300
        @SuppressWarnings("deprecation")
301
        private PostGISRasterDataParameters createParameters(String mainHost, String mainTable, String tableName) throws PostGISRasterCoreException, ValidateDataParametersException, InitializeException, ProviderNotRegisteredException {
302
                String newHost = mainHost.replaceFirst(mainTable, tableName);
303
                
304
                PostGISRasterServerExplorerParameters explorerParams = (PostGISRasterServerExplorerParameters) dataManager.createServerExplorerParameters(PostGISRasterServerExplorer.NAME);
305
                explorerParams.setHost(newHost);
306
                PostGISRasterServerExplorer explorer = (PostGISRasterServerExplorer) dataManager.createServerExplorer(explorerParams);
307
                RasterDataParameters storeParameters = (RasterDataParameters)explorer.getStoreParameters();
308
                storeParameters.setURI(newHost);
309
                return (PostGISRasterDataParameters)storeParameters;
310
        }
311
        
312
        /**
313
         * Selects the right overview. The right overview means the first 
314
         * one with a pixel size lesser or equals than the original. 
315
         * @param pixels
316
         * @param mts
317
         */
318
        private void overviewSelector(int pixels, double mts) {
319
                this.selectedProvider = overviews.get(overviews.size() - 1).provider;
320
                //System.out.println("*************" + overviews.get(overviews.size() - 1).pxSizeOverview + "**************");
321
                double pxSizeRequest = mts / (double)pixels;
322
                for (int i = overviews.size() - 1; i > 0; i--) {
323
                        Overview ovb = overviews.get(i);
324
                        if(pxSizeRequest <= ovb.pxSizeOverview) {
325
                                this.selectedProvider = ovb.provider;
326
                                //System.out.println(ovb.pxSizeOverview);
327
                        }
328
                }
329
                //System.out.println("***************************");
330
        }
331
        
332
        /*
333
         * (non-Javadoc)
334
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(double, double, double, double, int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.raster.cache.tile.provider.TileListener)
335
         */
336
        public void getWindow(Extent ex, int bufWidth, int bufHeight, 
337
                        BandList bandList, TileListener listener, Cancellable status) throws ProcessInterruptedException, RasterDriverException {
338
//                PostGISRasterDataParameters p = (PostGISRasterDataParameters)param;
339
//                Buffer buf = RasterLocator.getManager().createBuffer(getDataType()[0], bufWidth, bufHeight, getBandCount(), true);
340
//                TileCacheManager m = TileCacheLocator.getManager();
341
//                Tile tile = m.createTile(-1, 0, 0);
342
//                
343
//                //Creamos un BandList con todas las bandas del fichero
344
//                BandList bl = new BandListImpl();
345
//                for(int i = 0; i < getBandCount(); i++) {
346
//                        try {
347
//                                DatasetBand band = new DatasetBandImpl(selectedProvider.getURIOfFirstProvider(), i, getDataType()[i], getBandCount());
348
//                                bl.addBand(band, i);
349
//                        } catch(BandNotFoundInListException e) {
350
//                                //No a?adimos la banda
351
//                        }
352
//                }
353
//                
354
//                if(p.getNumberOfBlocks() > 1) {
355
//                        for (int i = 0; i < p.getNumberOfBlocks(); i++) {
356
//                                GdalNative gdal;
357
//                                try {
358
//                                        gdal = new GdalNative(p.getURI() + " column='rast' where='rid = " + i + "'");
359
//                                        gdal.readWindow(buf, bandList, 0, 0, gdal.width, gdal.height, bufWidth, bufHeight);
360
//                                        Extent ext = gdal.getExtentWithoutRot();
361
//                                        tile.setUl(new Point2D.Double(ext.getULX(), ext.getULY()));
362
//                                        tile.setLr(new Point2D.Double(ext.getLRX(), ext.getLRY()));
363
//                                        tile.setData(new Object[]{buf, null, null});
364
//                                        listener.tileReady(tile);
365
//                                } catch (GdalException e) {
366
//                                        throw new RasterDriverException("", e);
367
//                                } catch (IOException e) {
368
//                                        throw new RasterDriverException("", e);
369
//                                } catch (TileGettingException e) {
370
//                                        throw new RasterDriverException("", e);
371
//                                }
372
//                        }
373
//                }
374
                super.getWindow(ex, bufWidth, bufHeight, bandList, listener, status);
375
        }
376

    
377
        /*
378
         * (non-Javadoc)
379
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(org.gvsig.fmap.dal.coverage.datastruct.Extent, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer)
380
         */
381
        public Buffer getWindow(Extent ex, BandList bandList, Buffer rasterBuf, TaskStatus status) 
382
                throws ProcessInterruptedException, RasterDriverException {
383
                return super.getWindow(ex, bandList, rasterBuf, status);
384
        }
385

    
386
        /*
387
         * (non-Javadoc)
388
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(double, double, double, double, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer, boolean)
389
         */
390
        public Buffer getWindow(double ulx, double uly, double w, double h, 
391
                        BandList bandList, Buffer rasterBuf, boolean adjustToExtent, TaskStatus status) throws ProcessInterruptedException, RasterDriverException {
392
                return super.getWindow(ulx, uly, w, h, bandList, rasterBuf, adjustToExtent, status);
393
        }
394

    
395
        /*
396
         * (non-Javadoc)
397
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(double, double, double, double, int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer, boolean)
398
         */
399
        public Buffer getWindow(Extent extent, 
400
                        int bufWidth, int bufHeight, BandList bandList, Buffer rasterBuf, boolean adjustToExtent) throws ProcessInterruptedException, RasterDriverException {
401

    
402
                try {
403
                        readOverviews();
404
                } catch (DataException e) {
405
                        throw new RasterDriverException("Overviews can't be read", e);
406
                }
407

    
408
                overviewSelector(bufWidth, extent.width());
409
                //Creamos un BandList con todas las bandas del fichero
410
                BandList bl = new BandListImpl();
411
                for(int i = 0; i < getBandCount(); i++) {
412
                        try {
413
                                DatasetBand band = new DatasetBandImpl(selectedProvider.getURIOfFirstProvider(), i, getDataType()[i], getBandCount());
414
                                bl.addBand(band, i);
415
                        } catch(BandNotFoundInListException e) {
416
                                //No a?adimos la banda
417
                        }
418
                }
419
                bl.setDrawableBands(bandList.getDrawableBands());
420

    
421
                DefaultRasterQuery q = (DefaultRasterQuery)RasterLocator.getManager().createQuery();
422
                q.setAreaOfInterest(extent, bufWidth, bufHeight);
423
                q.setBandList(bandList);
424
                q.setBuffer(rasterBuf);
425
                q.setAdjustToExtent(adjustToExtent);
426
                return selectedProvider.getDataSet(q);
427
        }
428

    
429
        /*
430
         * (non-Javadoc)
431
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(int, int, int, int, int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer)
432
         */
433
        public Buffer getWindow(int x, int y, int w, int h, 
434
                        int bufWidth, int bufHeight, BandList bandList, Buffer rasterBuf, TaskStatus status) throws ProcessInterruptedException, RasterDriverException {
435
                return super.getWindow(x, y, w, h, bandList, rasterBuf, status);
436
        }
437

    
438
        /*
439
         * (non-Javadoc)
440
         * @see org.gvsig.raster.impl.provider.RasterProvider#isTiled()
441
         */
442
        /*public boolean isTiled() {
443
                PostGISRasterDataParameters p = (PostGISRasterDataParameters)param;
444
                return p.getNumberOfBlocks() > 1;
445
        }*/
446

    
447
}