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

History | View | Annotate | Download (39 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.net.URI;
37
import java.net.URISyntaxException;
38
import java.util.ArrayList;
39
import java.util.HashMap;
40
import java.util.Iterator;
41
import java.util.List;
42
import java.util.Vector;
43
import java.util.prefs.Preferences;
44

    
45
import javax.print.attribute.PrintRequestAttributeSet;
46
import javax.swing.JOptionPane;
47

    
48
import org.cresques.cts.ICoordTrans;
49
import org.cresques.cts.IProjection;
50

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

    
111
import org.slf4j.Logger;
112
import org.slf4j.LoggerFactory;
113

    
114

    
115

    
116
/**
117
 * FMap's WMS Layer class.
118
 *
119
 * Las capas WMS son tileadas para descargarlas del servidor. Esto quiere decir que
120
 * est?n formadas por multiples ficheros raster. Por esto la fuente de datos raster (IRasterDatasource)
121
 * de la capa FLyrWMS es un objeto de tipo CompositeDataset. Este objeto est? compuesto por un array
122
 * bidimensional de MultiRasterDataset. Cada uno de los MultiRasterDataset corresponde con un tile
123
 * salvado en disco. Estos MultiRasterDataset se crean cada vez que se repinta ya que en WMS a cada
124
 * zoom varian los ficheros fuente. La secuencia de creaci?n de un CompositeDataset ser?a la siguiente:
125
 * <UL>
126
 * <LI>Se hace una petici?n de dibujado por parte del usuario llamando al m?todo draw de FLyrWMS</LI>
127
 * <LI>Se tilea la petici?n</LI>
128
 * <LI>Cada tile se dibuja abriendo una FLyerRaster para ese tile</LI>
129
 * <LI>Si es el primer dibujado se guarda una referencia en la capa WMS a las propiedades de renderizado, orden de bandas,
130
 * transparencia, filtros aplicados, ...</LI>
131
 * <LI>Si no es el primer dibujado se asignan las propiedades de renderizado cuya referencia se guarda en la capa WMS</LI>
132
 * <LI>Se guarda el MultiRasterDataset de cada tile</LI>
133
 * <LI>Al acabar todos los tiles creamos un CompositeDataset con los MultiRasterDataset de todos los tiles</LI>
134
 * <LI>Asignamos a la capa la referencia de las propiedades de renderizado que tenemos almacenadas. De esta forma si hay
135
 * alguna modificaci?n desde el cuadro de propiedades ser? efectiva sobre los tiles que se dibujan.</LI>
136
 * </UL>
137
 *
138
 *
139
 * @author Jaume Dominguez Faus
140
 *
141
 */
142
@SuppressWarnings("deprecation")
143
public class FLyrWMS extends DefaultFLyrRaster {
144
        public static final String           PERSISTENT_NAME           = "FLyrWMS_Persistent";
145
        public static final String           PERSISTENT_DESCRIPTION    = "FLyrWMS Persistent Definition";
146

    
147
        private static final GeometryManager geomManager               = GeometryLocator.getGeometryManager();
148
        private static final Logger          logger                    = LoggerFactory.getLogger(FLyrWMS.class);
149
        private boolean                                          mustSplitRequest          = false;
150
        private final int                                          maxTileDrawWidth          = 1023;
151
        private final int                                          maxTileDrawHeight         = 1023;
152
        private final int                                          maxTilePrintWidth         = 1023;
153
        private final int                                          maxTilePrintHeight        = 1023;
154
        private List<WeakReference<Thread>>         disableUpdateDrawVersion;
155
        //private Envelope                                         fullEnvelope              = null;
156
        private boolean                                                 firstLoad                 = false;
157
        private RasterManager                rManager                  = RasterLocator.getManager();
158
        //private WMSServerExplorer            explorer                  = null;
159
        private boolean                      deleteCache               = false;
160

    
161
        public FLyrWMS() {
162
                super();
163
                this.updateDrawVersion();
164
                try {
165
                        enableAwake();
166
                } catch (NotAvailableStateException e) {
167
                        logger.error("Fallo el estado de open. Closed=" + isClosed() + " Awake=" + isAwake(), this, e);
168
                }
169
        }
170

    
171
   public FLyrWMS(DataStoreParameters dataStoreParameters) throws Exception {
172
        this();
173
        //Create the explorer and connect
174
        DataManager dataManager = DALLocator.getDataManager();
175
        WMSServerExplorerParameters explorerParams = (WMSServerExplorerParameters)
176
               dataManager.createServerExplorerParameters(WMSServerExplorer.NAME);
177
        explorerParams.setHost((String)dataStoreParameters.getDynValue("uri"));
178
        WMSServerExplorer wmsServerExplorer =
179
            (WMSServerExplorer) dataManager.openServerExplorer(WMSServerExplorer.NAME, explorerParams);
180
        wmsServerExplorer.connect(null, ((RemoteStoreParameters)dataStoreParameters).isDeletingCache());
181

    
182
        //Set the parameters
183
        setParameters((WMSDataParameters)dataStoreParameters);
184
        setExplorer(wmsServerExplorer);
185
    }
186

    
187
        public static DataStore createDataStore(String host, IProjection srs) throws InitializeException {
188
                DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
189
                RasterDataParameters params = null;
190
                try {
191
                        params = (RasterDataParameters)dataman.createServerExplorerParameters(WMSServerExplorer.NAME);
192
                } catch (InitializeException e) {
193
                        return null;
194
                } catch (ProviderNotRegisteredException e) {
195
                        return null;
196
                }
197
                try {
198
            params.setURI(new URI(host));
199
        } catch (URISyntaxException e1) {
200
            throw new InitializeException("Can't create URI from "+host, e1);
201
        }
202
                params.setSRS(srs);
203

    
204
                try {
205
                        return dataman.openStore(params.getDataStoreName(), params);
206
                } catch (ValidateDataParametersException e) {
207
                        throw new InitializeException(e);
208
                } catch (ProviderNotRegisteredException e) {
209
                        throw new InitializeException(e);
210
                }
211
        }
212

    
213
        public void setDataStore(DataStore dataStore) throws LoadLayerException {
214
                this.dataStore = (RasterDataStore) dataStore;
215
                try {
216
                        this.dataStore.isOpen();
217
                        if(!isOpen())
218
                                enableOpen();
219
                } catch (NotAvailableStateException e) {
220
                        logger.error("Fallo el estado de open. Closed=" + isClosed() + " Awake=" + isAwake(), this, e);
221
                }
222
                setProjection(this.dataStore.getProjection());
223
        }
224

    
225
        /**
226
         * It choose the best format to load different maps if the server
227
         * supports it. This format could be png, because it supports
228
         * transparency.
229
         * @param formats
230
         * Arraywith all the formats supported by the server
231
         * @return
232
         */
233
        @SuppressWarnings("unused")
234
        private String getGreatFormat(Vector<String> formats){
235
                for (int i = 0 ; i < formats.size() ; i++){
236
                        String format = (String) formats.get(i);
237
                        if (format.equals("image/jpg")){
238
                                return format;
239
                        }
240
                        if (format.equals("image/jpeg")){
241
                                return format;
242
                        }
243
                }
244
                return (String)formats.get(0);
245
        }
246

    
247
        public static void registerPersistent() {
248
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
249
                DynStruct definition = manager.getDefinition("FLyrWMS_Persistent");
250
                if( definition == null ) {
251
                        if (manager.getDefinition(DefaultFLyrRaster.class) == null) {
252
                                DefaultFLyrRaster.registerPersistence();
253
                        }
254

    
255
                        definition = manager.addDefinition(
256
                                        FLyrWMS.class,
257
                                        "FLyrWMS_Persistent",
258
                                        "FLyrWMS Persistent Definition",
259
                                        null,
260
                                        null
261
                        );
262

    
263
                        definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE, DefaultFLyrRaster.PERSISTENT_NAME);
264
                }
265

    
266
                DefaultFLyrRaster.registerPersistence(definition);
267
        }
268

    
269
        public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
270
                        Cancellable cancel, double scale) throws ReadException {
271
                TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
272
                SimpleTaskStatus taskStatus = new RasterTaskStatus("Drawing " + getName() + "...", cancel);
273
                manager.add(taskStatus);
274
                taskStatus.setAutoremove(true);
275
                splitRequestCalculation(viewPort.getImageWidth(), viewPort.getImageHeight());
276

    
277
                if(!firstLoad) {
278
                        try {
279
                                initFilters();
280
                                try {
281
                                        if(!isOpen())
282
                                                enableOpen();
283
                                } catch (NotAvailableStateException e) {
284
                                        throw new ReadException("Fallo el estado de open. Closed=" + isClosed() + " Awake=" + isAwake(), e);
285
                                }
286
                        } catch (FilePaletteException e) {
287
                                logger.error(e.getMessage(), this, e);
288
                        }
289
                        firstLoad = true;
290
                }
291

    
292
                enableStopped();
293

    
294
                if(recalcLevel) {
295
                        double pixelSize = viewPort.getEnvelope().getLength(0) / (double)viewPort.getImageWidth();
296
                        zoomLevel = dataStore.getNearestLevel(pixelSize);
297
                }
298
                recalcLevel = true;
299

    
300
                if (isWithinScale(scale)) {
301

    
302
                        if(mustSplitRequest) {
303
                                Point2D p = viewPort.getOffset();
304
                                Rectangle r = new Rectangle((int) p.getX(), (int) p.getY(), viewPort.getImageWidth(), viewPort.getImageHeight());
305
                                Tiling tiles = new Tiling(maxTileDrawWidth, maxTileDrawHeight, r);
306
                                tiles.setAffineTransform((AffineTransform) viewPort.getAffineTransform().clone());
307

    
308
                                for (int tileNr = 0; tileNr < tiles.getNumTiles(); tileNr++) {
309
                                        // drawing part
310
                                        try {
311
                                                ViewPort vp = tiles.getTileViewPort(viewPort, tileNr);
312
                                                drawTile(g, vp, taskStatus, scale);
313
                                        } catch (LoadLayerException e) {
314
                                                throw new ReadException(e.getMessage(), e);
315
                                        } catch (NoninvertibleTransformException e) {
316
                                                throw new ReadException(e.getMessage(), e);
317
                                        }
318
                                }
319
                        } else {
320
                                try {
321
                                        drawTile(g, viewPort, taskStatus, scale);
322
                                } catch (LoadLayerException e) {
323
                                        setAvailable(false);
324
                                        logger.error("Server error:" + e.getMessage(), e);
325
                                }
326
                        }
327
                }
328
                disableStopped();
329
        }
