Statistics
| Revision:

gvsig-raster / org.gvsig.raster.wms / trunk / org.gvsig.raster.wms / org.gvsig.raster.wms.app.wmsclient / src / main / java / org / gvsig / raster / wms / app / wmsclient / layer / FLyrWMS.java @ 3767

History | View | Annotate | Download (38.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
 
23
package org.gvsig.raster.wms.app.wmsclient.layer;
24

    
25
import java.awt.Dimension;
26
import java.awt.Graphics2D;
27
import java.awt.Image;
28
import java.awt.Point;
29
import java.awt.Rectangle;
30
import java.awt.geom.AffineTransform;
31
import java.awt.geom.NoninvertibleTransformException;
32
import java.awt.geom.Point2D;
33
import java.awt.geom.Rectangle2D;
34
import java.awt.image.BufferedImage;
35
import java.lang.ref.WeakReference;
36
import java.util.ArrayList;
37
import java.util.HashMap;
38
import java.util.Iterator;
39
import java.util.List;
40
import java.util.Vector;
41
import java.util.prefs.Preferences;
42

    
43
import javax.print.attribute.PrintRequestAttributeSet;
44
import javax.swing.JOptionPane;
45

    
46
import org.cresques.cts.ICoordTrans;
47
import org.cresques.cts.IProjection;
48
import org.gvsig.andami.PluginServices;
49
import org.gvsig.fmap.dal.DALLocator;
50
import org.gvsig.fmap.dal.DataManager;
51
import org.gvsig.fmap.dal.DataParameters;
52
import org.gvsig.fmap.dal.DataStore;
53
import org.gvsig.fmap.dal.DataStoreParameters;
54
import org.gvsig.fmap.dal.coverage.RasterLocator;
55
import org.gvsig.fmap.dal.coverage.RasterManager;
56
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
57
import org.gvsig.fmap.dal.coverage.datastruct.ViewPortData;
58
import org.gvsig.fmap.dal.coverage.exception.FilePaletteException;
59
import org.gvsig.fmap.dal.coverage.exception.InfoByPointException;
60
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
61
import org.gvsig.fmap.dal.coverage.exception.QueryException;
62
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
63
import org.gvsig.fmap.dal.coverage.grid.RasterFilter;
64
import org.gvsig.fmap.dal.coverage.store.RasterDataStore;
65
import org.gvsig.fmap.dal.coverage.store.parameter.RasterDataParameters;
66
import org.gvsig.fmap.dal.coverage.store.parameter.RemoteStoreParameters;
67
import org.gvsig.fmap.dal.coverage.store.parameter.TileDataParameters;
68
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
69
import org.gvsig.fmap.dal.exception.DataException;
70
import org.gvsig.fmap.dal.exception.InitializeException;
71
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
72
import org.gvsig.fmap.dal.exception.ReadException;
73
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
74
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
75
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
76
import org.gvsig.fmap.geom.GeometryLocator;
77
import org.gvsig.fmap.geom.GeometryManager;
78
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
79
import org.gvsig.fmap.geom.primitive.Envelope;
80
import org.gvsig.fmap.mapcontext.ViewPort;
81
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
82
import org.gvsig.fmap.mapcontext.exceptions.UnsupportedVersionLayerException;
83
import org.gvsig.fmap.mapcontext.layers.FLayer;
84
import org.gvsig.fmap.mapcontext.layers.Tiling;
85
import org.gvsig.fmap.mapcontext.layers.operations.ComposedLayer;
86
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
87
import org.gvsig.gui.beans.Messages;
88
import org.gvsig.raster.fmap.layers.DefaultFLyrRaster;
89
import org.gvsig.raster.fmap.layers.IRasterLayerActions;
90
import org.gvsig.raster.fmap.layers.NotAvailableStateException;
91
import org.gvsig.raster.fmap.legend.ImageLegend;
92
import org.gvsig.raster.util.CancelTaskImpl;
93
import org.gvsig.raster.wms.app.wmsclient.wmc.WebMapContextTags;
94
import org.gvsig.raster.wms.app.wmsclient.wmc.XmlBuilder;
95
import org.gvsig.raster.wms.io.RemoteWMSStyle;
96
import org.gvsig.raster.wms.io.WMSDataParameters;
97
import org.gvsig.raster.wms.io.WMSLayerNode;
98
import org.gvsig.raster.wms.io.WMSServerExplorer;
99
import org.gvsig.raster.wms.io.WMSServerExplorerParameters;
100
import org.gvsig.tools.ToolsLocator;
101
import org.gvsig.tools.dynobject.DynObjectSet;
102
import org.gvsig.tools.dynobject.DynStruct;
103
import org.gvsig.tools.persistence.PersistenceManager;
104
import org.gvsig.tools.task.Cancellable;
105
import org.gvsig.tools.task.SimpleTaskStatus;
106
import org.gvsig.tools.task.TaskStatusManager;
107
import org.slf4j.Logger;
108
import org.slf4j.LoggerFactory;
109

    
110

    
111

    
112
/**
113
 * FMap's WMS Layer class.
114
 *
115
 * Las capas WMS son tileadas para descargarlas del servidor. Esto quiere decir que
116
 * est?n formadas por multiples ficheros raster. Por esto la fuente de datos raster (IRasterDatasource)
117
 * de la capa FLyrWMS es un objeto de tipo CompositeDataset. Este objeto est? compuesto por un array
118
 * bidimensional de MultiRasterDataset. Cada uno de los MultiRasterDataset corresponde con un tile
119
 * salvado en disco. Estos MultiRasterDataset se crean cada vez que se repinta ya que en WMS a cada
120
 * zoom varian los ficheros fuente. La secuencia de creaci?n de un CompositeDataset ser?a la siguiente:
121
 * <UL>
122
 * <LI>Se hace una petici?n de dibujado por parte del usuario llamando al m?todo draw de FLyrWMS</LI>
123
 * <LI>Se tilea la petici?n</LI>
124
 * <LI>Cada tile se dibuja abriendo una FLyerRaster para ese tile</LI>
125
 * <LI>Si es el primer dibujado se guarda una referencia en la capa WMS a las propiedades de renderizado, orden de bandas,
126
 * transparencia, filtros aplicados, ...</LI>
127
 * <LI>Si no es el primer dibujado se asignan las propiedades de renderizado cuya referencia se guarda en la capa WMS</LI>
128
 * <LI>Se guarda el MultiRasterDataset de cada tile</LI>
129
 * <LI>Al acabar todos los tiles creamos un CompositeDataset con los MultiRasterDataset de todos los tiles</LI>
130
 * <LI>Asignamos a la capa la referencia de las propiedades de renderizado que tenemos almacenadas. De esta forma si hay
131
 * alguna modificaci?n desde el cuadro de propiedades ser? efectiva sobre los tiles que se dibujan.</LI>
132
 * </UL>
133
 *
134
 *
135
 * @author Jaume Dominguez Faus
136
 *
137
 */
138
@SuppressWarnings("deprecation")
139
public class FLyrWMS extends DefaultFLyrRaster {
140
        public static final String           PERSISTENT_NAME           = "FLyrWMS_Persistent";
141
        public static final String           PERSISTENT_DESCRIPTION    = "FLyrWMS Persistent Definition";
142
        
143
        private static final GeometryManager geomManager               = GeometryLocator.getGeometryManager();
144
        private static final Logger          logger                    = LoggerFactory.getLogger(FLyrWMS.class);
145
        private boolean                                          mustSplitRequest          = false;
146
        private final int                                          maxTileDrawWidth          = 1023;
147
        private final int                                          maxTileDrawHeight         = 1023;
148
        private final int                                          maxTilePrintWidth         = 1023;
149
        private final int                                          maxTilePrintHeight        = 1023;
150
        private List<WeakReference<Thread>>         disableUpdateDrawVersion;
151
        //private Envelope                                         fullEnvelope              = null;
152
        private boolean                                                 firstLoad                 = false;
153
        private RasterManager                rManager                  = RasterLocator.getManager();
154
        //private WMSServerExplorer            explorer                  = null;
155
        private boolean                      deleteCache               = false;
156

    
157
        public FLyrWMS() {
158
                super();
159
                this.updateDrawVersion();
160
                try {
161
                        enableAwake();
162
                } catch (NotAvailableStateException e) {
163
                        logger.error("Fallo el estado de open. Closed=" + isClosed() + " Awake=" + isAwake(), this, e);
164
                }
165
        }
166
        
167
   public FLyrWMS(DataStoreParameters dataStoreParameters) throws Exception {
168
        this();
169
        //Create the explorer and connect
170
        DataManager dataManager = DALLocator.getDataManager();
171
        WMSServerExplorerParameters explorerParams = (WMSServerExplorerParameters) 
172
               dataManager.createServerExplorerParameters(WMSServerExplorer.NAME);
173
        explorerParams.setHost((String)dataStoreParameters.getDynValue("uri"));        
174
        WMSServerExplorer wmsServerExplorer = 
175
            (WMSServerExplorer) dataManager.openServerExplorer(WMSServerExplorer.NAME, explorerParams);
176
        wmsServerExplorer.connect(null, ((RemoteStoreParameters)dataStoreParameters).isDeletingCache());
177
        
178
        //Set the parameters
179
        setParameters((WMSDataParameters)dataStoreParameters);
180
        setExplorer(wmsServerExplorer);
181
    }
182
        
183
        public static DataStore createDataStore(String host, IProjection srs) throws InitializeException {
184
                DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
185
                RasterDataParameters params = null;
186
                try {
187
                        params = (RasterDataParameters)dataman.createServerExplorerParameters(WMSServerExplorer.NAME);
188
                } catch (InitializeException e) {
189
                        return null;
190
                } catch (ProviderNotRegisteredException e) {
191
                        return null;
192
                }
193
                params.setURI(host);
194
                params.setSRS(srs);
195
                
196
                try {
197
                        return dataman.openStore(params.getDataStoreName(), params);
198
                } catch (ValidateDataParametersException e) {
199
                        throw new InitializeException(e);
200
                } catch (ProviderNotRegisteredException e) {
201
                        throw new InitializeException(e);
202
                }
203
        }
204

    
205
        public void setDataStore(DataStore dataStore) throws LoadLayerException {
206
                this.dataStore = (RasterDataStore) dataStore;
207
                try {
208
                        this.dataStore.isOpen();
209
                        if(!isOpen())
210
                                enableOpen();
211
                } catch (NotAvailableStateException e) {
212
                        logger.error("Fallo el estado de open. Closed=" + isClosed() + " Awake=" + isAwake(), this, e);
213
                }
214
                setProjection(this.dataStore.getProjection());
215
        }
216

    
217
        /**
218
         * It choose the best format to load different maps if the server
219
         * supports it. This format could be png, because it supports
220
         * transparency.
221
         * @param formats
222
         * Arraywith all the formats supported by the server
223
         * @return
224
         */
225
        @SuppressWarnings("unused")
226
        private String getGreatFormat(Vector<String> formats){
227
                for (int i = 0 ; i < formats.size() ; i++){
228
                        String format = (String) formats.get(i);
229
                        if (format.equals("image/jpg")){
230
                                return format;
231
                        }
232
                        if (format.equals("image/jpeg")){
233
                                return format;
234
                        }
235
                }
236
                return (String)formats.get(0);
237
        }
238
        
239
        public static void registerPersistent() {
240
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
241
                DynStruct definition = manager.getDefinition("FLyrWMS_Persistent");
242
                if( definition == null ) {
243
                        if (manager.getDefinition(DefaultFLyrRaster.class) == null) {
244
                                DefaultFLyrRaster.registerPersistence();
245
                        }
246

    
247
                        definition = manager.addDefinition(
248
                                        FLyrWMS.class,
249
                                        "FLyrWMS_Persistent",
250
                                        "FLyrWMS Persistent Definition",
251
                                        null, 
252
                                        null
253
                        );
254
                        
255
                        definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE, DefaultFLyrRaster.PERSISTENT_NAME);
256
                }
257

    
258
                DefaultFLyrRaster.registerPersistence(definition);
259
        }
260
        
261
        public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
262
                        Cancellable cancel, double scale) throws ReadException {
263
                TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
264
                SimpleTaskStatus taskStatus = new RasterTaskStatus("Drawing " + getName() + "...", cancel);
265
                manager.add(taskStatus);
266
                taskStatus.setAutoremove(true);
267
                splitRequestCalculation(viewPort.getImageWidth(), viewPort.getImageHeight());
268
                
269
                if(!firstLoad) {
270
                        try {
271
                                initFilters();
272
                                try {
273
                                        if(!isOpen())
274
                                                enableOpen();
275
                                } catch (NotAvailableStateException e) {
276
                                        throw new ReadException("Fallo el estado de open. Closed=" + isClosed() + " Awake=" + isAwake(), e);
277
                                }
278
                        } catch (FilePaletteException e) {
279
                                logger.error(e.getMessage(), this, e);
280
                        }
281
                        firstLoad = true;
282
                }
283
                
284
                enableStopped();
285
                
286
                if(recalcLevel) {
287
                        double pixelSize = viewPort.getEnvelope().getLength(0) / (double)viewPort.getImageWidth();
288
                        zoomLevel = dataStore.getNearestLevel(pixelSize);
289
                }
290
                recalcLevel = true;
291

    
292
                if (isWithinScale(scale)) {
293

    
294
                        if(mustSplitRequest) {
295
                                Point2D p = viewPort.getOffset();
296
                                Rectangle r = new Rectangle((int) p.getX(), (int) p.getY(), viewPort.getImageWidth(), viewPort.getImageHeight());
297
                                Tiling tiles = new Tiling(maxTileDrawWidth, maxTileDrawHeight, r);
298
                                tiles.setAffineTransform((AffineTransform) viewPort.getAffineTransform().clone());
299

    
300
                                for (int tileNr = 0; tileNr < tiles.getNumTiles(); tileNr++) {
301
                                        // drawing part
302
                                        try {
303
                                                ViewPort vp = tiles.getTileViewPort(viewPort, tileNr);
304
                                                drawTile(g, vp, taskStatus, scale);
305
                                        } catch (LoadLayerException e) {
306
                                                throw new ReadException(e.getMessage(), e);
307
                                        } catch (NoninvertibleTransformException e) {
308
                                                throw new ReadException(e.getMessage(), e);
309
                                        }
310
                                }
311
                        } else {
312
                                try {
313
                                        drawTile(g, viewPort, taskStatus, scale);
314
                                } catch (LoadLayerException e) {
315
                                        setAvailable(false);
316
                                        logger.error("Server error:" + e.getMessage(), e);
317
                                }
318
                        }
319
                }
320
                disableStopped();
321
        }
