Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extArcims / src / es / prodevelop / cit / gvsig / arcims / fmap / layers / FRasterLyrArcIMS.java @ 8707

History | View | Annotate | Download (29.8 KB)

1
package es.prodevelop.cit.gvsig.arcims.fmap.layers;
2

    
3
import es.prodevelop.cit.gvsig.arcims.fmap.drivers.ArcImsDriver;
4
import es.prodevelop.cit.gvsig.arcims.fmap.drivers.FMapFeatureArcImsDriver;
5
import es.prodevelop.cit.gvsig.arcims.fmap.drivers.FMapRasterArcImsDriver;
6
import es.prodevelop.cit.gvsig.arcims.fmap.listeners.FRasterLyrArcIMSListener;
7

    
8
import java.awt.Color;
9
import java.awt.Dimension;
10
import java.awt.Graphics2D;
11
import java.awt.Point;
12
import java.awt.Rectangle;
13
import java.awt.event.ActionEvent;
14
import java.awt.event.ActionListener;
15
import java.awt.geom.AffineTransform;
16
import java.awt.geom.NoninvertibleTransformException;
17
import java.awt.geom.Point2D;
18
import java.awt.geom.Rectangle2D;
19
import java.awt.image.BufferedImage;
20
import java.awt.image.DataBuffer;
21
import java.io.File;
22
import java.io.IOException;
23
import java.lang.reflect.Constructor;
24
import java.lang.reflect.InvocationTargetException;
25
import java.net.MalformedURLException;
26
import java.net.URL;
27
import java.util.ArrayList;
28
import java.util.HashMap;
29
import java.util.Map;
30
import java.util.Vector;
31

    
32
import org.apache.log4j.Logger;
33
import org.cresques.geo.ViewPortData;
34
import org.cresques.io.GdalFile;
35
import org.cresques.io.GeoRasterFile;
36
import org.cresques.cts.IProjection;
37
import org.cresques.filter.RasterFilterStack;
38
import org.cresques.filter.RasterFilterStackManager;
39
import org.cresques.px.Extent;
40
import org.cresques.px.PxRaster;
41
import org.gvsig.remoteClient.arcims.ArcImsClientP;
42
import org.gvsig.remoteClient.arcims.ArcImsProtImageHandler;
43
import org.gvsig.remoteClient.arcims.ArcImsProtocolHandler;
44
import org.gvsig.remoteClient.arcims.ArcImsStatus;
45
import org.gvsig.remoteClient.arcims.exceptions.ArcImsException;
46
import org.gvsig.remoteClient.arcims.utils.MyCancellable;
47
import org.gvsig.remoteClient.arcims.utils.ServiceInfoTags;
48
import org.gvsig.remoteClient.arcims.utils.ServiceInformation;
49
import org.gvsig.remoteClient.arcims.utils.ServiceInformationLayer;
50
import org.gvsig.remoteClient.utils.Utilities;
51

    
52
import com.iver.cit.gvsig.fmap.DriverException;
53
import com.iver.cit.gvsig.fmap.ViewPort;
54
import com.iver.cit.gvsig.fmap.crs.CRSFactory;
55
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
56

    
57
import com.iver.cit.gvsig.fmap.layers.FLayer;
58
import com.iver.cit.gvsig.fmap.layers.FLyrDefault;
59
import com.iver.cit.gvsig.fmap.layers.RasterAdapter;
60
import com.iver.cit.gvsig.fmap.layers.RasterOperations;
61
import com.iver.cit.gvsig.fmap.layers.StatusLayerRaster;
62
import com.iver.cit.gvsig.fmap.layers.StatusRasterInterface;
63
import com.iver.cit.gvsig.fmap.layers.Tiling;
64
import com.iver.cit.gvsig.fmap.layers.XMLException;
65
import com.iver.cit.gvsig.fmap.layers.layerOperations.InfoByPoint;
66
import com.iver.cit.gvsig.fmap.layers.layerOperations.StringXMLItem;
67
import com.iver.cit.gvsig.fmap.layers.layerOperations.XMLItem;
68
import com.iver.utiles.StringUtilities;
69
import com.iver.utiles.XMLEntity;
70
import com.iver.utiles.connections.ConnectionException;
71
import com.iver.utiles.swing.threads.Cancellable;
72
import com.iver.utiles.swing.threads.DefaultCancellableMonitorable;
73

    
74
import org.gvsig.remoteClient.wms.ICancellable;
75

    
76
/**
77
 * This class implements an ArcIMS raster layer.
78
 * 
79
 * @author jldominguez
80
 */