330

    
331

    
332
        /**
333
         * This is the method used to draw a tile in a WMS mosaic layer.
334
         * @throws LoadLayerException
335
         * @throws ReadDriverException
336
         * @return true when a tile has been painted
337
         */
338
        private void drawTile(Graphics2D g, ViewPort vp, SimpleTaskStatus taskStatus, double scale) throws LoadLayerException, ReadException {
339
                // Compute the query geometry
340
                // 1. Check if it is within borders
341
                Envelope layerEnv = getFullEnvelope();
342
                Envelope vpEnv = vp.getAdjustedEnvelope();
343
                if (!vpEnv.intersects(layerEnv)) {
344
                        return;
345
                }
346
                try {
347
                        Rectangle2D vpRect = getRectable2DFromEnvelope(vpEnv);
348
                        Rectangle2D layerRect = getRectable2DFromEnvelope(layerEnv);
349
                        // 2. Intersect layer and viewport extents to get the area of interest
350
                        Rectangle2D requestedRect = new Rectangle2D.Double();
351
                        Rectangle2D.intersect(layerRect, vpRect, requestedRect);
352

    
353
                        // 3. Compute image size in pixels from the requested Extent
354
                        double scalex = vp.getAffineTransform().getScaleX();
355
                        double scaley = vp.getAffineTransform().getScaleY();
356
                        int wImg = (int) Math.ceil(Math.abs(requestedRect.getWidth() * scalex));
357
                        int hImg = (int) Math.ceil(Math.abs(requestedRect.getHeight() * scaley));
358
                        if ((wImg <= 0) || (hImg <= 0)) {
359
                                return;
360
                        }
361

    
362
                        // 4. compute exactly the requested extent (from the rounded image size)
363
                        // ensuring we are still within the layer extent
364
                        double worldWidth = Math.abs((double)wImg/scalex);
365
                        double worldHeigh = Math.abs((double)hImg/scaley);
366
                        double worldX;
367
                        if (requestedRect.getX()+worldWidth>layerEnv.getMaximum(0)) {
368
                                // we've got outside of layer extent due to rounding
369
                                worldX = layerEnv.getMaximum(0)-worldWidth;
370
                        }
371
                        else {
372
                                worldX = requestedRect.getX();
373
                        }
374
                        double worldY;
375
                        if (requestedRect.getY()+worldHeigh>layerEnv.getMaximum(1)) {  // FIXME: test with different CRSs
376
                                worldY = layerEnv.getMaximum(1)-worldHeigh;
377
                        }
378
                        else {
379
                                worldY = requestedRect.getMinY();
380
                        }
381

    
382
                        requestedRect.setRect(worldX, worldY, worldWidth, worldHeigh);
383
                        Envelope requestedEnvelope = geomManager.createEnvelope(requestedRect.getMinX(),
384
                                        requestedRect.getMinY(),
385
                                        requestedRect.getMaxX(),
386
                                        requestedRect.getMaxY(),
387
                                        SUBTYPES.GEOM2D);
388
                        Extent requestedExtent = rManager.getDataStructFactory().createExtent(
389
                                        requestedEnvelope.getMinimum(0),
390
                                        requestedEnvelope.getMaximum(1),
391
                                        requestedEnvelope.getMaximum(0),
392
                                        requestedEnvelope.getMinimum(1));
393

    
394
                        // 5. compute the new AffineTransform (ViewPort class can do it for us
395
                        // if we provide the image size, extent and offset)
396
                        ViewPort auxVp = (ViewPort) vp.clone();
397
                        Dimension sz = new Dimension(wImg, hImg);
398
                        auxVp.setImageSize(sz);
399
                        auxVp.setEnvelope(requestedEnvelope);
400

    
401

    
402
                        // 6. compute tile offeset. It is the sum of the original viewport offset
403
                        // plus the offset introduced by intersecting layer and viewport extents
404
                        double offsetX = vp.getOffset().getX();
405
                        if (requestedEnvelope.getMinimum(0)-vpEnv.getMinimum(0)>0) {
406
                                offsetX = offsetX + (requestedEnvelope.getMinimum(0)-vpEnv.getMinimum(0))*auxVp.getAffineTransform().getScaleX();
407
                        }
408
                        double offsetY = vp.getOffset().getY(); // FIXME: test with different CRSs
409
                        if (requestedEnvelope.getMaximum(1)-vpEnv.getMaximum(1)<0) {
410
                                offsetY = offsetY + (requestedEnvelope.getMaximum(1)-vpEnv.getMaximum(1))*auxVp.getAffineTransform().getScaleY();
411
                        }
412

    
413
                        // 7. Compute again the AffineTransform considering also the offset
414
                        auxVp.setOffset(new Point2D.Double(offsetX, offsetY));
415
                        auxVp.refreshExtent(); // necessary after updating the offset
416

    
417
                        ViewPortData vpData = rManager.getDataStructFactory().createViewPortData(auxVp.getProjection(), requestedExtent, sz);
418
                        vpData.setMat(auxVp.getAffineTransform());
419
                        vpData.setDPI((int)auxVp.getDPI());
420
                        getParameters().setExtent(requestedRect);
421
                        if(getParameters().isSizeFixed()) {
422
                                getParameters().setWidth((int)getParameters().getFixedSize().getWidth());
423
                                getParameters().setHeight((int)getParameters().getFixedSize().getHeight());
424
                        } else {
425
                                getParameters().setWidth(wImg);
426
                                getParameters().setHeight(hImg);
427
                        }
428
                        if(getDataStore().getParameters() instanceof WMSDataParameters) {
429
                                getRender().draw(g, vpData, taskStatus);
430
                        } else {
431
                                Extent vpExtent = rManager.getDataStructFactory().createExtent(
432
                                                vpEnv.getMinimum(0),
433
                                                vpEnv.getMaximum(1),
434
                                                vpEnv.getMaximum(0),
435
                                                vpEnv.getMinimum(1));
436
                                ViewPortData vp2 = rManager.getDataStructFactory().createViewPortData(vp.getProjection(), vpExtent, vp.getImageSize() );
437
                                vp2.setMat(vp.getAffineTransform());
438
                                vp2.setDPI((int)vp.getDPI());
439
                                getParameters().setExtent(vpExtent.toRectangle2D());
440
                                getRender().drawTiledService(g, vp2, vp.getImageSize(), taskStatus);
441
                        }
442
                } catch (ProcessInterruptedException e) {
443
                } catch (CloneNotSupportedException e) {
444
                        drawingError(e);
445
                }
446
                catch (QueryException e) {
447
                        drawingError(e);
448
                } catch (CreateEnvelopeException e) {
449
                        drawingError(e);
450
                } finally {
451
                        taskStatus.terminate();
452
                }
453
        }
