Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / layers / FLyrVect.java @ 24376

History | View | Annotate | Download (62 KB)

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

    
43
import java.awt.Graphics2D;
44
import java.awt.Point;
45
import java.awt.geom.AffineTransform;
46
import java.awt.geom.Point2D;
47
import java.awt.geom.Rectangle2D;
48
import java.awt.image.BufferedImage;
49
import java.io.File;
50
import java.net.URI;
51
import java.util.ArrayList;
52

    
53
import javax.print.attribute.PrintRequestAttributeSet;
54
import javax.print.attribute.standard.PrintQuality;
55

    
56
import org.apache.log4j.Logger;
57
import org.cresques.cts.ICoordTrans;
58

    
59
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
60
import com.hardcode.gdbms.engine.data.DataSourceFactory;
61
import com.hardcode.gdbms.engine.data.NoSuchTableException;
62
import com.hardcode.gdbms.engine.data.driver.DriverException;
63
import com.hardcode.gdbms.engine.instruction.FieldNotFoundException;
64
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
65
import com.iver.cit.gvsig.exceptions.layers.LegendLayerException;
66
import com.iver.cit.gvsig.exceptions.layers.LoadLayerException;
67
import com.iver.cit.gvsig.exceptions.layers.ReloadLayerException;
68
import com.iver.cit.gvsig.exceptions.layers.StartEditionLayerException;
69
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException;
70
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
71
import com.iver.cit.gvsig.fmap.MapContext;
72
import com.iver.cit.gvsig.fmap.MapControl;
73
import com.iver.cit.gvsig.fmap.ViewPort;
74
import com.iver.cit.gvsig.fmap.core.CartographicSupport;
75
import com.iver.cit.gvsig.fmap.core.FPoint2D;
76
import com.iver.cit.gvsig.fmap.core.FShape;
77
import com.iver.cit.gvsig.fmap.core.IFeature;
78
import com.iver.cit.gvsig.fmap.core.IGeometry;
79
import com.iver.cit.gvsig.fmap.core.ILabelable;
80
import com.iver.cit.gvsig.fmap.core.IRow;
81
import com.iver.cit.gvsig.fmap.core.symbols.IMultiLayerSymbol;
82
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
83
import com.iver.cit.gvsig.fmap.core.v02.FSymbol;
84
import com.iver.cit.gvsig.fmap.drivers.BoundedShapes;
85
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
86
import com.iver.cit.gvsig.fmap.drivers.IVectorialDatabaseDriver;
87
import com.iver.cit.gvsig.fmap.drivers.VectorialDriver;
88
import com.iver.cit.gvsig.fmap.drivers.WithDefaultLegend;
89
import com.iver.cit.gvsig.fmap.edition.AfterFieldEditEvent;
90
import com.iver.cit.gvsig.fmap.edition.AfterRowEditEvent;
91
import com.iver.cit.gvsig.fmap.edition.AnnotationEditableAdapter;
92
import com.iver.cit.gvsig.fmap.edition.BeforeFieldEditEvent;
93
import com.iver.cit.gvsig.fmap.edition.BeforeRowEditEvent;
94
import com.iver.cit.gvsig.fmap.edition.EditionEvent;
95
import com.iver.cit.gvsig.fmap.edition.IEditionListener;
96
import com.iver.cit.gvsig.fmap.edition.ISpatialWriter;
97
import com.iver.cit.gvsig.fmap.edition.IWriteable;
98
import com.iver.cit.gvsig.fmap.edition.IWriter;
99
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
100
import com.iver.cit.gvsig.fmap.edition.VectorialEditableDBAdapter;
101
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
102
import com.iver.cit.gvsig.fmap.layers.layerOperations.ClassifiableVectorial;
103
import com.iver.cit.gvsig.fmap.layers.layerOperations.InfoByPoint;
104
import com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData;
105
import com.iver.cit.gvsig.fmap.layers.layerOperations.SingleLayer;
106
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData;
107
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialXMLItem;
108
import com.iver.cit.gvsig.fmap.layers.layerOperations.XMLItem;
109
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
110
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy;
111
import com.iver.cit.gvsig.fmap.operations.strategies.StrategyManager;
112
import com.iver.cit.gvsig.fmap.rendering.IClassifiedVectorLegend;
113
import com.iver.cit.gvsig.fmap.rendering.ILegend;
114
import com.iver.cit.gvsig.fmap.rendering.IVectorLegend;
115
import com.iver.cit.gvsig.fmap.rendering.LegendFactory;
116
import com.iver.cit.gvsig.fmap.rendering.SingleSymbolLegend;
117
import com.iver.cit.gvsig.fmap.rendering.ZSort;
118
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.AttrInTableLabelingStrategy;
119
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.ILabelingStrategy;
120
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelingFactory;
121
import com.iver.cit.gvsig.fmap.spatialindex.IPersistentSpatialIndex;
122
import com.iver.cit.gvsig.fmap.spatialindex.ISpatialIndex;
123
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeGt2;
124
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeJts;
125
import com.iver.cit.gvsig.fmap.spatialindex.SpatialIndexException;
126
import com.iver.utiles.FileUtils;
127
import com.iver.utiles.IPersistence;
128
import com.iver.utiles.NotExistInXMLEntity;
129
import com.iver.utiles.PostProcessSupport;
130
import com.iver.utiles.XMLEntity;
131
import com.iver.utiles.swing.threads.Cancellable;
132
import com.iver.utiles.swing.threads.CancellableMonitorable;
133

    
134
/**
135
 * Capa b?sica Vectorial.
136
 *
137
 * @author Fernando Gonz?lez Cort?s
138
 */
139

    
140
// TODO Cuando no sea para pruebas debe no ser public
141
public class FLyrVect extends FLyrDefault implements ILabelable,
142
        ClassifiableVectorial, SingleLayer, VectorialData, RandomVectorialData,
