Statistics
| Revision:

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

History | View | Annotate | Download (75.3 KB)

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

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

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

    
56
import org.apache.log4j.Logger;
57
import org.cresques.cts.ICoordTrans;
58
import org.gvsig.exceptions.BaseException;
59

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

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

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

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

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

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

    
183
    public boolean isWaitTodraw() {
184
                return waitTodraw;
185
        }
186

    
187
        public void setWaitTodraw(boolean waitTodraw) {
188
                this.waitTodraw = waitTodraw;
189
        }
190
    /**
191
     * Devuelve el VectorialAdapater de la capa.
192
     *
193
     * @return VectorialAdapter.
194
     */
195
    public ReadableVectorial getSource() {
196
        if (!this.isAvailable()) return null;
197
        return source;
198
    }
199

    
200
    /**
201
     * If we use a persistent spatial index associated with this layer, and the
202
     * index is not intrisic to the layer (for example spatial databases) this
203
     * method looks for existent spatial index, and loads it.
204
     *
205
     */
206
    private void loadSpatialIndex() {
207
        //FIXME: Al abrir el indice en fichero...
208
        //?C?mo lo liberamos? un metodo Layer.shutdown()
209

    
210

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

    
237
        try {
238
            source.start();
239
            spatialIndex = new QuadtreeGt2(FileUtils.getFileWithoutExtension(sptFile),
240
                    "NM", source.getFullExtent(), source.getShapeCount(), false);
241
            source.setSpatialIndex(spatialIndex);
242
        } catch (SpatialIndexException e) {
243
            spatialIndex = null;
244
            e.printStackTrace();
245
            return;
246
        } catch (ReadDriverException e) {
247
            spatialIndex = null;
248
            e.printStackTrace();
249
            return;
250
        }
251

    
252
    }
253

    
254
    /**
255
     * Checks if it has associated an external spatial index
256
     * (an spatial index file).
257
     *
258
     * It looks for it in main file path, or in temp system path.
259
     * If main file is rivers.shp, it looks for a file called
260
     * rivers.shp.qix.
261

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

    
292
    /**
293
     * Inserta el VectorialAdapter a la capa.
294
     *
295
     * @param va
296
     *            VectorialAdapter.
297
     */
298
    public void setSource(ReadableVectorial rv) {
299
        source = rv;
300
        // azabala: we check if this layer could have a file spatial index
301
        // and load it if it exists
302
        loadSpatialIndex();
303
    }
304

    
305
    public Rectangle2D getFullExtent() throws ReadDriverException, ExpansionFileReadException {
306
            Rectangle2D rAux;
307
            source.start();
308
            rAux = (Rectangle2D)source.getFullExtent().clone();
309
            source.stop();
310

    
311
            // Si existe reproyecci?n, reproyectar el extent
312
            if (!(this.getProjection()!=null &&
313
                            this.getMapContext().getProjection()!=null &&
314
                            this.getProjection().getAbrev().equals(this.getMapContext().getProjection().getAbrev()))){
315
                    ICoordTrans ct = getCoordTrans();
316
                    try{
317
                            if (ct != null) {
318
                                    Point2D pt1 = new Point2D.Double(rAux.getMinX(), rAux.getMinY());
319
                                    Point2D pt2 = new Point2D.Double(rAux.getMaxX(), rAux.getMaxY());
320
                                    pt1 = ct.convert(pt1, null);
321
                                    pt2 = ct.convert(pt2, null);
322
                                    rAux = new Rectangle2D.Double();
323
                                    rAux.setFrameFromDiagonal(pt1, pt2);
324
                            }
325
                    }catch (IllegalStateException e) {
326
                            this.setAvailable(false);
327
                            this.addError(new ReprojectLayerException(getName(), e));
328
                    }
329
            }
330
            //Esto es para cuando se crea una capa nueva con el fullExtent de ancho y alto 0.
331
            if (rAux.getWidth()==0 && rAux.getHeight()==0) {
332
                rAux=new Rectangle2D.Double(0,0,100,100);
333
            }
334

    
335
            return rAux;
336
    }
337

    
338
    /**
339
     * Draws using IFeatureIterator. This method will replace the old draw(...) one.
340
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
341
     * @param image
342
     * @param g
343
     * @param viewPort
344
     * @param cancel
345
     * @param scale
346
     * @throws ReadDriverException
347
     */
348
    private void _draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
349
                    Cancellable cancel, double scale) throws ReadDriverException {
350
            boolean bDrawShapes = true;
351
            if (legend instanceof SingleSymbolLegend) {
352
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
353
            }
354
            Point2D offset = viewPort.getOffset();
355
            double dpi = MapContext.getScreenDPI();
356

    
357

    
358

    
359
            if (bDrawShapes) {
360
                    boolean cacheFeatures = isSpatialCacheEnabled();
361
                    SpatialCache cache = null;
362
                    if (cacheFeatures) {
363
                            getSpatialCache().clearAll();
364
                            cache = getSpatialCache();
365
                    }
366

    
367
                    try {
368
                            ArrayList<String> fieldList = new ArrayList<String>();
369

    
370
                            // fields from legend
371
                            String[] aux = null;
372

    
373
                            if (legend instanceof IClassifiedVectorLegend) {
374
                                    aux = ((IClassifiedVectorLegend) legend).getClassifyingFieldNames();
375
                                    if (aux!=null) {
376
                                            for (int i = 0; i < aux.length; i++) {
377
                                                    // check fields exists
378
                                                    if (sds.getFieldIndexByName(aux[i]) == -1) {
379
                                                            logger.warn("Error en leyenda de " + getName() +
380
                                                                            ". El campo " + aux[i] + " no est?.");
381
                                                            legend = LegendFactory.createSingleSymbolLegend(getShapeType());
382
                                                            break;
383
                                                    }
384
                                                    fieldList.add(aux[i]);
385
                                            }
386
                                    }
387
                            }
388
                            // Get the iterator over the visible features
389
                            IFeatureIterator it = null;
390
                            if (isJoined()) {
391
                                    it = new JoinFeatureIterator(this, viewPort,
392
                                                    fieldList.toArray(new String[fieldList.size()]));
393
                            }
394
                            else {
395
                                    ReadableVectorial rv=getSource();
396
//                                    rv.start();
397
                                    it = rv.getFeatureIterator(
398
                                            viewPort.getAdjustedExtent(),
399
                                            fieldList.toArray(new String[fieldList.size()]),
400
                                            viewPort.getProjection(),
401
                                            true);
402
//                                    rv.stop();
403
                            }
404

    
405
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
406

    
407
                            boolean bSymbolLevelError = false;
408

    
409
                            // if layer has map levels it will use a ZSort
410
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
411

    
412
                            // -- visual FX stuff
413
                            long time = System.currentTimeMillis();
414
                            BufferedImage virtualBim;
415
                            Graphics2D virtualGraphics;
416

    
417
                            // render temporary map each screenRefreshRate milliseconds;
418
                            int screenRefreshDelay = (int) ((1D/MapControl.getDrawFrameRate())*3*1000);
419
                            BufferedImage[] imageLevels = null;
420
                            Graphics2D[] graphics = null;
421
                            if (useZSort) {
422
                                    imageLevels = new BufferedImage[zSort.getLevelCount()];
423
                                    graphics = new Graphics2D[imageLevels.length];
424
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
425
                                            imageLevels[i] = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
426
                                            graphics[i] = imageLevels[i].createGraphics();
427
                                            graphics[i].setTransform(g.getTransform());
428
                                            graphics[i].setRenderingHints(g.getRenderingHints());
429
                                    }
430
                            }
431
                            // -- end visual FX stuff
432

    
433
                            boolean isInMemory = false;
434
                            if (getSource().getDriverAttributes() != null){
435
                                    isInMemory = getSource().getDriverAttributes().isLoadedInMemory();
436
                            }
437
                            SelectionSupport selectionSupport=getSelectionSupport();
438
                            // Iteration over each feature
439
                            while ( !cancel.isCanceled() && it.hasNext()) {
440
                                    IFeature feat = it.next();
441
                                    IGeometry geom = null;
442

    
443
                                    if (isInMemory){
444
                                            geom = feat.getGeometry().cloneGeometry();
445
                                    }else{
446
                                            geom = feat.getGeometry();
447
                                    }
448

    
449
                                    if (cacheFeatures) {
450
                                            if (cache.getMaxFeatures() >= cache.size()) {
451
                                                    // already reprojected
452
                                                    cache.insert(geom.getBounds2D(), geom);
453
                                            }
454
                                    }
455

    
456
                                    // retrieve the symbol associated to such feature
457
                                    ISymbol sym = legend.getSymbolByFeature(feat);
458

    
459
                                    if (sym == null) continue;
460

    
461
                                    //C?digo para poder acceder a los ?ndices para ver si est? seleccionado un Feature
462
                                    ReadableVectorial rv=getSource();
463
                                    int selectionIndex=-1;
464
                                    if (rv instanceof ISpatialDB){
465
                                            selectionIndex = ((ISpatialDB)rv).getRowIndexByFID(feat);
466
                                    }else{
467
                                            selectionIndex = Integer.parseInt(feat.getID());
468
                                    }
469
                                    if (selectionIndex!=-1) {
470
                                            if (selectionSupport.isSelected(selectionIndex)) {
471
                                                    sym = sym.getSymbolForSelection();
472
                                            }
473
                                    }
474

    
475
                                    // Check if this symbol is sized with CartographicSupport
476
                                    CartographicSupport csSym = null;
477
                                    int symbolType = sym.getSymbolType();
478
                                    boolean bDrawCartographicSupport = false;
479

    
480
                                    if (   symbolType == FShape.POINT
481
                                                    || symbolType == FShape.LINE
482
                                                    || sym instanceof CartographicSupport) {
483

    
484
                                            // patch
485
                                            if (!sym.getClass().equals(FSymbol.class)) {
486
                                                    csSym = (CartographicSupport) sym;
487
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
488
                                            }
489
                                    }
490

    
491
                                    int x = -1;
492
                                    int y = -1;
493
                                    int[] xyCoords = new int[2];
494

    
495
                                    // Check if size is a pixel
496
                                    boolean onePoint = bDrawCartographicSupport ?
497
                                                    isOnePoint(g.getTransform(), viewPort, MapContext.getScreenDPI(), csSym, geom, xyCoords) :
498
                                                            isOnePoint(g.getTransform(), viewPort, geom, xyCoords);
499

    
500
                                                    // Avoid out of bounds exceptions
501
                                                    if (onePoint) {
502
                                                            x = xyCoords[0];
503
                                                            y = xyCoords[1];
504
                                                            if (x<0 || y<0 || x>= viewPort.getImageWidth() || y>=viewPort.getImageHeight()) continue;
505
                                                    }
506

    
507
                                                    if (useZSort) {
508
                                                            // Check if this symbol is a multilayer
509
                                                                int[] symLevels = zSort.getLevels(sym);
510
                                                            if (sym instanceof IMultiLayerSymbol) {
511
                                                                    // if so, treat each of its layers as a single symbol
512
                                                                    // in its corresponding map level
513
                                                                    IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
514
                                                                    for (int i = 0; !cancel.isCanceled() && i < mlSym.getLayerCount(); i++) {
515
                                                                            ISymbol mySym = mlSym.getLayer(i);
516
                                                                        int symbolLevel = 0;
517
                                                                        if (symLevels != null) {
518
                                                                                symbolLevel = symLevels[i];
519
                                                                        } else {
520
                                                                                    /* an error occured when managing symbol levels.
521
                                                                                     * some of the legend changed events regarding the
522
                                                                                     * symbols did not finish satisfactory and the legend
523
                                                                                     * is now inconsistent. For this drawing, it will finish
524
                                                                                     * as it was at the bottom (level 0) but, when done, the
525
                                                                                     * ZSort will be reset to avoid app crashes. This is
526
                                                                                     * a bug that has to be fixed.
527
                                                                                     */
528
                                                                                    bSymbolLevelError = true;
529
                                                                            }
530

    
531
                                                                            if (onePoint) {
532
                                                                                    if (x<0 || y<0 || x>= imageLevels[symbolLevel].getWidth() || y>=imageLevels[symbolLevel].getHeight()) continue;
533
                                                                                    imageLevels[symbolLevel].setRGB(x, y, mySym.getOnePointRgb());
534
                                                                            } else {
535
                                                                                    if (!bDrawCartographicSupport) {
536
                                                                                            geom.drawInts(graphics[symbolLevel], viewPort, mySym, cancel);
537
                                                                                    } else {
538
                                                                                            geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) mySym, cancel);
539
                                                                                    }
540
                                                                            }
541
                                                                    }
542
                                                            } else {
543
                                                                    // else, just draw the symbol in its level
544
                                                                    int symbolLevel = 0;
545
                                                                    if (symLevels != null) {
546

    
547
                                                                            symbolLevel=symLevels[0];
548
                                                                    } else {
549
                                                                            /* If symLevels == null
550
                                                                             * an error occured when managing symbol levels.
551
                                                                             * some of the legend changed events regarding the
552
                                                                             * symbols did not finish satisfactory and the legend
553
                                                                             * is now inconsistent. For this drawing, it will finish
554
                                                                             * as it was at the bottom (level 0). This is
555
                                                                             * a bug that has to be fixed.
556
                                                                             */
557
//                                                                            bSymbolLevelError = true;
558
                                                                    }
559

    
560
                                                                    if (!bDrawCartographicSupport) {
561
                                                                            geom.drawInts(graphics[symbolLevel], viewPort, sym, cancel);
562
                                                                    } else {
563
                                                                            geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) csSym, cancel);
564
                                                                    }
565
                                                            }
