Statistics
| Revision:

svn-gvsig-desktop / tags / v1_11_0_Build_1306 / extensions / extArcims / src / es / prodevelop / cit / gvsig / arcims / fmap / layers / FFeatureLyrArcIMS.java @ 35731

History | View | Annotate | Download (40.3 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.cresques.cts.IProjection;
65
import org.gvsig.remoteClient.arcims.ArcImsClientP;
66
import org.gvsig.remoteClient.arcims.ArcImsFeatureClient;
67
import org.gvsig.remoteClient.arcims.ArcImsVectStatus;
68
import org.gvsig.remoteClient.arcims.exceptions.ArcImsException;
69
import org.gvsig.remoteClient.arcims.utils.FieldInformation;
70
import org.gvsig.remoteClient.arcims.utils.MyCancellable;
71
import org.gvsig.remoteClient.arcims.utils.ServiceInfoTags;
72
import org.gvsig.remoteClient.arcims.utils.ServiceInformation;
73
import org.gvsig.remoteClient.arcims.utils.ServiceInformationLayerFeatures;
74
import org.gvsig.remoteClient.utils.Utilities;
75

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

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

    
121

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

    
141
    //        private ArrayList initialColors = new ArrayList();
142
    private ArrayList geometries;
143
    private MyCancellable myCanc;
144

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

    
151
        setSource(vectAdapter);
152
        addLegendListener(this);
153
    }
154

    
155
    public FFeatureLyrArcIMS() {
156
    }
157

    
158
    public void setShapeType(int shpType) {
159
        shapeType = shpType;
160
    }
161

    
162
    public void setAdapter(VectorialEditableAdapter edapter) {
163
        setSource(edapter);
164

    
165
        try {
166
            shapeType = edapter.getShapeType();
167

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

    
174
        addLegendListener(this);
175
        myCanc = new MyCancellable(new DefaultCancellableMonitorable());
176

    
177
        //                loadInitialColors();
178
    }
179

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

    
197
        if (!isWithinScale(scale)) {
198
            return;
199
        }
200

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

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

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

    
225
        FMapFeatureArcImsDriver drv =
226
                (FMapFeatureArcImsDriver) getSource().getDriver();
227
        IVectorLegend lgnd = (IVectorLegend) getLegend();
228

    
229
        // get needed fields
230
                String[] _legflds = null;
231
                String[] legflds = null;
232
                String[] savedFieldNames = arcimsStatus.getSubfields();
233

    
234
                if (lgnd instanceof IClassifiedVectorLegend) {
235
                        
236
                        _legflds = ((IClassifiedVectorLegend) lgnd).getClassifyingFieldNames();
237
                        legflds = replaceSpecialChars(_legflds);
238
                        // legflds = _legflds;
239
                        
240
                        if (legflds!=null) {
241
                                String[] appended = appendAtringArrays(savedFieldNames, legflds);
242
                                arcimsStatus.setSubfields(appended);
243
                        }
244
                }
245

    
246
        try {
247
            // ********************************************
248
            // first item in query must contain ID or #ALL#
249
            // ********************************************
250
            geometries = (ArrayList) drv.getMap(arcimsStatus);
251
        } catch (Exception e) {
252
                // restore dubfields
253
                arcimsStatus.setSubfields(savedFieldNames);
254
                ReadDriverException de =
255
                        new ReadDriverException("While getting map (ArrayList of geometries) ", e);
256
            throw de;
257
        }
258
            // restore dubfields
259
        arcimsStatus.setSubfields(savedFieldNames);
260

    
261
            boolean bDrawShapes = true;
262
            
263
            if (lgnd instanceof SingleSymbolLegend) {
264
                    bDrawShapes = lgnd.getDefaultSymbol().isShapeVisible();
265
            }
266
            Point2D offset = viewPort.getOffset();
267
            double dpi = MapContext.getScreenDPI();
268

    
269
            if (bDrawShapes) {
270

    
271
                    try {
272

    
273
                            // Get the iterator over the visible features
274
                            IFeatureIterator it = new AvoidGeometryAndIdFeatureIterator(geometries, savedFieldNames.length);
275
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
276

    
277
                            boolean bSymbolLevelError = false;
278

    
279
                            // if layer has map levels it will use a ZSort
280
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
281

    
282
                            // -- visual FX stuff
283
                            long time = System.currentTimeMillis();
284
                            BufferedImage virtualBim;
285
                            Graphics2D virtualGraphics;
286

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

    
303

    
304
                            int featindex = -1;
305
                            // Iteration over each feature
306
                            while ( !cancel.isCanceled() && it.hasNext()) {
307
                                    
308
                                    featindex++;
309
                                    IFeature feat = it.next();
310
                                    geom = feat.getGeometry();
311
                                    
312
                                    clongeom = geom.cloneGeometry();
313
                                    geom = clongeom; 
314
                            
315
                            if ((layerTransf != null) && (isNotSame(layerTransf))) {
316
                                    geom.reProject(layerTransf);
317
                            }
318

    
319
                                    // retrieve the symbol associated to such feature
320
                                    ISymbol sym = lgnd.getSymbolByFeature(feat);
321

    
322
                                    if (sym == null) continue;
323

    
324
                                    //C?digo para poder acceder a los ?ndices para ver si est? seleccionado un Feature
325
                                    ReadableVectorial rv=getSource();
326
                                    int selectionIndex=-1;
327
                                    
328
                                    
329
                                    FMapFeatureArcImsDriver imsdrv = (FMapFeatureArcImsDriver) getSource().getDriver();
330
                                    selectionIndex = imsdrv.getOverallIndex(featindex);
331

    
332
                                    if (selectionIndex!=-1) {
333
                                            if (getSelectionSupport().isSelected(selectionIndex)) {
334
                                                    sym = sym.getSymbolForSelection();
335
                                            }
336
                                    }
337

    
338
                                    // Check if this symbol is sized with CartographicSupport
339
                                    CartographicSupport csSym = null;
340
                                    int symbolType = sym.getSymbolType();
341
                                    boolean bDrawCartographicSupport = false;
342

    
343
                                    if (   symbolType == FShape.POINT
344
                                                    || symbolType == FShape.LINE
345
                                                    || sym instanceof CartographicSupport) {
346

    
347
                                            // patch
348
                                            if (!sym.getClass().equals(FSymbol.class)) {
349
                                                    csSym = (CartographicSupport) sym;
350
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
351
                                            }
352
                                    }
353

    
354
                                    int x = -1;
355
                                    int y = -1;
356
                                    int[] xyCoords = new int[2];
357

    
358
                                    // Check if size is a pixel
359
                                    boolean onePoint = bDrawCartographicSupport ?
360
                                                    isOnePoint(g.getTransform(), viewPort, MapContext.getScreenDPI(), csSym, geom, xyCoords) :
361
                                                            isOnePoint(g.getTransform(), viewPort, geom, xyCoords);
362

    
363
                                                    // Avoid out of bounds exceptions
364
                                                    if (onePoint) {
365
                                                            x = xyCoords[0];
366
                                                            y = xyCoords[1];
367
                                                            if (x<0 || y<0 || x>= viewPort.getImageWidth() || y>=viewPort.getImageHeight()) continue;
368
                                                    }
369

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

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

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

    
423
                                                                    if (!bDrawCartographicSupport) {
424
                                                                            geom.drawInts(graphics[symbolLevel], viewPort, sym, cancel);
425
                                                                    } else {
426
                                                                            geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) csSym, cancel);
427
                                                                    }
428
                                                            }
429

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

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

    
462
                            if (useZSort) {
463
                                    g.drawImage(image, 0, 0, null);
464
                                    g.translate(offset.getX(), offset.getY());
465
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
466
                                            g.drawImage(imageLevels[i],0,0, null);
467
                                            imageLevels[i] = null;
468
                                            graphics[i] = null;
469
                                    }
470
                                    g.translate(-offset.getX(), -offset.getY());
471
                                    imageLevels = null;
472
                                    graphics = null;
473
                            }
474
                            it.closeIterator();
475

    
476
                            if (bSymbolLevelError) {
477
                                    ((IVectorLegend) getLegend()).setZSort(null);
478
                            }
479

    
480
                    } catch (ReadDriverException e) {
481
                            this.setVisible(false);
482
                            this.setActive(false);
483
                            throw e;
484
                    }
485
            }
486
    }
487

    
488

    
489

    
490
        private String[] replaceSpecialChars(String[] _legflds) {
491
                
492
                int len = _legflds.length;
493
                String[] resp = new String[len];
494
                for (int i=0; i<len; i++) {
495
                        resp[i] = replaceSpecialChars(_legflds[i]);
496
                }
497
                return resp;
498
        }
