Statistics
| Revision:

gvsig-raster / org.gvsig.raster.postgis / branches / org.gvsig.raster.postgis_dataaccess_refactoring / org.gvsig.raster.postgis.io / src / main / java / org / gvsig / raster / postgis / io / PostGISRasterProvider.java @ 2322

History | View | Annotate | Download (16.7 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
        /**
215
         * Reads overviews from database. The overviews in PostGIS raster are loaded 
216
         * in separated tables. The name of those tables is the same that the original table
217
         * with a overview prefix. Now this prefix is "o_X_" where the X is a factor scale.
218
         * 
219
         * For that reason the overview object contains the DataParameter which correspond
220
         * to each table.
221
         * @throws DataException 
222
         * @throws DataException
223
         */
224
        private void readOverviews() throws DataException  {
225
                if(overviews == null) {
226
                        overviews = new ArrayList<Overview>();
227
                        String mainHost = ((PostGISRasterDataParameters)param).getURI();
228

    
229
                        String mainTable = dbParameters.getTable();
230
                        List<?> parameters = dbServerExplorer.list();
231

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

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

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

    
401
        public Buffer getBufferLastRequest() throws ProcessInterruptedException,
402
                        RasterDriverException {
403
                return null;
404
        }
405

    
406
        public Rectangle2D getLayerExtent(String layerName, String srs)
407
                        throws RemoteServiceException {
408
                return null;
409
        }
410
        
411
        /**
412
         * Gets the name of a raster file
413
         */
414
        private String getTableName(String name) {
415
                String newName = "";
416
                String schema = null;
417
                String table = null;
418
                int index = name.indexOf(" schema='") + 8;
419
                if(index != -1) {
420
                        try {
421
                                schema = name.substring(index + 1, name.indexOf("'", index + 1)); 
422
                                newName += schema + ".";
423
                        } catch (StringIndexOutOfBoundsException e) {
424
                        }
425
                }
426
                index = name.indexOf(" table='") + 7;
427
                if(index != -1) {
428
                        try {
429
                                table = name.substring(index + 1, name.indexOf("'", index + 1));
430
                                newName += table;
431
                        } catch (StringIndexOutOfBoundsException e) {
432
                        }
433
                }
434
                return newName;
435
        }
436
        
437
        public TileServer getTileServer() {
438
                if(tileServer == null) {
439
                        DefaultRasterStore store = new DefaultRasterStore();
440
                        store.setProvider(this);
441
                        tileServer = new PostGISRasterTileServer(store);                        
442
                }
443
                return tileServer;
444
        }
445

    
446
}