566

    
567
                                                            // -- visual FX stuff
568
                                                            // Cuando el offset!=0 se est? dibujando sobre el Layout y por tanto no tiene que ejecutar el siguiente c?digo.
569
                                                            if (offset.getX()==0 && offset.getY()==0)
570
                                                                    if ((System.currentTimeMillis() - time) > screenRefreshDelay) {
571
                                                                            virtualBim = new BufferedImage(image.getWidth(),image.getHeight(),BufferedImage.TYPE_INT_ARGB);
572
                                                                            virtualGraphics = virtualBim.createGraphics();
573
                                                                            virtualGraphics.drawImage(image,0,0, null);
574
                                                                            for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
575
                                                                                    virtualGraphics.drawImage(imageLevels[i],0,0, null);
576
                                                                            }
577
                                                                            g.clearRect(0, 0, image.getWidth(), image.getHeight());
578
                                                                            g.drawImage(virtualBim, 0, 0, null);
579
                                                                            time = System.currentTimeMillis();
580
                                                                    }
581
                                                            // -- end visual FX stuff
582

    
583
                                                    } else {
584
                                                            // no ZSort, so there is only a map level, symbols are
585
                                                            // just drawn.
586
                                                            if (onePoint) {
587
                                                                    if (x<0 || y<0 || x>= image.getWidth() || y>=image.getHeight()) continue;
588
                                                                    image.setRGB(x, y, sym.getOnePointRgb());
589
                                                            } else {
590
                                                                    if (!bDrawCartographicSupport) {
591
                                                                            geom.drawInts(g, viewPort, sym, cancel);
592
                                                                    } else {
593
                                                                            geom.drawInts(g, viewPort, dpi, csSym, cancel);
594
                                                                    }
595
                                                            }
596
                                                    }
597
                            }
598

    
599
                            if (useZSort) {
600
                                    g.drawImage(image, (int)offset.getX(), (int)offset.getY(), null);
601
                                    g.translate(offset.getX(), offset.getY());
602
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
603
                                            g.drawImage(imageLevels[i],0,0, null);
604
                                            imageLevels[i] = null;
605
                                            graphics[i] = null;
606
                                    }
607
                                    g.translate(-offset.getX(), -offset.getY());
608
                                    imageLevels = null;
609
                                    graphics = null;
610
                            }
611
                            it.closeIterator();
612

    
613
                            if (bSymbolLevelError) {
614
                                    ((IVectorLegend) getLegend()).setZSort(null);
615
                            }
616

    
617
                    } catch (ReadDriverException e) {
618
                            this.setVisible(false);
619
                            this.setActive(false);
620
                            throw e;
621
                    }
622

    
623

    
624
            }
625
    }
626

    
627
           public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
628
            Cancellable cancel, double scale) throws ReadDriverException {
629
//            forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD = true;
630
//            if (!isUseStrategy()) {
631
                   if (isWaitTodraw()) {
632
                        return;
633
                }
634
                   _draw(image, g, viewPort, cancel, scale);
635
//            } else {
636
////                    moved up to FLayers
637
////                    if (isWithinScale(scale)) {
638
//
639
//
640
//                            // Las que solo tienen etiquetado sin pintar el shape,
641
//                            // no pasamos por ellas
642
//                            boolean bDrawShapes = true;
643
//                            if (legend instanceof SingleSymbolLegend) {
644
//                                    if (legend.getDefaultSymbol().isShapeVisible() == false)
645
//                                            bDrawShapes = false;
646
//                            }
647
//                            if (bDrawShapes) {
648
//                                    Strategy strategy = StrategyManager.getStrategy(this);
649
//                                    try {
650
//                                            prepareDrawing(image, g, viewPort);
651
//                                            strategy.draw(image, g, viewPort, cancel);
652
//                                    } catch (ReadDriverException e) {
653
//                                            this.setVisible(false);
654
//                                            this.setActive(false);
655
//                                            throw e;
656
//                                    }
657
//                            }
658
//                            if (getVirtualLayers() != null) {
659
//                                    getVirtualLayers().draw(image, g, viewPort, cancel, scale);
660
//                            }
661
////                    }
662
//            }
663
    }
664

    
665
    /**
666
     * Se llama antes de empezar a pintar.
667
     * Es ?til para preparar la cache a emplear, las leyendas, etc.
668
     * @param image
669
     * @param g
670
     * @param viewPort
671
     */
672
    private void prepareDrawing(BufferedImage image, Graphics2D g, ViewPort viewPort) {
673

    
674
    }
675

    
676
    public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
677
                    double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
678
            // TEST METHOD
679

    
680

    
681
                    /* SVN */
682

    
683
    /*        boolean bDrawShapes = true;
684
            if (legend instanceof SingleSymbolLegend) {
685
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
686
            }
687

688

689
            if (bDrawShapes) {
690
                    double dpi = 72;
691

692
                    PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
693
                    if (resolution.equals(PrintQuality.NORMAL)){
694
                            dpi = 300;
695
                    } else if (resolution.equals(PrintQuality.HIGH)){
696
                            dpi = 600;
697
                    } else if (resolution.equals(PrintQuality.DRAFT)){
698
                            dpi = 72;
699
                    }
700

701

702
                    try {
703
                            prepareDrawing(null, g, viewPort);
704
                            ArrayList<String> fieldList = new ArrayList<String>();
705
                            String[] aux;
706

707
                            // fields from legend
708
                            if (legend instanceof IClassifiedVectorLegend) {
709
                                    aux = ((IClassifiedVectorLegend) legend).
710
                                                                            getClassifyingFieldNames();
711
                                    for (int i = 0; i < aux.length; i++) {
712
                                            fieldList.add(aux[i]);
713
                                    }
714
                            }
715

716
                            // fields from labeling
717
                            if (isLabeled()) {
718
                                    aux = getLabelingStrategy().getUsedFields();
719
                                    for (int i = 0; i < aux.length; i++) {
720
                                            fieldList.add(aux[i]);
721
                                    }
722
                            }
723

724
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
725

726
                            // if layer has map levels it will use a ZSort
727
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
728

729

730
                            int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
731
                            for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
732
                                    // Get the iterator over the visible features
733
                                    IFeatureIterator it = getSource().getFeatureIterator(
734
                                                    viewPort.getAdjustedExtent(),
735
                                                    fieldList.toArray(new String[fieldList.size()]),
736
                                                    viewPort.getProjection(),
737
                                                    true);
738

739
                                    // Iteration over each feature
740
                                    while ( !cancel.isCanceled() && it.hasNext()) {
741
                                            IFeature feat = it.next();
742
                                            IGeometry geom = feat.getGeometry();
743

744
                                            // retreive the symbol associated to such feature
745
                                            ISymbol sym = legend.getSymbolByFeature(feat);
746

747
                                            if (useZSort) {
748
                                                    // Check if this symbol is a multilayer
749
                                                        if (sym instanceof IMultiLayerSymbol) {
750
                                                                // if so, get the layer corresponding to the current
751
                                                                // level. If none, continue to next iteration
752
                                                                IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
753
                                                                for (int i = 0; i < mlSym.getLayerCount(); i++) {
754
                                                                        ISymbol mySym = mlSym.getLayer(i);
755
                                                                        if (zSort.getSymbolLevel(mySym) == mapPass) {
756
                                                                                sym = mySym;
757
                                                                                break;
758
                                                                        }
759
                                                                        System.out.println("avoided layer "+i+"of symbol '"+mlSym.getDescription()+"' (pass "+mapPass+")");
760
                                                                }
761

762
                                                                if (sym == null) {
763
                                                                        continue;
764
                                                                }
765
                                                        } else {
766
                                                                // else, just draw the symbol in its level
767
                                                                if (zSort.getSymbolLevel(sym) != mapPass) {
768
                                                                        System.out.println("avoided single layer symbol '"+sym.getDescription()+"' (pass "+mapPass+")");
769
                                                                        continue;
770
                                                                }
771
                                                        }
772
                                            }
773

774
                                            // Check if this symbol is sized with CartographicSupport
775
                                            CartographicSupport csSym = null;
776
                                            int symbolType = sym.getSymbolType();
777
                                            boolean bDrawCartographicSupport = false;
778

779
                                            if (   symbolType == FShape.POINT
780
                                                            || symbolType == FShape.LINE
781
                                                            || sym instanceof CartographicSupport) {
782

783
                                                    csSym = (CartographicSupport) sym;
784
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
785
                                            }
786

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

789
                                            if (!bDrawCartographicSupport) {
790
                                                    geom.drawInts(g, viewPort, sym, null);
791
                                            } else {
792
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym);
793
                                            }
794

795
                                    }
796
                                    it.closeIterator();
797
                            }
798
                    } catch (ReadDriverException e) {
799
                            this.setVisible(false);
800
                            this.setActive(false);
801
                            throw e;
802
                    }
803
        */
804

    
805

    
806
            // TEST METHOD
807
            boolean bDrawShapes = true;
808
            if (legend instanceof SingleSymbolLegend) {
809
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
810
            }
811

    
812

    
813
            if (bDrawShapes) {
814

    
815
                    try {
816
                            double dpi = 72;
817

    
818
                            PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
819
                            if (resolution.equals(PrintQuality.NORMAL)){
820
                                    dpi = 300;
821
                            } else if (resolution.equals(PrintQuality.HIGH)){
822
                                    dpi = 600;
823
                            } else if (resolution.equals(PrintQuality.DRAFT)){
824
                                    dpi = 72;
825
                            }
826
                            ArrayList<String> fieldList = new ArrayList<String>();
827
                            String[] aux;
828

    
829
                            // fields from legend
830
                            if (legend instanceof IClassifiedVectorLegend) {
831
                                    aux = ((IClassifiedVectorLegend) legend).
832
                                    getClassifyingFieldNames();
833
                                    for (int i = 0; i < aux.length; i++) {
834
                                            fieldList.add(aux[i]);
835
                                    }
836
                            }
837
//
838
//                            // fields from labeling
839
//                            if (isLabeled()) {
840
//                                    aux = getLabelingStrategy().getUsedFields();
841
//                                    for (int i = 0; i < aux.length; i++) {
842
//                                            fieldList.add(aux[i]);
843
//                                    }
844
//                            }
845

    
846
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
847

    
848
                            // if layer has map levels it will use a ZSort
849
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
850

    
851

    
852
                            int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
853
                            for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
854
                                    // Get the iterator over the visible features
855
//                                    IFeatureIterator it = getSource().getFeatureIterator(
856
//                                                    viewPort.getAdjustedExtent(),
857
//                                                    fieldList.toArray(new String[fieldList.size()]),
858
//                                                    viewPort.getProjection(),
859
//                                                    true);
860
                                IFeatureIterator it = null;
861
                                if (isJoined()) {
862
                                        it = new JoinFeatureIterator(this, viewPort,
863
                                                        fieldList.toArray(new String[fieldList.size()]));
864
                                }
865
                                else {
866
                                        it = getSource().getFeatureIterator(
867
                                                viewPort.getAdjustedExtent(),
868
                                                fieldList.toArray(new String[fieldList.size()]),
869
                                                viewPort.getProjection(),
870
                                                true);
871
                                }
872

    
873
                                    // Iteration over each feature
874
                                    while ( !cancel.isCanceled() && it.hasNext()) {
875
                                            IFeature feat = it.next();
876
                                            IGeometry geom = feat.getGeometry();
877

    
878
                                            // retreive the symbol associated to such feature
879
                                            ISymbol sym = legend.getSymbolByFeature(feat);
880
                                            if (sym == null) {
881
                                                        continue;
882
                                                }
883
                                            if (useZSort) {
884
                                                        int[] symLevels = zSort.getLevels(sym);
885
                                                        if(symLevels != null){
886
                                                                // Check if this symbol is a multilayer
887
                                                                if (sym instanceof IMultiLayerSymbol) {
888
                                                                        // if so, get the layer corresponding to the current
889
                                                                        // level. If none, continue to next iteration
890
                                                                        IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
891
                                                                        for (int i = 0; i < mlSym.getLayerCount(); i++) {
892
                                                                                ISymbol mySym = mlSym.getLayer(i);
893
                                                                                if (symLevels[i] == mapPass) {
894
                                                                                        sym = mySym;
895
                                                                                        break;
896
                                                                                }
897
                                                                                System.out.println("avoided layer "+i+"of symbol '"+mlSym.getDescription()+"' (pass "+mapPass+")");
898
                                                                        }
899
                                                                } else {
900
                                                                        // else, just draw the symbol in its level
901
                                                                        if (symLevels[0] != mapPass) {
902
                                                                                System.out.println("avoided single layer symbol '"+sym.getDescription()+"' (pass "+mapPass+")");
903
                                                                                continue;
904
                                                                        }
905
                                                                }
906
                                                        }
907
                                            }
908

    
909
                                            // Check if this symbol is sized with CartographicSupport
910
                                            CartographicSupport csSym = null;
911
                                            int symbolType = sym.getSymbolType();
912

    
913
                                            if (   symbolType == FShape.POINT
914
                                                            || symbolType == FShape.LINE
915
                                                            || sym instanceof CartographicSupport) {
916

    
917
                                                    csSym = (CartographicSupport) sym;
918
                                            }
919

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

    
922
                                            if (csSym == null) {
923
                                                    geom.drawInts(g, viewPort, sym, null);
924
                                            } else {
925
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym, cancel);
926
                                            }
927

    
928
                                    }
929
                                    it.closeIterator();
930
                            }
931
                    } catch (ReadDriverException e) {
932
                            this.setVisible(false);
933
                            this.setActive(false);
934
                            throw e;
935
                    }
936
            }
937
    }
938

    
939

    
940
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
941
            double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
942
//            if (forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD) {
943
                    _print(g, viewPort, cancel, scale, properties);
944
//            } else {
945
////                    moved up to Flayers
946
////                    if (isVisible() && isWithinScale(scale)) {
947
//                            Strategy strategy = StrategyManager.getStrategy(this);
948
//
949
//                            strategy.print(g, viewPort, cancel, properties);
950
//                            ILabelingStrategy labeling;
951
//                            if ( (labeling = getLabelingStrategy() ) != null) {
952
//                                    // contains labels
953
//                                    labeling.print(g, viewPort, cancel, properties);
954
//                            }
955
////                    }
956
//            }
957
    }
958

    
959
    public void deleteSpatialIndex() {
960
        //must we delete possible spatial indexes files?
961
        spatialIndex = null;
962
    }
963

    
964
   /**
965
    * <p>
966
    * Creates an spatial index associated to this layer.
967
    * The spatial index will used
968
    * the native projection of the layer, so if the layer is reprojected, it will
969
    * be ignored.
970
    * </p>
971
    * @param cancelMonitor instance of CancellableMonitorable that allows
972
    * to monitor progress of spatial index creation, and cancel the process
973
    */
974
    public void createSpatialIndex(CancellableMonitorable cancelMonitor){
975
         // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
976
        // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
977
        // para que acepten recorrer sin geometria, solo con rectangulos.
978

    
979
        //If this vectorial layer is based in a spatial database, the spatial
980
        //index is already implicit. We only will index file drivers
981
        ReadableVectorial va = getSource();
982
        //We must think in non spatial databases, like HSQLDB
983
        if(!(va instanceof VectorialFileAdapter)){
984
            return;
985
        }
986
        if (!(va.getDriver() instanceof BoundedShapes)) {
987
            return;
988
        }
989
        File file = ((VectorialFileAdapter) va).getFile();
990
        String fileName = file.getAbsolutePath();
991
        ISpatialIndex localCopy = null;
992
        try {
993
            va.start();
994
            localCopy = new QuadtreeGt2(fileName, "NM", va.getFullExtent(),
995
                    va.getShapeCount(), true);
996

    
997
        } catch (SpatialIndexException e1) {
998
            // Probably we dont have writing permissions
999
            String directoryName = System.getProperty("java.io.tmpdir");
1000
            File newFile = new File(directoryName +
1001
                    File.separator +
1002
                    file.getName());
1003
            String newFileName = newFile.getName();
1004
            try {
1005
                localCopy = new QuadtreeGt2(newFileName, "NM", va.getFullExtent(),
1006
                        va.getShapeCount(), true);
1007
            } catch (SpatialIndexException e) {
1008
                // if we cant build a file based spatial index, we'll build
1009
                // a pure memory spatial index
1010
                localCopy = new QuadtreeJts();
1011
            } catch (ReadDriverException e) {
1012
                localCopy = new QuadtreeJts();
1013
            }
1014

    
1015
        } catch(Exception e){
1016
            e.printStackTrace();
1017
        }//try
1018
        BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
1019
        try {
1020
            for (int i=0; i < va.getShapeCount(); i++)
1021
            {
1022
                if(cancelMonitor != null){
1023
                    if(cancelMonitor.isCanceled())
1024
                        return;
1025
                    cancelMonitor.reportStep();
1026
                }
1027
                Rectangle2D r = shapeBounds.getShapeBounds(i);
1028
                if(r != null)
1029
                    localCopy.insert(r, i);
1030
            } // for
1031
            va.stop();
1032
            if(localCopy instanceof IPersistentSpatialIndex)
1033
                ((IPersistentSpatialIndex) localCopy).flush();
1034
            spatialIndex = localCopy;
1035
            //vectorial adapter needs a reference to the spatial index, to solve
1036
            //request for feature iteration based in spatial queries
1037
            source.setSpatialIndex(spatialIndex);
1038
        } catch (ReadDriverException e) {
1039
            // TODO Auto-generated catch block
1040
            e.printStackTrace();
1041
        }
1042
    }
1043

    
1044
    public void createSpatialIndex() {
1045
        createSpatialIndex(null);
1046
    }
1047

    
1048
    public void process(FeatureVisitor visitor, FBitSet subset)
1049
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
1050
        Strategy s = StrategyManager.getStrategy(this);
1051
        s.process(visitor, subset);
1052
    }
1053

    
1054
    public void process(FeatureVisitor visitor) throws ReadDriverException, VisitorException {
1055
        Strategy s = StrategyManager.getStrategy(this);
1056
        s.process(visitor);
1057
    }
1058

    
1059
    public void process(FeatureVisitor visitor, Rectangle2D rect)
1060
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
1061
        Strategy s = StrategyManager.getStrategy(this);
1062
        s.process(visitor, rect);
1063
    }
1064

    
1065
    public FBitSet queryByRect(Rectangle2D rect) throws ReadDriverException, VisitorException {
1066
        Strategy s = StrategyManager.getStrategy(this);
1067

    
1068
        return s.queryByRect(rect);
1069
    }
1070

    
1071
    public FBitSet queryByPoint(Point2D p, double tolerance)
1072
            throws ReadDriverException, VisitorException {
1073
        Strategy s = StrategyManager.getStrategy(this);
1074
        return s.queryByPoint(p, tolerance);
1075
    }
1076

    
1077
    public FBitSet queryByShape(IGeometry g, int relationship)
1078
            throws ReadDriverException, VisitorException {
1079
        Strategy s = StrategyManager.getStrategy(this);
1080
        return s.queryByShape(g, relationship);
1081
    }
1082

    
1083
    public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancel) throws ReadDriverException, VisitorException {
1084
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(p);
1085
        FBitSet bs = queryByPoint(pReal, tolerance);
1086
        VectorialXMLItem[] item = new VectorialXMLItem[1];
1087
        item[0] = new VectorialXMLItem(bs, this);
1088

    
1089
        return item;
1090
    }
1091

    
1092
    public void setLegend(IVectorLegend r) throws LegendLayerException {
1093
            if (this.legend == r){
1094
                    return;
1095
            }
1096
                if (this.legend != null && this.legend.equals(r)){
1097
                        return;
1098
                }
1099
        IVectorLegend oldLegend = legend;
1100

    
1101
        /*
1102
         * Parche para discriminar las leyendas clasificadas cuyos campos de
1103
         * clasificaci?n no est?n en la fuente de la capa.
1104
         *
1105
         * Esto puede ocurrir porque en versiones anteriores se admit?an
1106
         * leyendas clasificadas en capas que se han unido a una tabla
1107
         * por campos que pertenec?an a la tabla y no s?lo a la capa.
1108
         *
1109
         */
1110
//                if(r instanceof IClassifiedVectorLegend){
1111
//                        IClassifiedVectorLegend classifiedLegend = (IClassifiedVectorLegend)r;
1112
//                        String[] fieldNames = classifiedLegend.getClassifyingFieldNames();
1113
//
1114
//                        for (int i = 0; i < fieldNames.length; i++) {
1115
//                                try {
1116
//                                        if(this.getRecordset().getFieldIndexByName(fieldNames[i]) == -1){
1117
////                                        if(this.getSource().getRecordset().getFieldIndexByName(fieldNames[i]) == -1){
1118
//                                                logger.warn("Some fields of the classification of the legend doesn't belong with the source of the layer.");
1119
//                                                if (this.legend == null){
1120
//                                                        r = LegendFactory.createSingleSymbolLegend(this.getShapeType());
1121
//                                                } else {
1122
//                                                        return;
1123
//                                                }
1124
//                                        }
1125
//                                } catch (ReadDriverException e1) {
1126
//                                        throw new LegendLayerException(getName(),e1);
1127
//                                }
1128
//                        }
1129
//                }
1130
                /* Fin del parche */
1131

    
1132
                legend = r;
1133
        try {
1134
            legend.setDataSource(getRecordset());
1135
        } catch (FieldNotFoundException e1) {
1136
            throw new LegendLayerException(getName(),e1);
1137
        } catch (ReadDriverException e1) {
1138
            throw new LegendLayerException(getName(),e1);
1139
        } finally{
1140
                this.updateDrawVersion();
1141
        }
1142
        if (oldLegend != null){
1143
                oldLegend.removeLegendListener(this);
1144
        }
1145
        if (legend != null){
1146
                legend.addLegendListener(this);
1147
        }
1148
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
1149
                oldLegend, legend);
1150
        e.setLayer(this);
1151
        callLegendChanged(e);
1152
    }
1153

    
1154
    /**
1155
     * Devuelve la Leyenda de la capa.
1156
     *
1157
     * @return Leyenda.
1158
     */
1159
    public ILegend getLegend() {
1160
        return legend;
1161
    }
1162

    
1163
    /**
1164
     * Devuelve el tipo de shape que contiene la capa.
1165
     *
1166
     * @return tipo de shape.
1167
     *
1168
     * @throws DriverException
1169
     */
1170
    public int getShapeType() throws ReadDriverException {
1171
        if (typeShape == -1) {
1172
            getSource().start();
1173
            typeShape = getSource().getShapeType();
1174
            getSource().stop();
1175
        }
1176

    
1177
        return typeShape;
1178
    }