81
public class FRasterLyrArcIMS extends FLyrDefault implements RasterOperations, InfoByPoint {
82
        
83
        private MyCancellable myCanc;
84

    
85
        private static Logger logger = Logger.getLogger(FRasterLyrArcIMS.class.getName());
86
        
87
        private URL host;
88
        private String service;
89
        private String serviceType;
90
        private Rectangle2D fullExtent;
91
        private boolean firstLoad = false;
92
        private ArcImsStatus arcimsStatus = new ArcImsStatus();
93
        private String SRS;
94
        private String layerQuery;
95
        private ArcImsDriver driver;
96
        private VisualStatusArcIms visualStatus = new VisualStatusArcIms();
97
        
98
        private int transparency = -1;
99
        private boolean arcImsTransparency = true;
100

    
101
        private String format;
102
        private StatusRasterInterface status = null;
103
        private GeoRasterFile rasterFile = null;
104
        private PxRaster raster = null;
105
        private int rband = 0, gband = 1, bband = 2;
106
        private RasterFilterStackManager stackManager = null;
107
        private RasterFilterStack filterStack = null;
108
        private int posX = 0, posY = 0;
109
        private double posXWC = 0, posYWC = 0;
110
        private int r = 0, g = 0, b = 0;
111
        private ArrayList actionListeners = new ArrayList();
112
        private int maxTileWidth = 1023;
113
        private int maxTileHeight = 1023;
114
        
115
        private boolean nameQueryChange = false;
116
        
117
        private ArrayList listeners = new ArrayList();
118
        
119
        private boolean tiled = false;
120
        private int[] tileSize = new int[2];
121
        
122
        
123
        public static final String SCALE_CHANGED_COMMAND = "SCALE_HAS_CHANGED";
124
        private ActionEvent scaleChangedEvent = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, SCALE_CHANGED_COMMAND);
125
        
126
        public FRasterLyrArcIMS() {
127
                myCanc = new MyCancellable(new DefaultCancellableMonitorable());
128
        }
129

    
130
        /**
131
         * Gets the driver object onto which <tt>getMap()</tt> and
132
         * <tt>getFeatureInfo()</tt> requests are passed. If the driver was not
133
         * created, this methdo creates it with the server's URL and the service
134
         * name.
135
         * 
136
         * @return the driver that actually performs the requests.
137
         */
138
        public ArcImsDriver getDriver() {
139
                if (driver == null) {
140
                        driver = new FMapRasterArcImsDriver(host.toString(), service,
141
                                        this.serviceType);
142
                }
143
                return driver;
144
        }
145

    
146
        public void setDriver(FMapRasterArcImsDriver d) {
147
                driver = d;
148
        }
149

    
150
        /**
151
         * Gets the transformation matrix to be written in the georeference file.
152
         * The second and the third coefficients will always be zero (it doesn't
153
         * implement image rotation)
154
         * 
155
         * @param bBox
156
         *            Image's size and position (user's coordinates)
157
         * @param sz
158
         *            Images' size in pixels
159
         * @return the worldfile, as a String
160
         * @throws IOException
161
         */
162
        public String getDataWorldFile(Rectangle2D bBox, Dimension sz)
163
                        throws IOException {
164
                StringBuffer data = new StringBuffer();
165
                data.append((bBox.getMaxX() - bBox.getMinX()) / (sz.getWidth() - 1)
166
                                + "\n");
167
                data.append("0.0\n");
168
                data.append("0.0\n");
169
                data.append("-" + (bBox.getMaxY() - bBox.getMinY()) / (sz.getHeight() - 1) + "\n");
170
                // guardalo por si acaso :)
171
                // data.append((bBox.getMaxY() - bBox.getMinY()) / (sz.getHeight() - 1) + "\n");
172
                data.append("" + bBox.getMinX() + "\n");
173
                // data.append("" + bBox.getMinY() + "\n");
174
                data.append("" + bBox.getMaxY() + "\n");
175
                return data.toString();
176
        }
177

    
178
        /**
179
         * Gets the raster status
180
         * 
181
         * @return the raster status
182
         */
183
        public StatusRasterInterface getStatus() {
184
                return this.status;
185
        }
186

    
187
        public void setStatus(StatusRasterInterface s) {
188
                this.status = s;
189
        }
190

    
191
        /**
192
         * This method must be invoqued with <b>true</b> if the layer must show its
193
         * transparency. The level of transparency is set by another method.
194
         * 
195
         * @param t
196
         *            Whether or not the transparency must be shown.
197
         */
198
        public void setArcImsTransparency(boolean t) {
199
                this.arcImsTransparency = t;
200
        }
201

    
202
        /**
203
         * Drawing method invoqued from outside the plugin.
204
         * 
205
         * @param g
206
         *            graphic object on which drawing is made.
207
         * @param vp
208
         *            the view
209
         * @param cancel
210
         *            allows drawing abortion
211
         * @throws DriverException
212
         */
213
        private void drawTile(Graphics2D g, ViewPort vp, Cancellable cancel)
