Revision 2059

View differences:

org.gvsig.raster.wmts/tags/tagdate_29082013/org.gvsig.raster.wmts/org.gvsig.raster.wmts.io/src/main/resources/META-INF/services/org.gvsig.tools.library.Library
1
org.gvsig.raster.wmts.io.DefaultWMTSIOLibrary
org.gvsig.raster.wmts/tags/tagdate_29082013/org.gvsig.raster.wmts/org.gvsig.raster.wmts.io/src/main/java/org/gvsig/raster/wmts/io/WMTSServerExplorer.java
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

  
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2009 IVER T.I   {{Task}}
26
*/
27

  
28
package org.gvsig.raster.wmts.io;
29

  
30
import java.io.IOException;
31
import java.io.InputStream;
32
import java.net.InetAddress;
33
import java.net.MalformedURLException;
34
import java.net.URL;
35
import java.net.URLConnection;
36
import java.net.UnknownHostException;
37
import java.util.List;
38

  
39
import org.gvsig.compat.net.ICancellable;
40
import org.gvsig.fmap.dal.DALLocator;
41
import org.gvsig.fmap.dal.DataManager;
42
import org.gvsig.fmap.dal.DataServerExplorer;
43
import org.gvsig.fmap.dal.DataServerExplorerParameters;
44
import org.gvsig.fmap.dal.DataStoreParameters;
45
import org.gvsig.fmap.dal.NewDataStoreParameters;
46
import org.gvsig.fmap.dal.coverage.store.parameter.TileDataParameters;
47
import org.gvsig.fmap.dal.exception.DataException;
48
import org.gvsig.fmap.dal.exception.InitializeException;
49
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
50
import org.gvsig.fmap.dal.spi.DataServerExplorerProvider;
51
import org.gvsig.fmap.dal.spi.DataServerExplorerProviderServices;
52
import org.gvsig.raster.wmts.ogc.WMTSClient;
53
import org.gvsig.raster.wmts.ogc.WMTSOGCLocator;
54
import org.gvsig.raster.wmts.ogc.exception.WMTSException;
55

  
56
/**
57
 * Explorer for a WMTS server
58
 * @author Nacho Brodin (nachobrodin@gmail.com)
59
 */
60
public class WMTSServerExplorer implements DataServerExplorer, DataServerExplorerProvider {
61
	public static final String           NAME                     = "WMTSRemoteServerExplorer";
62
	private WMTSClient                   ogcClient                = null;
63
	private WMTSServerExplorerParameters parameters               = null;
64
	
65
	public WMTSServerExplorer(
66
			WMTSServerExplorerParameters parameters,
67
			DataServerExplorerProviderServices services)
68
			throws InitializeException {
69
		this.parameters = parameters;
70
	}
71
	
72
	public String getDataStoreProviderName() {
73
		return WMTSProvider.NAME;
74
	}
75
	
76
	public String getDescription() {
77
		return WMTSProvider.DESCRIPTION;
78
	}
79
	
80
	public DataStoreParameters getStoreParameters() {
81
		DataManager manager = DALLocator.getDataManager();
82
		WMTSDataParameters wmtsParams = null;
83
		try {
84
			wmtsParams = (WMTSDataParameters) manager.createStoreParameters(this.getDataStoreProviderName());
85
			wmtsParams.setURI(parameters.getHost());
86
			wmtsParams.setOGCClient(getOGCClient());
87

  
88
			if(WMTSProvider.TILED) {
89
				TileDataParameters tileParams = (TileDataParameters) manager.createStoreParameters("Tile Store");
90
				tileParams.setDataParameters(wmtsParams);
91
				return tileParams;
92
			} 
93
		} catch (InitializeException e) {
94
			e.printStackTrace();
95
		} catch (ProviderNotRegisteredException e) {
96
			e.printStackTrace();
97
		}
98
		return wmtsParams;
99
	}
100

  
101
	public boolean add(String provider, NewDataStoreParameters parameters,
102
			boolean overwrite) throws DataException {
103
		return false;
104
	}
105

  
106
	public boolean canAdd() {
107
		return false;
108
	}
109

  
110
	public boolean canAdd(String storeName) throws DataException {
111
		return false;
112
	}
113

  
114
	public NewDataStoreParameters getAddParameters(String storeName)
115
			throws DataException {
116
		return null;
117
	}
118

  
119
	public List<?> getDataStoreProviderNames() {
120
		return null;
121
	}
122

  
123
	/*
124
	 * (non-Javadoc)
125
	 * @see org.gvsig.fmap.dal.DataServerExplorer#getParameters()
126
	 */
127
	public DataServerExplorerParameters getParameters() {
128
		return parameters;
129
	}
130

  
131
	public List<?> list() throws DataException {
132
		return null;
133
	}
134

  
135
	public List<?> list(int mode) throws DataException {
136
		return null;
137
	}
138

  
139
	public void remove(DataStoreParameters parameters) throws DataException {
140
		
141
	}
142

  
143
	public void dispose() {
144
		
145
	}
146

  
147
	public String getProviderName() {
148
		return null;
149
	}
150

  
151
	//**********************************************
152
	//Connector
153
	//**********************************************
154
	
155
	public void connect(ICancellable cancellable) throws WMTSException {
156
		URL url = null;
157
		boolean override = false;
158
		
159
		try {
160
			url = new URL(parameters.getHost());
161
		} catch (Exception e) {
162
			throw new WMTSException("Malformed URL",e);
163
		}
164
        try {
165
        	ogcClient = WMTSOGCLocator.getManager().createWMTSClient(url.toString());
166
        	ogcClient.setForceLongitudeFirstAxisOrder(parameters.isLongitudeFirst());
167
        	if (!ogcClient.connect(override, cancellable))
168
        		throw new WMTSException("Error connecting");
169
        } catch (IOException e) {
170
			throw new WMTSException(e.getMessage(), e);
171
		}
172
	}
173
	
174
	/**
175
	 * Checks if the network and host are reachable
176
	 * @param timeout for the host
177
	 * @return true if both are reachable and false if they are not
178
	 */
179
	public boolean isHostReachable(int timeout) {
180
		URL url = null;
181
		URLConnection con = null;
182
		try {
183
			url = new URL(parameters.getHost());
184
			con = url.openConnection();
185
			if(con == null)
186
				return false;
187
			con.connect();
188
		} catch (MalformedURLException e) {
189
			return false;
190
		} catch (IOException e) {
191
			return false;
192
		}
193
		
194
		InputStream stream = null;
195
		try {
196
			stream = con.getInputStream();
197
			if(stream == null)
198
				return false;
199
		} catch (IOException e) {
200
		}
201
		
202
		return true;
203
	}
204

  
205
	/**
206
	 * Checks if the network and host are reachable
207
	 * @return true if both are reachable and false if they are not
208
	 */
209
	public boolean isHostReachable() {
210
		int timeout = 10000;
211
		return isHostReachable(timeout);
212
	}
213

  
214
	public boolean isConnected() {
215
		if(ogcClient != null)
216
			return true;
217
		return false;
218
	}
219
	
220
	public WMTSClient getOGCClient() {
221
		return ogcClient;
222
	}
223

  
224
	/*public WMTSThemes getThemes() {
225
		return connector.getThemes();
226
	}
227
    
228
    public WMTSLayer getLayer(String layerName) {
229
    	return connector.getLayer(layerName);
230
    }
231
    
232
	public List<WMTSTileMatrixSet> getTileMatrixSet() {
233
    	return connector.getTileMatrixSet();
234
    }
235
	
236
	public WMTSServiceIdentification getServiceIdentification() {
237
		return connector.getServiceIdentification();
238
	}
239
	
240
	public WMTSServiceProvider getServiceProvider() {
241
		return connector.getServiceProvider();
242
	}*/
243

  
244
	public String getHost() {
245
		return parameters.getHost();
246
	}
247

  
248
	public DataServerExplorerProviderServices getServerExplorerProviderServices() {
249
		return null;
250
	}
251
}
0 252

  
org.gvsig.raster.wmts/tags/tagdate_29082013/org.gvsig.raster.wmts/org.gvsig.raster.wmts.io/src/main/java/org/gvsig/raster/wmts/io/WMTSProvider.java
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.wmts.io;
23

  
24
import java.awt.Image;
25
import java.awt.geom.AffineTransform;
26
import java.awt.geom.NoninvertibleTransformException;
27
import java.awt.geom.Point2D;
28
import java.awt.geom.Rectangle2D;
29
import java.io.File;
30
import java.io.IOException;
31
import java.net.ConnectException;
32
import java.net.MalformedURLException;
33
import java.net.URL;
34
import java.util.List;
35

  
36
import javax.swing.ImageIcon;
37

  
38
import org.gvsig.compat.net.ICancellable;
39
import org.gvsig.fmap.dal.DALLocator;
40
import org.gvsig.fmap.dal.DataStore;
41
import org.gvsig.fmap.dal.DataStoreParameters;
42
import org.gvsig.fmap.dal.coverage.RasterLocator;
43
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
44
import org.gvsig.fmap.dal.coverage.datastruct.BandList;
45
import org.gvsig.fmap.dal.coverage.datastruct.DatasetBand;
46
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
47
import org.gvsig.fmap.dal.coverage.exception.BandAccessException;
48
import org.gvsig.fmap.dal.coverage.exception.BandNotFoundInListException;
49
import org.gvsig.fmap.dal.coverage.exception.FileNotOpenException;
50
import org.gvsig.fmap.dal.coverage.exception.InfoByPointException;
51
import org.gvsig.fmap.dal.coverage.exception.InvalidSetViewException;
52
import org.gvsig.fmap.dal.coverage.exception.NotSupportedExtensionException;
53
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
54
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
55
import org.gvsig.fmap.dal.coverage.exception.RemoteServiceException;
56
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
57
import org.gvsig.fmap.dal.coverage.store.props.HistogramComputer;
58
import org.gvsig.fmap.dal.coverage.store.props.Transparency;
59
import org.gvsig.fmap.dal.coverage.util.MathUtils;
60
import org.gvsig.fmap.dal.exception.InitializeException;
61
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
62
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
63
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
64
import org.gvsig.metadata.MetadataLocator;
65
import org.gvsig.raster.cache.tile.TileCacheLocator;
66
import org.gvsig.raster.cache.tile.TileCacheManager;
67
import org.gvsig.raster.cache.tile.exception.TileGettingException;
68
import org.gvsig.raster.cache.tile.provider.CacheStruct;
69
import org.gvsig.raster.cache.tile.provider.TileListener;
70
import org.gvsig.raster.cache.tile.provider.TileServer;
71
import org.gvsig.raster.impl.DefaultRasterManager;
72
import org.gvsig.raster.impl.buffer.DefaultRasterQuery;
73
import org.gvsig.raster.impl.datastruct.BandListImpl;
74
import org.gvsig.raster.impl.datastruct.DatasetBandImpl;
75
import org.gvsig.raster.impl.datastruct.ExtentImpl;
76
import org.gvsig.raster.impl.provider.DefaultRasterProvider;
77
import org.gvsig.raster.impl.provider.MemoryMatrixBuffer;
78
import org.gvsig.raster.impl.provider.RasterProvider;
79
import org.gvsig.raster.impl.provider.RemoteRasterProvider;
80
import org.gvsig.raster.impl.provider.TiledRasterProvider;
81
import org.gvsig.raster.impl.store.DefaultStoreFactory;
82
import org.gvsig.raster.impl.store.properties.DataStoreColorInterpretation;
83
import org.gvsig.raster.impl.store.properties.DataStoreTransparency;
84
import org.gvsig.raster.impl.store.properties.RemoteStoreHistogram;
85
import org.gvsig.raster.util.DefaultProviderServices;
86
import org.gvsig.raster.wmts.io.downloader.WMTSTileServer;
87
import org.gvsig.raster.wmts.ogc.WMTSClient;
88
import org.gvsig.raster.wmts.ogc.WMTSOGCLocator;
89
import org.gvsig.raster.wmts.ogc.WMTSStatus;
90
import org.gvsig.raster.wmts.ogc.exception.DownloadException;
91
import org.gvsig.raster.wmts.ogc.exception.ServerErrorException;
92
import org.gvsig.raster.wmts.ogc.exception.WMTSException;
93
import org.gvsig.raster.wmts.ogc.struct.WMTSBoundingBox;
94
import org.gvsig.raster.wmts.ogc.struct.WMTSLayer;
95
import org.gvsig.raster.wmts.ogc.struct.WMTSTile;
96
import org.gvsig.raster.wmts.ogc.struct.WMTSTileMatrix;
97
import org.gvsig.raster.wmts.ogc.struct.WMTSTileMatrixLimits;
98
import org.gvsig.raster.wmts.ogc.struct.WMTSTileMatrixSet;
99
import org.gvsig.raster.wmts.ogc.struct.WMTSTileMatrixSetLink;
100
import org.gvsig.tools.ToolsLocator;
101
import org.gvsig.tools.task.TaskStatus;
102
import org.slf4j.Logger;
103
import org.slf4j.LoggerFactory;
104
/**
105
 * Provider for WMTS service
106
 *
107
 * @author Nacho Brodin (nachobrodin@gmail.com)
108
 */
