Statistics
| Revision:

root / trunk / extensions / extArcims / src / es / prodevelop / cit / gvsig / arcims / fmap / layers / FFeatureLyrArcIMS.java @ 29733

History | View | Annotate | Download (38 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 java.awt.Color;
46
import java.awt.Graphics2D;
47
import java.awt.Point;
48
import java.awt.geom.AffineTransform;
49
import java.awt.geom.NoninvertibleTransformException;
50
import java.awt.geom.Point2D;
51
import java.awt.geom.Rectangle2D;
52
import java.awt.image.BufferedImage;
53
import java.net.MalformedURLException;
54
import java.net.URL;
55
import java.util.ArrayList;
56
import java.util.HashMap;
57
import java.util.Vector;
58

    
59
import javax.print.attribute.PrintRequestAttributeSet;
60
import javax.swing.ImageIcon;
61

    
62
import org.apache.log4j.Logger;
63
import org.cresques.cts.ICoordTrans;
64
import org.gvsig.remoteClient.arcims.ArcImsClientP;
65
import org.gvsig.remoteClient.arcims.ArcImsFeatureClient;
66
import org.gvsig.remoteClient.arcims.ArcImsVectStatus;
67
import org.gvsig.remoteClient.arcims.exceptions.ArcImsException;
68
import org.gvsig.remoteClient.arcims.utils.FieldInformation;
69
import org.gvsig.remoteClient.arcims.utils.MyCancellable;
70
import org.gvsig.remoteClient.arcims.utils.ServiceInfoTags;
71
import org.gvsig.remoteClient.arcims.utils.ServiceInformation;
72
import org.gvsig.remoteClient.arcims.utils.ServiceInformationLayerFeatures;
73
import org.gvsig.remoteClient.utils.Utilities;
74

    
75
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
76
import com.hardcode.gdbms.engine.data.DataSource;
77
import com.hardcode.gdbms.engine.data.driver.DriverException;
78
import com.hardcode.gdbms.engine.values.Value;
79
import com.iver.andami.PluginServices;
80
import com.iver.cit.gvsig.fmap.MapContext;
81
import com.iver.cit.gvsig.fmap.MapControl;
82
import com.iver.cit.gvsig.fmap.ViewPort;
83
import com.iver.cit.gvsig.fmap.core.CartographicSupport;
84
import com.iver.cit.gvsig.fmap.core.DefaultFeature;
85
import com.iver.cit.gvsig.fmap.core.FShape;
86
import com.iver.cit.gvsig.fmap.core.IFeature;
87
import com.iver.cit.gvsig.fmap.core.IGeometry;
88
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
89
import com.iver.cit.gvsig.fmap.core.symbols.IMultiLayerSymbol;
90
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
91
import com.iver.cit.gvsig.fmap.core.v02.FSymbol;
92
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
93
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
94
import com.iver.cit.gvsig.fmap.layers.FBitSet;
95
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
96
import com.iver.cit.gvsig.fmap.layers.ISpatialDB;
97
import com.iver.cit.gvsig.fmap.layers.LegendChangedEvent;
98
import com.iver.cit.gvsig.fmap.layers.ReadableVectorial;
99
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
100
import com.iver.cit.gvsig.fmap.layers.SpatialCache;
101
import com.iver.cit.gvsig.fmap.layers.XMLException;
102
import com.iver.cit.gvsig.fmap.layers.layerOperations.InfoByPoint;
103
import com.iver.cit.gvsig.fmap.rendering.IClassifiedVectorLegend;
104
import com.iver.cit.gvsig.fmap.rendering.ILegend;
105
import com.iver.cit.gvsig.fmap.rendering.IVectorLegend;
106
import com.iver.cit.gvsig.fmap.rendering.LegendListener;
107
import com.iver.cit.gvsig.fmap.rendering.SingleSymbolLegend;
108
import com.iver.cit.gvsig.fmap.rendering.ZSort;
109
import com.iver.utiles.XMLEntity;
110
import com.iver.utiles.connections.ConnectionException;
111
import com.iver.utiles.swing.threads.Cancellable;
112
import com.iver.utiles.swing.threads.DefaultCancellableMonitorable;
113

    
114
import es.prodevelop.cit.gvsig.arcims.fmap.drivers.ArcImsInMemoryAttsTableDriver;
115
import es.prodevelop.cit.gvsig.arcims.fmap.drivers.ArcImsVectorialAdapter;
116
import es.prodevelop.cit.gvsig.arcims.fmap.drivers.ArcImsVectorialEditableAdapter;
117
import es.prodevelop.cit.gvsig.arcims.fmap.drivers.FMapFeatureArcImsDriver;
118

    
119

    
120
public class FFeatureLyrArcIMS extends FLyrVect implements InfoByPoint,
121
    LegendListener {
122
    // ClassifiableVectorial, Selectable, AlphanumericData, VectorialData,
123
    // Labelable, SingleLayer, RandomVectorialData {
124
    private static Logger logger = Logger.getLogger(FFeatureLyrArcIMS.class.getName());
125
    private URL host;
126
    private String service;
127
    private String serviceType;
128
    private Rectangle2D fullExtent;
129
    private boolean firstLoad = true;
130
    private ArcImsVectStatus arcimsStatus = new ArcImsVectStatus();
131
    private String SRS;
132
    private String srsAbrev;
133
    private String layerQuery;
134
    private VisualStatusArcIms visualStatus = new VisualStatusArcIms();
135
    private int transparency = -1;
136
    private boolean arcImsTransparency = true;
137
    private int shapeType = 0;
138

    
139
    //        private ArrayList initialColors = new ArrayList();
140
    private ArrayList geometries;
141
    private MyCancellable myCanc;
142

    
143
    // from ancestor FLyrVect:
144
    // private VectorialAdapter source;
145
    // private SelectableDataSource sds; --> is created like this --> new SelectableDataSource(source.getRecordSet()) 
146
    public FFeatureLyrArcIMS(ReadableVectorial vectAdapter) {
147
        myCanc = new MyCancellable(new DefaultCancellableMonitorable());
148

    
149
        setSource(vectAdapter);
150
        addLegendListener(this);
151
    }
152

    
153
    public FFeatureLyrArcIMS() {
154
    }
155

    
156
    public void setShapeType(int shpType) {
157
        shapeType = shpType;
158
    }
159

    
160
    public void setAdapter(VectorialEditableAdapter edapter) {
161
        setSource(edapter);
162

    
163
        try {
164
            shapeType = edapter.getShapeType();
165

    
166
            // ((VectorialLegend) getLegend()).setShapeType(shapeType);
167
        }
168
        catch (ReadDriverException e) {
169
            logger.error("Unexpected error while getting shape type ", e);
170
        }
171

    
172
        addLegendListener(this);
173
        myCanc = new MyCancellable(new DefaultCancellableMonitorable());
174

    
175
        //                loadInitialColors();
176
    }
177

    
178
    /**
179
     * Draws using IFeatureIterator. This method will replace the old draw(...) one.
180
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
181
     * @param image
182
     * @param g
183
     * @param viewPort
184
     * @param cancel
185
     * @param scale
186
     * @throws ReadDriverException
187
     */
188
    private void _draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
189
                    Cancellable cancel, double scale) throws ReadDriverException {
190
            
191
        if (!isVisible()) {
192
            return;
193
        }
194

    
195
        if (!isWithinScale(scale)) {
196
            return;
197
        }
198

    
199
        // In case gvSIG calls the getVisualStatus method... (?)
200
        visualStatus.width = viewPort.getImageWidth();
201
        visualStatus.height = viewPort.getImageHeight();
202
        visualStatus.minX = viewPort.getAdjustedExtent().getMinX();
203
        visualStatus.minY = viewPort.getAdjustedExtent().getMinY();
204
        visualStatus.maxX = viewPort.getAdjustedExtent().getMaxX();
205
        visualStatus.maxY = viewPort.getAdjustedExtent().getMaxY();
206

    
207
        IGeometry geom, clongeom;
208
        
209
        ICoordTrans layerTransf = getCoordTrans();
210
        Rectangle2D bBox = viewPort.getAdjustedExtent();
211
        
212
        arcimsStatus.setExtent(bBox);
213
        arcimsStatus.setHeight(viewPort.getImageHeight());
214
        arcimsStatus.setWidth(viewPort.getImageWidth());
215

    
216
        // one-item vector:
217
        arcimsStatus.setLayerIds(Utilities.createVector(layerQuery, ","));
218
        arcimsStatus.setServer(host.toString());
219
        arcimsStatus.setService(service);
220
        arcimsStatus.setSrs(this.getProjection().getAbrev());
221
        arcimsStatus.setTransparency(this.arcImsTransparency);
222

    
223
        FMapFeatureArcImsDriver drv =
224
                (FMapFeatureArcImsDriver) getSource().getDriver();
225
        IVectorLegend lgnd = (IVectorLegend) getLegend();
226

    
227
        // get needed fields
228
                String[] legflds = null;
229
                String[] savedFieldNames = arcimsStatus.getSubfields();
230

    
231
                if (lgnd instanceof IClassifiedVectorLegend) {
232
                        legflds = ((IClassifiedVectorLegend) lgnd).getClassifyingFieldNames();
233
                        if (legflds!=null) {
234
                                String[] appended = appendAtringArrays(savedFieldNames, legflds);
235
                                arcimsStatus.setSubfields(appended);
236
                        }
237
                }
238

    
239
        try {
240
            // ********************************************
241
            // first item in query must contain ID or #ALL#
242
            // ********************************************
243
            geometries = (ArrayList) drv.getMap(arcimsStatus);
244
        } catch (Exception e) {
245
                // restore dubfields
246
                arcimsStatus.setSubfields(savedFieldNames);
247
                ReadDriverException de =
248
                        new ReadDriverException("While getting map (ArrayList of geometries) ", e);
249
            throw de;
250
        }
251
            // restore dubfields
252
        arcimsStatus.setSubfields(savedFieldNames);
253

    
254
            boolean bDrawShapes = true;
255
            
256
            if (lgnd instanceof SingleSymbolLegend) {
257
                    bDrawShapes = lgnd.getDefaultSymbol().isShapeVisible();
258
            }
259
            Point2D offset = viewPort.getOffset();
260
            double dpi = MapContext.getScreenDPI();
261

    
262
            if (bDrawShapes) {
263

    
264
                    try {
265

    
266
                            // Get the iterator over the visible features
267
                            IFeatureIterator it = new AvoidGeometryAndIdFeatureIterator(geometries, savedFieldNames.length);
268
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
269

    
270
                            boolean bSymbolLevelError = false;
271

    
272
                            // if layer has map levels it will use a ZSort
273
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
274

    
275
                            // -- visual FX stuff
276
                            long time = System.currentTimeMillis();
277
                            BufferedImage virtualBim;
278
                            Graphics2D virtualGraphics;
279

    
280
                            // render temporary map each screenRefreshRate milliseconds;
281
                            int screenRefreshDelay = (int) ((1D/MapControl.getDrawFrameRate())*3*1000);
282
                            BufferedImage[] imageLevels = null;
283
                            Graphics2D[] graphics = null;
284
                            if (useZSort) {
285
                                    imageLevels = new BufferedImage[zSort.getLevelCount()];
286
                                    graphics = new Graphics2D[imageLevels.length];
287
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
288
                                            imageLevels[i] = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
289
                                            graphics[i] = imageLevels[i].createGraphics();
290
                                            graphics[i].setTransform(g.getTransform());
291
                                            graphics[i].setRenderingHints(g.getRenderingHints());
292
                                    }
293
                            }
294
                            // -- end visual FX stuff
295

    
296

    
297
                            int featindex = -1;
298
                            // Iteration over each feature
299
                            while ( !cancel.isCanceled() && it.hasNext()) {
300
                                    
301
                                    featindex++;
302
                                    IFeature feat = it.next();
303
                                    geom = feat.getGeometry();
304
                                    
305
                                    clongeom = geom.cloneGeometry();
306
                                    geom = clongeom; 
307
                            
308
                            if ((layerTransf != null) && (isNotSame(layerTransf))) {
309
                                    geom.reProject(layerTransf);
310
                            }
311

    
312
                                    // retrieve the symbol associated to such feature
313
                                    ISymbol sym = lgnd.getSymbolByFeature(feat);
314

    
315
                                    if (sym == null) continue;
316

    
317
                                    //C?digo para poder acceder a los ?ndices para ver si est? seleccionado un Feature
318
                                    ReadableVectorial rv=getSource();
319
                                    int selectionIndex=-1;
320
                                    
321
                                    
322
                                    FMapFeatureArcImsDriver imsdrv = (FMapFeatureArcImsDriver) getSource().getDriver();
323
                                    selectionIndex = imsdrv.getOverallIndex(featindex);
324

    
325
                                    if (selectionIndex!=-1) {
326
                                            if (getSelectionSupport().isSelected(selectionIndex)) {
327
                                                    sym = sym.getSymbolForSelection();
328
                                            }
329
                                    }
330

    
331
                                    // Check if this symbol is sized with CartographicSupport
332
                                    CartographicSupport csSym = null;
333
                                    int symbolType = sym.getSymbolType();
334
                                    boolean bDrawCartographicSupport = false;
335

    
336
                                    if (   symbolType == FShape.POINT
337
                                                    || symbolType == FShape.LINE
338
                                                    || sym instanceof CartographicSupport) {
339

    
340
                                            // patch
341
                                            if (!sym.getClass().equals(FSymbol.class)) {
342
                                                    csSym = (CartographicSupport) sym;
343
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
344
                                            }
345
                                    }
346

    
347
                                    int x = -1;
348
                                    int y = -1;
349
                                    int[] xyCoords = new int[2];
350

    
351
                                    // Check if size is a pixel
352
                                    boolean onePoint = bDrawCartographicSupport ?
353
                                                    isOnePoint(g.getTransform(), viewPort, MapContext.getScreenDPI(), csSym, geom, xyCoords) :
354
                                                            isOnePoint(g.getTransform(), viewPort, geom, xyCoords);
355

    
356
                                                    // Avoid out of bounds exceptions
357
                                                    if (onePoint) {
358
                                                            x = xyCoords[0];
359
                                                            y = xyCoords[1];
360
                                                            if (x<0 || y<0 || x>= viewPort.getImageWidth() || y>=viewPort.getImageHeight()) continue;
361
                                                    }
362

    
363
                                                    if (useZSort) {
364
                                                            // Check if this symbol is a multilayer
365
                                                                int[] symLevels = zSort.getLevels(sym);
366
                                                            if (sym instanceof IMultiLayerSymbol) {
367
                                                                    // if so, treat each of its layers as a single symbol
368
                                                                    // in its corresponding map level
369
                                                                    IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
370
                                                                    for (int i = 0; !cancel.isCanceled() && i < mlSym.getLayerCount(); i++) {
371
                                                                            ISymbol mySym = mlSym.getLayer(i);
372
                                                                        int symbolLevel = 0;
373
                                                                        if (symLevels != null) {
374
                                                                                symbolLevel = symLevels[i];
375
                                                                        } else {
376
                                                                                    /* an error occured when managing symbol levels.
377
                                                                                     * some of the legend changed events regarding the
378
                                                                                     * symbols did not finish satisfactory and the legend
379
                                                                                     * is now inconsistent. For this drawing, it will finish
380
                                                                                     * as it was at the bottom (level 0) but, when done, the
381
                                                                                     * ZSort will be reset to avoid app crashes. This is
382
                                                                                     * a bug that has to be fixed.
383
                                                                                     */
384
                                                                                    bSymbolLevelError = true;
385
                                                                            }
386

    
387
                                                                            if (onePoint) {
388
                                                                                    if (x<0 || y<0 || x>= imageLevels[symbolLevel].getWidth() || y>=imageLevels[symbolLevel].getHeight()) continue;
389
                                                                                    imageLevels[symbolLevel].setRGB(x, y, mySym.getOnePointRgb());
390
                                                                            } else {
391
                                                                                    if (!bDrawCartographicSupport) {
392
                                                                                            geom.drawInts(graphics[symbolLevel], viewPort, mySym, cancel);
393
                                                                                    } else {
394
                                                                                            geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) mySym, cancel);
395
                                                                                    }
396
                                                                            }
397
                                                                    }
398
                                                            } else {
399
                                                                    // else, just draw the symbol in its level
400
                                                                    int symbolLevel = 0;
401
                                                                    if (symLevels != null) {
402

    
403
                                                                            symbolLevel=symLevels[0];
404
                                                                    } else {
405
                                                                            /* If symLevels == null
406
                                                                             * an error occured when managing symbol levels.
407
                                                                             * some of the legend changed events regarding the
408
                                                                             * symbols did not finish satisfactory and the legend
409
                                                                             * is now inconsistent. For this drawing, it will finish
410
                                                                             * as it was at the bottom (level 0). This is
411
                                                                             * a bug that has to be fixed.
412
                                                                             */
413
//                                                                            bSymbolLevelError = true;
414
                                                                    }
415

    
416
                                                                    if (!bDrawCartographicSupport) {
417
                                                                            geom.drawInts(graphics[symbolLevel], viewPort, sym, cancel);
418
                                                                    } else {
419
                                                                            geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) csSym, cancel);
420
                                                                    }
421
                                                            }
422

    
423
                                                            // -- visual FX stuff
424
                                                            // Cuando el offset!=0 se est? dibujando sobre el Layout y por tanto no tiene que ejecutar el siguiente c?digo.
425
                                                            if (offset.getX()==0 && offset.getY()==0)
426
                                                                    if ((System.currentTimeMillis() - time) > screenRefreshDelay) {
427
                                                                            virtualBim = new BufferedImage(image.getWidth(),image.getHeight(),BufferedImage.TYPE_INT_ARGB);
428
                                                                            virtualGraphics = virtualBim.createGraphics();
429
                                                                            virtualGraphics.drawImage(image,0,0, null);
430
                                                                            for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
431
                                                                                    virtualGraphics.drawImage(imageLevels[i],0,0, null);
432
                                                                            }
433
                                                                            g.clearRect(0, 0, image.getWidth(), image.getHeight());
434
                                                                            g.drawImage(virtualBim, 0, 0, null);
435
                                                                            time = System.currentTimeMillis();
436
                                                                    }
