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

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.TaskStatus;
65
import org.slf4j.Logger;
66
import org.slf4j.LoggerFactory;
67
/**
68
 * This class represents the data access just for PostGIS raster databases.
69
 * @author Nacho Brodin (nachobrodin@gmail.com)
70
 */
71
public class PostGISRasterProvider extends GdalProvider {
72
        public static String           NAME                     = "PostGIS Raster Store";
73
        public static String           DESCRIPTION              = "PostGIS Raster file";
74
        public static final String     METADATA_DEFINITION_NAME = "PostGISRasterStore";
75
        private static final String    OVERVIEW_PREFIX          = "o_";
76
        
77
        private DBServerExplorer       dbServerExplorer         = null;
78
        private DBStoreParameters      dbParameters             = null;
79
        private ArrayList<Overview>    overviews                = null;
80
        private DataManager            dataManager              = DALLocator.getDataManager();
81
        private DefaultRasterProvider  selectedProvider         = null;
82
        private Overview               mainOverview             = null;
83
        private static Logger          logger                   = LoggerFactory.getLogger(PostGISRasterProvider.class.getName());
84
        
85
        class Overview implements Comparable<Overview> {
86
                public int                         width               = 0;
87
                public int                         height              = 0;
88
                public int                         factor              = 0;
89
                public double                      pxSizeOverview      = 0;
90
                public DefaultRasterProvider       provider            = null;
91
                
92
                public Overview() {
93
                        
94
                }
95
                
96
                public Overview(int f, int w, int h, PostGISRasterDataParameters p) throws NotSupportedExtensionException {
97
                        this.width = w;
98
                        this.height = h;
99
                        this.factor = f;
100
                        if(p != null)
101
                                createProvider(p);
102
                        this.pxSizeOverview = getExtent().width() / (double)w;
103
                }
104
                
105
                public void createProvider(PostGISRasterDataParameters p) throws NotSupportedExtensionException {
106
                        GdalDataParameters gdalParams = new GdalDataParameters();
107
                        gdalParams.setURI(p.getURI());
108
                        try {
109
                                this.provider = new GdalProvider(gdalParams, storeServices);
110
                        } catch (NotSupportedExtensionException e) {
111
                                logger.info("===>" + gdalParams.getURI() + " " + e.getMessage(), e);
112
                        }
113
                        this.width = (int)provider.getWidth();
114
                        this.height = (int)provider.getHeight();
115
                        this.pxSizeOverview = provider.getExtent().width() / (double)this.width;
116
                }
117
                
118
                public int compareTo(Overview o) {
119
                        if(factor < o.factor)
120
                                return -1;
121
                        if(factor > o.factor)
122
                                return 1;
123
                        return 0;
124
                }
125
        }
126
        
127
        public static void register() {
128
                ExtensionPointManager extensionPoints = ToolsLocator.getExtensionPointManager();
129
                ExtensionPoint point = extensionPoints.get("DefaultDriver");
130
                point.append("reader", PostGISRasterProvider.NAME, PostGISRasterProvider.class);
131
                
132
                RasterLocator.getManager().registerFileProvidersTiled(PostGISRasterProvider.class);
133
                
134
                DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
135
                if (dataman != null && !dataman.getStoreProviders().contains(NAME)) {
136
                        dataman.registerStoreProvider(NAME,
137
                                        PostGISRasterProvider.class, PostGISRasterDataParameters.class);
138
                }
139

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

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

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

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

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

    
376
        /*
377
         * (non-Javadoc)
378
         * @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)
379
         */
380
        public Buffer getWindow(Extent ex, BandList bandList, Buffer rasterBuf, TaskStatus status) 
381
                throws ProcessInterruptedException, RasterDriverException {
382
                return super.getWindow(ex, bandList, rasterBuf, status);
383
        }
384

    
385
        /*
386
         * (non-Javadoc)
387
         * @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)
388
         */
389
        public Buffer getWindow(double ulx, double uly, double w, double h, 
390
                        BandList bandList, Buffer rasterBuf, boolean adjustToExtent, TaskStatus status) throws ProcessInterruptedException, RasterDriverException {
391
                return super.getWindow(ulx, uly, w, h, bandList, rasterBuf, adjustToExtent, status);
392
        }
393

    
394
        /*
395
         * (non-Javadoc)
396
         * @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)
397
         */
398
        public Buffer getWindow(Extent extent, 
399
                        int bufWidth, int bufHeight, BandList bandList, Buffer rasterBuf, boolean adjustToExtent) throws ProcessInterruptedException, RasterDriverException {
400

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

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

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

    
428
        /*
429
         * (non-Javadoc)
430
         * @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)
431
         */
432
        public Buffer getWindow(int x, int y, int w, int h, 
433
                        int bufWidth, int bufHeight, BandList bandList, Buffer rasterBuf, TaskStatus status) throws ProcessInterruptedException, RasterDriverException {
434
                return super.getWindow(x, y, w, h, bandList, rasterBuf, status);
435
        }
436

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

    
446
}