322
        
323
                
324
        /**
325
         * This is the method used to draw a tile in a WMS mosaic layer.
326
         * @throws LoadLayerException
327
         * @throws ReadDriverException
328
         * @return true when a tile has been painted
329
         */
330
        private void drawTile(Graphics2D g, ViewPort vp, SimpleTaskStatus taskStatus, double scale) throws LoadLayerException, ReadException {
331
                // Compute the query geometry
332
                // 1. Check if it is within borders
333
                Envelope layerEnv = getFullEnvelope();
334
                Envelope vpEnv = vp.getAdjustedEnvelope();
335
                if (!vpEnv.intersects(layerEnv)) {
336
                        return;
337
                }
338
                try {
339
                        Rectangle2D vpRect = getRectable2DFromEnvelope(vpEnv);
340
                        Rectangle2D layerRect = getRectable2DFromEnvelope(layerEnv);
341
                        // 2. Intersect layer and viewport extents to get the area of interest
342
                        Rectangle2D requestedRect = new Rectangle2D.Double(); 
343
                        Rectangle2D.intersect(layerRect, vpRect, requestedRect);
344

    
345
                        // 3. Compute image size in pixels from the requested Extent
346
                        double scalex = vp.getAffineTransform().getScaleX();
347
                        double scaley = vp.getAffineTransform().getScaleY();
348
                        int wImg = (int) Math.ceil(Math.abs(requestedRect.getWidth() * scalex));
349
                        int hImg = (int) Math.ceil(Math.abs(requestedRect.getHeight() * scaley));
350
                        if ((wImg <= 0) || (hImg <= 0)) {
351
                                return;
352
                        }
353
                        
354
                        // 4. compute exactly the requested extent (from the rounded image size)
355
                        // ensuring we are still within the layer extent
356
                        double worldWidth = Math.abs((double)wImg/scalex);
357
                        double worldHeigh = Math.abs((double)hImg/scaley);
358
                        double worldX;
359
                        if (requestedRect.getX()+worldWidth>layerEnv.getMaximum(0)) {
360
                                // we've got outside of layer extent due to rounding
361
                                worldX = layerEnv.getMaximum(0)-worldWidth;
362
                        }
363
                        else {
364
                                worldX = requestedRect.getX();
365
                        }
366
                        double worldY;
367
                        if (requestedRect.getY()+worldHeigh>layerEnv.getMaximum(1)) {  // FIXME: test with different CRSs
368
                                worldY = layerEnv.getMaximum(1)-worldHeigh;
369
                        }
370
                        else {
371
                                worldY = requestedRect.getMinY();
372
                        }
373
                        
374
                        requestedRect.setRect(worldX, worldY, worldWidth, worldHeigh); 
375
                        Envelope requestedEnvelope = geomManager.createEnvelope(requestedRect.getMinX(),
376
                                        requestedRect.getMinY(),
377
                                        requestedRect.getMaxX(),
378
                                        requestedRect.getMaxY(),
379
                                        SUBTYPES.GEOM2D);
380
                        Extent requestedExtent = rManager.getDataStructFactory().createExtent(
381
                                        requestedEnvelope.getMinimum(0), 
382
                                        requestedEnvelope.getMaximum(1), 
383
                                        requestedEnvelope.getMaximum(0), 
384
                                        requestedEnvelope.getMinimum(1));
385

    
386
                        // 5. compute the new AffineTransform (ViewPort class can do it for us
387
                        // if we provide the image size, extent and offset)
388
                        ViewPort auxVp = (ViewPort) vp.clone();
389
                        Dimension sz = new Dimension(wImg, hImg);
390
                        auxVp.setImageSize(sz);
391
                        auxVp.setEnvelope(requestedEnvelope);
392

    
393
                        
394
                        // 6. compute tile offeset. It is the sum of the original viewport offset
395
                        // plus the offset introduced by intersecting layer and viewport extents
396
                        double offsetX = vp.getOffset().getX();
397
                        if (requestedEnvelope.getMinimum(0)-vpEnv.getMinimum(0)>0) {
398
                                offsetX = offsetX + (requestedEnvelope.getMinimum(0)-vpEnv.getMinimum(0))*auxVp.getAffineTransform().getScaleX();
399
                        }
400
                        double offsetY = vp.getOffset().getY(); // FIXME: test with different CRSs
401
                        if (requestedEnvelope.getMaximum(1)-vpEnv.getMaximum(1)<0) {
402
                                offsetY = offsetY + (requestedEnvelope.getMaximum(1)-vpEnv.getMaximum(1))*auxVp.getAffineTransform().getScaleY();
403
                        }
404

    
405
                        // 7. Compute again the AffineTransform considering also the offset
406
                        auxVp.setOffset(new Point2D.Double(offsetX, offsetY));
407
                        auxVp.refreshExtent(); // necessary after updating the offset
408

    
409
                        ViewPortData vpData = rManager.getDataStructFactory().createViewPortData(auxVp.getProjection(), requestedExtent, sz);
410
                        vpData.setMat(auxVp.getAffineTransform());
411
                        vpData.setDPI((int)auxVp.getDPI());
412
                        getParameters().setExtent(requestedRect);
413
                        if(getParameters().isSizeFixed()) {
414
                                getParameters().setWidth((int)getParameters().getFixedSize().getWidth());
415
                                getParameters().setHeight((int)getParameters().getFixedSize().getHeight());
416
                        } else {
417
                                getParameters().setWidth(wImg);
418
                                getParameters().setHeight(hImg);
419
                        }
420
                        if(getDataStore().getParameters() instanceof WMSDataParameters) {
421
                                getRender().draw(g, vpData, taskStatus);
422
                        } else {
423
                                Extent vpExtent = rManager.getDataStructFactory().createExtent(
424
                                                vpEnv.getMinimum(0),
425
                                                vpEnv.getMaximum(1),
426
                                                vpEnv.getMaximum(0),
427
                                                vpEnv.getMinimum(1));
428
                                ViewPortData vp2 = rManager.getDataStructFactory().createViewPortData(vp.getProjection(), vpExtent, vp.getImageSize() );
429
                                vp2.setMat(vp.getAffineTransform());
430
                                vp2.setDPI((int)vp.getDPI());
431
                                getParameters().setExtent(vpExtent.toRectangle2D());
432
                                getRender().drawTiledService(g, vp2, vp.getImageSize(), taskStatus);
433
                        }
434
                } catch (ProcessInterruptedException e) {
435
                } catch (CloneNotSupportedException e) {
436
                        drawingError(e);
437
                }
438
                catch (QueryException e) {
439
                        drawingError(e);
440
                } catch (CreateEnvelopeException e) {
441
                        drawingError(e);
442
                } finally {
443
                        taskStatus.terminate();                                
444
                }
445
        }
