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

History | View | Annotate | Download (36.4 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.Point;
28
import java.awt.Rectangle;
29
import java.awt.geom.AffineTransform;
30
import java.awt.geom.NoninvertibleTransformException;
31
import java.awt.geom.Point2D;
32
import java.awt.geom.Rectangle2D;
33
import java.awt.image.BufferedImage;
34
import java.lang.ref.WeakReference;
35
import java.util.ArrayList;
36
import java.util.HashMap;
37
import java.util.Iterator;
38
import java.util.List;
39
import java.util.Vector;
40
import java.util.prefs.Preferences;
41

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

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

    
111

    
112

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

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

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

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

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

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

    
293
                if (isWithinScale(scale)) {
294

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

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

    
341
                // 2. Compute extent to be requested.
342
                Rectangle2D bBox = new Rectangle2D.Double();
343
                Rectangle2D.intersect(getRectable2DFromEnvelope(vpEnv),
344
                                getRectable2DFromEnvelope(envelope), bBox);
345

    
346
                // 3. Compute size in pixels
347
                double scalex = vp.getAffineTransform().getScaleX();
348
                double scaley = vp.getAffineTransform().getScaleY();
349
                int wImg = (int) Math.ceil(Math.abs(bBox.getWidth() * scalex) + 1);
350
                int hImg = (int) Math.ceil(Math.abs(bBox.getHeight() * scaley) + 1);
351

    
352
                Dimension sz = new Dimension(wImg, hImg);
353

    
354
                if ((wImg <= 0) || (hImg <= 0)) {
355
                        return;
356
                }
357

    
358
                //try {
359
                        
360
                        Rectangle2D extent = new Rectangle2D.Double();
361
                        Rectangle2D.Double vpExtent = this.getRectable2DFromEnvelope(vpEnv);
362
                        Rectangle2D.intersect(vpExtent, bBox, extent);
363
                        
364
                        Extent ex = rManager.getDataStructFactory().createExtent(
365
                                        vp.getAdjustedEnvelope().getMinimum(0), 
366
                                        vp.getAdjustedEnvelope().getMaximum(1), 
367
                                        vp.getAdjustedEnvelope().getMaximum(0), 
368
                                        vp.getAdjustedEnvelope().getMinimum(1));
369
                        ViewPortData vpData = rManager.getDataStructFactory().createViewPortData(vp.getProjection(), ex, sz );
370
                        vpData.setMat(vp.getAffineTransform());
371

    
372
                        try {
373
                                getParameters().setExtent(bBox);
374
                                if(getParameters().isSizeFixed()) {
375
                                        getParameters().setWidth((int)getParameters().getFixedSize().getWidth());
376
                                        getParameters().setHeight((int)getParameters().getFixedSize().getHeight());
377
                                } else {
378
                                        getParameters().setWidth(wImg);
379
                                        getParameters().setHeight(hImg);
380
                                }
381
                                
382
                                if(getDataStore().getParameters() instanceof WMSDataParameters) {
383
                                        getRender().draw(g, vpData, taskStatus);
384
                                } else {
385
                                        Envelope adjustedExtent = vp.getAdjustedExtent();
386
                                        Extent e = rManager.getDataStructFactory().createExtent(adjustedExtent.getLowerCorner().getX(),
387
                                                        adjustedExtent.getUpperCorner().getY(), adjustedExtent.getUpperCorner().getX(),
388
                                                        adjustedExtent.getLowerCorner().getY());
389
                                        ViewPortData vp2 = rManager.getDataStructFactory().createViewPortData(vp.getProjection(), e, vp.getImageSize() );
390
                                        vp2.setMat(vp.getAffineTransform());
391
                                        getParameters().setExtent(ex.toRectangle2D());
392
                                        getRender().drawTiledService(g, vp2, vp.getImageSize(), taskStatus);
393
                                }
394
                                //this.updateDrawVersion();
395
                        
396
                        } catch (ProcessInterruptedException e) {
397
                        } catch (QueryException e) {
398
                                setAvailable(false);
399
                                JOptionPane.showMessageDialog(null, "Problems drawing this layer:" + e.getMessage(), Messages.getText("Error"), JOptionPane.ERROR_MESSAGE);
400
                                logger.info("Problems drawing this layer:" + e.getMessage(), e);
401
                        } finally {
402
                                taskStatus.terminate();                                
403
                        }
404

    
405
                /*} catch (RemoteServiceException e) {
406
                        if (!taskStatus.isCancellationRequested()) {
407
                                if (callCount < MAX_RETRY_TIMES) {
408
                                        logger.warn("\n[ FLyrWMS.drawFixedSize() ]  Failed in trying " + callCount + "/" + MAX_RETRY_TIMES + ")\n"); // mess code
409
                                        drawTile(g, vp, taskStatus, scale);
410
                                } else {
411
                                        if (!isPrinting) {
412
                                                this.setVisible(false);
413
                                        }
414
                                        logger.error("Server error:" + e.getMessage(), e);
415
                                }
416
                        }
417
                }*/
418
                return;
419
        }
420

    
421
        /**
422
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#print(java.awt.Graphics2D,
423
         *                 com.iver.cit.gvsig.fmap.ViewPort,
424
         *                 com.iver.cit.gvsig.fmap.operations.Cancellable)
425
         */
426
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, double scale, PrintRequestAttributeSet properties)
427
        throws ReadException {
428
                TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
429
                SimpleTaskStatus taskStatus = new RasterTaskStatus("Printing " + getName() + "...", cancel);
430
                manager.add(taskStatus);
431
                taskStatus.setAutoremove(true);
432

    
433
                if (isVisible() && isWithinScale(scale)){
434
                        if (!mustTilePrint) {
435
                                draw(null, g, viewPort, cancel,scale);
436
                        } else {
437
                                Tiling tiles = new Tiling(maxTilePrintWidth, maxTilePrintHeight, g.getClipBounds());
438
                                tiles.setAffineTransform((AffineTransform) viewPort.getAffineTransform().clone());
439
                                for (int tileNr = 0; tileNr < tiles.getNumTiles(); tileNr++) {
440
                                        // Parte que dibuja
441
                                        try {
442
                                                ViewPort vp = tiles.getTileViewPort(viewPort, tileNr);
443
                                                drawTile(g, vp, taskStatus, scale);
444
                                        } catch (NoninvertibleTransformException e) {
445
                                                throw new ReadException(e.getMessage(), e);
446
                                        } catch (LoadLayerException e) {
447
                                                throw new ReadException(e.getMessage(), e);
448
                                        }
449
                                }
450
                        }
451
                }
452
                taskStatus.terminate();
453
        }
