Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / layers / FLyrVect.java @ 16542

History | View | Annotate | Download (55.8 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.Color;
44
import java.awt.Graphics2D;
45
import java.awt.Point;
46
import java.awt.geom.AffineTransform;
47
import java.awt.geom.Point2D;
48
import java.awt.geom.Rectangle2D;
49
import java.awt.image.BufferedImage;
50
import java.io.File;
51
import java.net.URI;
52
import java.util.ArrayList;
53

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

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

    
60
import com.hardcode.driverManager.Driver;
61
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
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.hardcode.gdbms.engine.instruction.SemanticException;
66
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
67
import com.iver.cit.gvsig.exceptions.layers.LegendLayerException;
68
import com.iver.cit.gvsig.exceptions.layers.LoadLayerException;
69
import com.iver.cit.gvsig.exceptions.layers.ReloadLayerException;
70
import com.iver.cit.gvsig.exceptions.layers.StartEditionLayerException;
71
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException;
72
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
73
import com.iver.cit.gvsig.fmap.MapContext;
74
import com.iver.cit.gvsig.fmap.MapControl;
75
import com.iver.cit.gvsig.fmap.ViewPort;
76
import com.iver.cit.gvsig.fmap.core.CartographicSupport;
77
import com.iver.cit.gvsig.fmap.core.FPoint2D;
78
import com.iver.cit.gvsig.fmap.core.FShape;
79
import com.iver.cit.gvsig.fmap.core.IFeature;
80
import com.iver.cit.gvsig.fmap.core.IGeometry;
81
import com.iver.cit.gvsig.fmap.core.ILabelable;
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.FConverter;
85
import com.iver.cit.gvsig.fmap.core.v02.FSymbol;
86
import com.iver.cit.gvsig.fmap.drivers.BoundedShapes;
87
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
88
import com.iver.cit.gvsig.fmap.drivers.IVectorialDatabaseDriver;
89
import com.iver.cit.gvsig.fmap.drivers.IVectorialJDBCDriver;
90
import com.iver.cit.gvsig.fmap.drivers.VectorialDriver;
91
import com.iver.cit.gvsig.fmap.drivers.WithDefaultLegend;
92
import com.iver.cit.gvsig.fmap.edition.AnnotationEditableAdapter;
93
import com.iver.cit.gvsig.fmap.edition.EditionEvent;
94
import com.iver.cit.gvsig.fmap.edition.ISpatialWriter;
95
import com.iver.cit.gvsig.fmap.edition.IWriteable;
96
import com.iver.cit.gvsig.fmap.edition.IWriter;
97
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
98
import com.iver.cit.gvsig.fmap.edition.VectorialEditableDBAdapter;
99
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
100
import com.iver.cit.gvsig.fmap.layers.layerOperations.ClassifiableVectorial;
101
import com.iver.cit.gvsig.fmap.layers.layerOperations.InfoByPoint;
102
import com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData;
103
import com.iver.cit.gvsig.fmap.layers.layerOperations.SingleLayer;
104
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData;
105
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialXMLItem;
106
import com.iver.cit.gvsig.fmap.layers.layerOperations.XMLItem;
107
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
108
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy;
109
import com.iver.cit.gvsig.fmap.operations.strategies.StrategyManager;
110
import com.iver.cit.gvsig.fmap.rendering.IClassifiedVectorLegend;
111
import com.iver.cit.gvsig.fmap.rendering.ILegend;
112
import com.iver.cit.gvsig.fmap.rendering.IVectorLegend;
113
import com.iver.cit.gvsig.fmap.rendering.LegendChangedEvent;
114
import com.iver.cit.gvsig.fmap.rendering.LegendFactory;
115
import com.iver.cit.gvsig.fmap.rendering.SingleSymbolLegend;
116
import com.iver.cit.gvsig.fmap.rendering.ZSort;
117
import com.iver.cit.gvsig.fmap.rendering.styling.AttrInTableLabeling;
118
import com.iver.cit.gvsig.fmap.rendering.styling.ILabelingStrategy;
119
import com.iver.cit.gvsig.fmap.rendering.styling.LabelingFactory;
120
import com.iver.cit.gvsig.fmap.spatialindex.IPersistentSpatialIndex;
121
import com.iver.cit.gvsig.fmap.spatialindex.ISpatialIndex;
122
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeGt2;
123
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeJts;
124
import com.iver.cit.gvsig.fmap.spatialindex.SpatialIndexException;
125
import com.iver.utiles.FileUtils;
126
import com.iver.utiles.IPersistence;
127
import com.iver.utiles.NotExistInXMLEntity;
128
import com.iver.utiles.PostProcessSupport;
129
import com.iver.utiles.XMLEntity;
130
import com.iver.utiles.swing.threads.Cancellable;
131
import com.iver.utiles.swing.threads.CancellableMonitorable;
132

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

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

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

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

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

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

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

    
195

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

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

    
237
    }
238

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

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

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

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

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

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

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

    
313
            return rAux;
314
    }
315

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

    
335

    
336

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

    
345
                    try {
346
                            prepareDrawing(image, g, viewPort);
347
                            ArrayList<String> fieldList = new ArrayList<String>();
348

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

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

    
358
                            }
359

    
360
                            // fields from labeling
361
                            if (getLabelingStrategy()!=null && isLabeled()) {
362
                                    aux = getLabelingStrategy().getUsedFields();
363
                                    for (int i = 0; i < aux.length; i++) {
364
                                            fieldList.add(aux[i]);
365
                                    }
366
                            }
367

    
368
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
369

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

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

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

    
390
                                    }
391
                            }
392
                            // -- end visual FX stuff
393

    
394
                            // Get the iterator over the visible features
395
                            IFeatureIterator it = getSource().getFeatureIterator(
396
                                            viewPort.getAdjustedExtent(),
397
                                            fieldList.toArray(new String[fieldList.size()]),
398
                                            viewPort.getProjection(),
399
                                            true);
400

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

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

    
413
                                    // retrieve the symbol associated to such feature
414
                                    ISymbol sym = legend.getSymbolByFeature(feat);
415

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

    
430
                                    // Check if this symbol is sized with CartographicSupport
431
                                    CartographicSupport csSym = null;
432
                                    int symbolType = sym.getSymbolType();
433
                                    boolean bDrawCartographicSupport = false;
