Statistics
| Revision:

svn-gvsig-desktop / branches / v10 / extensions / extArcims / src / es / prodevelop / cit / gvsig / arcims / fmap / layers / FRasterLyrArcIMS.java @ 20976

History | View | Annotate | Download (38.2 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 Prodevelop 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
 *   Prodevelop Integraci?n de Tecnolog?as SL
34
 *   Conde Salvatierra de ?lava , 34-10
35
 *   46004 Valencia
36
 *   Spain
37
 *
38
 *   +34 963 510 612
39
 *   +34 963 510 968
40
 *   gis@prodevelop.es
41
 *   http://www.prodevelop.es
42
 */
43
package es.prodevelop.cit.gvsig.arcims.fmap.layers;
44

    
45
import com.iver.andami.PluginServices;
46

    
47
import com.iver.cit.gvsig.fmap.DriverException;
48
import com.iver.cit.gvsig.fmap.ViewPort;
49
import com.iver.cit.gvsig.fmap.crs.CRSFactory;
50
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
51
import com.iver.cit.gvsig.fmap.layers.FLayer;
52
import com.iver.cit.gvsig.fmap.layers.FLyrDefault;
53
import com.iver.cit.gvsig.fmap.layers.RasterAdapter;
54
import com.iver.cit.gvsig.fmap.layers.RasterOperations;
55
import com.iver.cit.gvsig.fmap.layers.StatusLayerRaster;
56
import com.iver.cit.gvsig.fmap.layers.StatusRasterInterface;
57
import com.iver.cit.gvsig.fmap.layers.Tiling;
58
import com.iver.cit.gvsig.fmap.layers.XMLException;
59
import com.iver.cit.gvsig.fmap.layers.layerOperations.InfoByPoint;
60
import com.iver.cit.gvsig.fmap.layers.layerOperations.StringXMLItem;
61
import com.iver.cit.gvsig.fmap.layers.layerOperations.XMLItem;
62

    
63
import com.iver.utiles.StringUtilities;
64
import com.iver.utiles.XMLEntity;
65
import com.iver.utiles.connections.ConnectionException;
66
import com.iver.utiles.swing.threads.Cancellable;
67
import com.iver.utiles.swing.threads.DefaultCancellableMonitorable;
68

    
69
import es.prodevelop.cit.gvsig.arcims.fmap.drivers.ArcImsDriver;
70
import es.prodevelop.cit.gvsig.arcims.fmap.drivers.FMapFeatureArcImsDriver;
71
import es.prodevelop.cit.gvsig.arcims.fmap.drivers.FMapRasterArcImsDriver;
72
import es.prodevelop.cit.gvsig.arcims.fmap.listeners.FRasterLyrArcIMSListener;
73

    
74
import org.apache.log4j.Logger;
75

    
76
import org.cresques.cts.IProjection;
77

    
78
import org.cresques.filter.RasterFilterStack;
79
import org.cresques.filter.RasterFilterStackManager;
80

    
81
import org.cresques.geo.ViewPortData;
82

    
83
import org.cresques.io.GdalFile;
84
import org.cresques.io.GeoRasterFile;
85
import org.cresques.io.data.Grid;
86
import org.cresques.io.exceptions.NotSupportedExtensionException;
87

    
88
import org.cresques.px.Extent;
89
import org.cresques.px.PxRaster;
90

    
91
import org.gvsig.remoteClient.arcims.ArcImsClientP;
92
import org.gvsig.remoteClient.arcims.ArcImsProtImageHandler;
93
import org.gvsig.remoteClient.arcims.ArcImsProtocolHandler;
94
import org.gvsig.remoteClient.arcims.ArcImsStatus;
95
import org.gvsig.remoteClient.arcims.exceptions.ArcImsException;
96
import org.gvsig.remoteClient.arcims.utils.MyCancellable;
97
import org.gvsig.remoteClient.arcims.utils.ServiceInfoTags;
98
import org.gvsig.remoteClient.arcims.utils.ServiceInformation;
99
import org.gvsig.remoteClient.arcims.utils.ServiceInformationLayer;
100
import org.gvsig.remoteClient.utils.Utilities;
101
import org.gvsig.remoteClient.wms.ICancellable;
102

    
103
import java.awt.Color;
104
import java.awt.Dimension;
105
import java.awt.Graphics2D;
106
import java.awt.Point;
107
import java.awt.Rectangle;
108
import java.awt.event.ActionEvent;
109
import java.awt.event.ActionListener;
110
import java.awt.geom.AffineTransform;
111
import java.awt.geom.NoninvertibleTransformException;
112
import java.awt.geom.Point2D;
113
import java.awt.geom.Rectangle2D;
114
import java.awt.image.BufferedImage;
115
import java.awt.image.DataBuffer;
116

    
117
import java.io.File;
118
import java.io.IOException;
119

    
120
import java.lang.reflect.Constructor;
121
import java.lang.reflect.InvocationTargetException;
122

    
123
import java.net.MalformedURLException;
124
import java.net.URL;
125

    
126
import java.util.ArrayList;
127
import java.util.HashMap;
128
import java.util.Map;
129
import java.util.Vector;
130

    
131
import javax.print.attribute.PrintRequestAttributeSet;
132

    
133
import javax.swing.ImageIcon;
134

    
135

    
136
/**
137
 * This class implements an ArcIMS raster layer.
138
 *
139
 * @author jldominguez
140
 */
141
public class FRasterLyrArcIMS extends FLyrDefault implements RasterOperations,
142
    InfoByPoint {
143
    private static Logger logger = Logger.getLogger(FRasterLyrArcIMS.class.getName());
144
    public static final String SCALE_CHANGED_COMMAND = "SCALE_HAS_CHANGED";
145
    private MyCancellable myCanc;
146
    private URL host;
147
    private String service;
148
    private String serviceType;
149
    private Rectangle2D fullExtent;
150
    private boolean firstLoad = false;
151
    private ArcImsStatus arcimsStatus = new ArcImsStatus();
152
    private String SRS;
153
    private String layerQuery;
154
    private ArcImsDriver driver;
155
    private VisualStatusArcIms visualStatus = new VisualStatusArcIms();
156
    private int transparency = -1;
157
    private boolean arcImsTransparency = true;
158
    private String format;
159
    private StatusRasterInterface status = null;
160
    private GeoRasterFile rasterFile = null;
161
    private PxRaster raster = null;
162
    private int rband = 0;
163
    private int gband = 1;
164
    private int bband = 2;
165
    private RasterFilterStackManager stackManager = null;
166
    private RasterFilterStack filterStack = null;
167
    private int posX = 0;
168
    private int posY = 0;
169
    private double posXWC = 0;
170
    private double posYWC = 0;
171
    private int r = 0;
172
    private int g = 0;
173
    private int b = 0;
174
    private ArrayList actionListeners = new ArrayList();
175
    private int maxTileWidth = 1023;
176
    private int maxTileHeight = 1023;
177
    private Grid grid = null;
178
    private boolean nameQueryChange = false;
179
    private ArrayList listeners = new ArrayList();
180
    private boolean tiled = false;
181
    private int[] tileSize = new int[2];
182
    private ActionEvent scaleChangedEvent = new ActionEvent(this,
183
            ActionEvent.ACTION_PERFORMED, SCALE_CHANGED_COMMAND);
184

    
185
    public FRasterLyrArcIMS() {
186
        myCanc = new MyCancellable(new DefaultCancellableMonitorable());
187
    }
188

    
189
    /**
190
     * The extCatalogYNomenclator needs this creator.
191
     *
192
     * @param p a Map object with the following keys:
193
     *
194
     * (key, object type returned)
195
     * ---------------------------
196
     * "host", String (with or without the servlet path, example:
197
     *                                         "http://www.geographynetwork.com")
198
     * "service_name", String (remote service name)
199
     * "srs", String (coordinate system)
200
     * "layer_name", String (local layer's name)
201
     *
202
     * @return a FRasterLyrArcIMS layer
203
     */
204
    public FRasterLyrArcIMS(Map m) throws ConnectionException {
205
        myCanc = new MyCancellable(new DefaultCancellableMonitorable());
206

    
207
        String _host = "";
208

    
209
        try {
210
            _host = (String) m.get("host");
211

    
212
            String _service_name = (String) m.get("service_name");
213
            String _srs = (String) m.get("srs");
214
            String _image_format = "JPG";
215
            String _layer_name = (String) m.get("layer_name");
216

    
217
            // in case layer_name is missing or equals the empty string:
218
            if ((_layer_name == null) || (_layer_name.length() == 0)) {
219
                _layer_name = _service_name;
220
            }
221

    
222
            // ----------------------------
223
            URL _true_host = ArcImsProtocolHandler.getUrlWithServlet(new URL(
224
                        _host));
225
            IProjection _true_srs = CRSFactory.getCRS(_srs);
226

    
227
            FMapRasterArcImsDriver _drv = new FMapRasterArcImsDriver(_true_host.toString(),
228
                    _service_name, ServiceInfoTags.vIMAGESERVICE);
229

    
230
            if (!_drv.connect(myCanc)) {
231
                throw new ConnectionException("Unable to connect to host ",
232
                    new Exception(_host));
233
            }
234

    
235
            setDriver(_drv);
236
            setHost(_true_host);
237
            setService(_service_name);
238
            setServiceType(ServiceInfoTags.vIMAGESERVICE);
239
            setServiceInformationInStatus(_drv.getClient()
240
                                              .getServiceInformation());
241

    
242
            ServiceInformation _si = getArcimsStatus().getServiceInfo();
243

    
244
            if ((_si.getFeaturecoordsys() == null) ||
245
                    (_si.getFeaturecoordsys().equals(""))) {
246
                _si.setFeaturecoordsys(_true_srs.getAbrev()
247
                                                .substring(ServiceInfoTags.vINI_SRS.length())
248
                                                .trim());
249
                logger.warn("Server provides no SRS. ");
250
            }
251

    
252
            setFullExtent(((ArcImsProtImageHandler) _drv.getClient().getHandler()).getServiceExtent(
253
                    _true_srs, getArcimsStatus()));
254

    
255
            //  JPG
256
            setFormat(_image_format);
257
            setTransparency(0);
258

    
259
            // =================================== query
260
            int layercount = _si.getLayers().size();
261
            String _layer_query = "";
262

    
263
            for (int i = 0; i < layercount; i++) {
264
                if (isTrueString(
265
                            ((ServiceInformationLayer) _si.getLayer(i)).getVisible())) {
266
                    _layer_query = _layer_query + "," +
267
                        ((ServiceInformationLayer) _si.getLayer(i)).getId();
268
                }
269
            }
270

    
271
            if (_layer_query.length() == 0) {
272
                throw new Exception("No layers are visible by default ");
273
            }
274
            else {
275
                _layer_query = _layer_query.substring(1);
276
            }
277

    
278
            // ===================================
279
            setLayerQuery(_layer_query);
280
            setProjection(_true_srs);
281
            setName(_layer_name);
282
        }
283
        catch (Exception e) {
284
            new ConnectionException("Unable to connect to host " + _host, e);
285
        }
286
    }
287

    
288
    /**
289
     * Gets the driver object onto which <tt>getMap()</tt> and
290
     * <tt>getFeatureInfo()</tt> requests are passed. If the driver was not
291
     * created, this methdo creates it with the server's URL and the service
292
     * name.
293
     *
294
     * @return the driver that actually performs the requests.
295
     */
296
    public ArcImsDriver getDriver() {
297
        if (driver == null) {
298
            driver = new FMapRasterArcImsDriver(host.toString(), service,
299
                    this.serviceType);
300
        }
301

    
302
        return driver;
303
    }
304

    
305
    public void setDriver(FMapRasterArcImsDriver d) {
306
        driver = d;
307
    }
308

    
309
    /**
310
     * Gets the transformation matrix to be written in the georeference file.
311
     * The second and the third coefficients will always be zero (it doesn't
312
     * implement image rotation)
313
     *
314
     * @param bBox
315
     *            Image's size and position (user's coordinates)
316
     * @param sz
317
     *            Images' size in pixels
318
     * @return the worldfile, as a String
319
     * @throws IOException
320
     */
321
    public String getDataWorldFile(Rectangle2D bBox, Dimension sz)
322
        throws IOException {
323
        StringBuffer data = new StringBuffer();
324
        data.append(((bBox.getMaxX() - bBox.getMinX()) / (sz.getWidth() - 1)) +
325
            "\n");
326
        data.append("0.0\n");
327
        data.append("0.0\n");
328
        data.append("-" +
329
            ((bBox.getMaxY() - bBox.getMinY()) / (sz.getHeight() - 1)) + "\n");
330

    
331
        // guardalo por si acaso :)
332
        // data.append((bBox.getMaxY() - bBox.getMinY()) / (sz.getHeight() - 1) + "\n");
333
        data.append("" + bBox.getMinX() + "\n");
334

    
335
        // data.append("" + bBox.getMinY() + "\n");
336
        data.append("" + bBox.getMaxY() + "\n");
337

    
338
        return data.toString();
339
    }
340

    
341
    /**
342
     * Gets the raster status
343
     *
344
     * @return the raster status
345
     */
346
    public StatusRasterInterface getStatus() {
347
        return this.status;
348
    }
349

    
350
    public void setStatus(StatusRasterInterface s) {
351
        this.status = s;
352
    }
353

    
354
    /**
355
     * This method must be invoqued with <b>true</b> if the layer must show its
356
     * transparency. The level of transparency is set by another method.
357
     *
358
     * @param t
359
     *            Whether or not the transparency must be shown.
360
     */
361
    public void setArcImsTransparency(boolean t) {
362
        this.arcImsTransparency = t;
363
    }
364

    
365
    /**
366
     * Drawing method invoqued from outside the plugin.
367
     *
368
     * @param g
369
     *            graphic object on which drawing is made.
370
     * @param vp
371
     *            the view
372
     * @param cancel
373
     *            allows drawing abortion
374
     * @throws DriverException
375
     */
376
    private void drawTile(Graphics2D g, ViewPort vp, Cancellable cancel)
377
        throws DriverException {
378
        // This is the extent that will be requested
379
        Rectangle2D bBox = vp.getAdjustedExtent(); // getFullExtent();
380
        Dimension sz = vp.getImageSize();
381

    
382
        try {
383
            arcimsStatus.setExtent(bBox);
384
            arcimsStatus.setFormat(getFormat());
385
            arcimsStatus.setHeight(vp.getImageHeight());
386
            arcimsStatus.setWidth(vp.getImageWidth());
387
            arcimsStatus.setLayerIds(Utilities.createVector(layerQuery, ","));
388
            arcimsStatus.setServer(host.toString());
389
            arcimsStatus.setService(service);
390
            arcimsStatus.setSrs(this.getProjection().getAbrev());
391
            arcimsStatus.setTransparency(this.arcImsTransparency);
392

    
393
            // We need to cast because driver returns an Object
394
            File f = (File) getDriver().getMap(arcimsStatus);
395

    
396
            int lastp = f.getPath().lastIndexOf(".");
397
            String noext = f.getPath().substring(0, lastp);
398

    
399
            String nameWorldFile = noext + getExtensionWordFile(getFormat());
400

    
401
            com.iver.andami.Utilities.createTemp(nameWorldFile,
402
                this.getDataWorldFile(bBox, sz));
403

    
404
            // ------------------------------ START
405
            ViewPortData vpData = new ViewPortData(vp.getProjection(),
406
                    new Extent(bBox), sz);
407
            vpData.setMat(vp.getAffineTransform());
408

    
409
            // ------------------------------ END
410
            rasterProcess(g, vpData, f);
411
        }
412
        catch (IOException e) {
413
            DriverException de = new DriverException("connect_error");
414
            logger.error("While connecting ", e);
415
            throw de;
416
        }
417
        catch (ArcImsException e) {
418
            logger.error("While drawing ", e);
419
            this.setVisible(false);
420

    
421
            DriverException de = new DriverException(e.getMessage());
422
            throw de;
423
        }
424
    }
425

    
426
    /**
427
     * Drawing method invoqued from gvSIG to draw this layer. Uses a <tt>Tiling</tt>
428
     * object to prevent downloading images too large to be retrieved
429
     * (pixel count limit)
430
     *
431
     * @param image
432
     *            used to speed up drawing process
433
     * @param g
434
     *            graphic object on which drawing is make
435
     * @param viewPort
436
     *            the view's properties
437
     * @param cancel
438
     *            allows drawing abortion
439
     * @param scale the current scale
440
     *
441
     * @throws DriverException
442
     */
443
    public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
444
        Cancellable cancel, double scale) throws DriverException {
445
        if (!isVisible()) {
446
            return;
447
        }
448

    
449
        if (!isWithinScale(scale)) {
450
            return;
451
        }
452

    
453
        visualStatus.width = viewPort.getImageWidth();
454
        visualStatus.height = viewPort.getImageHeight();
455
        visualStatus.minX = viewPort.getAdjustedExtent().getMinX();
456
        visualStatus.minY = viewPort.getAdjustedExtent().getMinY();
457
        visualStatus.maxX = viewPort.getAdjustedExtent().getMaxX();
458
        visualStatus.maxY = viewPort.getAdjustedExtent().getMaxY();
459

    
460
        setTileDimensions(viewPort);
461

    
462
        Point2D p = viewPort.getOffset();
463
        Rectangle r = new Rectangle((int) p.getX(), (int) p.getY(),
464
                viewPort.getImageWidth() - 1, viewPort.getImageHeight() - 1);
465
        Tiling tiles = new Tiling(maxTileWidth, maxTileHeight, r);
466
        tiles.setAffineTransform((AffineTransform) viewPort.getAffineTransform()
467
                                                           .clone());
468

    
469
        tiled = false;
470

    
471
        if (tiles.getNumTiles() > 1) {
472
            tiled = true;
473
            tileSize[0] = tiles.getMaxTileWidth();
474
            tileSize[1] = tiles.getMaxTileHeight();
475
        }
476

    
477
        for (int tileNr = 0; tileNr < tiles.getNumTiles(); tileNr++) {
478
            // drawing part
479
            try {
480
                ViewPort vp = tiles.getTileViewPort(viewPort, tileNr);
481
                drawTile(g, vp, cancel);
482
            }
483
            catch (NoninvertibleTransformException e) {
484
                logger.error("Non invertible matrix ", e);
485
            }
486
        }
487

    
488
        // the status needs to be reset because the drawTile
489
        // method had changed its extent and dimension:
490
        arcimsStatus.setExtent(viewPort.getAdjustedExtent());
491
        arcimsStatus.setHeight(viewPort.getImageHeight());
492
        arcimsStatus.setWidth(viewPort.getImageWidth());
493

    
494
        callActionListeners(scaleChangedEvent);
495

    
496
        if (nameQueryChange) {
497
            callNameOrQueryListeners();
498
            nameQueryChange = false;
499
        }
500
    }
501

    
502
    private void setTileDimensions(ViewPort vp) {
503
        maxTileHeight = vp.getImageHeight();
504

    
505
        try {
506
            maxTileWidth = Integer.parseInt(arcimsStatus.getServiceInfo()
507
                                                        .getImagelimit_pixelcount()) / maxTileHeight;
508
            maxTileWidth--;
509
        }
510
        catch (NumberFormatException nfe) {
511
            logger.error("getImagelimit_pixelcount() returned a non parseable string. maxTileWidth was set to 100.",
512
                nfe);
513
            maxTileWidth = 100;
514
        }
515

    
516
        logger.info("Tile size = [ " + maxTileWidth + " , " + maxTileHeight +
517
            " ]");
518
    }
519

    
520
    /**
521
     * Gets the georeference file extension depending on the image's format.
522
     *
523
     * @param f
524
     *            raster file format
525
     * @return georeference file extension (".wld", ".tfw", etc)
526
     */
527
    private String getExtensionWordFile(String f) {
528
        String extWorldFile = ".wld";
529

    
530
        if (f.equals("tif") || f.equals("tiff")) {
531
            extWorldFile = ".tfw";
532
        }
533

    
534
        if (f.equals("jpeg")) {
535
            extWorldFile = ".jpgw";
536
        }
537

    
538
        return extWorldFile;
539
    }
540

    
541
    /**
542
     * Draws an image using PxRaster
543
     *
544
     * @param g
545
     *            graphics object on which drawing will be made
546
     * @param vpData
547
     *            viewport's properties
548
     * @param file
549
     *            the image file
550
     */
551
    private void rasterProcess(Graphics2D g, ViewPortData vpData, File file) {
552
        // PxRaster is created
553
        try {
554
            rasterFile = new GdalFile(vpData.getProjection(),
555
                    file.getAbsolutePath());
556
        }
557
        catch (NotSupportedExtensionException ex) {
558
            logger.error("While creating GdalFile: " + ex.getMessage(), ex);
559
        }
560

    
561
        raster = new PxRaster(rasterFile, null, rasterFile.getExtent());
562
        grid = new Grid(rasterFile);
563
        grid.addRenderizer(raster);
564

    
565
        if ((status != null) && firstLoad) {
566
            status.applyStatus(this);
567
            firstLoad = false;
568
        }
569

    
570
        if (this.filterStack != null) {
571
            raster.filterStack = this.filterStack;
572
        }
573

    
574
        raster.setTransparency(false);
575

    
576
        if ((this.transparency == -1) && !firstLoad) {
577
            ;
578
        }
579
        else
580
        {
581
            raster.setTransparency(this.transparency);
582
        }
583

    
584
        raster.setBand(GeoRasterFile.RED_BAND, rband);
585
        raster.setBand(GeoRasterFile.GREEN_BAND, gband);
586
        raster.setBand(GeoRasterFile.BLUE_BAND, bband);
587

    
588
        if (this.stackManager != null) {
589
            raster.setStackManager(this.stackManager);
590
        }
591

    
592
        if (visualStatus != null) {
593
            visualStatus.bandCount = raster.getBandCount();
594
            visualStatus.dataType = raster.getDataType();
595
        }
596

    
597
        raster.draw(g, vpData);
598

    
599
        // We get the Stack Manager with the first pxRaster of an image
600
        // so we can modify it afterwards from the properties dialog
601
        if (this.stackManager == null) {
602
            this.stackManager = raster.getStackManager();
603
        }
604

    
605
        if (this.filterStack == null) {
606
            this.filterStack = raster.filterStack;
607
        }
608
    }
609

    
610
    public void repaintRaster(Graphics2D g, ViewPortData vpData, File file) {
611
        rasterProcess(g, vpData, file);
612
    }
613

    
614
    public String getFormat() {
615
        return format;
616
    }
617

    
618
    public void setFormat(String format) {
619
        this.format = format;
620
    }
621

    
622
    /**
623
     * Gets a series of attributes that describe the layer's raster: Filename,
624
     * Filesize, Height, Width and Bands.
625
     *
626
     * @return A list of 2-element arrays { "Attribute name" , Value }
627
     */
628
    public ArrayList getAttributes() {
629
        if (rasterFile != null) {
630
            ArrayList attr = new ArrayList();
631
            Object[][] a = {
632
                    {
633
                        "Filename",
634
                        rasterFile.getName()
635
                                  .substring(rasterFile.getName()
636
                                                       .lastIndexOf("/") + 1,
637
                            rasterFile.getName().length())
638
                    },
639
                    { "Filesize", new Long(rasterFile.getFileSize()) },
640
                    {
641
                        "Width",
642
                        new Integer((new Double(this.getWidth())).intValue())
643
                    },
644
                    {
645
                        "Height",
646
                        new Integer((new Double(this.getHeight())).intValue())
647
                    },
648
                    { "Bands", new Integer(rasterFile.getBandCount()) }
649
                };
650

    
651
            for (int i = 0; i < a.length; i++) {
652
                attr.add(a[i]);
653
            }
654

    
655
            return attr;
656
        }
657

    
658
        return null;
659
    }
660

    
661
    /**
662
     *
663
    /**
664
     * Invoqued from gvSIG to draw this layer on a printable map. Uses a
665
     * <tt>Tiling</tt> object to prevent downloading images too large to be
666
     * retrieved (pixel count limit).
667
     *
668
     * @param g
669
     *            graphic object on which drawing is make
670
     * @param viewPort
671
     *            the view's properties
672
     * @param cancel
673
     *            allows drawing abortion
674
     * @param scale the current scale
675
     *
676
     * @throws DriverException
677
     */
678
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
679
        double scale, PrintRequestAttributeSet properties)