1179

    
1180
    public XMLEntity getXMLEntity() throws XMLException {
1181
        if (!this.isAvailable() && this.orgXMLEntity != null) {
1182
            return this.orgXMLEntity;
1183
        }
1184
        XMLEntity xml = super.getXMLEntity();
1185
        if (getLegend()!=null)
1186
            xml.addChild(getLegend().getXMLEntity());
1187
        try {
1188
            if (getRecordset()!=null)
1189
                xml.addChild(getRecordset().getSelectionSupport().getXMLEntity());
1190
        } catch (ReadDriverException e1) {
1191
            e1.printStackTrace();
1192
            throw new XMLException(e1);
1193
        }
1194
        // Repongo el mismo ReadableVectorial m?s abajo para cuando se guarda el proyecto.
1195
        ReadableVectorial rv=getSource();
1196
        xml.putProperty("type", "vectorial");
1197
        if (source instanceof VectorialEditableAdapter) {
1198
            setSource(((VectorialEditableAdapter) source).getOriginalAdapter());
1199
        }
1200
        if (source instanceof VectorialFileAdapter) {
1201
            xml.putProperty("type", "vectorial");
1202
            xml.putProperty("file", ((VectorialFileAdapter) source)
1203
                    .getFile());
1204
            try {
1205
                xml.putProperty("recordset-name", source.getRecordset()
1206
                        .getName());
1207
            } catch (ReadDriverException e) {
1208
                throw new XMLException(e);
1209
            } catch (RuntimeException e) {
1210
                e.printStackTrace();
1211
            }
1212
        } else if (source instanceof VectorialDBAdapter) {
1213
            xml.putProperty("type", "vectorial");
1214

    
1215
            IVectorialDatabaseDriver dbDriver = (IVectorialDatabaseDriver) source
1216
                    .getDriver();
1217

    
1218
            // Guardamos el nombre del driver para poder recuperarlo
1219
            // con el DriverManager de Fernando.
1220
            xml.putProperty("db", dbDriver.getName());
1221
            try {
1222
                xml.putProperty("recordset-name", source.getRecordset()
1223
                        .getName());
1224
            } catch (ReadDriverException e) {
1225
                throw new XMLException(e);
1226
            } catch (RuntimeException e) {
1227
                e.printStackTrace();
1228
            }
1229
            xml.addChild(dbDriver.getXMLEntity()); // Tercer child. Antes hemos
1230
                                                    // metido la leyenda y el
1231
                                                    // selection support
1232
        } else if (source instanceof VectorialAdapter) {
1233
            // Se supone que hemos hecho algo gen?rico.
1234
            xml.putProperty("type", "vectorial");
1235

    
1236
            VectorialDriver driver = source.getDriver();
1237

    
1238
            // Guardamos el nombre del driver para poder recuperarlo
1239
            // con el DriverManager de Fernando.
1240
            xml.putProperty("other", driver.getName());
1241
            // try {
1242
            try {
1243
                xml.putProperty("recordset-name", source.getRecordset()
1244
                        .getName());
1245
            } catch (ReadDriverException e) {
1246
                throw new XMLException(e);
1247
            } catch (RuntimeException e) {
1248
                e.printStackTrace();
1249
            }
1250
            if (driver instanceof IPersistence) {
1251
                // xml.putProperty("className", driver.getClass().getName());
1252
                    IPersistence persist = (IPersistence) driver;
1253
                xml.addChild(persist.getXMLEntity()); // Tercer child. Antes
1254
                                                        // hemos metido la
1255
                                                        // leyenda y el
1256
                                                        // selection support
1257
            }
1258
        }
1259
        if (rv!=null)
1260
            setSource(rv);
1261
        xml.putProperty("driverName", source.getDriver().getName());
1262
        if (bHasJoin)
1263
            xml.putProperty("hasJoin", "true");
1264

    
1265
        // properties from ILabelable
1266
        xml.putProperty("isLabeled", isLabeled);
1267
        if (strategy != null) {
1268
            XMLEntity strategyXML = strategy.getXMLEntity();
1269
            strategyXML.putProperty("Strategy", strategy.getClassName());
1270
            xml.addChild(strategy.getXMLEntity());
1271
        }
1272
        xml.addChild(getLinkProperties().getXMLEntity());
1273
        return xml;
1274
    }
1275

    
1276
    /**
1277
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1278
     */
1279
    public void setXMLEntity03(XMLEntity xml) throws XMLException {
1280

    
1281
        super.setXMLEntity(xml);
1282
        legend = LegendFactory.createFromXML03(xml.getChild(0));
1283

    
1284
        try {
1285
            setLegend(legend);
1286
        } catch (LegendLayerException e) {
1287
            throw new XMLException(e);
1288
        }
1289

    
1290
        try {
1291
            getRecordset().getSelectionSupport()
1292
                    .setXMLEntity03(xml.getChild(1));
1293
        } catch (ReadDriverException e) {
1294
            e.printStackTrace();
1295
        }
1296
    }
1297

    
1298
    /*
1299
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1300
     */