499

    
500
        private String replaceSpecialChars(String str) {
501
                if (str.compareToIgnoreCase("zIDz") == 0) return "#ID#";
502
                if (str.compareToIgnoreCase("zSHAPEz") == 0) return "#SHAPE#";
503
                return str;
504
        }
505

    
506
        private boolean isNotSame(ICoordTrans trans) {
507
            
508
            String from_abb = trans.getPOrig().getAbrev(); 
509
            String to_abb = trans.getPDest().getAbrev();
510
            return (from_abb.compareTo(to_abb) != 0);
511
        }
512

    
513
        private String[] appendAtringArrays(String[] arr1, String[] arr2) {
514
            
515
            int len = arr1.length + arr2.length;
516
            String[] resp = new String[len];
517
            int i = 0;
518
            for (i=0; i<arr1.length; i++) resp[i] = arr1[i];
519
            for (i=0; i<arr2.length; i++) resp[arr1.length+i] = arr2[i];
520
                return resp;
521
        }
522

    
523
        /**
524
     *
525
     */
526
    public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
527
        Cancellable cancel, double scale) throws ReadDriverException {
528
            
529
            _draw(image, g, viewPort, cancel, scale);
530
    }
531

    
532
    private ISymbol getSymbolOrSelected(int i, ISymbol symbol) {
533
        boolean sel = false;
534

    
535
        try {
536
            sel = getRecordset().getSelectionSupport().isSelected(i);
537
        }
538
        catch (ReadDriverException e) {
539
            logger.error("While getting selection", e);
540
        }
541

    
542
        if (sel) {
543
            return SymbologyFactory.createDefaultSymbolByShapeType(shapeType, Color.YELLOW); 
544
        }
545
        else {
546
            return symbol;
547
        }
548
    }
549

    
550
    /**
551
     *
552
     */
553
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
554
        double scale, PrintRequestAttributeSet properties)
555
        throws ReadDriverException {
556
        draw(null, g, viewPort, cancel, scale);
557
    }
558

    
559
    /**
560
     *
561
     */
562
    public String queryByPoint(Point p) throws ReadDriverException {
563
        Point2D screenCoords;
564
        Point2D geoCoords;
565
        double screenTol;
566
        double geoTol;
567

    
568
        screenCoords = new Point2D.Double(p.getX(), p.getY());
569
        geoCoords = new Point2D.Double(p.getX(), p.getY());
570

    
571
        AffineTransform af = getMapContext().getViewPort().getAffineTransform();
572

    
573
        try {
574
            af.inverseTransform(screenCoords, geoCoords);
575
        }
576
        catch (NoninvertibleTransformException e) {
577
            logger.error("Non invertible AffineTransform ", e);
578
        }
579

    
580
        screenTol = 2.0;
581
        geoTol = 1.0;
582
        geoTol = screenTol / af.getScaleX();
583

    
584
        FBitSet fbs = null;
585
                try {
586
                        fbs = queryByPoint(geoCoords, geoTol);
587
                } catch (Exception e) {
588
                        logger.error("While doing query by point: " + e.getMessage());
589
                }
590

    
591
        // this invoques the client to get attrs.
592
        try {
593
            ((ArcImsVectorialAdapter) getSource()).requestFeatureAttributes(fbs);
594
        }
595
        catch (ArcImsException e) {
596
                ReadDriverException de = new ReadDriverException("While querying by point ", e);
597
            throw de;
598
        }
599

    
600
        String resp = getFormattedFieldsFromSetFeatures(fbs);
601
        System.err.println(resp); //TODO BORRAR ESTO
602

    
603
        return resp;
604
    }
605

    
606
    // TODO: move this to another class:
607
    private String getFormattedFieldsFromSetFeatures(FBitSet fbs) {
608
        String r = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
609
        r = r + "<FeatureInfoResponse>";
610
        r = r + "<LAYER ID=\"" + layerQuery + "\" NAME=\"" + getName() + "\">";
611

    
612
        for (int i = fbs.nextSetBit(0); i >= 0; i = fbs.nextSetBit(i + 1)) {
613
            r = r + getFormattedFieldsFromFeature(i);
614
        }
615

    
616
        r = r + "</LAYER>";
617
        r = r + "</FeatureInfoResponse>";
618

    
619
        return r;
620
    }