454

    
455
        public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
456
                        double scale) throws ReadException {
457
                draw(null, g, viewPort, cancel,scale);
458
        }
459

    
460
        public HashMap<String, Object> getProperties() {
461
                HashMap<String, Object> info = new HashMap<String, Object>();
462
                String[] layerNames = getParameters().getLayerQuery().split(",");
463
                Vector<WMSLayerNode> layers = new Vector<WMSLayerNode>(layerNames.length);
464
                try {
465
                        //explorer.connect(null);
466
                        for (int i = 0; i < layerNames.length; i++) {
467
                                layers.add(i, getExplorer().getLayer(layerNames[i]));
468
                        }
469
                        info.put("name", getName());
470
                        info.put("selectedLayers", layers);
471
                        info.put("host", getParameters().getURI());
472
                        info.put("srs", getParameters().getSRSCode());
473
                        info.put("format", getParameters().getFormat());
474
                        info.put("infoformat", getParameters().getInfoFormat());
475
                        info.put("wmsTransparency", new Boolean(getParameters().isWmsTransparent()));
476
                        info.put("styles", getParameters().getStyles());
477
                        info.put("dimensions", getParameters().getDimensions());
478
                        info.put("fixedSize", getParameters().getFixedSize());
479
                        return info;
480
                } catch (Exception e) {
481
                        e.printStackTrace();
482
                }
483
                return null;
484
        }
485

    
486
        /**
487
         * Creates the part of a OGC's MapContext document that would describe this
488
         * layer(s).
489
         * @param version, The desired version of the resulting document. (1.1.0)
490
         * @return String containing the xml.
491
         * @throws UnsupportedVersionLayerException
492
         */
