Statistics
| Revision:

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

History | View | Annotate | Download (60.2 KB)

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

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

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

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

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

    
128
/**
129
 * Capa b?sica Vectorial.
130
 *
131
 * @author Fernando Gonz?lez Cort?s
132
 */
133

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

    
148
    /** Leyenda de la capa vectorial */
149
    private IVectorLegend legend;
150
    private int typeShape = -1;
151
    private ReadableVectorial source;
152
    private SelectableDataSource sds;
153
    private SelectionSupport selectionSupport = new SelectionSupport();
154
    private SpatialCache spatialCache = new SpatialCache();
155
    private boolean spatialCacheEnabled = false;
156

    
157
    /**
158
     * An implementation of gvSIG spatial index
159
     */
160
    protected ISpatialIndex spatialIndex = null;
161
    private boolean bHasJoin = false;
162
    private XMLEntity orgXMLEntity = null;
163
    private XMLEntity loadSelection = null;
164
    private IVectorLegend loadLegend = null;
165

    
166
    //Lo a?ado. Caracter?sticas de HyperEnlace (LINK)
167
    private FLyrVectLinkProperties linkProperties=new FLyrVectLinkProperties();
168
    //private ArrayList linkProperties=null;
169

    
170
    /**
171
     * Devuelve el VectorialAdapater de la capa.
172
     *
173
     * @return VectorialAdapter.
174
     */
175
    public ReadableVectorial getSource() {
176
        if (!this.isAvailable()) return null;
177
        return source;
178
    }
179

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

    
190

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

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

    
232
    }
233

    
234
    /**
235
     * Checks if it has associated an external spatial index
236
     * (an spatial index file).
237
     *
238
     * It looks for it in main file path, or in temp system path.
239
     * If main file is rivers.shp, it looks for a file called
240
     * rivers.shp.qix.
241

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

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

    
285
    public Rectangle2D getFullExtent() throws ReadDriverException, ExpansionFileReadException {
286
            Rectangle2D rAux;
287
            source.start();
288
            rAux = (Rectangle2D)source.getFullExtent().clone();
289
            source.stop();
290

    
291
            // Si existe reproyecci?n, reproyectar el extent
292
            ICoordTrans ct = getCoordTrans();
293

    
294
            if (ct != null) {
295
                Point2D pt1 = new Point2D.Double(rAux.getMinX(), rAux.getMinY());
296
                Point2D pt2 = new Point2D.Double(rAux.getMaxX(), rAux.getMaxY());
297
                pt1 = ct.convert(pt1, null);
298
                pt2 = ct.convert(pt2, null);
299
                rAux = new Rectangle2D.Double();
300
                rAux.setFrameFromDiagonal(pt1, pt2);
301
            }
302

    
303
            //Esto es para cuando se crea una capa nueva con el fullExtent de ancho y alto 0.
304
            if (rAux.getWidth()==0 && rAux.getHeight()==0) {
305
                rAux=new Rectangle2D.Double(0,0,100,100);
306
            }
307

    
308
            return rAux;
309
    }
310

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

    
330

    
331

    
332
            if (bDrawShapes) {
333
                    boolean cacheFeatures = isSpatialCacheEnabled();
334
                    SpatialCache cache = null;
335
                if (cacheFeatures) {
336
                        getSpatialCache().clearAll();
337
                        cache = getSpatialCache();
338
                }
339

    
340
                    try {
341
                            ArrayList<String> fieldList = new ArrayList<String>();
342

    
343
                            // fields from legend
344
                            String[] aux = null;
345

    
346
                            if (legend instanceof IClassifiedVectorLegend) {
347
                                    aux = ((IClassifiedVectorLegend) legend).getClassifyingFieldNames();
348
                                    for (int i = 0; i < aux.length; i++) {
349
                                            fieldList.add(aux[i]);
350
                                    }
351
                            }
352

    
353
                            // Get the iterator over the visible features
354
                            IFeatureIterator it = getSource().getFeatureIterator(
355
                                            viewPort.getAdjustedExtent(),
356
                                            fieldList.toArray(new String[fieldList.size()]),
357
                                            viewPort.getProjection(),
358
                                            true);
359
                            
360
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
361
                            
362
                            boolean bSymbolLevelError = false;
363
                            
364
                            // if layer has map levels it will use a ZSort
365
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
366

    
367
                            // -- visual FX stuff
368
                            long time = System.currentTimeMillis();
369
                            BufferedImage virtualBim;
370
                            Graphics2D virtualGraphics;
371

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

    
388
                    
389
                            // Iteration over each feature
390
                            while ( !cancel.isCanceled() && it.hasNext()) {
391
                                    IFeature feat = it.next();
392
                                    IGeometry geom = feat.getGeometry();
393

    
394
                                    if (cacheFeatures) {
395
                                            if (cache.getMaxFeatures() >= cache.size()) {
396
                                                        // already reprojected
397
                                                        cache.insert(geom.getBounds2D(), geom);
398
                                                }
399
                                    }
400

    
401
                                    // retrieve the symbol associated to such feature
402
                                    ISymbol sym = legend.getSymbolByFeature(feat);
403

    
404
                                    if (sym == null) continue;
405
                                    
406
                                    //C?digo para poder acceder a los ?ndices para ver si est? seleccionado un Feature
407
                                    ReadableVectorial rv=getSource();
408
                                    int selectionIndex=-1;
409
                                    if (rv instanceof ISpatialDB){
410
                                            selectionIndex = ((ISpatialDB)rv).getRowIndexByFID(feat);
411
                                    }else{
412
                                            selectionIndex = Integer.parseInt(feat.getID());
413
                                    }
414
                                    if (selectionIndex!=-1) {
415
                                            if (selectionSupport.isSelected(selectionIndex)) {
416
                                                sym = sym.getSymbolForSelection();
417
                                        }
418
                                }
419

    
420
                                    // Check if this symbol is sized with CartographicSupport
421
                                    CartographicSupport csSym = null;
422
                                    int symbolType = sym.getSymbolType();
423
                                    boolean bDrawCartographicSupport = false;
424

    
425
                                    if (   symbolType == FShape.POINT
426
                                                    || symbolType == FShape.LINE
427
                                                    || sym instanceof CartographicSupport) {
428

    
429
                                            // patch
430
                                        if (!sym.getClass().equals(FSymbol.class)) {
431
                                                csSym = (CartographicSupport) sym;
432
                                                bDrawCartographicSupport = (csSym.getUnit() != -1);
433
                                        }
434
                                    }
435

    
436
                                    int x = -1;
437
                                    int y = -1;
438
                                    int[] xyCoords = new int[2];
439

    
440
                                    // Check if size is a pixel
441
                                    boolean onePoint = bDrawCartographicSupport ?
442
                                                    isOnePoint(g.getTransform(), viewPort, MapContext.getScreenDPI(), csSym, geom, xyCoords) :
443
                                                    isOnePoint(g.getTransform(), viewPort, geom, xyCoords);
444

    
445
                                        // Avoid out of bounds exceptions
446
                                        if (onePoint) {
447
                                                x = xyCoords[0];
448
                                                y = xyCoords[1];
449
                                                if (x<0 || y<0 || x>= viewPort.getImageWidth() || y>=viewPort.getImageHeight()) continue;
450
                                        }
451

    
452
                                        if (useZSort) {
453
                                                // Check if this symbol is a multilayer
454
                                                if (sym instanceof IMultiLayerSymbol) {
455
                                                        // if so, treat each of its layers as a single symbol
456
                                                        // in its corresponding map level
457
                                                        IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
458
                                                        for (int i = 0; !cancel.isCanceled() && i < mlSym.getLayerCount(); i++) {
459
                                                                ISymbol mySym = mlSym.getLayer(i);
460
                                                                int symbolLevel = zSort.getSymbolLevel(mySym);
461
                                                                
462
                                                                if (symbolLevel == -1) {
463
                                                                        /* an error occured when managing symbol levels.
464
                                                                         * some of the legend changed events regarding the
465
                                                                         * symbols did not finish satisfactory and the legend
466
                                                                         * is now inconsistent. For this drawing, it will finish
467
                                                                         * as it was at the bottom (level 0) but, when done, the
468
                                                                         * ZSort will be reset to avoid app crashes. This is
469
                                                                         * a bug that has to be fixed.
470
                                                                         */