214
                        throws DriverException {
215
                // This is the extent that will be requested
216
                Rectangle2D bBox = vp.getAdjustedExtent();// getFullExtent();
217
                Dimension sz = vp.getImageSize();
218

    
219
                try {
220
                        arcimsStatus.setExtent(bBox);
221
                        arcimsStatus.setFormat(getFormat());
222
                        arcimsStatus.setHeight(vp.getImageHeight());
223
                        arcimsStatus.setWidth(vp.getImageWidth());
224
                        arcimsStatus.setLayerIds(Utilities.createVector(layerQuery, ","));
225
                        arcimsStatus.setServer(host.toString());
226
                        arcimsStatus.setService(service);
227
                        arcimsStatus.setSrs(this.getProjection().getAbrev());
228
                        arcimsStatus.setTransparency(this.arcImsTransparency);
229

    
230
                        // We need to cast because driver returns an Object
231
                        File f = (File) getDriver().getMap(arcimsStatus);
232
                        
233
                        int lastp = f.getPath().lastIndexOf(".");
234
                        String noext = f.getPath().substring(0,lastp);
235
                        
236
                        String nameWorldFile = noext
237
                                        + getExtensionWordFile(getFormat());
238

    
239
                        com.iver.andami.Utilities.createTemp(nameWorldFile, this
240
                                        .getDataWorldFile(bBox, sz));
241

    
242
                        if (status != null && firstLoad) {
243
                                status.applyStatus(this);
244
                                firstLoad = false;
245
                        }
246

    
247
                        // And finally, obtain the extent intersecting the view and the BBox
248
                        // to draw to.
249
                        // ------------------------------ START (?)
250
                        // Rectangle2D extent = new Rectangle2D.Double();
251
                        // Rectangle2D.intersect(vp.getAdjustedExtent(), bBox, extent);
252
                        // ViewPortData vpData = new ViewPortData(vp.getProjection(),
253
                        // new Extent(extent), sz);
254
                        // vpData.setMat(vp.getAffineTransform());
255
                        // ------------------------------ END (?)
256

    
257
                        // ------------------------------ START
258
                        ViewPortData vpData = new ViewPortData(vp.getProjection(),
259
                                        new Extent(bBox), sz);
260
                        vpData.setMat(vp.getAffineTransform());
261
                        // ------------------------------ END
262

    
263
                        rasterProcess(g, vpData, f);
264

    
265
                } catch (IOException e) {
266
                        DriverException de = new DriverException("connect_error");
267
                        logger.error("While connecting ", e);
268
                        throw de;
269
                } catch (ArcImsException e) {
270
                        logger.error("While drawing ", e);
271
                        this.setVisible(false);
272
                        DriverException de = new DriverException(e.getMessage());
273
                        throw de;
274
                }
275

    
276
        }
277

    
278
        /**
279
         * Drawing method invoqued from gvSIG to draw this layer. Uses a <tt>Tiling</tt>
280
         * object to prevent downloading images too large to be retrieved
281
         * (pixel count limit)
282
         * 
283
         * @param image
284
         *            used to speed up drawing process
285
         * @param g
286
         *            graphic object on which drawing is make
287
         * @param viewPort
288
         *            the view's properties
289
         * @param cancel
290
         *            allows drawing abortion
291
         * @param scale the current scale
292
         *                                 
293
         * @throws DriverException
294
         */
295
        public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
296
                        Cancellable cancel, double scale) throws DriverException {
297
                
298
                if (! isVisible()) return;
299
                if (! isWithinScale(scale)) return;
300
                
301
                visualStatus.width = viewPort.getImageWidth();
302
                visualStatus.height = viewPort.getImageHeight();
303
                visualStatus.minX = viewPort.getAdjustedExtent().getMinX();
304
                visualStatus.minY = viewPort.getAdjustedExtent().getMinY();
305
                visualStatus.maxX = viewPort.getAdjustedExtent().getMaxX();
306
                visualStatus.maxY = viewPort.getAdjustedExtent().getMaxY();
307
                
308
                setTileDimensions(viewPort);
309
                        
310
                Point2D p = viewPort.getOffset();
311
                Rectangle r = new Rectangle((int) p.getX(), (int) p.getY(), viewPort.getImageWidth() - 1, viewPort.getImageHeight() - 1);
312
                Tiling tiles = new Tiling(maxTileWidth, maxTileHeight, r);
313
                tiles.setAffineTransform((AffineTransform) viewPort
314
                                .getAffineTransform().clone());
315
                
316
                tiled = false;
317
                if (tiles.getNumTiles() > 1) {
318
                        tiled = true;
319
                        tileSize[0] = tiles.getMaxTileWidth();
320
                        tileSize[1] = tiles.getMaxTileHeight();
321
                }
322
                for (int tileNr = 0; tileNr < tiles.getNumTiles(); tileNr++) {
323
                        // drawing part
324
                        try {
325
                                ViewPort vp = tiles.getTileViewPort(viewPort, tileNr);
326
                                drawTile(g, vp, cancel);
327
                        } catch (NoninvertibleTransformException e) {
328
                                logger.error("Non invertible matrix ", e);
329
                        }
330
                }
331
                
332
                // the status needs to be reset because the drawTile
333
                // method had changed its extent and dimension:
334
                arcimsStatus.setExtent(viewPort.getAdjustedExtent());
335
                arcimsStatus.setHeight(viewPort.getImageHeight());
336
                arcimsStatus.setWidth(viewPort.getImageWidth());
337

    
338
                callActionListeners(scaleChangedEvent);
339
                if (nameQueryChange) {
340
                        callNameOrQueryListeners();
341
                        nameQueryChange = false;
342
                }
343
        }