454

    
455
        private void drawingError(Exception e) {
456
                setAvailable(false);
457
                JOptionPane.showMessageDialog(null, "Problems drawing this layer:" + e.getMessage(), Messages.getText("Error"), JOptionPane.ERROR_MESSAGE);
458
                logger.info("Problems drawing this layer:" + e.getMessage(), e);
459
        }
460

    
461
        /**
462
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#print(java.awt.Graphics2D,
463
         *                 com.iver.cit.gvsig.fmap.ViewPort,
464
         *                 com.iver.cit.gvsig.fmap.operations.Cancellable)
465
         */
466
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, double scale, PrintRequestAttributeSet properties)
467
        throws ReadException {
468
                TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
469
                SimpleTaskStatus taskStatus = new RasterTaskStatus("Printing " + getName() + "...", cancel);
470
                manager.add(taskStatus);
471
                taskStatus.setAutoremove(true);
472
                splitRequestCalculation(viewPort.getImageWidth(), viewPort.getImageHeight());
473

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

    
496
        public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
497
                        double scale) throws ReadException {
498
                draw(null, g, viewPort, cancel,scale);
499
        }
500

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

    
527
        /**
528
         * Creates the part of a OGC's MapContext document that would describe this
529
         * layer(s).
530
         * @param version, The desired version of the resulting document. (1.1.0)
531
         * @return String containing the xml.
532
         * @throws UnsupportedVersionLayerException
533
         */