434

    
435
                                    if (   symbolType == FShape.POINT
436
                                                    || symbolType == FShape.LINE
437
                                                    || sym instanceof CartographicSupport) {
438

    
439
//                                             patch
440
                                        if (!sym.getClass().equals(FSymbol.class)) {
441
                                                csSym = (CartographicSupport) sym;
442
                                                bDrawCartographicSupport = (csSym.getUnit() != -1);
443
                                        }
444
                                    }
445

    
446
                                    int x = -1;
447
                                    int y = -1;
448
                                    int[] xyCoords = new int[2];
449

    
450
                                    // Check if size is a pixel
451
                                    boolean onePoint = bDrawCartographicSupport ?
452
                                                    isOnePoint(g.getTransform(), viewPort, MapContext.getScreenDPI(), csSym, geom, xyCoords) :
453
                                                    isOnePoint(g.getTransform(), viewPort, geom, xyCoords);
454

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

    
462
                                        if (useZSort) {
463
                                                // Check if this symbol is a multilayer
464
                                                if (sym instanceof IMultiLayerSymbol) {
465
                                                        // if so, treat each of its layers as a single symbol
466
                                                        // in its corresponding map level
467
                                                        IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
468
                                                        for (int i = 0; i < mlSym.getLayerCount(); i++) {
469
                                                                ISymbol mySym = mlSym.getLayer(i);
470
                                                                if (onePoint) {
471
                                                                        if (x<0 || y<0 || x>= imageLevels[zSort.getSymbolLevel(mySym)].getWidth() || y>=imageLevels[zSort.getSymbolLevel(mySym)].getHeight()) continue;
472
                                                                        imageLevels[zSort.getSymbolLevel(mySym)].setRGB(x, y, mySym.getOnePointRgb());
473
                                                                } else {
474
                                                                        if (!bDrawCartographicSupport) {
475
                                                                                geom.drawInts(graphics[zSort.getSymbolLevel(mySym)], viewPort, mySym, cancel);
476
                                                                        } else {
477
                                                                                geom.drawInts(graphics[zSort.getSymbolLevel(mySym)], viewPort, dpi, (CartographicSupport) mySym);
478
                                                                        }
479
                                                                }
480
                                                        }
481
                                                } else {
482
                                                        // else, just draw the symbol in its level
483
                                                        if (!bDrawCartographicSupport) {
484
                                                                geom.drawInts(graphics[zSort.getSymbolLevel(sym)], viewPort, sym, cancel);
485
                                                        } else {
486
                                                                geom.drawInts(graphics[zSort.getSymbolLevel(sym)], viewPort, dpi, (CartographicSupport) csSym);
487
                                                        }
488
                                                }
489

    
490
                                                // -- visual FX stuff
491
                                                // Cuando el offset!=0 se est? dibujando sobre el Layout y por tanto no tiene que ejecutar el siguiente c?digo.
492
                                                if (offset.getX()==0 && offset.getY()==0)
493
                                                        if ((System.currentTimeMillis() - time) > screenRefreshDelay) {
494
                                                                virtualBim = new BufferedImage(image.getWidth(),image.getHeight(),BufferedImage.TYPE_INT_ARGB);
495
                                                                virtualGraphics = virtualBim.createGraphics();
496
                                                                virtualGraphics.drawImage(image,0,0, null);
497
                                                                for (int i = 0; i < imageLevels.length; i++) {
498
                                                                        virtualGraphics.drawImage(imageLevels[i],0,0, null);
499
                                                                }
500
                                                                g.clearRect(0, 0, image.getWidth(), image.getHeight());
501
                                                                g.drawImage(virtualBim, 0, 0, null);
502
                                                                time = System.currentTimeMillis();
503
                                                        }
504
                                                // -- end visual FX stuff
505

    
506
                                        } else {
507
                                                // no ZSort, so there is only a map level, symbols are
508
                                                // just drawn.
509
                                                if (onePoint) {
510
                                                        if (x<0 || y<0 || x>= image.getWidth() || y>=image.getHeight()) continue;
511
                                                        image.setRGB(x, y, sym.getOnePointRgb());
512
                                                } else {
513
                                                        if (!bDrawCartographicSupport) {
514
                                                                geom.drawInts(g, viewPort, sym, cancel);
515
                                                        } else {
516
                                                                geom.drawInts(g, viewPort, dpi, csSym);
517
                                                        }
518
                                                }
519
                                        }
520
                            }
521

    
522
                            if (useZSort) {
523
                                    g.drawImage(image, 0, 0, null);
524
                                        g.translate(offset.getX(), offset.getY());
525
                                    for (int i = 0; i < imageLevels.length; i++) {
526
                                            g.drawImage(imageLevels[i],0,0, null);
527
                                            imageLevels[i] = null;
528
                                            graphics[i] = null;
529
                                    }
530
                                        g.translate(-offset.getX(), -offset.getY());
531
                                    imageLevels = null;
532
                                    graphics = null;
533
                            }
534
                            it.closeIterator();
535
                    } catch (ReadDriverException e) {
536
                            this.setVisible(false);
537
                            this.setActive(false);
538
                            throw e;
539
                    }
540
            }
541
    }
542

    
543
           public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
544
            Cancellable cancel, double scale) throws ReadDriverException {
545
//            forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD = true;
546
            if (!isUseStrategy()) {
547
                    _draw(image, g, viewPort, cancel, scale);
548
            } else {
549
//                    moved up to FLayers
550
//                    if (isWithinScale(scale)) {
551

    
552

    
553
                            // Las que solo tienen etiquetado sin pintar el shape,
554
                            // no pasamos por ellas
555
                            boolean bDrawShapes = true;
556
                            if (legend instanceof SingleSymbolLegend) {
557
                                    if (legend.getDefaultSymbol().isShapeVisible() == false)
558
                                            bDrawShapes = false;
559
                            }
560
                            if (bDrawShapes) {
561
                                    Strategy strategy = StrategyManager.getStrategy(this);
562
                                    try {
563
                                            prepareDrawing(image, g, viewPort);
564
                                            strategy.draw(image, g, viewPort, cancel);
565
                                    } catch (ReadDriverException e) {
566
                                            this.setVisible(false);
567
                                            this.setActive(false);
568
                                            throw e;
569
                                    }
570
                            }
571
                            if (getVirtualLayers() != null) {
572
                                    getVirtualLayers().draw(image, g, viewPort, cancel, scale);
573
                            }
574
//                    }
575
            }
576
    }