471
                                                                        bSymbolLevelError = true;
472
                                                                        symbolLevel=0;
473
                                                                }
474
                                                                
475
                                                                if (onePoint) {
476
                                                                        if (x<0 || y<0 || x>= imageLevels[symbolLevel].getWidth() || y>=imageLevels[symbolLevel].getHeight()) continue;
477
                                                                        imageLevels[symbolLevel].setRGB(x, y, mySym.getOnePointRgb());
478
                                                                } else {
479
                                                                        if (!bDrawCartographicSupport) {
480
                                                                                geom.drawInts(graphics[symbolLevel], viewPort, mySym, cancel);
481
                                                                        } else {
482
                                                                                geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) mySym, cancel);
483
                                                                        }
484
                                                                }
485
                                                        }
486
                                                } else {
487
                                                        // else, just draw the symbol in its level
488
                                                        if (!bDrawCartographicSupport) {
489
                                                                geom.drawInts(graphics[zSort.getSymbolLevel(sym)], viewPort, sym, cancel);
490
                                                        } else {
491
                                                                geom.drawInts(graphics[zSort.getSymbolLevel(sym)], viewPort, dpi, (CartographicSupport) csSym, cancel);
492
                                                        }
493
                                                }
494

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

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

    
527
                            if (useZSort) {
528
                                    g.drawImage(image, 0, 0, null);
529
                                        g.translate(offset.getX(), offset.getY());
530
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
531
                                            g.drawImage(imageLevels[i],0,0, null);
532
                                            imageLevels[i] = null;
533
                                            graphics[i] = null;
534
                                    }
535
                                        g.translate(-offset.getX(), -offset.getY());
536
                                    imageLevels = null;
537
                                    graphics = null;
538
                            }
539
                            it.closeIterator();
540
                            
541
                            if (bSymbolLevelError) {
542
                                    ((IVectorLegend) getLegend()).setZSort(null);
543
                            }
544
                            
545
                    } catch (ReadDriverException e) {
546
                            this.setVisible(false);
547
                            this.setActive(false);
548
                            throw e;
549
                    }
550
                    
551
                    
552
            }
553
    }
554

    
555
           public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
556
            Cancellable cancel, double scale) throws ReadDriverException {
557
//            forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD = true;
558
            if (!isUseStrategy()) {
559
                    _draw(image, g, viewPort, cancel, scale);
560
            } else {
561
//                    moved up to FLayers
562
//                    if (isWithinScale(scale)) {
563

    
564

    
565
                            // Las que solo tienen etiquetado sin pintar el shape,
566
                            // no pasamos por ellas
567
                            boolean bDrawShapes = true;
568
                            if (legend instanceof SingleSymbolLegend) {
569
                                    if (legend.getDefaultSymbol().isShapeVisible() == false)
570
                                            bDrawShapes = false;
571
                            }
572
                            if (bDrawShapes) {
573
                                    Strategy strategy = StrategyManager.getStrategy(this);
574
                                    try {
575
                                            prepareDrawing(image, g, viewPort);
576
                                            strategy.draw(image, g, viewPort, cancel);
577
                                    } catch (ReadDriverException e) {
578
                                            this.setVisible(false);
579
                                            this.setActive(false);
580
                                            throw e;
581
                                    }
582
                            }
583
                            if (getVirtualLayers() != null) {
584
                                    getVirtualLayers().draw(image, g, viewPort, cancel, scale);
585
                            }
586
//                    }
587
            }
588
    }
589

    
590
    /**
591
     * Se llama antes de empezar a pintar.
592
     * Es ?til para preparar la cache a emplear, las leyendas, etc.
593
     * @param image
594
     * @param g
595
     * @param viewPort
596
     */