446
        
447
        private void drawingError(Exception e) {
448
                setAvailable(false);
449
                JOptionPane.showMessageDialog(null, "Problems drawing this layer:" + e.getMessage(), Messages.getText("Error"), JOptionPane.ERROR_MESSAGE);
450
                logger.info("Problems drawing this layer:" + e.getMessage(), e);
451
        }        
452

    
453
        /**
454
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#print(java.awt.Graphics2D,
455
         *                 com.iver.cit.gvsig.fmap.ViewPort,
456
         *                 com.iver.cit.gvsig.fmap.operations.Cancellable)
457
         */
458
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, double scale, PrintRequestAttributeSet properties)
459
        throws ReadException {
460
                TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
461
                SimpleTaskStatus taskStatus = new RasterTaskStatus("Printing " + getName() + "...", cancel);
462
                manager.add(taskStatus);
463
                taskStatus.setAutoremove(true);
464
                splitRequestCalculation(viewPort.getImageWidth(), viewPort.getImageHeight());
465

    
466
                if (isVisible() && isWithinScale(scale)){
467
                        if (!mustSplitRequest) {
468
                                draw(null, g, viewPort, cancel,scale);
469
                        } else {
470
                                Tiling tiles = new Tiling(maxTilePrintWidth, maxTilePrintHeight, g.getClipBounds());
471
                                tiles.setAffineTransform((AffineTransform) viewPort.getAffineTransform().clone());
472
                                for (int tileNr = 0; tileNr < tiles.getNumTiles(); tileNr++) {
473
                                        // Parte que dibuja
474
                                        try {
475
                                                ViewPort vp = tiles.getTileViewPort(viewPort, tileNr);
476
                                                drawTile(g, vp, taskStatus, scale);
477
                                        } catch (NoninvertibleTransformException e) {
478
                                                throw new ReadException(e.getMessage(), e);
479
                                        } catch (LoadLayerException e) {
480
                                                throw new ReadException(e.getMessage(), e);
481
                                        }
482
                                }
483
                        }
484
                }
485
                taskStatus.terminate();
486
        }