493
        @SuppressWarnings({ "unchecked", "rawtypes" })
494
        public String toMapContext(String mapContextVersion) {
495
                XmlBuilder xml = new XmlBuilder();
496
                
497
                String query = getParameters().getLayerQuery();
498
                String[] layerNames = query.split(",");
499
                List<RemoteWMSStyle> styleList = getParameters().getStyles();
500
                for (int i = 0; i < layerNames.length; i++) {
501
                        WMSLayerNode layer = getExplorer().getLayer(layerNames[i]);
502
                        HashMap xmlAttrs = new HashMap();
503

    
504
                        // <Layer>
505
                        xmlAttrs.put(WebMapContextTags.HIDDEN, !isVisible() + "");
506
                        xmlAttrs.put(WebMapContextTags.QUERYABLE, getExplorer().isQueryable() + "");
507
                        xml.openTag(WebMapContextTags.LAYER, xmlAttrs);
508
                        xmlAttrs.clear();
509
                        if (mapContextVersion.equals("1.1.0") || mapContextVersion.equals("1.0.0")) {
510
                                // <Server>
511
                                xmlAttrs.put(WebMapContextTags.SERVICE, WebMapContextTags.WMS);
512
                                xmlAttrs.put(WebMapContextTags.VERSION, getExplorer().getVersion());
513
                                xmlAttrs.put(WebMapContextTags.SERVER_TITLE, getExplorer().getServiceTitle());
514
                                xml.openTag(WebMapContextTags.SERVER, xmlAttrs);
515
                                xmlAttrs.clear();
516

    
517
                                // <OnlineResource>
518
                                xmlAttrs.put(WebMapContextTags.XLINK_TYPE, "simple");
519
                                xmlAttrs.put(WebMapContextTags.XLINK_HREF, getParameters().getURI().toString());
520
                                xml.writeTag(WebMapContextTags.ONLINE_RESOURCE, xmlAttrs);
521
                                xmlAttrs.clear();
522
                                // </OnlineResource>
523

    
524
                                xml.closeTag();
525
                                // </Server>
526

    
527
                                // <Name>
528
                                xml.writeTag(WebMapContextTags.NAME, layer.getName().trim());
529
                                // </Name>
530

    
531
                                // <Title>
532
                                xml.writeTag(WebMapContextTags.TITLE, layer.getTitle().trim());
533
                                //?xml.writeTag(WebMapContextTags.TITLE, getName().trim());
534
                                // </Title>
535

    
536
                                // <Abstract>
537
                                if (layer.getAbstract() != null) {
538
                                        xml.writeTag(WebMapContextTags.ABSTRACT, layer.getAbstract());
539
                                        // </Abstract>
540
                                }
541

    
542
                                // <SRS> (a list of available SRS for the enclosing layer)
543
                                String[] strings = (String[]) layer.getAllSrs().toArray(new String[0]);
544
                                String mySRS = strings[0];
545
                                for (int j = 1; j < strings.length; j++) {
546
                                        mySRS += ","+strings[j];
547
                                }
548
                                xml.writeTag(WebMapContextTags.SRS, mySRS);
549
                                // </SRS>
550

    
551
                                // <FormatList>
552
                                xml.openTag(WebMapContextTags.FORMAT_LIST);
553
                                strings = getExplorer().getFormats();
554
                                for (int j = 0; j < strings.length; j++) {
555
                                        // <Format>
556
                                        String str = strings[j].trim();
557
                                        if (str.equals(getParameters().getFormat())) {
558
                                                xml.writeTag(WebMapContextTags.FORMAT, str, WebMapContextTags.CURRENT, "1");
559
                                        } else {
560
                                                xml.writeTag(WebMapContextTags.FORMAT, str);
561
                                                // </Format>
562
                                        }
563
                                }
564
                                xml.closeTag();
565
                                // </FormatList>
566

    
567
                                // <StyleList>
568
                                xml.openTag(WebMapContextTags.STYLE_LIST);
569

    
570
                                if (layer.getStyles().size() > 0) {
571
                                        for (int j = 0; j < layer.getStyles().size(); j++) {
572
                                                // <Style>
573
                                                RemoteWMSStyle st = layer.getStyles().get(j);
574
                                                if (st.getName().equals(styleList.get(i).getName())) {
575
                                                        xmlAttrs.put(WebMapContextTags.CURRENT, "1");
576
                                                }
577
                                                xml.openTag(WebMapContextTags.STYLE, xmlAttrs);
578
                                                xmlAttrs.clear();
579

    
580
                                                // <Name>
581
                                                xml.writeTag(WebMapContextTags.NAME, st.getName());
582
                                                // </Name>
583

    
584
                                                // <Title>
585
                                                xml.writeTag(WebMapContextTags.TITLE, st.getTitle());
586
                                                // </Title>
587

    
588
                                                // <LegendURL width="180" format="image/gif" height="50">
589
                                                // <OnlineResource xlink:type="simple" xlink:href="http://globe.digitalearth.gov/globe/en/icons/colorbars/NATIONAL.gif"/>
590
                                                // </OnlineResource>
591
                                                // </LegendURL>
592
                                                xml.closeTag();
593
                                                // </Style>
594

    
595
                                        }
596

    
597
                                } else {
598
                                        // Create fake style (for compatibility issues)
599
                                        xmlAttrs.put(WebMapContextTags.CURRENT, "1");
600
                                        // <Style>
601
                                        xml.openTag(WebMapContextTags.STYLE, xmlAttrs);
602
                                        xmlAttrs.clear();
603
                                        // <Name>
604
                                        xml.writeTag(WebMapContextTags.NAME, "default");
605
                                        // </Name>
606

    
607
                                        // <Title>
608
                                        xml.writeTag(WebMapContextTags.TITLE, "default");
609
                                        xml.closeTag();
610
                                }
611
                                // </StyleList>
612
                                xml.closeTag();
613
                                if (mapContextVersion.compareTo("1.0.0") > 0) {
614
                                        // <DimensionList>
615
                                        xml.openTag(WebMapContextTags.DIMENSION_LIST);
616
                                        // <Dimension>
617
                                        // </Dimension>
618
                                        xml.closeTag();
619
                                        // </DimensionList>
620
                                }
621
                        } else {
622
                                xml.writeTag("ERROR", PluginServices.getText(this, "unsupported_map_context_version"));
623
                        }
624
                        // </Layer>
625
                        xml.closeTag();
626
                }
627
                return xml.getXML();
628
        }
629

    
630
        public String getTocImageIcon() {
631
                return "icon-layer-wms";
632
        }
633

    
634
        public int[] getTileSize() {
635
                int[] size = {maxTileDrawWidth, maxTileDrawHeight};
636
                return size;
637
        }
638

    
639
        public boolean isTiled() {
640
                return mustTileDraw;
641
        }
642

    
643
        public ComposedLayer newComposedLayer() {
644
                Preferences prefs = Preferences.userRoot().node("gvsig.wms");
645

    
646
                /*
647
                 * from java.util.prefs import Preferences
648
                 * prefs = Preferences.userRoot().node("gvsig.wms")
649
                 * prefs.put("useComposedLayer","true")
650
                 */
651

    
652
                String str = prefs.get("useComposedLayer","false");
653
                Boolean useComposedLayer = Boolean.TRUE; // por defecto ya se usan
654
                try {
655
                        useComposedLayer = Boolean.valueOf(str);
656
                } catch (Exception e) {
657

    
658
                }
659
                if (useComposedLayer.booleanValue()) {
660
                        return new ComposedLayerWMS();
661
                } else {
662
                        return null;
663
                }
664
        }
665

    
666
        /*
667
         * Checks if can make a single petition for the two layers to the server
668
         * @see com.iver.cit.gvsig.fmap.layers.ComposedLayerWMS#canAdd(com.iver.cit.gvsig.fmap.layers.FLayer)
669
         */