344

    
345
        private void setTileDimensions(ViewPort vp) {
346
                maxTileHeight =  vp.getImageHeight();
347
                try {
348
                        maxTileWidth =
349
                                Integer.parseInt(arcimsStatus.getServiceInfo().getImagelimit_pixelcount()) / maxTileHeight;
350
                        maxTileWidth--;
351
                } catch (NumberFormatException nfe) {
352
                        logger.error("getImagelimit_pixelcount() returned a non parseable string. maxTileWidth was set to 100.", nfe);
353
                        maxTileWidth = 100;
354
                }
355
                logger.info("Tile size = [ " + maxTileWidth + " , " + maxTileHeight + " ]");
356
        }
357

    
358
        /**
359
         * Gets the georeference file extension depending on the image's format.
360
         * 
361
         * @param f
362
         *            raster file format
363
         * @return georeference file extension (".wld", ".tfw", etc)
364
         */
365
        private String getExtensionWordFile(String f) {
366
                String extWorldFile = ".wld";
367
                if (f.equals("tif") || f.equals("tiff"))
368
                        extWorldFile = ".tfw";
369
                if (f.equals("jpeg"))
370
                        extWorldFile = ".jpgw";
371
                return extWorldFile;
372
        }
373

    
374
        /**
375
         * Draws an image using PxRaster
376
         * 
377
         * @param g
378
         *            graphics object on which drawing will be made
379
         * @param vpData
380
         *            viewport's properties
381
         * @param file
382
         *            the image file
383
         */
384
        private void rasterProcess(Graphics2D g, ViewPortData vpData, File file) {
385

    
386
                // PxRaster is created
387
                rasterFile = new GdalFile(vpData.getProjection(), file
388
                                .getAbsolutePath());
389
                raster = new PxRaster(rasterFile, null, rasterFile.getExtent());
390

    
391
                if (this.filterStack != null)
392
                        raster.filterStack = this.filterStack;
393

    
394
                raster.setTransparency(false); 
395

    
396
                if (this.transparency == -1 && !firstLoad)
397
                        ;
398
                else
399
                        raster.setTransparency(this.transparency);
400

    
401
                raster.setBand(GeoRasterFile.RED_BAND, rband);
402
                raster.setBand(GeoRasterFile.GREEN_BAND, gband);
403
                raster.setBand(GeoRasterFile.BLUE_BAND, bband);
404

    
405
                if (this.stackManager != null)
406
                        raster.setStackManager(this.stackManager);
407
                
408
                if(visualStatus != null){
409
                        visualStatus.bandCount = raster.getBandCount();
410
                        visualStatus.dataType = raster.getDataType();
411
                }
412

    
413
                raster.draw(g, vpData);
414

    
415
                // We get the Stack Manager with the first pxRaster of an image
416
                // so we can modify it afterwards from the properties dialog
417
                if (this.stackManager == null)
418
                        this.stackManager = raster.getStackManager();
419

    
420
                if (this.filterStack == null)
421
                        this.filterStack = raster.filterStack;
422
        }
423

    
424
        public void repaintRaster(Graphics2D g, ViewPortData vpData, File file) {
425
                rasterProcess(g, vpData, file);
426
        }
427

    
428
        public String getFormat() {
429
                return format;
430
        }
431

    
432
        public void setFormat(String format) {
433
                this.format = format;
434
        }
435

    
436

    
437
        /**
438
         * Gets a series of attributes that describe the layer's raster: Filename,
439
         * Filesize, Height, Width and Bands.
440
         * 
441
         * @return A list of 2-element arrays { "Attribute name" , Value }
442
         */
443
        public ArrayList getAttributes() {
444
                if (rasterFile != null) {
445
                        ArrayList attr = new ArrayList();
446
                        Object[][] a = {
447
                                        {
448
                                                        "Filename",
449
                                                        rasterFile.getName().substring(
450
                                                                        rasterFile.getName().lastIndexOf("/") + 1,
451
                                                                        rasterFile.getName().length()) },
452
                                        { "Filesize", new Long(rasterFile.getFileSize()) },
453
                                        {
454
                                                        "Width",
455
                                                        new Integer((new Double(this.getWidth()))
456
                                                                        .intValue()) },
457
                                        {
458
                                                        "Height",
459
                                                        new Integer((new Double(this.getHeight()))
460
                                                                        .intValue()) },
461
                                        { "Bands", new Integer(rasterFile.getBandCount()) } };
462
                        for (int i = 0; i < a.length; i++) {
463
                                attr.add(a[i]);
464
                        }
465
                        return attr;
466
                }
467
                return null;
468
        }
469

    
470
        /**
471
         * 
472
        /**
473
         * Invoqued from gvSIG to draw this layer on a printable map. Uses a
474
         * <tt>Tiling</tt> object to prevent downloading images too large to be
475
         * retrieved (pixel count limit).
476
         * 
477
         * @param g
478
         *            graphic object on which drawing is make
479
         * @param viewPort
480
         *            the view's properties
481
         * @param cancel
482
         *            allows drawing abortion
483
         * @param scale the current scale
484
         *                                 
485
         * @throws DriverException
486
         */
487
        public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
488
                        double scale) throws DriverException {
489

    
490
                draw(null, g, viewPort, cancel, scale);
491
        }