487

    
488
        public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
489
                        double scale) throws ReadException {
490
                draw(null, g, viewPort, cancel,scale);
491
        }
492

    
493
        public HashMap<String, Object> getProperties() {
494
                HashMap<String, Object> info = new HashMap<String, Object>();
495
                String[] layerNames = getParameters().getLayerQuery().split(",");
496
                Vector<WMSLayerNode> layers = new Vector<WMSLayerNode>(layerNames.length);
497
                try {
498
                        //explorer.connect(null);
499
                        for (int i = 0; i < layerNames.length; i++) {
500
                                layers.add(i, getExplorer().getLayer(layerNames[i]));
501
                        }
502
                        info.put("name", getName());
503
                        info.put("selectedLayers", layers);
504
                        info.put("host", getParameters().getURI());
505
                        info.put("srs", getParameters().getSRSCode());
506
                        info.put("format", getParameters().getFormat());
507
                        info.put("infoformat", getParameters().getInfoFormat());
508
                        info.put("wmsTransparency", new Boolean(getParameters().isWmsTransparent()));
509
                        info.put("styles", getParameters().getStyles());
510
                        info.put("dimensions", getParameters().getDimensions());
511
                        info.put("fixedSize", getParameters().getFixedSize());
512
                        return info;
513
                } catch (Exception e) {
514
                        e.printStackTrace();
515
                }
516
                return null;
517
        }
518

    
519
        /**
520
         * Creates the part of a OGC's MapContext document that would describe this
521
         * layer(s).
522
         * @param version, The desired version of the resulting document. (1.1.0)
523
         * @return String containing the xml.
524
         * @throws UnsupportedVersionLayerException
525
         */
526
        @SuppressWarnings({ "unchecked", "rawtypes" })