670
        boolean isComposedLayerCompatible(FLayer layer) {
671
                FLyrWMS aLayer;
672

    
673
                if (!(layer instanceof FLyrWMS)) {
674
                        return false;
675
                }
676
                aLayer = (FLyrWMS)layer;
677
                if (!getParameters().getURI().equals(aLayer.getParameters().getURI())) {
678
                        return false;
679
                }
680
                
681
                WMSDataParameters p = getWMSParameters(getDataStore().getParameters()); 
682
                                
683
                if (!p.getFormat().equals(aLayer.getParameters().getFormat())) {
684
                        return false;
685
                }
686
                if (!p.getSRS().equals(aLayer.getParameters().getSRS())) {
687
                        return false;
688
                }
689
                if (p.getInfoLayerQuery() != null) {
690
                        if (!p.getInfoLayerQuery().equals(aLayer.getParameters().getInfoLayerQuery())) {
691
                                return false;
692
                        }
693
                }else if (p.getInfoLayerQuery() != null) {
694
                        return false;
695
                }
696

    
697

    
698
                // isFixedSize es privado
699
                if ((getParameters().getFixedSize() != null) &&
700
                                (aLayer.getParameters().getFixedSize() != null)) {
701
                        if (getParameters().getFixedSize().equals(aLayer.getParameters().getFixedSize())) {
702
                                return false;
703
                        }
704
                } else if ((getParameters().getFixedSize() != null) != (aLayer.getParameters().getFixedSize() != null)) {
705
                        return false;
706
                }
707

    
708
                // time elevation (dimensions)
709
                if ((p.getDimensions() != null) &&
710
                                (aLayer.getParameters().getDimensions() != null)) {
711
                        if (p.getDimensions().size() != aLayer.getParameters().getDimensions().size()) {
712
                                return false;
713
                        } else {
714
                                Iterator<String> iter = p.getDimensions().iterator();
715
                                while (iter.hasNext()) {
716
                                        if (!aLayer.getParameters().getDimensions().contains(iter.next())) {
717
                                                return false;
718
                                        }
719
                                }
720
                        }
721

    
722
                } else if ((p.getDimensions() != null) != (aLayer.getParameters().getDimensions() != null)) {
723
                        return false;
724
                }
725

    
726
                return true;
727
        }
728

    
729
        public boolean isActionEnabled(int action) {
730
                switch (action) {
731
                case IRasterLayerActions.ZOOM_PIXEL_RESOLUTION:
732
                case IRasterLayerActions.FLYRASTER_BAR_TOOLS:
733
                case IRasterLayerActions.BANDS_FILE_LIST:
734
                case IRasterLayerActions.COLOR_TABLE:
735
                case IRasterLayerActions.GEOLOCATION:
736
                case IRasterLayerActions.PANSHARPENING:
737
                case IRasterLayerActions.SAVE_COLORINTERP:
738
                case IRasterLayerActions.SAVEAS:
739
                case IRasterLayerActions.BANDS_RGB:
740
                case IRasterLayerActions.ENHANCED:
741
                case IRasterLayerActions.STATS:
742
                case IRasterLayerActions.NODATA:
743
                        return false;
744
                case IRasterLayerActions.REMOTE_ACTIONS:
745
                        return true;
746
                }
747

    
748
                return super.isActionEnabled(action);
749
        }
750

    
751
        public ILegend getLegend() {
752
                if(getDataStore() != null)
753
                        return new ImageLegend(getDataStore().getImageLegend());
754
                return null;
755
        }
756
        
757
        public boolean isRemote() {
758
                return true;
759
        }
760

    
761
        public boolean overviewsSupport() {
762
                return false;
763
        }
764

    
765
        protected void updateDrawVersion() {
766
                if (this.disableUpdateDrawVersion != null){
767

    
768
                        Thread curThread = Thread.currentThread();
769

    
770
                        Thread aThread;
771

    
772
                        Iterator<WeakReference<Thread>> iter = this.disableUpdateDrawVersion.iterator();
773
                        while (iter.hasNext()){
774
                                aThread = (Thread) ((WeakReference<?>)iter.next()).get();
775
                                if (aThread == null){
776
                                        iter.remove();
777
                                } else if(aThread.equals(curThread)){
778
                                        return;
779
                                }
780
                        }
781
                }
782
                //                Exception ex = new Exception();
783
                //                ex.printStackTrace();
784
                super.updateDrawVersion();
785
        }
