Statistics
| Revision:

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

History | View | Annotate | Download (70.7 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
import org.gvsig.exceptions.BaseException;
59

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

    
139
/**
140
 * Capa b?sica Vectorial.
141
 *
142
 * @author Fernando Gonz?lez Cort?s
143
 */
144

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

    
159
    /** Leyenda de la capa vectorial */
160
    private IVectorLegend legend;
161
    private int typeShape = -1;
162
    private ReadableVectorial source;
163
    private SelectableDataSource sds;
164
    private SelectionSupport selectionSupport = new SelectionSupport();
165
    private SpatialCache spatialCache = new SpatialCache();
166
    private boolean spatialCacheEnabled = false;
167

    
168
    /**
169
     * An implementation of gvSIG spatial index
170
     */
171
    protected ISpatialIndex spatialIndex = null;
172
    private boolean bHasJoin = false;
173
    private XMLEntity orgXMLEntity = null;
174
    private XMLEntity loadSelection = null;
175
    private IVectorLegend loadLegend = null;
176

    
177
    //Lo a?ado. Caracter?sticas de HyperEnlace (LINK)
178
    private FLyrVectLinkProperties linkProperties=new FLyrVectLinkProperties();
179
    //private ArrayList linkProperties=null;
180

    
181
    /**
182
     * Devuelve el VectorialAdapater de la capa.
183
     *
184
     * @return VectorialAdapter.
185
     */
186
    public ReadableVectorial getSource() {
187
        if (!this.isAvailable()) return null;
188
        return source;
189
    }
190

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

    
201

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

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

    
243
    }
244

    
245
    /**
246
     * Checks if it has associated an external spatial index
247
     * (an spatial index file).
248
     *
249
     * It looks for it in main file path, or in temp system path.
250
     * If main file is rivers.shp, it looks for a file called
251
     * rivers.shp.qix.
252

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

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

    
296
    public Rectangle2D getFullExtent() throws ReadDriverException, ExpansionFileReadException {
297
            Rectangle2D rAux;
298
            source.start();
299
            rAux = (Rectangle2D)source.getFullExtent().clone();
300
            source.stop();
301

    
302
            // Si existe reproyecci?n, reproyectar el extent
303
            ICoordTrans ct = getCoordTrans();
304
                        try{
305
                    if (ct != null) {
306
                        Point2D pt1 = new Point2D.Double(rAux.getMinX(), rAux.getMinY());
307
                        Point2D pt2 = new Point2D.Double(rAux.getMaxX(), rAux.getMaxY());
308
                        pt1 = ct.convert(pt1, null);
309
                        pt2 = ct.convert(pt2, null);
310
                        rAux = new Rectangle2D.Double();
311
                        rAux.setFrameFromDiagonal(pt1, pt2);
312
                    }
313
                        }catch (IllegalStateException e) {
314
                                this.setAvailable(false);
315
                                this.addError(new ReprojectLayerException(getName(), e));
316
                        }
317
            //Esto es para cuando se crea una capa nueva con el fullExtent de ancho y alto 0.
318
            if (rAux.getWidth()==0 && rAux.getHeight()==0) {
319
                rAux=new Rectangle2D.Double(0,0,100,100);
320
            }
321

    
322
            return rAux;
323
    }
324

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

    
344

    
345

    
346
            if (bDrawShapes) {
347
                    boolean cacheFeatures = isSpatialCacheEnabled();
348
                    SpatialCache cache = null;
349
                    if (cacheFeatures) {
350
                            getSpatialCache().clearAll();
351
                            cache = getSpatialCache();
352
                    }
353

    
354
                    try {
355
                            ArrayList<String> fieldList = new ArrayList<String>();
356

    
357
                            // fields from legend
358
                            String[] aux = null;
359

    
360
                            if (legend instanceof IClassifiedVectorLegend) {
361
                                    aux = ((IClassifiedVectorLegend) legend).getClassifyingFieldNames();
362
                                    if (aux!=null) {
363
                                            for (int i = 0; i < aux.length; i++) {
364
                                                            fieldList.add(aux[i]);
365
                                            }
366
                                    }
367
                            }
368
                            // Get the iterator over the visible features
369
                            IFeatureIterator it = getSource().getFeatureIterator(
370
                                            viewPort.getAdjustedExtent(),
371
                                            fieldList.toArray(new String[fieldList.size()]),
372
                                            viewPort.getProjection(),
373
                                            true);
374

    
375
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
376

    
377
                            boolean bSymbolLevelError = false;
378

    
379
                            // if layer has map levels it will use a ZSort
380
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
381

    
382
                            // -- visual FX stuff
383
                            long time = System.currentTimeMillis();
384
                            BufferedImage virtualBim;
385
                            Graphics2D virtualGraphics;
386

    
387
                            // render temporary map each screenRefreshRate milliseconds;
388
                            int screenRefreshDelay = (int) ((1D/MapControl.getDrawFrameRate())*3*1000);
389
                            BufferedImage[] imageLevels = null;
390
                            Graphics2D[] graphics = null;
391
                            if (useZSort) {
392
                                    imageLevels = new BufferedImage[zSort.getLevelCount()];
393
                                    graphics = new Graphics2D[imageLevels.length];
394
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
395
                                            imageLevels[i] = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
396
                                            graphics[i] = imageLevels[i].createGraphics();
397
                                            graphics[i].setTransform(g.getTransform());
398
                                            graphics[i].setRenderingHints(g.getRenderingHints());
399
                                    }
400
                            }
401
                            // -- end visual FX stuff
402

    
403

    
404
                            // Iteration over each feature
405
                            while ( !cancel.isCanceled() && it.hasNext()) {
406
                                    IFeature feat = it.next();
407
                                    IGeometry geom = feat.getGeometry();
408

    
409
                                    if (cacheFeatures) {
410
                                            if (cache.getMaxFeatures() >= cache.size()) {
411
                                                    // already reprojected
412
                                                    cache.insert(geom.getBounds2D(), geom);
413
                                            }
414
                                    }
415

    
416
                                    // retrieve the symbol associated to such feature
417
                                    ISymbol sym = legend.getSymbolByFeature(feat);
418

    
419
                                    if (sym == null) continue;
420

    
421
                                    //C?digo para poder acceder a los ?ndices para ver si est? seleccionado un Feature
422
                                    ReadableVectorial rv=getSource();
423
                                    int selectionIndex=-1;
424
                                    if (rv instanceof ISpatialDB){
425
                                            selectionIndex = ((ISpatialDB)rv).getRowIndexByFID(feat);
426
                                    }else{
427
                                            selectionIndex = Integer.parseInt(feat.getID());
428
                                    }
429
                                    if (selectionIndex!=-1) {
430
                                            if (selectionSupport.isSelected(selectionIndex)) {
431
                                                    sym = sym.getSymbolForSelection();
432
                                            }
433
                                    }
434

    
435
                                    // Check if this symbol is sized with CartographicSupport
436
                                    CartographicSupport csSym = null;
437
                                    int symbolType = sym.getSymbolType();
438
                                    boolean bDrawCartographicSupport = false;
439

    
440
                                    if (   symbolType == FShape.POINT
441
                                                    || symbolType == FShape.LINE
442
                                                    || sym instanceof CartographicSupport) {
443

    
444
                                            // patch
445
                                            if (!sym.getClass().equals(FSymbol.class)) {
446
                                                    csSym = (CartographicSupport) sym;
447
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
448
                                            }
449
                                    }
450

    
451
                                    int x = -1;
452
                                    int y = -1;
453
                                    int[] xyCoords = new int[2];
454

    
455
                                    // Check if size is a pixel
456
                                    boolean onePoint = bDrawCartographicSupport ?
457
                                                    isOnePoint(g.getTransform(), viewPort, MapContext.getScreenDPI(), csSym, geom, xyCoords) :
458
                                                            isOnePoint(g.getTransform(), viewPort, geom, xyCoords);
459

    
460
                                                    // Avoid out of bounds exceptions
461
                                                    if (onePoint) {
462
                                                            x = xyCoords[0];
463
                                                            y = xyCoords[1];
464
                                                            if (x<0 || y<0 || x>= viewPort.getImageWidth() || y>=viewPort.getImageHeight()) continue;
465
                                                    }
466

    
467
                                                    if (useZSort) {
468
                                                            // Check if this symbol is a multilayer
469
                                                                int[] symLevels = zSort.getLevels(sym);
470
                                                            if (sym instanceof IMultiLayerSymbol) {
471
                                                                    // if so, treat each of its layers as a single symbol
472
                                                                    // in its corresponding map level
473
                                                                    IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
474
                                                                    for (int i = 0; !cancel.isCanceled() && i < mlSym.getLayerCount(); i++) {
475
                                                                            ISymbol mySym = mlSym.getLayer(i);
476
                                                                        int symbolLevel = 0;
477
                                                                        if (symLevels != null) {
478
                                                                                symbolLevel = symLevels[i];
479
                                                                        } else {
480
                                                                                    /* an error occured when managing symbol levels.
481
                                                                                     * some of the legend changed events regarding the
482
                                                                                     * symbols did not finish satisfactory and the legend
483
                                                                                     * is now inconsistent. For this drawing, it will finish
484
                                                                                     * as it was at the bottom (level 0) but, when done, the
485
                                                                                     * ZSort will be reset to avoid app crashes. This is
486
                                                                                     * a bug that has to be fixed.
487
                                                                                     */