577

    
578
    /**
579
     * Se llama antes de empezar a pintar.
580
     * Es ?til para preparar la cache a emplear, las leyendas, etc.
581
     * @param image
582
     * @param g
583
     * @param viewPort
584
     */
585
    private void prepareDrawing(BufferedImage image, Graphics2D g, ViewPort viewPort) {
586

    
587
    }
588

    
589
    public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
590
                    double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
591
            // TEST METHOD
592

    
593
            boolean bDrawShapes = true;
594
            if (legend instanceof SingleSymbolLegend) {
595
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
596
            }
597

    
598

    
599
            if (bDrawShapes) {
600
                    double dpi = 72;
601

    
602
                    PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
603
                    if (resolution.equals(PrintQuality.NORMAL)){
604
                            dpi = 300;
605
                    } else if (resolution.equals(PrintQuality.HIGH)){
606
                            dpi = 600;
607
                    } else if (resolution.equals(PrintQuality.DRAFT)){
608
                            dpi = 72;
609
                    }
610

    
611

    
612
                    try {
613
                            prepareDrawing(null, g, viewPort);
614
                            ArrayList<String> fieldList = new ArrayList<String>();
615
                            String[] aux;
616

    
617
                            // fields from legend
618
                            if (legend instanceof IClassifiedVectorLegend) {
619
                                    aux = ((IClassifiedVectorLegend) legend).
620
                                                                            getClassifyingFieldNames();
621
                                    for (int i = 0; i < aux.length; i++) {
622
                                            fieldList.add(aux[i]);
623
                                    }
624
                            }
625

    
626
                            // fields from labeling
627
                            if (isLabeled()) {
628
                                    aux = getLabelingStrategy().getUsedFields();
629
                                    for (int i = 0; i < aux.length; i++) {
630
                                            fieldList.add(aux[i]);
631
                                    }
632
                            }
633

    
634
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
635

    
636
                            // if layer has map levels it will use a ZSort
637
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
638

    
639

    
640
                            int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
641
                            for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
642
                                    // Get the iterator over the visible features
643
                                    IFeatureIterator it = getSource().getFeatureIterator(
644
                                                    viewPort.getAdjustedExtent(),
645
                                                    fieldList.toArray(new String[fieldList.size()]),
646
                                                    viewPort.getProjection(),
647
                                                    true);
648

    
649
                                    // Iteration over each feature
650
                                    while ( !cancel.isCanceled() && it.hasNext()) {
651
                                            IFeature feat = it.next();
652
                                            IGeometry geom = feat.getGeometry();
653

    
654
                                            // retreive the symbol associated to such feature
655
                                            ISymbol sym = legend.getSymbolByFeature(feat);
656

    
657
                                            if (useZSort) {
658
                                                    // Check if this symbol is a multilayer
659
                                                        if (sym instanceof IMultiLayerSymbol) {
660
                                                                // if so, get the layer corresponding to the current
661
                                                                // level. If none, continue to next iteration
662
                                                                IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
663
                                                                for (int i = 0; i < mlSym.getLayerCount(); i++) {
664
                                                                        ISymbol mySym = mlSym.getLayer(i);
665
                                                                        if (zSort.getSymbolLevel(mySym) == mapPass) {
666
                                                                                sym = mySym;
667
                                                                                break;
668
                                                                        }
669
                                                                        System.out.println("avoided layer "+i+"of symbol '"+mlSym.getDescription()+"' (pass "+mapPass+")");
670
                                                                }
671

    
672
                                                                if (sym == null) {
673
                                                                        continue;
674
                                                                }
675
                                                        } else {
676
                                                                // else, just draw the symbol in its level
677
                                                                if (zSort.getSymbolLevel(sym) != mapPass) {
678
                                                                        System.out.println("avoided single layer symbol '"+sym.getDescription()+"' (pass "+mapPass+")");
679
                                                                        continue;
680
                                                                }
681
                                                        }
682
                                            }
683

    
684
                                            // Check if this symbol is sized with CartographicSupport
685
                                            CartographicSupport csSym = null;
686
                                            int symbolType = sym.getSymbolType();
687
                                            boolean bDrawCartographicSupport = false;
688

    
689
                                            if (   symbolType == FShape.POINT
690
                                                            || symbolType == FShape.LINE
691
                                                            || sym instanceof CartographicSupport) {
692

    
693
                                                    csSym = (CartographicSupport) sym;
694
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
695
                                            }
696

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

    
699
                                            if (!bDrawCartographicSupport) {
700
                                                    geom.drawInts(g, viewPort, sym, null);
701
                                            } else {
702
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym);
703
                                            }
704

    
705
                                    }
706
                                    it.closeIterator();
707
                            }
708
                    } catch (ReadDriverException e) {
709
                            this.setVisible(false);
710
                            this.setActive(false);
711
                            throw e;
712
                    }
713
            }
714
    }
715

    
716

    
717
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
718
            double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
719
            if (forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
720
                    _print(g, viewPort, cancel, scale, properties);
721
            } else {
722
//                    moved up to Flayers
723
//                    if (isVisible() && isWithinScale(scale)) {
724
                            Strategy strategy = StrategyManager.getStrategy(this);
725

    
726
                            strategy.print(g, viewPort, cancel, properties);
727
                            ILabelingStrategy labeling;
728
                            if ( (labeling = getLabelingStrategy() ) != null) {
729
                                    // contains labels
730
                                    labeling.print(g, viewPort, cancel, properties);
731
                            }
732
//                    }
733
            }
734
    }
735

    
736
    public void deleteSpatialIndex() {
737
        //must we delete possible spatial indexes files?
738
        spatialIndex = null;
739
    }
740

    
741
   /**
742
    * <p>
743
    * Creates an spatial index associated to this layer.
744
    * The spatial index will used
745
    * the native projection of the layer, so if the layer is reprojected, it will
746
    * be ignored.
747
    * </p>
748
    * @param cancelMonitor instance of CancellableMonitorable that allows
749
    * to monitor progress of spatial index creation, and cancel the process
750
    */