492

    
493
        public HashMap getProperties() {
494
                HashMap info = new HashMap();
495
                String[] layerNames = getLayerQuery().split(",");
496
                Vector layers = new Vector(layerNames.length);
497
                try {
498
                        if (((FMapRasterArcImsDriver) getDriver()).connect(myCanc)) {
499
                                info.put("layerName", this.getName());
500
                                info.put("serverUrl", this.getHost());
501
                                info.put("serviceName", this.getService());
502
                                info.put("serviceType", this.getServiceType());
503
                                info.put("format", this.format);
504
                                for (int i = 0; i < layerNames.length; i++)
505
                                        layers.add(layerNames[i]);
506
                                info.put("layerIds", layers);
507
                                return info;
508
                        }
509
                } catch (Exception e) {
510
                        logger.error("Error while reading FRasterLyrArcIMS properties. ", e);
511
                }
512
                return null;
513
        }
514

    
515
        public RasterFilterStack getFilterStack() {
516
                if (raster != null)
517
                        return raster.filterStack;
518
                return null;
519
        }
520

    
521
        public double getHeight() {
522
                return visualStatus.height;
523
        }
524

    
525
        public double getMaxX() {
526
                return visualStatus.maxX;
527
        }
528

    
529
        public double getMaxY() {
530
                return visualStatus.maxY;
531
        }
532

    
533
        public double getMinX() {
534
                return visualStatus.minX;
535
        }
536

    
537
        public double getMinY() {
538
                return visualStatus.minY;
539
        }
540

    
541
        public int[] getPixel(double wcx, double wcy) {
542
                if (getPxRaster() != null)
543
                        return getPxRaster().getPixel(wcx, wcy);
544
                return null;
545
        }
546

    
547
        public RasterAdapter getSource() {
548
                return null;
549
        }
550

    
551
        public double getWidth() {
552
                return visualStatus.width;
553
        }
554

    
555
        public void setBand(int flag, int nBand) {
556
                switch (flag) {
557
                case GeoRasterFile.RED_BAND:
558
                        setBandR(nBand);
559
                        break;
560
                case GeoRasterFile.GREEN_BAND:
561
                        setBandG(nBand);
562
                        break;
563
                case GeoRasterFile.BLUE_BAND:
564
                        setBandB(nBand);
565
                        break;
566
                }
567
        }
568

    
569
        
570
        public void setFilterStack(RasterFilterStack stack) {
571
                this.filterStack = stack;
572
        }
573

    
574
        public void setPos(int x, int y) {
575
                this.posX = x;
576
                this.posY = y;
577
        }
578

    
579
        public void setPosWC(double x, double y) {
580
                this.posXWC = x;
581
                this.posYWC = y;
582
        }
583

    
584
        public void setRGB(int r, int g, int b) {
585
                this.r = r;
586
                this.g = g;
587
                this.b = b;
588
        }
589
        
590
        public Color getRGB() {
591
                return new Color(r, g, b);
592
        }
593

    
594
        public void setSource(RasterAdapter ra) {
595
        }
596

    
597
        /**
598
         * @return Returns the raster.
599
         */
600
        public PxRaster getPxRaster() {
601
                return raster;
602
        }
603

    
604
        /**
605
         * @return Returns the rasterFile.
606
         */
607
        public GeoRasterFile getGeoRasterFile() {
608
                return rasterFile;
609
        }
610

    
611

    
612
        /**
613
         * Sets the R-band.
614
         * 
615
         * @param r
616
         */
617
        public void setBandR(int r) {
618
                this.rband = r;
619
        }
620

    
621
        /**
622
         * Sets the G-band.
623
         * 
624
         * @param g
625
         */
626
        public void setBandG(int g) {
627
                this.gband = g;
628
        }
629

    
630
        /**
631
         * Sets the B-band.
632
         * 
633
         * @param b
634
         */
635
        public void setBandB(int b) {
636
                this.bband = b;
637
        }
638

    
639
        /**
640
         * 
641
         * @return XMLEntity.
642
         * @throws XMLException
643
         */
644
        public XMLEntity getXMLEntity() throws XMLException {
645
                XMLEntity xml = super.getXMLEntity();
646

    
647
                xml.putProperty("fullExtent", StringUtilities.rect2String(fullExtent));
648
                xml.putProperty("host", host.toExternalForm());
649
                xml.putProperty("serviceName", service);
650
                xml.putProperty("serviceType", serviceType);
651
                xml.putProperty("layerQuery", layerQuery);
652
                xml.putProperty("format", format);
653
                if (status != null) {
654
                        status.getXMLEntity(xml, true, this);
655
                } else {
656
                        status = new StatusLayerRaster();
657
                        status.getXMLEntity(xml, true, this);
658
                }
659
                xml.putProperty("arcims_transparency", arcImsTransparency);
660
                return xml;
661
        }
662

    
663
        /**
664
         * 
665
         * @param xml
666
         *            XMLEntity
667
         * 
668
         * @throws XMLException
669
         * @throws DriverException
670
         * @throws DriverIOException
671
         */