488
                                                                                    bSymbolLevelError = true;
489
                                                                            }
490

    
491
                                                                            if (onePoint) {
492
                                                                                    if (x<0 || y<0 || x>= imageLevels[symbolLevel].getWidth() || y>=imageLevels[symbolLevel].getHeight()) continue;
493
                                                                                    imageLevels[symbolLevel].setRGB(x, y, mySym.getOnePointRgb());
494
                                                                            } else {
495
                                                                                    if (!bDrawCartographicSupport) {
496
                                                                                            geom.drawInts(graphics[symbolLevel], viewPort, mySym, cancel);
497
                                                                                    } else {
498
                                                                                            geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) mySym, cancel);
499
                                                                                    }
500
                                                                            }
501
                                                                    }
502
                                                            } else {
503
                                                                    // else, just draw the symbol in its level
504
                                                                    int symbolLevel = 0;
505
                                                                    if (symLevels != null) {
506

    
507
                                                                            symbolLevel=symLevels[0];
508
                                                                    } else {
509
                                                                            /* If symLevels == null
510
                                                                             * an error occured when managing symbol levels.
511
                                                                             * some of the legend changed events regarding the
512
                                                                             * symbols did not finish satisfactory and the legend
513
                                                                             * is now inconsistent. For this drawing, it will finish
514
                                                                             * as it was at the bottom (level 0). This is
515
                                                                             * a bug that has to be fixed.
516
                                                                             */
517
//                                                                            bSymbolLevelError = true;
518
                                                                    }
519

    
520
                                                                    if (!bDrawCartographicSupport) {
521
                                                                            geom.drawInts(graphics[symbolLevel], viewPort, sym, cancel);
522
                                                                    } else {
523
                                                                            geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) csSym, cancel);
524
                                                                    }
525
                                                            }
526

    
527
                                                            // -- visual FX stuff
528
                                                            // Cuando el offset!=0 se est? dibujando sobre el Layout y por tanto no tiene que ejecutar el siguiente c?digo.
529
                                                            if (offset.getX()==0 && offset.getY()==0)
530
                                                                    if ((System.currentTimeMillis() - time) > screenRefreshDelay) {
531
                                                                            virtualBim = new BufferedImage(image.getWidth(),image.getHeight(),BufferedImage.TYPE_INT_ARGB);
532
                                                                            virtualGraphics = virtualBim.createGraphics();
533
                                                                            virtualGraphics.drawImage(image,0,0, null);
534
                                                                            for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
535
                                                                                    virtualGraphics.drawImage(imageLevels[i],0,0, null);
536
                                                                            }
537
                                                                            g.clearRect(0, 0, image.getWidth(), image.getHeight());
538
                                                                            g.drawImage(virtualBim, 0, 0, null);
539
                                                                            time = System.currentTimeMillis();
540
                                                                    }
541
                                                            // -- end visual FX stuff
542

    
543
                                                    } else {
544
                                                            // no ZSort, so there is only a map level, symbols are
545
                                                            // just drawn.
546
                                                            if (onePoint) {
547
                                                                    if (x<0 || y<0 || x>= image.getWidth() || y>=image.getHeight()) continue;
548
                                                                    image.setRGB(x, y, sym.getOnePointRgb());
549
                                                            } else {
550
                                                                    if (!bDrawCartographicSupport) {
551
                                                                            geom.drawInts(g, viewPort, sym, cancel);
552
                                                                    } else {
553
                                                                            geom.drawInts(g, viewPort, dpi, csSym, cancel);
554
                                                                    }
555
                                                            }
556
                                                    }
557
                            }
558

    
559
                            if (useZSort) {
560
                                    g.drawImage(image, 0, 0, null);
561
                                    g.translate(offset.getX(), offset.getY());
562
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
563
                                            g.drawImage(imageLevels[i],0,0, null);
564
                                            imageLevels[i] = null;
565
                                            graphics[i] = null;
566
                                    }
567
                                    g.translate(-offset.getX(), -offset.getY());
568
                                    imageLevels = null;
569
                                    graphics = null;
570
                            }
571
                            it.closeIterator();
572

    
573
                            if (bSymbolLevelError) {
574
                                    ((IVectorLegend) getLegend()).setZSort(null);
575
                            }
576

    
577
                    } catch (ReadDriverException e) {
578
                            this.setVisible(false);
579
                            this.setActive(false);
580
                            throw e;
581
                    }
582

    
583

    
584
            }
585
    }
586

    
587
           public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
588
            Cancellable cancel, double scale) throws ReadDriverException {
589
//            forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD = true;
590
//            if (!isUseStrategy()) {
591
                    _draw(image, g, viewPort, cancel, scale);
592
//            } else {
593
////                    moved up to FLayers
594
////                    if (isWithinScale(scale)) {
595
//
596
//
597
//                            // Las que solo tienen etiquetado sin pintar el shape,
598
//                            // no pasamos por ellas
599
//                            boolean bDrawShapes = true;
600
//                            if (legend instanceof SingleSymbolLegend) {
601
//                                    if (legend.getDefaultSymbol().isShapeVisible() == false)
602
//                                            bDrawShapes = false;
603
//                            }
604
//                            if (bDrawShapes) {
605
//                                    Strategy strategy = StrategyManager.getStrategy(this);
606
//                                    try {
607
//                                            prepareDrawing(image, g, viewPort);
608
//                                            strategy.draw(image, g, viewPort, cancel);
609
//                                    } catch (ReadDriverException e) {
610
//                                            this.setVisible(false);
611
//                                            this.setActive(false);
612
//                                            throw e;
613
//                                    }
614
//                            }
615
//                            if (getVirtualLayers() != null) {
616
//                                    getVirtualLayers().draw(image, g, viewPort, cancel, scale);
617
//                            }
618
////                    }
619
//            }
620
    }
621

    
622
    /**
623
     * Se llama antes de empezar a pintar.
624
     * Es ?til para preparar la cache a emplear, las leyendas, etc.
625
     * @param image
626
     * @param g
627
     * @param viewPort
628
     */
629
    private void prepareDrawing(BufferedImage image, Graphics2D g, ViewPort viewPort) {
630

    
631
    }
632

    
633
    public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
634
                    double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
635
            // TEST METHOD
636

    
637

    
638
                    /* SVN */