751
    public void createSpatialIndex(CancellableMonitorable cancelMonitor){
752
         // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
753
        // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
754
        // para que acepten recorrer sin geometria, solo con rectangulos.
755

    
756
        //If this vectorial layer is based in a spatial database, the spatial
757
        //index is already implicit. We only will index file drivers
758
        ReadableVectorial va = getSource();
759
        //We must think in non spatial databases, like HSQLDB
760
        if(!(va instanceof VectorialFileAdapter)){
761
            return;
762
        }
763
        if (!(va.getDriver() instanceof BoundedShapes)) {
764
            return;
765
        }
766
        File file = ((VectorialFileAdapter) va).getFile();
767
        String fileName = file.getAbsolutePath();
768
        ISpatialIndex localCopy = null;
769
        try {
770
            va.start();
771
            localCopy = new QuadtreeGt2(fileName, "NM", va.getFullExtent(),
772
                    va.getShapeCount(), true);
773

    
774
        } catch (SpatialIndexException e1) {
775
            // Probably we dont have writing permissions
776
            String directoryName = System.getProperty("java.io.tmpdir");
777
            File newFile = new File(directoryName +
778
                    File.separator +
779
                    file.getName());
780
            String newFileName = newFile.getName();
781
            try {
782
                localCopy = new QuadtreeGt2(newFileName, "NM", va.getFullExtent(),
783
                        va.getShapeCount(), true);
784
            } catch (SpatialIndexException e) {
785
                // if we cant build a file based spatial index, we'll build
786
                // a pure memory spatial index
787
                localCopy = new QuadtreeJts();
788
            } catch (ReadDriverException e) {
789
                localCopy = new QuadtreeJts();
790
            }
791

    
792
        } catch(Exception e){
793
            e.printStackTrace();
794
        }//try
795
        BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
796
        try {
797
            for (int i=0; i < va.getShapeCount(); i++)
798
            {
799
                if(cancelMonitor != null){
800
                    if(cancelMonitor.isCanceled())
801
                        return;
802
                    cancelMonitor.reportStep();
803
                }
804
                Rectangle2D r = shapeBounds.getShapeBounds(i);
805
                if(r != null)
806
                    localCopy.insert(r, i);
807
            } // for
808
            va.stop();
809
            if(localCopy instanceof IPersistentSpatialIndex)
810
                ((IPersistentSpatialIndex) localCopy).flush();
811
            spatialIndex = localCopy;
812
            //vectorial adapter needs a reference to the spatial index, to solve
813
            //request for feature iteration based in spatial queries
814
            source.setSpatialIndex(spatialIndex);
815
        } catch (ReadDriverException e) {
816
            // TODO Auto-generated catch block
817
            e.printStackTrace();
818
        }
819
    }
820

    
821
    public void createSpatialIndex() {
822
        createSpatialIndex(null);
823
    }
824

    
825
    public void process(FeatureVisitor visitor, FBitSet subset)
826
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
827
        Strategy s = StrategyManager.getStrategy(this);
828
        s.process(visitor, subset);
829
    }
830

    
831
    public void process(FeatureVisitor visitor) throws ReadDriverException, VisitorException {
832
        Strategy s = StrategyManager.getStrategy(this);
833
        s.process(visitor);
834
    }
835

    
836
    public void process(FeatureVisitor visitor, Rectangle2D rect)
837
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
838
        Strategy s = StrategyManager.getStrategy(this);
839
        s.process(visitor, rect);
840
    }
841

    
842
    public FBitSet queryByRect(Rectangle2D rect) throws ReadDriverException, VisitorException {
843
        Strategy s = StrategyManager.getStrategy(this);
844

    
845
        return s.queryByRect(rect);
846
    }
847

    
848
    public FBitSet queryByPoint(Point2D p, double tolerance)
849
            throws ReadDriverException, VisitorException {
850
        Strategy s = StrategyManager.getStrategy(this);
851
        return s.queryByPoint(p, tolerance);
852
    }
853

    
854
    public FBitSet queryByShape(IGeometry g, int relationship)
855
            throws ReadDriverException, VisitorException {
856
        Strategy s = StrategyManager.getStrategy(this);
857
        return s.queryByShape(g, relationship);
858
    }
859

    
860
    public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancel) throws ReadDriverException, VisitorException {
861
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(p);
862
        FBitSet bs = queryByPoint(pReal, tolerance);
863
        VectorialXMLItem[] item = new VectorialXMLItem[1];
864
        item[0] = new VectorialXMLItem(bs, this);
865

    
866
        return item;
867
    }
868

    
869
    public void setLegend(IVectorLegend r) throws LegendLayerException {
870
        IVectorLegend oldLegend = legend;
871
        legend = r;
872
        try {
873
            legend.setDataSource(getRecordset());
874
        } catch (FieldNotFoundException e1) {
875
            throw new LegendLayerException(getName(),e1);
876
        } catch (ReadDriverException e1) {
877
            throw new LegendLayerException(getName(),e1);
878
        }
879
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
880
                oldLegend, legend);
881
        callLegendChanged(e);
882
    }
883

    
884
    /**
885
     * Devuelve la Leyenda de la capa.
886
     *
887
     * @return Leyenda.
888
     */
889
    public ILegend getLegend() {
890
        return legend;
891
    }
892

    
893
    /**
894
     * Devuelve el tipo de shape que contiene la capa.
895
     *
896
     * @return tipo de shape.
897
     *
898
     * @throws DriverException
899
     */
900
    public int getShapeType() throws ReadDriverException {
901
        if (typeShape == -1) {
902
            getSource().start();
903
            typeShape = getSource().getShapeType();
904
            getSource().stop();
905
        }
906

    
907
        return typeShape;
908
    }