534
        @SuppressWarnings({ "unchecked", "rawtypes" })
535
        public String toMapContext(String mapContextVersion) {
536
                XmlBuilder xml = new XmlBuilder();
537

    
538
                String query = getParameters().getLayerQuery();
539
                String[] layerNames = query.split(",");
540
                List<RemoteWMSStyle> styleList = getParameters().getStyles();
541
                for (int i = 0; i < layerNames.length; i++) {
542
                        WMSLayerNode layer = getExplorer().getLayer(layerNames[i]);
543
                        HashMap xmlAttrs = new HashMap();
544

    
545
                        // <Layer>
546
                        xmlAttrs.put(WebMapContextTags.HIDDEN, !isVisible() + "");
547
                        xmlAttrs.put(WebMapContextTags.QUERYABLE, getExplorer().isQueryable() + "");
548
                        xml.openTag(WebMapContextTags.LAYER, xmlAttrs);
549
                        xmlAttrs.clear();
550
                        if (mapContextVersion.equals("1.1.0") || mapContextVersion.equals("1.0.0")) {
551
                                // <Server>
552
                                xmlAttrs.put(WebMapContextTags.SERVICE, WebMapContextTags.WMS);
553
                                xmlAttrs.put(WebMapContextTags.VERSION, getExplorer().getVersion());
554
                                xmlAttrs.put(WebMapContextTags.SERVER_TITLE, getExplorer().getServiceTitle());
555
                                xml.openTag(WebMapContextTags.SERVER, xmlAttrs);
556
                                xmlAttrs.clear();
557

    
558
                                // <OnlineResource>
559
                                xmlAttrs.put(WebMapContextTags.XLINK_TYPE, "simple");
560
                                xmlAttrs.put(WebMapContextTags.XLINK_HREF, getParameters().getURI().toString());
561
                                xml.writeTag(WebMapContextTags.ONLINE_RESOURCE, xmlAttrs);
562
                                xmlAttrs.clear();
563
                                // </OnlineResource>
564

    
565
                                xml.closeTag();
566
                                // </Server>
567

    
568
                                // <Name>
569
                                xml.writeTag(WebMapContextTags.NAME, layer.getName().trim());
570
                                // </Name>
571

    
572
                                // <Title>
573
                                xml.writeTag(WebMapContextTags.TITLE, layer.getTitle().trim());
574
                                //?xml.writeTag(WebMapContextTags.TITLE, getName().trim());
575
                                // </Title>
576

    
577
                                // <Abstract>
578
                                if (layer.getAbstract() != null) {
579
                                        xml.writeTag(WebMapContextTags.ABSTRACT, layer.getAbstract());
580
                                        // </Abstract>
581
                                }
582

    
583
                                // <SRS> (a list of available SRS for the enclosing layer)
584
                                String[] strings = (String[]) layer.getAllSrs().toArray(new String[0]);
585
                                String mySRS = strings[0];
586
                                for (int j = 1; j < strings.length; j++) {
587
                                        mySRS += ","+strings[j];
588
                                }
589
                                xml.writeTag(WebMapContextTags.SRS, mySRS);
590
                                // </SRS>
591

    
592
                                // <FormatList>
593
                                xml.openTag(WebMapContextTags.FORMAT_LIST);
594
                                strings = getExplorer().getFormats();
595
                                for (int j = 0; j < strings.length; j++) {
596
                                        // <Format>
597
                                        String str = strings[j].trim();
598
                                        if (str.equals(getParameters().getFormat())) {
599
                                                xml.writeTag(WebMapContextTags.FORMAT, str, WebMapContextTags.CURRENT, "1");
600
                                        } else {
601
                                                xml.writeTag(WebMapContextTags.FORMAT, str);
602
                                                // </Format>
603
                                        }
604
                                }
605
                                xml.closeTag();
606
                                // </FormatList>
607

    
608
                                // <StyleList>
609
                                xml.openTag(WebMapContextTags.STYLE_LIST);
610

    
611
                                if (layer.getStyles().size() > 0) {
612
                                        for (int j = 0; j < layer.getStyles().size(); j++) {
613
                                                // <Style>
614
                                                RemoteWMSStyle st = layer.getStyles().get(j);
615
                                                if (st.getName().equals(styleList.get(i).getName())) {
616
                                                        xmlAttrs.put(WebMapContextTags.CURRENT, "1");
617
                                                }
618
                                                xml.openTag(WebMapContextTags.STYLE, xmlAttrs);
619
                                                xmlAttrs.clear();
620

    
621
                                                // <Name>
622
                                                xml.writeTag(WebMapContextTags.NAME, st.getName());
623
                                                // </Name>
624

    
625
                                                // <Title>
626
                                                xml.writeTag(WebMapContextTags.TITLE, st.getTitle());
627
                                                // </Title>
628

    
629
                                                // <LegendURL width="180" format="image/gif" height="50">
630
                                                // <OnlineResource xlink:type="simple" xlink:href="http://globe.digitalearth.gov/globe/en/icons/colorbars/NATIONAL.gif"/>
631
                                                // </OnlineResource>
632
                                                // </LegendURL>
633
                                                xml.closeTag();
634
                                                // </Style>
635

    
636
                                        }
637

    
638
                                } else {
639
                                        // Create fake style (for compatibility issues)
640
                                        xmlAttrs.put(WebMapContextTags.CURRENT, "1");
641
                                        // <Style>
642
                                        xml.openTag(WebMapContextTags.STYLE, xmlAttrs);
643
                                        xmlAttrs.clear();
644
                                        // <Name>
645
                                        xml.writeTag(WebMapContextTags.NAME, "default");
646
                                        // </Name>
647

    
648
                                        // <Title>
649
                                        xml.writeTag(WebMapContextTags.TITLE, "default");
650
                                        xml.closeTag();
651
                                }
652
                                // </StyleList>
653
                                xml.closeTag();
654
                                if (mapContextVersion.compareTo("1.0.0") > 0) {
655
                                        // <DimensionList>
656
                                        xml.openTag(WebMapContextTags.DIMENSION_LIST);
657
                                        // <Dimension>
658
                                        // </Dimension>
659
                                        xml.closeTag();
660
                                        // </DimensionList>
661
                                }
662
                        } else {
663
                                xml.writeTag("ERROR", PluginServices.getText(this, "unsupported_map_context_version"));
664
                        }
665
                        // </Layer>
666
                        xml.closeTag();
667
                }
668
                return xml.getXML();
669
        }