639

    
640
    /*        boolean bDrawShapes = true;
641
            if (legend instanceof SingleSymbolLegend) {
642
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
643
            }
644

645

646
            if (bDrawShapes) {
647
                    double dpi = 72;
648

649
                    PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
650
                    if (resolution.equals(PrintQuality.NORMAL)){
651
                            dpi = 300;
652
                    } else if (resolution.equals(PrintQuality.HIGH)){
653
                            dpi = 600;
654
                    } else if (resolution.equals(PrintQuality.DRAFT)){
655
                            dpi = 72;
656
                    }
657

658

659
                    try {
660
                            prepareDrawing(null, g, viewPort);
661
                            ArrayList<String> fieldList = new ArrayList<String>();
662
                            String[] aux;
663

664
                            // fields from legend
665
                            if (legend instanceof IClassifiedVectorLegend) {
666
                                    aux = ((IClassifiedVectorLegend) legend).
667
                                                                            getClassifyingFieldNames();
668
                                    for (int i = 0; i < aux.length; i++) {
669
                                            fieldList.add(aux[i]);
670
                                    }
671
                            }
672

673
                            // fields from labeling
674
                            if (isLabeled()) {
675
                                    aux = getLabelingStrategy().getUsedFields();
676
                                    for (int i = 0; i < aux.length; i++) {
677
                                            fieldList.add(aux[i]);
678
                                    }
679
                            }
680

681
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
682

683
                            // if layer has map levels it will use a ZSort
684
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
685

686

687
                            int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
688
                            for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
689
                                    // Get the iterator over the visible features
690
                                    IFeatureIterator it = getSource().getFeatureIterator(
691
                                                    viewPort.getAdjustedExtent(),
692
                                                    fieldList.toArray(new String[fieldList.size()]),
693
                                                    viewPort.getProjection(),
694
                                                    true);
695

696
                                    // Iteration over each feature
697
                                    while ( !cancel.isCanceled() && it.hasNext()) {
698
                                            IFeature feat = it.next();
699
                                            IGeometry geom = feat.getGeometry();
700

701
                                            // retreive the symbol associated to such feature
702
                                            ISymbol sym = legend.getSymbolByFeature(feat);
703

704
                                            if (useZSort) {
705
                                                    // Check if this symbol is a multilayer
706
                                                        if (sym instanceof IMultiLayerSymbol) {
707
                                                                // if so, get the layer corresponding to the current
708
                                                                // level. If none, continue to next iteration
709
                                                                IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
710
                                                                for (int i = 0; i < mlSym.getLayerCount(); i++) {
711
                                                                        ISymbol mySym = mlSym.getLayer(i);
712
                                                                        if (zSort.getSymbolLevel(mySym) == mapPass) {
713
                                                                                sym = mySym;
714
                                                                                break;
715
                                                                        }
716
                                                                        System.out.println("avoided layer "+i+"of symbol '"+mlSym.getDescription()+"' (pass "+mapPass+")");
717
                                                                }
718

719
                                                                if (sym == null) {
720
                                                                        continue;
721
                                                                }
722
                                                        } else {
723
                                                                // else, just draw the symbol in its level
724
                                                                if (zSort.getSymbolLevel(sym) != mapPass) {
725
                                                                        System.out.println("avoided single layer symbol '"+sym.getDescription()+"' (pass "+mapPass+")");
726
                                                                        continue;
727
                                                                }
728
                                                        }
729
                                            }
730

731
                                            // Check if this symbol is sized with CartographicSupport
732
                                            CartographicSupport csSym = null;
733
                                            int symbolType = sym.getSymbolType();
734
                                            boolean bDrawCartographicSupport = false;
735

736
                                            if (   symbolType == FShape.POINT
737
                                                            || symbolType == FShape.LINE
738
                                                            || sym instanceof CartographicSupport) {
739

740
                                                    csSym = (CartographicSupport) sym;
741
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
742
                                            }
743

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

746
                                            if (!bDrawCartographicSupport) {
747
                                                    geom.drawInts(g, viewPort, sym, null);
748
                                            } else {
749
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym);
750
                                            }
751

752
                                    }
753
                                    it.closeIterator();
754
                            }
755
                    } catch (ReadDriverException e) {
756
                            this.setVisible(false);
757
                            this.setActive(false);
758
                            throw e;
759
                    }
760
        */
761

    
762

    
763
            // TEST METHOD
764
            boolean bDrawShapes = true;
765
            if (legend instanceof SingleSymbolLegend) {
766
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
767
            }
768

    
769

    
770
            if (bDrawShapes) {
771

    
772
                    try {
773
                            double dpi = 72;
774

    
775
                            PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
776
                            if (resolution.equals(PrintQuality.NORMAL)){
777
                                    dpi = 300;
778
                            } else if (resolution.equals(PrintQuality.HIGH)){
779
                                    dpi = 600;
780
                            } else if (resolution.equals(PrintQuality.DRAFT)){
781
                                    dpi = 72;
782
                            }
783
                            ArrayList<String> fieldList = new ArrayList<String>();
784
                            String[] aux;
785

    
786
                            // fields from legend
787
                            if (legend instanceof IClassifiedVectorLegend) {
788
                                    aux = ((IClassifiedVectorLegend) legend).
789
                                    getClassifyingFieldNames();
790
                                    for (int i = 0; i < aux.length; i++) {
791
                                            fieldList.add(aux[i]);
792
                                    }
793
                            }
794
//
795
//                            // fields from labeling
796
//                            if (isLabeled()) {
797
//                                    aux = getLabelingStrategy().getUsedFields();
798
//                                    for (int i = 0; i < aux.length; i++) {
799
//                                            fieldList.add(aux[i]);
800
//                                    }
801
//                            }
802

    
803
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
804

    
805
                            // if layer has map levels it will use a ZSort
806
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
807

    
808

    
809
                            int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
810
                            for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
811
                                    // Get the iterator over the visible features
812
                                    IFeatureIterator it = getSource().getFeatureIterator(
813
                                                    viewPort.getAdjustedExtent(),
814
                                                    fieldList.toArray(new String[fieldList.size()]),
815
                                                    viewPort.getProjection(),
816
                                                    true);
817

    
818
                                    // Iteration over each feature
819
                                    while ( !cancel.isCanceled() && it.hasNext()) {
820
                                            IFeature feat = it.next();
821
                                            IGeometry geom = feat.getGeometry();
822

    
823
                                            // retreive the symbol associated to such feature
824
                                            ISymbol sym = legend.getSymbolByFeature(feat);
825
                                            if (sym == null) {
826
                                                        continue;
827
                                                }
828
                                            if (useZSort) {
829
                                                        int[] symLevels = zSort.getLevels(sym);
830
                                                        if(symLevels != null){
831
                                                                // Check if this symbol is a multilayer
832
                                                                if (sym instanceof IMultiLayerSymbol) {
833
                                                                        // if so, get the layer corresponding to the current
834
                                                                        // level. If none, continue to next iteration
835
                                                                        IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
836
                                                                        for (int i = 0; i < mlSym.getLayerCount(); i++) {
837
                                                                                ISymbol mySym = mlSym.getLayer(i);
838
                                                                                if (symLevels[i] == mapPass) {
839
                                                                                        sym = mySym;
840
                                                                                        break;
841
                                                                                }
842
                                                                                System.out.println("avoided layer "+i+"of symbol '"+mlSym.getDescription()+"' (pass "+mapPass+")");
843
                                                                        }
844
                                                                } else {
845
                                                                        // else, just draw the symbol in its level
846
                                                                        if (symLevels[0] != mapPass) {
847
                                                                                System.out.println("avoided single layer symbol '"+sym.getDescription()+"' (pass "+mapPass+")");
848
                                                                                continue;
849
                                                                        }
850
                                                                }
851
                                                        }
852
                                            }
853

    
854
                                            // Check if this symbol is sized with CartographicSupport
855
                                            CartographicSupport csSym = null;
856
                                            int symbolType = sym.getSymbolType();
857

    
858
                                            if (   symbolType == FShape.POINT
859
                                                            || symbolType == FShape.LINE
860
                                                            || sym instanceof CartographicSupport) {
861

    
862
                                                    csSym = (CartographicSupport) sym;
863
                                            }
864

    
865
//                                            System.err.println("passada "+mapPass+" pinte s?mboll "+sym.getDescription());
866

    
867
                                            if (csSym == null) {
868
                                                    geom.drawInts(g, viewPort, sym, null);
869
                                            } else {
870
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym, cancel);
871
                                            }
872

    
873
                                    }
874
                                    it.closeIterator();
875
                            }
876
                    } catch (ReadDriverException e) {
877
                            this.setVisible(false);
878
                            this.setActive(false);
879
                            throw e;
880
                    }
881
            }
882
    }
883

    
884

    
885
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
886
            double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
887
//            if (forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
888
                    _print(g, viewPort, cancel, scale, properties);
889
//            } else {
890
////                    moved up to Flayers
891
////                    if (isVisible() && isWithinScale(scale)) {
892
//                            Strategy strategy = StrategyManager.getStrategy(this);
893
//
894
//                            strategy.print(g, viewPort, cancel, properties);
895
//                            ILabelingStrategy labeling;
896
//                            if ( (labeling = getLabelingStrategy() ) != null) {
897
//                                    // contains labels
898
//                                    labeling.print(g, viewPort, cancel, properties);
899
//                            }
900
////                    }
901
//            }
902
    }
903

    
904
    public void deleteSpatialIndex() {
905
        //must we delete possible spatial indexes files?
906
        spatialIndex = null;
907
    }
908

    
909
   /**
910
    * <p>
911
    * Creates an spatial index associated to this layer.
912
    * The spatial index will used
913
    * the native projection of the layer, so if the layer is reprojected, it will
914
    * be ignored.
915
    * </p>
916
    * @param cancelMonitor instance of CancellableMonitorable that allows
917
    * to monitor progress of spatial index creation, and cancel the process
918
    */