527
        public String toMapContext(String mapContextVersion) {
528
                XmlBuilder xml = new XmlBuilder();
529
                
530
                String query = getParameters().getLayerQuery();
531
                String[] layerNames = query.split(",");
532
                List<RemoteWMSStyle> styleList = getParameters().getStyles();
533
                for (int i = 0; i < layerNames.length; i++) {
534
                        WMSLayerNode layer = getExplorer().getLayer(layerNames[i]);
535
                        HashMap xmlAttrs = new HashMap();
536

    
537
                        // <Layer>
538
                        xmlAttrs.put(WebMapContextTags.HIDDEN, !isVisible() + "");
539
                        xmlAttrs.put(WebMapContextTags.QUERYABLE, getExplorer().isQueryable() + "");
540
                        xml.openTag(WebMapContextTags.LAYER, xmlAttrs);
541
                        xmlAttrs.clear();
542
                        if (mapContextVersion.equals("1.1.0") || mapContextVersion.equals("1.0.0")) {
543
                                // <Server>
544
                                xmlAttrs.put(WebMapContextTags.SERVICE, WebMapContextTags.WMS);
545
                                xmlAttrs.put(WebMapContextTags.VERSION, getExplorer().getVersion());
546
                                xmlAttrs.put(WebMapContextTags.SERVER_TITLE, getExplorer().getServiceTitle());
547
                                xml.openTag(WebMapContextTags.SERVER, xmlAttrs);
548
                                xmlAttrs.clear();
549

    
550
                                // <OnlineResource>
551
                                xmlAttrs.put(WebMapContextTags.XLINK_TYPE, "simple");
552
                                xmlAttrs.put(WebMapContextTags.XLINK_HREF, getParameters().getURI().toString());
553
                                xml.writeTag(WebMapContextTags.ONLINE_RESOURCE, xmlAttrs);
554
                                xmlAttrs.clear();
555
                                // </OnlineResource>
556

    
557
                                xml.closeTag();
558
                                // </Server>
559

    
560
                                // <Name>
561
                                xml.writeTag(WebMapContextTags.NAME, layer.getName().trim());
562
                                // </Name>
563

    
564
                                // <Title>
565
                                xml.writeTag(WebMapContextTags.TITLE, layer.getTitle().trim());
566
                                //?xml.writeTag(WebMapContextTags.TITLE, getName().trim());
567
                                // </Title>
568

    
569
                                // <Abstract>
570
                                if (layer.getAbstract() != null) {
571
                                        xml.writeTag(WebMapContextTags.ABSTRACT, layer.getAbstract());
572
                                        // </Abstract>
573
                                }
574

    
575
                                // <SRS> (a list of available SRS for the enclosing layer)
576
                                String[] strings = (String[]) layer.getAllSrs().toArray(new String[0]);
577
                                String mySRS = strings[0];
578
                                for (int j = 1; j < strings.length; j++) {
579
                                        mySRS += ","+strings[j];
580
                                }
581
                                xml.writeTag(WebMapContextTags.SRS, mySRS);
582
                                // </SRS>
583

    
584
                                // <FormatList>
585
                                xml.openTag(WebMapContextTags.FORMAT_LIST);
586
                                strings = getExplorer().getFormats();
587
                                for (int j = 0; j < strings.length; j++) {
588
                                        // <Format>
589
                                        String str = strings[j].trim();
590
                                        if (str.equals(getParameters().getFormat())) {
591
                                                xml.writeTag(WebMapContextTags.FORMAT, str, WebMapContextTags.CURRENT, "1");
592
                                        } else {
593
                                                xml.writeTag(WebMapContextTags.FORMAT, str);
594
                                                // </Format>
595
                                        }
596
                                }
597
                                xml.closeTag();
598
                                // </FormatList>
599

    
600
                                // <StyleList>
601
                                xml.openTag(WebMapContextTags.STYLE_LIST);
602

    
603
                                if (layer.getStyles().size() > 0) {
604
                                        for (int j = 0; j < layer.getStyles().size(); j++) {
605
                                                // <Style>
606
                                                RemoteWMSStyle st = layer.getStyles().get(j);
607
                                                if (st.getName().equals(styleList.get(i).getName())) {
608
                                                        xmlAttrs.put(WebMapContextTags.CURRENT, "1");
609
                                                }
610
                                                xml.openTag(WebMapContextTags.STYLE, xmlAttrs);
611
                                                xmlAttrs.clear();
612

    
613
                                                // <Name>
614
                                                xml.writeTag(WebMapContextTags.NAME, st.getName());
615
                                                // </Name>
616

    
617
                                                // <Title>
618
                                                xml.writeTag(WebMapContextTags.TITLE, st.getTitle());
619
                                                // </Title>
620

    
621
                                                // <LegendURL width="180" format="image/gif" height="50">
622
                                                // <OnlineResource xlink:type="simple" xlink:href="http://globe.digitalearth.gov/globe/en/icons/colorbars/NATIONAL.gif"/>
623
                                                // </OnlineResource>
624
                                                // </LegendURL>
625
                                                xml.closeTag();
626
                                                // </Style>
627

    
628
                                        }
629

    
630
                                } else {
631
                                        // Create fake style (for compatibility issues)
632
                                        xmlAttrs.put(WebMapContextTags.CURRENT, "1");
633
                                        // <Style>
634
                                        xml.openTag(WebMapContextTags.STYLE, xmlAttrs);
635
                                        xmlAttrs.clear();
636
                                        // <Name>
637
                                        xml.writeTag(WebMapContextTags.NAME, "default");
638
                                        // </Name>
639

    
640
                                        // <Title>
641
                                        xml.writeTag(WebMapContextTags.TITLE, "default");
642
                                        xml.closeTag();
643
                                }
644
                                // </StyleList>
645
                                xml.closeTag();
646
                                if (mapContextVersion.compareTo("1.0.0") > 0) {
647
                                        // <DimensionList>
648
                                        xml.openTag(WebMapContextTags.DIMENSION_LIST);
649
                                        // <Dimension>
650
                                        // </Dimension>
651
                                        xml.closeTag();
652
                                        // </DimensionList>
653
                                }
654
                        } else {
655
                                xml.writeTag("ERROR", PluginServices.getText(this, "unsupported_map_context_version"));
656
                        }
657
                        // </Layer>
658
                        xml.closeTag();
659
                }
660
                return xml.getXML();
661
        }