1301
    public void setXMLEntity(XMLEntity xml) throws XMLException {
1302
        try {
1303
                    super.setXMLEntity(xml);
1304
                    XMLEntity legendXML = xml.getChild(0);
1305
                    IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1306

    
1307
                    /*
1308
                     * Parche para detectar cuando, por algun problema de persistencia
1309
                     * respecto a versiones anteriores, la leyenda que se ha cargado
1310
                     * no se corresponde con el tipo de shape de la capa.
1311
                     */
1312
                    int legShapeType = leg.getShapeType();
1313
                    if (legShapeType != 0 && legShapeType != this.getShapeType()){
1314
                            leg = LegendFactory.createSingleSymbolLegend(this.getShapeType());
1315
                                logger.warn("Legend shape type and layer shape type does not match.");
1316
                    }
1317
                    /* Fin del parche */
1318

    
1319
                    try {
1320
                            getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1321
                            // JMVIVO: Esto sirve para algo????
1322
                            /*
1323
                             *  Jaume: si, para restaurar el selectable datasource cuando se
1324
                             *  clona la capa, cuando se carga de un proyecto. Si no esta ya
1325
                             *  no se puede ni hacer consultas sql, ni hacer selecciones,
1326
                             *  ni usar la mayor parte de las herramientas.
1327
                             *
1328
                             *  Lo vuelvo a poner.
1329
                             */
1330

    
1331
                            String recordsetName = xml.getStringProperty("recordset-name");
1332

    
1333
//                            SelectableDataSource sds = new SelectableDataSource(LayerFactory
1334
//                                            .getDataSourceFactory().createRandomDataSource(
1335
//                                                            recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
1336

    
1337
                            LayerFactory.getDataSourceFactory().changeDataSourceName(
1338
                                            getSource().getRecordset().getName(), recordsetName);
1339
                            SelectableDataSource sds = new SelectableDataSource(LayerFactory
1340
                                            .getDataSourceFactory().createRandomDataSource(
1341
                                                            recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
1342

    
1343
                    } catch (NoSuchTableException e1) {
1344
                            this.setAvailable(false);
1345
                            throw new XMLException(e1);
1346
                    } catch (ReadDriverException e1) {
1347
                            this.setAvailable(false);
1348
                            throw new XMLException(e1);
1349
                    }
1350
                    // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1351
                    // el final
1352
                    // de la lectura del proyecto
1353
                    if (xml.contains("hasJoin")) {
1354
                            setIsJoined(true);
1355
                            PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1356
                    } else {
1357
                            try {
1358
                                    setLegend(leg);
1359
                            } catch (LegendLayerException e) {
1360
                                    throw new XMLException(e);
1361
                            }
1362
                    }
1363

    
1364
                    //Por compatibilidad con proyectos anteriores a la 1.0
1365
                    boolean containsIsLabeled = xml.contains("isLabeled");
1366
                    if (containsIsLabeled){
1367
                            isLabeled = xml.getBooleanProperty("isLabeled");
1368
                    }
1369
                    // set properties for ILabelable
1370
                    XMLEntity labelingXML = xml.firstChild("labelingStrategy", "labelingStrategy");
1371
                    if (labelingXML!= null) {
1372
                            if(!containsIsLabeled){
1373
                                    isLabeled = true;
1374
                            }
1375
                            try {
1376
                                    ILabelingStrategy labeling = LabelingFactory.createStrategyFromXML(labelingXML, this);
1377
                                    if (isJoined()) {
1378
                                            PostProcessSupport.addToPostProcess(this, "setLabelingStrategy", labeling, 1);
1379
                                    }
1380
                                    else
1381
                                            this.setLabelingStrategy(labeling);
1382

    
1383
                            } catch (NotExistInXMLEntity neXMLEX) {
1384
                                    // no strategy was set, just continue;
1385
                                    logger.warn("Reached what should be unreachable code");
1386
                            }
1387
                    } else if (legendXML.contains("labelFieldName")|| legendXML.contains("labelfield")) {
1388
                            /* (jaume) begin patch;
1389
                         * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1390
                         * no longer managed by the Legend but by the ILabelingStrategy. The
1391
                         * following allows restoring older projects' labelings.
1392
                         */
1393
                            String labelTextField =        null;
1394
                            if (legendXML.contains("labelFieldName")){
1395
                                    labelTextField = legendXML.getStringProperty("labelFieldName");
1396
                                if (labelTextField != null) {
1397
                                        AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1398
                                        labeling.setLayer(this);
1399
                                                int unit = 1;
1400
                                                boolean useFixedSize = false;
1401
                                            String labelFieldHeight = legendXML.getStringProperty("labelHeightFieldName");
1402
                                            labeling.setTextField(labelTextField);
1403
                                            if(labelFieldHeight!=null){
1404
                                                    labeling.setHeightField(labelFieldHeight);
1405
                                            } else {
1406
                                                    double size = -1;
1407
                                                    for(int i=0; i<legendXML.getChildrenCount();i++){
1408
                                                            XMLEntity xmlChild = legendXML.getChild(i);
1409
                                                            if(xmlChild.contains("m_FontSize")){
1410
                                                                    double childFontSize =  xmlChild.getDoubleProperty("m_FontSize");
1411
                                                                    if(size<0){
1412
                                                                            size = childFontSize;
1413
                                                                            useFixedSize = true;
1414
                                                                    } else {
1415
                                                                            useFixedSize = useFixedSize && (size==childFontSize);
1416
                                                                    }
1417
                                                                    if(xmlChild.contains("m_bUseFontSize")){
1418
                                                                            if(xmlChild.getBooleanProperty("m_bUseFontSize")){
1419
                                                                                    unit = -1;
1420
                                                                            } else {
1421
                                                                                    unit = 1;
1422
                                                                            }
1423
                                                                    }
1424
                                                            }
1425
                                                    }
1426
                                                    labeling.setFixedSize(size/1.4);//Factor de correcci?n que se aplicaba antes en el etiquetado
1427
                                            }
1428
                                                labeling.setUsesFixedSize(useFixedSize);
1429
                                                labeling.setUnit(unit);
1430
                                        labeling.setRotationField(legendXML.getStringProperty("labelRotationFieldName"));
1431
                                        if (isJoined()) {
1432
                                                PostProcessSupport.addToPostProcess(this, "setLabelingStrategy", labeling, 1);
1433
                                        }
1434
                                        else
1435
                                                this.setLabelingStrategy(labeling);
1436
                                        this.setIsLabeled(true);
1437
                                }
1438
                            }else{
1439
                                    labelTextField = legendXML.getStringProperty("labelfield");
1440
                                    if (labelTextField != null) {
1441
                                            AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1442
                                            labeling.setLayer(this);
1443
                                                int unit = 1;
1444
                                                boolean useFixedSize = false;
1445
                                            String labelFieldHeight = legendXML.getStringProperty("labelFieldHeight");
1446
                                            labeling.setTextField(labelTextField);
1447
                                            if(labelFieldHeight!=null){
1448
                                                    labeling.setHeightField(labelFieldHeight);
1449
                                            } else {
1450
                                                    double size = -1;
1451
                                                    for(int i=0; i<legendXML.getChildrenCount();i++){
1452
                                                            XMLEntity xmlChild = legendXML.getChild(i);
1453
                                                            if(xmlChild.contains("m_FontSize")){
1454
                                                                    double childFontSize =  xmlChild.getDoubleProperty("m_FontSize");
1455
                                                                    if(size<0){
1456
                                                                            size = childFontSize;
1457
                                                                            useFixedSize = true;
1458
                                                                    } else {
1459
                                                                            useFixedSize = useFixedSize && (size==childFontSize);
1460
                                                                    }
1461
                                                                    if(xmlChild.contains("m_bUseFontSize")){
1462
                                                                            if(xmlChild.getBooleanProperty("m_bUseFontSize")){
1463
                                                                                    unit = -1;
1464
                                                                            } else {
1465
                                                                                    unit = 1;
1466
                                                                            }
1467
                                                                    }
1468
                                                            }
1469
                                                    }
1470
                                                    labeling.setFixedSize(size/1.4);//Factor de correcci?n que se aplicaba antes en el etiquetado
1471
                                            }
1472
                                                labeling.setUsesFixedSize(useFixedSize);
1473
                                                labeling.setUnit(unit);
1474
                                            labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
1475
                                        if (isJoined()) {
1476
                                                PostProcessSupport.addToPostProcess(this, "setLabelingStrategy", labeling, 1);
1477
                                        }
1478
                                        else
1479
                                                this.setLabelingStrategy(labeling);
1480
                                            this.setIsLabeled(true);
1481
                                    }
1482
                            }
1483

    
1484
                }else if(!containsIsLabeled){
1485
                                    isLabeled = false;
1486
                    }
1487

    
1488
                    // compatibility with hyperlink from 1.9 alpha version... do we really need to be compatible with alpha versions??
1489
                    XMLEntity xmlLinkProperties=xml.firstChild("typeChild", "linkProperties");
1490
                    if (xmlLinkProperties != null){
1491
                            try {
1492
                                    String fieldName=xmlLinkProperties.getStringProperty("fieldName");
1493
                                    xmlLinkProperties.remove("fieldName");
1494
                                    String extName = xmlLinkProperties.getStringProperty("extName");
1495
                                    xmlLinkProperties.remove("extName");
1496
                                    int typeLink = xmlLinkProperties.getIntProperty("typeLink");
1497
                                    xmlLinkProperties.remove("typeLink");
1498
                                    if (fieldName!=null) {
1499
                                            setProperty("legacy.hyperlink.selectedField", fieldName);
1500
                                            setProperty("legacy.hyperlink.type", new Integer(typeLink));
1501
                                            if (extName!=null) {
1502
                                                    setProperty("legacy.hyperlink.extension", extName);
1503
                                            }
1504
                                    }
1505
                            }
1506
                            catch (NotExistInXMLEntity ex) {
1507
                                    logger.warn("Error getting old hyperlink configuration", ex);
1508
                            }
1509
                    }
1510

    
1511
            } catch (XMLException e) {
1512
                    this.setAvailable(false);
1513
                    this.orgXMLEntity = xml;
1514
            } catch (Exception e) {
1515
                    e.printStackTrace();
1516
                    this.setAvailable(false);
1517
                    this.orgXMLEntity = xml;
1518

    
1519
            }
1520

    
1521

    
1522
    }
1523

    
1524
    public void setXMLEntityNew(XMLEntity xml) throws XMLException {
1525
        try {
1526
            super.setXMLEntity(xml);
1527

    
1528
            XMLEntity legendXML = xml.getChild(0);
1529
            IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1530
            /* (jaume) begin patch;
1531
             * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1532
             * no longer managed by the Legend but by the ILabelingStrategy. The
1533
             * following allows restoring older projects' labelings.
1534
             */
1535
            if (legendXML.contains("labelFieldHeight")) {
1536
                AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1537
                labeling.setLayer(this);
1538
                labeling.setTextField(legendXML.getStringProperty("labelFieldHeight"));
1539
                labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
1540
                this.setLabelingStrategy(labeling);
1541
                this.setIsLabeled(true);
1542
              }
1543
            /* end patch */
1544
            try {
1545
                getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1546

    
1547
                this.setLoadSelection(xml.getChild(1));
1548
            } catch (ReadDriverException e1) {
1549
                this.setAvailable(false);
1550
                throw new XMLException(e1);
1551
            }
1552
            // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1553
            // el final
1554
            // de la lectura del proyecto
1555
            if (xml.contains("hasJoin")) {
1556
                setIsJoined(true);
1557
                PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1558
            } else {
1559
                this.setLoadLegend(leg);
1560
            }
1561

    
1562
        } catch (XMLException e) {
1563
            this.setAvailable(false);
1564
            this.orgXMLEntity = xml;
1565
        } catch (Exception e) {
1566
            this.setAvailable(false);
1567
            this.orgXMLEntity = xml;
1568
        }
1569

    
1570

    
1571
    }
1572

    
1573

    
1574
    /**
1575
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
1576
     * identifiquen la capa.
1577
     *
1578
     * @return DOCUMENT ME!
1579
     */
1580
    public String toString() {
1581
        /*
1582
         * Se usa internamente para que la parte de datos identifique de forma
1583
         * un?voca las tablas
1584
         */
1585
        String ret = super.toString();
1586

    
1587
        return "layer" + ret.substring(ret.indexOf('@') + 1);
1588
    }
1589

    
1590
    public boolean isJoined() {
1591
        return bHasJoin;
1592
    }
1593

    
1594
    /**
1595
     * Returns if a layer is spatially indexed
1596
     *
1597
     * @return if this layer has the ability to proces spatial queries without
1598
     *         secuential scans.
1599
     */
1600
    public boolean isSpatiallyIndexed() {
1601
        ReadableVectorial source = getSource();
1602
        if (source instanceof ISpatialDB)
1603
            return true;
1604

    
1605
//FIXME azabala
1606
/*
1607
 * Esto es muy dudoso, y puede cambiar.
1608
 * Estoy diciendo que las que no son fichero o no son
1609
 * BoundedShapes estan indexadas. Esto es mentira, pero
1610
 * as? quien pregunte no querr? generar el indice.
1611
 * Esta por ver si interesa generar el indice para capas
1612
 * HSQLDB, WFS, etc.
1613
 */
1614
        if(!(source instanceof VectorialFileAdapter)){
1615
            return true;
1616
        }
1617
        if (!(source.getDriver() instanceof BoundedShapes)) {
1618
            return true;
1619
        }
1620

    
1621
        if (getISpatialIndex() != null)
1622
            return true;
1623
        return false;
1624
    }
1625

    
1626
    public void setIsJoined(boolean hasJoin) {
1627
        bHasJoin = hasJoin;
1628
    }
1629

    
1630
    /**
1631
     * @return Returns the spatialIndex.
1632
     */
1633
    public ISpatialIndex getISpatialIndex() {
1634
        return spatialIndex;
1635
    }
1636
    /**
1637
     * Sets the spatial index. This could be useful if, for some
1638
     * reasons, you want to work with a distinct spatial index
1639
     * (for example, a spatial index which could makes nearest
1640
     * neighbour querys)
1641
     * @param spatialIndex
1642
     */
1643
    public void setISpatialIndex(ISpatialIndex spatialIndex){
1644
        this.spatialIndex = spatialIndex;
1645
    }
1646

    
1647
    public SelectableDataSource getRecordset() throws ReadDriverException {
1648
        if (!this.isAvailable()) return null;
1649
        if (sds == null) {
1650

    
1651
                SelectableDataSource ds = source.getRecordset();
1652

    
1653
                if (ds == null) {
1654
                    return null;
1655
                }
1656

    
1657
                sds = ds;
1658
                getSelectionSupport().addSelectionListener(this);
1659

    
1660
        }
1661
        return sds;
1662
    }
1663

    
1664
    public void setEditing(boolean b) throws StartEditionLayerException {
1665
        super.setEditing(b);
1666
        try {
1667
            if (b) {
1668
                VectorialEditableAdapter vea = null;
1669
                // TODO: Qu? pasa si hay m?s tipos de adapters?
1670
                // FJP: Se podr?a pasar como argumento el
1671
                // VectorialEditableAdapter
1672
                // que se quiera usar para evitar meter c?digo aqu? de este
1673
                // estilo.
1674
                if (getSource() instanceof VectorialDBAdapter) {
1675
                    vea = new VectorialEditableDBAdapter();
1676
                } else if (this instanceof FLyrAnnotation) {
1677
                    vea = new AnnotationEditableAdapter(
1678
                            (FLyrAnnotation) this);
1679
                } else {
1680
                    vea = new VectorialEditableAdapter();
1681
                }
1682
                vea.addEditionListener(this);
1683
                vea.setOriginalVectorialAdapter(getSource());
1684
//                                azo: implementations of readablevectorial need
1685
                //references of projection and spatial index
1686
                vea.setProjection(getProjection());
1687
                vea.setSpatialIndex(spatialIndex);
1688

    
1689

    
1690
                // /vea.setSpatialIndex(getSpatialIndex());
1691
                // /vea.setFullExtent(getFullExtent());
1692
                vea.setCoordTrans(getCoordTrans());
1693
                vea.startEdition(EditionEvent.GRAPHIC);
1694
                setSource(vea);
1695
                getRecordset().setSelectionSupport(
1696
                        vea.getOriginalAdapter().getRecordset()
1697
                                .getSelectionSupport());
1698

    
1699
            } else {
1700
                VectorialEditableAdapter vea = (VectorialEditableAdapter) getSource();
1701
                vea.removeEditionListener(this);
1702
                setSource(vea.getOriginalAdapter());
1703
            }
1704
            // Si tenemos una leyenda, hay que pegarle el cambiazo a su
1705
            // recordset
1706
            setRecordset(getSource().getRecordset());
1707
            if (getLegend() instanceof IVectorLegend) {
1708
                IVectorLegend ley = (IVectorLegend) getLegend();
1709
                ley.setDataSource(getSource().getRecordset());
1710
                // Esto lo pongo para evitar que al dibujar sobre un
1711
                // dxf, dwg, o dgn no veamos nada. Es debido al checkbox
1712
                // de la leyenda de textos "dibujar solo textos".
1713
//jaume
1714
//                                if (!(getSource().getDriver() instanceof IndexedShpDriver)){
1715
//                                        FSymbol symbol=new FSymbol(getShapeType());
1716
//                                        symbol.setFontSizeInPixels(false);
1717
//                                        symbol.setFont(new Font("SansSerif", Font.PLAIN, 9));
1718
//                                        Color color=symbol.getColor();
1719
//                                        int alpha=symbol.getColor().getAlpha();
1720
//                                        if (alpha>250) {
1721
//                                                symbol.setColor(new Color(color.getRed(),color.getGreen(),color.getBlue(),100));
1722
//                                        }
1723
//                                        ley.setDefaultSymbol(symbol);
1724
//                                }
1725
//jaume//
1726
                ley.useDefaultSymbol(true);
1727
            }
1728
        } catch (ReadDriverException e) {
1729
            throw new StartEditionLayerException(getName(),e);
1730
        } catch (FieldNotFoundException e) {
1731
            throw new StartEditionLayerException(getName(),e);
1732
        } catch (StartWriterVisitorException e) {
1733
            throw new StartEditionLayerException(getName(),e);
1734
        }
1735

    
1736
        setSpatialCacheEnabled(b);
1737
        callEditionChanged(LayerEvent
1738
                .createEditionChangedEvent(this, "edition"));
1739

    
1740
    }
1741

    
1742
    /**
1743
     * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
1744
     * forma, podr?s poner leyendas basadas en el nuevo recordset
1745
     *
1746
     * @param newSds
1747
     */
1748
    public void setRecordset(SelectableDataSource newSds) {
1749
            // TODO: Deberiamos hacer comprobaciones del cambio
1750
        sds = newSds;
1751
                getSelectionSupport().addSelectionListener(this);
1752
                this.updateDrawVersion();
1753
    }
1754

    
1755
    public void clearSpatialCache()
1756
    {
1757
        spatialCache.clearAll();
1758
    }
1759

    
1760
    public boolean isSpatialCacheEnabled() {
1761
        return spatialCacheEnabled;
1762
    }
1763

    
1764
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1765
        this.spatialCacheEnabled = spatialCacheEnabled;
1766
    }
1767

    
1768
    public SpatialCache getSpatialCache() {
1769
        return spatialCache;
1770
    }
1771

    
1772
    /**
1773
     * Siempre es un numero mayor de 1000
1774
     * @param maxFeatures
1775
     */
1776
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
1777
        if (maxFeatures > spatialCache.maxFeatures)
1778
            spatialCache.setMaxFeatures(maxFeatures);
1779

    
1780
    }
1781

    
1782
    /**
1783
     * This method returns a boolean that is used by the FPopMenu
1784
     * to make visible the properties menu or not. It is visible by
1785
     * default, and if a later don't have to show this menu only
1786
     * has to override this method.
1787
     * @return
1788
     * If the properties menu is visible (or not)
1789
     */
1790
    public boolean isPropertiesMenuVisible(){
1791
        return true;
1792
    }
1793

    
1794
    public void reload() throws ReloadLayerException {
1795
        this.setAvailable(true);
1796
        super.reload();
1797
        this.updateDrawVersion();
1798
        try {
1799
            this.source.getDriver().reload();
1800
            if (this.getLegend() == null) {
1801
                if (this.getRecordset().getDriver() instanceof WithDefaultLegend) {
1802
                    WithDefaultLegend aux = (WithDefaultLegend) this.getRecordset().getDriver();
1803
                    this.setLegend((IVectorLegend) aux.getDefaultLegend());
1804
                    this.setLabelingStrategy(aux.getDefaultLabelingStrategy());
1805
                } else {
1806
                    this.setLegend(LegendFactory.createSingleSymbolLegend(
1807
                            this.getShapeType()));
1808
                }
1809
            }
1810

    
1811
        } catch (LegendLayerException e) {
1812
            this.setAvailable(false);
1813
            throw new ReloadLayerException(getName(),e);
1814
        } catch (ReadDriverException e) {
1815
            this.setAvailable(false);
1816
            throw new ReloadLayerException(getName(),e);
1817
        }
1818

    
1819
    }
1820

    
1821
    protected void setLoadSelection(XMLEntity xml) {
1822
        this.loadSelection = xml;
1823
    }
1824

    
1825
    protected void setLoadLegend(IVectorLegend legend) {
1826
        this.loadLegend = legend;
1827
    }
1828

    
1829
    protected void putLoadSelection() throws XMLException {
1830
        if (this.loadSelection == null) return;
1831
        try {
1832
            this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1833
        } catch (ReadDriverException e) {
1834
            throw new XMLException(e);
1835
        }
1836
        this.loadSelection = null;
1837

    
1838
    }
1839
    protected void putLoadLegend() throws LegendLayerException {
1840
        if (this.loadLegend == null) return;
1841
        this.setLegend(this.loadLegend);
1842
        this.loadLegend = null;
1843
    }
1844

    
1845
    protected void cleanLoadOptions() {
1846
        this.loadLegend = null;
1847
        this.loadSelection = null;
1848
    }
1849

    
1850
    public boolean isWritable() {
1851
        VectorialDriver drv = getSource().getDriver();
1852
        if (!drv.isWritable())
1853
            return false;
1854
        if (drv instanceof IWriteable)
1855
        {
1856
            IWriter writer = ((IWriteable)drv).getWriter();
1857
            if (writer != null)
1858
            {
1859
                if (writer instanceof ISpatialWriter)
1860
                    return true;
1861
            }
1862
        }
1863
        return false;
1864

    
1865
    }
1866

    
1867
    public FLayer cloneLayer() throws Exception {
1868
        FLyrVect clonedLayer = new FLyrVect();
1869
        clonedLayer.setSource(getSource());
1870
        if (isJoined()) {
1871
                        clonedLayer.setIsJoined(true);
1872
                        clonedLayer.setRecordset(getRecordset());
1873
                }
1874
        clonedLayer.setVisible(isVisible());
1875
        clonedLayer.setISpatialIndex(getISpatialIndex());
1876
        clonedLayer.setName(getName());
1877
        clonedLayer.setCoordTrans(getCoordTrans());
1878

    
1879
        clonedLayer.setLegend((IVectorLegend)getLegend().cloneLegend());
1880

    
1881
        clonedLayer.setIsLabeled(isLabeled());
1882
        ILabelingStrategy labelingStrategy=getLabelingStrategy();
1883
        if (labelingStrategy!=null)
1884
                clonedLayer.setLabelingStrategy(labelingStrategy);
1885

    
1886
        return clonedLayer;
1887
    }
1888

    
1889
    public SelectionSupport getSelectionSupport() {
1890
                try {
1891
                        return getRecordset().getSelectionSupport();
1892
                } catch (ReadDriverException e) {
1893
                        e.printStackTrace();
1894
                }
1895
                return null;
1896
        }
1897

    
1898
    protected boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, double dpi, CartographicSupport csSym, IGeometry geom, int[] xyCoords) {
1899
            return isOnePoint(graphicsTransform, viewPort, geom, xyCoords) && csSym.getCartographicSize(viewPort, dpi, (FShape)geom.getInternalShape()) <= 1;
1900
    }
1901

    
1902
    protected boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, IGeometry geom, int[] xyCoords) {
1903
            boolean onePoint = false;
1904
            int type=geom.getGeometryType() % FShape.Z;
1905
            if (type!=FShape.POINT && type!=FShape.MULTIPOINT && type!=FShape.NULL) {
1906

    
1907
                        Rectangle2D geomBounds = geom.getBounds2D();
1908

    
1909
                //        ICoordTrans ct = getCoordTrans();
1910

    
1911
                        // Se supone que la geometria ya esta
1912
                        // repoyectada y no hay que hacer
1913
                        // ninguna transformacion
1914
//                        if (ct!=null) {
1915
////                                geomBounds = ct.getInverted().convert(geomBounds);
1916
//                                geomBounds = ct.convert(geomBounds);
1917
//                        }
1918

    
1919
                        double dist1Pixel = viewPort.getDist1pixel();
1920

    
1921
                        onePoint = (geomBounds.getWidth()  <= dist1Pixel
1922
                                         && geomBounds.getHeight() <= dist1Pixel);
1923

    
1924
                        if (onePoint) {
1925
                                // avoid out of range exceptions
1926
                                FPoint2D p = new FPoint2D(geomBounds.getMinX(), geomBounds.getMinY());
1927
                                p.transform(viewPort.getAffineTransform());
1928
                                p.transform(graphicsTransform);
1929
                                xyCoords[0] = (int) p.getX();
1930
                                xyCoords[1] = (int) p.getY();
1931

    
1932
                        }
1933

    
1934
                }
1935
            return onePoint;
1936
    }
1937
    /*
1938
     * jaume. Stuff from ILabeled.
1939
     */
1940
    private boolean isLabeled;
1941
    private ILabelingStrategy strategy;
1942

    
1943
    public boolean isLabeled() {
1944
        return isLabeled;
1945
    }
1946

    
1947
    public void setIsLabeled(boolean isLabeled) {
1948
        this.isLabeled = isLabeled;
1949
    }
1950

    
1951
    public ILabelingStrategy getLabelingStrategy() {
1952
        return strategy;
1953
    }
1954

    
1955
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1956
        this.strategy = strategy;
1957
        try {
1958
                        strategy.setLayer(this);
1959
                } catch (ReadDriverException e) {
1960
                        // TODO Auto-generated catch block
1961
                        e.printStackTrace();
1962
                }
1963
    }
1964

    
1965
    public void drawLabels(BufferedImage image, Graphics2D g, ViewPort viewPort,
1966
                    Cancellable cancel, double scale, double dpi) throws ReadDriverException {
1967
        if (strategy!=null && isWithinScale(scale)) {
1968
                strategy.draw(image, g, viewPort, cancel, dpi);
1969
        }
1970
    }
1971
    public void printLabels(Graphics2D g, ViewPort viewPort,
1972
                    Cancellable cancel, double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
1973
        if (strategy!=null) {
1974
                strategy.print(g, viewPort, cancel, properties);
1975
        }
1976
    }
1977

    
1978

    
1979
    //M?todos para el uso de HyperLinks en capas FLyerVect
1980

    
1981
    /**
1982
     * Return true, because a Vectorial Layer supports HyperLink
1983
     */
1984
    public boolean allowLinks()
1985
    {
1986
            return true;
1987
    }
1988

    
1989
    /**
1990
         * Returns an instance of AbstractLinkProperties that contains the information
1991
         * of the HyperLink
1992
         * @return Abstra
1993
         */
1994
    public AbstractLinkProperties getLinkProperties()
1995
    {
1996
            return linkProperties;
1997
    }
1998

    
1999
    /**
2000
         * Provides an array with URIs. Returns one URI by geometry that includes the point
2001
         * in its own geometry limits with a allowed tolerance.
2002
         * @param layer, the layer
2003
         * @param point, the point to check that is contained or not in the geometries in the layer
2004
         * @param tolerance, the tolerance allowed. Allowed margin of error to detect if the  point
2005
         *                 is contained in some geometries of the layer
2006
         * @return
2007
         */
2008
    public URI[] getLink(Point2D point, double tolerance)
2009
    {
2010
            //return linkProperties.getLink(this)
2011
            return linkProperties.getLink(this,point,tolerance);
2012
    }
2013
//    /**
2014
//     * @deprecated Don?t use Strategy, you should be use iterators.
2015
//     */
2016
//        public boolean isUseStrategy() {
2017
//                return useStrategy;
2018
//        }
2019
//        /**
2020
//     * @deprecated Don?t use Strategy, you should be use iterators.
2021
//     */
2022
//        public void setUseStrategy(boolean useStrategy) {
2023
//                this.useStrategy = useStrategy;
2024
//        }
2025
//
2026
//        @Override
2027
//        public void load() throws LoadLayerException {
2028
//                super.load();
2029
//                useStrategy=forTestOnlyVariableUseIterators_REMOVE_THIS_FIELD;
2030
//        }
2031

    
2032
        public void selectionChanged(SelectionEvent e) {
2033
                this.updateDrawVersion();
2034
        }
2035

    
2036
        public void afterFieldEditEvent(AfterFieldEditEvent e) {
2037
                this.updateDrawVersion();
2038
        }
2039

    
2040
        public void afterRowEditEvent(IRow feat, AfterRowEditEvent e) {
2041
                this.updateDrawVersion();
2042

    
2043
        }
2044

    
2045
        public void beforeFieldEditEvent(BeforeFieldEditEvent e) {
2046

    
2047
        }
2048

    
2049
        public void beforeRowEditEvent(IRow feat, BeforeRowEditEvent e) {
2050

    
2051
        }
2052

    
2053
        public void processEvent(EditionEvent e) {
2054
                if (e.getChangeType()== e.ROW_EDITION){
2055
                        this.updateDrawVersion();
2056
                }
2057

    
2058
        }
2059

    
2060
        public void legendCleared(LegendClearEvent event) {
2061
                this.updateDrawVersion();
2062
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
2063
                legend, legend);
2064
        this.callLegendChanged(e);
2065
        }
2066

    
2067
        public boolean symbolChanged(SymbolLegendEvent e) {
2068
                this.updateDrawVersion();
2069
        LegendChangedEvent event = LegendChangedEvent.createLegendChangedEvent(
2070
                legend, legend);
2071
        this.callLegendChanged(event);
2072
        return true;
2073
        }
2074
        public String getTypeStringVectorLayer() throws ReadDriverException {
2075
                String typeString="";
2076
                int typeShape=((FLyrVect)this).getShapeType();
2077
                if (FShape.MULTI==typeShape){
2078
                        ReadableVectorial rv=((FLyrVect)this).getSource();
2079
                        int i=0;
2080
                        boolean isCorrect=false;
2081
                        while(rv.getShapeCount()>i && !isCorrect){
2082
                                IGeometry geom=rv.getShape(i);
2083
                                if (geom==null){
2084
                                        i++;
2085
                                        continue;
2086
                                }
2087
                                isCorrect=true;
2088
                                if ((geom.getGeometryType() & FShape.Z) == FShape.Z){
2089
                                        typeString="Geometries3D";
2090
                                }else{
2091
                                        typeString="Geometries2D";
2092
                                 }
2093
                         }
2094
                }else{
2095
                        ReadableVectorial rv=((FLyrVect)this).getSource();
2096
                        int i=0;
2097
                        boolean isCorrect=false;
2098
                        while(rv.getShapeCount()>i && !isCorrect){
2099
                                IGeometry geom=rv.getShape(i);
2100
                                if (geom==null){
2101
                                        i++;
2102
                                        continue;
2103
                                }
2104
                                isCorrect=true;
2105
                                int type=geom.getGeometryType();
2106
                                if (FShape.POINT == type){
2107
                                        typeString="Point2D";
2108
                                } else if (FShape.LINE == type){
2109
                                        typeString="Line2D";
2110
                                } else if (FShape.POLYGON == type){
2111
                                        typeString="Polygon2D";
2112
                                } else if (FShape.MULTIPOINT == type){
2113
                                        typeString="MultiPint2D";
2114
                                } else if ((FShape.POINT | FShape.Z)  == type ){
2115
                                        typeString="Point3D";
2116
                                } else if ((FShape.LINE | FShape.Z)  == type ){
2117
                                        typeString="Line3D";
2118
                                } else if ((FShape.POLYGON | FShape.Z)  == type ){
2119
                                        typeString="Polygon3D";
2120
                                } else if ((FShape.MULTIPOINT | FShape.Z)  == type ){
2121
                                        typeString="MultiPoint3D";
2122
                                } else if ((FShape.POINT | FShape.M)  == type ){
2123
                                        typeString="PointM";
2124
                                } else if ((FShape.LINE | FShape.M)  == type ){
2125
                                        typeString="LineM";
2126
                                } else if ((FShape.POLYGON | FShape.M)  == type ){
2127
                                        typeString="PolygonM";
2128
                                } else if ((FShape.MULTIPOINT | FShape.M)  == type ){
2129
                                        typeString="MultiPointM";
2130
                                } else if ((FShape.MULTI | FShape.M)  == type ){
2131
                                        typeString="M";
2132
                                }
2133

    
2134
                        }
2135
                        return typeString;
2136
                }
2137
                return "";
2138
        }
2139
        public int getTypeIntVectorLayer() throws ReadDriverException {
2140
                int typeInt=0;
2141
                int typeShape=((FLyrVect)this).getShapeType();
2142
                if (FShape.MULTI==typeShape){
2143
                        ReadableVectorial rv=((FLyrVect)this).getSource();
2144
                        int i=0;
2145
                        boolean isCorrect=false;
2146
                        while(rv.getShapeCount()>i && !isCorrect){
2147
                                IGeometry geom=rv.getShape(i);
2148
                                if (geom==null){
2149
                                        i++;
2150
                                        continue;
2151
                                }
2152
                                isCorrect=true;
2153
                                if ((geom.getGeometryType() & FShape.Z) == FShape.Z){
2154
                                        typeInt=FShape.MULTI | FShape.Z;
2155
                                }else{
2156
                                        typeInt=FShape.MULTI;
2157
                                }
2158
                        }
2159
                }else{
2160
                        ReadableVectorial rv=((FLyrVect)this).getSource();
2161
                        int i=0;
2162
                        boolean isCorrect=false;
2163
                        while(rv.getShapeCount()>i && !isCorrect){
2164
                                IGeometry geom=rv.getShape(i);
2165
                                if (geom==null){
2166
                                        i++;
2167
                                        continue;
2168
                                }
2169
                                isCorrect=true;
2170
                                int type=geom.getGeometryType();
2171
                                typeInt=type;
2172
                        }
2173
                        return typeInt;
2174
                }
2175
                return typeInt;
2176
        }
2177
 }