597
    private void prepareDrawing(BufferedImage image, Graphics2D g, ViewPort viewPort) {
598

    
599
    }
600

    
601
    public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
602
                    double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
603
            // TEST METHOD
604

    
605
                 
606
                    /* SVN */
607
                    
608
    /*        boolean bDrawShapes = true;
609
            if (legend instanceof SingleSymbolLegend) {
610
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
611
            }
612

613

614
            if (bDrawShapes) {
615
                    double dpi = 72;
616

617
                    PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
618
                    if (resolution.equals(PrintQuality.NORMAL)){
619
                            dpi = 300;
620
                    } else if (resolution.equals(PrintQuality.HIGH)){
621
                            dpi = 600;
622
                    } else if (resolution.equals(PrintQuality.DRAFT)){
623
                            dpi = 72;
624
                    }
625

626

627
                    try {
628
                            prepareDrawing(null, g, viewPort);
629
                            ArrayList<String> fieldList = new ArrayList<String>();
630
                            String[] aux;
631

632
                            // fields from legend
633
                            if (legend instanceof IClassifiedVectorLegend) {
634
                                    aux = ((IClassifiedVectorLegend) legend).
635
                                                                            getClassifyingFieldNames();
636
                                    for (int i = 0; i < aux.length; i++) {
637
                                            fieldList.add(aux[i]);
638
                                    }
639
                            }
640

641
                            // fields from labeling
642
                            if (isLabeled()) {
643
                                    aux = getLabelingStrategy().getUsedFields();
644
                                    for (int i = 0; i < aux.length; i++) {
645
                                            fieldList.add(aux[i]);
646
                                    }
647
                            }
648

649
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
650

651
                            // if layer has map levels it will use a ZSort
652
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
653

654

655
                            int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
656
                            for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
657
                                    // Get the iterator over the visible features
658
                                    IFeatureIterator it = getSource().getFeatureIterator(
659
                                                    viewPort.getAdjustedExtent(),
660
                                                    fieldList.toArray(new String[fieldList.size()]),
661
                                                    viewPort.getProjection(),
662
                                                    true);
663

664
                                    // Iteration over each feature
665
                                    while ( !cancel.isCanceled() && it.hasNext()) {
666
                                            IFeature feat = it.next();
667
                                            IGeometry geom = feat.getGeometry();
668

669
                                            // retreive the symbol associated to such feature
670
                                            ISymbol sym = legend.getSymbolByFeature(feat);
671

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

687
                                                                if (sym == null) {
688
                                                                        continue;
689
                                                                }
690
                                                        } else {
691
                                                                // else, just draw the symbol in its level
692
                                                                if (zSort.getSymbolLevel(sym) != mapPass) {
693
                                                                        System.out.println("avoided single layer symbol '"+sym.getDescription()+"' (pass "+mapPass+")");
694
                                                                        continue;
695
                                                                }
696
                                                        }
697
                                            }
698

699
                                            // Check if this symbol is sized with CartographicSupport
700
                                            CartographicSupport csSym = null;
701
                                            int symbolType = sym.getSymbolType();
702
                                            boolean bDrawCartographicSupport = false;
703

704
                                            if (   symbolType == FShape.POINT
705
                                                            || symbolType == FShape.LINE
706
                                                            || sym instanceof CartographicSupport) {
707

708
                                                    csSym = (CartographicSupport) sym;
709
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
710
                                            }
711

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

714
                                            if (!bDrawCartographicSupport) {
715
                                                    geom.drawInts(g, viewPort, sym, null);
716
                                            } else {
717
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym);
718
                                            }
719

720
                                    }
721
                                    it.closeIterator();
722
                            }
723
                    } catch (ReadDriverException e) {
724
                            this.setVisible(false);
725
                            this.setActive(false);
726
                            throw e;
727
                    }
728
        */
729
                    
730
                    
731
            // TEST METHOD
732
            boolean bDrawShapes = true;
733
            if (legend instanceof SingleSymbolLegend) {
734
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
735
            }
736

    
737

    
738
            if (bDrawShapes) {
739

    
740
                    try {
741
                            double dpi = 72;
742

    
743
                            PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
744
                            if (resolution.equals(PrintQuality.NORMAL)){
745
                                    dpi = 300;
746
                            } else if (resolution.equals(PrintQuality.HIGH)){
747
                                    dpi = 600;
748
                            } else if (resolution.equals(PrintQuality.DRAFT)){
749
                                    dpi = 72;
750
                            }
751
                            ArrayList<String> fieldList = new ArrayList<String>();
752
                            String[] aux;
753

    
754
                            // fields from legend
755
                            if (legend instanceof IClassifiedVectorLegend) {
756
                                    aux = ((IClassifiedVectorLegend) legend).
757
                                    getClassifyingFieldNames();
758
                                    for (int i = 0; i < aux.length; i++) {
759
                                            fieldList.add(aux[i]);
760
                                    }
761
                            }
762
//
763
//                            // fields from labeling
764
//                            if (isLabeled()) {
765
//                                    aux = getLabelingStrategy().getUsedFields();
766
//                                    for (int i = 0; i < aux.length; i++) {
767
//                                            fieldList.add(aux[i]);
768
//                                    }
769
//                            }
770

    
771
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
772

    
773
                            // if layer has map levels it will use a ZSort
774
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
775

    
776

    
777
                            int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
778
                            for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
779
                                    // Get the iterator over the visible features
780
                                    IFeatureIterator it = getSource().getFeatureIterator(
781
                                                    viewPort.getAdjustedExtent(),
782
                                                    fieldList.toArray(new String[fieldList.size()]),
783
                                                    viewPort.getProjection(),
784
                                                    true);
785

    
786
                                    // Iteration over each feature
787
                                    while ( !cancel.isCanceled() && it.hasNext()) {
788
                                            IFeature feat = it.next();
789
                                            IGeometry geom = feat.getGeometry();
790

    
791
                                            // retreive the symbol associated to such feature
792
                                            ISymbol sym = legend.getSymbolByFeature(feat);
793

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

    
809
                                                            if (sym == null) {
810
                                                                    continue;
811
                                                            }
812
                                                    } else {
813
                                                            // else, just draw the symbol in its level
814
                                                            if (zSort.getSymbolLevel(sym) != mapPass) {
815
                                                                    System.out.println("avoided single layer symbol '"+sym.getDescription()+"' (pass "+mapPass+")");
816
                                                                    continue;
817
                                                            }
818
                                                    }
819
                                            }
820

    
821
                                            // Check if this symbol is sized with CartographicSupport
822
                                            CartographicSupport csSym = null;
823
                                            int symbolType = sym.getSymbolType();
824
                                            boolean bDrawCartographicSupport = false;
825

    
826
                                            if (   symbolType == FShape.POINT
827
                                                            || symbolType == FShape.LINE
828
                                                            || sym instanceof CartographicSupport) {
829

    
830
                                                    csSym = (CartographicSupport) sym;
831
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
832
                                            }
833

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

    
836
                                            if (!bDrawCartographicSupport) {
837
                                                    geom.drawInts(g, viewPort, sym, null);
838
                                            } else {
839
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym, cancel);
840
                                            }