919
    public void createSpatialIndex(CancellableMonitorable cancelMonitor){
920
         // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
921
        // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
922
        // para que acepten recorrer sin geometria, solo con rectangulos.
923

    
924
        //If this vectorial layer is based in a spatial database, the spatial
925
        //index is already implicit. We only will index file drivers
926
        ReadableVectorial va = getSource();
927
        //We must think in non spatial databases, like HSQLDB
928
        if(!(va instanceof VectorialFileAdapter)){
929
            return;
930
        }
931
        if (!(va.getDriver() instanceof BoundedShapes)) {
932
            return;
933
        }
934
        File file = ((VectorialFileAdapter) va).getFile();
935
        String fileName = file.getAbsolutePath();
936
        ISpatialIndex localCopy = null;
937
        try {
938
            va.start();
939
            localCopy = new QuadtreeGt2(fileName, "NM", va.getFullExtent(),
940
                    va.getShapeCount(), true);
941

    
942
        } catch (SpatialIndexException e1) {
943
            // Probably we dont have writing permissions
944
            String directoryName = System.getProperty("java.io.tmpdir");
945
            File newFile = new File(directoryName +
946
                    File.separator +
947
                    file.getName());
948
            String newFileName = newFile.getName();
949
            try {
950
                localCopy = new QuadtreeGt2(newFileName, "NM", va.getFullExtent(),
951
                        va.getShapeCount(), true);
952
            } catch (SpatialIndexException e) {
953
                // if we cant build a file based spatial index, we'll build
954
                // a pure memory spatial index
955
                localCopy = new QuadtreeJts();
956
            } catch (ReadDriverException e) {
957
                localCopy = new QuadtreeJts();
958
            }
959

    
960
        } catch(Exception e){
961
            e.printStackTrace();
962
        }//try
963
        BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
964
        try {
965
            for (int i=0; i < va.getShapeCount(); i++)
966
            {
967
                if(cancelMonitor != null){
968
                    if(cancelMonitor.isCanceled())
969
                        return;
970
                    cancelMonitor.reportStep();
971
                }
972
                Rectangle2D r = shapeBounds.getShapeBounds(i);
973
                if(r != null)
974
                    localCopy.insert(r, i);
975
            } // for
976
            va.stop();
977
            if(localCopy instanceof IPersistentSpatialIndex)
978
                ((IPersistentSpatialIndex) localCopy).flush();
979
            spatialIndex = localCopy;
980
            //vectorial adapter needs a reference to the spatial index, to solve
981
            //request for feature iteration based in spatial queries
982
            source.setSpatialIndex(spatialIndex);
983
        } catch (ReadDriverException e) {
984
            // TODO Auto-generated catch block
985
            e.printStackTrace();
986
        }
987
    }
988

    
989
    public void createSpatialIndex() {
990
        createSpatialIndex(null);
991
    }
992

    
993
    public void process(FeatureVisitor visitor, FBitSet subset)
994
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
995
        Strategy s = StrategyManager.getStrategy(this);
996
        s.process(visitor, subset);
997
    }
998

    
999
    public void process(FeatureVisitor visitor) throws ReadDriverException, VisitorException {
1000
        Strategy s = StrategyManager.getStrategy(this);
1001
        s.process(visitor);
1002
    }
1003

    
1004
    public void process(FeatureVisitor visitor, Rectangle2D rect)
1005
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
1006
        Strategy s = StrategyManager.getStrategy(this);
1007
        s.process(visitor, rect);
1008
    }
1009

    
1010
    public FBitSet queryByRect(Rectangle2D rect) throws ReadDriverException, VisitorException {
1011
        Strategy s = StrategyManager.getStrategy(this);
1012

    
1013
        return s.queryByRect(rect);
1014
    }
1015

    
1016
    public FBitSet queryByPoint(Point2D p, double tolerance)
1017
            throws ReadDriverException, VisitorException {
1018
        Strategy s = StrategyManager.getStrategy(this);
1019
        return s.queryByPoint(p, tolerance);
1020
    }
1021

    
1022
    public FBitSet queryByShape(IGeometry g, int relationship)
1023
            throws ReadDriverException, VisitorException {
1024
        Strategy s = StrategyManager.getStrategy(this);
1025
        return s.queryByShape(g, relationship);
1026
    }
1027

    
1028
    public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancel) throws ReadDriverException, VisitorException {
1029
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(p);
1030
        FBitSet bs = queryByPoint(pReal, tolerance);
1031
        VectorialXMLItem[] item = new VectorialXMLItem[1];
1032
        item[0] = new VectorialXMLItem(bs, this);
1033

    
1034
        return item;
1035
    }
1036

    
1037
    public void setLegend(IVectorLegend r) throws LegendLayerException {
1038
            if (this.legend == r){
1039
                    return;
1040
            }
1041
                if (this.legend != null && this.legend.equals(r)){
1042
                        return;
1043
                }
1044
        IVectorLegend oldLegend = legend;
1045

    
1046
        /*
1047
         * Parche para discriminar las leyendas clasificadas cuyos campos de
1048
         * clasificaci?n no est?n en la fuente de la capa.
1049
         *
1050
         * Esto puede ocurrir porque en versiones anteriores se admit?an
1051
         * leyendas clasificadas en capas que se han unido a una tabla
1052
         * por campos que pertenec?an a la tabla y no s?lo a la capa.
1053
         *
1054
         */
1055
                if(r instanceof IClassifiedVectorLegend){
1056
                        IClassifiedVectorLegend classifiedLegend = (IClassifiedVectorLegend)r;
1057
                        String[] fieldNames = classifiedLegend.getClassifyingFieldNames();
1058

    
1059
                        for (int i = 0; i < fieldNames.length; i++) {
1060
                                try {
1061
                                        if(this.getSource().getRecordset().getFieldIndexByName(fieldNames[i]) == -1){
1062
                                                logger.warn("Some fields of the classification of the legend doesn't belong with the source of the layer.");
1063
                                                if (this.legend == null){
1064
                                                        r = LegendFactory.createSingleSymbolLegend(this.getShapeType());
1065
                                                } else {
1066
                                                        return;
1067
                                                }
1068
                                        }
1069
                                } catch (ReadDriverException e1) {
1070
                                        throw new LegendLayerException(getName(),e1);
1071
                                }
1072
                        }
1073
                }
1074
                /* Fin del parche */
1075

    
1076
                legend = r;
1077
        try {
1078
            legend.setDataSource(getRecordset());
1079
        } catch (FieldNotFoundException e1) {
1080
            throw new LegendLayerException(getName(),e1);
1081
        } catch (ReadDriverException e1) {
1082
            throw new LegendLayerException(getName(),e1);
1083
        } finally{
1084
                this.updateDrawVersion();
1085
        }
1086
        if (oldLegend != null){
1087
                oldLegend.removeLegendListener(this);
1088
        }
1089
        if (legend != null){
1090
                legend.addLegendListener(this);
1091
        }
1092
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
1093
                oldLegend, legend);
1094
        e.setLayer(this);
1095
        callLegendChanged(e);
1096
    }
1097

    
1098
    /**
1099
     * Devuelve la Leyenda de la capa.
1100
     *
1101
     * @return Leyenda.
1102
     */
1103
    public ILegend getLegend() {
1104
        return legend;
1105
    }
1106

    
1107
    /**
1108
     * Devuelve el tipo de shape que contiene la capa.
1109
     *
1110
     * @return tipo de shape.
1111
     *
1112
     * @throws DriverException
1113
     */
1114
    public int getShapeType() throws ReadDriverException {
1115
        if (typeShape == -1) {
1116
            getSource().start();
1117
            typeShape = getSource().getShapeType();
1118
            getSource().stop();
1119
        }
1120

    
1121
        return typeShape;
1122
    }