621

    
622
    // TODO: move this to another class:
623
    private String getFormattedFieldsFromFeature(int j) {
624
        String r = "<FIELDS ";
625
        String fieldName;
626
        String fieldValue;
627
        DataSource ds = null;
628

    
629
        try {
630
            ds = getSource().getRecordset();
631
        }
632
        catch (ReadDriverException e1) {
633
            logger.error("DriverException while getting field values. ", e1);
634
        }
635

    
636
        int count;
637

    
638
        try {
639
            count = ds.getFieldCount();
640

    
641
            for (int i = 0; i < count; i++) {
642
                fieldName = ds.getFieldName(i);
643
                fieldName = ArcImsInMemoryAttsTableDriver.replaceUnwantedCharacters(fieldName);
644

    
645
                fieldValue = restoreSpecialChars(ds.getFieldValue((long) j, i)
646
                                                   .toString());
647
                logger.debug("fieldvalue = " + fieldValue);
648
                r = r + " " + fieldName + "=" + "\"" + fieldValue + "\"";
649
            }
650

    
651
            // <FIELDS NOMBRE="LR-542" OBSERVACIO="" TIPO="CAUT3" _SHAPE_="[Geometry]" _ID_="1975" />
652
            r = r + "/>";
653
        }
654
        catch (ReadDriverException e) {
655
            logger.error("DriverException while getting field values. ", e);
656
        }
657

    
658
        return r;
659
    }
660

    
661
    private String restoreSpecialChars(String str) {
662
        /*
663
         * < 60 3c, > 62 3e, & 38 26, " 34 22, ' 39 27
664
         */
665
        String resp = str.replaceAll("\\x26", "&amp;");
666
        resp = resp.replaceAll("\\x3c", "&lt;");
667
        resp = resp.replaceAll("\\x3e", "&gt;");
668

    
669
        resp = resp.replaceAll("\\x22", "&quot;");
670
        resp = resp.replaceAll("\\x27", "&#39;");
671

    
672
        return resp;
673
    }
674

    
675
    public void setInitialLegend() {
676
        FMapFeatureArcImsDriver drv = (FMapFeatureArcImsDriver) getSource()
677
                                                                    .getDriver();
678

    
679
        //Try to get the legend from the service information
680
        try {
681
                ArcImsClientP cli = drv.getClient();
682
                String lyr_id_0 = (String) arcimsStatus.getLayerIds().get(0);
683
                SelectableDataSource ds = getRecordset();
684
            ILegend initialleg = cli.getLegend(lyr_id_0, ds); 
685

    
686
            if (initialleg != null) {
687
                setLegend((IVectorLegend) initialleg);
688
            }
689

    
690
            return;
691
        }
692
        catch (Exception e) {
693
            logger.error("While setting initial legend ", e);
694
        }
695

    
696
    }
697

    
698
    // Classifiable
699
    public int getShapeType() throws ReadDriverException {
700
        FMapFeatureArcImsDriver drv = (FMapFeatureArcImsDriver) getSource()
701
                                                                    .getDriver();
702

    
703
        return drv.getShapeType();
704
    }
705

    
706
    public void setServiceInformationInStatus(ServiceInformation si) {
707
        this.arcimsStatus.setServiceInformation(si);
708
    }
709

    
710
    public ArcImsVectStatus getArcimsStatus() {
711
        return arcimsStatus;
712
    }
713

    
714
    public void setArcimsStatus(ArcImsVectStatus arcimsStatus) {
715
        this.arcimsStatus = arcimsStatus;
716
    }
717

    
718
    public boolean isFirstLoad() {
719
        return firstLoad;
720
    }
721

    
722
    public void setFirstLoad(boolean firstLoad) {
723
        this.firstLoad = firstLoad;
724
    }
725

    
726
    public URL getHost() {
727
        return host;
728
    }
729

    
730
    public void setHost(URL host) {
731
        this.host = host;
732
    }
733

    
734
    public String getLayerQuery() {
735
        return layerQuery;
736
    }
737

    
738
    public void setLayerQuery(String lQuery) {
739
        this.layerQuery = lQuery;
740

    
741
        if (layerQuery.substring(0, 1).compareTo(",") == 0) {
742
            layerQuery = layerQuery.substring(1);
743
        }
744
    }
745

    
746
    public String getService() {
747
        return service;
748
    }
749

    
750
    public void setService(String service) {
751
        this.service = service;
752
    }
753

    
754
    public String getServiceType() {
755
        return serviceType;
756
    }
757

    
758
    public void setServiceType(String serviceType) {
759
        this.serviceType = serviceType;
760
    }
761

    
762
    public String getSRS() {
763
        return SRS;
764
    }
765

    
766
    public void setSRS(String srs) {
767
        SRS = srs;
768
    }
769

    
770
    public boolean getArcImsTransparency() {
771
        return arcImsTransparency;
772
    }
773

    
774
    public void setArcImsTransparency(boolean arcImsTransparency) {
775
        this.arcImsTransparency = arcImsTransparency;
776
    }
777

    
778
    public int getTransparency() {
779
        return transparency;
780
    }
781

    
782
    public void setTransparency(int transparency) {
783
        this.transparency = transparency;
784
    }
785

    
786
    public HashMap getProperties() {
787
        HashMap info = new HashMap();
788
        String[] layerNames = getLayerQuery().split(",");
789
        Vector layers = new Vector(layerNames.length);
790
        FMapFeatureArcImsDriver drv = (FMapFeatureArcImsDriver) getSource()
791
                                                                    .getDriver();
792

    
793
        try {
794
            if (drv.connect(myCanc)) {
795
                info.put("layerName", this.getName());
796
                info.put("serverUrl", this.getHost());
797
                info.put("serviceName", this.getService());
798
                info.put("serviceType", this.getServiceType());
799

    
800
                for (int i = 0; i < layerNames.length; i++)
801
                    layers.add(layerNames[i]);
802

    
803
                info.put("layerIds", layers);
804

    
805
                return info;
806
            }
807
        }
808
        catch (Exception e) {
809
            logger.error("Error in FRasterLyrArcIMS.getProperties() ", e);
810
        }
811

    
812
        return null;
813
    }
814

    
815
    public void setLayerIdsInStatus(Vector idsv) {
816
        arcimsStatus.setLayerIds(idsv);
817
    }
818

    
819
    public void setProjectionInStatus(String abbrev_srs) {
820
        arcimsStatus.setSrs(abbrev_srs);
821
    }
822

    
823
    public void setHostInStatus(URL url) {
824
        arcimsStatus.setServer(url.toString());
825
    }
826

    
827
    public void setServiceInStatus(String srv) {
828
        arcimsStatus.setService(srv);
829
    }
830

    
831
    public void setSubfieldsInStatus() {
832
        String[] subfields = new String[2];
833
        String id = (String) arcimsStatus.getLayerIds().get(0);
834
        ServiceInformationLayerFeatures silf = (ServiceInformationLayerFeatures) arcimsStatus.getServiceInfo()
835
                                                                                             .getLayerById(id);
836
        FieldInformation fi = (FieldInformation) silf.getFieldInformationByType(FieldInformation.ID)
837
                                                     .get(0);
838
        subfields[1] = fi.getName();
839
        fi = (FieldInformation) silf.getFieldInformationByType(FieldInformation.SHAPE)
840
                                    .get(0);
841
        subfields[0] = fi.getName();
842
        arcimsStatus.setSubfields(subfields);
843
    }
844

    
845
    public void legendChanged(LegendChangedEvent e) {
846
        MapContext fmap = getMapContext();
847

    
848
        if (fmap != null) {
849
            fmap.invalidate();
850
        }
851
    }