672
        public void setXMLEntity(XMLEntity xml) throws XMLException {
673

    
674
                super.setXMLEntity(xml);
675
                fullExtent = StringUtilities.string2Rect(xml
676
                                .getStringProperty("fullExtent"));
677
                try {
678
                        host = new URL(xml.getStringProperty("host"));
679
                } catch (MalformedURLException e) {
680
                        logger.error("Whle reading XML file ", e);
681
                        throw new XMLException(e);
682
                }
683

    
684
                this.layerQuery = xml.getStringProperty("layerQuery");
685
                this.service = xml.getStringProperty("serviceName");
686
                this.serviceType = xml.getStringProperty("serviceType");
687
                this.format = xml.getStringProperty("format");
688
                
689
                FMapRasterArcImsDriver drv = new FMapRasterArcImsDriver(host.toString(), service, serviceType);
690
                if (!drv.connect(myCanc)) {
691
                        logger.error("Error while loading service information. ");
692
                }
693
                ArcImsClientP cli = (ArcImsClientP) drv.getClient();
694
                ServiceInformation si = cli.getServiceInformation();
695
                this.arcimsStatus.setServiceInformation(si);
696

    
697
                if (xml.contains("arcims_transparency"))
698
                        this.arcImsTransparency = xml
699
                                        .getBooleanProperty("arcims_transparency");
700

    
701
                String claseStr = StatusLayerRaster.defaultClass;
702
                if (xml.contains("raster.class"))
703
                        claseStr = xml.getStringProperty("raster.class");
704

    
705
                if (status != null) {
706
                        status.setXMLEntity(xml, this);
707
                } else {
708
                        // When we load a project
709
                        if (claseStr != null && !claseStr.equals("")) {
710
                                try {
711
                                        Class clase = Class.forName(claseStr);
712
                                        Constructor constr = clase.getConstructor(null);
713
                                        status = (StatusRasterInterface) constr.newInstance(null);
714
                                        if (status != null)
715
                                                status.setXMLEntity(xml, this);
716
                                } catch (ClassNotFoundException exc) {
717
                                        logger.error("Whle reading XML file ", exc);
718
                                } catch (InstantiationException exc) {
719
                                        logger.error("Whle reading XML file ", exc);
720
                                } catch (IllegalAccessException exc) {
721
                                        logger.error("Whle reading XML file ", exc);
722
                                } catch (NoSuchMethodException exc) {
723
                                        logger.error("Whle reading XML file ", exc);
724
                                } catch (InvocationTargetException exc) {
725
                                        logger.error("Whle reading XML file ", exc);
726
                                }
727
                        }
728
                }
729
                firstLoad = true;
730
        }
731

    
732
        public Vector getLayerScaleInfoVector() {
733
                Vector v = new Vector();
734
                String id;
735

    
736
                for (int i = 0; i < arcimsStatus.getLayerIds().size(); i++) {
737
                        id = (String) arcimsStatus.getLayerIds().get(i);
738
                        v.add(getScaleInfo(id));
739
                }
740
                return v;
741
        }
742

    
743
        public LayerScaleData getScaleInfo(String theId) {
744
                ServiceInformation si;
745
                ServiceInformationLayer sil;
746
                int noflayers;
747
                long true_max_scale, true_min_scale;
748

    
749
                LayerScaleData theLayerScaleData = null;
750

    
751
                si = arcimsStatus.getServiceInfo();
752
                int _dpi = si.getScreen_dpi();
753
                String mapUnits = si.getMapunits();
754

    
755
                noflayers = si.getLayers().size();
756
                for (int i = 0; i < noflayers; i++) {
757
                        sil = (ServiceInformationLayer) si.getLayer(i);
758
                        if ((sil.getId().compareTo(theId)) == 0) {
759
                                true_max_scale = LayerScaleData
760
                                                .getTrueScaleFromRelativeScaleAndMapUnits(sil.getMaxscale(),
761
                                                                mapUnits, _dpi);
762
                                true_min_scale = LayerScaleData
763
                                                .getTrueScaleFromRelativeScaleAndMapUnits(sil.getMinscale(),
764
                                                                mapUnits, _dpi);
765
                                theLayerScaleData = new LayerScaleData(sil.getName(), sil.getId(),
766
                                                true_min_scale, true_max_scale, sil.getType());
767
                        }
768
                }
769
                return theLayerScaleData;
770
        }
771

    
772
        public void addActionlistener(ActionListener al) {
773
                if (actionListeners.contains(al)) return;
774
                actionListeners.add(al);
775
        }
776
        
777
        public void removeActionlistener(ActionListener al) {
778
                actionListeners.remove(al);
779
        }
780
        
781
        private void callActionListeners(ActionEvent ae) {
782
                ActionListener al;
783
                for (int i=0; i<actionListeners.size(); i++) {
784
                        al = (ActionListener) actionListeners.get(i);
785
                        al.actionPerformed(ae);
786
                }
787
        }
788
        
789
        public long getScale() {
790
                return getMapContext().getScaleView();
791
        }
792

    
793
        public int getMaxTileHeight() {
794
                return maxTileHeight;
795
        }
796

    
797
        public void setMaxTileHeight(int maxTileHeight) {
798
                this.maxTileHeight = maxTileHeight;
799
        }
800

    
801
        public int getMaxTileWidth() {
802
                return maxTileWidth;
803
        }
804

    
805
        public void setMaxTileWidth(int maxTileWidth) {
806
                this.maxTileWidth = maxTileWidth;
807
        }
808
        