662

    
663
        public String getTocImageIcon() {
664
                return "icon-layer-wms";
665
        }
666

    
667
        public int[] getTileSize() {
668
                int[] size = {maxTileDrawWidth, maxTileDrawHeight};
669
                return size;
670
        }
671

    
672
        public boolean isTiled() {
673
                return mustSplitRequest;
674
        }
675
        
676
        private void splitRequestCalculation(int width, int height) {
677
            RasterDataStore store = this.getDataStore();
678
            if( store == null ) {
679
                String msg = "Can't get RasterDataStore associated to this layer ("+this.toString()+").";
680
                logger.warn(msg);
681
                throw new RuntimeException(msg);
682
            }
683
            mustSplitRequest = (!store.isTiled() && (width > maxTileDrawWidth || height > maxTileDrawHeight));
684
        }
685

    
686
        public ComposedLayer newComposedLayer() {
687
                Preferences prefs = Preferences.userRoot().node("gvsig.wms");
688

    
689
                /*
690
                 * from java.util.prefs import Preferences
691
                 * prefs = Preferences.userRoot().node("gvsig.wms")
692
                 * prefs.put("useComposedLayer","true")
693
                 */
694

    
695
                String str = prefs.get("useComposedLayer","false");
696
                Boolean useComposedLayer = Boolean.TRUE; // por defecto ya se usan
697
                try {
698
                        useComposedLayer = Boolean.valueOf(str);
699
                } catch (Exception e) {
700

    
701
                }
702
                if (useComposedLayer.booleanValue()) {
703
                        return new ComposedLayerWMS();
704
                } else {
705
                        return null;
706
                }
707
        }
708

    
709
        /*
710
         * Checks if can make a single petition for the two layers to the server
711
         * @see com.iver.cit.gvsig.fmap.layers.ComposedLayerWMS#canAdd(com.iver.cit.gvsig.fmap.layers.FLayer)
712
         */
713
        boolean isComposedLayerCompatible(FLayer layer) {
714
                FLyrWMS aLayer;
715

    
716
                if (!(layer instanceof FLyrWMS)) {
717
                        return false;
718
                }
719
                aLayer = (FLyrWMS)layer;
720
                if (!getParameters().getURI().equals(aLayer.getParameters().getURI())) {
721
                        return false;
722
                }
723
                
724
                WMSDataParameters p = getWMSParameters(getDataStore().getParameters()); 
725
                                
726
                if (!p.getFormat().equals(aLayer.getParameters().getFormat())) {
727
                        return false;
728
                }
729
                if (!p.getSRS().equals(aLayer.getParameters().getSRS())) {
730
                        return false;
731
                }
732
                if (p.getInfoLayerQuery() != null) {
733
                        if (!p.getInfoLayerQuery().equals(aLayer.getParameters().getInfoLayerQuery())) {
734
                                return false;
735
                        }
736
                }else if (p.getInfoLayerQuery() != null) {
737
                        return false;
738
                }
739

    
740

    
741
                // isFixedSize es privado
742
                if ((getParameters().getFixedSize() != null) &&
743
                                (aLayer.getParameters().getFixedSize() != null)) {
744
                        if (getParameters().getFixedSize().equals(aLayer.getParameters().getFixedSize())) {
745
                                return false;
746
                        }
747
                } else if ((getParameters().getFixedSize() != null) != (aLayer.getParameters().getFixedSize() != null)) {
748
                        return false;
749
                }
750

    
751
                // time elevation (dimensions)
752
                if ((p.getDimensions() != null) &&
753
                                (aLayer.getParameters().getDimensions() != null)) {
754
                        if (p.getDimensions().size() != aLayer.getParameters().getDimensions().size()) {
755
                                return false;
756
                        } else {
757
                                Iterator<String> iter = p.getDimensions().iterator();
758
                                while (iter.hasNext()) {
759
                                        if (!aLayer.getParameters().getDimensions().contains(iter.next())) {
760
                                                return false;
761
                                        }
762
                                }
763
                        }
764

    
765
                } else if ((p.getDimensions() != null) != (aLayer.getParameters().getDimensions() != null)) {
766
                        return false;
767
                }
768

    
769
                return true;
770
        }
771

    
772
        public boolean isActionEnabled(int action) {
773
                switch (action) {
774
                case IRasterLayerActions.ZOOM_PIXEL_RESOLUTION:
775
                case IRasterLayerActions.FLYRASTER_BAR_TOOLS:
776
                case IRasterLayerActions.BANDS_FILE_LIST:
777
                case IRasterLayerActions.COLOR_TABLE:
778
                case IRasterLayerActions.GEOLOCATION:
779
                case IRasterLayerActions.PANSHARPENING:
780
                case IRasterLayerActions.SAVE_COLORINTERP:
781
                case IRasterLayerActions.SAVEAS:
782
                case IRasterLayerActions.BANDS_RGB:
783
                case IRasterLayerActions.ENHANCED:
784
                case IRasterLayerActions.STATS:
785
                case IRasterLayerActions.NODATA:
786
                        return false;
787
                case IRasterLayerActions.REMOTE_ACTIONS:
788
                        return true;
789
                }
790

    
791
                return super.isActionEnabled(action);
792
        }
793

    
794
        public ILegend getLegend() {
795
                if(getDataStore() != null) {
796
                        Image img = getDataStore().getImageLegend();
797
                        if(img != null)
798
                                return new ImageLegend(img);
799
                }
800
                return null;
801
        }
802
        
803
        public boolean isRemote() {
804
                return true;
805
        }
806

    
807
        public boolean overviewsSupport() {
808
                return false;
809
        }
810

    
811
        protected void updateDrawVersion() {
812
                if (this.disableUpdateDrawVersion != null){
813

    
814
                        Thread curThread = Thread.currentThread();
815

    
816
                        Thread aThread;
817

    
818
                        Iterator<WeakReference<Thread>> iter = this.disableUpdateDrawVersion.iterator();
819
                        while (iter.hasNext()){
820
                                aThread = (Thread) ((WeakReference<?>)iter.next()).get();
821
                                if (aThread == null){
822
                                        iter.remove();
823
                                } else if(aThread.equals(curThread)){
824
                                        return;
825
                                }
826
                        }
827
                }
828
                //                Exception ex = new Exception();
829
                //                ex.printStackTrace();
830
                super.updateDrawVersion();
831
        }