909

    
910
    public XMLEntity getXMLEntity() throws XMLException {
911
        if (!this.isAvailable() && this.orgXMLEntity != null) {
912
            return this.orgXMLEntity;
913
        }
914
        XMLEntity xml = super.getXMLEntity();
915
        if (getLegend()!=null)
916
            xml.addChild(getLegend().getXMLEntity());
917
        try {
918
            if (getRecordset()!=null)
919
                xml.addChild(getRecordset().getSelectionSupport().getXMLEntity());
920
        } catch (ReadDriverException e1) {
921
            e1.printStackTrace();
922
            throw new XMLException(e1);
923
        }
924
        // Repongo el mismo ReadableVectorial m?s abajo para cuando se guarda el proyecto.
925
        ReadableVectorial rv=getSource();
926
        xml.putProperty("type", "vectorial");
927
        if (source instanceof VectorialEditableAdapter) {
928
            setSource(((VectorialEditableAdapter) source).getOriginalAdapter());
929
        }
930
        if (source instanceof VectorialFileAdapter) {
931
            xml.putProperty("type", "vectorial");
932
            xml.putProperty("file", ((VectorialFileAdapter) source)
933
                    .getFile());
934
            try {
935
                xml.putProperty("recordset-name", source.getRecordset()
936
                        .getName());
937
            } catch (ReadDriverException e) {
938
                throw new XMLException(e);
939
            } catch (RuntimeException e) {
940
                e.printStackTrace();
941
            }
942
        } else if (source instanceof VectorialDBAdapter) {
943
            xml.putProperty("type", "vectorial");
944

    
945
            IVectorialDatabaseDriver dbDriver = (IVectorialDatabaseDriver) source
946
                    .getDriver();
947

    
948
            // Guardamos el nombre del driver para poder recuperarlo
949
            // con el DriverManager de Fernando.
950
            xml.putProperty("db", dbDriver.getName());
951
            try {
952
                xml.putProperty("recordset-name", source.getRecordset()
953
                        .getName());
954
            } catch (ReadDriverException e) {
955
                throw new XMLException(e);
956
            } catch (RuntimeException e) {
957
                e.printStackTrace();
958
            }
959
            xml.addChild(dbDriver.getXMLEntity()); // Tercer child. Antes hemos
960
                                                    // metido la leyenda y el
961
                                                    // selection support
962
        } else if (source instanceof VectorialAdapter) {
963
            // Se supone que hemos hecho algo gen?rico.
964
            xml.putProperty("type", "vectorial");
965

    
966
            VectorialDriver driver = source.getDriver();
967

    
968
            // Guardamos el nombre del driver para poder recuperarlo
969
            // con el DriverManager de Fernando.
970
            xml.putProperty("other", driver.getName());
971
            // try {
972
            try {
973
                xml.putProperty("recordset-name", source.getRecordset()
974
                        .getName());
975
            } catch (ReadDriverException e) {
976
                throw new XMLException(e);
977
            } catch (RuntimeException e) {
978
                e.printStackTrace();
979
            }
980
            if (driver instanceof IPersistence) {
981
                // xml.putProperty("className", driver.getClass().getName());
982
                    IPersistence persist = (IPersistence) driver;
983
                xml.addChild(persist.getXMLEntity()); // Tercer child. Antes
984
                                                        // hemos metido la
985
                                                        // leyenda y el
986
                                                        // selection support
987
            }
988
        }
989
        if (rv!=null)
990
            setSource(rv);
991
        xml.putProperty("driverName", source.getDriver().getName());
992
        if (bHasJoin)
993
            xml.putProperty("hasJoin", "true");
994

    
995
        // properties from ILabelable
996
        xml.putProperty("isLabeled", isLabeled);
997
        if (strategy != null) {
998
            XMLEntity strategyXML = strategy.getXMLEntity();
999
            strategyXML.putProperty("Strategy", strategy.getClassName());
1000
            xml.addChild(strategy.getXMLEntity());
1001
        }
1002
        xml.addChild(getLinkProperties().getXMLEntity());
1003
        return xml;
1004
    }
1005

    
1006
    /**
1007
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1008
     */
1009
    public void setXMLEntity03(XMLEntity xml) throws XMLException {
1010

    
1011
        super.setXMLEntity(xml);
1012
        legend = LegendFactory.createFromXML03(xml.getChild(0));
1013

    
1014
        try {
1015
            setLegend(legend);
1016
        } catch (LegendLayerException e) {
1017
            throw new XMLException(e);
1018
        }
1019

    
1020
        try {
1021
            getRecordset().getSelectionSupport()
1022
                    .setXMLEntity03(xml.getChild(1));
1023
        } catch (ReadDriverException e) {
1024
            e.printStackTrace();
1025
        }
1026
    }
1027

    
1028
    /*
1029
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1030
     */
1031
    public void setXMLEntity(XMLEntity xml) throws XMLException {
1032
        try {
1033
            super.setXMLEntity(xml);
1034
            XMLEntity legendXML = xml.getChild(0);
1035
            IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1036
            /* (jaume) begin patch;
1037
             * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1038
             * no longer managed by the Legend but by the ILabelingStrategy. The
1039
             * following allows restoring older projects' labelings.
1040
             */
1041
            if (legendXML.contains("labelFieldName")) {
1042
                String labelTextField = legendXML.getStringProperty("labelFieldName");
1043
                if (labelTextField != null) {
1044
                    AttrInTableLabeling labeling = new AttrInTableLabeling();
1045
                    labeling.setLayer(this);
1046
                    labeling.setTextField(legendXML.getStringProperty("labelFieldName"));
1047
                    labeling.setHeightField(legendXML.getStringProperty("labelHeightFieldName"));
1048
                    labeling.setRotationField(legendXML.getStringProperty("labelRotationFieldName"));
1049
                    this.setLabelingStrategy(labeling);
1050
                    this.setIsLabeled(true);
1051
                }
1052
              }
1053
            /* end patch */
1054
            try {
1055
                getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1056
                // JMVIVO: Esto sirve para algo????
1057
                String recordsetName = xml.getStringProperty("recordset-name");
1058

    
1059
                LayerFactory.getDataSourceFactory().changeDataSourceName(
1060
                        getSource().getRecordset().getName(), recordsetName);
1061
            } catch (NoSuchTableException e1) {
1062
                this.setAvailable(false);
1063
                throw new XMLException(e1);
1064
            } catch (ReadDriverException e1) {
1065
                this.setAvailable(false);
1066
                throw new XMLException(e1);
1067
            }
1068
            // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1069
            // el final
1070
            // de la lectura del proyecto
1071
            if (xml.contains("hasJoin")) {
1072
                setIsJoined(true);
1073
                PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1074
            } else {
1075
                try {
1076

    
1077
                    setLegend(leg);
1078
                } catch (LegendLayerException e) {
1079
                    throw new XMLException(e);
1080
                }
1081
            }
1082

    
1083
            // set properties for ILabelable
1084
            for (int i = 0; i < xml.getChildrenCount(); i++) {
1085
                try {
1086
                    if (xml.getChild(i).contains("Strategy")) {
1087
                        XMLEntity xmlStrategy = xml.getChild(i);
1088
                        this.strategy = LabelingFactory.createStrategyFromXML(xmlStrategy.getChild(0));
1089
                    }
1090
                } catch (NotExistInXMLEntity neXMLEX) {
1091
                    // no strategy was set, just continue;
1092
                    logger.warn("Reached what should be unreachable code");
1093
                }
1094
            }
1095

    
1096
            XMLEntity xmlLinkProperties=xml.firstChild("typeChild","linkProperties");
1097
            if (xmlLinkProperties != null){
1098
                     getLinkProperties().setXMLEntity(xmlLinkProperties);
1099
            }
1100

    
1101
        } catch (XMLException e) {
1102
            this.setAvailable(false);
1103
            this.orgXMLEntity = xml;
1104
        } catch (Exception e) {
1105
            e.printStackTrace();
1106
            this.setAvailable(false);
1107
            this.orgXMLEntity = xml;
1108

    
1109
        }
1110

    
1111

    
1112
    }