680
        throws DriverException {
681
        draw(null, g, viewPort, cancel, scale);
682
    }
683

    
684
    public HashMap getProperties() {
685
        HashMap info = new HashMap();
686
        String[] layerNames = getLayerQuery().split(",");
687
        Vector layers = new Vector(layerNames.length);
688

    
689
        try {
690
            if (((FMapRasterArcImsDriver) getDriver()).connect(myCanc)) {
691
                info.put("layerName", this.getName());
692
                info.put("serverUrl", this.getHost());
693
                info.put("serviceName", this.getService());
694
                info.put("serviceType", this.getServiceType());
695
                info.put("format", this.format);
696

    
697
                for (int i = 0; i < layerNames.length; i++)
698
                    layers.add(layerNames[i]);
699

    
700
                info.put("layerIds", layers);
701

    
702
                return info;
703
            }
704
        }
705
        catch (Exception e) {
706
            logger.error("Error while reading FRasterLyrArcIMS properties. ", e);
707
        }
708

    
709
        return null;
710
    }
711

    
712
    public RasterFilterStack getFilterStack() {
713
        if (raster != null) {
714
            return raster.filterStack;
715
        }
716

    
717
        return null;
718
    }
719

    
720
    public double getHeight() {
721
        return visualStatus.height;
722
    }