437
                                                            // -- end visual FX stuff
438

    
439
                                                    } else {
440
                                                            // no ZSort, so there is only a map level, symbols are
441
                                                            // just drawn.
442
                                                            if (onePoint) {
443
                                                                    if (x<0 || y<0 || x>= image.getWidth() || y>=image.getHeight()) continue;
444
                                                                    image.setRGB(x, y, sym.getOnePointRgb());
445
                                                            } else {
446
                                                                    if (!bDrawCartographicSupport) {
447
                                                                            geom.drawInts(g, viewPort, sym, cancel);
448
                                                                    } else {
449
                                                                            geom.drawInts(g, viewPort, dpi, csSym, cancel);
450
                                                                    }
451
                                                            }
452
                                                    }
453
                            }
454

    
455
                            if (useZSort) {
456
                                    g.drawImage(image, 0, 0, null);
457
                                    g.translate(offset.getX(), offset.getY());
458
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
459
                                            g.drawImage(imageLevels[i],0,0, null);
460
                                            imageLevels[i] = null;
461
                                            graphics[i] = null;
462
                                    }
463
                                    g.translate(-offset.getX(), -offset.getY());
464
                                    imageLevels = null;
465
                                    graphics = null;
466
                            }
467
                            it.closeIterator();
468

    
469
                            if (bSymbolLevelError) {
470
                                    ((IVectorLegend) getLegend()).setZSort(null);
471
                            }
472

    
473
                    } catch (ReadDriverException e) {
474
                            this.setVisible(false);
475
                            this.setActive(false);
476
                            throw e;
477
                    }
478

    
479

    
480
            }
481
    }
482

    
483

    
484

    
485
        private boolean isNotSame(ICoordTrans trans) {
486
            
487
            String from_abb = trans.getPOrig().getAbrev(); 
488
            String to_abb = trans.getPDest().getAbrev();
489
            return (from_abb.compareTo(to_abb) != 0);
490
        }
491

    
492
        private String[] appendAtringArrays(String[] arr1, String[] arr2) {
493
            
494
            int len = arr1.length + arr2.length;
495
            String[] resp = new String[len];
496
            int i = 0;
497
            for (i=0; i<arr1.length; i++) resp[i] = arr1[i];
498
            for (i=0; i<arr2.length; i++) resp[arr1.length+i] = arr2[i];
499
                return resp;
500
        }
501

    
502
        /**
503
     *
504
     */
505
    public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
506
        Cancellable cancel, double scale) throws ReadDriverException {
507
            
508
            _draw(image, g, viewPort, cancel, scale);
509
    }
510

    
511
    private ISymbol getSymbolOrSelected(int i, ISymbol symbol) {
512
        boolean sel = false;
513

    
514
        try {
515
            sel = getRecordset().getSelectionSupport().isSelected(i);
516
        }
517
        catch (ReadDriverException e) {
518
            logger.error("While getting selection", e);
519
        }
520

    
521
        if (sel) {
522
            return SymbologyFactory.createDefaultSymbolByShapeType(shapeType, Color.YELLOW); 
523
        }
524
        else {
525
            return symbol;
526
        }
527
    }
528

    
529
    /**
530
     *
531
     */
532
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
533
        double scale, PrintRequestAttributeSet properties)
534
        throws ReadDriverException {
535
        draw(null, g, viewPort, cancel, scale);
536
    }
537

    
538
    /**
539
     *
540
     */
541
    public String queryByPoint(Point p) throws ReadDriverException {
542
        Point2D screenCoords;
543
        Point2D geoCoords;
544
        double screenTol;
545
        double geoTol;
546

    
547
        screenCoords = new Point2D.Double(p.getX(), p.getY());
548
        geoCoords = new Point2D.Double(p.getX(), p.getY());
549

    
550
        AffineTransform af = getMapContext().getViewPort().getAffineTransform();
551

    
552
        try {
553
            af.inverseTransform(screenCoords, geoCoords);
554
        }
555
        catch (NoninvertibleTransformException e) {
556
            logger.error("Non invertible AffineTransform ", e);
557
        }
558

    
559
        screenTol = 2.0;
560
        geoTol = 1.0;
561
        geoTol = screenTol / af.getScaleX();
562

    
563
        FBitSet fbs = null;
564
                try {
565
                        fbs = queryByPoint(geoCoords, geoTol);
566
                } catch (Exception e) {
567
                        logger.error("While doing query by point: " + e.getMessage());
568
                }
569

    
570
        // this invoques the client to get attrs.
571
        try {
572
            ((ArcImsVectorialAdapter) getSource()).requestFeatureAttributes(fbs);
573
        }
574
        catch (ArcImsException e) {
575
                ReadDriverException de = new ReadDriverException("While querying by point ", e);
576
            throw de;
577
        }
578

    
579
        String resp = getFormattedFieldsFromSetFeatures(fbs);
580
        System.err.println(resp); //TODO BORRAR ESTO
581

    
582
        return resp;
583
    }
584

    
585
    // TODO: move this to another class:
586
    private String getFormattedFieldsFromSetFeatures(FBitSet fbs) {
587
        String r = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
588
        r = r + "<FeatureInfoResponse>";
589
        r = r + "<LAYER ID=\"" + layerQuery + "\" NAME=\"" + getName() + "\">";
590

    
591
        for (int i = fbs.nextSetBit(0); i >= 0; i = fbs.nextSetBit(i + 1)) {
592
            r = r + getFormattedFieldsFromFeature(i);
593
        }
594

    
595
        r = r + "</LAYER>";
596
        r = r + "</FeatureInfoResponse>";
597

    
598
        return r;
599
    }
600

    
601
    // TODO: move this to another class:
602
    private String getFormattedFieldsFromFeature(int j) {
603
        String r = "<FIELDS ";
604
        String fieldName;
605
        String fieldValue;
606
        DataSource ds = null;
607

    
608
        try {
609
            ds = getSource().getRecordset();
610
        }
611
        catch (ReadDriverException e1) {
612
            logger.error("DriverException while getting field values. ", e1);
613
        }
614

    
615
        int count;
616

    
617
        try {
618
            count = ds.getFieldCount();
619

    
620
            for (int i = 0; i < count; i++) {
621
                fieldName = ds.getFieldName(i);
622
                fieldName = ArcImsInMemoryAttsTableDriver.replaceUnwantedCharacters(fieldName);
623

    
624
                fieldValue = restoreSpecialChars(ds.getFieldValue((long) j, i)
625
                                                   .toString());
626
                logger.debug("fieldvalue = " + fieldValue);
627
                r = r + " " + fieldName + "=" + "\"" + fieldValue + "\"";
628
            }
629

    
630
            // <FIELDS NOMBRE="LR-542" OBSERVACIO="" TIPO="CAUT3" _SHAPE_="[Geometry]" _ID_="1975" />
631
            r = r + "/>";
632
        }
633
        catch (ReadDriverException e) {
634
            logger.error("DriverException while getting field values. ", e);
635
        }
636

    
637
        return r;
638
    }
639

    
640
    private String restoreSpecialChars(String str) {
641
        /*
642
         * < 60 3c, > 62 3e, & 38 26, " 34 22, ' 39 27
643
         */
644
        String resp = str.replaceAll("\\x26", "&amp;");
645
        resp = resp.replaceAll("\\x3c", "&lt;");
646
        resp = resp.replaceAll("\\x3e", "&gt;");
647

    
648
        resp = resp.replaceAll("\\x22", "&quot;");
649
        resp = resp.replaceAll("\\x27", "&#39;");
650

    
651
        return resp;
652
    }
653

    
654
    public void setInitialLegend() {
655
        FMapFeatureArcImsDriver drv = (FMapFeatureArcImsDriver) getSource()
656
                                                                    .getDriver();
657

    
658
        //Try to get the legend from the service information
659
        try {
660
                ArcImsClientP cli = drv.getClient();
661
                String lyr_id_0 = (String) arcimsStatus.getLayerIds().get(0);
662
                SelectableDataSource ds = getRecordset();
663
            ILegend initialleg = cli.getLegend(lyr_id_0, ds); 
664

    
665
            if (initialleg != null) {
666
                setLegend((IVectorLegend) initialleg);
667
            }
668

    
669
            return;
670
        }
671
        catch (Exception e) {
672
            logger.error("While setting initial legend ", e);
673
        }
674

    
675
    }
676

    
677
    // Classifiable
678
    public int getShapeType() throws ReadDriverException {
679
        FMapFeatureArcImsDriver drv = (FMapFeatureArcImsDriver) getSource()
680
                                                                    .getDriver();
681

    
682
        return drv.getShapeType();
683
    }
684

    
685
    public void setServiceInformationInStatus(ServiceInformation si) {
686
        this.arcimsStatus.setServiceInformation(si);
687
    }
688

    
689
    public ArcImsVectStatus getArcimsStatus() {
690
        return arcimsStatus;
691
    }
692

    
693
    public void setArcimsStatus(ArcImsVectStatus arcimsStatus) {
694
        this.arcimsStatus = arcimsStatus;
695
    }
696

    
697
    public boolean isFirstLoad() {
698
        return firstLoad;
699
    }
700

    
701
    public void setFirstLoad(boolean firstLoad) {
702
        this.firstLoad = firstLoad;
703
    }
704

    
705
    public URL getHost() {
706
        return host;
707
    }
708

    
709
    public void setHost(URL host) {
710
        this.host = host;
711
    }
712

    
713
    public String getLayerQuery() {
714
        return layerQuery;
715
    }
716

    
717
    public void setLayerQuery(String lQuery) {
718
        this.layerQuery = lQuery;
719

    
720
        if (layerQuery.substring(0, 1).compareTo(",") == 0) {
721
            layerQuery = layerQuery.substring(1);
722
        }
723
    }
724

    
725
    public String getService() {
726
        return service;
727
    }
728

    
729
    public void setService(String service) {
730
        this.service = service;
731
    }
732

    
733
    public String getServiceType() {
734
        return serviceType;
735
    }
736

    
737
    public void setServiceType(String serviceType) {
738
        this.serviceType = serviceType;
739
    }
740

    
741
    public String getSRS() {
742
        return SRS;
743
    }
744

    
745
    public void setSRS(String srs) {
746
        SRS = srs;
747
    }
748

    
749
    public boolean getArcImsTransparency() {
750
        return arcImsTransparency;
751
    }
752

    
753
    public void setArcImsTransparency(boolean arcImsTransparency) {
754
        this.arcImsTransparency = arcImsTransparency;
755
    }
756

    
757
    public int getTransparency() {
758
        return transparency;
759
    }
760

    
761
    public void setTransparency(int transparency) {
762
        this.transparency = transparency;
763
    }
764

    
765
    public HashMap getProperties() {
766
        HashMap info = new HashMap();
767
        String[] layerNames = getLayerQuery().split(",");
768
        Vector layers = new Vector(layerNames.length);
769
        FMapFeatureArcImsDriver drv = (FMapFeatureArcImsDriver) getSource()
770
                                                                    .getDriver();
771

    
772
        try {
773
            if (drv.connect(myCanc)) {
774
                info.put("layerName", this.getName());
775
                info.put("serverUrl", this.getHost());
776
                info.put("serviceName", this.getService());
777
                info.put("serviceType", this.getServiceType());
778

    
779
                for (int i = 0; i < layerNames.length; i++)
780
                    layers.add(layerNames[i]);
781

    
782
                info.put("layerIds", layers);
783

    
784
                return info;
785
            }
786
        }
787
        catch (Exception e) {
788
            logger.error("Error in FRasterLyrArcIMS.getProperties() ", e);
789
        }
790

    
791
        return null;
792
    }
793

    
794
    public void setLayerIdsInStatus(Vector idsv) {
795
        arcimsStatus.setLayerIds(idsv);
796
    }
797

    
798
    public void setProjectionInStatus(String abbrev_srs) {
799
        arcimsStatus.setSrs(abbrev_srs);
800
    }
801

    
802
    public void setHostInStatus(URL url) {
803
        arcimsStatus.setServer(url.toString());
804
    }
805

    
806
    public void setServiceInStatus(String srv) {
807
        arcimsStatus.setService(srv);
808
    }
809

    
810
    public void setSubfieldsInStatus() {
811
        String[] subfields = new String[2];
812
        String id = (String) arcimsStatus.getLayerIds().get(0);
813
        ServiceInformationLayerFeatures silf = (ServiceInformationLayerFeatures) arcimsStatus.getServiceInfo()
814
                                                                                             .getLayerById(id);
815
        FieldInformation fi = (FieldInformation) silf.getFieldInformationByType(FieldInformation.ID)
816
                                                     .get(0);
817
        subfields[1] = fi.getName();
818
        fi = (FieldInformation) silf.getFieldInformationByType(FieldInformation.SHAPE)
819
                                    .get(0);
820
        subfields[0] = fi.getName();
821
        arcimsStatus.setSubfields(subfields);
822
    }
823

    
824
    public void legendChanged(LegendChangedEvent e) {
825
        MapContext fmap = getMapContext();
826

    
827
        if (fmap != null) {
828
            fmap.invalidate();
829
        }
830
    }