1113

    
1114
    public void setXMLEntityNew(XMLEntity xml) throws XMLException {
1115
        try {
1116
            super.setXMLEntity(xml);
1117

    
1118
            XMLEntity legendXML = xml.getChild(0);
1119
            IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1120
            /* (jaume) begin patch;
1121
             * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1122
             * no longer managed by the Legend but by the ILabelingStrategy. The
1123
             * following allows restoring older projects' labelings.
1124
             */
1125
            if (legendXML.contains("labelFieldHeight")) {
1126
                AttrInTableLabeling labeling = new AttrInTableLabeling();
1127
                labeling.setLayer(this);
1128
                labeling.setTextField(legendXML.getStringProperty("labelFieldHeight"));
1129
                labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
1130
                this.setLabelingStrategy(labeling);
1131
                this.setIsLabeled(true);
1132
              }
1133
            /* end patch */
1134
            try {
1135
                getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1136

    
1137
                this.setLoadSelection(xml.getChild(1));
1138
            } catch (ReadDriverException e1) {
1139
                this.setAvailable(false);
1140
                throw new XMLException(e1);
1141
            }
1142
            // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1143
            // el final
1144
            // de la lectura del proyecto
1145
            if (xml.contains("hasJoin")) {
1146
                setIsJoined(true);
1147
                PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1148
            } else {
1149
                this.setLoadLegend(leg);
1150
            }
1151

    
1152
        } catch (XMLException e) {
1153
            this.setAvailable(false);
1154
            this.orgXMLEntity = xml;
1155
        } catch (Exception e) {
1156
            this.setAvailable(false);
1157
            this.orgXMLEntity = xml;
1158
        }
1159

    
1160

    
1161
    }
1162

    
1163

    
1164
    /**
1165
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
1166
     * identifiquen la capa.
1167
     *
1168
     * @return DOCUMENT ME!
1169
     */
1170
    public String toString() {
1171
        /*
1172
         * Se usa internamente para que la parte de datos identifique de forma
1173
         * un?voca las tablas
1174
         */
1175
        String ret = super.toString();
1176

    
1177
        return "layer" + ret.substring(ret.indexOf('@') + 1);
1178
    }
1179

    
1180
    public boolean isJoined() {
1181
        return bHasJoin;
1182
    }
1183

    
1184
    /**
1185
     * Returns if a layer is spatially indexed
1186
     *
1187
     * @return if this layer has the ability to proces spatial queries without
1188
     *         secuential scans.
1189
     */
1190
    public boolean isSpatiallyIndexed() {
1191
        ReadableVectorial source = getSource();
1192
        if (source instanceof ISpatialDB)
1193
            return true;
1194

    
1195
//FIXME azabala
1196
/*
1197
 * Esto es muy dudoso, y puede cambiar.
1198
 * Estoy diciendo que las que no son fichero o no son
1199
 * BoundedShapes estan indexadas. Esto es mentira, pero
1200
 * as? quien pregunte no querr? generar el indice.
1201
 * Esta por ver si interesa generar el indice para capas
1202
 * HSQLDB, WFS, etc.
1203
 */
1204
        if(!(source instanceof VectorialFileAdapter)){
1205
            return true;
1206
        }
1207
        if (!(source.getDriver() instanceof BoundedShapes)) {
1208
            return true;
1209
        }
1210

    
1211
        if (getISpatialIndex() != null)
1212
            return true;
1213
        return false;
1214
    }
1215

    
1216
    public void setIsJoined(boolean hasJoin) {
1217
        bHasJoin = hasJoin;
1218
    }
1219

    
1220
    /**
1221
     * @return Returns the spatialIndex.
1222
     */
1223
    public ISpatialIndex getISpatialIndex() {
1224
        return spatialIndex;
1225
    }
1226
    /**
1227
     * Sets the spatial index. This could be useful if, for some
1228
     * reasons, you want to work with a distinct spatial index
1229
     * (for example, a spatial index which could makes nearest
1230
     * neighbour querys)
1231
     * @param spatialIndex
1232
     */
1233
    public void setISpatialIndex(ISpatialIndex spatialIndex){
1234
        this.spatialIndex = spatialIndex;
1235
    }
1236

    
1237
    public SelectableDataSource getRecordset() throws ReadDriverException {
1238
        if (!this.isAvailable()) return null;
1239
        if (sds == null) {
1240

    
1241
                SelectableDataSource ds = source.getRecordset();
1242

    
1243
                if (ds == null) {
1244
                    return null;
1245
                }
1246

    
1247
                sds = ds;
1248
                sds.setSelectionSupport(selectionSupport);
1249

    
1250
        }
1251
        return sds;
1252
    }