786

    
787
        protected void disableUpdateDrawVersion() {
788
                if (this.disableUpdateDrawVersion == null) {
789
                        this.disableUpdateDrawVersion = new ArrayList<WeakReference<Thread>>();
790
                }
791
                this.disableUpdateDrawVersion.add(new WeakReference<Thread>(Thread.currentThread()));
792
        }
793

    
794
        protected void enableUpdateDrawVersion() {
795
                if (this.disableUpdateDrawVersion == null){
796
                        return;
797
                }
798
                Thread curThread = Thread.currentThread();
799
                Thread aThread;
800

    
801
                Iterator<WeakReference<Thread>> iter = this.disableUpdateDrawVersion.iterator();
802
                while (iter.hasNext()) {
803
                        aThread = (Thread) ((WeakReference<?>)iter.next()).get();
804
                        if (aThread == null) {
805
                                iter.remove();
806
                        } else if(aThread.equals(curThread)) {
807
                                iter.remove();
808
                                break;
809
                        }
810
                }
811

    
812
        }
813

    
814
        private Rectangle2D.Double getRectable2DFromEnvelope(Envelope env) {
815
                return new Rectangle2D.Double(env.getMinimum(0), env.getMinimum(1), env
816
                                .getLength(0), env.getLength(1));
817
        }
818

    
819
        /*private Envelope getEnvelopeFromRectable2D(Rectangle2D rect) {
820
                try {
821
                        return geomManager.createEnvelope(rect.getMinX(), rect.getMinY(),
822
                                        rect.getMaxX(), rect.getMaxY(),
823
                                        SUBTYPES.GEOM2D);
824
                } catch (CreateEnvelopeException e) {
825
                        logger.error("Error creating the envelope", e);
826
                }
827
                return null;
828
        }*/
829
        
830
        @Override
831
        public String getFileFormat() {
832
                return "WMS";
833
        }
834
        
835
        @Override
836
        public FLayer getFileLayer() throws RasterDriverException {
837
                /*if(getDataStore() instanceof DefaultRemoteRasterStore) {
838
                        RemoteRasterProvider prov = (RemoteRasterProvider)((DefaultRemoteRasterStore)getDataStore()).getProvider(0);
839
                        File file = null;
840
                        
841
                        if(getParameters().isSizeFixed()) {
842
                                file = prov.getFileLayer();
843
                        } else {
844
                                file = prov.getLastRequest();
845
                        }
846
                                
847
                        if(file == null)
848
                                return null;
849
                        
850
                        try {
851
                                return DefaultFLyrRaster.createLayer("tmp", file);
852
                        } catch (LoadLayerException e) {
853
                                throw new RasterDriverException(e.getMessage(), e);
854
                        }
855
                }*/
856
                return null;
857
        }
858

    
859
        /**
860
         * Devuelve el envelope en la proyeccion de la vista
861
         */
862
        public Envelope getFullEnvelope() {
863
                Extent e1 = getDataStore().getExtent();
864
                Envelope rAux = null;
865
                try {
866
                        rAux = geomManager.createEnvelope(e1.getMin().getX(), e1.getMin().getY(), e1.getMax().getX(), e1.getMax().getY(), SUBTYPES.GEOM2D);
867
                } catch (CreateEnvelopeException exc) {
868
                        logger.error("Error creating the envelope", exc);
869
                }
870

    
871
                // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
872
                // y alto 0.
873
                if (rAux == null || rAux.getMaximum(0) - rAux.getMinimum(0) == 0
874
                                && rAux.getMaximum(1) - rAux.getMinimum(1) == 0) {
875
                        try {
876
                                rAux = geomManager.createEnvelope(0, 0, 100, 100, SUBTYPES.GEOM2D);
877
                        } catch (CreateEnvelopeException e) {
878
                                logger.error("Error creating the envelope", e);
879
                        }
880
                }
881
                // Si existe reproyecci?n, reproyectar el extent
882
                ICoordTrans ct = getCoordTrans();
883
                if (ct != null) {
884
                        Point2D pt1 = new Point2D.Double(rAux.getMinimum(0), rAux
885
                                        .getMinimum(1));
886
                        Point2D pt2 = new Point2D.Double(rAux.getMaximum(0), rAux
887
                                        .getMaximum(1));
888
                        pt1 = ct.convert(pt1, null);
889
                        pt2 = ct.convert(pt2, null);
890
                        try {
891
                                rAux = geomManager.createEnvelope(pt1.getX(), pt1.getY(), pt2
892
                                                .getX(), pt2.getY(), SUBTYPES.GEOM2D);
893
                        } catch (CreateEnvelopeException e) {
894
                                logger.error("Error creating the envelope", e);
895
                        }// new
896
                        // Rectangle2D.Double();
897
                }
898
                return rAux;
899

    
900
        }
901
        
902
        public Extent getFullRasterExtent() {
903
                return getExtentFromEnvelope(getFullEnvelope());
904
        }
905
        
906
        public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p, double tolerance) throws LoadLayerException, DataException {
907
                Point p1 = new Point((int)p.getX(), (int)p.getY());
908
                return getInfo(p1, tolerance, null, false);
909
        }
910

    
911
        @Override
912
        public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel,
913
                        boolean fast) throws LoadLayerException, DataException {
914

    
915
                //try {
916
                ViewPort viewPort = getMapContext().getViewPort();
917

    
918
                getParameters().setExtent(this.getRectable2DFromEnvelope(viewPort.getAdjustedEnvelope()));
919
                if(getParameters().isSizeFixed()) {
920
                        getParameters().setWidth((int)getParameters().getFixedSize().getWidth());
921
                        getParameters().setHeight((int)getParameters().getFixedSize().getHeight());
922
                } else {
923
                        getParameters().setWidth(viewPort.getImageWidth());
924
                        getParameters().setHeight(viewPort.getImageHeight());
925
                }
926
                
927
                CancelTaskImpl cancellable = new CancelTaskImpl(cancel);
928
                getParameters().setCancellable(cancellable);
929
                
930
                String fInfo;
931
                try {
932
                        //Point2D pt = new Point2D.Double();
933
                        //try {
934
                                //viewPort.getAffineTransform().transform(p, pt);
935
                        /*} catch (NoninvertibleTransformException e) {
936
                                return null;
937
                        }*/
938
                        
939
                        Extent bbox = getExtentFromEnvelope(viewPort.getAdjustedEnvelope());
940
                        fInfo = getDataStore().getInfoByPoint(p.getX(), 
941
                                        p.getY(), 
942
                                        bbox, 
943
                                        viewPort.getImageWidth(), 
944
                                        viewPort.getImageHeight(), 
945
                                        cancellable);
946
                } catch (InfoByPointException e) {
947
                        throw new LoadLayerException("Error in getInfoByPoint", e);
948
                }
949
                return new DynObjectSetWMSInfo(fInfo, getParameters().getInfoFormat());
950
        }
951
        
952
        private Extent getExtentFromEnvelope(Envelope env) {
953
                double minx = env.getMinimum(0);
954
                double miny = env.getMinimum(1);
955
                double maxx = env.getMaximum(0);
956
                double maxy = env.getMaximum(1);
957
                Point2D ul = new Point2D.Double(minx, maxy);
958
                Point2D ur = new Point2D.Double(maxx, maxy);
959
                Point2D ll = new Point2D.Double(minx, miny);
960
                Point2D lr = new Point2D.Double(maxx, miny);
961
                return rManager.getDataStructFactory().createExtent(ul, lr, ur, ll);
962
        }
963
    
964
    /**
965
     * Sets the data store parameters
966
     * @param params
967
     * @throws InitializeException
968
     */