1123

    
1124
    public XMLEntity getXMLEntity() throws XMLException {
1125
        if (!this.isAvailable() && this.orgXMLEntity != null) {
1126
            return this.orgXMLEntity;
1127
        }
1128
        XMLEntity xml = super.getXMLEntity();
1129
        if (getLegend()!=null)
1130
            xml.addChild(getLegend().getXMLEntity());
1131
        try {
1132
            if (getRecordset()!=null)
1133
                xml.addChild(getRecordset().getSelectionSupport().getXMLEntity());
1134
        } catch (ReadDriverException e1) {
1135
            e1.printStackTrace();
1136
            throw new XMLException(e1);
1137
        }
1138
        // Repongo el mismo ReadableVectorial m?s abajo para cuando se guarda el proyecto.
1139
        ReadableVectorial rv=getSource();
1140
        xml.putProperty("type", "vectorial");
1141
        if (source instanceof VectorialEditableAdapter) {
1142
            setSource(((VectorialEditableAdapter) source).getOriginalAdapter());
1143
        }
1144
        if (source instanceof VectorialFileAdapter) {
1145
            xml.putProperty("type", "vectorial");
1146
            xml.putProperty("file", ((VectorialFileAdapter) source)
1147
                    .getFile());
1148
            try {
1149
                xml.putProperty("recordset-name", source.getRecordset()
1150
                        .getName());
1151
            } catch (ReadDriverException e) {
1152
                throw new XMLException(e);
1153
            } catch (RuntimeException e) {
1154
                e.printStackTrace();
1155
            }
1156
        } else if (source instanceof VectorialDBAdapter) {
1157
            xml.putProperty("type", "vectorial");
1158

    
1159
            IVectorialDatabaseDriver dbDriver = (IVectorialDatabaseDriver) source
1160
                    .getDriver();
1161

    
1162
            // Guardamos el nombre del driver para poder recuperarlo
1163
            // con el DriverManager de Fernando.
1164
            xml.putProperty("db", dbDriver.getName());
1165
            try {
1166
                xml.putProperty("recordset-name", source.getRecordset()
1167
                        .getName());
1168
            } catch (ReadDriverException e) {
1169
                throw new XMLException(e);
1170
            } catch (RuntimeException e) {
1171
                e.printStackTrace();
1172
            }
1173
            xml.addChild(dbDriver.getXMLEntity()); // Tercer child. Antes hemos
1174
                                                    // metido la leyenda y el
1175
                                                    // selection support
1176
        } else if (source instanceof VectorialAdapter) {
1177
            // Se supone que hemos hecho algo gen?rico.
1178
            xml.putProperty("type", "vectorial");
1179

    
1180
            VectorialDriver driver = source.getDriver();
1181

    
1182
            // Guardamos el nombre del driver para poder recuperarlo
1183
            // con el DriverManager de Fernando.
1184
            xml.putProperty("other", driver.getName());
1185
            // try {
1186
            try {
1187
                xml.putProperty("recordset-name", source.getRecordset()
1188
                        .getName());
1189
            } catch (ReadDriverException e) {
1190
                throw new XMLException(e);
1191
            } catch (RuntimeException e) {
1192
                e.printStackTrace();
1193
            }
1194
            if (driver instanceof IPersistence) {
1195
                // xml.putProperty("className", driver.getClass().getName());
1196
                    IPersistence persist = (IPersistence) driver;
1197
                xml.addChild(persist.getXMLEntity()); // Tercer child. Antes
1198
                                                        // hemos metido la
1199
                                                        // leyenda y el
1200
                                                        // selection support
1201
            }
1202
        }
1203
        if (rv!=null)
1204
            setSource(rv);
1205
        xml.putProperty("driverName", source.getDriver().getName());
1206
        if (bHasJoin)
1207
            xml.putProperty("hasJoin", "true");
1208

    
1209
        // properties from ILabelable
1210
        xml.putProperty("isLabeled", isLabeled);
1211
        if (strategy != null) {
1212
            XMLEntity strategyXML = strategy.getXMLEntity();
1213
            strategyXML.putProperty("Strategy", strategy.getClassName());
1214
            xml.addChild(strategy.getXMLEntity());
1215
        }
1216
        xml.addChild(getLinkProperties().getXMLEntity());
1217
        return xml;
1218
    }
1219

    
1220
    /**
1221
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1222
     */
1223
    public void setXMLEntity03(XMLEntity xml) throws XMLException {
1224

    
1225
        super.setXMLEntity(xml);
1226
        legend = LegendFactory.createFromXML03(xml.getChild(0));
1227

    
1228
        try {
1229
            setLegend(legend);
1230
        } catch (LegendLayerException e) {
1231
            throw new XMLException(e);
1232
        }
1233

    
1234
        try {
1235
            getRecordset().getSelectionSupport()
1236
                    .setXMLEntity03(xml.getChild(1));
1237
        } catch (ReadDriverException e) {
1238
            e.printStackTrace();
1239
        }
1240
    }
1241

    
1242
    /*
1243
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1244
     */