852

    
853
    public void setXMLEntity(XMLEntity xml) throws XMLException {
854
        try {
855
            setHost(new URL(xml.getStringProperty("_host")));
856
        }
857
        catch (MalformedURLException e) {
858
            logger.error("Bad url ", e);
859
        }
860

    
861
        setService(xml.getStringProperty("_service"));
862
        setLayerQuery(xml.getStringProperty("layerQuery"));
863
        setSrsAbrev(xml.getStringProperty("srs_abrev"));
864

    
865
        FMapFeatureArcImsDriver drv = new FMapFeatureArcImsDriver(host.toString(),
866
                service, layerQuery);
867

    
868
        if (!(drv.connect(myCanc))) {
869
            throw new XMLException(new DriverException(
870
                    "Unable to connect to server"));
871
        }
872

    
873
        drv.setLayer(this);
874

    
875
        Vector ids = new Vector();
876
        ids.add(getLayerQuery());
877
        setLayerIdsInStatus(ids);
878

    
879
        ArcImsClientP cli = drv.getClient();
880
        ServiceInformation si = cli.getServiceInformation();
881
        arcimsStatus.setServiceInformation(si);
882

    
883
        String srs = getSrsAbrev();
884
        arcimsStatus.setSrs(srs);
885

    
886
        if ((si.getFeaturecoordsys() == null) ||
887
                (si.getFeaturecoordsys().equals(""))) {
888
            si.setFeaturecoordsys(srs.substring(
889
                    ServiceInfoTags.vINI_SRS.length()).trim());
890
            logger.warn("Server provides no SRS. ");
891
        }
892

    
893
        Rectangle2D fext = null;
894

    
895
        try {
896
            fext = ((ArcImsFeatureClient) drv.getClient()).getLayerExtent(arcimsStatus);
897
        }
898
        catch (Exception e) {
899
            logger.error("While loading ArcIMS layer ", e);
900
        }
901

    
902
        arcimsStatus.setExtent(fext);
903
        drv.setFullExtent(fext);
904

    
905
        setSubfieldsInStatus();
906

    
907
        // drv.loadRecordSet();
908
        ArcImsVectorialAdapter oldadapter = new ArcImsVectorialAdapter(drv);
909
        ArcImsVectorialEditableAdapter adapter = new ArcImsVectorialEditableAdapter();
910

    
911
        String recordsetName = xml.getStringProperty("recordset-name");
912

    
913
        try {
914
            adapter.setOriginalDataSource(drv.getRecordSet(recordsetName));
915
            adapter.setOriginalVectorialAdapter(oldadapter);
916
        }
917
        catch (ReadDriverException e) {
918
            logger.error("While setting original data source ", e);
919
        }
920

    
921

    
922
        setAdapter(adapter);
923

    
924
        drv.setAdapter(adapter);
925

    
926
        setInitialLegend();
927

    
928
        try {
929
            setRecordset(((FMapFeatureArcImsDriver) getSource().getDriver()).getRecordSet());
930
        }
931
        catch (Exception e) {
932
            logger.error("While setting data source ", e);
933
        }
934

    
935
        super.setXMLEntity(xml);
936
    }
937

    
938
    public XMLEntity getXMLEntity() throws XMLException {
939
        XMLEntity resp = super.getXMLEntity();
940

    
941
        // PluginServices.getMDIManager().addView(null);
942
        resp.putProperty("srs_abrev", getMapContext().getProjection().getAbrev());
943
        resp.putProperty("_host", host.toString());
944
        resp.putProperty("_service", service);
945
        resp.putProperty("layerQuery", layerQuery);
946

    
947
        return resp;
948
    }
949

    
950
    public String getSrsAbrev() {
951
        return srsAbrev;
952
    }
953

    
954
    public void setSrsAbrev(String srsAbrev) {
955
        this.srsAbrev = srsAbrev;
956
    }
957

    
958
    /**
959
     * The extCatalogYNomenclator needs this creator.
960
     *
961
     * @param p a Map object with the following keys:
962
     *
963
     * (key, object type returned)
964
     * ---------------------------
965
     * "host", String (with or without the servlet path)
966
     * "service_name", String (remote service name)
967
     * "srs", String (coordinate system)
968
     * "layer_id", String (*single* remote layer's ID)
969
     * "layer_name", String (local layer name)
970
     *
971
     * @return a FRasterLyrArcIMS layer
972
     * @throws ConnectionException
973
     */
974

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

    
1071
        try {
1072
            resp = createImageIcon("images/esrilogo.png");
1073
        }
1074
        catch (Exception ex) {
1075
        }
1076

    
1077
        if (resp == null) {
1078
            return super.getTocImageIcon();
1079
        }
1080
        else {
1081
            return resp;
1082
        }
1083
    }
1084

    
1085
    protected ImageIcon createImageIcon(String path) {
1086
        java.net.URL imgURL = createExtensionUrl(path);
1087

    
1088
        if (imgURL != null) {
1089
            return new ImageIcon(imgURL);
1090
        }
1091
        else {
1092
            logger.error("File not found: " + path);
1093

    
1094
            return null;
1095
        }
1096
    }
1097

    
1098
    protected java.net.URL createExtensionUrl(String path) {
1099
        return PluginServices.getPluginServices(
1100
            "es.prodevelop.cit.gvsig.arcims").getClassLoader().getResource(path);
1101

    
1102
        // return getClass().getClassLoader().getResource(path);
1103
    }