143
        AlphanumericData, InfoByPoint, SelectionListener, IEditionListener {
144
    private static Logger logger = Logger.getLogger(FLyrVect.class.getName());
145
    /**
146
     * @deprecated Don?t use Strategy, you should be use iterators.
147
     */
148
//    public static boolean forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD = true;
149
    /**
150
     * @deprecated Don?t use Strategy, you should be use iterators.
151
     */
152
//    private boolean useStrategy=false;
153

    
154
    /** Leyenda de la capa vectorial */
155
    private IVectorLegend legend;
156
    private int typeShape = -1;
157
    private ReadableVectorial source;
158
    private SelectableDataSource sds;
159
    private SelectionSupport selectionSupport = new SelectionSupport();
160
    private SpatialCache spatialCache = new SpatialCache();
161
    private boolean spatialCacheEnabled = false;
162

    
163
    /**
164
     * An implementation of gvSIG spatial index
165
     */
166
    protected ISpatialIndex spatialIndex = null;
167
    private boolean bHasJoin = false;
168
    private XMLEntity orgXMLEntity = null;
169
    private XMLEntity loadSelection = null;
170
    private IVectorLegend loadLegend = null;
171

    
172
    //Lo a?ado. Caracter?sticas de HyperEnlace (LINK)
173
    private FLyrVectLinkProperties linkProperties=new FLyrVectLinkProperties();
174
    //private ArrayList linkProperties=null;
175

    
176
    /**
177
     * Devuelve el VectorialAdapater de la capa.
178
     *
179
     * @return VectorialAdapter.
180
     */
181
    public ReadableVectorial getSource() {
182
        if (!this.isAvailable()) return null;
183
        return source;
184
    }
185

    
186
    /**
187
     * If we use a persistent spatial index associated with this layer, and the
188
     * index is not intrisic to the layer (for example spatial databases) this
189
     * method looks for existent spatial index, and loads it.
190
     *
191
     */
192
    private void loadSpatialIndex() {
193
        //FIXME: Al abrir el indice en fichero...
194
        //?C?mo lo liberamos? un metodo Layer.shutdown()
195

    
196

    
197
        ReadableVectorial source = getSource();
198
        //REVISAR QUE PASA CON LOS DRIVERS DXF, DGN, etc.
199
        //PUES SON VECTORIALFILEADAPTER
200
        if (!(source instanceof VectorialFileAdapter)) {
201
            // we are not interested in db adapters
202
            return;
203
        }
204
        VectorialDriver driver = source.getDriver();
205
        if (!(driver instanceof BoundedShapes)) {
206
            // we dont spatially index layers that are not bounded
207
            return;
208
        }
209
        File file = ((VectorialFileAdapter) source).getFile();
210
        String fileName = file.getAbsolutePath();
211
        File sptFile = new File(fileName + ".qix");
212
        if (!sptFile.exists() || (!(sptFile.length() > 0))) {
213
            // before to exit, look for it in temp path
214
            String tempPath = System.getProperty("java.io.tmpdir");
215
            fileName = tempPath + File.separator + sptFile.getName();
216
            sptFile = new File(fileName);
217
            // it doesnt exists, must to create
218
            if (!sptFile.exists() || (!(sptFile.length() > 0))) {
219
                return;
220
            }// if
221
        }// if
222

    
223
        try {
224
            source.start();
225
            spatialIndex = new QuadtreeGt2(FileUtils.getFileWithoutExtension(sptFile),
226
                    "NM", source.getFullExtent(), source.getShapeCount(), false);
227
            source.setSpatialIndex(spatialIndex);
228
        } catch (SpatialIndexException e) {
229
            spatialIndex = null;
230
            e.printStackTrace();
231
            return;
232
        } catch (ReadDriverException e) {
233
            spatialIndex = null;
234
            e.printStackTrace();
235
            return;
236
        }
237

    
238
    }
239

    
240
    /**
241
     * Checks if it has associated an external spatial index
242
     * (an spatial index file).
243
     *
244
     * It looks for it in main file path, or in temp system path.
245
     * If main file is rivers.shp, it looks for a file called
246
     * rivers.shp.qix.
247

248
     * @return
249
     */
250
    public boolean isExternallySpatiallyIndexed() {
251
        /*
252
         * FIXME (AZABALA): Independizar del tipo de fichero de ?ndice
253
          * con el que se trabaje (ahora mismo considera la extension .qix,
254
         * pero esto depender? del tipo de ?ndice)
255
         * */
256
        ReadableVectorial source = getSource();
257
        if (!(source instanceof VectorialFileAdapter)) {
258
            // we are not interested in db adapters.
259
            // think in non spatial dbs, like HSQLDB
260
            return false;
261
        }
262
        File file = ((VectorialFileAdapter) source).getFile();
263
        String fileName = file.getAbsolutePath();
264
        File sptFile = new File(fileName + ".qix");
265
        if (!sptFile.exists() || (!(sptFile.length() > 0))) {
266
            // before to exit, look for it in temp path
267
            // it doesnt exists, must to create
268
            String tempPath = System.getProperty("java.io.tmpdir");
269
            fileName = tempPath + File.separator + sptFile.getName();
270
            sptFile = new File(fileName);
271
            if (!sptFile.exists() || (!(sptFile.length() > 0))) {
272
                return false;
273
            }// if
274
        }// if
275
        return true;
276
    }
277

    
278
    /**
279
     * Inserta el VectorialAdapter a la capa.
280
     *
281
     * @param va
282
     *            VectorialAdapter.
283
     */
284
    public void setSource(ReadableVectorial rv) {
285
        source = rv;
286
        // azabala: we check if this layer could have a file spatial index
287
        // and load it if it exists
288
        loadSpatialIndex();
289
    }
290

    
291
    public Rectangle2D getFullExtent() throws ReadDriverException, ExpansionFileReadException {
292
            Rectangle2D rAux;
293
            source.start();
294
            rAux = (Rectangle2D)source.getFullExtent().clone();
295
            source.stop();
296

    
297
            // Si existe reproyecci?n, reproyectar el extent
298
            ICoordTrans ct = getCoordTrans();
299

    
300
            if (ct != null) {
301
                Point2D pt1 = new Point2D.Double(rAux.getMinX(), rAux.getMinY());
302
                Point2D pt2 = new Point2D.Double(rAux.getMaxX(), rAux.getMaxY());
303
                pt1 = ct.convert(pt1, null);
304
                pt2 = ct.convert(pt2, null);
305
                rAux = new Rectangle2D.Double();
306
                rAux.setFrameFromDiagonal(pt1, pt2);
307
            }
308

    
309
            //Esto es para cuando se crea una capa nueva con el fullExtent de ancho y alto 0.
310
            if (rAux.getWidth()==0 && rAux.getHeight()==0) {
311
                rAux=new Rectangle2D.Double(0,0,100,100);
312
            }
313

    
314
            return rAux;
315
    }
316

    
317
    /**
318
     * Draws using IFeatureIterator. This method will replace the old draw(...) one.
319
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
320
     * @param image
321
     * @param g
322
     * @param viewPort
323
     * @param cancel
324
     * @param scale
325
     * @throws ReadDriverException
326
     */
327
    private void _draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
328
                    Cancellable cancel, double scale) throws ReadDriverException {
329
            boolean bDrawShapes = true;
330
            if (legend instanceof SingleSymbolLegend) {
331
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
332
            }
333
            Point2D offset = viewPort.getOffset();
334
            double dpi = MapContext.getScreenDPI();
335

    
336

    
337

    
338
            if (bDrawShapes) {
339
                    boolean cacheFeatures = isSpatialCacheEnabled();
340
                    SpatialCache cache = null;
341
                if (cacheFeatures) {
342
                        getSpatialCache().clearAll();
343
                        cache = getSpatialCache();
344
                }
345

    
346
                    try {
347
                            ArrayList<String> fieldList = new ArrayList<String>();
348

    
349
                            // fields from legend
350
                            String[] aux = null;
351

    
352
                            if (legend instanceof IClassifiedVectorLegend) {
353
                                    aux = ((IClassifiedVectorLegend) legend).getClassifyingFieldNames();
354
                                    for (int i = 0; i < aux.length; i++) {
355
                                            fieldList.add(aux[i]);
356
                                    }
357
                            }
358

    
359
                            // Get the iterator over the visible features
360
                            IFeatureIterator it = getSource().getFeatureIterator(
361
                                            viewPort.getAdjustedExtent(),
362
                                            fieldList.toArray(new String[fieldList.size()]),
363
                                            viewPort.getProjection(),
364
                                            true);
365

    
366
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
367

    
368
                            boolean bSymbolLevelError = false;
369

    
370
                            // if layer has map levels it will use a ZSort
371
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
372

    
373
                            // -- visual FX stuff
374
                            long time = System.currentTimeMillis();
375
                            BufferedImage virtualBim;
376
                            Graphics2D virtualGraphics;
377

    
378
                            // render temporary map each screenRefreshRate milliseconds;
379
                            int screenRefreshDelay = (int) ((1D/MapControl.getDrawFrameRate())*3*1000);
380
                            BufferedImage[] imageLevels = null;
381
                            Graphics2D[] graphics = null;
382
                            if (useZSort) {
383
                                    imageLevels = new BufferedImage[zSort.getLevelCount()];
384
                                    graphics = new Graphics2D[imageLevels.length];
385
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
386
                                            imageLevels[i] = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
387
                                            graphics[i] = imageLevels[i].createGraphics();
388
                                            graphics[i].setTransform(g.getTransform());
389
                                            graphics[i].setRenderingHints(g.getRenderingHints());
390
                                    }
391
                            }
392
                            // -- end visual FX stuff
393

    
394

    
395
                            // Iteration over each feature
396
                            while ( !cancel.isCanceled() && it.hasNext()) {
397
                                    IFeature feat = it.next();
398
                                    IGeometry geom = feat.getGeometry();
399

    
400
                                    if (cacheFeatures) {
401
                                            if (cache.getMaxFeatures() >= cache.size()) {
402
                                                        // already reprojected
403
                                                        cache.insert(geom.getBounds2D(), geom);
404
                                                }
405
                                    }
406

    
407
                                    // retrieve the symbol associated to such feature
408
                                    ISymbol sym = legend.getSymbolByFeature(feat);
409

    
410
                                    if (sym == null) continue;
411

    
412
                                    //C?digo para poder acceder a los ?ndices para ver si est? seleccionado un Feature
413
                                    ReadableVectorial rv=getSource();
414
                                    int selectionIndex=-1;
415
                                    if (rv instanceof ISpatialDB){
416
                                            selectionIndex = ((ISpatialDB)rv).getRowIndexByFID(feat);
417
                                    }else{
418
                                            selectionIndex = Integer.parseInt(feat.getID());
419
                                    }
420
                                    if (selectionIndex!=-1) {
421
                                            if (selectionSupport.isSelected(selectionIndex)) {
422
                                                sym = sym.getSymbolForSelection();
423
                                        }
424
                                }
425

    
426
                                    // Check if this symbol is sized with CartographicSupport
427
                                    CartographicSupport csSym = null;
428
                                    int symbolType = sym.getSymbolType();
429
                                    boolean bDrawCartographicSupport = false;
430

    
431
                                    if (   symbolType == FShape.POINT
432
                                                    || symbolType == FShape.LINE
433
                                                    || sym instanceof CartographicSupport) {
434

    
435
                                            // patch
436
                                        if (!sym.getClass().equals(FSymbol.class)) {
437
                                                csSym = (CartographicSupport) sym;
438
                                                bDrawCartographicSupport = (csSym.getUnit() != -1);
439
                                        }
440
                                    }
441

    
442
                                    int x = -1;
443
                                    int y = -1;
444
                                    int[] xyCoords = new int[2];
445

    
446
                                    // Check if size is a pixel
447
                                    boolean onePoint = bDrawCartographicSupport ?
448
                                                    isOnePoint(g.getTransform(), viewPort, MapContext.getScreenDPI(), csSym, geom, xyCoords) :
449
                                                    isOnePoint(g.getTransform(), viewPort, geom, xyCoords);
450

    
451
                                        // Avoid out of bounds exceptions
452
                                        if (onePoint) {
453
                                                x = xyCoords[0];
454
                                                y = xyCoords[1];
455
                                                if (x<0 || y<0 || x>= viewPort.getImageWidth() || y>=viewPort.getImageHeight()) continue;
456
                                        }
457

    
458
                                        if (useZSort) {
459
                                                // Check if this symbol is a multilayer
460
                                                if (sym instanceof IMultiLayerSymbol) {
461
                                                        // if so, treat each of its layers as a single symbol
462
                                                        // in its corresponding map level
463
                                                        IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
464
                                                        for (int i = 0; !cancel.isCanceled() && i < mlSym.getLayerCount(); i++) {
465
                                                                ISymbol mySym = mlSym.getLayer(i);
466
                                                                int symbolLevel = zSort.getSymbolLevel(mySym);
467

    
468
                                                                if (symbolLevel == -1) {
469
                                                                        /* an error occured when managing symbol levels.
470
                                                                         * some of the legend changed events regarding the
471
                                                                         * symbols did not finish satisfactory and the legend
472
                                                                         * is now inconsistent. For this drawing, it will finish
473
                                                                         * as it was at the bottom (level 0) but, when done, the
474
                                                                         * ZSort will be reset to avoid app crashes. This is
475
                                                                         * a bug that has to be fixed.
476
                                                                         */
477
                                                                        bSymbolLevelError = true;
478
                                                                        symbolLevel=0;
479
                                                                }
480

    
481
                                                                if (onePoint) {
482
                                                                        if (x<0 || y<0 || x>= imageLevels[symbolLevel].getWidth() || y>=imageLevels[symbolLevel].getHeight()) continue;
483
                                                                        imageLevels[symbolLevel].setRGB(x, y, mySym.getOnePointRgb());
484
                                                                } else {
485
                                                                        if (!bDrawCartographicSupport) {
486
                                                                                geom.drawInts(graphics[symbolLevel], viewPort, mySym, cancel);
487
                                                                        } else {
488
                                                                                geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) mySym, cancel);
489
                                                                        }
490
                                                                }
491
                                                        }
492
                                                } else {
493
                                                        // else, just draw the symbol in its level
494
                                                        if (!bDrawCartographicSupport) {
495
                                                                geom.drawInts(graphics[zSort.getSymbolLevel(sym)], viewPort, sym, cancel);
496
                                                        } else {
497
                                                                geom.drawInts(graphics[zSort.getSymbolLevel(sym)], viewPort, dpi, (CartographicSupport) csSym, cancel);
498
                                                        }
499
                                                }
500

    
501
                                                // -- visual FX stuff
502
                                                // Cuando el offset!=0 se est? dibujando sobre el Layout y por tanto no tiene que ejecutar el siguiente c?digo.
503
                                                if (offset.getX()==0 && offset.getY()==0)
504
                                                        if ((System.currentTimeMillis() - time) > screenRefreshDelay) {
505
                                                                virtualBim = new BufferedImage(image.getWidth(),image.getHeight(),BufferedImage.TYPE_INT_ARGB);
506
                                                                virtualGraphics = virtualBim.createGraphics();
507
                                                                virtualGraphics.drawImage(image,0,0, null);
508
                                                                for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
509
                                                                        virtualGraphics.drawImage(imageLevels[i],0,0, null);
510
                                                                }
511
                                                                g.clearRect(0, 0, image.getWidth(), image.getHeight());
512
                                                                g.drawImage(virtualBim, 0, 0, null);
513
                                                                time = System.currentTimeMillis();
514
                                                        }
515
                                                // -- end visual FX stuff
516

    
517
                                        } else {
518
                                                // no ZSort, so there is only a map level, symbols are
519
                                                // just drawn.
520
                                                if (onePoint) {
521
                                                        if (x<0 || y<0 || x>= image.getWidth() || y>=image.getHeight()) continue;
522
                                                        image.setRGB(x, y, sym.getOnePointRgb());
523
                                                } else {
524
                                                        if (!bDrawCartographicSupport) {
525
                                                                geom.drawInts(g, viewPort, sym, cancel);
526
                                                        } else {
527
                                                                geom.drawInts(g, viewPort, dpi, csSym, cancel);
528
                                                        }
529
                                                }
530
                                        }
531
                            }
532

    
533
                            if (useZSort) {
534
                                    g.drawImage(image, 0, 0, null);
535
                                        g.translate(offset.getX(), offset.getY());
536
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
537
                                            g.drawImage(imageLevels[i],0,0, null);
538
                                            imageLevels[i] = null;
539
                                            graphics[i] = null;
540
                                    }
541
                                        g.translate(-offset.getX(), -offset.getY());
542
                                    imageLevels = null;
543
                                    graphics = null;
544
                            }
545
                            it.closeIterator();
546

    
547
                            if (bSymbolLevelError) {
548
                                    ((IVectorLegend) getLegend()).setZSort(null);
549
                            }
550

    
551
                    } catch (ReadDriverException e) {
552
                            this.setVisible(false);
553
                            this.setActive(false);
554
                            throw e;
555
                    }
556

    
557

    
558
            }
559
    }
560

    
561
           public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
562
            Cancellable cancel, double scale) throws ReadDriverException {
563
//            forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD = true;
564
//            if (!isUseStrategy()) {
565
                    _draw(image, g, viewPort, cancel, scale);
566
//            } else {
567
////                    moved up to FLayers
568
////                    if (isWithinScale(scale)) {
569
//
570
//
571
//                            // Las que solo tienen etiquetado sin pintar el shape,
572
//                            // no pasamos por ellas
573
//                            boolean bDrawShapes = true;
574
//                            if (legend instanceof SingleSymbolLegend) {
575
//                                    if (legend.getDefaultSymbol().isShapeVisible() == false)
576
//                                            bDrawShapes = false;
577
//                            }
578
//                            if (bDrawShapes) {
579
//                                    Strategy strategy = StrategyManager.getStrategy(this);
580
//                                    try {
581
//                                            prepareDrawing(image, g, viewPort);
582
//                                            strategy.draw(image, g, viewPort, cancel);
583
//                                    } catch (ReadDriverException e) {
584
//                                            this.setVisible(false);
585
//                                            this.setActive(false);
586
//                                            throw e;
587
//                                    }
588
//                            }
589
//                            if (getVirtualLayers() != null) {
590
//                                    getVirtualLayers().draw(image, g, viewPort, cancel, scale);
591
//                            }
592
////                    }
593
//            }
594
    }
595

    
596
    /**
597
     * Se llama antes de empezar a pintar.
598
     * Es ?til para preparar la cache a emplear, las leyendas, etc.
599
     * @param image
600
     * @param g
601
     * @param viewPort
602
     */
603
    private void prepareDrawing(BufferedImage image, Graphics2D g, ViewPort viewPort) {
604

    
605
    }
606

    
607
    public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
608
                    double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
609
            // TEST METHOD
610

    
611

    
612
                    /* SVN */
613

    
614
    /*        boolean bDrawShapes = true;
615
            if (legend instanceof SingleSymbolLegend) {
616
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
617
            }
618

619

620
            if (bDrawShapes) {
621
                    double dpi = 72;
622

623
                    PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
624
                    if (resolution.equals(PrintQuality.NORMAL)){
625
                            dpi = 300;
626
                    } else if (resolution.equals(PrintQuality.HIGH)){
627
                            dpi = 600;
628
                    } else if (resolution.equals(PrintQuality.DRAFT)){
629
                            dpi = 72;
630
                    }
631

632

633
                    try {
634
                            prepareDrawing(null, g, viewPort);
635
                            ArrayList<String> fieldList = new ArrayList<String>();
636
                            String[] aux;
637

638
                            // fields from legend
639
                            if (legend instanceof IClassifiedVectorLegend) {
640
                                    aux = ((IClassifiedVectorLegend) legend).
641
                                                                            getClassifyingFieldNames();
642
                                    for (int i = 0; i < aux.length; i++) {
643
                                            fieldList.add(aux[i]);
644
                                    }
645
                            }
646

647
                            // fields from labeling
648
                            if (isLabeled()) {
649
                                    aux = getLabelingStrategy().getUsedFields();
650
                                    for (int i = 0; i < aux.length; i++) {
651
                                            fieldList.add(aux[i]);
652
                                    }
653
                            }
654

655
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
656

657
                            // if layer has map levels it will use a ZSort
658
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
659

660

661
                            int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
662
                            for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
663
                                    // Get the iterator over the visible features
664
                                    IFeatureIterator it = getSource().getFeatureIterator(
665
                                                    viewPort.getAdjustedExtent(),
666
                                                    fieldList.toArray(new String[fieldList.size()]),
667
                                                    viewPort.getProjection(),
668
                                                    true);
669

670
                                    // Iteration over each feature
671
                                    while ( !cancel.isCanceled() && it.hasNext()) {
672
                                            IFeature feat = it.next();
673
                                            IGeometry geom = feat.getGeometry();
674

675
                                            // retreive the symbol associated to such feature
676
                                            ISymbol sym = legend.getSymbolByFeature(feat);
677

678
                                            if (useZSort) {
679
                                                    // Check if this symbol is a multilayer
680
                                                        if (sym instanceof IMultiLayerSymbol) {
681
                                                                // if so, get the layer corresponding to the current
682
                                                                // level. If none, continue to next iteration
683
                                                                IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
684
                                                                for (int i = 0; i < mlSym.getLayerCount(); i++) {
685
                                                                        ISymbol mySym = mlSym.getLayer(i);
686
                                                                        if (zSort.getSymbolLevel(mySym) == mapPass) {
687
                                                                                sym = mySym;
688
                                                                                break;
689
                                                                        }
690
                                                                        System.out.println("avoided layer "+i+"of symbol '"+mlSym.getDescription()+"' (pass "+mapPass+")");
691
                                                                }
692

693
                                                                if (sym == null) {
694
                                                                        continue;
695
                                                                }
696
                                                        } else {
697
                                                                // else, just draw the symbol in its level
698
                                                                if (zSort.getSymbolLevel(sym) != mapPass) {
699
                                                                        System.out.println("avoided single layer symbol '"+sym.getDescription()+"' (pass "+mapPass+")");
700
                                                                        continue;
701
                                                                }
702
                                                        }
703
                                            }
704

705
                                            // Check if this symbol is sized with CartographicSupport
706
                                            CartographicSupport csSym = null;
707
                                            int symbolType = sym.getSymbolType();
708
                                            boolean bDrawCartographicSupport = false;
709

710
                                            if (   symbolType == FShape.POINT
711
                                                            || symbolType == FShape.LINE
712
                                                            || sym instanceof CartographicSupport) {
713

714
                                                    csSym = (CartographicSupport) sym;
715
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
716
                                            }
717

718
                                            System.err.println("passada "+mapPass+" pinte s?mboll "+sym.getDescription());
719

720
                                            if (!bDrawCartographicSupport) {
721
                                                    geom.drawInts(g, viewPort, sym, null);
722
                                            } else {
723
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym);
724
                                            }
725

726
                                    }
727
                                    it.closeIterator();
728
                            }
729
                    } catch (ReadDriverException e) {
730
                            this.setVisible(false);
731
                            this.setActive(false);
732
                            throw e;
733
                    }
734
        */
735

    
736

    
737
            // TEST METHOD
738
            boolean bDrawShapes = true;
739
            if (legend instanceof SingleSymbolLegend) {
740
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
741
            }
742

    
743

    
744
            if (bDrawShapes) {
745

    
746
                    try {
747
                            double dpi = 72;
748

    
749
                            PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
750
                            if (resolution.equals(PrintQuality.NORMAL)){
751
                                    dpi = 300;
752
                            } else if (resolution.equals(PrintQuality.HIGH)){
753
                                    dpi = 600;
754
                            } else if (resolution.equals(PrintQuality.DRAFT)){
755
                                    dpi = 72;
756
                            }
757
                            ArrayList<String> fieldList = new ArrayList<String>();
758
                            String[] aux;
759

    
760
                            // fields from legend
761
                            if (legend instanceof IClassifiedVectorLegend) {
762
                                    aux = ((IClassifiedVectorLegend) legend).
763
                                    getClassifyingFieldNames();
764
                                    for (int i = 0; i < aux.length; i++) {
765
                                            fieldList.add(aux[i]);
766
                                    }
767
                            }
768
//
769
//                            // fields from labeling
770
//                            if (isLabeled()) {
771
//                                    aux = getLabelingStrategy().getUsedFields();
772
//                                    for (int i = 0; i < aux.length; i++) {
773
//                                            fieldList.add(aux[i]);
774
//                                    }
775
//                            }
776

    
777
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
778

    
779
                            // if layer has map levels it will use a ZSort
780
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
781

    
782

    
783
                            int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
784
                            for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
785
                                    // Get the iterator over the visible features
786
                                    IFeatureIterator it = getSource().getFeatureIterator(
787
                                                    viewPort.getAdjustedExtent(),
788
                                                    fieldList.toArray(new String[fieldList.size()]),
789
                                                    viewPort.getProjection(),
790
                                                    true);
791

    
792
                                    // Iteration over each feature
793
                                    while ( !cancel.isCanceled() && it.hasNext()) {
794
                                            IFeature feat = it.next();
795
                                            IGeometry geom = feat.getGeometry();
796

    
797
                                            // retreive the symbol associated to such feature
798
                                            ISymbol sym = legend.getSymbolByFeature(feat);
799

    
800
                                            if (useZSort) {
801
                                                    // Check if this symbol is a multilayer
802
                                                    if (sym instanceof IMultiLayerSymbol) {
803
                                                            // if so, get the layer corresponding to the current
804
                                                            // level. If none, continue to next iteration
805
                                                            IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
806
                                                            for (int i = 0; i < mlSym.getLayerCount(); i++) {
807
                                                                    ISymbol mySym = mlSym.getLayer(i);
808
                                                                    if (zSort.getSymbolLevel(mySym) == mapPass) {
809
                                                                            sym = mySym;
810
                                                                            break;
811
                                                                    }
812
                                                                    System.out.println("avoided layer "+i+"of symbol '"+mlSym.getDescription()+"' (pass "+mapPass+")");
813
                                                            }
814

    
815
                                                            if (sym == null) {
816
                                                                    continue;
817
                                                            }
818
                                                    } else {
819
                                                            // else, just draw the symbol in its level
820
                                                            if (zSort.getSymbolLevel(sym) != mapPass) {
821
                                                                    System.out.println("avoided single layer symbol '"+sym.getDescription()+"' (pass "+mapPass+")");
822
                                                                    continue;
823
                                                            }
824
                                                    }
825
                                            }
826

    
827
                                            // Check if this symbol is sized with CartographicSupport
828
                                            CartographicSupport csSym = null;
829
                                            int symbolType = sym.getSymbolType();
830
                                            boolean bDrawCartographicSupport = false;
831

    
832
                                            if (   symbolType == FShape.POINT
833
                                                            || symbolType == FShape.LINE
834
                                                            || sym instanceof CartographicSupport) {
835

    
836
                                                    csSym = (CartographicSupport) sym;
837
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
838
                                            }
839

    
840
                                            System.err.println("passada "+mapPass+" pinte s?mboll "+sym.getDescription());
841

    
842
                                            if (!bDrawCartographicSupport) {
843
                                                    geom.drawInts(g, viewPort, sym, null);
844
                                            } else {
845
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym, cancel);
846
                                            }
847

    
848
                                    }
849
                                    it.closeIterator();
850
                            }
851
                    } catch (ReadDriverException e) {
852
                            this.setVisible(false);
853
                            this.setActive(false);
854
                            throw e;
855
                    }
856
            }
857
    }
858

    
859

    
860
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
861
            double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
862
//            if (forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
863
                    _print(g, viewPort, cancel, scale, properties);
864
//            } else {
865
////                    moved up to Flayers
866
////                    if (isVisible() && isWithinScale(scale)) {
867
//                            Strategy strategy = StrategyManager.getStrategy(this);
868
//
869
//                            strategy.print(g, viewPort, cancel, properties);
870
//                            ILabelingStrategy labeling;
871
//                            if ( (labeling = getLabelingStrategy() ) != null) {
872
//                                    // contains labels
873
//                                    labeling.print(g, viewPort, cancel, properties);
874
//                            }
875
////                    }
876
//            }
877
    }
878

    
879
    public void deleteSpatialIndex() {
880
        //must we delete possible spatial indexes files?
881
        spatialIndex = null;
882
    }
883

    
884
   /**
885
    * <p>
886
    * Creates an spatial index associated to this layer.
887
    * The spatial index will used
888
    * the native projection of the layer, so if the layer is reprojected, it will
889
    * be ignored.
890
    * </p>
891
    * @param cancelMonitor instance of CancellableMonitorable that allows
892
    * to monitor progress of spatial index creation, and cancel the process
893
    */
894
    public void createSpatialIndex(CancellableMonitorable cancelMonitor){
895
         // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
896
        // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
897
        // para que acepten recorrer sin geometria, solo con rectangulos.
898

    
899
        //If this vectorial layer is based in a spatial database, the spatial
900
        //index is already implicit. We only will index file drivers
901
        ReadableVectorial va = getSource();
902
        //We must think in non spatial databases, like HSQLDB
903
        if(!(va instanceof VectorialFileAdapter)){
904
            return;
905
        }
906
        if (!(va.getDriver() instanceof BoundedShapes)) {
907
            return;
908
        }
909
        File file = ((VectorialFileAdapter) va).getFile();
910
        String fileName = file.getAbsolutePath();
911
        ISpatialIndex localCopy = null;
912
        try {
913
            va.start();
914
            localCopy = new QuadtreeGt2(fileName, "NM", va.getFullExtent(),
915
                    va.getShapeCount(), true);
916

    
917
        } catch (SpatialIndexException e1) {
918
            // Probably we dont have writing permissions
919
            String directoryName = System.getProperty("java.io.tmpdir");
920
            File newFile = new File(directoryName +
921
                    File.separator +
922
                    file.getName());
923
            String newFileName = newFile.getName();
924
            try {
925
                localCopy = new QuadtreeGt2(newFileName, "NM", va.getFullExtent(),
926
                        va.getShapeCount(), true);
927
            } catch (SpatialIndexException e) {
928
                // if we cant build a file based spatial index, we'll build
929
                // a pure memory spatial index
930
                localCopy = new QuadtreeJts();
931
            } catch (ReadDriverException e) {
932
                localCopy = new QuadtreeJts();
933
            }
934

    
935
        } catch(Exception e){
936
            e.printStackTrace();
937
        }//try
938
        BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
939
        try {
940
            for (int i=0; i < va.getShapeCount(); i++)
941
            {
942
                if(cancelMonitor != null){
943
                    if(cancelMonitor.isCanceled())
944
                        return;
945
                    cancelMonitor.reportStep();
946
                }
947
                Rectangle2D r = shapeBounds.getShapeBounds(i);
948
                if(r != null)
949
                    localCopy.insert(r, i);
950
            } // for
951
            va.stop();
952
            if(localCopy instanceof IPersistentSpatialIndex)
953
                ((IPersistentSpatialIndex) localCopy).flush();
954
            spatialIndex = localCopy;
955
            //vectorial adapter needs a reference to the spatial index, to solve
956
            //request for feature iteration based in spatial queries
957
            source.setSpatialIndex(spatialIndex);
958
        } catch (ReadDriverException e) {
959
            // TODO Auto-generated catch block
960
            e.printStackTrace();
961
        }
962
    }
963

    
964
    public void createSpatialIndex() {
965
        createSpatialIndex(null);
966
    }
967

    
968
    public void process(FeatureVisitor visitor, FBitSet subset)
969
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
970
        Strategy s = StrategyManager.getStrategy(this);
971
        s.process(visitor, subset);
972
    }
973

    
974
    public void process(FeatureVisitor visitor) throws ReadDriverException, VisitorException {
975
        Strategy s = StrategyManager.getStrategy(this);
976
        s.process(visitor);
977
    }
978

    
979
    public void process(FeatureVisitor visitor, Rectangle2D rect)
980
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
981
        Strategy s = StrategyManager.getStrategy(this);
982
        s.process(visitor, rect);
983
    }
984

    
985
    public FBitSet queryByRect(Rectangle2D rect) throws ReadDriverException, VisitorException {
986
        Strategy s = StrategyManager.getStrategy(this);
987

    
988
        return s.queryByRect(rect);
989
    }
990

    
991
    public FBitSet queryByPoint(Point2D p, double tolerance)
992
            throws ReadDriverException, VisitorException {
993
        Strategy s = StrategyManager.getStrategy(this);
994
        return s.queryByPoint(p, tolerance);
995
    }
996

    
997
    public FBitSet queryByShape(IGeometry g, int relationship)
998
            throws ReadDriverException, VisitorException {
999
        Strategy s = StrategyManager.getStrategy(this);
1000
        return s.queryByShape(g, relationship);
1001
    }
1002

    
1003
    public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancel) throws ReadDriverException, VisitorException {
1004
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(p);
1005
        FBitSet bs = queryByPoint(pReal, tolerance);
1006
        VectorialXMLItem[] item = new VectorialXMLItem[1];
1007
        item[0] = new VectorialXMLItem(bs, this);
1008

    
1009
        return item;
1010
    }
1011

    
1012
    public void setLegend(IVectorLegend r) throws LegendLayerException {
1013
            if (this.legend == r){
1014
                    return;
1015
            }
1016
                if (this.legend != null && this.legend.equals(r)){
1017
                        return;
1018
                }
1019
        IVectorLegend oldLegend = legend;
1020
        legend = r;
1021
        try {
1022
            legend.setDataSource(getRecordset());
1023
        } catch (FieldNotFoundException e1) {
1024
            throw new LegendLayerException(getName(),e1);
1025
        } catch (ReadDriverException e1) {
1026
            throw new LegendLayerException(getName(),e1);
1027
        } finally{
1028
                this.updateDrawVersion();
1029
        }
1030
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
1031
                oldLegend, legend);
1032
        callLegendChanged(e);
1033
    }
1034

    
1035
    /**
1036
     * Devuelve la Leyenda de la capa.
1037
     *
1038
     * @return Leyenda.
1039
     */
1040
    public ILegend getLegend() {
1041
        return legend;
1042
    }
1043

    
1044
    /**
1045
     * Devuelve el tipo de shape que contiene la capa.
1046
     *
1047
     * @return tipo de shape.
1048
     *
1049
     * @throws DriverException
1050
     */
1051
    public int getShapeType() throws ReadDriverException {
1052
        if (typeShape == -1) {
1053
            getSource().start();
1054
            typeShape = getSource().getShapeType();
1055
            getSource().stop();
1056
        }
1057

    
1058
        return typeShape;
1059
    }
1060

    
1061
    public XMLEntity getXMLEntity() throws XMLException {
1062
        if (!this.isAvailable() && this.orgXMLEntity != null) {
1063
            return this.orgXMLEntity;
1064
        }
1065
        XMLEntity xml = super.getXMLEntity();
1066
        if (getLegend()!=null)
1067
            xml.addChild(getLegend().getXMLEntity());
1068
        try {
1069
            if (getRecordset()!=null)
1070
                xml.addChild(getRecordset().getSelectionSupport().getXMLEntity());
1071
        } catch (ReadDriverException e1) {
1072
            e1.printStackTrace();
1073
            throw new XMLException(e1);
1074
        }
1075
        // Repongo el mismo ReadableVectorial m?s abajo para cuando se guarda el proyecto.
1076
        ReadableVectorial rv=getSource();
1077
        xml.putProperty("type", "vectorial");
1078
        if (source instanceof VectorialEditableAdapter) {
1079
            setSource(((VectorialEditableAdapter) source).getOriginalAdapter());
1080
        }
1081
        if (source instanceof VectorialFileAdapter) {
1082
            xml.putProperty("type", "vectorial");
1083
            xml.putProperty("file", ((VectorialFileAdapter) source)
1084
                    .getFile());
1085
            try {
1086
                xml.putProperty("recordset-name", source.getRecordset()
1087
                        .getName());
1088
            } catch (ReadDriverException e) {
1089
                throw new XMLException(e);
1090
            } catch (RuntimeException e) {
1091
                e.printStackTrace();
1092
            }
1093
        } else if (source instanceof VectorialDBAdapter) {
1094
            xml.putProperty("type", "vectorial");
1095

    
1096
            IVectorialDatabaseDriver dbDriver = (IVectorialDatabaseDriver) source
1097
                    .getDriver();
1098

    
1099
            // Guardamos el nombre del driver para poder recuperarlo
1100
            // con el DriverManager de Fernando.
1101
            xml.putProperty("db", dbDriver.getName());
1102
            try {
1103
                xml.putProperty("recordset-name", source.getRecordset()
1104
                        .getName());
1105
            } catch (ReadDriverException e) {
1106
                throw new XMLException(e);
1107
            } catch (RuntimeException e) {
1108
                e.printStackTrace();
1109
            }
1110
            xml.addChild(dbDriver.getXMLEntity()); // Tercer child. Antes hemos
1111
                                                    // metido la leyenda y el
1112
                                                    // selection support
1113
        } else if (source instanceof VectorialAdapter) {
1114
            // Se supone que hemos hecho algo gen?rico.
1115
            xml.putProperty("type", "vectorial");
1116

    
1117
            VectorialDriver driver = source.getDriver();
1118

    
1119
            // Guardamos el nombre del driver para poder recuperarlo
1120
            // con el DriverManager de Fernando.
1121
            xml.putProperty("other", driver.getName());
1122
            // try {
1123
            try {
1124
                xml.putProperty("recordset-name", source.getRecordset()
1125
                        .getName());
1126
            } catch (ReadDriverException e) {
1127
                throw new XMLException(e);
1128
            } catch (RuntimeException e) {
1129
                e.printStackTrace();
1130
            }
1131
            if (driver instanceof IPersistence) {
1132
                // xml.putProperty("className", driver.getClass().getName());
1133
                    IPersistence persist = (IPersistence) driver;
1134
                xml.addChild(persist.getXMLEntity()); // Tercer child. Antes
1135
                                                        // hemos metido la
1136
                                                        // leyenda y el
1137
                                                        // selection support
1138
            }
1139
        }
1140
        if (rv!=null)
1141
            setSource(rv);
1142
        xml.putProperty("driverName", source.getDriver().getName());
1143
        if (bHasJoin)
1144
            xml.putProperty("hasJoin", "true");
1145

    
1146
        // properties from ILabelable
1147
        xml.putProperty("isLabeled", isLabeled);
1148
        if (strategy != null) {
1149
            XMLEntity strategyXML = strategy.getXMLEntity();
1150
            strategyXML.putProperty("Strategy", strategy.getClassName());
1151
            xml.addChild(strategy.getXMLEntity());
1152
        }
1153
        xml.addChild(getLinkProperties().getXMLEntity());
1154
        return xml;
1155
    }
1156

    
1157
    /**
1158
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1159
     */
1160
    public void setXMLEntity03(XMLEntity xml) throws XMLException {
1161

    
1162
        super.setXMLEntity(xml);
1163
        legend = LegendFactory.createFromXML03(xml.getChild(0));
1164

    
1165
        try {
1166
            setLegend(legend);
1167
        } catch (LegendLayerException e) {
1168
            throw new XMLException(e);
1169
        }
1170

    
1171
        try {
1172
            getRecordset().getSelectionSupport()
1173
                    .setXMLEntity03(xml.getChild(1));
1174
        } catch (ReadDriverException e) {
1175
            e.printStackTrace();
1176
        }
1177
    }
1178

    
1179
    /*
1180
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1181
     */
1182
    public void setXMLEntity(XMLEntity xml) throws XMLException {
1183
        try {
1184
                    super.setXMLEntity(xml);
1185
                    XMLEntity legendXML = xml.getChild(0);
1186
                    IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1187
                    /* (jaume) begin patch;
1188
                     * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1189
                     * no longer managed by the Legend but by the ILabelingStrategy. The
1190
                     * following allows restoring older projects' labelings.
1191
                     */
1192
                    if (legendXML.contains("labelFieldName")) {
1193
                            String labelTextField = legendXML.getStringProperty("labelFieldName");
1194
                            if (labelTextField != null) {
1195
                                    AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1196
                                    labeling.setLayer(this);
1197
                                    labeling.setTextField(legendXML.getStringProperty("labelFieldName"));
1198
                                    labeling.setHeightField(legendXML.getStringProperty("labelHeightFieldName"));
1199
                                    labeling.setRotationField(legendXML.getStringProperty("labelRotationFieldName"));
1200
                                    this.setLabelingStrategy(labeling);
1201
                                    this.setIsLabeled(true);
1202
                            }
1203
                    }
1204
                    /* end patch */
1205
                    try {
1206
                            getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1207
                            // JMVIVO: Esto sirve para algo????
1208
                            /*
1209
                             *  Jaume: si, para restaurar el selectable datasource cuando se
1210
                             *  clona la capa, cuando se carga de un proyecto. Si no esta ya
1211
                             *  no se puede ni hacer consultas sql, ni hacer selecciones,
1212
                             *  ni usar la mayor parte de las herramientas.
1213
                             *
1214
                             *  Lo vuelvo a poner.
1215
                             */
1216

    
1217
                            String recordsetName = xml.getStringProperty("recordset-name");
1218

    
1219
//                            SelectableDataSource sds = new SelectableDataSource(LayerFactory
1220
//                                            .getDataSourceFactory().createRandomDataSource(
1221
//                                                            recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
1222

    
1223
                            LayerFactory.getDataSourceFactory().changeDataSourceName(
1224
                                            getSource().getRecordset().getName(), recordsetName);
1225
                            SelectableDataSource sds = new SelectableDataSource(LayerFactory
1226
                                            .getDataSourceFactory().createRandomDataSource(
1227
                                                            recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
1228

    
1229
                    } catch (NoSuchTableException e1) {
1230
                            this.setAvailable(false);
1231
                            throw new XMLException(e1);
1232
                    } catch (ReadDriverException e1) {
1233
                            this.setAvailable(false);
1234
                            throw new XMLException(e1);
1235
                    }
1236
                    // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1237
                    // el final
1238
                    // de la lectura del proyecto
1239
                    if (xml.contains("hasJoin")) {
1240
                            setIsJoined(true);
1241
                            PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1242
                    } else {
1243
                            try {
1244
                                    setLegend(leg);
1245
                            } catch (LegendLayerException e) {
1246
                                    throw new XMLException(e);
1247
                            }
1248
                    }
1249

    
1250
                    // set properties for ILabelable
1251
                    XMLEntity labelingXML = xml.firstChild("id", "LabelingStrategy");
1252
                    if (labelingXML!= null) {
1253
                            isLabeled = true;
1254
                            try {
1255
                                    this.strategy = LabelingFactory.createStrategyFromXML(labelingXML, this);
1256
                            } catch (NotExistInXMLEntity neXMLEX) {
1257
                                    // no strategy was set, just continue;
1258
                                    logger.warn("Reached what should be unreachable code");
1259
                            }
1260
                    } else {
1261
                            isLabeled = false;
1262
                    }
1263

    
1264
                    XMLEntity xmlLinkProperties=xml.firstChild("typeChild","linkProperties");
1265
                    if (xmlLinkProperties != null){
1266
                            getLinkProperties().setXMLEntity(xmlLinkProperties);
1267
                    }
1268

    
1269
            } catch (XMLException e) {
1270
                    this.setAvailable(false);
1271
                    this.orgXMLEntity = xml;
1272
            } catch (Exception e) {
1273
                    e.printStackTrace();
1274
                    this.setAvailable(false);
1275
                    this.orgXMLEntity = xml;
1276

    
1277
            }
1278

    
1279

    
1280
    }
1281

    
1282
    public void setXMLEntityNew(XMLEntity xml) throws XMLException {
1283
        try {
1284
            super.setXMLEntity(xml);
1285

    
1286
            XMLEntity legendXML = xml.getChild(0);
1287
            IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1288
            /* (jaume) begin patch;
1289
             * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1290
             * no longer managed by the Legend but by the ILabelingStrategy. The
1291
             * following allows restoring older projects' labelings.
1292
             */
1293
            if (legendXML.contains("labelFieldHeight")) {
1294
                AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1295
                labeling.setLayer(this);
1296
                labeling.setTextField(legendXML.getStringProperty("labelFieldHeight"));
1297
                labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
1298
                this.setLabelingStrategy(labeling);
1299
                this.setIsLabeled(true);
1300
              }
1301
            /* end patch */
1302
            try {
1303
                getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1304

    
1305
                this.setLoadSelection(xml.getChild(1));
1306
            } catch (ReadDriverException e1) {
1307
                this.setAvailable(false);
1308
                throw new XMLException(e1);
1309
            }
1310
            // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1311
            // el final
1312
            // de la lectura del proyecto
1313
            if (xml.contains("hasJoin")) {
1314
                setIsJoined(true);
1315
                PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1316
            } else {
1317
                this.setLoadLegend(leg);
1318
            }
1319

    
1320
        } catch (XMLException e) {
1321
            this.setAvailable(false);
1322
            this.orgXMLEntity = xml;
1323
        } catch (Exception e) {
1324
            this.setAvailable(false);
1325
            this.orgXMLEntity = xml;
1326
        }
1327

    
1328

    
1329
    }
1330

    
1331

    
1332
    /**
1333
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
1334
     * identifiquen la capa.
1335
     *
1336
     * @return DOCUMENT ME!
1337
     */
1338
    public String toString() {
1339
        /*
1340
         * Se usa internamente para que la parte de datos identifique de forma
1341
         * un?voca las tablas
1342
         */
1343
        String ret = super.toString();
1344

    
1345
        return "layer" + ret.substring(ret.indexOf('@') + 1);
1346
    }
1347

    
1348
    public boolean isJoined() {
1349
        return bHasJoin;
1350
    }
1351

    
1352
    /**
1353
     * Returns if a layer is spatially indexed
1354
     *
1355
     * @return if this layer has the ability to proces spatial queries without
1356
     *         secuential scans.
1357
     */
1358
    public boolean isSpatiallyIndexed() {
1359
        ReadableVectorial source = getSource();
1360
        if (source instanceof ISpatialDB)
1361
            return true;
1362

    
1363
//FIXME azabala
1364
/*
1365
 * Esto es muy dudoso, y puede cambiar.
1366
 * Estoy diciendo que las que no son fichero o no son
1367
 * BoundedShapes estan indexadas. Esto es mentira, pero
1368
 * as? quien pregunte no querr? generar el indice.
1369
 * Esta por ver si interesa generar el indice para capas
1370
 * HSQLDB, WFS, etc.
1371
 */
1372
        if(!(source instanceof VectorialFileAdapter)){
1373
            return true;
1374
        }
1375
        if (!(source.getDriver() instanceof BoundedShapes)) {
1376
            return true;
1377
        }
1378

    
1379
        if (getISpatialIndex() != null)
1380
            return true;
1381
        return false;
1382
    }
1383

    
1384
    public void setIsJoined(boolean hasJoin) {
1385
        bHasJoin = hasJoin;
1386
    }
1387

    
1388
    /**
1389
     * @return Returns the spatialIndex.
1390
     */
1391
    public ISpatialIndex getISpatialIndex() {
1392
        return spatialIndex;
1393
    }
1394
    /**
1395
     * Sets the spatial index. This could be useful if, for some
1396
     * reasons, you want to work with a distinct spatial index
1397
     * (for example, a spatial index which could makes nearest
1398
     * neighbour querys)
1399
     * @param spatialIndex
1400
     */
1401
    public void setISpatialIndex(ISpatialIndex spatialIndex){
1402
        this.spatialIndex = spatialIndex;
1403
    }
1404

    
1405
    public SelectableDataSource getRecordset() throws ReadDriverException {
1406
        if (!this.isAvailable()) return null;
1407
        if (sds == null) {
1408

    
1409
                SelectableDataSource ds = source.getRecordset();
1410

    
1411
                if (ds == null) {
1412
                    return null;
1413
                }
1414

    
1415
                sds = ds;
1416
                sds.setSelectionSupport(selectionSupport);
1417
                selectionSupport.addSelectionListener(this);
1418

    
1419
        }
1420
        return sds;
1421
    }
1422

    
1423
    public void setEditing(boolean b) throws StartEditionLayerException {
1424
        super.setEditing(b);
1425
        try {
1426
            if (b) {
1427
                VectorialEditableAdapter vea = null;
1428
                // TODO: Qu? pasa si hay m?s tipos de adapters?
1429
                // FJP: Se podr?a pasar como argumento el
1430
                // VectorialEditableAdapter
1431
                // que se quiera usar para evitar meter c?digo aqu? de este
1432
                // estilo.
1433
                if (getSource() instanceof VectorialDBAdapter) {
1434
                    vea = new VectorialEditableDBAdapter();
1435
                } else if (this instanceof FLyrAnnotation) {
1436
                    vea = new AnnotationEditableAdapter(
1437
                            (FLyrAnnotation) this);
1438
                } else {
1439
                    vea = new VectorialEditableAdapter();
1440
                }
1441
                vea.addEditionListener(this);
1442
                vea.setOriginalVectorialAdapter(getSource());
1443
//                                azo: implementations of readablevectorial need
1444
                //references of projection and spatial index
1445
                vea.setProjection(getProjection());
1446
                vea.setSpatialIndex(spatialIndex);
1447

    
1448

    
1449
                // /vea.setSpatialIndex(getSpatialIndex());
1450
                // /vea.setFullExtent(getFullExtent());
1451
                vea.setCoordTrans(getCoordTrans());
1452
                vea.startEdition(EditionEvent.GRAPHIC);
1453
                setSource(vea);
1454
                getRecordset().setSelectionSupport(
1455
                        vea.getOriginalAdapter().getRecordset()
1456
                                .getSelectionSupport());
1457

    
1458
            } else {
1459
                VectorialEditableAdapter vea = (VectorialEditableAdapter) getSource();
1460
                vea.removeEditionListener(this);
1461
                setSource(vea.getOriginalAdapter());
1462
            }
1463
            // Si tenemos una leyenda, hay que pegarle el cambiazo a su
1464
            // recordset
1465
            setRecordset(getSource().getRecordset());
1466
            if (getLegend() instanceof IVectorLegend) {
1467
                IVectorLegend ley = (IVectorLegend) getLegend();
1468
                ley.setDataSource(getSource().getRecordset());
1469
                // Esto lo pongo para evitar que al dibujar sobre un
1470
                // dxf, dwg, o dgn no veamos nada. Es debido al checkbox
1471
                // de la leyenda de textos "dibujar solo textos".
1472
//jaume
1473
//                                if (!(getSource().getDriver() instanceof IndexedShpDriver)){
1474
//                                        FSymbol symbol=new FSymbol(getShapeType());
1475
//                                        symbol.setFontSizeInPixels(false);
1476
//                                        symbol.setFont(new Font("SansSerif", Font.PLAIN, 9));
1477
//                                        Color color=symbol.getColor();
1478
//                                        int alpha=symbol.getColor().getAlpha();
1479
//                                        if (alpha>250) {
1480
//                                                symbol.setColor(new Color(color.getRed(),color.getGreen(),color.getBlue(),100));
1481
//                                        }
1482
//                                        ley.setDefaultSymbol(symbol);
1483
//                                }
1484
//jaume//
1485
                ley.useDefaultSymbol(true);
1486
            }
1487
        } catch (ReadDriverException e) {
1488
            throw new StartEditionLayerException(getName(),e);
1489
        } catch (FieldNotFoundException e) {
1490
            throw new StartEditionLayerException(getName(),e);
1491
        } catch (StartWriterVisitorException e) {
1492
            throw new StartEditionLayerException(getName(),e);
1493
        }
1494

    
1495
        setSpatialCacheEnabled(b);
1496
        callEditionChanged(LayerEvent
1497
                .createEditionChangedEvent(this, "edition"));
1498

    
1499
    }
1500

    
1501
    /**
1502
     * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
1503
     * forma, podr?s poner leyendas basadas en el nuevo recordset
1504
     *
1505
     * @param newSds
1506
     */
1507
    public void setRecordset(SelectableDataSource newSds) {
1508
            // TODO: Deberiamos hacer comprobaciones del cambio
1509
        sds = newSds;
1510
        sds.setSelectionSupport(selectionSupport);
1511
                selectionSupport.addSelectionListener(this);
1512
                this.updateDrawVersion();
1513
    }
1514

    
1515
    public void clearSpatialCache()
1516
    {
1517
        spatialCache.clearAll();
1518
    }
1519

    
1520
    public boolean isSpatialCacheEnabled() {
1521
        return spatialCacheEnabled;
1522
    }
1523

    
1524
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1525
        this.spatialCacheEnabled = spatialCacheEnabled;
1526
    }
1527

    
1528
    public SpatialCache getSpatialCache() {
1529
        return spatialCache;
1530
    }
1531

    
1532
    /**
1533
     * Siempre es un numero mayor de 1000
1534
     * @param maxFeatures
1535
     */
1536
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
1537
        if (maxFeatures > spatialCache.maxFeatures)
1538
            spatialCache.setMaxFeatures(maxFeatures);
1539

    
1540
    }