1253

    
1254
    public void setEditing(boolean b) throws StartEditionLayerException {
1255
        super.setEditing(b);
1256
        try {
1257
            if (b) {
1258
                VectorialEditableAdapter vea = null;
1259
                // TODO: Qu? pasa si hay m?s tipos de adapters?
1260
                // FJP: Se podr?a pasar como argumento el
1261
                // VectorialEditableAdapter
1262
                // que se quiera usar para evitar meter c?digo aqu? de este
1263
                // estilo.
1264
                if (getSource() instanceof VectorialDBAdapter) {
1265
                    vea = new VectorialEditableDBAdapter();
1266
                } else if (this instanceof FLyrAnnotation) {
1267
                    vea = new AnnotationEditableAdapter(
1268
                            (FLyrAnnotation) this);
1269
                } else {
1270
                    vea = new VectorialEditableAdapter();
1271
                }
1272
                vea.setOriginalVectorialAdapter(getSource());
1273
//                                azo: implementations of readablevectorial need
1274
                //references of projection and spatial index
1275
                vea.setProjection(getProjection());
1276
                vea.setSpatialIndex(spatialIndex);
1277

    
1278

    
1279
                // /vea.setSpatialIndex(getSpatialIndex());
1280
                // /vea.setFullExtent(getFullExtent());
1281
                vea.setCoordTrans(getCoordTrans());
1282
                vea.startEdition(EditionEvent.GRAPHIC);
1283
                setSource(vea);
1284
                getRecordset().setSelectionSupport(
1285
                        vea.getOriginalAdapter().getRecordset()
1286
                                .getSelectionSupport());
1287

    
1288
            } else {
1289
                VectorialEditableAdapter vea = (VectorialEditableAdapter) getSource();
1290
                setSource(vea.getOriginalAdapter());
1291
            }
1292
            // Si tenemos una leyenda, hay que pegarle el cambiazo a su
1293
            // recordset
1294
            setRecordset(getSource().getRecordset());
1295
            if (getLegend() instanceof IVectorLegend) {
1296
                IVectorLegend ley = (IVectorLegend) getLegend();
1297
                ley.setDataSource(getSource().getRecordset());
1298
                // Esto lo pongo para evitar que al dibujar sobre un
1299
                // dxf, dwg, o dgn no veamos nada. Es debido al checkbox
1300
                // de la leyenda de textos "dibujar solo textos".
1301
//jaume
1302
//                                if (!(getSource().getDriver() instanceof IndexedShpDriver)){
1303
//                                        FSymbol symbol=new FSymbol(getShapeType());
1304
//                                        symbol.setFontSizeInPixels(false);
1305
//                                        symbol.setFont(new Font("SansSerif", Font.PLAIN, 9));
1306
//                                        Color color=symbol.getColor();
1307
//                                        int alpha=symbol.getColor().getAlpha();
1308
//                                        if (alpha>250) {
1309
//                                                symbol.setColor(new Color(color.getRed(),color.getGreen(),color.getBlue(),100));
1310
//                                        }
1311
//                                        ley.setDefaultSymbol(symbol);
1312
//                                }
1313
//jaume//
1314
                ley.useDefaultSymbol(true);
1315
            }
1316
        } catch (ReadDriverException e) {
1317
            throw new StartEditionLayerException(getName(),e);
1318
        } catch (FieldNotFoundException e) {
1319
            throw new StartEditionLayerException(getName(),e);
1320
        } catch (StartWriterVisitorException e) {
1321
            throw new StartEditionLayerException(getName(),e);
1322
        }
1323

    
1324
        setSpatialCacheEnabled(b);
1325
        callEditionChanged(LayerEvent
1326
                .createEditionChangedEvent(this, "edition"));
1327

    
1328
    }
1329

    
1330
    /**
1331
     * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
1332
     * forma, podr?s poner leyendas basadas en el nuevo recordset
1333
     *
1334
     * @param newSds
1335
     */
1336
    public void setRecordset(SelectableDataSource newSds) {
1337
        sds = newSds;
1338
        sds.setSelectionSupport(selectionSupport);
1339
    }
1340

    
1341
    public void clearSpatialCache()
1342
    {
1343
        spatialCache.clearAll();
1344
    }
1345

    
1346
    public boolean isSpatialCacheEnabled() {
1347
        return spatialCacheEnabled;
1348
    }
1349

    
1350
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1351
        this.spatialCacheEnabled = spatialCacheEnabled;
1352
    }
1353

    
1354
    public SpatialCache getSpatialCache() {
1355
        return spatialCache;
1356
    }
1357

    
1358
    /**
1359
     * Siempre es un numero mayor de 1000
1360
     * @param maxFeatures
1361
     */
1362
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
1363
        if (maxFeatures > spatialCache.maxFeatures)
1364
            spatialCache.setMaxFeatures(maxFeatures);
1365

    
1366
    }
1367

    
1368
    /**
1369
     * This method returns a boolean that is used by the FPopMenu
1370
     * to make visible the properties menu or not. It is visible by
1371
     * default, and if a later don't have to show this menu only
1372
     * has to override this method.
1373
     * @return
1374
     * If the properties menu is visible (or not)
1375
     */
1376
    public boolean isPropertiesMenuVisible(){
1377
        return true;
1378
    }
1379

    
1380
    public void reload() throws ReloadLayerException {
1381
        this.setAvailable(true);
1382
        super.reload();
1383
        try {
1384
            this.source.getDriver().reload();
1385
            if (this.getLegend() == null) {
1386
                if (this.getRecordset().getDriver() instanceof WithDefaultLegend) {
1387
                    WithDefaultLegend aux = (WithDefaultLegend) this.getRecordset().getDriver();
1388
                    this.setLegend((IVectorLegend) aux.getDefaultLegend());
1389
                    this.setLabelingStrategy(aux.getDefaultLabelingStrategy());
1390
                } else {
1391
                    this.setLegend(LegendFactory.createSingleSymbolLegend(
1392
                            this.getShapeType()));
1393
                }
1394
            }
1395

    
1396
        } catch (LegendLayerException e) {
1397
            this.setAvailable(false);
1398
            throw new ReloadLayerException(getName(),e);
1399
        } catch (ReadDriverException e) {
1400
            this.setAvailable(false);
1401
            throw new ReloadLayerException(getName(),e);
1402
        }
1403

    
1404
    }
1405

    
1406
    protected void setLoadSelection(XMLEntity xml) {
1407
        this.loadSelection = xml;
1408
    }
1409

    
1410
    protected void setLoadLegend(IVectorLegend legend) {
1411
        this.loadLegend = legend;
1412
    }
1413

    
1414
    protected void putLoadSelection() throws XMLException {
1415
        if (this.loadSelection == null) return;
1416
        try {
1417
            this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1418
        } catch (ReadDriverException e) {
1419
            throw new XMLException(e);
1420
        }
1421
        this.loadSelection = null;
1422

    
1423
    }