723

    
724
    public double getMaxX() {
725
        return visualStatus.maxX;
726
    }
727

    
728
    public double getMaxY() {
729
        return visualStatus.maxY;
730
    }
731

    
732
    public double getMinX() {
733
        return visualStatus.minX;
734
    }
735

    
736
    public double getMinY() {
737
        return visualStatus.minY;
738
    }
739

    
740
    public int[] getPixel(double wcx, double wcy) {
741
        if (getPxRaster() != null) {
742
            return getPxRaster().getPixel(wcx, wcy);
743
        }
744

    
745
        return null;
746
    }
747

    
748
    public RasterAdapter getSource() {
749
        return null;
750
    }
751

    
752
    public double getWidth() {
753
        return visualStatus.width;
754
    }
755

    
756
    public void setBand(int flag, int nBand) {
757
        switch (flag) {
758
        case GeoRasterFile.RED_BAND:
759
            setBandR(nBand);
760

    
761
            break;
762

    
763
        case GeoRasterFile.GREEN_BAND:
764
            setBandG(nBand);
765

    
766
            break;
767

    
768
        case GeoRasterFile.BLUE_BAND:
769
            setBandB(nBand);
770

    
771
            break;
772
        }
773
    }
774

    
775
    public void setFilterStack(RasterFilterStack stack) {
776
        this.filterStack = stack;
777
    }