1541

    
1542
    /**
1543
     * This method returns a boolean that is used by the FPopMenu
1544
     * to make visible the properties menu or not. It is visible by
1545
     * default, and if a later don't have to show this menu only
1546
     * has to override this method.
1547
     * @return
1548
     * If the properties menu is visible (or not)
1549
     */
1550
    public boolean isPropertiesMenuVisible(){
1551
        return true;
1552
    }
1553

    
1554
    public void reload() throws ReloadLayerException {
1555
        this.setAvailable(true);
1556
        super.reload();
1557
        this.updateDrawVersion();
1558
        try {
1559
            this.source.getDriver().reload();
1560
            if (this.getLegend() == null) {
1561
                if (this.getRecordset().getDriver() instanceof WithDefaultLegend) {
1562
                    WithDefaultLegend aux = (WithDefaultLegend) this.getRecordset().getDriver();
1563
                    this.setLegend((IVectorLegend) aux.getDefaultLegend());
1564
                    this.setLabelingStrategy(aux.getDefaultLabelingStrategy());
1565
                } else {
1566
                    this.setLegend(LegendFactory.createSingleSymbolLegend(
1567
                            this.getShapeType()));
1568
                }
1569
            }
1570

    
1571
        } catch (LegendLayerException e) {
1572
            this.setAvailable(false);
1573
            throw new ReloadLayerException(getName(),e);
1574
        } catch (ReadDriverException e) {
1575
            this.setAvailable(false);
1576
            throw new ReloadLayerException(getName(),e);
1577
        }
1578

    
1579
    }
1580

    
1581
    protected void setLoadSelection(XMLEntity xml) {
1582
        this.loadSelection = xml;
1583
    }
1584

    
1585
    protected void setLoadLegend(IVectorLegend legend) {
1586
        this.loadLegend = legend;
1587
    }
1588

    
1589
    protected void putLoadSelection() throws XMLException {
1590
        if (this.loadSelection == null) return;
1591
        try {
1592
            this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1593
        } catch (ReadDriverException e) {
1594
            throw new XMLException(e);
1595
        }
1596
        this.loadSelection = null;
1597

    
1598
    }
1599
    protected void putLoadLegend() throws LegendLayerException {
1600
        if (this.loadLegend == null) return;
1601
        this.setLegend(this.loadLegend);
1602
        this.loadLegend = null;
1603
    }
1604

    
1605
    protected void cleanLoadOptions() {
1606
        this.loadLegend = null;
1607
        this.loadSelection = null;
1608
    }
1609

    
1610
    public boolean isWritable() {
1611
        VectorialDriver drv = getSource().getDriver();
1612
        if (!drv.isWritable())
1613
            return false;
1614
        if (drv instanceof IWriteable)
1615
        {
1616
            IWriter writer = ((IWriteable)drv).getWriter();
1617
            if (writer != null)
1618
            {
1619
                if (writer instanceof ISpatialWriter)
1620
                    return true;
1621
            }
1622
        }
1623
        return false;
1624

    
1625
    }
1626

    
1627
    public FLayer cloneLayer() throws Exception {
1628
        FLyrVect clonedLayer = new FLyrVect();
1629
        clonedLayer.setSource(getSource());
1630
        if (isJoined()) {
1631
                        clonedLayer.setIsJoined(true);
1632
                        clonedLayer.setRecordset(getRecordset());
1633
                }
1634
        clonedLayer.setVisible(isVisible());
1635
        clonedLayer.setISpatialIndex(getISpatialIndex());
1636
        clonedLayer.setName(getName());
1637
        clonedLayer.setCoordTrans(getCoordTrans());
1638

    
1639
        clonedLayer.setLegend((IVectorLegend)getLegend().cloneLegend());
1640

    
1641
        clonedLayer.setIsLabeled(isLabeled());
1642
        clonedLayer.setLabelingStrategy(getLabelingStrategy());
1643

    
1644
        return clonedLayer;
1645
    }
1646

    
1647

    
1648
    private boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, double dpi, CartographicSupport csSym, IGeometry geom, int[] xyCoords) {
1649
            return isOnePoint(graphicsTransform, viewPort, geom, xyCoords) && csSym.getCartographicSize(viewPort, dpi, (FShape)geom.getInternalShape()) <= 1;
1650
    }
1651

    
1652
    private boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, IGeometry geom, int[] xyCoords) {
1653
            boolean onePoint = false;
1654
            int type=geom.getGeometryType() % FShape.Z;
1655
            if (type!=FShape.POINT && type!=FShape.MULTIPOINT) {
1656

    
1657
                        Rectangle2D geomBounds = geom.getBounds2D();
1658

    
1659
                        ICoordTrans ct = getCoordTrans();
1660

    
1661
                        if (ct!=null) {
1662
//                                geomBounds = ct.getInverted().convert(geomBounds);
1663
                                geomBounds = ct.convert(geomBounds);
1664
                        }
1665

    
1666
                        double dist1Pixel = viewPort.getDist1pixel();
1667

    
1668
                        onePoint = (geomBounds.getWidth()  <= dist1Pixel
1669
                                         && geomBounds.getHeight() <= dist1Pixel);
1670

    
1671
                        if (onePoint) {
1672
                                // avoid out of range exceptions
1673
                                FPoint2D p = new FPoint2D(geomBounds.getMinX(), geomBounds.getMinY());
1674
                                p.transform(viewPort.getAffineTransform());
1675
                                p.transform(graphicsTransform);
1676
                                xyCoords[0] = (int) p.getX();
1677
                                xyCoords[1] = (int) p.getY();
1678

    
1679
                        }
1680

    
1681
                }
1682
            return onePoint;
1683
    }
1684
    /*
1685
     * jaume. Stuff from ILabeled.
1686
     */
1687
    private boolean isLabeled;
1688
    private ILabelingStrategy strategy;
1689

    
1690
    public boolean isLabeled() {
1691
        return isLabeled;
1692
    }
1693

    
1694
    public void setIsLabeled(boolean isLabeled) {
1695
        this.isLabeled = isLabeled;
1696
    }
1697

    
1698
    public ILabelingStrategy getLabelingStrategy() {
1699
        return strategy;
1700
    }
1701

    
1702
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1703
        this.strategy = strategy;
1704
    }
1705

    
1706
    public void drawLabels(BufferedImage image, Graphics2D g, ViewPort viewPort,
1707
                    Cancellable cancel, double scale, double dpi) throws ReadDriverException {
1708
        if (strategy!=null && isWithinScale(scale)) {
1709
                strategy.draw(image, g, viewPort, cancel, dpi);
1710
        }
1711
    }
1712
    public void printLabels(Graphics2D g, ViewPort viewPort,
1713
                    Cancellable cancel, double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
1714
        if (strategy!=null) {
1715
                strategy.print(g, viewPort, cancel, properties);
1716
        }
1717
    }
1718

    
1719

    
1720
    //M?todos para el uso de HyperLinks en capas FLyerVect
1721

    
1722
    /**
1723
     * Return true, because a Vectorial Layer supports HyperLink
1724
     */
1725
    public boolean allowLinks()
1726
    {
1727
            return true;
1728
    }
1729

    
1730
    /**
1731
         * Returns an instance of AbstractLinkProperties that contains the information
1732
         * of the HyperLink
1733
         * @return Abstra
1734
         */
1735
    public AbstractLinkProperties getLinkProperties()
1736
    {
1737
            return linkProperties;
1738
    }
1739

    
1740
    /**
1741
         * Provides an array with URIs. Returns one URI by geometry that includes the point
1742
         * in its own geometry limits with a allowed tolerance.
1743
         * @param layer, the layer
1744
         * @param point, the point to check that is contained or not in the geometries in the layer
1745
         * @param tolerance, the tolerance allowed. Allowed margin of error to detect if the  point
1746
         *                 is contained in some geometries of the layer
1747
         * @return
1748
         */
1749
    public URI[] getLink(Point2D point, double tolerance)
1750
    {
1751
            //return linkProperties.getLink(this)
1752
            return linkProperties.getLink(this,point,tolerance);
1753
    }
1754
//    /**
1755
//     * @deprecated Don?t use Strategy, you should be use iterators.
1756
//     */
1757
//        public boolean isUseStrategy() {
1758
//                return useStrategy;
1759
//        }
1760
//        /**
1761
//     * @deprecated Don?t use Strategy, you should be use iterators.
1762
//     */
1763
//        public void setUseStrategy(boolean useStrategy) {
1764
//                this.useStrategy = useStrategy;
1765
//        }
1766
//
1767
//        @Override
1768
//        public void load() throws LoadLayerException {
1769
//                super.load();
1770
//                useStrategy=forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD;
1771
//        }
1772

    
1773
        public void selectionChanged(SelectionEvent e) {
1774
                this.updateDrawVersion();
1775
        }
1776

    
1777
        public void afterFieldEditEvent(AfterFieldEditEvent e) {
1778

    
1779
        }
1780

    
1781
        public void afterRowEditEvent(IRow feat, AfterRowEditEvent e) {
1782
                this.updateDrawVersion();
1783

    
1784
        }
1785

    
1786
        public void beforeFieldEditEvent(BeforeFieldEditEvent e) {
1787

    
1788
        }
1789

    
1790
        public void beforeRowEditEvent(IRow feat, BeforeRowEditEvent e) {
1791

    
1792
        }
1793

    
1794
        public void processEvent(EditionEvent e) {
1795
                if (e.getChangeType()== e.ROW_EDITION){
1796
                        this.updateDrawVersion();
1797
                }
1798

    
1799
        }
1800

    
1801
 }