809
        public void setServiceInformationInStatus(ServiceInformation si) {
810
                this.arcimsStatus.setServiceInformation(si);
811
        }
812

    
813
        /**
814
         * This is the <tt>getDriver</tt> method. The <tt>getDriver</tt>
815
         * method will be implemented by sub-classes.
816
         *  
817
         * @param d the new driver.
818
         */
819
        public void setDriver(ArcImsDriver d) {
820
                driver = d;
821
        }
822

    
823
        public ArcImsStatus getArcimsStatus() {
824
                return arcimsStatus;
825
        }
826

    
827
        public void setArcimsStatus(ArcImsStatus arcimsStatus) {
828
                this.arcimsStatus = arcimsStatus;
829
        }
830

    
831
        public boolean isFirstLoad() {
832
                return firstLoad;
833
        }
834

    
835
        public void setFirstLoad(boolean firstLoad) {
836
                this.firstLoad = firstLoad;
837
        }
838

    
839
        public URL getHost() {
840
                return host;
841
        }
842

    
843
        public void setHost(URL host) {
844
                this.host = host;
845
        }
846

    
847
        public String getLayerQuery() {
848
                return layerQuery;
849
        }
850

    
851
        public void setLayerQuery(String lQuery) {
852
                this.layerQuery = lQuery;
853
                if (layerQuery.substring(0, 1).compareTo(",") == 0)
854
                        layerQuery = layerQuery.substring(1);
855
        }
856

    
857
        public String getService() {
858
                return service;
859
        }
860

    
861
        public void setService(String service) {
862
                this.service = service;
863
        }
864

    
865
        public String getServiceType() {
866
                return serviceType;
867
        }
868

    
869
        public void setServiceType(String serviceType) {
870
                this.serviceType = serviceType;
871
        }
872

    
873
        public String getSRS() {
874
                return SRS;
875
        }
876

    
877
        public void setSRS(String srs) {
878
                SRS = srs;
879
        }
880

    
881
        public void setFullExtent(Rectangle2D fullExtent) {
882
                this.fullExtent = fullExtent;
883
        }
884
        
885
        public Rectangle2D getFullExtent() {
886
                return fullExtent;
887
        }
888

    
889
        public boolean getArcImsTransparency() {
890
                return arcImsTransparency;
891
        }
892

    
893
        public int getTransparency() {
894
                return transparency;
895
        }
896

    
897
        public void setTransparency(int transparency) {
898
                this.transparency = transparency;
899
        }
900
        
901
        
902
        
903
        private class VisualStatusArcIms {
904
                /**
905
                 * Ancho y alto de la imagen o del conjunto de tiles si los tiene. Coincide con 
906
                 * el ancho y alto del viewPort
907
                 */
908
                private        int                                                        width = 0, height = 0;
909
                private double                                                minX = 0D, minY = 0D, maxX = 0D, maxY = 0D;
910
                private int                                                 bandCount = 0;
911
                private int                                                        dataType = DataBuffer.TYPE_UNDEFINED;
912
        }
913

    
914

    
915

    
916
        public int getPosX() {
917
                return posX;
918
        }
919

    
920
        public void setPosX(int posX) {
921
                this.posX = posX;
922
        }
923

    
924
        public double getPosXWC() {
925
                return posXWC;
926
        }
927

    
928
        public void setPosXWC(double posXWC) {
929
                this.posXWC = posXWC;
930
        }
931

    
932
        public int getPosY() {
933
                return posY;
934
        }
935

    
936
        public void setPosY(int posY) {
937
                this.posY = posY;
938
        }
939

    
940
        public double getPosYWC() {
941
                return posYWC;
942
        }
943

    
944
        public void setPosYWC(double posYWC) {
945
                this.posYWC = posYWC;
946
        }
947

    
948
        public void setFormatInStatus(String imgFormat) {
949
                arcimsStatus.setFormat(imgFormat);
950
        }
951

    
952
        /**
953
         * This method invoques the <tt>FMapRasterArcImsDriver</tt>'s
954
         * <tt>getFeatureInfo</tt> method with the given coordinates as a
955
         * parameter
956
         * 
957
         * @param p
958
         *            the corrdinates of the screen pixel to be queried
959
         * 
960
         * @return the data retrieved for that pixel
961
         * @throws DriverException 
962
         */
963
        public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancel) throws DriverException {
964
                StringXMLItem[] resp = new StringXMLItem[1];
965
                String respStr;
966

    
967
                if (  ((FMapRasterArcImsDriver) driver).isQueryable()) {
968
                        try {
969
                                respStr = ((FMapRasterArcImsDriver) driver).getFeatureInfo(arcimsStatus, (int) p.getX(), (int) p
970
                                                .getY(), Integer.MAX_VALUE);
971
                        } catch (ArcImsException e) {
972
                                DriverException de = new DriverException(e.getMessage());
973
                                logger.error("In query by point ", e);
974
                                throw de;
975
                        }
976
                } else {
977
                        DriverException de = new DriverException("layer_not_queriable");
978
                        throw de;
979
                }
980
                System.err.println(resp); //TODO BORRAR ESTO
981
                resp[0] = new StringXMLItem(respStr, this);
982
                return resp;
983
        }