831

    
832
    public void setXMLEntity(XMLEntity xml) throws XMLException {
833
        try {
834
            setHost(new URL(xml.getStringProperty("_host")));
835
        }
836
        catch (MalformedURLException e) {
837
            logger.error("Bad url ", e);
838
        }
839

    
840
        setService(xml.getStringProperty("_service"));
841
        setLayerQuery(xml.getStringProperty("layerQuery"));
842
        setSrsAbrev(xml.getStringProperty("srs_abrev"));
843

    
844
        FMapFeatureArcImsDriver drv = new FMapFeatureArcImsDriver(host.toString(),
845
                service, layerQuery);
846

    
847
        if (!(drv.connect(myCanc))) {
848
            throw new XMLException(new DriverException(
849
                    "Unable to connect to server"));
850
        }
851

    
852
        drv.setLayer(this);
853

    
854
        Vector ids = new Vector();
855
        ids.add(getLayerQuery());
856
        setLayerIdsInStatus(ids);
857

    
858
        ArcImsClientP cli = drv.getClient();
859
        ServiceInformation si = cli.getServiceInformation();
860
        arcimsStatus.setServiceInformation(si);
861

    
862
        String srs = getSrsAbrev();
863
        arcimsStatus.setSrs(srs);
864

    
865
        if ((si.getFeaturecoordsys() == null) ||
866
                (si.getFeaturecoordsys().equals(""))) {
867
            si.setFeaturecoordsys(srs.substring(
868
                    ServiceInfoTags.vINI_SRS.length()).trim());
869
            logger.warn("Server provides no SRS. ");
870
        }
871

    
872
        Rectangle2D fext = null;
873

    
874
        try {
875
            fext = ((ArcImsFeatureClient) drv.getClient()).getLayerExtent(arcimsStatus);
876
        }
877
        catch (Exception e) {
878
            logger.error("While loading ArcIMS layer ", e);
879
        }
880

    
881
        arcimsStatus.setExtent(fext);
882
        drv.setFullExtent(fext);
883

    
884
        setSubfieldsInStatus();
885

    
886
        // drv.loadRecordSet();
887
        ArcImsVectorialAdapter oldadapter = new ArcImsVectorialAdapter(drv);
888
        ArcImsVectorialEditableAdapter adapter = new ArcImsVectorialEditableAdapter();
889

    
890
        String recordsetName = xml.getStringProperty("recordset-name");
891

    
892
        try {
893
            adapter.setOriginalDataSource(drv.getRecordSet(recordsetName));
894
            adapter.setOriginalVectorialAdapter(oldadapter);
895
        }
896
        catch (ReadDriverException e) {
897
            logger.error("While setting original data source ", e);
898
        }
899

    
900

    
901
        setAdapter(adapter);
902

    
903
        drv.setAdapter(adapter);
904

    
905
        setInitialLegend();
906

    
907
        try {
908
            setRecordset(((FMapFeatureArcImsDriver) getSource().getDriver()).getRecordSet());
909
        }
910
        catch (Exception e) {
911
            logger.error("While setting data source ", e);
912
        }
913

    
914
        super.setXMLEntity(xml);
915
    }
916

    
917
    public XMLEntity getXMLEntity() throws XMLException {
918
        XMLEntity resp = super.getXMLEntity();
919

    
920
        // PluginServices.getMDIManager().addView(null);
921
        resp.putProperty("srs_abrev", getMapContext().getProjection().getAbrev());
922
        resp.putProperty("_host", host.toString());
923
        resp.putProperty("_service", service);
924
        resp.putProperty("layerQuery", layerQuery);
925

    
926
        return resp;
927
    }
928

    
929
    public String getSrsAbrev() {
930
        return srsAbrev;
931
    }
932

    
933
    public void setSrsAbrev(String srsAbrev) {
934
        this.srsAbrev = srsAbrev;
935
    }
936

    
937
    /**
938
     * The extCatalogYNomenclator needs this creator.
939
     *
940
     * @param p a Map object with the following keys:
941
     *
942
     * (key, object type returned)
943
     * ---------------------------
944
     * "host", String (with or without the servlet path)
945
     * "service_name", String (remote service name)
946
     * "srs", String (coordinate system)
947
     * "layer_id", String (*single* remote layer's ID)
948
     * "layer_name", String (local layer name)
949
     *
950
     * @return a FRasterLyrArcIMS layer
951
     * @throws ConnectionException
952
     */