841

    
842
                                    }
843
                                    it.closeIterator();
844
                            }
845
                    } catch (ReadDriverException e) {
846
                            this.setVisible(false);
847
                            this.setActive(false);
848
                            throw e;
849
                    }
850
            }
851
    }
852

    
853

    
854
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
855
            double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
856
            if (forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
857
                    _print(g, viewPort, cancel, scale, properties);
858
            } else {
859
//                    moved up to Flayers
860
//                    if (isVisible() && isWithinScale(scale)) {
861
                            Strategy strategy = StrategyManager.getStrategy(this);
862

    
863
                            strategy.print(g, viewPort, cancel, properties);
864
                            ILabelingStrategy labeling;
865
                            if ( (labeling = getLabelingStrategy() ) != null) {
866
                                    // contains labels
867
                                    labeling.print(g, viewPort, cancel, properties);
868
                            }
869
//                    }
870
            }
871
    }
872

    
873
    public void deleteSpatialIndex() {
874
        //must we delete possible spatial indexes files?
875
        spatialIndex = null;
876
    }
877

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

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

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

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

    
958
    public void createSpatialIndex() {
959
        createSpatialIndex(null);
960
    }
961

    
962
    public void process(FeatureVisitor visitor, FBitSet subset)
963
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
964
        Strategy s = StrategyManager.getStrategy(this);
965
        s.process(visitor, subset);
966
    }
967

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

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

    
979
    public FBitSet queryByRect(Rectangle2D rect) throws ReadDriverException, VisitorException {
980
        Strategy s = StrategyManager.getStrategy(this);
981

    
982
        return s.queryByRect(rect);
983
    }
984

    
985
    public FBitSet queryByPoint(Point2D p, double tolerance)
986
            throws ReadDriverException, VisitorException {
987
        Strategy s = StrategyManager.getStrategy(this);
988
        return s.queryByPoint(p, tolerance);
989
    }
990

    
991
    public FBitSet queryByShape(IGeometry g, int relationship)
992
            throws ReadDriverException, VisitorException {
993
        Strategy s = StrategyManager.getStrategy(this);
994
        return s.queryByShape(g, relationship);
995
    }
996

    
997
    public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancel) throws ReadDriverException, VisitorException {
998
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(p);
999
        FBitSet bs = queryByPoint(pReal, tolerance);
1000
        VectorialXMLItem[] item = new VectorialXMLItem[1];
1001
        item[0] = new VectorialXMLItem(bs, this);
1002

    
1003
        return item;
1004
    }
1005

    
1006
    public void setLegend(IVectorLegend r) throws LegendLayerException {
1007
        IVectorLegend oldLegend = legend;
1008
        legend = r;
1009
        try {
1010
            legend.setDataSource(getRecordset());
1011
        } catch (FieldNotFoundException e1) {
1012
            throw new LegendLayerException(getName(),e1);
1013
        } catch (ReadDriverException e1) {
1014
            throw new LegendLayerException(getName(),e1);
1015
        }
1016
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
1017
                oldLegend, legend);
1018
        callLegendChanged(e);
1019
    }
1020

    
1021
    /**
1022
     * Devuelve la Leyenda de la capa.
1023
     *
1024
     * @return Leyenda.
1025
     */
1026
    public ILegend getLegend() {
1027
        return legend;
1028
    }
1029

    
1030
    /**
1031
     * Devuelve el tipo de shape que contiene la capa.
1032
     *
1033
     * @return tipo de shape.
1034
     *
1035
     * @throws DriverException
1036
     */
1037
    public int getShapeType() throws ReadDriverException {
1038
        if (typeShape == -1) {
1039
            getSource().start();
1040
            typeShape = getSource().getShapeType();
1041
            getSource().stop();
1042
        }
1043

    
1044
        return typeShape;
1045
    }