109
public class WMTSProvider extends DefaultRasterProvider implements RemoteRasterProvider, TiledRasterProvider {
110
	public static String                NAME                     = "Wmts Store";
111
	public static String                DESCRIPTION              = "Wmts Raster file";
112
	public static final String          METADATA_DEFINITION_NAME = "WmtsStore";
113
	private static Logger               logger                   = LoggerFactory.getLogger(WMTSProvider.class);
114
	public static boolean               TILED                    = true;
115
	
116
	//Los tiles se piden de forma secuencial y sin lanzar threads para ello (+Lento)
117
	public static int                   SEQUENTIAL               = 0;
118
	//Los tiles se piden en threads y hay un thread manager para gestionar que no se pidan m?s de cierto n?mero
119
	public static int                   LIMITED_THREADS          = 1;
120
	//Los tiles se piden en threads y se lanzan tantos threads como tiles haya
121
	public static int                   UNLIMITED_THREADS        = 2;
122
	private int                         requestType              = LIMITED_THREADS;
123
	
124
	private static final double         MTS_X_GRADO              = 111319.490793274;
125
	
126
	private Extent                      viewRequest              = null;
127
	private WMTSClient                  ogcClient                = null;
128
	//private static Hashtable<URL, WMTSConnector>    
129
	//                                    drivers                  = new Hashtable<URL, WMTSConnector> ();
130
	private boolean                     open                     = false;
131
	private File                        lastRequest              = null;
132
	private DataStoreTransparency       lastFileTransparency     = null;
133
	private int                         lastWidthRequest         = 0;
134
	private int                         lastHeightRequest        = 0;
135
	private WMTSStatus                  lastStatus               = null;
136
	private boolean                     gridSubsets              = true;
137
	private Extent[]                    extentByLevel            = null; //Only for layers without gridSubsets
138
	private Extent                      bbox                     = null;
139
	private MathUtils                   math                     = RasterLocator.getManager().getMathUtils();
140
	
141
	/**
142
	 * This thread manages the number of tiles that have been thrown.
143
	 * This number is controlled by the NTHREADS_QUEUE variable.
144
	 * 
145
	 * @author Nacho Brodin (nachobrodin@gmail.com)
146
	 */
147
	public class RequestThreadManager extends Thread {
148
		private TilePipe               pipe           = null;
149
		private List<WMTSTile>         tiles          = null;
150
		private WMTSStatus             status         = null;
151
		
152
		public RequestThreadManager(TilePipe pipe, List<WMTSTile> tiles, WMTSStatus status) {
153
			this.pipe = pipe;
154
			this.tiles = tiles;
155
			this.status = status;
156
		}
157
		
158
		public void run() {
159
			for (int i = 0; i < tiles.size(); i++) {
160
				WMTSTile tile = tiles.get(i);
161
				WMTSStatus statusCopy = status.cloneStatus();
162
				statusCopy.setTileRow(tile.getRow());
163
				statusCopy.setTileCol(tile.getCol());
164
				if (pipe.getSize() > TilePipe.NTHREADS_QUEUE) {
165
					try {
166
						synchronized (this) {
167
							wait();							
168
						}
169
					} catch( InterruptedException e ) {
170
					}
171
				}
172
				new RequestTileLauncher(pipe, statusCopy, tile).start();
173
			}
174
		}
175
	}
176
	
177
	/**
178
	 * Thread to download a tile
179
	 * @author Nacho Brodin (nachobrodin@gmail.com)
180
	 */
181
	class RequestTileLauncher extends Thread {
182
		private TilePipe      pipe    = null;
183
		private WMTSStatus    status  = null;
184
		private WMTSTile      tile    = null;
185

  
186
		public RequestTileLauncher(TilePipe pipe, WMTSStatus status, WMTSTile tile) {
187
			this.pipe = pipe;
188
			this.status = status;
189
			this.tile = tile;
190
		}
191

  
192
		public void run() {
193
			try {
194
				//File file = getConnector().getTile(status, null);
195
				URL url = getOGCClient().getTileURL(status);
196
				tile.setFile(getOGCClient().downloadFile(url, null));
197
				pipe.setTile(tile);
198
			} catch (DownloadException e) {
199
				logger.info("Error downloading files", e);
200
			} catch (MalformedURLException e) {
201
				logger.info("Malformed URL", e);
202
			} catch (WMTSException e) {
203
				logger.info("", e);
204
			}
205
		}
206
	}
207
	
208
	/**
209
	 * Point information 
210
	 * @author Nacho Brodin (nachobrodin@gmail.com)
211
	 */
212
	public class PointInfo {
213
		public Point2D worldCoord;
214
		public Point2D tile;
215
		public Point2D pixelInTile;
216
		public int     level;
217
		
218
		public PointInfo(Point2D worldCoord) {
219
			this.worldCoord = worldCoord;
220
		}
221
	}
222

  
223
	public static void register() {
224
		DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
225
		if (dataman != null && !dataman.getStoreProviders().contains(NAME)) {
226
			dataman.registerStoreProvider(NAME,
227
					WMTSProvider.class, WMTSDataParametersImpl.class);
228
		}
229

  
230
		if (!dataman.getExplorerProviders().contains(WMTSServerExplorer.NAME)) {
231
			dataman.registerExplorerProvider(WMTSServerExplorer.NAME, WMTSServerExplorer.class, WMTSServerExplorerParameters.class);
232
		}
233
		dataman.registerStoreFactory(NAME, DefaultStoreFactory.class);
234
	}
235
	
236
	public WMTSProvider() throws NotSupportedExtensionException {
237
		super();
238
	}
239
	
240
	/**
241
	 * Constructor. Abre el dataset.
242
	 * @param proj Proyecci?n
243
	 * @param fName Nombre del fichero
244
	 * @throws NotSupportedExtensionException
245
	 */
246
	public WMTSProvider(String params) throws NotSupportedExtensionException {
247
		super(params);
248
		if(params instanceof String) {
249
			WMTSDataParameters p = new WMTSDataParametersImpl();
250
			p.setURI((String)params);
251
			super.init(p, null, ToolsLocator.getDynObjectManager()
252
					.createDynObject(
253
							MetadataLocator.getMetadataManager().getDefinition(
254
									DataStore.METADATA_DEFINITION_NAME)));
255
			init(p, null);
256
		}
257
	}
258
	
259
	public WMTSProvider(WMTSDataParameters params,
260
			DataStoreProviderServices storeServices) throws NotSupportedExtensionException {
261
		super(params, storeServices, ToolsLocator.getDynObjectManager()
262
				.createDynObject(
263
						MetadataLocator.getMetadataManager().getDefinition(
264
								DataStore.METADATA_DEFINITION_NAME)));
265
		init(params, storeServices);
266
	}
267
	
268
	/**
269
	 * Gets the connector from the URL
270
	 * @return
271
	 * @throws RemoteServiceException
272
	 */
273
	public WMTSClient getOGCClient() throws WMTSException {
274
		if(ogcClient == null) {
275
			WMTSDataParameters p = (WMTSDataParameters)parameters;
276
			ogcClient = p.getOGCClient();
277
			if(ogcClient != null)
278
				return ogcClient;
279
			
280
			URL url = null;
281
			try {
282
				url = new URL(p.getURI());
283
			} catch (Exception e) {
284
				throw new WMTSException("Malformed URL",e);
285
			}
286
			try {
287
				ogcClient = WMTSOGCLocator.getManager().createWMTSClient(url.toString());
288
				ogcClient.connect(true, new ICancellable() {
289
					
290
					public boolean isCanceled() {
291
						return false;
292
					}
293
					
294
					public Object getID() {
295
						return null;
296
					}
297
				});
298
			} catch (ConnectException e) {
299
				throw new WMTSException("Connect exception",e);
300
			} catch (IOException e) {
301
				throw new WMTSException("Connect exception",e);
302
			}
303
		}
304
		return ogcClient;
305
	}
306

  
307
	/**
308
	 * Crea las referencias al fichero y carga
309
	 * las estructuras con la informaci?n y los metadatos.
310
	 * @param proj Proyecci?n
311
	 * @param param Parametros de carga
312
	 * @throws NotSupportedExtensionException
313
	 */
314
	public void init (DataStoreParameters params,
315
			DataStoreProviderServices storeServices) throws NotSupportedExtensionException {
316
		setParam(storeServices, params);
317
		if(((WMTSDataParameters)params).getImageFormat().compareTo("image/gif") == 0) {
318
			setDataType(new int[]{Buffer.TYPE_BYTE});
319
			bandCount = 1;
320
		} else {
321
			setDataType(new int[]{Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE});
322
			bandCount = 4;
323
		}
324
		
325
		if(!(param instanceof WMTSDataParameters))
326
			return;
327
		
328
		gridSubsets = hasGridSubsets((WMTSDataParameters)param);
329
		open = true;
330
	}
331
	
332
	/**
333
	 * Returns true if this layer has grid subsets
334
	 * @return
335
	 */
336
	public boolean hasGridSubsets() {
337
		return gridSubsets;
338
	}
339
	
340
	/**
341
	 * Checks if this layer has grid subsets or doesn't
342
	 * @param p
343
	 * @return
344
	 */
345
	private boolean hasGridSubsets(WMTSDataParameters p) {
346
		List<WMTSTileMatrixLimits> tileMatrixSetLimits = null;
347
		List<WMTSTileMatrixSetLink> tileMatrixSetLinkList = p.getLayer().getTileMatrixSetLink();
348
		String srs = p.getSRSCode();
349
		for (int i = 0; i < tileMatrixSetLinkList.size(); i++) {
350
			WMTSTileMatrixSetLink tileMatrixSetLink = (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(i);
351
			WMTSTileMatrixSet tms = tileMatrixSetLink.getTileMatrixSet();
352
			List<WMTSTileMatrixLimits> tmsl = tileMatrixSetLink.getTileMatrixLimits();
353
			String srsTileSet = tms.getSupportedCRS();
354
			if(srsTileSet.compareTo(srs) == 0) {
355
				tileMatrixSetLimits = tmsl;
356
			}
357
		}
358
		
359
		return tileMatrixSetLimits.size() <= 0 ? false : true; 
360
	}
361
	
362
	/*public static final WMTSConnector getConnectorFromURL(URL url) throws IOException {
363
		WMTSConnector drv = (WMTSConnector) drivers.get(url);
364
		if (drv == null) {
365
			drv = new WMTSConnector(url);
366
			drivers.put(url, drv);
367
		}
368
		return drv;
369
	}*/
370
	
371
	/**
372
	 * Obtiene el objeto que contiene que contiene la interpretaci?n de
373
	 * color por banda
374
	 * @return
375
	 */
376
	public ColorInterpretation getColorInterpretation() {
377
		if(super.getColorInterpretation() == null) {
378
			ColorInterpretation colorInterpretation = new DataStoreColorInterpretation();
379
			colorInterpretation.initColorInterpretation(getBandCount());
380
			if(getBandCount() >= 3) {
381
				colorInterpretation.setColorInterpValue(0, DataStoreColorInterpretation.RED_BAND);
382
				colorInterpretation.setColorInterpValue(1, DataStoreColorInterpretation.GREEN_BAND);
383
				colorInterpretation.setColorInterpValue(2, DataStoreColorInterpretation.BLUE_BAND);
384
			}
385
			if(getBandCount() == 4)
386
				colorInterpretation.setColorInterpValue(3, DataStoreColorInterpretation.ALPHA_BAND);
387
			if(getBandCount() > 4 || getBandCount() < 3) {
388
				for (int i = 0; i < getBandCount(); i++) {
389
					colorInterpretation.setColorInterpValue(i, DataStoreColorInterpretation.UNDEF_BAND);
390
				}
391
			}
392
			setColorInterpretation(colorInterpretation);
393
		}
394
		return super.getColorInterpretation();
395
	}
396
	
397
	public boolean isTiled() {
398
		return true;
399
	}
400
	
401
	public AffineTransform getAffineTransform() {
402
		WMTSDataParameters p = (WMTSDataParameters)parameters;
403
		Extent e = getExtent();
404
		double psX = e.width() / (lastWidthRequest <= 0 ? p.getWidth() : lastWidthRequest);
405
		double psY = -(e.height() / (lastHeightRequest <= 0 ? p.getHeight() : lastHeightRequest));
406
		ownTransformation = new AffineTransform(
407
				psX, 
408
				0, 
409
				0, 
410
				psY, 
411
				e.getULX() - (psX / 2),
412
				e.getULY() - (psY / 2));
413
		externalTransformation = (AffineTransform) ownTransformation.clone();
414
		return ownTransformation;
415
	}
416
	
417
	/**
418
	 * Gets the bounding box in world coordinates. If the layer has grid subsets (TileMatrixLimits) then
419
	 * this will have a only extent but if the layer doesn't have grid subsets then this will have a different
420
	 * extent in each level resolution. In this case we need to know the extent for each level.
421
	 * @return Extent
422
	 */
423
	public Extent getExtent() {
424
		WMTSDataParameters p = (WMTSDataParameters)parameters;
425
		if(gridSubsets) {
426
			WMTSLayer layer = p.getLayer();
427
			WMTSBoundingBox bbox = layer.getWGS84BBox();
428
			return new ExtentImpl(bbox.toRectangle2D());
429
		} else {
430
			/*WMTSTileMatrixSet tileMatrixSet = getTileMatrixSetLink().getTileMatrixSet();
431
			
432
			//Si ya se han calculado los niveles es q el extent es v?lido sino el nivel ser? el 0
433
			double scale = 0D;
434
			int level = 0;
435
			if(extentByLevel != null && p.getExtent() != null) {
436
				scale = getScale(p.getExtent(), p.getWidth());
437
				try {
438
					level = getLevelFromScale(scale, tileMatrixSet);
439
				} catch (RasterDriverException e) {
440
					e.printStackTrace();
441
				}				
442
			}
443
			
444
			Extent[] ext = getExtentByResolutionLevel();
445
			
446
			if(ext != null && level >= 0 && level < ext.length)
447
				return ext[level];*/
448
			if(bbox == null)
449
				getExtentByResolutionLevel();
450
			return bbox;
451
		}
452
	}
453
	
454
	/**
455
	 * Gets the suffix of the downloaded image
456
	 * @return
457
	 */
458
	public String getFileSuffix() {
459
		WMTSDataParameters p = (WMTSDataParameters)parameters;
460
		String format = p.getImageFormat();
461
		if (format == null){
462
			return "xml";
463
		}
464
		if (format.indexOf("png") >= 0){
465
	        return "png";
466
		}	
467
	    if (format.indexOf("xml") >= 0){
468
	        return "xml";
469
	    }	
470
	    if (format.indexOf("gif") >= 0){
471
	        return "gif";
472
	    }
473
	    if (format.indexOf("tif") >= 0){
474
	        return "tif";
475
	    }
476
	    if (format.indexOf("bmp") >= 0){
477
	        return "bmp";
478
	    }
479
	    if (format.indexOf("jpg") >= 0
480
	        || format.indexOf("jpeg") >= 0){
481
	        return "jpg";			 
482
	    }
483
		return "xml";
484
	}
485

  
486
	/**
487
	 * When a layer doesn't have grid subsets this will have a different bounding
488
	 * box by resolution level. This function calculates and returns the array of
489
	 * extents, one by resolution level.
490
	 * @return
491
	 */
492
	public Extent[] getExtentByResolutionLevel() {
493
		if(extentByLevel == null) {
494
			WMTSDataParameters p = (WMTSDataParameters)parameters;
495
			WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
496
			WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
497
			
498
	    	double widthMtsTile = 0;
499
	    	double heightMtsTile = 0;
500
			List<WMTSTileMatrix> tileMatrixList = tileMatrixSet.getTileMatrix();
501
			extentByLevel = new ExtentImpl[tileMatrixList.size()];
502
			double minX = 0;
503
			double minY = 0;
504
			double maxX = 0;
505
			double maxY = 0;
506
			for (int i = 0; i < tileMatrixList.size(); i++) {
507
				WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixList.get(i);
508
		    	if(!p.isProjected()) {
509
		    		widthMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / (MTS_X_GRADO * 1000);
510
		    		heightMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / (MTS_X_GRADO * 1000);
511
		    	} else {
512
		    		widthMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / 1000;
513
		    		heightMtsTile = (tileMatrix.getScaleDenominator() * tileMatrix.getTileWidth() * 0.28) / 1000;
514
		    	}
515
		    	
516
		    	double h = Math.abs(tileMatrix.getTopLeftCorner()[0] - (tileMatrix.getTopLeftCorner()[0] - (tileMatrix.getMatrixHeight() * heightMtsTile)));
517
		    	Rectangle2D r = new Rectangle2D.Double(
518
		    			tileMatrix.getTopLeftCorner()[1], 
519
		    			tileMatrix.getTopLeftCorner()[0] - h,
520
		    			Math.abs(tileMatrix.getTopLeftCorner()[1] - (tileMatrix.getTopLeftCorner()[1] + (tileMatrix.getMatrixWidth() * widthMtsTile))),
521
		    			h);
522
		    	extentByLevel[i] = new ExtentImpl(r);
523
		    	if(i == 0) {
524
		    		minX = extentByLevel[i].getMin().getX();
525
		    		minY = extentByLevel[i].getMin().getY();
526
		    		maxX = extentByLevel[i].getMax().getX();
527
		    		maxY = extentByLevel[i].getMax().getY();
528
		    	} else {
529
		    		minX = Math.min(minX, extentByLevel[i].getMin().getX());
530
		    		minY = Math.min(minY, extentByLevel[i].getMin().getY());
531
		    		maxX = Math.max(maxX, extentByLevel[i].getMax().getX());
532
		    		maxY = Math.max(maxY, extentByLevel[i].getMax().getY());
533
		    	}
534
			}
535
			bbox = new ExtentImpl(minX, maxY, maxX, minY);
536
		}
537
		return extentByLevel;
538
	}
539
	
540
	public Rectangle2D getLayerExtent(String layerName, String srs) throws RemoteServiceException {
541
		return null;
542
	}
543

  
544
	public RasterProvider load() {
545
		return this;
546
	}
547
	
548
	public boolean isOpen() {
549
		return open;
550
	}
551

  
552
	public void close() {
553
		open = false;
554
	}
555
	
556
	public Transparency getTransparency() {
557
		if(lastFileTransparency == null) {
558
			lastFileTransparency = new DataStoreTransparency();
559
			lastFileTransparency.setTransparencyBand(3);
560
		}
561
		return lastFileTransparency;
562
	}
563

  
564
	public String translateFileName(String fileName) {
565
		return fileName;
566
	}
567

  
568
	public void setView(Extent e) {
569
		viewRequest = e;
570
	}
571

  
572
	public Extent getView() {
573
		return viewRequest;
574
	}
575

  
576
	public double getWidth() {
577
		WMTSDataParameters p = (WMTSDataParameters)parameters;
578
		if (lastWidthRequest <= 0) 
579
			return p.getWidth();
580
		return lastWidthRequest;
581
	}
582

  
583
	public double getHeight() {
584
		WMTSDataParameters p = (WMTSDataParameters)parameters;
585
		if (lastHeightRequest <= 0) 
586
			return p.getHeight();
587
		return lastHeightRequest;
588
	}
589

  
590
	public Object readCompleteLine(int line, int band)
591
		throws InvalidSetViewException, FileNotOpenException, RasterDriverException {
592
		return null;
593
	}
594
	
595
	/**
596
	 * When the remote layer has fixed size this method downloads the file and return its reference. 
597
	 * File layer has in the long side FIXED_SIZE pixels and the bounding box is complete. This file could be
598
	 * useful to build an histogram or calculate statistics. This represents a sample of data.
599
	 * @return
600
	 * @throws RasterDriverException
601
	 */
602
	public File getFileLayer() throws RasterDriverException {
603
		return null;
604
	}
605

  
606
	/**
607
	 * Reads a complete block of data and returns an tridimensional array of the right type. This function is useful
608
	 * to read a file very fast without setting a view. In a WMTS service when the size is fixed then it will read the
609
	 * entire image but when the source hasn't pixel size it will read a sample of data. This set of data will have
610
	 * the size defined in FIXED_SIZE. 
611
	 * 
612
	 * @param pos Posici?n donde se empieza  a leer
613
	 * @param blockHeight Altura m?xima del bloque leido
614
	 * @return Object que es un array tridimendional del tipo de datos del raster. (Bandas X Filas X Columnas)
615
	 * @throws InvalidSetViewException
616
	 * @throws FileNotOpenException
617
	 * @throws RasterDriverException
618
	 */
619
	public Object readBlock(int pos, int blockHeight, double scale) 
620
	throws InvalidSetViewException, FileNotOpenException, RasterDriverException, ProcessInterruptedException {
621
		return null;
622
	}
623
	
624
	public Object getData(int x, int y, int band)
625
		throws InvalidSetViewException, FileNotOpenException, RasterDriverException {
626
		return null;
627
	}
628
	
629
	/**
630
	 * Assigns the list of bands RGB and read a window of data
631
	 * @param rasterBuf
632
	 * @param bandList
633
	 * @param lastFile
634
	 * @param ulx
635
	 * @param uly
636
	 * @param lrx
637
	 * @param lry
638
	 * @return
639
	 * @throws RasterDriverException
640
	 * @throws ProcessInterruptedException
641
	 */
642
	public Buffer getBuffer(Buffer rasterBuf, BandList bandList, File lastFile, 
643
			double ulx, double uly, double lrx, double lry) throws RasterDriverException, ProcessInterruptedException {
644
		return null;
645
	}
646
	
647
	/**
648
	 * Gets the tile matrix from the selected level
649
	 * @param level
650
	 * @return
651
	 */
652
	private WMTSTileMatrix getTileMatrixByLevel(int level) {
653
		level = adjustLevel(level);
654
		
655
		WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
656
		WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
657
		List<WMTSTileMatrixLimits> tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
658
		
659
		WMTSTileMatrixLimits tileMatrixLimits = null;
660
		WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(level);
661
		if(hasGridSubsets()) {
662
			tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(level);
663
			tileMatrix = tileMatrixLimits.getTileMatrix();
664
		}
665
		return tileMatrix;
666
	}
667
	
668
	/**
669
	 * Returns the number of levels
670
	 * @return
671
	 */
672
	public int getZoomLevels() {
673
		WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
674
		WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
675
		if(hasGridSubsets()) {
676
			List<WMTSTileMatrixLimits> tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
677
			return Math.min(tileMatrixSet.getTileMatrix().size(), tileMatrixSetLimits.size());
678
		}
679
		return tileMatrixSet.getTileMatrix().size();
680
		
681
	}
682
	
683
	public Extent getCoordsInTheNearestLevel(Extent extent, int w, int h) {
684
		double[] pixelSizes = getPixelSizeByLevel();
685
		double currentPixelSize = extent.width() / (double)w;
686
		
687
		int level = 0;
688
		for (int i = 0; i < (pixelSizes.length - 1); i++) {
689
			if(currentPixelSize < pixelSizes[i] && currentPixelSize >= pixelSizes[i + 1]) {
690
				level = i + 1;
691
				break;
692
			}
693
		}
694
		
695
		return getZoomLevelCoordinates(level, extent, w, h);
696
	}
697
	
698
	public Extent getCoordsInLevel(Point2D viewCenter, int level, int w, int h) {
699
		WMTSDataParameters p = (WMTSDataParameters)param;
700
		level = adjustLevel(level);
701
		WMTSTileMatrix tileMatrix = getTileMatrixByLevel(level);
702
		
703
		boolean proj = p.isProjected();
704
		
705
		double psX = tileMatrix.getWidthWCTile(proj) / tileMatrix.getTileWidth();
706
		double psY = tileMatrix.getHeightWCTile(proj) / tileMatrix.getTileHeight();
707
		
708
		double ulx = viewCenter.getX() - ((w / 2) * psX);
709
		double uly = viewCenter.getY() - ((h / 2) * psY);
710
		double lrx = ulx + (w * psX);
711
		double lry = uly + (h * psY);
712
		return new ExtentImpl(ulx, uly, lrx, lry);
713
	}
714
	
715
	/**
716
	 * Calculates the extent of a zoom level using other extent as a reference. The new extent is 
717
	 * calculated with the same coordinate at the center. 
718
	 * @param level
719
	 * @param extent
720
	 * @param w
721
	 * @param h
722
	 * @return
723
	 */
724
	public Extent getZoomLevelCoordinates(int level, Extent extent, int w, int h) {
725
		double centerX = extent.getCenterX();
726
		double centerY = extent.getCenterY();
727
		return getCoordsInLevel(new Point2D.Double(centerX, centerY), level, w, h);
728
	}
729
	
730
	/**
731
	 * Returns a list of pixel sizes by level
732
	 * @return
733
	 */
734
	public double[] getPixelSizeByLevel() {
735
		WMTSDataParameters p = (WMTSDataParameters)param;
736
		double[] list = new double[getZoomLevels()];
737
		
738
		for (int i = 0; i < getZoomLevels(); i++) {
739
			WMTSTileMatrix tileMatrix = getTileMatrixByLevel(i);
740
			list[i] = math.adjustDouble(tileMatrix.getWidthWCTile(p.isProjected()) / tileMatrix.getTileWidth());
741
		}
742
		return list;
743
	}
744
	
745
	/**
746
	 * Adjust de level to the range
747
	 * @param level
748
	 * @return
749
	 */
750
	private int adjustLevel(int level) {
751
		if(level < 0)
752
			level = 0;
753
		if(level > getZoomLevels())
754
			level = getZoomLevels();
755
		return level;
756
	}
757
	
758
	public org.gvsig.raster.cache.tile.Tile getTile(DefaultRasterQuery q) throws TileGettingException {
759
		//q.getResolutionLevel(), q.getTileCol(), q.getTileRow(), q.getBBox(), q.getCacheStruct()!
760
		
761
		CacheStruct str = getTileServer().getStruct();
762
		
763
		//1-Selecci?n de WMTSTileMatrixSet por srs
764
		WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
765
		WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
766
		List<WMTSTileMatrixLimits> tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
767
		
768
		WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(q.getResolutionLevel());
769
		if(gridSubsets) {
770
			WMTSTileMatrixLimits tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(q.getResolutionLevel());
771
			tileMatrix = tileMatrixLimits.getTileMatrix();
772
		}
773
		int bufWidth = tileMatrix.getTileWidth();
774
		int bufHeight = tileMatrix.getTileHeight();
775
		
776
		try {
777
			Rectangle2D r = q.getBBox().toRectangle2D();//new Rectangle2D.Double(Math.min(minX, maxX), Math.min(minY, maxY), Math.abs(maxX - minX), Math.abs(maxY - minY));
778
			WMTSStatus status = buildWMTSStatus(r, bufWidth , bufHeight);
779
			
780
			int[] size = str.getTileSizeByLevel(q.getResolutionLevel());
781
			WMTSTile tile = WMTSOGCLocator.getManager().createTile(
782
					size, 
783
					new int[]{q.getTileRow(), q.getTileCol()}, 
784
					new double[]{q.getBBox().getULX(), q.getBBox().getULY(), q.getBBox().getLRX(), q.getBBox().getLRY()});
785
			
786
			File file = getOGCClient().getTile(status, null);
787
			tile.setFile(file);
788
			//Creamos un BandList con todas las bandas del fichero
789
			BandList bandList = new BandListImpl();
790
			for(int i = 0; i < getBandCount(); i++) {
791
				try {
792
					DatasetBand band = new DatasetBandImpl(getURIOfFirstProvider(), i, getDataType()[i], getBandCount());
793
					bandList.addBand(band);
794
				} catch(BandNotFoundInListException e) {
795
					//No a?adimos la banda
796
				}
797
			}
798
			return drawTile(tile, null, bandList);
799
		} catch (WMTSException e) {
800
			throw new TileGettingException("Error getting tiles", e);
801
		} catch (ServerErrorException e) {
802
			throw new TileGettingException("Error getting tiles", e);
803
		} catch (RasterDriverException e) {
804
			throw new TileGettingException("Error getting tiles", e);
805
		}
806
	}
807
	
808
	public void getWindow(Extent ex, int bufWidth, int bufHeight, 
809
			BandList bandList, TileListener listener, TaskStatus taskStatus) throws ProcessInterruptedException, RasterDriverException {
810
		Rectangle2D r = ex.toRectangle2D();//new Rectangle2D.Double(Math.min(minX, maxX), Math.min(minY, maxY), Math.abs(maxX - minX), Math.abs(maxY - minY));
811
		WMTSStatus status = buildWMTSStatus(r, bufWidth, bufHeight);
812
		request(status, bandList, listener, requestType);
813
	}
814
	
815
	public Buffer getWindow(Extent extent, int bufWidth, int bufHeight, 
816
			BandList bandList, Buffer rasterBuf, boolean adjustToExtent, TaskStatus taskStatus) throws ProcessInterruptedException, RasterDriverException {
817
		Rectangle2D r = extent.toRectangle2D();//new Rectangle2D.Double(Math.min(ulx, lrx), Math.min(lry, uly), Math.abs(lrx - ulx), Math.abs(uly - lry));
818
		WMTSStatus status = buildWMTSStatus(r, bufWidth, bufHeight);
819
		org.gvsig.raster.cache.tile.Tile[] tileList = request(status, bandList, null, requestType);
820
		MemoryMatrixBuffer matrixBuffer = new MemoryMatrixBuffer(tileList);
821
		return matrixBuffer.getWindow(extent, rasterBuf);
822
	}
823
	
824
	public Buffer getWindow(Extent extent, BandList bandList, Buffer rasterBuf, TaskStatus taskStatus) 
825
		throws ProcessInterruptedException, RasterDriverException {
826
		lastWidthRequest = rasterBuf.getWidth();
827
		lastHeightRequest = rasterBuf.getHeight();
828
		Rectangle2D r = extent.toRectangle2D();//new Rectangle2D.Double(Math.min(ulx, lrx), Math.min(lry, uly), Math.abs(lrx - ulx), Math.abs(uly - lry));
829
		WMTSStatus status = buildWMTSStatus(r, lastWidthRequest, lastHeightRequest);
830
		org.gvsig.raster.cache.tile.Tile[] tileList = request(status, bandList, null, requestType);
831
		MemoryMatrixBuffer matrixBuffer = new MemoryMatrixBuffer(tileList);
832
		return matrixBuffer.getWindow(extent, rasterBuf);
833
	}
834

  
835
	public Buffer getWindow(double ulx, double uly, double w, double h, 
836
			BandList bandList, Buffer rasterBuf, boolean adjustToExtent, TaskStatus taskStatus) throws ProcessInterruptedException, RasterDriverException {
837
		lastWidthRequest = rasterBuf.getWidth();
838
		lastHeightRequest = rasterBuf.getHeight();
839
		Rectangle2D r = new Rectangle2D.Double(ulx, uly - h, w, h);
840
		WMTSStatus status = buildWMTSStatus(r, lastWidthRequest, lastHeightRequest);
841
		org.gvsig.raster.cache.tile.Tile[] tileList = request(status, bandList, null, requestType);
842
		MemoryMatrixBuffer matrixBuffer = new MemoryMatrixBuffer(tileList);
843
		return matrixBuffer.getWindow(new ExtentImpl(ulx, uly, ulx + w, uly - h), rasterBuf);
844
	}
845

  
846
	public Buffer getWindow(int x, int y, int w, int h, BandList bandList, Buffer rasterBuf, TaskStatus status) throws ProcessInterruptedException, RasterDriverException {
847
		lastWidthRequest = rasterBuf.getWidth();
848
		lastHeightRequest = rasterBuf.getHeight();
849
		return null;
850
	}
851
	
852
	/**
853
	 * Gets the information from a point 
854
	 * @param wcx
855
	 * @param wcy
856
	 * @param level
857
	 * @return
858
	 * @throws RasterDriverException
859
	 */
860
	public String getFeatureInfo(double wcx, double wcy, int level) throws RasterDriverException {
861
		PointInfo pointInfo = new PointInfo(new Point2D.Double(wcx, wcy));
862
		pointInfo.level = level;
863
		getTileInfo(pointInfo);
864
		
865
		WMTSClient ogcClient = null;
866
		try {
867
			ogcClient = getOGCClient();
868
			lastStatus.setTileRow((int)pointInfo.tile.getX());
869
			lastStatus.setTileCol((int)pointInfo.tile.getY());
870
			
871
			String fi = ogcClient.getFeatureInfo(lastStatus, (int)pointInfo.pixelInTile.getX(), (int)pointInfo.pixelInTile.getY(), null);
872
			return fi;
873
		} catch (WMTSException e) {
874
			throw new RasterDriverException("Error getting the connector object", e);
875
		} /*catch (ServerErrorException e) {
876
			throw new RasterDriverException("Error getting the connector object", e);
877
		}*/
878
	}
879
	
880
	/**
881
	 * Gets a tile position from a world coordinates point and a resolution level
882
	 * @param point
883
	 * @param level
884
	 * @return An array with two elements. The first is the row and the second the column
885
	 * of the tile in the tile matrix
886
	 */
887
	private void getTileInfo(PointInfo pointInfo) {
888
		WMTSDataParameters p = (WMTSDataParameters)param;
889
		
890
		WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
891
		WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
892
		List<WMTSTileMatrixLimits> tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
893
		
894
		WMTSTileMatrixLimits tileMatrixLimits = null;
895
		WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(pointInfo.level);
896
		if(hasGridSubsets()) {
897
			tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(pointInfo.level);
898
			tileMatrix = tileMatrixLimits.getTileMatrix();
899
		}
900
		
901
		List<WMTSTile> tiles = null;
902
		if(hasGridSubsets())
903
			tiles = tileMatrix.contains(p.isProjected(), tileMatrixLimits, pointInfo.worldCoord, getExtent().toRectangle2D());
904
		else
905
			tiles = tileMatrix.contains(p.isProjected(), pointInfo.worldCoord, getExtent().toRectangle2D());
906
		
907
		//Tile row and column
908
		pointInfo.tile = new Point2D.Double(tiles.get(0).getRow(), tiles.get(0).getCol());
909
		
910
		//Desplazamiento en pixels dentro del tile
911
		Point2D rasterPoint = tiles.get(0).worldToRaster(pointInfo.worldCoord);
912
		pointInfo.pixelInTile = new Point2D.Double(rasterPoint.getX(), rasterPoint.getY());
913
	}
914
	
915
	/**
916
	 * Builds the WMTSStatus object using the parameters and the request bounding box. 
917
	 * @param r
918
	 * @param bufWidth
919
	 * @return
920
	 * @throws RasterDriverException
921
	 */
922
	public WMTSStatus buildWMTSStatus(Rectangle2D r, int bufWidth, int bufHeight) throws RasterDriverException {
923
		WMTSDataParameters p = (WMTSDataParameters)param;
924
		
925
		//Mantiene actualizados los par?metros del WMTSStoreParameters con la ?ltima petici?n hecha
926
		p.setExtent(r);
927
		p.setWidth(bufWidth);
928
		p.setHeight(bufHeight);
929
		
930
		lastWidthRequest = bufWidth;
931
		lastHeightRequest = bufHeight;
932
		
933
		//1-Selecci?n de WMTSTileMatrixSet por srs
934
		WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
935
		WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
936
		List<WMTSTileMatrixLimits> tileMatrixSetLimits = tileMatrixSetLink.getTileMatrixLimits();
937
		int initialLevel = p.getLayer().getInitialLevel(tileMatrixSet.getIdentifier());
938
		
939
		//Esto hace lo mismo que getScale y getLevelFromScale
940
		/*int level = 0;
941
		double[] pixelSizes = getPixelSizeByLevel();
942
		double psViewPort = math.adjustDouble(r.getWidth() / (double)bufWidth);
943
		for (int i = 0; i < pixelSizes.length - 1; i++) {
944
			if(psViewPort <= pixelSizes[i] && psViewPort > pixelSizes[i + 1]) {
945
				level = i;
946
				break;
947
			}
948
		}*/
949
		
950
		//2-Calculo de la escala
951
		double scale = getScale(r, bufWidth);
952
		
953
		//3-Selecci?n del nivel a partir de la escala
954
		int level = getLevelFromScale(scale, tileMatrixSet);
955
		
956
		//Para evitar que se salga del array si la capa tiene menos niveles que el tilematrixset
957
		int dif = 0;
958
		if(gridSubsets)
959
			dif = (level - initialLevel) >= tileMatrixSetLimits.size() ?  (level - initialLevel) - tileMatrixSetLimits.size() + 1 : 0;
960
		
961
		//4-Obtenemos la matriz de tiles y los l?mites si tiene subsets
962
		@SuppressWarnings("unused")
963
		WMTSTileMatrixLimits tileMatrixLimits = null;
964
		WMTSTileMatrix tileMatrix = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(level - dif);
965
		if(gridSubsets)
966
			tileMatrixLimits = (WMTSTileMatrixLimits)tileMatrixSetLimits.get(level - initialLevel - dif);
967
		
968
		//5-Selecci?n de tiles que entran en esta bounding box
969
		List<WMTSTile> tiles = null;
970
		/*if(gridSubsets)
971
			tiles = tileMatrix.intersects(p.isProjected(), tileMatrixLimits, r, getExtent().toRectangle2D());
972
		else*/
973
		Extent[] extList = getExtentByResolutionLevel();
974
		tiles = tileMatrix.intersects(p.isProjected(), r, extList[level].toRectangle2D());
975
		
976
		//6-Petici?n
977
		WMTSStatus status = null;
978
		try {
979
			status = getOGCClient().createStatus();
980
		} catch (WMTSException e) {
981
			throw new RasterDriverException("Error creating WMTSStatus", e);
982
		}
983
		status.setTileList(tiles);
984
		status.setLayer(p.getLayer().getIdentifier());//.substring(p.getLayer().getIdentifier().indexOf("_") + 1));
985
		status.setFormat(p.getImageFormat());
986
		status.setInfoFormat(p.getInfoFormat());
987
		status.setStyle(p.getStyle() != null ? p.getStyle().getIdentifier() : "");
988
		status.setTileMatrixSet(tileMatrixSet.getIdentifier());
989
		status.setTileMatrix(tileMatrix.getIdentifier());
990
		status.setLevel(level - dif);
991
		this.lastStatus = status;
992
		
993
		return status;
994
	}
995
	
996
	/**
997
	 * Gets the resolution level from the real coordinates
998
	 * @param r
999
	 * @param 
1000
	 * @return
1001
	 * @throws RasterDriverException
1002
	 */
1003
	public int getLevelFromRealCoords(Rectangle2D r, int width) throws RasterDriverException {
1004
		double scale = getScale(r, width);
1005
		WMTSTileMatrixSetLink tileMatrixSetLink = getTileMatrixSetLink();
1006
		WMTSTileMatrixSet tileMatrixSet = tileMatrixSetLink.getTileMatrixSet();
1007
		return getLevelFromScale(scale, tileMatrixSet);
1008
	}
1009
	
1010
	/**
1011
	 * Gets the resolution level from the scale
1012
	 * @param scale
1013
	 * @param tileMatrixSet
1014
	 * @return
1015
	 * @throws RasterDriverException
1016
	 */
1017
	public int getLevelFromScale(double scale, WMTSTileMatrixSet tileMatrixSet) throws RasterDriverException {
1018
		//Recorremos los tileMatrix para obtener la escala m?s aproximada
1019
		int levelModifier = 0;
1020
		scale = math.adjustDouble(scale);
1021
		try {
1022
			for (int resolutionLevel = 0; resolutionLevel < tileMatrixSet.getTileMatrix().size(); resolutionLevel++) {
1023
				WMTSTileMatrix tm = (WMTSTileMatrix)tileMatrixSet.getTileMatrix().get(resolutionLevel);
1024
				double scaleDenominator = math.adjustDouble(tm.getScaleDenominator());
1025
				if(scale >= scaleDenominator) {
1026
					return Math.max(resolutionLevel + levelModifier, 0);
1027
				}
1028
			}
1029
		} catch (IndexOutOfBoundsException e) {
1030
			throw new RasterDriverException("Error in this resolution level", e);
1031
		}
1032
		return 0;
1033
	}
1034
	
1035
	/**
1036
	 * Get the tile matrix set using the crs
1037
	 * @param srs
1038
	 * @return
1039
	 */
1040
	public WMTSTileMatrixSetLink getTileMatrixSetLink() {
1041
		WMTSDataParameters p = (WMTSDataParameters)param;
1042
		List<WMTSTileMatrixSetLink> tileMatrixSetLinkList = p.getLayer().getTileMatrixSetLink();
1043
		for (int i = 0; i < tileMatrixSetLinkList.size(); i++) {
1044
			WMTSTileMatrixSetLink tileMatrixSetLink = (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(i);
1045
			String srsTileSet = tileMatrixSetLink.getTileMatrixSet().getSupportedCRS();
1046
			if(srsTileSet.compareTo(p.getSRSCode()) == 0) {
1047
				return tileMatrixSetLink;
1048
			}
1049
		}
1050
		if(tileMatrixSetLinkList != null && tileMatrixSetLinkList.size() > 0)
1051
			return (WMTSTileMatrixSetLink)tileMatrixSetLinkList.get(0);
1052
		return null;
1053
	}
1054
	
1055
	/**
1056
	 * Gets the scale using the extent and the width in pixels.
1057
	 * @param r
1058
	 * @param width
1059
	 * @return
1060
	 */
1061
	private double getScale(Rectangle2D r, int width) {
1062
		WMTSDataParameters p = (WMTSDataParameters)param;
1063
		if(!p.isProjected()) {
1064
			return (r.getWidth() * MTS_X_GRADO) / (width * 0.00028);
1065
		} else
1066
			return (r.getWidth()) / (width * 0.00028);
1067
	}
1068
	
1069
	/**
1070
	 * Throw a request
1071
	 * @param status
1072
	 * @param bandList
1073
	 * @param listener
1074
	 * @param alphaBandNumber 
1075
	 * @return returns a buffer if the listener is null. In any other case it return null.
1076
	 * @throws RasterDriverException 
1077
	 * @throws ProcessInterruptedException 
1078
	 */
1079
	private synchronized org.gvsig.raster.cache.tile.Tile[] request(
1080
			WMTSStatus status, BandList bandList, TileListener listener, int requestType) throws RasterDriverException, ProcessInterruptedException {
1081
		//WMTSDataParameters p = (WMTSDataParameters)param;
1082
		WMTSClient ogcClient = null;
1083
		try {
1084
			ogcClient = getOGCClient();
1085
		} catch (WMTSException e) {
1086
			throw new RasterDriverException("Error getting the connector object", e);
1087
		}
1088
		
1089
		if(ogcClient == null)
1090
			throw new RasterDriverException("Error getting the connector object");
1091
		
1092
		List<WMTSTile> tiles = status.getTileList();
1093
		
1094
		TilePipe pipe = new TilePipe();
1095
		//TilePipe2 pipe = new TilePipe2();
1096
		//TileThreadPool pool = null;
1097
		
1098
		//Caso 1: Lanza un thread que gestiona que no se lancen muchos threads a la vez
1099
		if(requestType == LIMITED_THREADS) {
1100
			RequestThreadManager threadManager = new RequestThreadManager(pipe, tiles, status);
1101
			pipe.setRequestManager(threadManager);
1102
			threadManager.start();
1103
		//Caso 2: Lanza todos los threads
1104
		} else if(requestType == UNLIMITED_THREADS) {
1105
			for (int i = 0; i < tiles.size(); i++) {
1106
				WMTSTile tile = tiles.get(i);
1107
				WMTSStatus statusCopy = status.cloneStatus();
1108
				statusCopy.setTileRow(tile.getRow());
1109
				statusCopy.setTileCol(tile.getCol());
1110
				new RequestTileLauncher(pipe, statusCopy, tile).start();
1111
			}
1112
		}
1113
		
1114
		org.gvsig.raster.cache.tile.Tile[] tileList = new org.gvsig.raster.cache.tile.Tile[tiles.size()]; 
1115
		
1116
		if(requestType == LIMITED_THREADS || requestType == UNLIMITED_THREADS) {
1117
			int nCollected = 0;
1118
			while (nCollected < tiles.size()) {
1119
				WMTSTile tile = pipe.getTile();
1120
				tileList[nCollected] = drawTile(tile, listener, bandList);
1121
				nCollected ++;
1122
			}
1123
		}
1124
		
1125
		if(requestType == SEQUENTIAL) {
1126
			for (int i = 0; i < tiles.size(); i++) {
1127
				WMTSTile tile = tiles.get(i);
1128
				status.setTileRow(tile.getRow());
1129
				status.setTileCol(tile.getCol());
1130
				//TODO:Cancelaci?n
1131
				try {
1132
					File file = ogcClient.getTile(status, null);
1133
					tile.setFile(file);
1134
					tileList[i] = drawTile(tile, listener, bandList);
1135
				} catch (WMTSException e) {
1136
					throw new RasterDriverException("Error getting tiles", e);
1137
				} catch (ServerErrorException e) {
1138
					throw new RasterDriverException("Error getting tiles", e);
1139
				}
1140
			}
1141
		}
1142
		if(listener != null) 
1143
			listener.endReading();
1144
		
1145
		return tileList;
1146
	}
1147
	
1148
	/**
1149
	 * Reads a tile with gdal and calls the method nextBuffer
1150
	 * @param tile
1151
	 * @param listener
1152
	 * @param bandList
1153
	 * @return
1154
	 * @throws RasterDriverException
1155
	 */
1156
	private synchronized org.gvsig.raster.cache.tile.Tile drawTile(WMTSTile tile, TileListener listener, BandList bandList) throws RasterDriverException {
1157
		WMTSDataParameters p = (WMTSDataParameters)param;
1158
		try {
1159
			String serverName = bandList.getBand(0).getFileName();
1160
			for (int j = 0; j < bandList.getBandCount(); j++) {
1161
				bandList.getBand(j).setFileName(tile.getFile().getPath());
1162
			}
1163
			
1164
			DefaultRasterProvider driver = DefaultProviderServices.loadProvider(tile.getFile());
1165
			colorTable = driver.getColorTable();
1166
			bandCount = driver.getBandCount();
1167
			lastFileTransparency = (DataStoreTransparency)driver.getTransparency();
1168
			Buffer rasterBuf = DefaultRasterManager.getInstance().createBuffer(
1169
					getDataType()[0], 
1170
					tile.getWidthPx(), 
1171
					tile.getHeightPx(), 
1172
					3, 
1173
					true);
1174
			
1175
			DefaultRasterQuery q = (DefaultRasterQuery)RasterLocator.getManager().createQuery();
1176
			q.setAreaOfInterest(0, 0, tile.getWidthPx(), tile.getHeightPx());
1177
			q.setBandList(bandList);
1178
			q.setBuffer(rasterBuf);
1179
			Buffer buf = driver.getDataSet(q);
1180
			
1181
			buf.setDataExtent(new Rectangle2D.Double(
1182
					Math.min(tile.getULX(), tile.getLRX()), 
1183
					Math.min(tile.getULY(), tile.getLRY()), 
1184
					Math.abs(tile.getULX() - tile.getLRX()), 
1185
					Math.abs(tile.getULY() - tile.getLRY())));
1186
			
1187
			Buffer alphaBand = null;
1188
			if(p.getAlphaBand() != -1 && listener != null && p.getAlphaBand() < bandCount) {
1189
				alphaBand = DefaultRasterManager.getInstance().createBuffer(
1190
						getDataType()[0], 
1191
						tile.getWidthPx(), 
1192
						tile.getHeightPx(), 
1193
						1, 
1194
						true);
1195
				int[] oldDB = bandList.getDrawableBands();
1196
				bandList.setDrawableBands(new int[]{p.getAlphaBand()});
1197
				q.setBandList(bandList);
1198
				q.setBuffer(alphaBand);
1199
				alphaBand = driver.getDataSet(q);
1200
				bandList.setDrawableBands(oldDB);
1201
			}
1202

  
1203
			for (int j = 0; j < bandList.getBandCount(); j++) {
1204
				bandList.getBand(j).setFileName(serverName);
1205
			}
1206

  
1207
			driver.close();
1208

  
1209

  
1210
			TileCacheManager m = TileCacheLocator.getManager();
1211
			org.gvsig.raster.cache.tile.Tile t = m.createTile(-1, tile.getRow(), tile.getCol());
1212
			t.setData(new Object[]{buf, alphaBand});
1213
			t.setUl(new Point2D.Double(tile.getULX(), tile.getULY()));
1214
			t.setLr(new Point2D.Double(tile.getLRX(), tile.getLRY()));
1215
			t.setDownloaderParams("AffineTransform", getAffineTransform());
1216
			t.setDownloaderParams("Tiling", new Boolean(true));
1217
			if(listener != null) 
1218
				listener.tileReady(t);
1219
			else 
1220
				return t;
1221

  
1222
		} catch (ProcessInterruptedException e) {
1223
		} catch (TileGettingException e) {
1224
			throw new RasterDriverException("Error throwing a tile", e);
1225
		} catch (ProviderNotRegisteredException e) {
1226
			throw new RasterDriverException("Error throwing a tile", e);
1227
		} catch (InitializeException e) {
1228
			throw new RasterDriverException("Error throwing a tile", e);
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff