Statistics
| Revision:

root / trunk / extensions / extWMS / src / com / iver / cit / gvsig / fmap / layers / FLyrWMS.java @ 37961

History | View | Annotate | Download (70.8 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
*
3
* Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
*
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
*
19
* For more information, contact:
20
*
21
*  Generalitat Valenciana
22
*   Conselleria d'Infraestructures i Transport
23
*   Av. Blasco Ib??ez, 50
24
*   46010 VALENCIA
25
*   SPAIN
26
*
27
*      +34 963862235
28
*   gvsig@gva.es
29
*      www.gvsig.gva.es
30
*
31
*    or
32
*
33
*   IVER T.I. S.A
34
*   Salamanca 50
35
*   46005 Valencia
36
*   Spain
37
*
38
*   +34 963163400
39
*   dac@iver.es
40
*/
41
package com.iver.cit.gvsig.fmap.layers;
42

    
43
import java.awt.Component;
44
import java.awt.Dimension;
45
import java.awt.Graphics2D;
46
import java.awt.Image;
47
import java.awt.Point;
48
import java.awt.Rectangle;
49
import java.awt.geom.AffineTransform;
50
import java.awt.geom.NoninvertibleTransformException;
51
import java.awt.geom.Point2D;
52
import java.awt.geom.Rectangle2D;
53
import java.awt.image.BufferedImage;
54
import java.io.File;
55
import java.io.IOException;
56
import java.lang.ref.WeakReference;
57
import java.lang.reflect.Constructor;
58
import java.lang.reflect.InvocationTargetException;
59
import java.net.MalformedURLException;
60
import java.net.URL;
61
import java.util.ArrayList;
62
import java.util.HashMap;
63
import java.util.Hashtable;
64
import java.util.Iterator;
65
import java.util.List;
66
import java.util.Map;
67
import java.util.Vector;
68
import java.util.logging.Logger;
69
import java.util.prefs.Preferences;
70

    
71
import javax.print.attribute.PrintRequestAttributeSet;
72
import javax.swing.ImageIcon;
73
import javax.swing.JOptionPane;
74

    
75
import org.cresques.geo.ViewPortData;
76
import org.cresques.px.Extent;
77
import org.exolab.castor.xml.ValidationException;
78
import org.gvsig.fmap.raster.layers.FLyrRasterSE;
79
import org.gvsig.fmap.raster.layers.IRasterLayerActions;
80
import org.gvsig.fmap.raster.layers.IStatusRaster;
81
import org.gvsig.fmap.raster.layers.StatusLayerRaster;
82
import org.gvsig.raster.dataset.CompositeDataset;
83
import org.gvsig.raster.dataset.IBuffer;
84
import org.gvsig.raster.dataset.MosaicNotValidException;
85
import org.gvsig.raster.dataset.MultiRasterDataset;
86
import org.gvsig.raster.dataset.NotSupportedExtensionException;
87
import org.gvsig.raster.dataset.io.RasterDriverException;
88
import org.gvsig.raster.grid.GridPalette;
89
import org.gvsig.raster.grid.GridTransparency;
90
import org.gvsig.raster.grid.filter.FilterTypeException;
91
import org.gvsig.raster.grid.filter.RasterFilterList;
92
import org.gvsig.raster.grid.filter.RasterFilterListManager;
93
import org.gvsig.raster.grid.filter.bands.ColorTableFilter;
94
import org.gvsig.raster.grid.filter.bands.ColorTableListManager;
95
import org.gvsig.remoteClient.utils.Utilities;
96
import org.gvsig.remoteClient.wms.ICancellable;
97
import org.gvsig.remoteClient.wms.WMSStatus;
98

    
99
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
100
import com.hardcode.gdbms.engine.data.driver.DriverException;
101
import com.iver.andami.PluginServices;
102
import com.iver.andami.messages.NotificationManager;
103
import com.iver.cit.gvsig.exceptions.layers.ConnectionErrorLayerException;
104
import com.iver.cit.gvsig.exceptions.layers.LoadLayerException;
105
import com.iver.cit.gvsig.exceptions.layers.URLLayerException;
106
import com.iver.cit.gvsig.exceptions.layers.UnsupportedVersionLayerException;
107
import com.iver.cit.gvsig.fmap.ConnectionErrorExceptionType;
108
import com.iver.cit.gvsig.fmap.MapContext;
109
import com.iver.cit.gvsig.fmap.ViewPort;
110
import com.iver.cit.gvsig.fmap.WMSDriverExceptionType;
111
import com.iver.cit.gvsig.fmap.crs.CRSFactory;
112
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
113
import com.iver.cit.gvsig.fmap.drivers.wms.FMapWMSDriver;
114
import com.iver.cit.gvsig.fmap.drivers.wms.FMapWMSDriverFactory;
115
import com.iver.cit.gvsig.fmap.drivers.wms.WMSException;
116
import com.iver.cit.gvsig.fmap.layers.WMSLayerNode.FMapWMSStyle;
117
import com.iver.cit.gvsig.fmap.layers.layerOperations.ComposedLayer;
118
import com.iver.cit.gvsig.fmap.layers.layerOperations.IHasImageLegend;
119
import com.iver.cit.gvsig.fmap.layers.layerOperations.StringXMLItem;
120
import com.iver.cit.gvsig.fmap.layers.layerOperations.XMLItem;
121
import com.iver.cit.gvsig.fmap.rendering.ILegend;
122
import com.iver.cit.gvsig.fmap.rendering.XmlBuilder;
123
import com.iver.cit.gvsig.wmc.WebMapContextTags;
124
import com.iver.utiles.StringUtilities;
125
import com.iver.utiles.XMLEntity;
126
import com.iver.utiles.swing.threads.Cancellable;
127

    
128

    
129

    
130
/**
131
* FMap's WMS Layer class.
132
*
133
* Las capas WMS son tileadas para descargarlas del servidor. Esto quiere decir que
134
* est?n formadas por multiples ficheros raster. Por esto la fuente de datos raster (IRasterDatasource)
135
* de la capa FLyrWMS es un objeto de tipo CompositeDataset. Este objeto est? compuesto por un array
136
* bidimensional de MultiRasterDataset. Cada uno de los MultiRasterDataset corresponde con un tile
137
* salvado en disco. Estos MultiRasterDataset se crean cada vez que se repinta ya que en WMS a cada
138
* zoom varian los ficheros fuente. La secuencia de creaci?n de un CompositeDataset ser?a la siguiente:
139
* <UL>
140
* <LI>Se hace una petici?n de dibujado por parte del usuario llamando al m?todo draw de FLyrWMS</LI>
141
* <LI>Se tilea la petici?n</LI>
142
* <LI>Cada tile se dibuja abriendo una FLyerRaster para ese tile</LI>
143
* <LI>Si es el primer dibujado se guarda una referencia en la capa WMS a las propiedades de renderizado, orden de bandas,
144
* transparencia, filtros aplicados, ...</LI>
145
* <LI>Si no es el primer dibujado se asignan las propiedades de renderizado cuya referencia se guarda en la capa WMS</LI>
146
* <LI>Se guarda el MultiRasterDataset de cada tile</LI>
147
* <LI>Al acabar todos los tiles creamos un CompositeDataset con los MultiRasterDataset de todos los tiles</LI>
148
* <LI>Asignamos a la capa la referencia de las propiedades de renderizado que tenemos almacenadas. De esta forma si hay
149
* alguna modificaci?n desde el cuadro de propiedades ser? efectiva sobre los tiles que se dibujan.</LI>
150
* </UL>
151
*
152
*
153
* @author Jaume Dominguez Faus
154
*
155
*/
156
public class FLyrWMS extends FLyrRasterSE implements IHasImageLegend{
157
        private boolean                                         isPrinting = false;
158
        private boolean                                         mustTileDraw = true;
159
        private boolean                                         mustTilePrint = true;
160
        private final int                                         maxTileDrawWidth = 1023;
161
        private final int                                         maxTileDrawHeight = 1023;
162
        private final int                                         maxTilePrintWidth = 1023;
163
        private final int                                         maxTilePrintHeight = 1023;
164
        private final int                                        minTilePrintWidth = 12;
165
        private final int                                        minTilePrintHeight = 12;
166

    
167
        public URL                                                         host;
168
        public String                                                 m_Format;
169

    
170
        private String                                                 m_SRS;
171
        private String                                                 layerQuery;
172
        private String                                                 infoLayerQuery;
173
        private FMapWMSDriver                                 wms;
174
        private WMSStatus                                         wmsStatus = new WMSStatus();
175
        private Rectangle2D                                 fullExtent;
176
        private boolean                                                wmsTransparency;
177
        private Vector                                                 styles;
178
        private Vector                                                 dimensions;
179
        private boolean                                                firstLoad = false;
180
        private Hashtable                                         onlineResources = new Hashtable();
181
        private Dimension                                         fixedSize;
182
        private boolean                                         queryable = true;
183
        private VisualStatus                                visualStatus = new VisualStatus();
184
        /**
185
         * Lista de filtros aplicada en la renderizaci?n
186
         */
187
        private RasterFilterList            filterList = null;
188
        private GridTransparency                        transparency = null;
189
        private int[]                       renderBands = null;
190
        private FLyrRasterSE[]                                layerRaster = null;
191
        private ArrayList                   filterArguments = null;
192

    
193
        private List                                                disableUpdateDrawVersion;
194
        private int                         lastNColumns = 0;
195
        private int                         lastNRows = 0;
196
        private boolean                                         hasImageLegend = false;
197

    
198
        /***
199
         * WMS 1.3 standard defines a fixed pixel size of 0.28 mm for the server.
200
         * As
201
         *   1 inch = 25.4 mm
202
         * then the server is supposed to have the following DPI:
203
         *   25.4 / 0.28 = 90.714285714 dpi
204
         */
205

    
206
        private final double WMS_DPI = 90.714285714;
207
        private String infoFormat;
208
   
209

    
210
        private class MyCancellable implements ICancellable
211
        {
212
                private Cancellable original;
213
                public MyCancellable(Cancellable cancelOriginal)
214
                {
215
                        this.original = cancelOriginal;
216
                }
217
                public boolean isCanceled() {
218
                        if (original == null) return false;
219
                        return original.isCanceled();
220
                }
221
                public Object getID() {
222
                        return this;
223
                }
224

    
225
        }
226

    
227
        public FLyrWMS(){
228
                super();
229
                this.updateDrawVersion();
230
        }
231

    
232
        public FLyrWMS(Map args) throws LoadLayerException{
233
                this.updateDrawVersion();
234
                FMapWMSDriver drv = null;
235
                String host = (String)args.get("host");
236
                String sLayer = (String)args.get("layer");
237
                Rectangle2D fullExtent = (Rectangle2D)args.get("FullExtent");
238
                String sSRS = (String)args.get("SRS");
239
                String sFormat = (String)args.get("Format");
240
                String[] sLayers = sLayer.split(",");
241

    
242
                try {
243
                        this.setHost(new URL(host));
244
                } catch (MalformedURLException e) {
245
                        //e.printStackTrace();
246
                        throw new URLLayerException(getName(),e);
247
                }
248
                        try {
249
                                drv = this.getDriver();
250
                        } catch (IllegalStateException e) {
251
                                throw new LoadLayerException(getName(),e);
252
                        } catch (ValidationException e) {
253
                                throw new LoadLayerException(getName(),e);
254
                        } catch (IOException e) {
255
                                throw new ConnectionErrorLayerException(getName(),e);
256
                        }
257
                if( sFormat == null || sSRS == null || fullExtent == null ) {
258
                        if (!drv.connect(null))
259
                                throw new ConnectionErrorLayerException(getName(),null);
260

    
261
                        WMSLayerNode wmsNode = drv.getLayer(sLayer);
262

    
263
                        if (wmsNode == null){
264
                                throw new LoadLayerException(getName(),null);
265
                        }
266
                        if( sFormat == null ) {
267
                                sFormat = this.getGreatFormat(drv.getFormats());
268
                        }
269
                        // SRS
270
                        Vector allSrs = wmsNode.getAllSrs();
271
                        boolean isSRSSupported = false;
272
                        if( sSRS != null ) {
273
                                for (int i=0; i<allSrs.size() ; i++){
274
                                                 if (((String)allSrs.get(i)).compareTo(sSRS) == 0){
275
                                                         isSRSSupported = true;
276
                                                 }
277
                                         }
278
                        }
279

    
280
                                 if(!isSRSSupported) {
281
                                         for (int i=0; i<allSrs.size() ; i++){
282
                                                 if (((String)wmsNode.getAllSrs().get(i)).compareTo("EPSG:4326") == 0){
283
                                                         sSRS = (String)wmsNode.getAllSrs().get(i);
284
                                                 }
285
                                         }
286
                                         if (sSRS==null){
287
                                                 sSRS = (String)wmsNode.getAllSrs().get(0);
288
                                         }
289
                                 }
290
                        if( fullExtent == null ) {
291
                                fullExtent = drv.getLayersExtent(sLayers,sSRS);
292
                        }
293
                }
294

    
295

    
296
                this.setFullExtent(fullExtent);
297
                this.setFormat(sFormat);
298
                this.setLayerQuery(sLayer);
299
                this.setInfoLayerQuery("");
300
                this.setSRS(sSRS);
301
                this.setName(sLayer);
302
                this.setOnlineResources(drv.getOnlineResources());
303
                if (drv.getInfoFormats() != null) {
304
                        if (drv.getInfoFormats().size() > 0)
305
                                this.setInfoFormat((String) drv.getInfoFormats().get(0));
306
                }
307
                
308
                this.setDriver(drv);
309
                initServerScale();
310
                load();
311
        }
312

    
313
        private void setInfoFormat(String infoFormat) {
314
                this.infoFormat = infoFormat;
315
        }
316

    
317
        /**
318
         * It choose the best format to load different maps if the server
319
         * supports it. This format could be png, because it supports
320
         * transparency.
321
         * @param formats
322
         * Arraywith all the formats supported by the server
323
         * @return
324
         */
325
        private String getGreatFormat(Vector formats){
326
                        for (int i=0 ; i<formats.size() ; i++){
327
                                        String format = (String) formats.get(i);
328
                                if (format.equals("image/jpg")){
329
                                                        return format;
330
                                }
331
                                if (format.equals("image/jpeg")){
332
                                                        return format;
333
                                }
334
                        }
335

    
336
                        return (String)formats.get(0);
337
        }
338

    
339
        /**
340
         * Clase que contiene los datos de visualizaci?n de WMS.
341
         * @author Nacho Brodin (brodin_ign@gva.es)
342
         */
343
        private class VisualStatus{
344
                /**
345
                 * Ancho y alto de la imagen o del conjunto de tiles si los tiene. Coincide con
346
                 * el ancho y alto del viewPort
347
                 */
348
                private double                                                minX = 0D;
349
                private double                                                minY = 0D;
350
                private double                                                maxX = 0D;
351
                private double                                                maxY = 0D;
352
                /**
353
                 * Lista de nombre de fichero que componen toda la visualizaci?n.
354
                 */
355
                private String[]                                        fileNames = null;
356

    
357
                public Object clone() {
358
                        VisualStatus s = new VisualStatus();
359
                        s.maxX = maxX;
360
                        s.maxY = maxY;
361
                        s.minX = minX;
362
                        s.minY = minY;
363
                        s.fileNames = new String[fileNames.length];
364
                        for (int i = 0; i < fileNames.length; i++)
365
                                s.fileNames[i] = fileNames[i];
366
                        return s;
367
                }
368
        }
369

    
370

    
371
        /**
372
         * Devuelve el XMLEntity con la informaci?n necesaria para reproducir la
373
         * capa.
374
         *
375
         * @return XMLEntity.
376
         * @throws XMLException
377
         */
378
        public XMLEntity getXMLEntity() throws XMLException {
379
                XMLEntity xml = super.getXMLEntityWithoutChecks();
380
                if (xml != null){
381

    
382
                        // Full extent
383
                        xml.putProperty("fullExtent", StringUtilities.rect2String(fullExtent));
384

    
385
                        // Host
386
                        xml.putProperty("host", host.toExternalForm());
387

    
388
                        // Part of the query that is not the host, or the
389
                        // layer names, or other not listed bellow
390
                        xml.putProperty("infoLayerQuery", infoLayerQuery);
391

    
392
                        // Part of the query containing the layer names
393
                        xml.putProperty("layerQuery", layerQuery);
394

    
395
                        // Format
396
                        xml.putProperty("format", m_Format);
397

    
398
                        // SRS
399
                        xml.putProperty("srs", m_SRS);
400
                        if (status!=null)
401
                                status.getXMLEntity(xml, true, this);
402
                        else{
403
                                status = new StatusLayerRaster();
404
                                status.getXMLEntity(xml, true, this);
405
                        }
406

    
407
                        // Transparency
408
                        xml.putProperty("wms_transparency", wmsTransparency);
409

    
410
                        // Styles
411
                        if (styles!=null){
412
                                String stylePr = "";
413
                                for (int i = 0; i < styles.size(); i++) {
414
                                        stylePr += styles.get(i).toString();
415
                                        if (i<styles.size()-1)
416
                                                stylePr += ",";
417
                                }
418
                                if (stylePr.endsWith(","))
419
                                        stylePr += " ";
420
                                xml.putProperty("styles", stylePr);
421
                        }
422

    
423
                        // Dimensions
424
                        if (dimensions!=null){
425
                                String dim = "";
426
                                for (int i = 0; i < dimensions.size(); i++) {
427
                                        dim += (String) dimensions.get(i);
428
                                        if (i<dimensions.size()-1)
429
                                                dim += ",";
430
                                }
431
                                if (dim.endsWith(","))
432
                                        dim += " ";
433
                                xml.putProperty("dimensions", dim);
434
                        }
435

    
436
                        // OnlineResources
437
                        Iterator it = onlineResources.keySet().iterator();
438
                        String strOnlines = "";
439
                        while (it.hasNext()) {
440
                                String key = (String) it.next();
441
                                String value = (String) onlineResources.get(key);
442
                                strOnlines += key+"~##SEP2##~"+value;
443
                                if (it.hasNext())
444
                                        strOnlines += "~##SEP1##~";
445
                        }
446
                        xml.putProperty("onlineResources", strOnlines);
447

    
448
                        // Queryable
449
                        xml.putProperty("queryable", queryable);
450
                        if(wms != null)
451
                                xml.putProperty("hasImageLegend", wms.hasLegendGraphic());
452

    
453
                        // fixedSize
454
                        if (isSizeFixed()) {
455
                                xml.putProperty("fixedSize", true);
456
                                xml.putProperty("fixedWidth", fixedSize.width);
457
                                xml.putProperty("fixedHeight", fixedSize.height);
458
                        }
459
                }
460
                return xml;
461
        }
462

    
463
        /**
464
         * A partir del XMLEntity reproduce la capa.
465
         *
466
         * @param xml XMLEntity
467
         *
468
         * @throws XMLException
469
         * @throws DriverException
470
         * @throws DriverIOException
471
         */
472
        public void setXMLEntity03(XMLEntity xml)
473
                throws XMLException {
474
                super.setXMLEntity(xml);
475
                fullExtent = StringUtilities.string2Rect(xml.getStringProperty(
476
                                        "fullExtent"));
477

    
478
                try {
479
                        host = new URL(xml.getStringProperty("host"));
480
                } catch (MalformedURLException e) {
481
                        throw new XMLException(e);
482
                }
483

    
484
                infoLayerQuery = xml.getStringProperty("infoLayerQuery");
485
                layerQuery = xml.getStringProperty("layerQuery");
486
                m_Format = xml.getStringProperty("format");
487
                m_SRS = xml.getStringProperty("srs");
488
        }
489

    
490
        /**
491
         * A partir del XMLEntity reproduce la capa.
492
         *
493
         * @param xml XMLEntity
494
         *
495
         * @throws XMLException
496
         * @throws DriverException
497
         * @throws DriverIOException
498
         */
499
        public void setXMLEntity(XMLEntity xml)
500
                throws XMLException {
501
                for (int i = 0; i < xml.getPropertyCount(); i++) {
502
                        String key = xml.getPropertyName(i);
503
                        if(key.startsWith("raster.file")) {
504
                                xml.putProperty(key, "");
505
                        }
506
                }
507

    
508

    
509
                super.setXMLEntity(xml);
510
                fullExtent = StringUtilities.string2Rect(xml.getStringProperty(
511
                                        "fullExtent"));
512

    
513
                // Host
514
                try {
515
                        host = new URL(xml.getStringProperty("host"));
516
                } catch (MalformedURLException e) {
517
                        throw new XMLException(e);
518
                }
519

    
520
                // Part of the query that is not the host, or the
521
                // layer names, or other not listed bellow
522
                infoLayerQuery = xml.getStringProperty("infoLayerQuery");
523

    
524
                // Part of the query containing the layer names
525
                layerQuery = xml.getStringProperty("layerQuery");
526

    
527
                // Format
528
                m_Format = xml.getStringProperty("format");
529

    
530
                // SRS
531
                m_SRS = xml.getStringProperty("srs");
532

    
533
                String claseStr = StatusLayerRaster.defaultClass;
534
                if (xml.contains("raster.class")) {
535
                        claseStr = xml.getStringProperty("raster.class");
536
                }
537

    
538
                // Transparency
539
                                if (xml.contains("wms_transparency"))
540
                                                wmsTransparency = xml.getBooleanProperty("wms_transparency");
541

    
542
                                // Styles
543
                                if (xml.contains("styles")){
544
                                                styles = new Vector();
545
                                                String[] stl = xml.getStringProperty("styles").split(",");
546

    
547
                                                for (int i = 0; i < stl.length; i++) {
548
                                                        if (stl[i].equals(" "))
549
                                                                stl[i]="";
550
                                                                styles.add(stl[i]);
551
                                                }
552
                                }
553

    
554
                                // Dimensions
555
                                if (xml.contains("dimensions")){
556
                                                dimensions = new Vector();
557
                                                String[] dims = xml.getStringProperty("dimensions").split(",");
558
                                                for (int i = 0; i < dims.length; i++){
559
                                                        if (dims[i].equals(" "))
560
                                                                dims[i]="";
561

    
562
                                                                dimensions.add(dims[i]);
563
                                                }
564
                                }
565

    
566
                                // OnlineResources
567
                                if (xml.contains("onlineResources")) {
568
                                        String[] operations = xml.getStringProperty("onlineResources").split("~##SEP1##~");
569
                                        for (int i = 0; i < operations.length; i++) {
570
                                String[] resources = operations[i].split("~##SEP2##~");
571
                                if (resources.length==2 && resources[1]!="")
572
                                        onlineResources.put(resources[0], resources[1]);
573
                        }
574
                                }
575

    
576
                                // Queryable
577
                                queryable = true; // let's assume that the layer is queryable by default
578
                                if (xml.contains("queryable"))
579
                                        queryable = xml.getBooleanProperty("queryable");
580

    
581
                                hasImageLegend=false;
582
                                if (xml.contains("hasImageLegend")){
583
                                        hasImageLegend=xml.getBooleanProperty("hasImageLegend");
584
                                }
585

    
586
                                // fixedSize
587
                                if (xml.contains("fixedSize")) {
588
                                        fixedSize = new Dimension(xml.getIntProperty("fixedWidth"),
589
                                                                                                                                xml.getIntProperty("fixedHeight"));
590
                                }
591

    
592
                if(status!=null)
593
                        status.setXMLEntity(xml, this);
594
                else{
595
                        if(claseStr != null && !claseStr.equals("")){
596
                                try{
597
                                        Class clase = LayerFactory.getLayerClassForLayerClassName(claseStr);
598
                                        Constructor constr = clase.getConstructor(null);
599
                                        status = (IStatusRaster)constr.newInstance(null);
600
                                        if(status != null) {
601
                                                ((StatusLayerRaster)status).setNameClass(claseStr);
602
                                                status.setXMLEntity(xml, this);
603
                                                filterArguments = status.getFilterArguments();
604
                                                transparency = status.getTransparency();
605
                                                renderBands = status.getRenderBands();
606
                                        }
607
                                }catch(ClassNotFoundException exc){
608
                                        exc.printStackTrace();
609
                                }catch(InstantiationException exc){
610
                                        exc.printStackTrace();
611
                                }catch(IllegalAccessException exc){
612
                                        exc.printStackTrace();
613
                                }catch(NoSuchMethodException exc){
614
                                        exc.printStackTrace();
615
                                }catch(InvocationTargetException exc){
616
                                        exc.printStackTrace();
617
                                }
618
                        }
619
                }
620
                firstLoad = true;
621
        }
622

    
623
        /**
624
         * @throws ReadDriverException
625
         * @throws LoadLayerException
626
         * @see com.iver.cit.gvsig.fmap.layers.layerOperations.InfoByPoint#queryByPoint(com.iver.cit.gvsig.fmap.operations.QueriedPoint)
627
         */
628
        public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancellable) throws ReadDriverException {
629
                XMLItem[] item = new XMLItem[1];
630
                try {
631
                        if (queryable)         {
632
                                //TODO
633
                                // check if there are layers which are not queryable
634
                                ViewPort viewPort = getMapContext().getViewPort();
635

    
636
                                Point tiledPoint = new Point((int) p.getX() % maxTilePrintWidth, (int) p.getY() % maxTilePrintHeight);
637
                                Rectangle rect = new Rectangle(0, 0, viewPort.getImageWidth() - 1, viewPort.getImageHeight() - 1);
638
                                Tiling tiles = new Tiling(maxTilePrintWidth, maxTilePrintHeight, rect);
639
                                tiles.setAffineTransform((AffineTransform) viewPort.getAffineTransform().clone());
640
                                int nCols = tiles.getNumCols();
641

    
642
                                int col = (int) p.getX() / maxTilePrintWidth;
643
                                int row = (int) p.getY() / maxTilePrintHeight;
644
                                int tileIndex = (row*nCols) + col;
645

    
646
                                ViewPort vp = tiles.getTileViewPort(viewPort, tileIndex);
647
                                wmsStatus.setExtent(vp.getAdjustedExtent());
648
                                wmsStatus.setHeight(vp.getImageHeight());
649
                                wmsStatus.setWidth(vp.getImageWidth());
650
                                wmsStatus.setOnlineResource((String) onlineResources.get("GetFeatureInfo"));
651
                                
652
                                // We search for application string
653
                                // TODO: Maybe the user wants to select the format        
654
                                if (infoFormat == null) {
655
                                        try {
656
                                                infoFormat = "text/xml"; // bydefault
657
                                                if (getDriver().getInfoFormats().size() > 0) {
658
                                                        for (int iFormat = 0; iFormat < getDriver().getInfoFormats().size(); iFormat++ ) {
659
                                                                String auxFormat = (String) getDriver().getInfoFormats().get(iFormat);
660
                                                                if (auxFormat.contains("vnd.ogc")) {
661
                                                                        infoFormat = auxFormat;
662
                                                                        break;
663
                                                                }
664
                                                        }
665
                                                }
666
                                        } catch (UnsupportedVersionLayerException e) {
667
                                                e.printStackTrace();
668
                                                throw new ReadDriverException(FMapWMSDriver.class.getName()+"::"+getName()+" - UnsupportedVersionLayerException", e);
669
                                        } catch (IllegalStateException e) {
670
                                                e.printStackTrace();
671
                                                throw new ReadDriverException(FMapWMSDriver.class.getName()+"::"+getName()+" - UnsupportedVersionLayerException", e);
672
                                        }
673
                                }
674
                                wmsStatus.setInfoFormat(infoFormat);
675

    
676

    
677
                                wmsStatus.setFormat( m_Format );
678
                                wmsStatus.setLayerNames(Utilities.createVector(layerQuery,","));
679
                                wmsStatus.setSrs(m_SRS);
680
                                wmsStatus.setStyles(styles);
681
                                wmsStatus.setDimensions(dimensions);
682
                                wmsStatus.setTransparency(wmsTransparency);
683
                                wmsStatus.setSrs(m_SRS);
684
                                MyCancellable c = new MyCancellable(cancellable);
685
                                try {
686
                                        item[0] = new StringXMLItem(new String(getDriver()
687
                                                        .getFeatureInfo(wmsStatus, (int) tiledPoint.getX(), (int) tiledPoint.getY(), Integer.MAX_VALUE, c)),this);
688
                                } catch (UnsupportedVersionLayerException e) {
689
                                        throw new ReadDriverException(FMapWMSDriver.class.getName()+"::"+getName()+" - UnsupportedVersionLayerException", e);
690
                                } catch (IllegalStateException e) {
691
                                        throw new ReadDriverException(FMapWMSDriver.class.getName()+"::"+getName()+" - IllegalStateException", e);
692
                                }
693
                                return item;
694
                        }
695
                        else
696
                        {
697
                                JOptionPane.showMessageDialog((Component)PluginServices.getMainFrame(),this.getName() + " " +
698
                                                PluginServices.getText(this,"layer_not_queryable"));
699
                                item[0] =  new StringXMLItem("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><info></info>",this);
700
                                return item;
701
                                //return null;
702
                        }
703
                } catch (WMSException  e) {
704
                        item[0] = new StringXMLItem("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><exception>" +
705
                        e.getMessage() + "</exception>", this);
706
                        return item;
707
                } catch (ValidationException e) {
708
                        throw new ReadDriverException(FMapWMSDriver.class.getName()+"::"+getName()+" - ValidationException", e);
709
                } catch (IOException e) {
710
                        throw new ReadDriverException(FMapWMSDriver.class.getName()+"::"+getName()+" - IOException", e);
711
                } catch (NoninvertibleTransformException e) {
712
                        NotificationManager.addError("NotinvertibleTransform", e);
713
                }
714
                return null;
715
        }
716

    
717
        /*
718
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#getFullExtent()
719
         */
720
        public Rectangle2D getFullExtent() {
721
                return fullExtent;
722
        }
723

    
724
        /*
725
         *
726
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#draw(java.awt.image.BufferedImage,
727
         *                 java.awt.Graphics2D, com.iver.cit.gvsig.fmap.ViewPort,
728
         *                 com.iver.cit.gvsig.fmap.operations.Cancellable)
729
         */
730
        private int callCount; // mess code, represents the amount of times the methods drawFixedSize or drawTile where tried for an extent
731
        private static final int MAX_RETRY_TIMES = 5; // mess code, represents the max amount of retries allowed.
732
        public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
733
                        Cancellable cancel,double scale) throws ReadDriverException {
734
                callCount = 0; // mess code
735
                lastNColumns = lastNRows = 0;
736

    
737
                enableStopped();
738

    
739
                closeAndFree();
740

    
741
                if (isWithinScale(scale)){
742
                        Point2D p = viewPort.getOffset();
743
                        // p will be (0, 0) when drawing a view or other when painting onto
744
                        // the Layout.
745
                        visualStatus.minX = viewPort.getAdjustedExtent().getMinX();
746
                        visualStatus.minY = viewPort.getAdjustedExtent().getMinY();
747
                        visualStatus.maxX = viewPort.getAdjustedExtent().getMaxX();
748
                        visualStatus.maxY = viewPort.getAdjustedExtent().getMaxY();
749

    
750

    
751
                        if (isSizeFixed()) {
752
                                // This condition handles those situations in which the server can
753
                                // only give static extent and resolution maps despite we need
754
                                // a specific BBOX and pixel WIDTH and HEIGHT
755
                                try {
756
                                        visualStatus.fileNames = new String[1];
757
                                        layerRaster = new FLyrRasterSE[1];
758
                                        drawFixedSize(g, viewPort, cancel, scale);
759
                                        if(layerRaster != null && layerRaster[0] != null) {
760
                                                dataset = layerRaster[0].getDataSource();
761
                                                initializeRasterLayer(null, new IBuffer[][]{{layerRaster[0].getRender().getLastRenderBuffer()}});
762
                                                getRender().setLastRenderBuffer(layerRaster[0].getRender().getLastRenderBuffer());
763
                                        }
764
                                } catch (LoadLayerException e) {
765
                                        // TODO Auto-generated catch block
766
                                        e.printStackTrace();
767
                                } catch (InterruptedException e) {
768
                                }
769

    
770
                        } else {
771
                                if(mustTileDraw){
772
                                        Rectangle r = new Rectangle((int) p.getX(), (int) p.getY(), viewPort.getImageWidth(), viewPort.getImageHeight());
773
                                        Tiling tiles = new Tiling(maxTileDrawWidth, maxTileDrawHeight, r);
774
                                        tiles.setAffineTransform((AffineTransform) viewPort.getAffineTransform().clone());
775
                                        visualStatus.fileNames = new String[tiles.getNumTiles()];
776
                                        MultiRasterDataset[][] datasets = new MultiRasterDataset[tiles.getNumRows()][tiles.getNumCols()];
777
                                        IBuffer[][] buf = new IBuffer[tiles.getNumRows()][tiles.getNumCols()];
778
                                        layerRaster = new FLyrRasterSE[tiles.getNumTiles()];
779
                                        lastNColumns = tiles.getNumCols();
780
                                        lastNRows = tiles.getNumRows();
781
                                        for (int tileNr = 0; tileNr < tiles.getNumTiles(); tileNr++) {
782
                                                // drawing part
783
                                                try {
784
                                                        ViewPort vp = tiles.getTileViewPort(viewPort, tileNr);
785
                                                        boolean painted = drawTile(g, vp, cancel, tileNr, scale, tileNr);
786
                                                        if(        layerRaster != null &&
787
                                                                        layerRaster[tileNr] != null &&
788
                                                                        painted) {
789
                                                                        datasets[(int)(tileNr / tiles.getNumCols())][tileNr % tiles.getNumCols()] = (MultiRasterDataset)layerRaster[tileNr].getDataSource().newDataset();
790
                                                                        buf[(int)(tileNr / tiles.getNumCols())][tileNr % tiles.getNumCols()] = layerRaster[tileNr].getRender().getLastRenderBuffer();
791
                                                                }
792
                                                } catch (NoninvertibleTransformException e) {
793
                                                        e.printStackTrace();
794
                                                } catch (LoadLayerException e) {
795
                                                        // TODO Auto-generated catch block
796
                                                        e.printStackTrace();
797
                                                }
798
                                        }
799
                                        try {
800
                                                if(datasets != null && datasets[0][0] != null) {
801
                                                        dataset = new CompositeDataset(datasets);
802
                                                        initializeRasterLayer(datasets, buf);
803
                                                        buf = null;
804
                                                }
805
                                        } catch (MosaicNotValidException e) {
806
                                                throw new ReadDriverException("No hay continuidad en el mosaico.", e);
807
                                        } catch (LoadLayerException e) {
808
                                                throw new ReadDriverException("Error inicializando la capa.", e);
809
                                        } catch (InterruptedException e) {
810
                                        }
811
                                } else
812
                                        try {
813
                                                layerRaster = new FLyrRasterSE[1];
814
                                                visualStatus.fileNames = new String[1];
815
                                                drawTile(g, viewPort, cancel, 0, scale, 0);
816
                                                if(layerRaster != null && layerRaster[0] != null) {
817
                                                        dataset = layerRaster[0].getDataSource();
818
                                                        getRender().setLastRenderBuffer(layerRaster[0].getRender().getLastRenderBuffer());
819
                                                        initializeRasterLayer(null, new IBuffer[][]{{layerRaster[0].getRender().getLastRenderBuffer()}});
820
                                                }
821
                                        } catch (LoadLayerException e) {
822
                                                // TODO Auto-generated catch block
823
                                                e.printStackTrace();
824
                                        } catch (InterruptedException e) {
825
                                        }
826
                        }
827
                }
828
                disableStopped();
829

    
830
                /*Runtime r = Runtime.getRuntime();
831
                System.err.println("********************WMS**********************");
832
                System.err.println("Memoria Total: " + (r.totalMemory() / 1024) +"KB");
833
                System.err.println("Memoria Usada: " + ((r.totalMemory() - r.freeMemory()) / 1024) +"KB");
834
                System.err.println("Memoria Libre: " + (r.freeMemory() / 1024) +"KB");
835
                System.err.println("Memoria MaxMemory: " + (r.maxMemory() / 1024) +"KB");
836
                System.err.println("*********************************************");*/
837
        }
838

    
839
        /**
840
         * Closes files and releases memory (pointers to null)
841
         */
842
        synchronized private void closeAndFree() {
843
                while(readingData != null && readingData.compareTo(Thread.currentThread().toString()) != 0)
844
                        try {
845
                                Thread.sleep(100);
846
                        } catch (InterruptedException e) {
847
                        }
848

    
849
                if(dataset != null) {
850
                        dataset.close();
851
                        dataset = null;
852
                }
853

    
854
                //Cerramos el dataset asociado a la capa si est? abierto.
855
                if(layerRaster != null) {
856
                        for (int i = 0; i < layerRaster.length; i++) {
857
                                if(layerRaster[i] != null) {
858
                                        layerRaster[i].setRemoveRasterFlag(true);
859
                                        layerRaster[i].getDataSource().close();
860
                                        System.out.println("CloseAndFree WMS" + this.getName());
861
                                        if (layerRaster[i] != null) {
862
                                                layerRaster[i].getRender().free();
863
                                                System.out.println("CloseAndFree WMS after render free" + this.getName());
864
                                                if(layerRaster[i].getBufferFactory() != null)
865
                                                        layerRaster[i].getBufferFactory().free();
866
                                                layerRaster[i] = null;
867
                                                System.out.println("CloseAndFree WMS after bufferFactory free");
868
                                        }
869
                                }
870
                        }
871
                }
872
                if (getRender() != null)
873
                        getRender().free();
874
                System.out.println("CloseAndFree WMS before System.gc");
875
                System.gc();
876
        }
877

    
878
        /**
879
         * Acciones que se realizan despu?s de asignar la fuente de datos a
880
         * la capa raster.
881
         *
882
         * @throws LoadLayerException
883
         * @throws InterruptedException
884
         */
885
        private void initializeRasterLayer(MultiRasterDataset[][] datasets, IBuffer[][] buf) throws LoadLayerException, InterruptedException {
886
                if(this.filterList != null)
887
                        getRender().setFilterList(filterList);
888
                if(this.transparency != null)
889
                        getRender().setLastTransparency(transparency);
890
                if(this.renderBands != null)
891
                        getRender().setRenderBands(renderBands);
892
                if(datasets != null) {
893
                        String[][] names = new String[datasets.length][datasets[0].length];
894
                        for (int i = 0; i < datasets.length; i++) {
895
                                for (int j = 0; j < datasets[i].length; j++) {
896
                                        if(datasets[i][j] != null)
897
                                                names[i][j] = datasets[i][j].getDataset(0)[0].getFName();
898
                                }
899
                        }
900
                        super.setLoadParams(names);
901
                }
902
                super.init();
903
                if(buf != null && buf[0][0] != null) {
904
                        int drawablesBandCount = layerRaster[0].getDataSource().getBands().getDrawableBandsCount();
905
                        IBuffer buff = null;
906
                        if(dataset instanceof CompositeDataset)
907
                                buff = ((CompositeDataset)dataset).generateBuffer(buf, drawablesBandCount);
908
                        else
909
                                buff = buf[0][0];
910

    
911
                        if(getRender().getLastRenderBuffer() != null)
912
                                getRender().getLastRenderBuffer().free();
913
                        getRender().setLastRenderBuffer(buff);
914
                }
915
        }
916

    
917
        private void drawFixedSize(Graphics2D g, ViewPort vp, Cancellable cancel, double scale) throws ReadDriverException, LoadLayerException {
918
                callCount++; // mess code, it is not unusual a wms server to response an error which is completely
919
                                         // temporal and the response is available if we retry requesting.
920
                                         //
921

    
922

    
923
                // This is the extent that will be requested
924
                Rectangle2D bBox = getFullExtent();
925
                MyCancellable c = new MyCancellable(cancel);
926

    
927
                try {
928
                        wmsStatus.setExtent( bBox );
929
                        wmsStatus.setFormat( m_Format );
930
                        wmsStatus.setHeight( fixedSize.height );
931
                        wmsStatus.setWidth( fixedSize.width );
932
                        wmsStatus.setLayerNames(Utilities.createVector(layerQuery,","));
933
                        wmsStatus.setSrs(m_SRS);
934
                        wmsStatus.setStyles(styles);
935
                        wmsStatus.setDimensions(dimensions);
936
                        wmsStatus.setTransparency(wmsTransparency);
937
                        wmsStatus.setOnlineResource((String) onlineResources.get("GetMap"));
938
                        File f = getDriver().getMap(wmsStatus, c);
939
                        if (f == null)
940
                                return;
941
                        String nameWorldFile = f.getPath() + getExtensionWorldFile();
942
                        com.iver.andami.Utilities.createTemp(nameWorldFile, this.getDataWorldFile(bBox, fixedSize));
943

    
944
                        IStatusRaster status = getStatus();
945
                        if(status!=null && firstLoad){
946
                                try {
947
                                        status.applyStatus(this);
948
                                } catch (NotSupportedExtensionException e) {
949
                                        throw new ReadDriverException("", e);
950
                                } catch (RasterDriverException e) {
951
                                        throw new ReadDriverException("", e);
952
                                } catch (FilterTypeException e) {
953
                                        throw new ReadDriverException("", e);
954
                                }
955
                                firstLoad = false;
956
                        }
957

    
958
                        // And finally, obtain the extent intersecting the view and the BBox
959
                        // to draw to.
960
                        Rectangle2D extent = new Rectangle2D.Double();
961
                        Rectangle2D.intersect(vp.getAdjustedExtent(), bBox, extent);
962

    
963
                        ViewPortData vpData = new ViewPortData(
964
                                vp.getProjection(), new Extent(extent), fixedSize );
965
                        vpData.setMat(vp.getAffineTransform());
966

    
967
                        String filePath = f.getAbsolutePath();
968
                        visualStatus.fileNames[0] = filePath;
969

    
970
                        try {
971
                                rasterProcess(filePath, g, vp, scale, cancel, 0);
972
                                this.updateDrawVersion();
973
                        } catch (FilterTypeException e) {
974
                        }
975
                } catch (ValidationException e) {
976
                        if (!c.isCanceled())
977
                        {
978
                                LoadLayerException exception = new LoadLayerException(getName(),e);
979
                                throw exception;
980
                        }
981
                } catch (IOException e) {
982
                        if (!c.isCanceled())
983
                                if (callCount<MAX_RETRY_TIMES) { // mess code
984
                                        NotificationManager.addWarning("\n[ FLyrWMS.drawFixedSize() ]  Failed in trying " + callCount + "/" + MAX_RETRY_TIMES + ")\n", null); // mess code
985
                                        // I'll try again requesting up to MAX_RETRY_TIMES times before throw an error // mess code
986
                                        // (this is mess code, should be replaced by a layer status handler which is scheduled for version > 1.0) // mess code
987
                                        drawFixedSize(g, vp, cancel, scale); // mess code
988
                                } // mess code
989

    
990
                                if (callCount == 1) { // mess code
991
                                        ConnectionErrorExceptionType type = new ConnectionErrorExceptionType();
992
                                        type.setLayerName(getName());
993
                                        try {
994
                                                type.setDriverName("WMS Driver");
995
                                        } catch (Exception e1) {
996
                                        }
997
                                        type.setHost(host);
998
                                        throw new ConnectionErrorLayerException(getName(),e);
999
                                } // mess code
1000

    
1001
                } catch (WMSException e) {
1002
                        if (!c.isCanceled()) {
1003
                                if (callCount<MAX_RETRY_TIMES) { // mess code
1004
                                        NotificationManager.addWarning("\n[ FLyrWMS.drawFixedSize() ]  Failed in trying " + callCount + "/" + MAX_RETRY_TIMES + ")\n", null); // mess code
1005
                                        // I'll try again requesting up to MAX_RETRY_TIMES times before throw an error // mess code
1006
                                        // (this is mess code, should be replaced by a layer status handler which is scheduled for version > 1.0) // mess code
1007
                                        drawFixedSize(g, vp, cancel, scale); // mess code
1008
                                } // mess code
1009
                                if (callCount == 1) { // mess code
1010
                                        if (!isPrinting)
1011
                                                this.setVisible(false);
1012
                                        throw new LoadLayerException(getName(),e);
1013

    
1014

    
1015
                                } // mess code
1016
                        }
1017
                }catch (NullPointerException e) {
1018
                        this.setVisible(false);
1019
                }
1020
                callCount--; // mess code
1021
        }
1022

    
1023
        /**
1024
         * Carga y dibuja el raster usando la librer?a
1025
         * @param filePath Ruta al fichero en disco
1026
         * @param g Graphics2D
1027
         * @param vp ViewPort
1028
         * @param scale Escala para el draw
1029
         * @param cancel Cancelaci?n para el draw
1030
         * @throws ReadDriverException
1031
         * @throws LoadLayerException
1032
         */
1033
        private void rasterProcess(String filePath, Graphics2D g, ViewPort vp, double scale, Cancellable cancel, int nLyr) throws ReadDriverException, LoadLayerException, FilterTypeException {
1034
                //Cargamos el dataset con el raster de disco.
1035
                layerRaster[nLyr] = FLyrRasterSE.createLayer("", filePath, vp.getProjection());
1036
                //layerRaster[nLyr].getRender().setBufferFactory(layerRaster[nLyr].getBufferFactory());
1037
                layerRaster[nLyr].setNoDataValue(getNoDataValue());
1038
                layerRaster[nLyr].setNoDataType(getNoDataType());
1039
//                layerRaster[nLyr].init();
1040

    
1041
                //Obtenemos la tabla de color del raster abierto ya que se le va a sustituir la lista
1042
                //de filtros y el de tabla de color no queremos sustituirlo.
1043
                RasterFilterList rasterFilterList = layerRaster[nLyr].getRender().getFilterList();
1044
                ColorTableFilter ct = (ColorTableFilter)rasterFilterList.getFilterByBaseClass(ColorTableFilter.class);
1045
                Object param = null;
1046
                if(ct != null)
1047
                        param = ct.getParam("colorTable");
1048

    
1049
                //En caso de cargar un proyecto con XMLEntity se crean los filtros
1050
                if(filterArguments != null) {
1051
                        RasterFilterList fl = new RasterFilterList();
1052
                        fl.addEnvParam("IStatistics", layerRaster[nLyr].getDataSource().getStatistics());
1053
                        fl.addEnvParam("MultiRasterDataset", layerRaster[nLyr].getDataSource());
1054
                        fl.setInitDataType(layerRaster[nLyr].getDataType()[0]);
1055
                        RasterFilterListManager filterListManager = new RasterFilterListManager(fl);
1056
                        filterListManager.createFilterListFromStrings(filterArguments);
1057
                        filterArguments = null;
1058
                        filterList = fl;
1059
                }
1060

    
1061
                //Como el raster se carga a cada zoom el render se crea nuevamente y la lista de
1062
                //filtros siempre estar? vacia a cada visualizaci?n. Para evitarlo tenemos que
1063
                //guardar la lista de filtro aplicada en la visualizaci?n anterior.
1064
                if(this.filterList != null) {
1065
                        this.disableUpdateDrawVersion();
1066
                        //Si ten?a tabla de color le asignamos la original
1067
                        if(param != null && param instanceof GridPalette) {
1068
                                this.filterList.remove(ColorTableFilter.class);
1069
                                RasterFilterListManager filterManager = new RasterFilterListManager(filterList);
1070
                                ColorTableListManager ctm = new ColorTableListManager(filterManager);
1071
                                ctm.addColorTableFilter((GridPalette)param);
1072
                                filterList.move(ColorTableFilter.class, 0);
1073
                                filterList.controlTypes();
1074
                        }
1075
                        layerRaster[nLyr].getRender().setFilterList(filterList);
1076
                        this.enableUpdateDrawVersion();
1077
                }
1078
                if(this.transparency != null)
1079
                        layerRaster[nLyr].getRender().setLastTransparency(transparency);
1080
                if(this.renderBands != null)
1081
                        layerRaster[nLyr].getRender().setRenderBands(renderBands);
1082

    
1083
                //Dibujamos
1084
                disableUpdateDrawVersion();
1085
                layerRaster[nLyr].draw(null, g, vp, cancel, scale);
1086
                enableUpdateDrawVersion();
1087

    
1088
                //La primera vez asignamos la lista de filtros asociada al renderizador. Guardamos una referencia
1089
                //en esta clase para que a cada zoom no se pierda.
1090
                if (this.filterList == null)
1091
                        filterList = layerRaster[nLyr].getRender().getFilterList();
1092
                if (this.transparency == null)
1093
                        transparency = layerRaster[nLyr].getRender().getLastTransparency();
1094
                if (this.renderBands == null)
1095
                        renderBands = layerRaster[nLyr].getRender().getRenderBands();
1096

    
1097
        }
1098

    
1099
        /*
1100
         * (non-Javadoc)
1101
         * @see org.gvsig.fmap.raster.IRasterRendering#getRenderFilterList()
1102
         */
1103
        public RasterFilterList getRenderFilterList(){
1104
                return (filterList != null) ? filterList : getRender().getFilterList();
1105
        }
1106

    
1107
        /*
1108
         * (non-Javadoc)
1109
         * @see org.gvsig.raster.hierarchy.IRasterRendering#setRenderFilterList(org.gvsig.raster.grid.filter.RasterFilterList)
1110
         */
1111
        public void setRenderFilterList(RasterFilterList filterList) {
1112
                if (filterList == this.filterList){
1113
                        return;
1114
                }
1115
                this.filterList = filterList;
1116
                this.updateDrawVersion();
1117
                super.getRender().setFilterList(filterList);
1118
        }
1119

    
1120
        /*
1121
         * (non-Javadoc)
1122
         * @see org.gvsig.fmap.raster.IRasterRendering#getRenderTransparency()
1123
         */
1124
        public GridTransparency getRenderTransparency() {
1125
                return (transparency != null) ? transparency : getRender().getLastTransparency();
1126
        }
1127

    
1128
        /*
1129
         * (non-Javadoc)
1130
         * @see org.gvsig.raster.hierarchy.IRasterRendering#getRenderBands()
1131
         */
1132
        public int[] getRenderBands() {
1133
                return (renderBands != null) ? renderBands : getRender().getRenderBands();
1134
        }
1135

    
1136
        /*
1137
         * (non-Javadoc)
1138
         * @see org.gvsig.raster.hierarchy.IRasterRendering#setRenderBands(int[])
1139
         */
1140
        public void setRenderBands(int[] renderBands) {
1141
                //TODO: Comprobar si hay cambios
1142
                this.renderBands = renderBands;
1143
                this.updateDrawVersion();
1144
                getRender().setRenderBands(renderBands);
1145
        }
1146

    
1147
        /**
1148
         * This is the method used to draw a tile in a WMS mosaic layer.
1149
         * @throws LoadLayerException
1150
         * @throws ReadDriverException
1151
         * @return true when a tile has been painted
1152
         */
1153
        private boolean drawTile(Graphics2D g, ViewPort vp, Cancellable cancel, int tile, double scale, int nLyr) throws LoadLayerException, ReadDriverException {
1154
                callCount++;
1155
                // Compute the query geometry
1156
                // 1. Check if it is within borders
1157
//                Rectangle2D extent = getFullExtent();
1158
//                                if ((vp.getAdjustedExtent().getMinX() > extent.getMaxX()) ||
1159
//                                                                (vp.getAdjustedExtent().getMinY() > extent.getMaxY()) ||
1160
//                                                                (vp.getAdjustedExtent().getMaxX() < extent.getMinX()) ||
1161
//                                                                (vp.getAdjustedExtent().getMaxY() < extent.getMinY())) {
1162
//                                                return false;
1163
//                                }
1164

    
1165
                                // 2. Compute extent to be requested.
1166
//                                Rectangle2D bBox = new Rectangle2D.Double();
1167
//                                Rectangle2D.intersect(vp.getAdjustedExtent(), extent, bBox); // FIXME: ESTO PROVOCA FALLOS SI EL EXTENT (fullextent) no es correcto
1168

    
1169
                                Rectangle2D bBox = vp.getAdjustedExtent();
1170
                                
1171
                                // 3. Compute size in pixels
1172
                                double scalex = vp.getAffineTransform().getScaleX();
1173
                                double scaley = vp.getAffineTransform().getScaleY();
1174
                                int wImg = (int) Math.ceil(Math.abs(bBox.getWidth() * scalex) + 1);
1175
                                int hImg = (int) Math.ceil(Math.abs(bBox.getHeight() * scaley) + 1);
1176

    
1177
                                Dimension sz = new Dimension(wImg, hImg);
1178

    
1179
                                if ((wImg <= 0) || (hImg <= 0)) {
1180
                                                return false;
1181
                                }
1182
                                MyCancellable c = new MyCancellable(cancel);
1183

    
1184
                try {
1185
                        sz = new Dimension(wImg, hImg);
1186
                        // Rectangle2D.intersect(vp.getAdjustedExtent(), extent, bBox);
1187

    
1188

    
1189
                        wmsStatus.setExtent( bBox );
1190
                        wmsStatus.setFormat(m_Format);
1191
                        wmsStatus.setHeight( hImg );
1192
                        wmsStatus.setWidth( wImg );
1193
                        wmsStatus.setLayerNames(Utilities.createVector(layerQuery,","));
1194
                        wmsStatus.setSrs(m_SRS);
1195
                        wmsStatus.setStyles(styles);
1196
                        wmsStatus.setDimensions(dimensions);
1197
                        wmsStatus.setTransparency(wmsTransparency);
1198
                        wmsStatus.setOnlineResource((String) onlineResources.get("GetMap"));
1199

    
1200
                        // begin patch; Avoid to request too small tiles.
1201
                        // This generally occurs when printing
1202

    
1203
                        if (wImg < minTilePrintWidth) {
1204
                                double wScale = (double) minTilePrintWidth / wImg;
1205
                                wmsStatus.setWidth(minTilePrintWidth);
1206
                                Rectangle2D sExtent = wmsStatus.getExtent();
1207
                                Point2D initialPoint = new Point2D.Double(sExtent.getX(), sExtent.getY());
1208
                                sExtent.setRect(sExtent.getX()*wScale, sExtent.getY(), sExtent.getWidth()*wScale, sExtent.getHeight());
1209
                                if (!bBox.contains(initialPoint)) {
1210
                                        sExtent.setRect(sExtent.getX() - initialPoint.getX(), sExtent.getY(), sExtent.getWidth(), sExtent.getHeight());
1211
                                }
1212
                        }
1213

    
1214
                        if (hImg < minTilePrintHeight) {
1215
                                double hScale = (double) minTilePrintHeight / hImg;
1216
                                wmsStatus.setHeight(minTilePrintHeight);
1217
                                Rectangle2D sExtent = wmsStatus.getExtent();
1218
                                Point2D initialPoint = new Point2D.Double(sExtent.getX(), sExtent.getY());
1219
                                sExtent.setRect(sExtent.getX(), sExtent.getY()*hScale, sExtent.getWidth(), sExtent.getHeight()*hScale);
1220
                                if (!bBox.contains(initialPoint)) {
1221
                                        sExtent.setRect(sExtent.getX(), sExtent.getY() - initialPoint.getY(), sExtent.getWidth(), sExtent.getHeight());
1222
                                }
1223
                        }
1224

    
1225
                        // end patch
1226
                        File f = getDriver().getMap(wmsStatus, c);
1227
                        if (f == null)
1228
                                return false;
1229
                        String nameWordFile = f.getPath() + getExtensionWorldFile();
1230
                        com.iver.andami.Utilities.createTemp(nameWordFile, this.getDataWorldFile(bBox, sz));
1231

    
1232
                        ViewPortData vpData = new ViewPortData(
1233
                                vp.getProjection(), new Extent(bBox), sz );
1234
                        vpData.setMat(vp.getAffineTransform());
1235

    
1236
                        String filePath = f.getAbsolutePath();
1237
                        visualStatus.fileNames[tile] = filePath;
1238
                        try {
1239
                                rasterProcess(filePath, g, vp, scale, cancel, nLyr);
1240
//                                this.updateDrawVersion();
1241
                        } catch (FilterTypeException e) {
1242
                        }
1243

    
1244
                } catch (ValidationException e) {
1245
                        if (!c.isCanceled())
1246
                        {
1247
                                LoadLayerException exception = new LoadLayerException(getName(),e);
1248
                                throw exception;
1249
                        }
1250
                } catch (IOException e) {
1251
                        if (!c.isCanceled()){
1252
                                if (callCount<MAX_RETRY_TIMES) { // mess code
1253
                                        NotificationManager.addWarning("\n[ FLyrWMS.drawFixedSize() ]  Failed in trying " + callCount + "/" + MAX_RETRY_TIMES + ")\n", null); // mess code
1254
                                        // I'll try again requesting up to MAX_RETRY_TIMES times before throw an error // mess code
1255
                                        // (this is mess code, should be replaced by a layer status handler which is scheduled for version > 1.0) // mess code
1256

    
1257
                                        drawFixedSize(g, vp, cancel, scale); // mess code
1258
                                } // mess code
1259
                        }
1260
                        if (callCount == 1) { // mess code
1261
                                throw new ConnectionErrorLayerException(getName(),e);
1262
                        }//if
1263
                } catch (WMSException e) {
1264
                        if (!c.isCanceled()) {
1265
                                if (callCount<MAX_RETRY_TIMES) { // mess code
1266
                                        Logger.getAnonymousLogger().warning("\n[ FLyrWMS.drawFixedSize() ]  Failed in trying " + callCount + "/" + MAX_RETRY_TIMES + ")\n"); // mess code
1267
                                        // I'll try again requesting up to MAX_RETRY_TIMES times before throw an error // mess code
1268
                                        // (this is mess code, should be replaced by a layer status handler which is scheduled for version > 1.0) // mess code
1269
                                        drawTile(g, vp, cancel, tile, scale, nLyr);
1270
                                } // mess code
1271
                                if (callCount == 1) { // mess code
1272
//                azabala                        JOptionPane.showMessageDialog((Component)PluginServices.getMainFrame(), e.getMessage());
1273
                                        WMSDriverExceptionType type = new WMSDriverExceptionType();
1274
                                        type.setLayerName(getName());
1275
                                        try {
1276
                                                type.setDriverName("WMS Driver");
1277
                                        } catch (Exception e1) {
1278
                                        }
1279
                                        type.setWcsStatus(this.wmsStatus);
1280
                                        if (!isPrinting)
1281
                                                this.setVisible(false);
1282
                                        throw new LoadLayerException(getName(),e);
1283

    
1284

    
1285
                                } //if
1286
                        }//if
1287
                }//catch
1288
                callCount--;
1289
                return true;
1290
        }
1291

    
1292
   /**
1293
    * Applies server min/max scale as layer min/max scale.
1294
    * The purpose is to update the TOC icon according with
1295
    * the WMS layer visibilitiy. 
1296
    */
1297
   private void initServerScale() {
1298
       /**
1299
        * We have to calculate the equivalent scale for our system, taking into account the
1300
        * server DPI and our real DPI.
1301
        */
1302
       double minScale = getCorrectedServerMinScale();
1303
       double maxScale = getCorrectedServerMaxScale();
1304
       if (minScale>0) {
1305
           setMinScale(minScale);
1306
       }
1307
       if (maxScale>0 &&
1308
               maxScale>minScale) {
1309
           setMaxScale(maxScale);
1310
       }
1311
   }
1312
        
1313
        /**
1314
    * Calculates the equivalent MinScaleDenominator for our system, taking into account the
1315
    * server DPI and our real DPI.
1316
    * 
1317
    * WMS 1.3 standard defines a fixed pixel size of 0.28 mm for the server,
1318
    * which may not match our real settings, so this conversion is required
1319
    * to properly use MinScaleDenominator and MaxScaleDenominator values.
1320
    *
1321
    * @return
1322
    */
1323
   public double getCorrectedServerMinScale() {
1324
       return (getServerMinScale()*MapContext.getScreenDPI())/WMS_DPI;
1325
   }
1326
   
1327
   /**
1328
    * Calculates the equivalent MaxScaleDenominator for our system, taking into account the
1329
    * server DPI and our real DPI.
1330
    * 
1331
    * WMS 1.3 standard defines a fixed pixel size of 0.28 mm for the server,
1332
    * which may not match our real settings, so this conversion is required
1333
    * to properly use MinScaleDenominator and MaxScaleDenominator values.
1334
    *
1335
    * @return
1336
    */
1337
   public double getCorrectedServerMaxScale() {
1338
       return (getServerMaxScale()*MapContext.getScreenDPI())/WMS_DPI;
1339
   }
1340
   
1341
   /**
1342
    * Returns the value of MinScaleDenominator tag, if available,
1343
    * or -1 otherwise.
1344
    *  
1345
    * @return
1346
    */
1347
   public double getServerMinScale() {
1348
       String[] layers = getLayerNames();
1349
       double minScale=Double.MAX_VALUE;
1350
       for (int i=0; i<layers.length; i++) {
1351
           WMSLayerNode layer = wms.getLayer(layers[i]);
1352
           double lyrMinScale = layer.getScaleMin(); 
1353
           if ((lyrMinScale > 0) && (lyrMinScale<minScale)) {
1354
               minScale = lyrMinScale;
1355
           }
1356
       }
1357
       if (minScale==Double.MAX_VALUE) {
1358
           return -1;
1359
       }
1360
       else {
1361
           return minScale;
1362
       }
1363
   }
1364

    
1365
   /**
1366
    * Returns the value of MaxScaleDenominator tag, if available,
1367
    * or -1 otherwise.
1368
    *  
1369
    * @return
1370
    */
1371
   public double getServerMaxScale() {
1372
       String[] layers = getLayerNames();
1373
       double maxScale=-1, lyrMaxScale;
1374
       for (int i=0; i<layers.length; i++) {
1375
           WMSLayerNode layer = wms.getLayer(layers[i]);
1376
           lyrMaxScale = layer.getScaleMax();
1377
           if (lyrMaxScale!=-1
1378
                   && lyrMaxScale>maxScale) {
1379
               maxScale = lyrMaxScale;
1380
           }
1381
           
1382
       }
1383
       return maxScale;
1384
   }
1385
   
1386
   
1387
   /**
1388
         * Obtiene la extensi?n del fichero de georreferenciaci?n
1389
         * @return String con la extensi?n del fichero de georreferenciaci?n dependiendo
1390
         * del valor del formato obtenido del servidor. Por defecto asignaremos un .wld
1391
         */
1392
        private String getExtensionWorldFile(){
1393
                String extWorldFile = ".wld";
1394
                        if(m_Format.equals("image/tif") || m_Format.equals("image/tiff"))
1395
                                extWorldFile = ".tfw";
1396
                        //En la versi?n 1.6 de gdal no soporta jpgw si el fichero de imagen no 
1397
                        //tiene extensi?n. Solo lo lee si es wld
1398
                        /*if(m_Format.equals("image/jpeg"))
1399
                                extWorldFile = ".jpgw";*/
1400
                        return extWorldFile;
1401
        }
1402

    
1403
        /**
1404
         * Calcula el contenido del fichero de georreferenciaci?n de una imagen.
1405
         * @param bBox Tama?o y posici?n de la imagen (en coordenadas de usuario)
1406
         * @param sz Tama?o de la imagen en pixeles.
1407
         * @return el 'WorldFile', como String.
1408
         * @throws IOException
1409
         */
1410
        public String getDataWorldFile(Rectangle2D bBox, Dimension sz) throws IOException {
1411
                StringBuffer data = new StringBuffer();
1412
                        data.append((bBox.getMaxX() - bBox.getMinX())/(sz.getWidth() - 1)+"\n");
1413
                        data.append("0.0\n");
1414
                        data.append("0.0\n");
1415
                        data.append("-"+(bBox.getMaxY() - bBox.getMinY())/(sz.getHeight() - 1)+"\n");
1416
                        data.append(""+bBox.getMinX()+"\n");
1417
                        data.append(""+bBox.getMaxY()+"\n");
1418
                        return data.toString();
1419
        }
1420

    
1421
        /**
1422
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#print(java.awt.Graphics2D,
1423
         *                 com.iver.cit.gvsig.fmap.ViewPort,
1424
         *                 com.iver.cit.gvsig.fmap.operations.Cancellable)
1425
         */
1426
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, double scale, PrintRequestAttributeSet properties)
1427
                throws ReadDriverException {
1428

    
1429
                closeAndFree();
1430

    
1431
                if (isVisible() && isWithinScale(scale)) {
1432
                        isPrinting = true;
1433
                        if (!mustTilePrint) {
1434
                                draw(null, g, viewPort, cancel,scale);
1435
                        } else {
1436
                                // Para no pedir imagenes demasiado grandes, vamos
1437
                                // a hacer lo mismo que hace EcwFile: chunkear.
1438
                                // Llamamos a drawView con cuadraditos m?s peque?os
1439
                                // del BufferedImage ni caso, cuando se imprime viene con null
1440

    
1441
                                Tiling tiles = new Tiling(maxTilePrintWidth, maxTilePrintHeight, g.getClipBounds());
1442
                                tiles.setAffineTransform((AffineTransform) viewPort.getAffineTransform().clone());
1443
                                visualStatus.fileNames = new String[tiles.getNumTiles()];
1444
                                layerRaster = new FLyrRasterSE[tiles.getNumTiles()];
1445
                                for (int tileNr=0; tileNr < tiles.getNumTiles(); tileNr++) {
1446
                                        // Parte que dibuja
1447
                                        try {
1448
                                                ViewPort vp = tiles.getTileViewPort(viewPort, tileNr);
1449
                                                drawTile(g, vp, cancel, tileNr, scale, tileNr);
1450
                                        } catch (NoninvertibleTransformException e) {
1451
                                                e.printStackTrace();
1452
                                        } catch (LoadLayerException e) {
1453
                                                // TODO Auto-generated catch block
1454
                                                e.printStackTrace();
1455
                                        }
1456
                                }
1457
                        }
1458
                        isPrinting = false;
1459
                }
1460
        }
1461

    
1462
        public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,double scale)
1463
                throws ReadDriverException {
1464
                draw(null, g, viewPort, cancel,scale);
1465
        }
1466

    
1467
        /**
1468
         * Devuelve el FMapWMSDriver.
1469
         *
1470
         * @return FMapWMSDriver
1471
         *
1472
         * @throws IllegalStateException
1473
         * @throws ValidationException
1474
         * @throws UnsupportedVersionLayerException
1475
         * @throws IOException
1476
         */
1477
        public FMapWMSDriver getDriver()
1478
                throws IllegalStateException, ValidationException,
1479
                        UnsupportedVersionLayerException, IOException {
1480
                return FMapWMSDriverFactory.getFMapDriverForURL(host);
1481
        }
1482

    
1483
        /**
1484
         * Devuelve el FMapWMSDriver.
1485
         *
1486
         * @return FMapWMSDriver
1487
         *
1488
         * @throws IllegalStateException
1489
         * @throws ValidationException
1490
         * @throws UnsupportedVersionLayerException
1491
         * @throws IOException
1492
         */
1493
        public void setDriver(FMapWMSDriver drv) {
1494
                //TODO: Comprobar cambio
1495
                wms = drv;
1496
                initServerScale();
1497
                this.updateDrawVersion();
1498
        }
1499

    
1500
        /**
1501
         * Devuelve el URL.
1502
         *
1503
         * @return URL.
1504
         */
1505
        public URL getHost() {
1506
                return host;
1507
        }
1508

    
1509
        /**
1510
         * Inserta el URL.
1511
         *
1512
         * @param host URL.
1513
         */
1514
        public void setHost(URL host) {
1515
                if (this.host == host){
1516
                        return;
1517
                }
1518
                if (this.host != null && this.fullExtent.equals(host)){
1519
                        return;
1520
                }
1521

    
1522
                this.host = host;
1523
                this.updateDrawVersion();
1524
        }
1525

    
1526
        /**
1527
         * Devuelve la informaci?n de la consulta.
1528
         *
1529
         * @return String.
1530
         */
1531
        public String getInfoLayerQuery() {
1532
                return infoLayerQuery;
1533
        }
1534

    
1535
        /**
1536
         * Inserta la informaci?n de la consulta.
1537
         *
1538
         * @param infoLayerQuery String.
1539
         */
1540
        public void setInfoLayerQuery(String infoLayerQuery) {
1541
                this.infoLayerQuery = infoLayerQuery;
1542
        }
1543

    
1544
        /**
1545
         * Devuelve la consulta.
1546
         *
1547
         * @return String.
1548
         */
1549
        public String getLayerQuery() {
1550
                return layerQuery;
1551
        }
1552

    
1553
        /**
1554
         * Inserta la consulta.
1555
         *
1556
         * @param layerQuery consulta.
1557
         */
1558
        public void setLayerQuery(String layerQuery) {
1559
                if (this.layerQuery == layerQuery){
1560
                        return;
1561
                }
1562
                if (this.layerQuery != null && this.layerQuery.equals(layerQuery)){
1563
                        return;
1564
                }
1565

    
1566
                this.layerQuery = layerQuery;
1567
       wmsStatus.setLayerNames(Utilities.createVector(layerQuery,","));
1568
                this.updateDrawVersion();
1569
        }
1570

    
1571
        /**
1572
         * Devuelve el formato.
1573
         *
1574
         * @return Formato.
1575
         */
1576
        public String getFormat() {
1577
                return m_Format;
1578
        }
1579

    
1580
        /**
1581
         * Inserta el formato.
1582
         *
1583
         * @param format Formato.
1584
         */
1585
        public void setFormat(String format) {
1586
                if (this.m_Format == format){
1587
                        return;
1588
                }
1589
                if (this.m_Format != null && this.m_Format.equals(format)){
1590
                        return;
1591
                }
1592
                m_Format = format;
1593
                this.updateDrawVersion();
1594
        }
1595

    
1596
        /**
1597
         * Devuelve el SRS.
1598
         *
1599
         * @return SRS.
1600
         */
1601
        public String getSRS() {
1602
                return m_SRS;
1603
        }
1604

    
1605
        /**
1606
         * Inserta el SRS.
1607
         *
1608
         * @param m_srs SRS.
1609
         */
1610
        public void setSRS(String m_srs) {
1611
                if (m_SRS == m_srs){
1612
                        return;
1613
                }
1614
                if (m_SRS != null && m_SRS.equals(m_srs)){
1615
                        return;
1616
                }
1617
                m_SRS = m_srs;
1618
                this.updateDrawVersion();
1619
                setProjection(CRSFactory.getCRS(getSRS()));
1620
        }
1621

    
1622
        /**
1623
         * Inserta la extensi?n total de la capa.
1624
         *
1625
         * @param fullExtent Rect?ngulo.
1626
         */
1627
        public void setFullExtent(Rectangle2D fullExtent) {
1628
                if (this.fullExtent == fullExtent){
1629
                        return;
1630
                }
1631
                if (this.fullExtent != null && this.fullExtent.equals(fullExtent)){
1632
                        return;
1633
                }
1634

    
1635
                this.fullExtent = fullExtent;
1636
                this.updateDrawVersion();
1637
        }
1638

    
1639
        public HashMap getProperties() {
1640
                HashMap info = new HashMap();
1641
                                String[] layerNames = getLayerQuery().split(",");
1642
                                Vector layers = new Vector(layerNames.length);
1643
                                try {
1644
                                                if(getDriver().connect(null)){
1645
                                                                for (int i = 0; i < layerNames.length; i++) {
1646
                                                                                layers.add(i, getDriver().getLayer(layerNames[i]));
1647
                                                                }
1648
                                                                info.put("name", getName());
1649
                                                                info.put("selectedLayers", layers);
1650
                                                                info.put("host", getHost());
1651
                                                                info.put("srs", getSRS());
1652
                                                                info.put("format", getFormat());
1653
                                                                info.put("wmsTransparency", new Boolean(wmsTransparency));
1654
                                                                info.put("styles", styles);
1655
                                                                info.put("dimensions", dimensions);
1656
                                                                info.put("fixedSize", fixedSize);
1657
                                                                return info;
1658
                                                }
1659
                                } catch (Exception e) {
1660
                                                e.printStackTrace();
1661
                                }
1662
                                return null;
1663
        }
1664

    
1665
        public double getMaxX() {
1666
                return visualStatus.maxX;
1667
        }
1668

    
1669
        public double getMaxY() {
1670
                return visualStatus.maxY;
1671
        }
1672

    
1673
        public double getMinX() {
1674
                return visualStatus.minX;
1675
        }
1676

    
1677
        public double getMinY() {
1678
                return visualStatus.minY;
1679
        }
1680

    
1681
  
1682
   /**
1683
    * Returns the names of the WMS layers that are loaded in this
1684
    * gvSIG layer.
1685
    * 
1686
    * @return An array containing the names of the WMS layers
1687
    */
1688
   public String[] getLayerNames() {
1689
       Vector namesList = wmsStatus.getLayerNames();
1690
       String[] names = new String[namesList.size()];
1691
       for (int i=0; i<names.length; i++) {
1692
           Object o = namesList.get(i);
1693
           if (o instanceof String) {
1694
               names[i] = (String) o;
1695
           }
1696
           else { // this should not happen
1697
               names[i] = o.toString();
1698
           }
1699
       }
1700
       return names;
1701
   }
1702

    
1703
        /**
1704
         * @return Returns the wmsTransparency.
1705
         */
1706
        public boolean isWmsTransparent() {
1707
                return wmsTransparency;
1708
        }
1709

    
1710
        /**
1711
         * @param wmsTransparency The wmsTransparency to set.
1712
         */
1713
        public void setWmsTransparency(boolean wmsTransparency) {
1714
                if (this.wmsTransparency == wmsTransparency){
1715
                        return;
1716
                }
1717
                this.wmsTransparency = wmsTransparency;
1718
                this.updateDrawVersion();
1719
        }
1720

    
1721
        /**
1722
         * @param styles
1723
         */
1724
        public void setStyles(Vector styles) {
1725
                if (this.styles == styles){
1726
                        return;
1727
                }
1728
                if (this.styles != null && styles != null ){
1729
                        if (this.styles.containsAll(styles) && this.styles.size() ==styles.size()){
1730
                                return;
1731
                        }
1732
                }
1733
                this.styles = styles;
1734
                this.updateDrawVersion();
1735
        }
1736

    
1737
        /**
1738
         * Sets the dimension vector that is a list of key-value pairs containing
1739
         * the name of the dimension and the value for it
1740
         * @param dimensions
1741
         */
1742
        public void setDimensions(Vector dimensions) {
1743
                if (this.dimensions == dimensions){
1744
                        return;
1745
                }
1746
                if (this.dimensions != null && dimensions != null ){
1747
                        if (this.dimensions.containsAll(dimensions) && this.dimensions.size() ==dimensions.size()){
1748
                                return;
1749
                        }
1750
                }
1751
                this.dimensions = dimensions;
1752
                this.updateDrawVersion();
1753
        }
1754

    
1755
        /**
1756
         * Sets the set of URLs that should be accessed for each operation performed
1757
         * to the server.
1758
         *
1759
         * @param onlineResources
1760
         */
1761
        public void setOnlineResources(Hashtable onlineResources) {
1762
                if (this.onlineResources == onlineResources){
1763
                        return;
1764
                }
1765
                if (this.onlineResources != null && this.onlineResources.equals(onlineResources)){
1766
                        return;
1767
                }
1768

    
1769
                this.onlineResources = onlineResources;
1770
                this.updateDrawVersion();
1771
        }
1772

    
1773
        /**
1774
         * Gets the URL that should be accessed for an operation performed
1775
         * to the server.
1776
         *
1777
         * @param onlineResources
1778
         */
1779
        public String getOnlineResource(String operation) {
1780
                return ((String) onlineResources.get(operation));
1781
        }
1782

    
1783
        /**
1784
         * When a server is not fully featured and it only can serve constant map
1785
         * sizes this value must be set. It expresses the size in pixels (width, height)
1786
         * that the map will be requested.
1787
         * @param Dimension sz
1788
         */
1789
        public void setFixedSize(Dimension sz) {
1790
                if (this.fixedSize == sz){
1791
                        return;
1792
                }
1793
                if (this.fixedSize != null && this.fixedSize.equals(sz)){
1794
                        return;
1795
                }
1796
                fixedSize = sz;
1797
                this.updateDrawVersion();
1798
        }
1799

    
1800
        /**
1801
         * Tells whether if this layer must deal with the server with the constant-size
1802
         * limitations or not.
1803
         * @return boolean.
1804
         */
1805
        private boolean isSizeFixed() {
1806
                return fixedSize != null && fixedSize.getWidth() > 0 && fixedSize.getHeight() > 0;
1807
        }
1808

    
1809
        /**
1810
         * If it is true, this layer accepts GetFeatureInfo operations. This WMS operations
1811
         * maps to FMap's infoByPoint(p) operation.
1812
         * @param b
1813
         */
1814
        public void setQueryable(boolean b) {
1815
                queryable = b;
1816
        }
1817

    
1818
        /**
1819
         * Creates the part of a OGC's MapContext document that would describe this
1820
         * layer(s).
1821
         * @param version, The desired version of the resulting document. (1.1.0)
1822
         * @return String containing the xml.
1823
         * @throws UnsupportedVersionLayerException
1824
         */
1825
        public String toMapContext(String mapContextVersion) {
1826
                XmlBuilder xml = new XmlBuilder();
1827
                FMapWMSDriver drv;
1828
                try {
1829
                        drv = getDriver();
1830
                } catch (Exception e) {
1831
                        return xml.toString();
1832
                }
1833
                String[] layerNames = getLayerQuery().split(",");
1834
                String[] styleNames = (String[]) styles.toArray(new String[0]);
1835
                for (int i = 0; i < layerNames.length; i++) {
1836
                        WMSLayerNode layer = drv.getLayer(layerNames[i]);
1837
                        HashMap xmlAttrs = new HashMap();
1838

    
1839
                        // <Layer>
1840
                        xmlAttrs.put(WebMapContextTags.HIDDEN, !isVisible()+"");
1841
                        xmlAttrs.put(WebMapContextTags.QUERYABLE, queryable+"");
1842
                        xml.openTag(WebMapContextTags.LAYER, xmlAttrs);
1843
                        xmlAttrs.clear();
1844
                        if (mapContextVersion.equals("1.1.0") || mapContextVersion.equals("1.0.0")) {
1845
                                // <Server>
1846
                                xmlAttrs.put(WebMapContextTags.SERVICE, WebMapContextTags.WMS);
1847
                                xmlAttrs.put(WebMapContextTags.VERSION, drv.getVersion());
1848
                                xmlAttrs.put(WebMapContextTags.SERVER_TITLE, drv.getServiceTitle());
1849
                                xml.openTag(WebMapContextTags.SERVER, xmlAttrs);
1850
                                xmlAttrs.clear();
1851

    
1852
                                        // <OnlineResource>
1853
                                        xmlAttrs.put(WebMapContextTags.XLINK_TYPE, "simple");
1854
                                        xmlAttrs.put(WebMapContextTags.XLINK_HREF, getHost().toString());
1855
                                        xml.writeTag(WebMapContextTags.ONLINE_RESOURCE, xmlAttrs);
1856
                                        xmlAttrs.clear();
1857
                                        // </OnlineResource>
1858

    
1859
                                xml.closeTag();
1860
                                // </Server>
1861

    
1862
                                // <Name>
1863
                                xml.writeTag(WebMapContextTags.NAME, layer.getName().trim());
1864
                                // </Name>
1865

    
1866
                                // <Title>
1867
                                xml.writeTag(WebMapContextTags.TITLE, layer.getTitle().trim());
1868
                                //?xml.writeTag(WebMapContextTags.TITLE, getName().trim());
1869
                                // </Title>
1870

    
1871
                                // <Abstract>
1872
                                if (layer.getAbstract() != null)
1873
                                        xml.writeTag(WebMapContextTags.ABSTRACT, layer.getAbstract());
1874
                                // </Abstract>
1875

    
1876
                                // <SRS> (a list of available SRS for the enclosing layer)
1877
                                String[] strings = (String[]) layer.getAllSrs().toArray(new String[0]);
1878
                                String mySRS = strings[0];
1879
                                for (int j = 1; j < strings.length; j++) {
1880
                                        mySRS += ","+strings[j];
1881
                                }
1882
                                xml.writeTag(WebMapContextTags.SRS, mySRS);
1883
                                // </SRS>
1884

    
1885
                                // <FormatList>
1886
                                xml.openTag(WebMapContextTags.FORMAT_LIST);
1887
                                        strings = (String[]) drv.getFormats().toArray(new String[0]);
1888
                                        for (int j = 0; j < strings.length; j++) {
1889
                                                                                // <Format>
1890
                                                String str = strings[j].trim();
1891
                                                if (str.equals(getFormat()))
1892
                                                        xml.writeTag(WebMapContextTags.FORMAT, str, WebMapContextTags.CURRENT, "1");
1893
                                                else
1894
                                                        xml.writeTag(WebMapContextTags.FORMAT, str);
1895
                                                                                // </Format>
1896
                                        }
1897
                                xml.closeTag();
1898
                                // </FormatList>
1899

    
1900
                                // <StyleList>
1901
                                xml.openTag(WebMapContextTags.STYLE_LIST);
1902

    
1903
                                        if (layer.getStyles().size()>0) {
1904
                                                for (int j = 0; j < layer.getStyles().size(); j++) {
1905
                                                        // <Style>
1906
                                                        FMapWMSStyle st = (FMapWMSStyle) layer.getStyles().get(j);
1907
                                                        if (st.name.equals(styleNames[i]))
1908
                                                                xmlAttrs.put(WebMapContextTags.CURRENT, "1");
1909
                                                        xml.openTag(WebMapContextTags.STYLE, xmlAttrs);
1910
                                                        xmlAttrs.clear();
1911

    
1912
                                                                // <Name>
1913
                                                                xml.writeTag(WebMapContextTags.NAME, st.name);
1914
                                                                // </Name>
1915

    
1916
                                                                // <Title>
1917
                                                                xml.writeTag(WebMapContextTags.TITLE, st.title);
1918
                                                                // </Title>
1919

    
1920
                                                                // <LegendURL width="180" format="image/gif" height="50">
1921
                                                                        // <OnlineResource xlink:type="simple" xlink:href="http://globe.digitalearth.gov/globe/en/icons/colorbars/NATIONAL.gif"/>
1922
                                                                        // </OnlineResource>
1923
                                                                // </LegendURL>
1924
                                                        xml.closeTag();
1925
                                                        // </Style>
1926

    
1927
                                                }
1928

    
1929
                                        } else {
1930
                                                // Create fake style (for compatibility issues)
1931
                                                xmlAttrs.put(WebMapContextTags.CURRENT, "1");
1932
                                                // <Style>
1933
                                                xml.openTag(WebMapContextTags.STYLE, xmlAttrs);
1934
                                                        xmlAttrs.clear();
1935
                                                        // <Name>
1936
                                                        xml.writeTag(WebMapContextTags.NAME, "default");
1937
                                                        // </Name>
1938

    
1939
                                                        // <Title>
1940
                                                        xml.writeTag(WebMapContextTags.TITLE, "default");
1941
                                                        // </Title>
1942

    
1943
//                                                        // <LegendURL width="180" format="image/gif" height="50">
1944
//                                                        xmlAttrs.put(WebMapContextTags.WIDTH, "0");
1945
//                                                        xmlAttrs.put(WebMapContextTags.HEIGHT, "0");
1946
//                                                        xmlAttrs.put(WebMapContextTags.FORMAT.toLowerCase(), "image/gif");
1947
//                                                        xml.openTag(WebMapContextTags.LEGEND_URL, xmlAttrs);
1948
//                                                        xmlAttrs.clear();
1949
//                                                                // <OnlineResource xlink:type="simple" xlink:href="http://globe.digitalearth.gov/globe/en/icons/colorbars/NATIONAL.gif"/>
1950
//                                                                xmlAttrs.put(WebMapContextTags.XLINK_TYPE, "simple");
1951
//                                                                xmlAttrs.put(WebMapContextTags.XLINK_HREF, "http://globe.digitalearth.gov/globe/en/icons/colorbars/NATIONAL.gif");
1952
//                                                                xml.writeTag(WebMapContextTags.ONLINE_RESOURCE, xmlAttrs);
1953
//                                                                // </OnlineResource>
1954
//                                                    // </LegendURL>
1955
//                                                        xml.closeTag();
1956
                                                // </Style>
1957
                                                xml.closeTag();
1958
                                        }
1959
                                // </StyleList>
1960
                                xml.closeTag();
1961
                                if (mapContextVersion.compareTo("1.0.0") > 0) {
1962
                                // <DimensionList>
1963
                                        xml.openTag(WebMapContextTags.DIMENSION_LIST);
1964
                                        // <Dimension>
1965
                                        // </Dimension>
1966
                                        xml.closeTag();
1967
                                // </DimensionList>
1968
                                }
1969
                        } else {
1970
                                xml.writeTag("ERROR", PluginServices.getText(this, "unsupported_map_context_version"));
1971
                        }
1972
                        // </Layer>
1973
                        xml.closeTag();
1974
                }
1975
                return xml.getXML();
1976
        }
1977

    
1978
        public ImageIcon getTocImageIcon() {
1979
                return new ImageIcon(getClass().getResource("image/icon-layer-wms.png"));
1980
        }
1981

    
1982
        /*
1983
         *  (non-Javadoc)
1984
         * @see com.iver.cit.gvsig.fmap.layers.RasterOperations#getTileSize()
1985
         */
1986
        public int[] getTileSize() {
1987
                int[] size = {maxTileDrawWidth, maxTileDrawHeight};
1988
                return size;
1989
        }
1990

    
1991
        /*
1992
         *  (non-Javadoc)
1993
         * @see com.iver.cit.gvsig.fmap.layers.RasterOperations#isTiled()
1994
         */
1995
        public boolean isTiled() {
1996
                return mustTileDraw;
1997
        }
1998

    
1999
        public Image getImageLegend() {
2000
                try {
2001
                        if (wms == null)
2002
                                wms = getDriver();
2003
                        if (wms.hasLegendUrl(wmsStatus,layerQuery) ||wms.hasLegendGraphic() || hasImageLegend) {
2004
                                wmsStatus.setOnlineResource((String) onlineResources
2005
                                                .get("GetLegendGraphic"));
2006
                                String path = getPathImage();// File legend =
2007
                                                                                                // getDriver().getLegendGraphic(wmsStatus,
2008
                                                                                                // layerQuery, null);
2009
                                Image img = null;
2010
                                if ((path != null) && (path.length() > 0))
2011
                                        img = new ImageIcon(path).getImage();
2012
                                return img;
2013
                        }
2014
                } catch (Exception e) {
2015
                }
2016
                return null;
2017
        }
2018

    
2019
        public String getPathImage() {
2020
                try {
2021
                        File legend = getDriver().getLegendGraphic(wmsStatus, layerQuery, null);
2022
                        return legend.getAbsolutePath();
2023
                }catch(Exception e){
2024
                        e.printStackTrace();
2025
                        return null;
2026
                }
2027
        }
2028

    
2029
        /* (non-Javadoc)
2030
         * @see com.iver.cit.gvsig.fmap.layers.FLayer#newComposedLayer()
2031
         */
2032
        public ComposedLayer newComposedLayer() {
2033
                Preferences prefs = Preferences.userRoot().node("gvsig.wms");
2034

    
2035
                /*
2036
                 * from java.util.prefs import Preferences
2037
                 * prefs = Preferences.userRoot().node("gvsig.wms")
2038
                 * prefs.put("useComposedLayer","true")
2039
                 */
2040

    
2041
                String str = prefs.get("useComposedLayer","false");
2042
                Boolean useComposedLayer = Boolean.TRUE; // por defecto ya se usan
2043
                try {
2044
                        useComposedLayer = Boolean.valueOf(str);
2045
                } catch (Exception e) {
2046

    
2047
                }
2048
                if (useComposedLayer.booleanValue()) {
2049
                        return new ComposedLayerWMS();
2050
                } else {
2051
                        return null;
2052
                }
2053
        }
2054

    
2055
        /**
2056
         * @param styles
2057
         */
2058
        public Vector getStyles() {
2059
                return this.styles;
2060
        }
2061

    
2062

    
2063
        /*
2064
         * Checks if can make a single petition for the two layers to the server
2065
         * @see com.iver.cit.gvsig.fmap.layers.ComposedLayerWMS#canAdd(com.iver.cit.gvsig.fmap.layers.FLayer)
2066
         */
2067
        boolean isComposedLayerCompatible(FLayer layer) {
2068
                FLyrWMS aLayer;
2069

    
2070
                if (!(layer instanceof FLyrWMS)) {
2071
                        return false;
2072
                }
2073
                aLayer = (FLyrWMS)layer;
2074
                if (!this.getHost().equals(aLayer.getHost())) {
2075
                        return false;
2076
                }
2077
                if (!this.getFormat().equals(aLayer.getFormat())) {
2078
                        return false;
2079
                }
2080
                if (!this.getSRS().equals(aLayer.getSRS())) {
2081
                        return false;
2082
                }
2083
                if (this.getInfoLayerQuery() != null) {
2084
                        if (!this.getInfoLayerQuery().equals(aLayer.getInfoLayerQuery())) {
2085
                                return false;
2086
                        }
2087
                }else if (aLayer.getInfoLayerQuery() != null) {
2088
                        return false;
2089
                }
2090

    
2091

    
2092
                // isFixedSize es privado
2093
                if ((this.fixedSize != null) &&
2094
                                (aLayer.fixedSize!= null)) {
2095
                        if (this.fixedSize.equals(aLayer.fixedSize)) {
2096
                                return false;
2097
                        }
2098
                } else if ((this.fixedSize != null) != (aLayer.fixedSize != null)) {
2099
                        return false;
2100
                }
2101

    
2102
                // time elevation (dimensions)
2103
                if ((this.dimensions != null) &&
2104
                                (aLayer.dimensions != null)) {
2105
                        if (this.dimensions.size() != aLayer.dimensions.size()) {
2106
                                return false;
2107
                        } else {
2108
                                Iterator iter = this.dimensions.iterator();
2109
                                while (iter.hasNext()) {
2110
                                        if (!aLayer.dimensions.contains(iter.next())) {
2111
                                                return false;
2112
                                        }
2113
                                }
2114
                        }
2115

    
2116
                } else if ((this.dimensions != null) != (aLayer.dimensions != null)) {
2117
                        return false;
2118
                }
2119

    
2120
                return true;
2121
        }
2122

    
2123
        /*
2124
         * (non-Javadoc)
2125
         * @see org.gvsig.fmap.raster.layers.FLyrRasterSE#isActionEnabled(int)
2126
         */
2127
        public boolean isActionEnabled(int action) {
2128
                switch (action) {
2129
                        case IRasterLayerActions.ZOOM_PIXEL_RESOLUTION:
2130
                        case IRasterLayerActions.FLYRASTER_BAR_TOOLS:
2131
                        case IRasterLayerActions.BANDS_FILE_LIST:
2132
                        case IRasterLayerActions.COLOR_TABLE:
2133
                        case IRasterLayerActions.GEOLOCATION:
2134
                        case IRasterLayerActions.PANSHARPENING:
2135
                        case IRasterLayerActions.SAVE_COLORINTERP:
2136
                                return false;
2137
                        case IRasterLayerActions.REMOTE_ACTIONS:
2138
                                return true;
2139
                }
2140

    
2141
                return super.isActionEnabled(action);
2142
        }
2143

    
2144
        /*
2145
         * (non-Javadoc)
2146
         * @see org.gvsig.fmap.raster.layers.FLyrRasterSE#getLegend()
2147
         */
2148
        public ILegend getLegend() {
2149
                return null;
2150
        }
2151

    
2152
        /*
2153
         * (non-Javadoc)
2154
         * @see org.gvsig.fmap.raster.IRasterOperations#getDatatype()
2155
         */
2156
        public int[] getDataType(){
2157
                try {
2158
                        return dataset.getDataType();
2159
                } catch (NullPointerException e) {
2160
                        if(layerRaster != null && layerRaster[0] != null)
2161
                                return layerRaster[0].getDataType();
2162
                        else
2163
                                return new int[]{IBuffer.TYPE_UNDEFINED};
2164
                }
2165
        }
2166

    
2167
        /*
2168
         * (non-Javadoc)
2169
         * @see org.gvsig.fmap.raster.layers.FLyrRasterSE#overviewsSupport()
2170
         */
2171
        public boolean overviewsSupport() {
2172
                return false;
2173
        }
2174

    
2175
        protected void updateDrawVersion() {
2176
                if (this.disableUpdateDrawVersion != null){
2177

    
2178
                        Thread curThread = Thread.currentThread();
2179

    
2180
                        Thread aThread;
2181

    
2182
                        Iterator iter = this.disableUpdateDrawVersion.iterator();
2183
                        while (iter.hasNext()){
2184
                                aThread = (Thread) ((WeakReference)iter.next()).get();
2185
                                if (aThread == null){
2186
                                        iter.remove();
2187
                                } else if(aThread.equals(curThread)){
2188
                                        return;
2189
                                }
2190
                        }
2191
                }
2192
//                Exception ex = new Exception();
2193
//                ex.printStackTrace();
2194
                super.updateDrawVersion();
2195
        }
2196

    
2197
        protected void disableUpdateDrawVersion(){
2198
                if (this.disableUpdateDrawVersion == null){
2199
                        this.disableUpdateDrawVersion = new ArrayList();
2200
                }
2201
                this.disableUpdateDrawVersion.add(new WeakReference(Thread.currentThread()));
2202
        }
2203

    
2204
        protected void enableUpdateDrawVersion(){
2205
                if (this.disableUpdateDrawVersion == null){
2206
                        return;
2207
                }
2208

    
2209
                Thread curThread = Thread.currentThread();
2210

    
2211
                Thread aThread;
2212

    
2213

    
2214
                Iterator iter = this.disableUpdateDrawVersion.iterator();
2215
                while (iter.hasNext()){
2216
                        aThread = (Thread) ((WeakReference)iter.next()).get();
2217
                        if (aThread == null){
2218
                                iter.remove();
2219
                        } else if(aThread.equals(curThread)){
2220
                                iter.remove();
2221
                                break;
2222
                        }
2223
                }
2224

    
2225
        }
2226
        
2227
        /*
2228
         * (non-Javadoc)
2229
         * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#cloneLayer()
2230
         */
2231
        public FLayer cloneLayer() throws Exception {
2232
                FLyrWMS layer = new FLyrWMS();
2233
                layer.setHost(this.getHost());
2234
                layer.setName(this.getName());
2235
                layer.setSRS(this.getSRS());
2236
                layer.setFormat(this.getFormat());
2237
                layer.setFullExtent(this.fullExtent);
2238
                layer.setDriver(this.getDriver());
2239
        layer.setStyles(getStyles());
2240
        layer.setOnlineResources(this.onlineResources);
2241
        layer.setFixedSize(this.fixedSize);
2242
        layer.setQueryable(this.queryable);
2243
        layer.setWmsTransparency(this.wmsTransparency);
2244
        layer.setDimensions(this.dimensions);
2245
        layer.setLayerQuery(this.layerQuery);
2246
        layer.setInfoLayerQuery(this.infoLayerQuery);
2247
        
2248
                ArrayList filters = null;
2249
                if(layer.getRender().getFilterList() == null) {
2250
                        layer.getRender().setFilterList(new RasterFilterList());
2251
                        filters = layer.getRender().getFilterList().getStatusCloned();
2252
                }
2253
                else
2254
                        filters = getRender().getFilterList().getStatusCloned();
2255
                layer.getRender().getFilterList().setStatus(filters);
2256
                
2257
                return layer;
2258
        }
2259

    
2260
        /*
2261
         * (non-Javadoc)
2262
         * @see org.gvsig.fmap.raster.layers.FLyrRasterSE#getFileLayer()
2263
         */
2264
        public FLayer getFileLayer() {
2265
                if(layerRaster != null && layerRaster[0] != null) {
2266
                        FLyrRasterSE ly = null;
2267
                        if(lastNColumns == 0 && lastNRows == 0) {
2268
                                try {
2269
                                        ly = createLayer(layerRaster[0].getName(), layerRaster[0].getLoadParams(), layerRaster[0].getProjection());
2270
                                } catch (LoadLayerException e) {
2271
                                        return null;
2272
                                }
2273
                        } else {
2274

    
2275
                                String[][] s = new String[lastNRows][lastNColumns];
2276

    
2277
                                for (int i = 0; i < s.length; i++) {
2278
                                        for (int j = 0; j < s[0].length; j++) {
2279
                                                s[i][j] = ((FLyrRasterSE)layerRaster[i]).getDataSource().getNameDatasetStringList(i, j)[0];
2280
                                        }
2281
                                }
2282
                                try {
2283
                                        ly = createLayer("preview", s, getProjection());
2284
                                } catch (LoadLayerException e) {
2285
                                        return null;
2286
                                }
2287
                        }
2288
                        return ly;
2289
                }
2290
                return null;
2291
        }
2292

    
2293
}