1245
    public void setXMLEntity(XMLEntity xml) throws XMLException {
1246
        try {
1247
                    super.setXMLEntity(xml);
1248
                    XMLEntity legendXML = xml.getChild(0);
1249
                    IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1250

    
1251
                    /*
1252
                     * Parche para detectar cuando, por algun problema de persistencia
1253
                     * respecto a versiones anteriores, la leyenda que se ha cargado
1254
                     * no se corresponde con el tipo de shape de la capa.
1255
                     */
1256
                    int legShapeType = leg.getShapeType();
1257
                    if (legShapeType != 0 && legShapeType != this.getShapeType()){
1258
                            leg = LegendFactory.createSingleSymbolLegend(this.getShapeType());
1259
                                logger.warn("Legend shape type and layer shape type does not match.");
1260
                    }
1261
                    /* Fin del parche */
1262

    
1263
                    try {
1264
                            getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1265
                            // JMVIVO: Esto sirve para algo????
1266
                            /*
1267
                             *  Jaume: si, para restaurar el selectable datasource cuando se
1268
                             *  clona la capa, cuando se carga de un proyecto. Si no esta ya
1269
                             *  no se puede ni hacer consultas sql, ni hacer selecciones,
1270
                             *  ni usar la mayor parte de las herramientas.
1271
                             *
1272
                             *  Lo vuelvo a poner.
1273
                             */
1274

    
1275
                            String recordsetName = xml.getStringProperty("recordset-name");
1276

    
1277
//                            SelectableDataSource sds = new SelectableDataSource(LayerFactory
1278
//                                            .getDataSourceFactory().createRandomDataSource(
1279
//                                                            recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
1280

    
1281
                            LayerFactory.getDataSourceFactory().changeDataSourceName(
1282
                                            getSource().getRecordset().getName(), recordsetName);
1283
                            SelectableDataSource sds = new SelectableDataSource(LayerFactory
1284
                                            .getDataSourceFactory().createRandomDataSource(
1285
                                                            recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
1286

    
1287
                    } catch (NoSuchTableException e1) {
1288
                            this.setAvailable(false);
1289
                            throw new XMLException(e1);
1290
                    } catch (ReadDriverException e1) {
1291
                            this.setAvailable(false);
1292
                            throw new XMLException(e1);
1293
                    }
1294
                    // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1295
                    // el final
1296
                    // de la lectura del proyecto
1297
                    if (xml.contains("hasJoin")) {
1298
                            setIsJoined(true);
1299
                            PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1300
                    } else {
1301
                            try {
1302
                                    setLegend(leg);
1303
                            } catch (LegendLayerException e) {
1304
                                    throw new XMLException(e);
1305
                            }
1306
                    }
1307

    
1308
                    //Por compatibilidad con proyectos anteriores a la 1.0
1309
                    boolean containsIsLabeled = xml.contains("isLabeled");
1310
                    if (containsIsLabeled){
1311
                            isLabeled = xml.getBooleanProperty("isLabeled");
1312
                    }
1313
                    // set properties for ILabelable
1314
                    XMLEntity labelingXML = xml.firstChild("labelingStrategy", "labelingStrategy");
1315
                    if (labelingXML!= null) {
1316
                            if(!containsIsLabeled){
1317
                                    isLabeled = true;
1318
                            }
1319
                            try {
1320
                                    this.strategy = LabelingFactory.createStrategyFromXML(labelingXML, this);
1321
                            } catch (NotExistInXMLEntity neXMLEX) {
1322
                                    // no strategy was set, just continue;
1323
                                    logger.warn("Reached what should be unreachable code");
1324
                            }
1325
                    } else if (legendXML.contains("labelFieldName")|| legendXML.contains("labelfield")) {
1326
                            /* (jaume) begin patch;
1327
                         * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1328
                         * no longer managed by the Legend but by the ILabelingStrategy. The
1329
                         * following allows restoring older projects' labelings.
1330
                         */
1331
                            String labelTextField =        null;
1332
                            if (legendXML.contains("labelFieldName")){
1333
                                    labelTextField = legendXML.getStringProperty("labelFieldName");
1334
                                if (labelTextField != null) {
1335
                                        AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1336
                                        labeling.setLayer(this);
1337
                                        labeling.setUsesFixedSize(true);
1338
                                        labeling.setFixedSize(10);
1339
                                            labeling.setTextField(labelTextField);
1340
                                        labeling.setHeightField(legendXML.getStringProperty("labelHeightFieldName"));
1341
                                        labeling.setRotationField(legendXML.getStringProperty("labelRotationFieldName"));
1342
                                        this.setLabelingStrategy(labeling);
1343
                                        this.setIsLabeled(true);
1344
                                }
1345
                            }else{
1346
                                    labelTextField = legendXML.getStringProperty("labelfield");
1347
                                    if (labelTextField != null) {
1348
                                            AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1349
                                            labeling.setLayer(this);
1350
                                            labeling.setUsesFixedSize(true);
1351
                                            labeling.setFixedSize(10);
1352
                                            labeling.setTextField(labelTextField);
1353
                                            labeling.setHeightField(legendXML.getStringProperty("labelFieldHeight"));
1354
                                            labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
1355
                                            this.setLabelingStrategy(labeling);
1356
                                            this.setIsLabeled(true);
1357
                                    }
1358
                            }
1359

    
1360
                }else if(!containsIsLabeled){
1361
                                    isLabeled = false;
1362
                    }
1363

    
1364
                    // compatibility with hyperlink from 1.9 alpha version... do we really need to be compatible with alpha versions??
1365
                    XMLEntity xmlLinkProperties=xml.firstChild("typeChild", "linkProperties");
1366
                    if (xmlLinkProperties != null){
1367
                            try {
1368
                                    String fieldName=xmlLinkProperties.getStringProperty("fieldName");
1369
                                    xmlLinkProperties.remove("fieldName");
1370
                                    String extName = xmlLinkProperties.getStringProperty("extName");
1371
                                    xmlLinkProperties.remove("extName");
1372
                                    int typeLink = xmlLinkProperties.getIntProperty("typeLink");
1373
                                    xmlLinkProperties.remove("typeLink");
1374
                                    if (fieldName!=null) {
1375
                                            setProperty("legacy.hyperlink.selectedField", fieldName);
1376
                                            setProperty("legacy.hyperlink.type", new Integer(typeLink));
1377
                                            if (extName!=null) {
1378
                                                    setProperty("legacy.hyperlink.extension", extName);
1379
                                            }
1380
                                    }
1381
                            }
1382
                            catch (NotExistInXMLEntity ex) {
1383
                                    logger.warn("Error getting old hyperlink configuration", ex);
1384
                            }
1385
                    }
1386

    
1387
            } catch (XMLException e) {
1388
                    this.setAvailable(false);
1389
                    this.orgXMLEntity = xml;
1390
            } catch (Exception e) {
1391
                    e.printStackTrace();
1392
                    this.setAvailable(false);
1393
                    this.orgXMLEntity = xml;
1394

    
1395
            }
1396

    
1397

    
1398
    }
1399

    
1400
    public void setXMLEntityNew(XMLEntity xml) throws XMLException {
1401
        try {
1402
            super.setXMLEntity(xml);
1403

    
1404
            XMLEntity legendXML = xml.getChild(0);
1405
            IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1406
            /* (jaume) begin patch;
1407
             * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1408
             * no longer managed by the Legend but by the ILabelingStrategy. The
1409
             * following allows restoring older projects' labelings.
1410
             */
1411
            if (legendXML.contains("labelFieldHeight")) {
1412
                AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1413
                labeling.setLayer(this);
1414
                labeling.setTextField(legendXML.getStringProperty("labelFieldHeight"));
1415
                labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
1416
                this.setLabelingStrategy(labeling);
1417
                this.setIsLabeled(true);
1418
              }
1419
            /* end patch */
1420
            try {
1421
                getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1422

    
1423
                this.setLoadSelection(xml.getChild(1));
1424
            } catch (ReadDriverException e1) {
1425
                this.setAvailable(false);
1426
                throw new XMLException(e1);
1427
            }
1428
            // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1429
            // el final
1430
            // de la lectura del proyecto
1431
            if (xml.contains("hasJoin")) {
1432
                setIsJoined(true);
1433
                PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1434
            } else {
1435
                this.setLoadLegend(leg);
1436
            }
1437

    
1438
        } catch (XMLException e) {
1439
            this.setAvailable(false);
1440
            this.orgXMLEntity = xml;
1441
        } catch (Exception e) {
1442
            this.setAvailable(false);
1443
            this.orgXMLEntity = xml;
1444
        }
1445

    
1446

    
1447
    }
1448

    
1449

    
1450
    /**
1451
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
1452
     * identifiquen la capa.
1453
     *
1454
     * @return DOCUMENT ME!
1455
     */
1456
    public String toString() {
1457
        /*
1458
         * Se usa internamente para que la parte de datos identifique de forma
1459
         * un?voca las tablas
1460
         */
1461
        String ret = super.toString();
1462

    
1463
        return "layer" + ret.substring(ret.indexOf('@') + 1);
1464
    }
1465

    
1466
    public boolean isJoined() {
1467
        return bHasJoin;
1468
    }
1469

    
1470
    /**
1471
     * Returns if a layer is spatially indexed
1472
     *
1473
     * @return if this layer has the ability to proces spatial queries without
1474
     *         secuential scans.
1475
     */
1476
    public boolean isSpatiallyIndexed() {
1477
        ReadableVectorial source = getSource();
1478
        if (source instanceof ISpatialDB)
1479
            return true;
1480

    
1481
//FIXME azabala
1482
/*
1483
 * Esto es muy dudoso, y puede cambiar.
1484
 * Estoy diciendo que las que no son fichero o no son
1485
 * BoundedShapes estan indexadas. Esto es mentira, pero
1486
 * as? quien pregunte no querr? generar el indice.
1487
 * Esta por ver si interesa generar el indice para capas
1488
 * HSQLDB, WFS, etc.
1489
 */
1490
        if(!(source instanceof VectorialFileAdapter)){
1491
            return true;
1492
        }
1493
        if (!(source.getDriver() instanceof BoundedShapes)) {
1494
            return true;
1495
        }
1496

    
1497
        if (getISpatialIndex() != null)
1498
            return true;
1499
        return false;
1500
    }
1501

    
1502
    public void setIsJoined(boolean hasJoin) {
1503
        bHasJoin = hasJoin;
1504
    }
1505

    
1506
    /**
1507
     * @return Returns the spatialIndex.
1508
     */
1509
    public ISpatialIndex getISpatialIndex() {
1510
        return spatialIndex;
1511
    }
1512
    /**
1513
     * Sets the spatial index. This could be useful if, for some
1514
     * reasons, you want to work with a distinct spatial index
1515
     * (for example, a spatial index which could makes nearest
1516
     * neighbour querys)
1517
     * @param spatialIndex
1518
     */
1519
    public void setISpatialIndex(ISpatialIndex spatialIndex){
1520
        this.spatialIndex = spatialIndex;
1521
    }
1522

    
1523
    public SelectableDataSource getRecordset() throws ReadDriverException {
1524
        if (!this.isAvailable()) return null;
1525
        if (sds == null) {
1526

    
1527
                SelectableDataSource ds = source.getRecordset();
1528

    
1529
                if (ds == null) {
1530
                    return null;
1531
                }
1532

    
1533
                sds = ds;
1534
                sds.setSelectionSupport(selectionSupport);
1535
                selectionSupport.addSelectionListener(this);
1536

    
1537
        }
1538
        return sds;
1539
    }
1540

    
1541
    public void setEditing(boolean b) throws StartEditionLayerException {
1542
        super.setEditing(b);
1543
        try {
1544
            if (b) {
1545
                VectorialEditableAdapter vea = null;
1546
                // TODO: Qu? pasa si hay m?s tipos de adapters?
1547
                // FJP: Se podr?a pasar como argumento el
1548
                // VectorialEditableAdapter
1549
                // que se quiera usar para evitar meter c?digo aqu? de este
1550
                // estilo.
1551
                if (getSource() instanceof VectorialDBAdapter) {
1552
                    vea = new VectorialEditableDBAdapter();
1553
                } else if (this instanceof FLyrAnnotation) {
1554
                    vea = new AnnotationEditableAdapter(
1555
                            (FLyrAnnotation) this);
1556
                } else {
1557
                    vea = new VectorialEditableAdapter();
1558
                }
1559
                vea.addEditionListener(this);
1560
                vea.setOriginalVectorialAdapter(getSource());
1561
//                                azo: implementations of readablevectorial need
1562
                //references of projection and spatial index
1563
                vea.setProjection(getProjection());
1564
                vea.setSpatialIndex(spatialIndex);
1565

    
1566

    
1567
                // /vea.setSpatialIndex(getSpatialIndex());
1568
                // /vea.setFullExtent(getFullExtent());
1569
                vea.setCoordTrans(getCoordTrans());
1570
                vea.startEdition(EditionEvent.GRAPHIC);
1571
                setSource(vea);
1572
                getRecordset().setSelectionSupport(
1573
                        vea.getOriginalAdapter().getRecordset()
1574
                                .getSelectionSupport());
1575

    
1576
            } else {
1577
                VectorialEditableAdapter vea = (VectorialEditableAdapter) getSource();
1578
                vea.removeEditionListener(this);
1579
                setSource(vea.getOriginalAdapter());
1580
            }
1581
            // Si tenemos una leyenda, hay que pegarle el cambiazo a su
1582
            // recordset
1583
            setRecordset(getSource().getRecordset());
1584
            if (getLegend() instanceof IVectorLegend) {
1585
                IVectorLegend ley = (IVectorLegend) getLegend();
1586
                ley.setDataSource(getSource().getRecordset());
1587
                // Esto lo pongo para evitar que al dibujar sobre un
1588
                // dxf, dwg, o dgn no veamos nada. Es debido al checkbox
1589
                // de la leyenda de textos "dibujar solo textos".
1590
//jaume
1591
//                                if (!(getSource().getDriver() instanceof IndexedShpDriver)){
1592
//                                        FSymbol symbol=new FSymbol(getShapeType());
1593
//                                        symbol.setFontSizeInPixels(false);
1594
//                                        symbol.setFont(new Font("SansSerif", Font.PLAIN, 9));
1595
//                                        Color color=symbol.getColor();
1596
//                                        int alpha=symbol.getColor().getAlpha();
1597
//                                        if (alpha>250) {
1598
//                                                symbol.setColor(new Color(color.getRed(),color.getGreen(),color.getBlue(),100));
1599
//                                        }
1600
//                                        ley.setDefaultSymbol(symbol);
1601
//                                }
1602
//jaume//
1603
                ley.useDefaultSymbol(true);
1604
            }
1605
        } catch (ReadDriverException e) {
1606
            throw new StartEditionLayerException(getName(),e);
1607
        } catch (FieldNotFoundException e) {
1608
            throw new StartEditionLayerException(getName(),e);
1609
        } catch (StartWriterVisitorException e) {
1610
            throw new StartEditionLayerException(getName(),e);
1611
        }
1612

    
1613
        setSpatialCacheEnabled(b);
1614
        callEditionChanged(LayerEvent
1615
                .createEditionChangedEvent(this, "edition"));
1616

    
1617
    }
1618

    
1619
    /**
1620
     * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
1621
     * forma, podr?s poner leyendas basadas en el nuevo recordset
1622
     *
1623
     * @param newSds
1624
     */
1625
    public void setRecordset(SelectableDataSource newSds) {
1626
            // TODO: Deberiamos hacer comprobaciones del cambio
1627
        sds = newSds;
1628
        sds.setSelectionSupport(selectionSupport);
1629
                selectionSupport.addSelectionListener(this);
1630
                this.updateDrawVersion();
1631
    }
1632

    
1633
    public void clearSpatialCache()
1634
    {
1635
        spatialCache.clearAll();
1636
    }
1637

    
1638
    public boolean isSpatialCacheEnabled() {
1639
        return spatialCacheEnabled;
1640
    }
1641

    
1642
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1643
        this.spatialCacheEnabled = spatialCacheEnabled;
1644
    }
1645

    
1646
    public SpatialCache getSpatialCache() {
1647
        return spatialCache;
1648
    }
1649

    
1650
    /**
1651
     * Siempre es un numero mayor de 1000
1652
     * @param maxFeatures
1653
     */
1654
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
1655
        if (maxFeatures > spatialCache.maxFeatures)
1656
            spatialCache.setMaxFeatures(maxFeatures);
1657

    
1658
    }