1046

    
1047
    public XMLEntity getXMLEntity() throws XMLException {
1048
        if (!this.isAvailable() && this.orgXMLEntity != null) {
1049
            return this.orgXMLEntity;
1050
        }
1051
        XMLEntity xml = super.getXMLEntity();
1052
        if (getLegend()!=null)
1053
            xml.addChild(getLegend().getXMLEntity());
1054
        try {
1055
            if (getRecordset()!=null)
1056
                xml.addChild(getRecordset().getSelectionSupport().getXMLEntity());
1057
        } catch (ReadDriverException e1) {
1058
            e1.printStackTrace();
1059
            throw new XMLException(e1);
1060
        }
1061
        // Repongo el mismo ReadableVectorial m?s abajo para cuando se guarda el proyecto.
1062
        ReadableVectorial rv=getSource();
1063
        xml.putProperty("type", "vectorial");
1064
        if (source instanceof VectorialEditableAdapter) {
1065
            setSource(((VectorialEditableAdapter) source).getOriginalAdapter());
1066
        }
1067
        if (source instanceof VectorialFileAdapter) {
1068
            xml.putProperty("type", "vectorial");
1069
            xml.putProperty("file", ((VectorialFileAdapter) source)
1070
                    .getFile());
1071
            try {
1072
                xml.putProperty("recordset-name", source.getRecordset()
1073
                        .getName());
1074
            } catch (ReadDriverException e) {
1075
                throw new XMLException(e);
1076
            } catch (RuntimeException e) {
1077
                e.printStackTrace();
1078
            }
1079
        } else if (source instanceof VectorialDBAdapter) {
1080
            xml.putProperty("type", "vectorial");
1081

    
1082
            IVectorialDatabaseDriver dbDriver = (IVectorialDatabaseDriver) source
1083
                    .getDriver();
1084

    
1085
            // Guardamos el nombre del driver para poder recuperarlo
1086
            // con el DriverManager de Fernando.
1087
            xml.putProperty("db", dbDriver.getName());
1088
            try {
1089
                xml.putProperty("recordset-name", source.getRecordset()
1090
                        .getName());
1091
            } catch (ReadDriverException e) {
1092
                throw new XMLException(e);
1093
            } catch (RuntimeException e) {
1094
                e.printStackTrace();
1095
            }
1096
            xml.addChild(dbDriver.getXMLEntity()); // Tercer child. Antes hemos
1097
                                                    // metido la leyenda y el
1098
                                                    // selection support
1099
        } else if (source instanceof VectorialAdapter) {
1100
            // Se supone que hemos hecho algo gen?rico.
1101
            xml.putProperty("type", "vectorial");
1102

    
1103
            VectorialDriver driver = source.getDriver();
1104

    
1105
            // Guardamos el nombre del driver para poder recuperarlo
1106
            // con el DriverManager de Fernando.
1107
            xml.putProperty("other", driver.getName());
1108
            // try {
1109
            try {
1110
                xml.putProperty("recordset-name", source.getRecordset()
1111
                        .getName());
1112
            } catch (ReadDriverException e) {
1113
                throw new XMLException(e);
1114
            } catch (RuntimeException e) {
1115
                e.printStackTrace();
1116
            }
1117
            if (driver instanceof IPersistence) {
1118
                // xml.putProperty("className", driver.getClass().getName());
1119
                    IPersistence persist = (IPersistence) driver;
1120
                xml.addChild(persist.getXMLEntity()); // Tercer child. Antes
1121
                                                        // hemos metido la
1122
                                                        // leyenda y el
1123
                                                        // selection support
1124
            }
1125
        }
1126
        if (rv!=null)
1127
            setSource(rv);
1128
        xml.putProperty("driverName", source.getDriver().getName());
1129
        if (bHasJoin)
1130
            xml.putProperty("hasJoin", "true");
1131

    
1132
        // properties from ILabelable
1133
        xml.putProperty("isLabeled", isLabeled);
1134
        if (strategy != null) {
1135
            XMLEntity strategyXML = strategy.getXMLEntity();
1136
            strategyXML.putProperty("Strategy", strategy.getClassName());
1137
            xml.addChild(strategy.getXMLEntity());
1138
        }
1139
        xml.addChild(getLinkProperties().getXMLEntity());
1140
        return xml;
1141
    }
1142

    
1143
    /**
1144
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1145
     */
1146
    public void setXMLEntity03(XMLEntity xml) throws XMLException {
1147

    
1148
        super.setXMLEntity(xml);
1149
        legend = LegendFactory.createFromXML03(xml.getChild(0));
1150

    
1151
        try {
1152
            setLegend(legend);
1153
        } catch (LegendLayerException e) {
1154
            throw new XMLException(e);
1155
        }
1156

    
1157
        try {
1158
            getRecordset().getSelectionSupport()
1159
                    .setXMLEntity03(xml.getChild(1));
1160
        } catch (ReadDriverException e) {
1161
            e.printStackTrace();
1162
        }
1163
    }
1164

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

    
1203
                            String recordsetName = xml.getStringProperty("recordset-name");
1204

    
1205
                            SelectableDataSource sds = new SelectableDataSource(LayerFactory
1206
                                            .getDataSourceFactory().createRandomDataSource(
1207
                                                            recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
1208

    
1209
                            LayerFactory.getDataSourceFactory().changeDataSourceName(
1210
                                            getSource().getRecordset().getName(), recordsetName);
1211
                    } catch (NoSuchTableException e1) {
1212
                            this.setAvailable(false);
1213
                            throw new XMLException(e1);
1214
                    } catch (ReadDriverException e1) {
1215
                            this.setAvailable(false);
1216
                            throw new XMLException(e1);
1217
                    }
1218
                    // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1219
                    // el final
1220
                    // de la lectura del proyecto
1221
                    if (xml.contains("hasJoin")) {
1222
                            setIsJoined(true);
1223
                            PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1224
                    } else {
1225
                            try {
1226
                                    setLegend(leg);
1227
                            } catch (LegendLayerException e) {
1228
                                    throw new XMLException(e);
1229
                            }
1230
                    }
1231

    
1232
                    // set properties for ILabelable
1233
                    XMLEntity labelingXML = xml.firstChild("id", "LabelingStrategy");
1234
                    if (labelingXML!= null) {
1235
                            isLabeled = true;
1236
                            try {
1237
                                    this.strategy = LabelingFactory.createStrategyFromXML(labelingXML, this);
1238
                            } catch (NotExistInXMLEntity neXMLEX) {
1239
                                    // no strategy was set, just continue;
1240
                                    logger.warn("Reached what should be unreachable code");
1241
                            }
1242
                    } else {
1243
                            isLabeled = false;
1244
                    }
1245

    
1246
                    XMLEntity xmlLinkProperties=xml.firstChild("typeChild","linkProperties");
1247
                    if (xmlLinkProperties != null){
1248
                            getLinkProperties().setXMLEntity(xmlLinkProperties);
1249
                    }
1250

    
1251
            } catch (XMLException e) {
1252
                    this.setAvailable(false);
1253
                    this.orgXMLEntity = xml;
1254
            } catch (Exception e) {
1255
                    e.printStackTrace();
1256
                    this.setAvailable(false);
1257
                    this.orgXMLEntity = xml;
1258

    
1259
            }