832

    
833
        protected void disableUpdateDrawVersion() {
834
                if (this.disableUpdateDrawVersion == null) {
835
                        this.disableUpdateDrawVersion = new ArrayList<WeakReference<Thread>>();
836
                }
837
                this.disableUpdateDrawVersion.add(new WeakReference<Thread>(Thread.currentThread()));
838
        }
839

    
840
        protected void enableUpdateDrawVersion() {
841
                if (this.disableUpdateDrawVersion == null){
842
                        return;
843
                }
844
                Thread curThread = Thread.currentThread();
845
                Thread aThread;
846

    
847
                Iterator<WeakReference<Thread>> iter = this.disableUpdateDrawVersion.iterator();
848
                while (iter.hasNext()) {
849
                        aThread = (Thread) ((WeakReference<?>)iter.next()).get();
850
                        if (aThread == null) {
851
                                iter.remove();
852
                        } else if(aThread.equals(curThread)) {
853
                                iter.remove();
854
                                break;
855
                        }
856
                }
857

    
858
        }
859

    
860
        private Rectangle2D.Double getRectable2DFromEnvelope(Envelope env) {
861
                return new Rectangle2D.Double(env.getMinimum(0), env.getMinimum(1), env
862
                                .getLength(0), env.getLength(1));
863
        }
864

    
865
        /*private Envelope getEnvelopeFromRectable2D(Rectangle2D rect) {
866
                try {
867
                        return geomManager.createEnvelope(rect.getMinX(), rect.getMinY(),
868
                                        rect.getMaxX(), rect.getMaxY(),
869
                                        SUBTYPES.GEOM2D);
870
                } catch (CreateEnvelopeException e) {
871
                        logger.error("Error creating the envelope", e);
872
                }
873
                return null;
874
        }*/
875
        
876
        @Override
877
        public String getFileFormat() {
878
                return "WMS";
879
        }
880
        
881
        @Override
882
        public FLayer getFileLayer() throws RasterDriverException {
883
                /*if(getDataStore() instanceof DefaultRemoteRasterStore) {
884
                        RemoteRasterProvider prov = (RemoteRasterProvider)((DefaultRemoteRasterStore)getDataStore()).getProvider(0);
885
                        File file = null;
886
                        
887
                        if(getParameters().isSizeFixed()) {
888
                                file = prov.getFileLayer();
889
                        } else {
890
                                file = prov.getLastRequest();
891
                        }
892
                                
893
                        if(file == null)
894
                                return null;
895
                        
896
                        try {
897
                                return DefaultFLyrRaster.createLayer("tmp", file);
898
                        } catch (LoadLayerException e) {
899
                                throw new RasterDriverException(e.getMessage(), e);
900
                        }
901
                }*/
902
                return null;
903
        }
904

    
905
        /**
906
         * Devuelve el envelope en la proyeccion de la vista
907
         */
908
        public Envelope getFullEnvelope() {
909
                Extent e1 = getDataStore().getExtent();
910
                Envelope rAux = null;
911
                try {
912
                        rAux = geomManager.createEnvelope(e1.getMin().getX(), e1.getMin().getY(), e1.getMax().getX(), e1.getMax().getY(), SUBTYPES.GEOM2D);
913
                } catch (CreateEnvelopeException exc) {
914
                        logger.error("Error creating the envelope", exc);
915
                }
916

    
917
                // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
918
                // y alto 0.
919
                if (rAux == null || rAux.getMaximum(0) - rAux.getMinimum(0) == 0
920
                                && rAux.getMaximum(1) - rAux.getMinimum(1) == 0) {
921
                        try {
922
                                rAux = geomManager.createEnvelope(0, 0, 100, 100, SUBTYPES.GEOM2D);
923
                        } catch (CreateEnvelopeException e) {
924
                                logger.error("Error creating the envelope", e);
925
                        }
926
                }
927
                // Si existe reproyecci?n, reproyectar el extent
928
                ICoordTrans ct = getCoordTrans();
929
                if (ct != null) {
930
                        Point2D pt1 = new Point2D.Double(rAux.getMinimum(0), rAux
931
                                        .getMinimum(1));
932
                        Point2D pt2 = new Point2D.Double(rAux.getMaximum(0), rAux
933
                                        .getMaximum(1));
934
                        pt1 = ct.convert(pt1, null);
935
                        pt2 = ct.convert(pt2, null);
936
                        try {
937
                                rAux = geomManager.createEnvelope(pt1.getX(), pt1.getY(), pt2
938
                                                .getX(), pt2.getY(), SUBTYPES.GEOM2D);
939
                        } catch (CreateEnvelopeException e) {
940
                                logger.error("Error creating the envelope", e);
941
                        }// new
942
                        // Rectangle2D.Double();
943
                }
944
                return rAux;
945

    
946
        }
947
        
948
        public Extent getFullRasterExtent() {
949
                return getExtentFromEnvelope(getFullEnvelope());
950
        }
951
        
952
        public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p, double tolerance) throws LoadLayerException, DataException {
953
                Point p1 = new Point((int)p.getX(), (int)p.getY());
954
                return getInfo(p1, tolerance, null, false);
955
        }
956

    
957
        @Override
958
        public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel,
959
                        boolean fast) throws LoadLayerException, DataException {
960

    
961
                //try {
962
                ViewPort viewPort = getMapContext().getViewPort();
963

    
964
                getParameters().setExtent(this.getRectable2DFromEnvelope(viewPort.getAdjustedEnvelope()));
965
                if(getParameters().isSizeFixed()) {
966
                        getParameters().setWidth((int)getParameters().getFixedSize().getWidth());
967
                        getParameters().setHeight((int)getParameters().getFixedSize().getHeight());
968
                } else {
969
                        getParameters().setWidth(viewPort.getImageWidth());
970
                        getParameters().setHeight(viewPort.getImageHeight());
971
                }
972
                
973
                CancelTaskImpl cancellable = new CancelTaskImpl(cancel);
974
                getParameters().setCancellable(cancellable);
975
                
976
                String fInfo;
977
                try {
978
                        //Point2D pt = new Point2D.Double();
979
                        //try {
980
                                //viewPort.getAffineTransform().transform(p, pt);
981
                        /*} catch (NoninvertibleTransformException e) {
982
                                return null;
983
                        }*/
984
                        
985
                        Extent bbox = getExtentFromEnvelope(viewPort.getAdjustedEnvelope());
986
                        fInfo = getDataStore().getInfoByPoint(p.getX(), 
987
                                        p.getY(), 
988
                                        bbox, 
989
                                        viewPort.getImageWidth(), 
990
                                        viewPort.getImageHeight(), 
991
                                        cancellable);
992
                } catch (InfoByPointException e) {
993
                        throw new LoadLayerException("Error in getInfoByPoint", e);
994
                }
995
                return new DynObjectSetWMSInfo(fInfo, getParameters().getInfoFormat());
996
        }