670

    
671
        public String getTocImageIcon() {
672
                return "icon-layer-wms";
673
        }
674

    
675
        public int[] getTileSize() {
676
                int[] size = {maxTileDrawWidth, maxTileDrawHeight};
677
                return size;
678
        }
679

    
680
        public boolean isTiled() {
681
                return mustSplitRequest;
682
        }
683

    
684
        private void splitRequestCalculation(int width, int height) {
685
            RasterDataStore store = this.getDataStore();
686
            if( store == null ) {
687
                String msg = "Can't get RasterDataStore associated to this layer ("+this.toString()+").";
688
                logger.warn(msg);
689
                throw new RuntimeException(msg);
690
            }
691
            mustSplitRequest = (!store.isTiled() && (width > maxTileDrawWidth || height > maxTileDrawHeight));
692
        }
693

    
694
        public ComposedLayer newComposedLayer() {
695
                Preferences prefs = Preferences.userRoot().node("gvsig.wms");
696

    
697
                /*
698
                 * from java.util.prefs import Preferences
699
                 * prefs = Preferences.userRoot().node("gvsig.wms")
700
                 * prefs.put("useComposedLayer","true")
701
                 */
702

    
703
                String str = prefs.get("useComposedLayer","false");
704
                Boolean useComposedLayer = Boolean.TRUE; // por defecto ya se usan
705
                try {
706
                        useComposedLayer = Boolean.valueOf(str);
707
                } catch (Exception e) {
708

    
709
                }
710
                if (useComposedLayer.booleanValue()) {
711
                        return new ComposedLayerWMS();
712
                } else {
713
                        return null;
714
                }
715
        }