1260

    
1261

    
1262
    }
1263

    
1264
    public void setXMLEntityNew(XMLEntity xml) throws XMLException {
1265
        try {
1266
            super.setXMLEntity(xml);
1267

    
1268
            XMLEntity legendXML = xml.getChild(0);
1269
            IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1270
            /* (jaume) begin patch;
1271
             * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1272
             * no longer managed by the Legend but by the ILabelingStrategy. The
1273
             * following allows restoring older projects' labelings.
1274
             */
1275
            if (legendXML.contains("labelFieldHeight")) {
1276
                AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1277
                labeling.setLayer(this);
1278
                labeling.setTextField(legendXML.getStringProperty("labelFieldHeight"));
1279
                labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
1280
                this.setLabelingStrategy(labeling);
1281
                this.setIsLabeled(true);
1282
              }
1283
            /* end patch */
1284
            try {
1285
                getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1286

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

    
1302
        } catch (XMLException e) {
1303
            this.setAvailable(false);
1304
            this.orgXMLEntity = xml;
1305
        } catch (Exception e) {
1306
            this.setAvailable(false);
1307
            this.orgXMLEntity = xml;
1308
        }
1309

    
1310

    
1311
    }
1312

    
1313

    
1314
    /**
1315
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
1316
     * identifiquen la capa.
1317
     *
1318
     * @return DOCUMENT ME!
1319
     */
1320
    public String toString() {
1321
        /*
1322
         * Se usa internamente para que la parte de datos identifique de forma
1323
         * un?voca las tablas
1324
         */
1325
        String ret = super.toString();
1326

    
1327
        return "layer" + ret.substring(ret.indexOf('@') + 1);
1328
    }
1329

    
1330
    public boolean isJoined() {
1331
        return bHasJoin;
1332
    }
1333

    
1334
    /**
1335
     * Returns if a layer is spatially indexed
1336
     *
1337
     * @return if this layer has the ability to proces spatial queries without
1338
     *         secuential scans.
1339
     */
1340
    public boolean isSpatiallyIndexed() {
1341
        ReadableVectorial source = getSource();
1342
        if (source instanceof ISpatialDB)
1343
            return true;
1344

    
1345
//FIXME azabala
1346
/*
1347
 * Esto es muy dudoso, y puede cambiar.
1348
 * Estoy diciendo que las que no son fichero o no son
1349
 * BoundedShapes estan indexadas. Esto es mentira, pero
1350
 * as? quien pregunte no querr? generar el indice.
1351
 * Esta por ver si interesa generar el indice para capas
1352
 * HSQLDB, WFS, etc.
1353
 */
1354
        if(!(source instanceof VectorialFileAdapter)){
1355
            return true;
1356
        }
1357
        if (!(source.getDriver() instanceof BoundedShapes)) {
1358
            return true;
1359
        }
1360

    
1361
        if (getISpatialIndex() != null)
1362
            return true;
1363
        return false;
1364
    }
1365

    
1366
    public void setIsJoined(boolean hasJoin) {
1367
        bHasJoin = hasJoin;
1368
    }
1369

    
1370
    /**
1371
     * @return Returns the spatialIndex.
1372
     */
1373
    public ISpatialIndex getISpatialIndex() {
1374
        return spatialIndex;
1375
    }
1376
    /**
1377
     * Sets the spatial index. This could be useful if, for some
1378
     * reasons, you want to work with a distinct spatial index
1379
     * (for example, a spatial index which could makes nearest
1380
     * neighbour querys)
1381
     * @param spatialIndex
1382
     */
1383
    public void setISpatialIndex(ISpatialIndex spatialIndex){
1384
        this.spatialIndex = spatialIndex;
1385
    }
1386

    
1387
    public SelectableDataSource getRecordset() throws ReadDriverException {
1388
        if (!this.isAvailable()) return null;
1389
        if (sds == null) {
1390

    
1391
                SelectableDataSource ds = source.getRecordset();
1392

    
1393
                if (ds == null) {
1394
                    return null;
1395
                }
1396

    
1397
                sds = ds;
1398
                sds.setSelectionSupport(selectionSupport);
1399

    
1400
        }
1401
        return sds;
1402
    }
1403

    
1404
    public void setEditing(boolean b) throws StartEditionLayerException {
1405
        super.setEditing(b);
1406
        try {
1407
            if (b) {
1408
                VectorialEditableAdapter vea = null;
1409
                // TODO: Qu? pasa si hay m?s tipos de adapters?
1410
                // FJP: Se podr?a pasar como argumento el
1411
                // VectorialEditableAdapter
1412
                // que se quiera usar para evitar meter c?digo aqu? de este
1413
                // estilo.
1414
                if (getSource() instanceof VectorialDBAdapter) {
1415
                    vea = new VectorialEditableDBAdapter();
1416
                } else if (this instanceof FLyrAnnotation) {
1417
                    vea = new AnnotationEditableAdapter(
1418
                            (FLyrAnnotation) this);
1419
                } else {
1420
                    vea = new VectorialEditableAdapter();
1421
                }
1422
                vea.setOriginalVectorialAdapter(getSource());
1423
//                                azo: implementations of readablevectorial need
1424
                //references of projection and spatial index
1425
                vea.setProjection(getProjection());
1426
                vea.setSpatialIndex(spatialIndex);
1427

    
1428

    
1429
                // /vea.setSpatialIndex(getSpatialIndex());
1430
                // /vea.setFullExtent(getFullExtent());
1431
                vea.setCoordTrans(getCoordTrans());
1432
                vea.startEdition(EditionEvent.GRAPHIC);
1433
                setSource(vea);
1434
                getRecordset().setSelectionSupport(
1435
                        vea.getOriginalAdapter().getRecordset()
1436
                                .getSelectionSupport());
1437

    
1438
            } else {
1439
                VectorialEditableAdapter vea = (VectorialEditableAdapter) getSource();
1440
                setSource(vea.getOriginalAdapter());
1441
            }
1442
            // Si tenemos una leyenda, hay que pegarle el cambiazo a su
1443
            // recordset
1444
            setRecordset(getSource().getRecordset());
1445
            if (getLegend() instanceof IVectorLegend) {
1446
                IVectorLegend ley = (IVectorLegend) getLegend();
1447
                ley.setDataSource(getSource().getRecordset());
1448
                // Esto lo pongo para evitar que al dibujar sobre un
1449
                // dxf, dwg, o dgn no veamos nada. Es debido al checkbox
1450
                // de la leyenda de textos "dibujar solo textos".
1451
//jaume
1452
//                                if (!(getSource().getDriver() instanceof IndexedShpDriver)){
1453
//                                        FSymbol symbol=new FSymbol(getShapeType());
1454
//                                        symbol.setFontSizeInPixels(false);
1455
//                                        symbol.setFont(new Font("SansSerif", Font.PLAIN, 9));
1456
//                                        Color color=symbol.getColor();
1457
//                                        int alpha=symbol.getColor().getAlpha();
1458
//                                        if (alpha>250) {
1459
//                                                symbol.setColor(new Color(color.getRed(),color.getGreen(),color.getBlue(),100));
1460
//                                        }
1461
//                                        ley.setDefaultSymbol(symbol);
1462
//                                }
1463
//jaume//
1464
                ley.useDefaultSymbol(true);
1465
            }
1466
        } catch (ReadDriverException e) {
1467
            throw new StartEditionLayerException(getName(),e);
1468
        } catch (FieldNotFoundException e) {
1469
            throw new StartEditionLayerException(getName(),e);
1470
        } catch (StartWriterVisitorException e) {
1471
            throw new StartEditionLayerException(getName(),e);
1472
        }
1473

    
1474
        setSpatialCacheEnabled(b);
1475
        callEditionChanged(LayerEvent
1476
                .createEditionChangedEvent(this, "edition"));
1477

    
1478
    }
1479

    
1480
    /**
1481
     * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
1482
     * forma, podr?s poner leyendas basadas en el nuevo recordset
1483
     *
1484
     * @param newSds
1485
     */
1486
    public void setRecordset(SelectableDataSource newSds) {
1487
        sds = newSds;
1488
        sds.setSelectionSupport(selectionSupport);
1489
    }
1490

    
1491
    public void clearSpatialCache()
1492
    {
1493
        spatialCache.clearAll();
1494
    }
1495

    
1496
    public boolean isSpatialCacheEnabled() {
1497
        return spatialCacheEnabled;
1498
    }
1499

    
1500
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1501
        this.spatialCacheEnabled = spatialCacheEnabled;
1502
    }