969
    public void setParameters(DataStoreParameters params) throws InitializeException {
970
            if(params instanceof TileDataParameters) {
971
                        ((TileDataParameters)params).deleteCache(deleteCache);
972
                }
973
            
974
            DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
975
                try {
976
                        DataStore dStore = dataman.openStore(params.getDataStoreName(), params);
977
                        this.setDataStore(dStore);
978
                        
979
                        if(params instanceof WMSDataParameters) {
980
                                this.setName(((WMSDataParameters)params).getURI());
981
                        }
982
                        
983
                        if(params instanceof TileDataParameters) {
984
                                DataParameters p = ((TileDataParameters) params).getDataParameters();
985
                                if(p instanceof WMSDataParameters) {
986
                                        this.setName(((WMSDataParameters) p).getURI());
987
                                }
988
                        }
989
                } catch (ValidateDataParametersException e) {
990
                        throw new InitializeException(e);
991
                } catch (ProviderNotRegisteredException e) {
992
                        throw new InitializeException(e);
993
                } catch (LoadLayerException e) {
994
                        throw new InitializeException(e);
995
                }
996
    }
997
    
998
        public WMSDataParameters getParameters() {
999
                return getWMSParameters(getDataStore().getParameters());
1000
    }
1001
    
1002
    /**
1003
     * Gets <code>WMSDataParameters</code>
1004
     * @param parameters
1005
     * @return
1006
     */
1007
    private WMSDataParameters getWMSParameters(DataStoreParameters parameters) {
1008
            WMSDataParameters params = null;
1009
            if(parameters instanceof WMSDataParameters) {
1010
                        params = (WMSDataParameters) parameters;
1011
                }
1012
                
1013
                if(parameters instanceof TileDataParameters) {
1014
                        DataParameters p = ((TileDataParameters) parameters).getDataParameters();
1015
                        if(p instanceof WMSDataParameters) {
1016
                                params = (WMSDataParameters) p;
1017
                        }
1018
                }
1019
                return params;
1020
    }
1021
    
1022
    /**
1023
         * Assigns the flag to delete this layer from the cache
1024
         * @param selected
1025
         */
1026
        public void deleteCache(boolean deleteCache) {
1027
                this.deleteCache = deleteCache;
1028
        }
1029
    
1030
    /**
1031
     * Sets the explorer
1032
     * @param explorer
1033
     */
1034
    public void setExplorer(WMSServerExplorer explorer) {
1035
            if(getDataStore() != null)
1036
                    getDataStore().setExplorer(explorer);
1037
    }
1038
    
1039
    /**
1040
     * Gets the explorer
1041
     * @return
1042
     */
1043
    public WMSServerExplorer getExplorer() {
1044
            try {
1045
                        return (WMSServerExplorer)getDataStore().getExplorer();
1046
                } catch (ValidateDataParametersException e) {
1047
                        logger.debug("Error getting the explorer", e);
1048
                } catch (DataException e) {
1049
                        logger.debug("Error getting the explorer", e);
1050
                }
1051
            return null;
1052
    }
1053
    
1054
        public FLayer cloneLayer() throws Exception {
1055
                RasterDataStore  ds = dataStore.cloneDataStore();
1056
                FLyrWMS newLayer = new FLyrWMS();
1057
                newLayer.setName(getName());
1058
                newLayer.setOpenRasterStore(ds);
1059
                //newLayer.firstLoad = firstLoad;
1060
                newLayer.setExplorer(getExplorer());
1061
                
1062
                List<RasterFilter> filters = getRender().getFilterList().getStatusCloned();
1063

    
1064
                //Hacemos una copia de las bandas a renderizar
1065
                ColorInterpretation ci = getRender().getRenderColorInterpretation();
1066
                if(ci != null) {
1067
                        newLayer.getRender().setRenderColorInterpretation(ci.cloneColorInterpretation());
1068
                }
1069

    
1070
                //Asignamos el entorno
1071
                if(newLayer.getRender().getFilterList() == null)
1072
                        newLayer.getRender().setFilterList(RasterLocator.getManager().createEmptyFilterList(getRender().getFilterList().getInitDataType()));
1073
                newLayer.getRender().getFilterList().setEnv(getRender().getFilterList().getEnv());
1074
                newLayer.getRender().getFilterList().setStatus(filters);
1075

    
1076
                // Asignamos los valores noData del original
1077
                newLayer.setNoDataValue(getNoDataValue());
1078
                if(dataStore.getNoDataValue().isDefined())
1079
                        newLayer.setNoDataTransparent(true);
1080
                newLayer.enableOpen();
1081
                
1082
                return newLayer;
1083
        }
1084
        
1085

    
1086
}