716

    
717
        /*
718
         * Checks if can make a single petition for the two layers to the server
719
         * @see com.iver.cit.gvsig.fmap.layers.ComposedLayerWMS#canAdd(com.iver.cit.gvsig.fmap.layers.FLayer)
720
         */
721
        boolean isComposedLayerCompatible(FLayer layer) {
722
                FLyrWMS aLayer;
723

    
724
                if (!(layer instanceof FLyrWMS)) {
725
                        return false;
726
                }
727
                aLayer = (FLyrWMS)layer;
728
                if (!getParameters().getURI().equals(aLayer.getParameters().getURI())) {
729
                        return false;
730
                }
731

    
732
                WMSDataParameters p = getWMSParameters(getDataStore().getParameters());
733

    
734
                if (!p.getFormat().equals(aLayer.getParameters().getFormat())) {
735
                        return false;
736
                }
737
                if (!p.getSRS().equals(aLayer.getParameters().getSRS())) {
738
                        return false;
739
                }
740
                if (p.getInfoLayerQuery() != null) {
741
                        if (!p.getInfoLayerQuery().equals(aLayer.getParameters().getInfoLayerQuery())) {
742
                                return false;
743
                        }
744
                }else if (p.getInfoLayerQuery() != null) {
745
                        return false;
746
                }
747

    
748

    
749
                // isFixedSize es privado
750
                if ((getParameters().getFixedSize() != null) &&
751
                                (aLayer.getParameters().getFixedSize() != null)) {
752
                        if (getParameters().getFixedSize().equals(aLayer.getParameters().getFixedSize())) {
753
                                return false;
754
                        }
755
                } else if ((getParameters().getFixedSize() != null) != (aLayer.getParameters().getFixedSize() != null)) {
756
                        return false;
757
                }
758

    
759
                // time elevation (dimensions)
760
                if ((p.getDimensions() != null) &&
761
                                (aLayer.getParameters().getDimensions() != null)) {
762
                        if (p.getDimensions().size() != aLayer.getParameters().getDimensions().size()) {
763
                                return false;
764
                        } else {
765
                                Iterator<String> iter = p.getDimensions().iterator();
766
                                while (iter.hasNext()) {
767
                                        if (!aLayer.getParameters().getDimensions().contains(iter.next())) {
768
                                                return false;
769
                                        }
770
                                }
771
                        }
772

    
773
                } else if ((p.getDimensions() != null) != (aLayer.getParameters().getDimensions() != null)) {
774
                        return false;
775
                }
776

    
777
                return true;
778
        }
779

    
780
        public boolean isActionEnabled(int action) {
781
                switch (action) {
782
                case IRasterLayerActions.ZOOM_PIXEL_RESOLUTION:
783
                case IRasterLayerActions.FLYRASTER_BAR_TOOLS:
784
                case IRasterLayerActions.BANDS_FILE_LIST:
785
                case IRasterLayerActions.COLOR_TABLE:
786
                case IRasterLayerActions.GEOLOCATION:
787
                case IRasterLayerActions.PANSHARPENING:
788
                case IRasterLayerActions.SAVE_COLORINTERP:
789
                case IRasterLayerActions.SAVEAS:
790
                case IRasterLayerActions.BANDS_RGB:
791
                case IRasterLayerActions.ENHANCED:
792
                case IRasterLayerActions.STATS:
793
                case IRasterLayerActions.NODATA:
794
                        return false;
795
                case IRasterLayerActions.REMOTE_ACTIONS:
796
                        return true;
797
                }
798

    
799
                return super.isActionEnabled(action);
800
        }
801

    
802
        public ILegend getLegend() {
803
                if(getDataStore() != null) {
804
                        Image img = getDataStore().getImageLegend();
805
                        if(img != null)
806
                                return new ImageLegend(img);
807
                }
808
                return null;
809
        }
810

    
811
        public boolean isRemote() {
812
                return true;
813
        }
814

    
815
        public boolean overviewsSupport() {
816
                return false;
817
        }
818

    
819
        protected void updateDrawVersion() {
820
                if (this.disableUpdateDrawVersion != null){
821

    
822
                        Thread curThread = Thread.currentThread();
823

    
824
                        Thread aThread;
825

    
826
                        Iterator<WeakReference<Thread>> iter = this.disableUpdateDrawVersion.iterator();
827
                        while (iter.hasNext()){
828
                                aThread = (Thread) ((WeakReference<?>)iter.next()).get();
829
                                if (aThread == null){
830
                                        iter.remove();
831
                                } else if(aThread.equals(curThread)){
832
                                        return;
833
                                }
834
                        }
835
                }
836
                //                Exception ex = new Exception();
837
                //                ex.printStackTrace();
838
                super.updateDrawVersion();
839
        }
840

    
841
        protected void disableUpdateDrawVersion() {
842
                if (this.disableUpdateDrawVersion == null) {
843
                        this.disableUpdateDrawVersion = new ArrayList<WeakReference<Thread>>();
844
                }
845
                this.disableUpdateDrawVersion.add(new WeakReference<Thread>(Thread.currentThread()));
846
        }