1659

    
1660
    /**
1661
     * This method returns a boolean that is used by the FPopMenu
1662
     * to make visible the properties menu or not. It is visible by
1663
     * default, and if a later don't have to show this menu only
1664
     * has to override this method.
1665
     * @return
1666
     * If the properties menu is visible (or not)
1667
     */
1668
    public boolean isPropertiesMenuVisible(){
1669
        return true;
1670
    }
1671

    
1672
    public void reload() throws ReloadLayerException {
1673
        this.setAvailable(true);
1674
        super.reload();
1675
        this.updateDrawVersion();
1676
        try {
1677
            this.source.getDriver().reload();
1678
            if (this.getLegend() == null) {
1679
                if (this.getRecordset().getDriver() instanceof WithDefaultLegend) {
1680
                    WithDefaultLegend aux = (WithDefaultLegend) this.getRecordset().getDriver();
1681
                    this.setLegend((IVectorLegend) aux.getDefaultLegend());
1682
                    this.setLabelingStrategy(aux.getDefaultLabelingStrategy());
1683
                } else {
1684
                    this.setLegend(LegendFactory.createSingleSymbolLegend(
1685
                            this.getShapeType()));
1686
                }
1687
            }
1688

    
1689
        } catch (LegendLayerException e) {
1690
            this.setAvailable(false);
1691
            throw new ReloadLayerException(getName(),e);
1692
        } catch (ReadDriverException e) {
1693
            this.setAvailable(false);
1694
            throw new ReloadLayerException(getName(),e);
1695
        }
1696

    
1697
    }
1698

    
1699
    protected void setLoadSelection(XMLEntity xml) {
1700
        this.loadSelection = xml;
1701
    }
1702

    
1703
    protected void setLoadLegend(IVectorLegend legend) {
1704
        this.loadLegend = legend;
1705
    }
1706

    
1707
    protected void putLoadSelection() throws XMLException {
1708
        if (this.loadSelection == null) return;
1709
        try {
1710
            this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1711
        } catch (ReadDriverException e) {
1712
            throw new XMLException(e);
1713
        }
1714
        this.loadSelection = null;
1715

    
1716
    }
1717
    protected void putLoadLegend() throws LegendLayerException {
1718
        if (this.loadLegend == null) return;
1719
        this.setLegend(this.loadLegend);
1720
        this.loadLegend = null;
1721
    }
1722

    
1723
    protected void cleanLoadOptions() {
1724
        this.loadLegend = null;
1725
        this.loadSelection = null;
1726
    }
1727

    
1728
    public boolean isWritable() {
1729
        VectorialDriver drv = getSource().getDriver();
1730
        if (!drv.isWritable())
1731
            return false;
1732
        if (drv instanceof IWriteable)
1733
        {
1734
            IWriter writer = ((IWriteable)drv).getWriter();
1735
            if (writer != null)
1736
            {
1737
                if (writer instanceof ISpatialWriter)
1738
                    return true;
1739
            }
1740
        }
1741
        return false;
1742

    
1743
    }
1744

    
1745
    public FLayer cloneLayer() throws Exception {
1746
        FLyrVect clonedLayer = new FLyrVect();
1747
        clonedLayer.setSource(getSource());
1748
        if (isJoined()) {
1749
                        clonedLayer.setIsJoined(true);
1750
                        clonedLayer.setRecordset(getRecordset());
1751
                }
1752
        clonedLayer.setVisible(isVisible());
1753
        clonedLayer.setISpatialIndex(getISpatialIndex());
1754
        clonedLayer.setName(getName());
1755
        clonedLayer.setCoordTrans(getCoordTrans());
1756

    
1757
        clonedLayer.setLegend((IVectorLegend)getLegend().cloneLegend());
1758

    
1759
        clonedLayer.setIsLabeled(isLabeled());
1760
        ILabelingStrategy labelingStrategy=getLabelingStrategy();
1761
        if (labelingStrategy!=null)
1762
                clonedLayer.setLabelingStrategy(labelingStrategy);
1763

    
1764
        return clonedLayer;
1765
    }
1766

    
1767

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

    
1772
    private boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, IGeometry geom, int[] xyCoords) {
1773
            boolean onePoint = false;
1774
            int type=geom.getGeometryType() % FShape.Z;
1775
            if (type!=FShape.POINT && type!=FShape.MULTIPOINT && type!=FShape.NULL) {
1776

    
1777
                        Rectangle2D geomBounds = geom.getBounds2D();
1778

    
1779
                //        ICoordTrans ct = getCoordTrans();
1780

    
1781
                        // Se supone que la geometria ya esta
1782
                        // repoyectada y no hay que hacer
1783
                        // ninguna transformacion
1784
//                        if (ct!=null) {
1785
////                                geomBounds = ct.getInverted().convert(geomBounds);
1786
//                                geomBounds = ct.convert(geomBounds);
1787
//                        }
1788

    
1789
                        double dist1Pixel = viewPort.getDist1pixel();
1790

    
1791
                        onePoint = (geomBounds.getWidth()  <= dist1Pixel
1792
                                         && geomBounds.getHeight() <= dist1Pixel);
1793

    
1794
                        if (onePoint) {
1795
                                // avoid out of range exceptions
1796
                                FPoint2D p = new FPoint2D(geomBounds.getMinX(), geomBounds.getMinY());
1797
                                p.transform(viewPort.getAffineTransform());
1798
                                p.transform(graphicsTransform);
1799
                                xyCoords[0] = (int) p.getX();
1800
                                xyCoords[1] = (int) p.getY();
1801

    
1802
                        }
1803

    
1804
                }
1805
            return onePoint;
1806
    }
1807
    /*
1808
     * jaume. Stuff from ILabeled.
1809
     */
1810
    private boolean isLabeled;
1811
    private ILabelingStrategy strategy;
1812

    
1813
    public boolean isLabeled() {
1814
        return isLabeled;
1815
    }
1816

    
1817
    public void setIsLabeled(boolean isLabeled) {
1818
        this.isLabeled = isLabeled;
1819
    }