778

    
779
    public void setPos(int x, int y) {
780
        this.posX = x;
781
        this.posY = y;
782
    }
783

    
784
    public void setPosWC(double x, double y) {
785
        this.posXWC = x;
786
        this.posYWC = y;
787
    }
788

    
789
    public void setRGB(int r, int g, int b) {
790
        this.r = r;
791
        this.g = g;
792
        this.b = b;
793
    }
794

    
795
    public Color getRGB() {
796
        return new Color(r, g, b);
797
    }
798

    
799
    public void setSource(RasterAdapter ra) {
800
    }
801

    
802
    /**
803
     * @return Returns the raster.
804
     */
805
    public PxRaster getPxRaster() {
806
        return raster;
807
    }
808

    
809
    /**
810
     * @return Returns the rasterFile.
811
     */
812
    public GeoRasterFile getGeoRasterFile() {
813
        return rasterFile;
814
    }
815

    
816
    /**
817
     * Sets the R-band.
818
     *
819
     * @param r
820
     */
821
    public void setBandR(int r) {
822
        this.rband = r;
823
    }
824

    
825
    /**
826
     * Sets the G-band.
827
     *
828
     * @param g
829
     */
830
    public void setBandG(int g) {
831
        this.gband = g;
832
    }
833

    
834
    /**
835
     * Sets the B-band.
836
     *
837
     * @param b
838
     */