1503

    
1504
    public SpatialCache getSpatialCache() {
1505
        return spatialCache;
1506
    }
1507

    
1508
    /**
1509
     * Siempre es un numero mayor de 1000
1510
     * @param maxFeatures
1511
     */
1512
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
1513
        if (maxFeatures > spatialCache.maxFeatures)
1514
            spatialCache.setMaxFeatures(maxFeatures);
1515

    
1516
    }
1517

    
1518
    /**
1519
     * This method returns a boolean that is used by the FPopMenu
1520
     * to make visible the properties menu or not. It is visible by
1521
     * default, and if a later don't have to show this menu only
1522
     * has to override this method.
1523
     * @return
1524
     * If the properties menu is visible (or not)
1525
     */
1526
    public boolean isPropertiesMenuVisible(){
1527
        return true;
1528
    }
1529

    
1530
    public void reload() throws ReloadLayerException {
1531
        this.setAvailable(true);
1532
        super.reload();
1533
        try {
1534
            this.source.getDriver().reload();
1535
            if (this.getLegend() == null) {
1536
                if (this.getRecordset().getDriver() instanceof WithDefaultLegend) {
1537
                    WithDefaultLegend aux = (WithDefaultLegend) this.getRecordset().getDriver();
1538
                    this.setLegend((IVectorLegend) aux.getDefaultLegend());
1539
                    this.setLabelingStrategy(aux.getDefaultLabelingStrategy());
1540
                } else {
1541
                    this.setLegend(LegendFactory.createSingleSymbolLegend(
1542
                            this.getShapeType()));
1543
                }
1544
            }
1545

    
1546
        } catch (LegendLayerException e) {
1547
            this.setAvailable(false);
1548
            throw new ReloadLayerException(getName(),e);
1549
        } catch (ReadDriverException e) {
1550
            this.setAvailable(false);
1551
            throw new ReloadLayerException(getName(),e);
1552
        }
1553

    
1554
    }
1555

    
1556
    protected void setLoadSelection(XMLEntity xml) {
1557
        this.loadSelection = xml;
1558
    }
1559

    
1560
    protected void setLoadLegend(IVectorLegend legend) {
1561
        this.loadLegend = legend;
1562
    }
1563

    
1564
    protected void putLoadSelection() throws XMLException {
1565
        if (this.loadSelection == null) return;
1566
        try {
1567
            this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1568
        } catch (ReadDriverException e) {
1569
            throw new XMLException(e);
1570
        }
1571
        this.loadSelection = null;
1572

    
1573
    }
1574
    protected void putLoadLegend() throws LegendLayerException {
1575
        if (this.loadLegend == null) return;
1576
        this.setLegend(this.loadLegend);
1577
        this.loadLegend = null;
1578
    }
1579

    
1580
    protected void cleanLoadOptions() {
1581
        this.loadLegend = null;
1582
        this.loadSelection = null;
1583
    }