953

    
954
    /*
955
    
956
    public FFeatureLyrArcIMS(Map m) throws ConnectionException {
957
    
958
            String _host = (String) m.get("host");
959
    
960
            try {
961
    
962
                    String _layer_id = (String) m.get("layer_id");
963
                    String _service_name = (String) m.get("service_name");
964
                    String _layer_name = (String) m.get("layer_name");
965
                    String _srs = (String) m.get("srs");
966
    
967
                    // ----------------------------------
968
    
969
                    URL _true_host = ArcImsProtocolHandler.getUrlWithServlet(new URL(_host));
970
                    IProjection _true_srs = CRSFactory.getCRS(_srs);
971
    
972
    
973
                    FMapFeatureArcImsDriver _drv = new FMapFeatureArcImsDriver(_true_host.toString(),
974
                                    _service_name, _layer_id);
975
                    if (!(_drv.connect(myCanc))) throw new Exception();
976
                    ArcImsVectorialAdapter _oldadapter = new ArcImsVectorialAdapter(_drv);
977
                    VectorialEditableAdapter _adapter = new VectorialEditableAdapter();
978
                    _drv.setLayer(this);
979
    
980
                    ServiceInformation _si = _drv.getClient().getServiceInformation();
981
                    ServiceInformationLayerFeatures _silf = (ServiceInformationLayerFeatures)
982
                    _si.getLayerById(_layer_id);
983
    
984
                    setProjectionInStatus(_true_srs.getAbrev());
985
                    setHostInStatus(_true_host);
986
                    setServiceInStatus(_service_name);
987
    
988
                    String _units = _si.getMapunits();
989
                    int _theDpi = _si.getScreen_dpi();
990
                    long _scale;
991
                    if (_silf.getMaxscale()!=-1) {
992
                            _scale = LayerScaleData.getTrueScaleFromRelativeScaleAndMapUnits(
993
                                            _silf.getMaxscale(), _units, _theDpi);
994
                            setMaxScale((double) _scale);
995
                    }
996
                    if (_silf.getMinscale()!=-1) {
997
                            _scale = LayerScaleData.getTrueScaleFromRelativeScaleAndMapUnits(
998
                                            _silf.getMinscale(), _units, _theDpi);
999
                            setMinScale((double) _scale);
1000
                    }
1001
    
1002
                    setServiceInformationInStatus(_si);
1003
                    Vector _ids = new Vector(); _ids.add(_layer_id);
1004
                    setLayerIdsInStatus((Vector) _ids.clone());
1005
                    setSubfieldsInStatus();
1006
    
1007
                    setHost(_true_host);
1008
                    setService(_service_name);
1009
                    setServiceType(ServiceInfoTags.vFEATURESERVICE);
1010
                    setTransparency(0);
1011
                    setLayerQuery(_layer_id);
1012
                    setProjection(_true_srs);
1013
                    setName(_layer_name);
1014
    
1015
                    Rectangle2D _fext = ((ArcImsFeatureClient)
1016
                                    _drv.getClient()).getLayerExtent(getArcimsStatus());
1017
                    _drv.setFullExtent(_fext);
1018
                    // individualLayers[i].setF. setFullExtent(((ArcImsProtImageHandler) drv.getClient().getHandler()).getServiceExtent(srs, individualLayers[i].getArcimsStatus()));
1019
    
1020
                    // ------ -------------
1021
                    _drv.setAdapter(_adapter);
1022
                    // adapter.setRecordSet(drv.getRecordSet());
1023
                    _adapter.setOriginalDataSource(_drv.getRecordSet());
1024
                    _adapter.setOriginalVectorialAdapter(_oldadapter);
1025
                    _drv.declareTable();
1026
    
1027
                    setSource(_adapter);
1028
                    _adapter.setDriver(_drv);
1029
    
1030
                    getSource().setDriver(_drv);
1031
                    setInitialLegend();
1032
                    setShapeType(_adapter.getShapeType());
1033
                    setRecordset(_drv.getRecordSet());
1034
                    // ------ -------------
1035
    
1036
                    if ((_si.getFeaturecoordsys() == null) ||
1037
                                    (_si.getFeaturecoordsys().equals(""))) {
1038
                            _si.setFeaturecoordsys(_true_srs.getAbrev().substring(ServiceInfoTags.vINI_SRS.length()).trim());
1039
                            logger.warn("Server provides no SRS. ");
1040
                    }
1041
            } catch (Exception e) {
1042
                    throw new ConnectionException("Unable to connect to host " + _host, e);
1043
            }
1044
    }
1045
    
1046
    */
1047
    public ImageIcon getTocImageIcon() {
1048
        ImageIcon resp = null;
1049

    
1050
        try {
1051
            resp = createImageIcon("images/esrilogo.png");
1052
        }
1053
        catch (Exception ex) {
1054
        }
1055

    
1056
        if (resp == null) {
1057
            return super.getTocImageIcon();
1058
        }
1059
        else {
1060
            return resp;
1061
        }
1062
    }
1063

    
1064
    protected ImageIcon createImageIcon(String path) {
1065
        java.net.URL imgURL = createExtensionUrl(path);
1066

    
1067
        if (imgURL != null) {
1068
            return new ImageIcon(imgURL);
1069
        }
1070
        else {
1071
            logger.error("File not found: " + path);
1072

    
1073
            return null;
1074
        }
1075
    }
1076

    
1077
    protected java.net.URL createExtensionUrl(String path) {
1078
        return PluginServices.getPluginServices(
1079
            "es.prodevelop.cit.gvsig.arcims").getClassLoader().getResource(path);
1080

    
1081
        // return getClass().getClassLoader().getResource(path);
1082
    }
1083

    
1084
    /**
1085
     * Keeps the image's height and width or the image's tiles' height and
1086
     * width, if any. These values are the same as the viewPort's height and
1087
     * width,
1088
     */
1089
    private class VisualStatusArcIms {
1090
        protected int width = 0;
1091
        protected int height = 0;
1092
        protected double minX = 0D;
1093
        protected double minY = 0D;
1094
        protected double maxX = 0D;
1095
        protected double maxY = 0D;
1096
    }
1097
    
1098
    private class AvoidGeometryAndIdFeatureIterator implements IFeatureIterator {
1099
            
1100
            private ArrayList featArray;
1101
            private int index = 0;
1102
            private int size = 0;
1103
            private int noToAvoid = 0;
1104
            
1105
            public AvoidGeometryAndIdFeatureIterator(ArrayList arr, int navoided) {
1106
                    featArray = arr;
1107
                    size = arr.size();
1108
                    index = 0;
1109
                    noToAvoid = navoided;
1110
            }
1111

    
1112
                public void closeIterator() throws ReadDriverException {
1113
                    index = 0;
1114
                }
1115

    
1116
                public boolean hasNext() throws ReadDriverException {
1117
                        return (index < size);
1118
                }
1119

    
1120
                public IFeature next() throws ReadDriverException {
1121
                        index++;
1122
                        if (index > size) {
1123
                                logger.error("Out of index in AuxFeatureIterator: " + (index-1));
1124
                                return null;
1125
                        } else {
1126
                                IFeature resp = (IFeature) featArray.get(index-1);
1127
                                Value[] oldatts = resp.getAttributes();
1128
                                Value[] newatts = new Value[oldatts.length - noToAvoid];
1129
                                for (int i=0; i<newatts.length; i++) newatts[i] = oldatts[i + noToAvoid];
1130
                                resp.setAttributes(newatts);
1131
                                return resp;
1132
                        }
1133
                }
1134
            
1135
    }
1136
}