847

    
848
        protected void enableUpdateDrawVersion() {
849
                if (this.disableUpdateDrawVersion == null){
850
                        return;
851
                }
852
                Thread curThread = Thread.currentThread();
853
                Thread aThread;
854

    
855
                Iterator<WeakReference<Thread>> iter = this.disableUpdateDrawVersion.iterator();
856
                while (iter.hasNext()) {
857
                        aThread = (Thread) ((WeakReference<?>)iter.next()).get();
858
                        if (aThread == null) {
859
                                iter.remove();
860
                        } else if(aThread.equals(curThread)) {
861
                                iter.remove();
862
                                break;
863
                        }
864
                }
865

    
866
        }
867

    
868
        private Rectangle2D.Double getRectable2DFromEnvelope(Envelope env) {
869
                return new Rectangle2D.Double(env.getMinimum(0), env.getMinimum(1), env
870
                                .getLength(0), env.getLength(1));
871
        }
872

    
873
        /*private Envelope getEnvelopeFromRectable2D(Rectangle2D rect) {
874
                try {
875
                        return geomManager.createEnvelope(rect.getMinX(), rect.getMinY(),
876
                                        rect.getMaxX(), rect.getMaxY(),
877
                                        SUBTYPES.GEOM2D);
878
                } catch (CreateEnvelopeException e) {
879
                        logger.error("Error creating the envelope", e);
880
                }
881
                return null;
882
        }*/
883

    
884
        @Override
885
        public String getFileFormat() {
886
                return "WMS";
887
        }
888

    
889
        @Override
890
        public FLayer getFileLayer() throws RasterDriverException {
891
                /*if(getDataStore() instanceof DefaultRemoteRasterStore) {
892
                        RemoteRasterProvider prov = (RemoteRasterProvider)((DefaultRemoteRasterStore)getDataStore()).getProvider(0);
893
                        File file = null;
894

895
                        if(getParameters().isSizeFixed()) {
896
                                file = prov.getFileLayer();
897
                        } else {
898
                                file = prov.getLastRequest();
899
                        }
900

901
                        if(file == null)
902
                                return null;
903

904
                        try {
905
                                return DefaultFLyrRaster.createLayer("tmp", file);
906
                        } catch (LoadLayerException e) {
907
                                throw new RasterDriverException(e.getMessage(), e);
908
                        }
909
                }*/
910
                return null;
911
        }
912

    
913
        /**
914
         * Devuelve el envelope en la proyeccion de la vista
915
         */
916
        public Envelope getFullEnvelope() {
917
                Extent e1 = getDataStore().getExtent();
918
                Envelope rAux = null;
919
                try {
920
                        rAux = geomManager.createEnvelope(e1.getMin().getX(), e1.getMin().getY(), e1.getMax().getX(), e1.getMax().getY(), SUBTYPES.GEOM2D);
921
                } catch (CreateEnvelopeException exc) {
922
                        logger.error("Error creating the envelope", exc);
923
                }
924

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

    
954
        }
955

    
956
        public Extent getFullRasterExtent() {
957
                return getExtentFromEnvelope(getFullEnvelope());
958
        }
959

    
960
        public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p, double tolerance) throws LoadLayerException, DataException {
961
                Point p1 = new Point((int)p.getX(), (int)p.getY());
962
                return getInfo(p1, tolerance, null, false);
963
        }
964

    
965
        @Override
966
        public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel,
967
                        boolean fast) throws LoadLayerException, DataException {
968

    
969
                //try {
970
                ViewPort viewPort = getMapContext().getViewPort();
971

    
972
                getParameters().setExtent(this.getRectable2DFromEnvelope(viewPort.getAdjustedEnvelope()));
973
                if(getParameters().isSizeFixed()) {
974
                        getParameters().setWidth((int)getParameters().getFixedSize().getWidth());
975
                        getParameters().setHeight((int)getParameters().getFixedSize().getHeight());
976
                } else {
977
                        getParameters().setWidth(viewPort.getImageWidth());
978
                        getParameters().setHeight(viewPort.getImageHeight());
979
                }
980

    
981
                CancelTaskImpl cancellable = new CancelTaskImpl(cancel);
982
                getParameters().setCancellable(cancellable);
983

    
984
                String fInfo;
985
                try {
986
                        //Point2D pt = new Point2D.Double();
987
                        //try {
988
                                //viewPort.getAffineTransform().transform(p, pt);
989
                        /*} catch (NoninvertibleTransformException e) {
990
                                return null;
991
                        }*/
992

    
993
                        Extent bbox = getExtentFromEnvelope(viewPort.getAdjustedEnvelope());
994
                        fInfo = getDataStore().getInfoByPoint(p.getX(),
995
                                        p.getY(),
996
                                        bbox,
997
                                        viewPort.getImageWidth(),
998
                                        viewPort.getImageHeight(),
999
                                        cancellable);
1000
                } catch (InfoByPointException e) {
1001
                        throw new LoadLayerException("Error in getInfoByPoint", e);
1002
                }
1003
                return new DynObjectSetWMSInfo(fInfo, getParameters().getInfoFormat());
1004
        }
1005

    
1006
        private Extent getExtentFromEnvelope(Envelope env) {
1007
                double minx = env.getMinimum(0);
1008
                double miny = env.getMinimum(1);
1009
                double maxx = env.getMaximum(0);
1010
                double maxy = env.getMaximum(1);
1011
                Point2D ul = new Point2D.Double(minx, maxy);
1012
                Point2D ur = new Point2D.Double(maxx, maxy);
1013
                Point2D ll = new Point2D.Double(minx, miny);
1014
                Point2D lr = new Point2D.Double(maxx, miny);
1015
                return rManager.getDataStructFactory().createExtent(ul, lr, ur, ll);
1016
        }