1104
    
1105
    
1106
    
1107
    public Rectangle2D getFullExtent() throws ReadDriverException, ExpansionFileReadException {
1108
            
1109
            ReadableVectorial rv = getSource();
1110
            
1111
        Rectangle2D rAux;
1112
        rv.start();
1113
        rAux = (Rectangle2D) rv.getFullExtent().clone();
1114
        rv.stop();
1115

    
1116
        // Si existe reproyecci?n, reproyectar el extent
1117
        ICoordTrans ct = getCoordTrans();
1118
                try{
1119
                if ((ct != null) && (!sourceEqualsTarget(ct))) {
1120
                    Point2D pt1 = new Point2D.Double(rAux.getMinX(), rAux.getMinY());
1121
                    Point2D pt2 = new Point2D.Double(rAux.getMaxX(), rAux.getMaxY());
1122
                    pt1 = ct.convert(pt1, null);
1123
                    pt2 = ct.convert(pt2, null);
1124
                    rAux = new Rectangle2D.Double();
1125
                    rAux.setFrameFromDiagonal(pt1, pt2);
1126
                }
1127
                } catch (IllegalStateException e) {
1128
                        // this.setAvailable(false);
1129
                        // this.addError(new ReprojectLayerException(getName(), e));
1130
                        logger.error("Unable to reproject extent: " + rAux.toString());
1131
                        logger.error("Transf from CRS: " + ct.getPOrig().getFullCode());
1132
                        logger.error("Transf to CRS  : " + ct.getPDest().getFullCode());
1133
                        logger.warn("No reprojection made.");
1134
                }
1135
        //Esto es para cuando se crea una capa nueva con el fullExtent de ancho y alto 0.
1136
        if (rAux.getWidth()==0 && rAux.getHeight()==0) {
1137
            rAux=new Rectangle2D.Double(0,0,100,100);
1138
        }
1139

    
1140
        return rAux;
1141

    
1142
    }
1143
    
1144
    private boolean sourceEqualsTarget(ICoordTrans ct) {
1145
            
1146
            IProjection p1 = ct.getPOrig();
1147
            IProjection p2 = ct.getPDest();
1148
            String str1 = p1.getFullCode();
1149
            String str2 = p2.getFullCode();
1150
            return (str1.compareTo(str2) == 0);
1151
}
1152
    
1153
    
1154
    
1155

    
1156
    /**
1157
     * Keeps the image's height and width or the image's tiles' height and
1158
     * width, if any. These values are the same as the viewPort's height and
1159
     * width,
1160
     */
1161
    private class VisualStatusArcIms {
1162
        protected int width = 0;
1163
        protected int height = 0;
1164
        protected double minX = 0D;
1165
        protected double minY = 0D;
1166
        protected double maxX = 0D;
1167
        protected double maxY = 0D;
1168
    }
1169
    
1170
    private class AvoidGeometryAndIdFeatureIterator implements IFeatureIterator {
1171
            
1172
            private ArrayList featArray;
1173
            private int index = 0;
1174
            private int size = 0;
1175
            private int noToAvoid = 0;
1176
            
1177
            public AvoidGeometryAndIdFeatureIterator(ArrayList arr, int navoided) {
1178
                    featArray = arr;
1179
                    size = arr.size();
1180
                    index = 0;
1181
                    noToAvoid = navoided;
1182
            }
1183

    
1184
                public void closeIterator() throws ReadDriverException {
1185
                    index = 0;
1186
                }
1187

    
1188
                public boolean hasNext() throws ReadDriverException {
1189
                        return (index < size);
1190
                }
1191

    
1192
                public IFeature next() throws ReadDriverException {
1193
                        index++;
1194
                        if (index > size) {
1195
                                logger.error("Out of index in AuxFeatureIterator: " + (index-1));
1196
                                return null;
1197
                        } else {
1198
                                IFeature resp = (IFeature) featArray.get(index-1);
1199
                                Value[] oldatts = resp.getAttributes();
1200
                                Value[] newatts = new Value[oldatts.length - noToAvoid];
1201
                                for (int i=0; i<newatts.length; i++) newatts[i] = oldatts[i + noToAvoid];
1202
                                resp.setAttributes(newatts);
1203
                                return resp;
1204
                        }
1205
                }
1206
            
1207
    }
1208
}