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

History | View | Annotate | Download (16.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.awt.geom.Rectangle2D;
26
import java.io.File;
27
import java.util.ArrayList;
28
import java.util.Collections;
29
import java.util.Iterator;
30
import java.util.List;
31

    
32
import org.gvsig.fmap.dal.DALLocator;
33
import org.gvsig.fmap.dal.DataManager;
34
import org.gvsig.fmap.dal.DataStore;
35
import org.gvsig.fmap.dal.coverage.RasterLocator;
36
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
37
import org.gvsig.fmap.dal.coverage.exception.BandAccessException;
38
import org.gvsig.fmap.dal.coverage.exception.NotSupportedExtensionException;
39
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
40
import org.gvsig.fmap.dal.coverage.exception.QueryException;
41
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
42
import org.gvsig.fmap.dal.coverage.exception.RemoteServiceException;
43
import org.gvsig.fmap.dal.coverage.store.RasterQuery;
44
import org.gvsig.fmap.dal.coverage.store.parameter.RasterDataParameters;
45
import org.gvsig.fmap.dal.exception.DataException;
46
import org.gvsig.fmap.dal.exception.InitializeException;
47
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
48
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
49
import org.gvsig.fmap.dal.serverexplorer.db.DBServerExplorer;
50
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
51
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
52
import org.gvsig.fmap.dal.store.db.DBStoreParameters;
53
import org.gvsig.metadata.MetadataLocator;
54
import org.gvsig.raster.cache.tile.provider.TileServer;
55
import org.gvsig.raster.gdal.io.GdalDataParameters;
56
import org.gvsig.raster.gdal.io.GdalNative;
57
import org.gvsig.raster.gdal.io.GdalProvider;
58
import org.gvsig.raster.impl.buffer.SpiRasterQuery;
59
import org.gvsig.raster.impl.provider.AbstractRasterProvider;
60
import org.gvsig.raster.impl.provider.RemoteRasterProvider;
61
import org.gvsig.raster.impl.store.AbstractRasterDataParameters;
62
import org.gvsig.raster.impl.store.DefaultRasterStore;
63
import org.gvsig.raster.impl.store.DefaultStoreFactory;
64
import org.gvsig.raster.postgis.io.downloader.PostGISRasterTileServer;
65
import org.gvsig.tools.ToolsLocator;
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 implements RemoteRasterProvider {
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 AbstractRasterProvider 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 AbstractRasterProvider      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 show(int n) {
107
                        System.out.println("********Overview:" + n + "*********");
108
                        System.out.println("Width:" + width);
109
                        System.out.println("Height:" + height);
110
                        System.out.println("Factor:" + factor);
111
                        System.out.println("Pixel Size:" + pxSizeOverview);
112
                        System.out.println("***********************************");
113
                }
114
                
115
                public void createProvider(PostGISRasterDataParameters p) throws NotSupportedExtensionException {
116
                        GdalDataParameters gdalParams = new GdalDataParameters();
117
                        gdalParams.setURI(p.getURI());
118
                        try {
119
                                this.provider = new GdalProvider(gdalParams, storeServices);
120
                        } catch (NotSupportedExtensionException e) {
121
                                logger.info("===>" + gdalParams.getURI() + " " + e.getMessage(), e);
122
                        }
123
                        this.width = (int)provider.getWidth();
124
                        this.height = (int)provider.getHeight();
125
                        this.pxSizeOverview = provider.getExtent().width() / (double)this.width;
126
                }
127
                
128
                public int compareTo(Overview o) {
129
                        if(factor < o.factor)
130
                                return -1;
131
                        if(factor > o.factor)
132
                                return 1;
133
                        return 0;
134
                }
135
        }
136
        
137
        public static void register() {
138
                RasterLocator.getManager().getProviderServices().registerFileProvidersTiled(PostGISRasterProvider.class);
139
                
140
                DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
141
                if (dataman != null && !dataman.getStoreProviders().contains(NAME)) {
142
                        dataman.registerStoreProvider(NAME,
143
                                        PostGISRasterProvider.class, PostGISRasterDataParameters.class);
144
                }
145

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

    
199
                //Obtenemos el tipo de dato de gdal y lo convertimos el de RasterBuf
200
                int[] dt = new int[file.getDataType().length];
201
                for (int i = 0; i < dt.length; i++)
202
                        dt[i] = GdalNative.getRasterBufTypeFromGdalType(file.getDataType()[i]);
203
                setDataType(dt);
204
                
205
                PostGISRasterDataParameters p = (PostGISRasterDataParameters)params;
206
                dbParameters = p.getDBStoreParameters();
207
                dbServerExplorer = p.getDBExplorer();
208
        }
209
        
210
        public String getRMFFile() {
211
                return super.getRMFFileForRemoteServices(getTableName(uri));
212
        }
213
        
214
        public String getName() {
215
                return getTableName(uri);
216
        }
217
        
218
        public String getFullName() {
219
                return uri;
220
        }        
221

    
222
        public String getProviderName() {
223
            return NAME;
224
        }
225
        
226
        
227
        /**
228
         * Reads overviews from database. The overviews in PostGIS raster are loaded 
229
         * in separated tables. The name of those tables is the same that the original table
230
         * with a overview prefix. Now this prefix is "o_X_" where the X is a factor scale.
231
         * 
232
         * For that reason the overview object contains the DataParameter which correspond
233
         * to each table.
234
         * @throws DataException 
235
         * @throws DataException
236
         */
237
        private void readOverviews() throws DataException  {
238
                if(overviews == null) {
239
                        overviews = new ArrayList<Overview>();
240
                        String mainHost = ((PostGISRasterDataParameters)param).getURI();
241

    
242
                        String mainTable = dbParameters.getTable();
243
                        List<?> parameters = dbServerExplorer.list();
244

    
245
                        int mainFactor = 1; 
246
                                
247
                        if(isOverview(mainTable, mainTable)) {
248
                                mainFactor = getFactor(mainTable);
249
                        }
250
                        overviews.add(mainOverview);
251
                        
252
                        Iterator<?> iter = parameters.iterator();
253
                        while (iter.hasNext()) {
254
                                DBStoreParameters p = (DBStoreParameters) iter.next();
255
                                String tname = p.getTable();
256

    
257
                                try {
258
                                        if(isOverview(mainTable, tname)) {
259
                                                Overview o = new Overview();
260
                                                o.factor = (getFactor(tname) / mainFactor);
261
                                                o.width = (int)(getWidth() / o.factor);
262
                                                o.height = (int)(getHeight() / o.factor);
263
                                                o.pxSizeOverview = getExtent().width() / (double)o.width;
264
                                                o.createProvider(createParameters(mainHost, mainTable, tname));
265
                                                overviews.add(o);
266
                                        }
267
                                } catch (NumberFormatException e) {
268
                                } catch (PostGISRasterCoreException e) {
269
                                } catch (ValidateDataParametersException e) {
270
                                } catch (NotSupportedExtensionException e) {
271
                                }
272
                        }
273
                        Collections.sort(overviews);
274
                        
275
                        for (int i = 0; i < overviews.size(); i++) {
276
                                overviews.get(i).show(i);
277
                        }
278
                }
279
        }
280
        
281
        /**
282
         * Returns true if tname is an overview of mainTable
283
         * @param mainTable
284
         * @param tname
285
         * @return
286
         */
287
        private boolean isOverview(String mainTable, String tname) throws NumberFormatException {
288
                if(mainTable.compareTo(tname) != 0) {
289
                        return ((tname.endsWith(mainTable) && tname.startsWith(OVERVIEW_PREFIX)) ||
290
                                        (tname.startsWith(OVERVIEW_PREFIX) && mainTable.startsWith(OVERVIEW_PREFIX) && getFactor(tname) > getFactor(mainTable)));
291
                }
292
                return false;
293
        }
294
        
295
        /**
296
         * Gets the overview factor number reading the name of the table
297
         * @param tname
298
         * @return
299
         * @throws NumberFormatException
300
         */
301
        private int getFactor(String tname) throws NumberFormatException {
302
                String factor = tname.substring(tname.indexOf('_') + 1);
303
                factor = factor.substring(0, factor.indexOf('_'));
304
                return new Integer(factor);
305
        }
306
        
307
        /**
308
         * Creates the list of parameters
309
         * @param mainHost
310
         * @param mainTable
311
         * @param tableName
312
         * @return
313
         * @throws PostGISRasterCoreException 
314
         * @throws PostGISRasterCoreException
315
         * @throws ProviderNotRegisteredException 
316
         * @throws InitializeException 
317
         * @throws ValidateDataParametersException 
318
         */
319
        @SuppressWarnings("deprecation")
320
        private PostGISRasterDataParameters createParameters(String mainHost, String mainTable, String tableName) throws PostGISRasterCoreException, ValidateDataParametersException, InitializeException, ProviderNotRegisteredException {
321
                String newHost = mainHost.replaceFirst(mainTable, tableName);
322
                
323
                PostGISRasterServerExplorerParameters explorerParams = (PostGISRasterServerExplorerParameters) dataManager.createServerExplorerParameters(PostGISRasterServerExplorer.NAME);
324
                explorerParams.setHost(newHost);
325
                PostGISRasterServerExplorer explorer = (PostGISRasterServerExplorer) dataManager.createServerExplorer(explorerParams);
326
                RasterDataParameters storeParameters = (RasterDataParameters)explorer.getStoredParameters();
327
                storeParameters.setURI(newHost);
328
                return (PostGISRasterDataParameters)storeParameters;
329
        }
330
        
331
        /**
332
         * Selects the right overview. The right overview means the first 
333
         * one with a pixel size lesser or equals than the original. 
334
         * @param pixels
335
         * @param mts
336
         */
337
        private void overviewSelector(int pixels, double mts) {
338
                this.selectedProvider = overviews.get(overviews.size() - 1).provider;
339
                //System.out.println("*************" + overviews.get(overviews.size() - 1).pxSizeOverview + "**************");
340
                double pxSizeRequest = mts / (double)pixels;
341
                for (int i = overviews.size() - 1; i >= 0; i--) {
342
                        Overview ovb = overviews.get(i);
343
                        //System.out.println(".....Overview:" + i + " PS request:" + pxSizeRequest + " PS Overview:" + ovb.pxSizeOverview);
344
                        if(pxSizeRequest >= ovb.pxSizeOverview) {
345
                                this.selectedProvider = ovb.provider;
346
                                break;
347
                                //System.out.println(ovb.pxSizeOverview);
348
                        }
349
                }
350
                //System.out.println("***************************");
351
                logger.info("...Overview selected: " + getTableName(selectedProvider.getURI()) + " W:" + selectedProvider.getWidth() + " H:" + selectedProvider.getHeight() + " PS:" + selectedProvider.getCellSize());
352
        }
353
        
354
        public int getOverviewCount(int band) throws BandAccessException, RasterDriverException {
355
                if(band >= getBandCount())
356
                        throw new BandAccessException("Wrong band");
357
                return overviews.size();
358
        }
359
        
360
        public int getOverviewWidth(int band, int overview) throws BandAccessException, RasterDriverException {
361
                if (band >= getBandCount())
362
                        throw new BandAccessException("Wrong band");
363
                if (overview >= overviews.size())
364
                        throw new BandAccessException("Wrong overview count");
365
                return overviews.get(overview).width;
366
        }
367

    
368
        public int getOverviewHeight(int band, int overview) throws BandAccessException, RasterDriverException {
369
                if (band >= getBandCount())
370
                        throw new BandAccessException("Wrong band");
371
                if (overview >= overviews.size())
372
                        throw new BandAccessException("Wrong overview count");
373
                return overviews.get(overview).height;
374
        }
375
        
376
        @Override
377
        public void loadBuffer(SpiRasterQuery q) 
378
                        throws ProcessInterruptedException, RasterDriverException {
379
                try {
380
                        readOverviews();
381
                } catch (DataException e) {
382
                        throw new RasterDriverException("Overviews can't be read", e);
383
                }
384
                //System.out.println("---------------------------------");
385
                //System.err.println(q.getAdjustedBufWidth() + " # " + q.getAdjustedRequestBoundingBox().width());
386
                //System.err.println(q.getBufWidth() + " # " + q.getRequestBoundingBox().width());
387
                
388
                overviewSelector(q.getAdjustedBufWidth(), q.getAdjustedRequestBoundingBox().width());
389
                
390
                DefaultRasterStore store = new DefaultRasterStore();
391
                store.setProvider(selectedProvider);
392
                try {
393
                        store.query((RasterQuery)q);
394
                } catch (QueryException e) {
395
                        throw new RasterDriverException("", e);
396
                }
397
        }
398
        
399
        /**
400
         * When the remote layer has fixed size this method downloads the file and return its reference. 
401
         * File layer has in the long side FIXED_SIZE pixels and the bounding box is complete. This file could be
402
         * useful to build an histogram or calculate statistics. This represents a sample of data.
403
         * @return
404
         * @throws RasterDriverException
405
         */
406
        public File getFileLayer() throws RasterDriverException {
407
                return null;
408
        }
409
        
410
        public File getLastRequest() {
411
                return null;
412
        }
413

    
414
        public Buffer getBufferLastRequest() throws ProcessInterruptedException,
415
                        RasterDriverException {
416
                return null;
417
        }
418

    
419
        public Rectangle2D getLayerExtent(String layerName, String srs)
420
                        throws RemoteServiceException {
421
                return null;
422
        }
423
        
424
        /**
425
         * Gets the name of a raster file
426
         */
427
        private String getTableName(String name) {
428
                String newName = "";
429
                String schema = null;
430
                String table = null;
431
                int index = name.indexOf(" schema='") + 8;
432
                if(index != -1) {
433
                        try {
434
                                schema = name.substring(index + 1, name.indexOf("'", index + 1)); 
435
                                newName += schema + ".";
436
                        } catch (StringIndexOutOfBoundsException e) {
437
                        }
438
                }
439
                index = name.indexOf(" table='") + 7;
440
                if(index != -1) {
441
                        try {
442
                                table = name.substring(index + 1, name.indexOf("'", index + 1));
443
                                newName += table;
444
                        } catch (StringIndexOutOfBoundsException e) {
445
                        }
446
                }
447
                return newName;
448
        }
449
        
450
        public TileServer getTileServer() {
451
                if(tileServer == null) {
452
                        DefaultRasterStore store = new DefaultRasterStore();
453
                        store.setProvider(this);
454
                        tileServer = new PostGISRasterTileServer(store);                        
455
                }
456
                return tileServer;
457
        }
458

    
459
}