839
    public void setBandB(int b) {
840
        this.bband = b;
841
    }
842

    
843
    /**
844
     *
845
     * @return XMLEntity.
846
     * @throws XMLException
847
     */
848
    public XMLEntity getXMLEntity() throws XMLException {
849
        XMLEntity xml = super.getXMLEntity();
850

    
851
        xml.putProperty("fullExtent", StringUtilities.rect2String(fullExtent));
852
        xml.putProperty("host", host.toExternalForm());
853
        xml.putProperty("serviceName", service);
854
        xml.putProperty("serviceType", serviceType);
855
        xml.putProperty("layerQuery", layerQuery);
856
        xml.putProperty("format", format);
857

    
858
        if (status != null) {
859
            status.getXMLEntity(xml, true, this);
860
        }
861
        else {
862
            status = new StatusLayerRaster();
863
            status.getXMLEntity(xml, true, this);
864
        }
865

    
866
        xml.putProperty("arcims_transparency", arcImsTransparency);
867

    
868
        return xml;
869
    }
870

    
871
    /**
872
     *
873
     * @param xml
874
     *            XMLEntity
875
     *
876
     * @throws XMLException
877
     * @throws DriverException
878
     * @throws DriverIOException
879
     */
880
    public void setXMLEntity(XMLEntity xml) throws XMLException {
881
        super.setXMLEntity(xml);
882
        fullExtent = StringUtilities.string2Rect(xml.getStringProperty(
883
                    "fullExtent"));
884

    
885
        try {
886
            host = new URL(xml.getStringProperty("host"));
887
        }
888
        catch (MalformedURLException e) {
889
            logger.error("Whle reading XML file ", e);
890
            throw new XMLException(e);
891
        }
892

    
893
        this.layerQuery = xml.getStringProperty("layerQuery");
894
        this.service = xml.getStringProperty("serviceName");
895
        this.serviceType = xml.getStringProperty("serviceType");
896
        this.format = xml.getStringProperty("format");
897

    
898
        FMapRasterArcImsDriver drv = new FMapRasterArcImsDriver(host.toString(),
899
                service, serviceType);
900

    
901
        if (!drv.connect(myCanc)) {
902
            logger.error("Error while loading service information. ");
903
        }
904

    
905
        ArcImsClientP cli = (ArcImsClientP) drv.getClient();
906
        ServiceInformation si = cli.getServiceInformation();
907
        this.arcimsStatus.setServiceInformation(si);
908

    
909
        if (xml.contains("arcims_transparency")) {
910
            this.arcImsTransparency = xml.getBooleanProperty(
911
                    "arcims_transparency");
912
        }
913

    
914
        String claseStr = StatusLayerRaster.defaultClass;
915

    
916
        if (xml.contains("raster.class")) {
917
            claseStr = xml.getStringProperty("raster.class");
918
        }
919

    
920
        if (status != null) {
921
            status.setXMLEntity(xml, this);
922
        }
923
        else {
924
            // When we load a project
925
            if ((claseStr != null) && !claseStr.equals("")) {
926
                try {
927
                    Class clase = Class.forName(claseStr);
928
                    Constructor constr = clase.getConstructor(null);
929
                    status = (StatusRasterInterface) constr.newInstance(null);
930

    
931
                    if (status != null) {
932
                        status.setXMLEntity(xml, this);
933
                    }
934
                }
935
                catch (ClassNotFoundException exc) {
936
                    logger.error("Whle reading XML file ", exc);
937
                }
938
                catch (InstantiationException exc) {
939
                    logger.error("Whle reading XML file ", exc);
940
                }
941
                catch (IllegalAccessException exc) {
942
                    logger.error("Whle reading XML file ", exc);
943
                }
944
                catch (NoSuchMethodException exc) {
945
                    logger.error("Whle reading XML file ", exc);
946
                }
947
                catch (InvocationTargetException exc) {
948
                    logger.error("Whle reading XML file ", exc);
949
                }
950
            }
951
        }
952

    
953
        firstLoad = true;
954
    }