1017

    
1018
    /**
1019
     * Sets the data store parameters
1020
     * @param params
1021
     * @throws InitializeException
1022
     */
1023
    public void setParameters(DataStoreParameters params) throws InitializeException {
1024
            if(params instanceof TileDataParameters) {
1025
                        ((TileDataParameters)params).deleteCache(deleteCache);
1026
                }
1027

    
1028
            DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
1029
                try {
1030
                        DataStore dStore = dataman.openStore(params.getDataStoreName(), params);
1031
                        this.setDataStore(dStore);
1032

    
1033
                        if(params instanceof WMSDataParameters) {
1034
                                this.setName(((WMSDataParameters)params).getURI().getPath());
1035
                        }
1036

    
1037
                        if(params instanceof TileDataParameters) {
1038
                                DataParameters p = ((TileDataParameters) params).getDataParameters();
1039
                                if(p instanceof WMSDataParameters) {
1040
                                        this.setName(((WMSDataParameters) p).getURI().getPath());
1041
                                }
1042
                        }
1043
                } catch (ValidateDataParametersException e) {
1044
                        throw new InitializeException(e);
1045
                } catch (ProviderNotRegisteredException e) {
1046
                        throw new InitializeException(e);
1047
                } catch (LoadLayerException e) {
1048
                        throw new InitializeException(e);
1049
                }
1050
    }
1051

    
1052
        public WMSDataParameters getParameters() {
1053
                return getWMSParameters(getDataStore().getParameters());
1054
    }
1055

    
1056
    /**
1057
     * Gets <code>WMSDataParameters</code>
1058
     * @param parameters
1059
     * @return
1060
     */
1061
    private WMSDataParameters getWMSParameters(DataStoreParameters parameters) {
1062
            WMSDataParameters params = null;
1063
            if(parameters instanceof WMSDataParameters) {
1064
                        params = (WMSDataParameters) parameters;
1065
                }
1066

    
1067
                if(parameters instanceof TileDataParameters) {
1068
                        DataParameters p = ((TileDataParameters) parameters).getDataParameters();
1069
                        if(p instanceof WMSDataParameters) {
1070
                                params = (WMSDataParameters) p;
1071
                        }
1072
                }
1073
                return params;
1074
    }
1075

    
1076
    /**
1077
         * Assigns the flag to delete this layer from the cache
1078
         * @param selected
1079
         */
1080
        public void deleteCache(boolean deleteCache) {
1081
                this.deleteCache = deleteCache;
1082
        }
1083

    
1084
    /**
1085
     * Sets the explorer
1086
     * @param explorer
1087
     */
1088
    public void setExplorer(WMSServerExplorer explorer) {
1089
            if(getDataStore() != null)
1090
                    getDataStore().setExplorer(explorer);
1091
    }
1092

    
1093
    /**
1094
     * Gets the explorer
1095
     * @return
1096
     */
1097
    public WMSServerExplorer getExplorer() {
1098
            try {
1099
                        return (WMSServerExplorer)getDataStore().getExplorer();
1100
                } catch (ValidateDataParametersException e) {
1101
                        logger.debug("Error getting the explorer", e);
1102
                } catch (DataException e) {
1103
                        logger.debug("Error getting the explorer", e);
1104
                }
1105
            return null;
1106
    }
1107

    
1108
        public FLayer cloneLayer() throws Exception {
1109
                RasterDataStore  ds = dataStore.cloneDataStore();
1110
                FLyrWMS newLayer = new FLyrWMS();
1111
                newLayer.setName(getName());
1112
                newLayer.setOpenRasterStore(ds);
1113
                //newLayer.firstLoad = firstLoad;
1114
                newLayer.setExplorer(getExplorer());
1115

    
1116
                List<RasterFilter> filters = getRender().getFilterList().getStatusCloned();
1117

    
1118
                //Hacemos una copia de las bandas a renderizar
1119
                ColorInterpretation ci = getRender().getRenderColorInterpretation();
1120
                if(ci != null) {
1121
                        newLayer.getRender().setRenderColorInterpretation(ci.cloneColorInterpretation());
1122
                }
1123

    
1124
                //Asignamos el entorno
1125
                if(newLayer.getRender().getFilterList() == null)
1126
                        newLayer.getRender().setFilterList(RasterLocator.getManager().createEmptyFilterList(getRender().getFilterList().getInitDataType()));
1127
                newLayer.getRender().getFilterList().setEnv(getRender().getFilterList().getEnv());
1128
                newLayer.getRender().getFilterList().setStatus(filters);
1129

    
1130
                // Asignamos los valores noData del original
1131
                newLayer.setNoDataValue(getNoDataValue());
1132
                if(dataStore.getNoDataValue().isDefined())
1133
                        newLayer.setNoDataTransparent(true);
1134
                newLayer.enableOpen();
1135

    
1136
                return newLayer;
1137
        }
1138

    
1139
        @Override
1140
        public boolean isInside(Point2D p) {
1141
                // Don't call the data store isInside method, as the data store
1142
                // parameters change for every WMS tile that is drawn, so it does not
1143
                // return sensible results.
1144
                return rManager.getRasterUtils().isInside(p, getDataStore().getExtent());
1145
        }
1146
}