997
        
998
        private Extent getExtentFromEnvelope(Envelope env) {
999
                double minx = env.getMinimum(0);
1000
                double miny = env.getMinimum(1);
1001
                double maxx = env.getMaximum(0);
1002
                double maxy = env.getMaximum(1);
1003
                Point2D ul = new Point2D.Double(minx, maxy);
1004
                Point2D ur = new Point2D.Double(maxx, maxy);
1005
                Point2D ll = new Point2D.Double(minx, miny);
1006
                Point2D lr = new Point2D.Double(maxx, miny);
1007
                return rManager.getDataStructFactory().createExtent(ul, lr, ur, ll);
1008
        }
1009
    
1010
    /**
1011
     * Sets the data store parameters
1012
     * @param params
1013
     * @throws InitializeException
1014
     */
1015
    public void setParameters(DataStoreParameters params) throws InitializeException {
1016
            if(params instanceof TileDataParameters) {
1017
                        ((TileDataParameters)params).deleteCache(deleteCache);
1018
                }
1019
            
1020
            DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
1021
                try {
1022
                        DataStore dStore = dataman.openStore(params.getDataStoreName(), params);
1023
                        this.setDataStore(dStore);
1024
                        
1025
                        if(params instanceof WMSDataParameters) {
1026
                                this.setName(((WMSDataParameters)params).getURI());
1027
                        }
1028
                        
1029
                        if(params instanceof TileDataParameters) {
1030
                                DataParameters p = ((TileDataParameters) params).getDataParameters();
1031
                                if(p instanceof WMSDataParameters) {
1032
                                        this.setName(((WMSDataParameters) p).getURI());
1033
                                }
1034
                        }
1035
                } catch (ValidateDataParametersException e) {
1036
                        throw new InitializeException(e);
1037
                } catch (ProviderNotRegisteredException e) {
1038
                        throw new InitializeException(e);
1039
                } catch (LoadLayerException e) {
1040
                        throw new InitializeException(e);
1041
                }
1042
    }
1043
    
1044
        public WMSDataParameters getParameters() {
1045
                return getWMSParameters(getDataStore().getParameters());
1046
    }
1047
    
1048
    /**
1049
     * Gets <code>WMSDataParameters</code>
1050
     * @param parameters
1051
     * @return
1052
     */
1053
    private WMSDataParameters getWMSParameters(DataStoreParameters parameters) {
1054
            WMSDataParameters params = null;
1055
            if(parameters instanceof WMSDataParameters) {
1056
                        params = (WMSDataParameters) parameters;
1057
                }
1058
                
1059
                if(parameters instanceof TileDataParameters) {
1060
                        DataParameters p = ((TileDataParameters) parameters).getDataParameters();
1061
                        if(p instanceof WMSDataParameters) {
1062
                                params = (WMSDataParameters) p;
1063
                        }
1064
                }
1065
                return params;
1066
    }
1067
    
1068
    /**
1069
         * Assigns the flag to delete this layer from the cache
1070
         * @param selected
1071
         */
1072
        public void deleteCache(boolean deleteCache) {
1073
                this.deleteCache = deleteCache;
1074
        }
1075
    
1076
    /**
1077
     * Sets the explorer
1078
     * @param explorer
1079
     */
1080
    public void setExplorer(WMSServerExplorer explorer) {
1081
            if(getDataStore() != null)
1082
                    getDataStore().setExplorer(explorer);
1083
    }
1084
    
1085
    /**
1086
     * Gets the explorer
1087
     * @return
1088
     */
1089
    public WMSServerExplorer getExplorer() {
1090
            try {
1091
                        return (WMSServerExplorer)getDataStore().getExplorer();
1092
                } catch (ValidateDataParametersException e) {
1093
                        logger.debug("Error getting the explorer", e);
1094
                } catch (DataException e) {
1095
                        logger.debug("Error getting the explorer", e);
1096
                }
1097
            return null;
1098
    }
1099
    
1100
        public FLayer cloneLayer() throws Exception {
1101
                RasterDataStore  ds = dataStore.cloneDataStore();
1102
                FLyrWMS newLayer = new FLyrWMS();
1103
                newLayer.setName(getName());
1104
                newLayer.setOpenRasterStore(ds);
1105
                //newLayer.firstLoad = firstLoad;
1106
                newLayer.setExplorer(getExplorer());
1107
                
1108
                List<RasterFilter> filters = getRender().getFilterList().getStatusCloned();
1109

    
1110
                //Hacemos una copia de las bandas a renderizar
1111
                ColorInterpretation ci = getRender().getRenderColorInterpretation();
1112
                if(ci != null) {
1113
                        newLayer.getRender().setRenderColorInterpretation(ci.cloneColorInterpretation());
1114
                }
1115

    
1116
                //Asignamos el entorno
1117
                if(newLayer.getRender().getFilterList() == null)
1118
                        newLayer.getRender().setFilterList(RasterLocator.getManager().createEmptyFilterList(getRender().getFilterList().getInitDataType()));
1119
                newLayer.getRender().getFilterList().setEnv(getRender().getFilterList().getEnv());
1120
                newLayer.getRender().getFilterList().setStatus(filters);
1121

    
1122
                // Asignamos los valores noData del original
1123
                newLayer.setNoDataValue(getNoDataValue());
1124
                if(dataStore.getNoDataValue().isDefined())
1125
                        newLayer.setNoDataTransparent(true);
1126
                newLayer.enableOpen();
1127
                
1128
                return newLayer;
1129
        }
1130
        
1131
        @Override
1132
        public boolean isInside(Point2D p) {
1133
                // Don't call the data store isInside method, as the data store
1134
                // parameters change for every WMS tile that is drawn, so it does not
1135
                // return sensible results.
1136
                return rManager.getRasterUtils().isInside(p, getDataStore().getExtent());
1137
        }
1138
}