955

    
956
    public Vector getLayerScaleInfoVector() {
957
        Vector v = new Vector();
958
        String id;
959

    
960
        for (int i = 0; i < arcimsStatus.getLayerIds().size(); i++) {
961
            id = (String) arcimsStatus.getLayerIds().get(i);
962
            v.add(getScaleInfo(id));
963
        }
964

    
965
        return v;
966
    }
967

    
968
    public LayerScaleData getScaleInfo(String theId) {
969
        ServiceInformation si;
970
        ServiceInformationLayer sil;
971
        int noflayers;
972
        long true_max_scale;
973
        long true_min_scale;
974

    
975
        LayerScaleData theLayerScaleData = null;
976

    
977
        si = arcimsStatus.getServiceInfo();
978

    
979
        int _dpi = si.getScreen_dpi();
980
        String mapUnits = si.getMapunits();
981

    
982
        noflayers = si.getLayers().size();
983

    
984
        for (int i = 0; i < noflayers; i++) {
985
            sil = (ServiceInformationLayer) si.getLayer(i);
986

    
987
            if ((sil.getId().compareTo(theId)) == 0) {
988
                true_max_scale = LayerScaleData.getTrueScaleFromRelativeScaleAndMapUnits(sil.getMaxscale(),
989
                        mapUnits, _dpi);
990
                true_min_scale = LayerScaleData.getTrueScaleFromRelativeScaleAndMapUnits(sil.getMinscale(),
991
                        mapUnits, _dpi);
992
                theLayerScaleData = new LayerScaleData(sil.getName(),
993
                        sil.getId(), true_min_scale, true_max_scale,
994
                        sil.getType());
995
            }
996
        }
997

    
998
        return theLayerScaleData;
999
    }