1584

    
1585
    public boolean isWritable() {
1586
        VectorialDriver drv = getSource().getDriver();
1587
        if (!drv.isWritable())
1588
            return false;
1589
        if (drv instanceof IWriteable)
1590
        {
1591
            IWriter writer = ((IWriteable)drv).getWriter();
1592
            if (writer != null)
1593
            {
1594
                if (writer instanceof ISpatialWriter)
1595
                    return true;
1596
            }
1597
        }
1598
        return false;
1599

    
1600
    }
1601

    
1602
    public FLayer cloneLayer() throws Exception {
1603
        FLyrVect clonedLayer = new FLyrVect();
1604
        clonedLayer.setSource(getSource());
1605
        if (isJoined()) {
1606
                        clonedLayer.setIsJoined(true);
1607
                        clonedLayer.setRecordset(getRecordset());
1608
                }
1609
        clonedLayer.setVisible(isVisible());
1610
        clonedLayer.setISpatialIndex(getISpatialIndex());
1611
        clonedLayer.setName(getName());
1612
        clonedLayer.setCoordTrans(getCoordTrans());
1613

    
1614
        clonedLayer.setLegend((IVectorLegend)getLegend().cloneLegend());
1615

    
1616
        clonedLayer.setIsLabeled(isLabeled());
1617
        clonedLayer.setLabelingStrategy(getLabelingStrategy());
1618

    
1619
        return clonedLayer;
1620
    }
1621

    
1622

    
1623
    private boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, double dpi, CartographicSupport csSym, IGeometry geom, int[] xyCoords) {
1624
            return isOnePoint(graphicsTransform, viewPort, geom, xyCoords) && csSym.getCartographicSize(viewPort, dpi, null) <= 1;
1625
    }
1626

    
1627
    private boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, IGeometry geom, int[] xyCoords) {
1628
            boolean onePoint = false;
1629
            int type=geom.getGeometryType() % FShape.Z;
1630
            if (type!=FShape.POINT && type!=FShape.MULTIPOINT) {
1631

    
1632
                        Rectangle2D geomBounds = geom.getBounds2D();
1633

    
1634
                        ICoordTrans ct = getCoordTrans();
1635

    
1636
                        if (ct!=null) {
1637
//                                geomBounds = ct.getInverted().convert(geomBounds);
1638
                                geomBounds = ct.convert(geomBounds);
1639
                        }
1640

    
1641
                        double dist1Pixel = viewPort.getDist1pixel();
1642

    
1643
                        onePoint = (geomBounds.getWidth()  <= dist1Pixel
1644
                                         && geomBounds.getHeight() <= dist1Pixel);
1645

    
1646
                        if (onePoint) {
1647
                                // avoid out of range exceptions
1648
                                FPoint2D p = new FPoint2D(geomBounds.getMinX(), geomBounds.getMinY());
1649
                                p.transform(viewPort.getAffineTransform());
1650
                                p.transform(graphicsTransform);
1651
                                xyCoords[0] = (int) p.getX();
1652
                                xyCoords[1] = (int) p.getY();
1653

    
1654
                        }
1655

    
1656
                }
1657
            return onePoint;
1658
    }
1659
    /*
1660
     * jaume. Stuff from ILabeled.
1661
     */
1662
    private boolean isLabeled;
1663
    private ILabelingStrategy strategy;
1664

    
1665
    public boolean isLabeled() {
1666
        return isLabeled;
1667
    }
1668

    
1669
    public void setIsLabeled(boolean isLabeled) {
1670
        this.isLabeled = isLabeled;
1671
    }
1672

    
1673
    public ILabelingStrategy getLabelingStrategy() {
1674
        return strategy;
1675
    }
1676

    
1677
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1678
        this.strategy = strategy;
1679
    }
1680

    
1681
    public void drawLabels(BufferedImage image, Graphics2D g, ViewPort viewPort,
1682
                    Cancellable cancel, double scale, double dpi) throws ReadDriverException {
1683
        if (strategy!=null && isWithinScale(scale)) {
1684
                strategy.draw(image, g, viewPort, cancel, dpi);
1685
        }
1686
    }
1687

    
1688

    
1689

    
1690
    //M?todos para el uso de HyperLinks en capas FLyerVect
1691

    
1692
    /**
1693
     * Return true, because a Vectorial Layer supports HyperLink
1694
     */
1695
    public boolean allowLinks()
1696
    {
1697
            return true;
1698
    }
1699

    
1700
    /**
1701
         * Returns an instance of AbstractLinkProperties that contains the information
1702
         * of the HyperLink
1703
         * @return Abstra
1704
         */
1705
    public AbstractLinkProperties getLinkProperties()
1706
    {
1707
            return linkProperties;
1708
    }
1709

    
1710
    /**
1711
         * Provides an array with URIs. Returns one URI by geometry that includes the point
1712
         * in its own geometry limits with a allowed tolerance.
1713
         * @param layer, the layer
1714
         * @param point, the point to check that is contained or not in the geometries in the layer
1715
         * @param tolerance, the tolerance allowed. Allowed margin of error to detect if the  point
1716
         *                 is contained in some geometries of the layer
1717
         * @return
1718
         */
1719
    public URI[] getLink(Point2D point, double tolerance)
1720
    {
1721
            //return linkProperties.getLink(this)
1722
            return linkProperties.getLink(this,point,tolerance);
1723
    }
1724
    /**
1725
     * @deprecated Don?t use Strategy, you should be use iterators.
1726
     */
1727
        public boolean isUseStrategy() {
1728
                return useStrategy;
1729
        }
1730
        /**
1731
     * @deprecated Don?t use Strategy, you should be use iterators.
1732
     */
1733
        public void setUseStrategy(boolean useStrategy) {
1734
                this.useStrategy = useStrategy;
1735
        }
1736

    
1737
        @Override
1738
        public void load() throws LoadLayerException {
1739
                super.load();
1740
                useStrategy=forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD;
1741
        }
1742

    
1743
 }