1820

    
1821
    public ILabelingStrategy getLabelingStrategy() {
1822
        return strategy;
1823
    }
1824

    
1825
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1826
        this.strategy = strategy;
1827
        try {
1828
                        strategy.setLayer(this);
1829
                } catch (ReadDriverException e) {
1830
                        // TODO Auto-generated catch block
1831
                        e.printStackTrace();
1832
                }
1833
    }
1834

    
1835
    public void drawLabels(BufferedImage image, Graphics2D g, ViewPort viewPort,
1836
                    Cancellable cancel, double scale, double dpi) throws ReadDriverException {
1837
        if (strategy!=null && isWithinScale(scale)) {
1838
                strategy.draw(image, g, viewPort, cancel, dpi);
1839
        }
1840
    }
1841
    public void printLabels(Graphics2D g, ViewPort viewPort,
1842
                    Cancellable cancel, double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
1843
        if (strategy!=null) {
1844
                strategy.print(g, viewPort, cancel, properties);
1845
        }
1846
    }
1847

    
1848

    
1849
    //M?todos para el uso de HyperLinks en capas FLyerVect
1850

    
1851
    /**
1852
     * Return true, because a Vectorial Layer supports HyperLink
1853
     */
1854
    public boolean allowLinks()
1855
    {
1856
            return true;
1857
    }
1858

    
1859
    /**
1860
         * Returns an instance of AbstractLinkProperties that contains the information
1861
         * of the HyperLink
1862
         * @return Abstra
1863
         */
1864
    public AbstractLinkProperties getLinkProperties()
1865
    {
1866
            return linkProperties;
1867
    }
1868

    
1869
    /**
1870
         * Provides an array with URIs. Returns one URI by geometry that includes the point
1871
         * in its own geometry limits with a allowed tolerance.
1872
         * @param layer, the layer
1873
         * @param point, the point to check that is contained or not in the geometries in the layer
1874
         * @param tolerance, the tolerance allowed. Allowed margin of error to detect if the  point
1875
         *                 is contained in some geometries of the layer
1876
         * @return
1877
         */
1878
    public URI[] getLink(Point2D point, double tolerance)
1879
    {
1880
            //return linkProperties.getLink(this)
1881
            return linkProperties.getLink(this,point,tolerance);
1882
    }
1883
//    /**
1884
//     * @deprecated Don?t use Strategy, you should be use iterators.
1885
//     */
1886
//        public boolean isUseStrategy() {
1887
//                return useStrategy;
1888
//        }
1889
//        /**
1890
//     * @deprecated Don?t use Strategy, you should be use iterators.
1891
//     */
1892
//        public void setUseStrategy(boolean useStrategy) {
1893
//                this.useStrategy = useStrategy;
1894
//        }
1895
//
1896
//        @Override
1897
//        public void load() throws LoadLayerException {
1898
//                super.load();
1899
//                useStrategy=forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD;
1900
//        }
1901

    
1902
        public void selectionChanged(SelectionEvent e) {
1903
                this.updateDrawVersion();
1904
        }
1905

    
1906
        public void afterFieldEditEvent(AfterFieldEditEvent e) {
1907
                this.updateDrawVersion();
1908
        }
1909

    
1910
        public void afterRowEditEvent(IRow feat, AfterRowEditEvent e) {
1911
                this.updateDrawVersion();
1912

    
1913
        }
1914

    
1915
        public void beforeFieldEditEvent(BeforeFieldEditEvent e) {
1916

    
1917
        }
1918

    
1919
        public void beforeRowEditEvent(IRow feat, BeforeRowEditEvent e) {
1920

    
1921
        }
1922

    
1923
        public void processEvent(EditionEvent e) {
1924
                if (e.getChangeType()== e.ROW_EDITION){
1925
                        this.updateDrawVersion();
1926
                }
1927

    
1928
        }
1929

    
1930
        public void legendCleared(LegendClearEvent event) {
1931
                this.updateDrawVersion();
1932
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
1933
                legend, legend);
1934
        this.callLegendChanged(e);
1935
        }
1936

    
1937
        public boolean symbolChanged(SymbolLegendEvent e) {
1938
                this.updateDrawVersion();
1939
        LegendChangedEvent event = LegendChangedEvent.createLegendChangedEvent(
1940
                legend, legend);
1941
        this.callLegendChanged(event);
1942
        return true;
1943
        }
1944
        public String getTypeStringVectorLayer() throws ReadDriverException {
1945
                String typeString="";
1946
                int typeShape=((FLyrVect)this).getShapeType();
1947
                if (FShape.MULTI==typeShape){
1948
                        ReadableVectorial rv=((FLyrVect)this).getSource();
1949
                        int i=0;
1950
                        boolean isCorrect=false;
1951
                        while(rv.getShapeCount()>i && !isCorrect){
1952
                                IGeometry geom=rv.getShape(i);
1953
                                if (geom==null){
1954
                                        i++;
1955
                                        continue;
1956
                                }
1957
                                isCorrect=true;
1958
                                if ((geom.getGeometryType() & FShape.Z) == FShape.Z){
1959
                                        typeString="Geometries3D";
1960
                                }else{
1961
                                        typeString="Geometries2D";
1962
                                 }
1963
                         }
1964
                }else{
1965
                        ReadableVectorial rv=((FLyrVect)this).getSource();
1966
                        int i=0;
1967
                        boolean isCorrect=false;
1968
                        while(rv.getShapeCount()>i && !isCorrect){
1969
                                IGeometry geom=rv.getShape(i);
1970
                                if (geom==null){
1971
                                        i++;
1972
                                        continue;
1973
                                }
1974
                                isCorrect=true;
1975
                                int type=geom.getGeometryType();
1976
                                if (FShape.POINT == type){
1977
                                        typeString="Point2D";
1978
                                } else if (FShape.LINE == type){
1979
                                        typeString="Line2D";
1980
                                } else if (FShape.POLYGON == type){
1981
                                        typeString="Polygon2D";
1982
                                } else if (FShape.MULTIPOINT == type){
1983
                                        typeString="MultiPint2D";
1984
                                } else if ((FShape.POINT | FShape.Z)  == type ){
1985
                                        typeString="Point3D";
1986
                                } else if ((FShape.LINE | FShape.Z)  == type ){
1987
                                        typeString="Line3D";
1988
                                } else if ((FShape.POLYGON | FShape.Z)  == type ){
1989
                                        typeString="Polygon3D";
1990
                                } else if ((FShape.MULTIPOINT | FShape.Z)  == type ){
1991
                                        typeString="MultiPoint3D";
1992
                                } else if ((FShape.POINT | FShape.M)  == type ){
1993
                                        typeString="PointM";
1994
                                } else if ((FShape.LINE | FShape.M)  == type ){
1995
                                        typeString="LineM";
1996
                                } else if ((FShape.POLYGON | FShape.M)  == type ){
1997
                                        typeString="PolygonM";
1998
                                } else if ((FShape.MULTIPOINT | FShape.M)  == type ){
1999
                                        typeString="MultiPointM";
2000
                                } else if ((FShape.MULTI | FShape.M)  == type ){
2001
                                        typeString="M";
2002
                                }
2003

    
2004
                        }
2005
                        return typeString;
2006
                }
2007
                return "";
2008
        }
2009
        public int getTypeIntVectorLayer() throws ReadDriverException {
2010
                int typeInt=0;
2011
                int typeShape=((FLyrVect)this).getShapeType();
2012
                if (FShape.MULTI==typeShape){
2013
                        ReadableVectorial rv=((FLyrVect)this).getSource();
2014
                        int i=0;
2015
                        boolean isCorrect=false;
2016
                        while(rv.getShapeCount()>i && !isCorrect){
2017
                                IGeometry geom=rv.getShape(i);
2018
                                if (geom==null){
2019
                                        i++;
2020
                                        continue;
2021
                                }
2022
                                isCorrect=true;
2023
                                if ((geom.getGeometryType() & FShape.Z) == FShape.Z){
2024
                                        typeInt=FShape.MULTI | FShape.Z;
2025
                                }else{
2026
                                        typeInt=FShape.MULTI;
2027
                                }
2028
                        }
2029
                }else{
2030
                        ReadableVectorial rv=((FLyrVect)this).getSource();
2031
                        int i=0;
2032
                        boolean isCorrect=false;
2033
                        while(rv.getShapeCount()>i && !isCorrect){
2034
                                IGeometry geom=rv.getShape(i);
2035
                                if (geom==null){
2036
                                        i++;
2037
                                        continue;
2038
                                }
2039
                                isCorrect=true;
2040
                                int type=geom.getGeometryType();
2041
                                typeInt=type;
2042
                        }
2043
                        return typeInt;
2044
                }
2045
                return typeInt;
2046
        }
2047
 }