1000

    
1001
    public void addActionlistener(ActionListener al) {
1002
        if (actionListeners.contains(al)) {
1003
            return;
1004
        }
1005

    
1006
        actionListeners.add(al);
1007
    }
1008

    
1009
    public void removeActionlistener(ActionListener al) {
1010
        actionListeners.remove(al);
1011
    }
1012

    
1013
    private void callActionListeners(ActionEvent ae) {
1014
        ActionListener al;
1015

    
1016
        for (int i = 0; i < actionListeners.size(); i++) {
1017
            al = (ActionListener) actionListeners.get(i);
1018
            al.actionPerformed(ae);
1019
        }
1020
    }
1021

    
1022
    public long getScale() {
1023
        return getMapContext().getScaleView();
1024
    }
1025

    
1026
    public int getMaxTileHeight() {
1027
        return maxTileHeight;
1028
    }
1029

    
1030
    public void setMaxTileHeight(int maxTileHeight) {
1031
        this.maxTileHeight = maxTileHeight;
1032
    }
1033

    
1034
    public int getMaxTileWidth() {
1035
        return maxTileWidth;
1036
    }
1037

    
1038
    public void setMaxTileWidth(int maxTileWidth) {
1039
        this.maxTileWidth = maxTileWidth;
1040
    }
1041

    
1042
    public void setServiceInformationInStatus(ServiceInformation si) {
1043
        this.arcimsStatus.setServiceInformation(si);
1044
    }
1045

    
1046
    /**
1047
     * This is the <tt>getDriver</tt> method. The <tt>getDriver</tt>
1048
     * method will be implemented by sub-classes.
1049
     *
1050
     * @param d the new driver.
1051
     */
1052
    public void setDriver(ArcImsDriver d) {
1053
        driver = d;
1054
    }
1055

    
1056
    public ArcImsStatus getArcimsStatus() {
1057
        return arcimsStatus;
1058
    }
1059

    
1060
    public void setArcimsStatus(ArcImsStatus arcimsStatus) {
1061
        this.arcimsStatus = arcimsStatus;
1062
    }
1063

    
1064
    public boolean isFirstLoad() {
1065
        return firstLoad;
1066
    }
1067

    
1068
    public void setFirstLoad(boolean firstLoad) {
1069
        this.firstLoad = firstLoad;
1070
    }
1071

    
1072
    public URL getHost() {
1073
        return host;
1074
    }
1075

    
1076
    public void setHost(URL host) {
1077
        this.host = host;
1078
    }
1079

    
1080
    public String getLayerQuery() {
1081
        return layerQuery;
1082
    }
1083

    
1084
    public void setLayerQuery(String lQuery) {
1085
        this.layerQuery = lQuery;
1086

    
1087
        if (layerQuery.substring(0, 1).compareTo(",") == 0) {
1088
            layerQuery = layerQuery.substring(1);
1089
        }
1090
    }
1091

    
1092
    public String getService() {
1093
        return service;
1094
    }
1095

    
1096
    public void setService(String service) {
1097
        this.service = service;
1098
    }
1099

    
1100
    public String getServiceType() {
1101
        return serviceType;
1102
    }
1103

    
1104
    public void setServiceType(String serviceType) {
1105
        this.serviceType = serviceType;
1106
    }
1107

    
1108
    public String getSRS() {
1109
        return SRS;
1110
    }
1111

    
1112
    public void setSRS(String srs) {
1113
        SRS = srs;
1114
    }
1115

    
1116
    public void setFullExtent(Rectangle2D fullExtent) {
1117
        this.fullExtent = fullExtent;
1118
    }
1119

    
1120
    public Rectangle2D getFullExtent() {
1121
        return fullExtent;
1122
    }
1123

    
1124
    public boolean getArcImsTransparency() {
1125
        return arcImsTransparency;
1126
    }
1127

    
1128
    public int getTransparency() {
1129
        return transparency;
1130
    }
1131

    
1132
    public void setTransparency(int transparency) {
1133
        this.transparency = transparency;
1134
    }
1135

    
1136
    public int getPosX() {
1137
        return posX;
1138
    }
