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

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

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

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

    
221
                        String mainTable = dbParameters.getTable();
222
                        List parameters = dbServerExplorer.list();
223

    
224
                        int mainFactor = 1; 
225
                                
226
                        if(isOverview(mainTable, mainTable)) {
227
                                mainFactor = getFactor(mainTable);
228
                        }
229
                        overviews.add(mainOverview);
230
                        
231
                        Iterator iter = parameters.iterator();
232
                        while (iter.hasNext()) {
233
                                DBStoreParameters p = (DBStoreParameters) iter.next();
234
                                String tname = p.getTable();
235

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

    
371
        /*
372
         * (non-Javadoc)
373
         * @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)
374
         */
375
        public Buffer getWindow(Extent ex, BandList bandList, Buffer rasterBuf) 
376
                throws ProcessInterruptedException, RasterDriverException {
377
                return super.getWindow(ex, bandList, rasterBuf);
378
        }
379

    
380
        /*
381
         * (non-Javadoc)
382
         * @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)
383
         */
384
        public Buffer getWindow(double ulx, double uly, double w, double h, 
385
                        BandList bandList, Buffer rasterBuf, boolean adjustToExtent) throws ProcessInterruptedException, RasterDriverException {
386
                return super.getWindow(ulx, uly, w, h, bandList, rasterBuf, adjustToExtent);
387
        }
388

    
389
        /*
390
         * (non-Javadoc)
391
         * @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)
392
         */
393
        public Buffer getWindow(Extent extent, 
394
                        int bufWidth, int bufHeight, BandList bandList, Buffer rasterBuf, boolean adjustToExtent) throws ProcessInterruptedException, RasterDriverException {
395

    
396
                try {
397
                        readOverviews();
398
                } catch (DataException e) {
399
                        throw new RasterDriverException("Overviews can't be read", e);
400
                }
401

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

    
415
                return selectedProvider.getWindow(extent, bufWidth, bufHeight, bl, rasterBuf, adjustToExtent);
416
        }
417

    
418
        /*
419
         * (non-Javadoc)
420
         * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWindowRaster(int, int, org.gvsig.fmap.dal.coverage.datastruct.BandList, org.gvsig.fmap.dal.coverage.dataset.Buffer)
421
         */
422
        public Buffer getWindow(int x, int y, 
423
                        BandList bandList, Buffer rasterBuf) throws ProcessInterruptedException, RasterDriverException {
424
                return super.getWindow(x, y, bandList, rasterBuf);
425
        }
426

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

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

    
445
}