984

    
985
        public boolean isTiled() {
986
                return tiled;
987
        }
988

    
989
        public int[] getTileSize() {
990
                return tileSize;
991
        }
992
        
993
        /**
994
         * The extCatalogYNomenclator needs this creator.
995
         * 
996
         * @param p a Map object with the following keys:
997
         * 
998
         * (key, object type returned)
999
         * ---------------------------
1000
         * "host", String (with or without the servlet path, example:
1001
         *                                         "http://www.geographynetwork.com")
1002
         * "service_name", String (remote service name)
1003
         * "srs", String (coordinate system)
1004
         * "layer_name", String (local layer's name)
1005
         * 
1006
         * @return a FRasterLyrArcIMS layer
1007
         */
1008
        public FRasterLyrArcIMS(Map m) throws ConnectionException {
1009
                myCanc = new MyCancellable(new DefaultCancellableMonitorable());
1010
                String _host = "";
1011
                try {
1012
                        _host = (String) m.get("host");
1013
                        String _service_name = (String) m.get("service_name");
1014
                        String _srs = (String) m.get("srs");
1015
                        String _image_format = "JPG";
1016
                        String _layer_name = (String) m.get("layer_name");
1017
                        
1018
                        // in case layer_name is missing or equals the empty string:
1019
                        if ((_layer_name == null) || (_layer_name.length() == 0)) {
1020
                                _layer_name = _service_name;
1021
                        }
1022
                        // ----------------------------
1023
                        
1024
                        URL _true_host = ArcImsProtocolHandler.getUrlWithServlet(new URL(_host));
1025
                        IProjection _true_srs = CRSFactory.getCRS(_srs);
1026
                        
1027
                        
1028

    
1029
                        FMapRasterArcImsDriver _drv = new FMapRasterArcImsDriver(
1030
                                        _true_host.toString(),
1031
                                        _service_name, ServiceInfoTags.vIMAGESERVICE);
1032
                        if (!_drv.connect(myCanc))
1033
                                throw new ConnectionException("Unable to connect to host ",
1034
                                                new Exception(_host));
1035

    
1036
                        setDriver(_drv);
1037
                        setHost(_true_host);
1038
                        setService(_service_name);
1039
                        setServiceType(ServiceInfoTags.vIMAGESERVICE);
1040
                        setServiceInformationInStatus(_drv.getClient()
1041
                                        .getServiceInformation());
1042
                        ServiceInformation _si = getArcimsStatus().getServiceInfo();
1043

    
1044
                        if ((_si.getFeaturecoordsys() == null)
1045
                                        || (_si.getFeaturecoordsys().equals(""))) {
1046
                                _si.setFeaturecoordsys(_true_srs.getAbrev().substring(
1047
                                                ServiceInfoTags.vINI_SRS.length()).trim());
1048
                                logger.warn("Server provides no SRS. ");
1049
                        }
1050
                        setFullExtent(((ArcImsProtImageHandler) _drv.getClient()
1051
                                        .getHandler()).getServiceExtent(_true_srs, getArcimsStatus()));
1052

    
1053
                        //  JPG
1054
                        setFormat(_image_format);
1055
                        setTransparency(0);
1056
                        
1057
                        // =================================== query
1058
                        int layercount = _si.getLayers().size();
1059
                        String _layer_query = "";
1060
                        for (int i=0; i<layercount; i++) {
1061
                                if (isTrueString(((ServiceInformationLayer) _si.getLayer(i)).getVisible())) {
1062
                                        _layer_query = _layer_query + "," + ((ServiceInformationLayer) _si.getLayer(i)).getId();
1063
                                }
1064
                        }
1065
                        if (_layer_query.length() == 0) {
1066
                                throw new Exception("No layers are visible by default ");
1067
                        } else {
1068
                                _layer_query = _layer_query.substring(1);
1069
                        }
1070
                        // ===================================
1071
                        
1072
                        setLayerQuery(_layer_query);
1073
                        setProjection(_true_srs);
1074
                        setName(_layer_name);
1075
                } catch (Exception e) {
1076
                        new ConnectionException("Unable to connect to host " + _host, e);
1077
                }
1078
        }        
1079
        
1080
        private boolean isTrueString(String visible) {
1081
                if (visible.compareToIgnoreCase("true") == 0) {
1082
                        return true;
1083
                }
1084
                return false;
1085
        }
1086

    
1087
        public void callNameOrQueryListeners() {
1088
                for (int i=0; i<listeners.size(); i++) {
1089
                        ((FRasterLyrArcIMSListener) listeners.get(i)).thingsHaveChanged(
1090
                                        getLayerQuery(), getName());
1091
                }
1092
        }        
1093
        
1094
        public void addNameOrQueryListener(FRasterLyrArcIMSListener l) {
1095
                if (! listeners.contains(l)) {
1096
                        listeners.add(l);
1097
                }
1098
        }
1099
        
1100
        public void removeNameOrQueryListener(FRasterLyrArcIMSListener l) {
1101
                listeners.remove(l);
1102
        }
1103

    
1104
        public void setNameQueryChange(boolean c) {
1105
                nameQueryChange = c;
1106
        }
1107
        
1108

    
1109
}