1139

    
1140
    public void setPosX(int posX) {
1141
        this.posX = posX;
1142
    }
1143

    
1144
    public double getPosXWC() {
1145
        return posXWC;
1146
    }
1147

    
1148
    public void setPosXWC(double posXWC) {
1149
        this.posXWC = posXWC;
1150
    }
1151

    
1152
    public int getPosY() {
1153
        return posY;
1154
    }
1155

    
1156
    public void setPosY(int posY) {
1157
        this.posY = posY;
1158
    }
1159

    
1160
    public double getPosYWC() {
1161
        return posYWC;
1162
    }
1163

    
1164
    public void setPosYWC(double posYWC) {
1165
        this.posYWC = posYWC;
1166
    }
1167

    
1168
    public void setFormatInStatus(String imgFormat) {
1169
        arcimsStatus.setFormat(imgFormat);
1170
    }
1171

    
1172
    /**
1173
     * This method invoques the <tt>FMapRasterArcImsDriver</tt>'s
1174
     * <tt>getFeatureInfo</tt> method with the given coordinates as a
1175
     * parameter
1176
     *
1177
     * @param p
1178
     *            the corrdinates of the screen pixel to be queried
1179
     *
1180
     * @return the data retrieved for that pixel
1181
     * @throws DriverException
1182
     */
1183
    public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancel)
1184
        throws DriverException {
1185
        StringXMLItem[] resp = new StringXMLItem[1];
1186
        String respStr;
1187

    
1188
        if (((FMapRasterArcImsDriver) driver).isQueryable()) {
1189
            try {
1190
                respStr = ((FMapRasterArcImsDriver) driver).getFeatureInfo(arcimsStatus,
1191
                        (int) p.getX(), (int) p.getY(), Integer.MAX_VALUE);
1192
            }
1193
            catch (ArcImsException e) {
1194
                DriverException de = new DriverException(e.getMessage());
1195
                logger.error("In query by point ", e);
1196
                throw de;
1197
            }
1198
        }
1199
        else {
1200
            DriverException de = new DriverException("layer_not_queriable");
1201
            throw de;
1202
        }
1203

    
1204
        resp[0] = new StringXMLItem(respStr, this);
1205

    
1206
        return resp;
1207
    }
1208

    
1209
    public boolean isTiled() {
1210
        return tiled;
1211
    }
1212

    
1213
    public int[] getTileSize() {
1214
        return tileSize;
1215
    }
1216

    
1217
    private boolean isTrueString(String visible) {
1218
        if (visible.compareToIgnoreCase("true") == 0) {
1219
            return true;
1220
        }
1221

    
1222
        return false;
1223
    }
1224

    
1225
    public void callNameOrQueryListeners() {
1226
        for (int i = 0; i < listeners.size(); i++) {
1227
            ((FRasterLyrArcIMSListener) listeners.get(i)).thingsHaveChanged(getLayerQuery(),
1228
                getName());
1229
        }
1230
    }
1231

    
1232
    public void addNameOrQueryListener(FRasterLyrArcIMSListener l) {
1233
        if (!listeners.contains(l)) {
1234
            listeners.add(l);
1235
        }
1236
    }
1237

    
1238
    public void removeNameOrQueryListener(FRasterLyrArcIMSListener l) {
1239
        listeners.remove(l);
1240
    }
1241

    
1242
    public void setNameQueryChange(boolean c) {
1243
        nameQueryChange = c;
1244
    }
1245

    
1246
    public ImageIcon getTocImageIcon() {
1247
        ImageIcon resp = null;
1248

    
1249
        try {
1250
            resp = createImageIcon("images/esrilogo.png");
1251
        }
1252
        catch (Exception ex) {
1253
        }
1254

    
1255
        if (resp == null) {
1256
            return super.getTocImageIcon();
1257
        }
1258
        else {
1259
            return resp;
1260
        }
1261
    }
1262

    
1263
    protected ImageIcon createImageIcon(String path) {
1264
        java.net.URL imgURL = createExtensionUrl(path);
1265

    
1266
        if (imgURL != null) {
1267
            return new ImageIcon(imgURL);
1268
        }
1269
        else {
1270
            logger.error("File not found: " + path);
1271

    
1272
            return null;
1273
        }
1274
    }
1275

    
1276
    protected java.net.URL createExtensionUrl(String path) {
1277
        return PluginServices.getPluginServices(
1278
            "es.prodevelop.cit.gvsig.arcims").getClassLoader().getResource(path);
1279

    
1280
        // return getClass().getClassLoader().getResource(path);
1281
    }
1282

    
1283
    public int getDataType() {
1284
        return rasterFile.getDataType();
1285
    }
1286

    
1287
    public Grid getGrid() {
1288
        return grid;
1289
    }
1290

    
1291
    private class VisualStatusArcIms {
1292
        /**
1293
         * Ancho y alto de la imagen o del conjunto de tiles si los tiene. Coincide con
1294
         * el ancho y alto del viewPort
1295
         */
1296
        private int width = 0;
1297

    
1298
        /**
1299
         * Ancho y alto de la imagen o del conjunto de tiles si los tiene. Coincide con
1300
         * el ancho y alto del viewPort
1301
         */
1302
        private int height = 0;
1303
        private double minX = 0D;
1304
        private double minY = 0D;
1305
        private double maxX = 0D;
1306
        private double maxY = 0D;
1307
        private int bandCount = 0;
1308
        private int dataType = DataBuffer.TYPE_UNDEFINED;
1309
    }
1310
}