1424
    protected void putLoadLegend() throws LegendLayerException {
1425
        if (this.loadLegend == null) return;
1426
        this.setLegend(this.loadLegend);
1427
        this.loadLegend = null;
1428
    }
1429

    
1430
    protected void cleanLoadOptions() {
1431
        this.loadLegend = null;
1432
        this.loadSelection = null;
1433
    }
1434

    
1435
    public boolean isWritable() {
1436
        VectorialDriver drv = getSource().getDriver();
1437
        if (!drv.isWritable())
1438
            return false;
1439
        if (drv instanceof IWriteable)
1440
        {
1441
            IWriter writer = ((IWriteable)drv).getWriter();
1442
            if (writer != null)
1443
            {
1444
                if (writer instanceof ISpatialWriter)
1445
                    return true;
1446
            }
1447
        }
1448
        return false;
1449

    
1450
    }
1451

    
1452
    public FLayer cloneLayer() throws Exception {
1453
        FLyrVect clonedLayer = new FLyrVect();
1454
        clonedLayer.setSource(getSource());
1455
        if (isJoined()) {
1456
                        clonedLayer.setIsJoined(true);
1457
                        clonedLayer.setRecordset(getRecordset());
1458
                }
1459
        clonedLayer.setVisible(isVisible());
1460
        clonedLayer.setISpatialIndex(getISpatialIndex());
1461
        clonedLayer.setName(getName());
1462
        clonedLayer.setCoordTrans(getCoordTrans());
1463

    
1464
        clonedLayer.setLegend((IVectorLegend)getLegend().cloneLegend());
1465

    
1466
        clonedLayer.setIsLabeled(isLabeled());
1467
        clonedLayer.setLabelingStrategy(getLabelingStrategy());
1468

    
1469
        return clonedLayer;
1470
    }
1471

    
1472

    
1473
    private boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, double dpi, CartographicSupport csSym, IGeometry geom, int[] xyCoords) {
1474
            return isOnePoint(graphicsTransform, viewPort, geom, xyCoords) && csSym.getCartographicSize(viewPort, dpi, null) <= 1;
1475
    }
1476

    
1477
    private boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, IGeometry geom, int[] xyCoords) {
1478
            boolean onePoint = false;
1479
            if (geom.getGeometryType()!=FShape.POINT) {
1480

    
1481
                        Rectangle2D geomBounds = geom.getBounds2D();
1482

    
1483
                        ICoordTrans ct = getCoordTrans();
1484

    
1485
                        if (ct!=null) {
1486
//                                geomBounds = ct.getInverted().convert(geomBounds);
1487
                                geomBounds = ct.convert(geomBounds);
1488
                        }
1489

    
1490
                        double dist1Pixel = viewPort.getDist1pixel();
1491

    
1492
                        onePoint = (geomBounds.getWidth()  <= dist1Pixel
1493
                                         && geomBounds.getHeight() <= dist1Pixel);
1494

    
1495
                        if (onePoint) {
1496
                                // avoid out of range exceptions
1497
                                FPoint2D p = new FPoint2D(geomBounds.getMinX(), geomBounds.getMinY());
1498
                                p.transform(viewPort.getAffineTransform());
1499
                                p.transform(graphicsTransform);
1500
                                xyCoords[0] = (int) p.getX();
1501
                                xyCoords[1] = (int) p.getY();
1502

    
1503
                        }
1504

    
1505
                }
1506
            return onePoint;
1507
    }
1508
    /*
1509
     * jaume. Stuff from ILabeled.
1510
     */
1511
    private boolean isLabeled;
1512
    private ILabelingStrategy strategy;
1513

    
1514
    public boolean isLabeled() {
1515
        return isLabeled;
1516
    }
1517

    
1518
    public void setIsLabeled(boolean isLabeled) {
1519
        this.isLabeled = isLabeled;
1520
    }
1521

    
1522
    public ILabelingStrategy getLabelingStrategy() {
1523
        return strategy;
1524
    }
1525

    
1526
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1527
        this.strategy = strategy;
1528
    }
1529

    
1530
    public void drawLabels(BufferedImage image, Graphics2D g, ViewPort viewPort,
1531
                    Cancellable cancel, double scale) throws ReadDriverException {
1532
        if (strategy!=null && isWithinScale(scale)) {
1533
                strategy.draw(image, g, viewPort, cancel);
1534
        }
1535
    }
1536

    
1537

    
1538

    
1539
    //M?todos para el uso de HyperLinks en capas FLyerVect
1540

    
1541
    /**
1542
     * Return true, because a Vectorial Layer supports HyperLink
1543
     */
1544
    public boolean allowLinks()
1545
    {
1546
            return true;
1547
    }
1548

    
1549
    /**
1550
         * Returns an instance of AbstractLinkProperties that contains the information
1551
         * of the HyperLink
1552
         * @return Abstra
1553
         */
1554
    public AbstractLinkProperties getLinkProperties()
1555
    {
1556
            return linkProperties;
1557
    }
1558

    
1559
    /**
1560
         * Provides an array with URIs. Returns one URI by geometry that includes the point
1561
         * in its own geometry limits with a allowed tolerance.
1562
         * @param layer, the layer
1563
         * @param point, the point to check that is contained or not in the geometries in the layer
1564
         * @param tolerance, the tolerance allowed. Allowed margin of error to detect if the  point
1565
         *                 is contained in some geometries of the layer
1566
         * @return
1567
         */
1568
    public URI[] getLink(Point2D point, double tolerance)
1569
    {
1570
            //return linkProperties.getLink(this)
1571
            return linkProperties.getLink(this,point,tolerance);
1572
    }
1573
    /**
1574
     * @deprecated Don?t use Strategy, you should be use iterators.
1575
     */
1576
        public boolean isUseStrategy() {
1577
                return useStrategy;
1578
        }
1579
        /**
1580
     * @deprecated Don?t use Strategy, you should be use iterators.
1581
     */
1582
        public void setUseStrategy(boolean useStrategy) {
1583
                this.useStrategy = useStrategy;
1584
        }
1585

    
1586
        @Override
1587
        public void load() throws LoadLayerException {
1588
                super.load();
1589
                useStrategy=forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD;
1590
        }
1591

    
1592
 }