Statistics
| Revision:

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

History | View | Annotate | Download (75.5 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
import org.gvsig.tools.file.PathGenerator;
60

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

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

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

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

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

    
179
    //Lo a?ado. Caracter?sticas de HyperEnlace (LINK)
180
    private FLyrVectLinkProperties linkProperties=new FLyrVectLinkProperties();
181
    //private ArrayList linkProperties=null;
182
    private boolean waitTodraw=false;
183
    private static PathGenerator pathGenerator=PathGenerator.getInstance();
184
    
185
    public boolean isWaitTodraw() {
186
                return waitTodraw;
187
        }
188

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

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

    
212

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

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

    
254
    }
255

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

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

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

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

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

    
337
            return rAux;
338
    }
339

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

    
359

    
360

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

    
369
                    try {
370
                            ArrayList<String> fieldList = new ArrayList<String>();
371

    
372
                            // fields from legend
373
                            String[] aux = null;
374

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

    
407
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
408

    
409
                            boolean bSymbolLevelError = false;
410

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

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

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

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

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

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

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

    
461
                                    if (sym == null) continue;
462

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

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

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

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

    
493
                                    int x = -1;
494
                                    int y = -1;
495
                                    int[] xyCoords = new int[2];
496

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

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

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

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

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

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

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

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

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

    
615
                            if (bSymbolLevelError) {
616
                                    ((IVectorLegend) getLegend()).setZSort(null);
617
                            }
618

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

    
625

    
626
            }
627
    }
628

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

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

    
676
    }
677

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

    
682

    
683
                    /* SVN */
684

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

690

691
            if (bDrawShapes) {
692
                    double dpi = 72;
693

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

703

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

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

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

726
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
727

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

731

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

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

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

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

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

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

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

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

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

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

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

    
807

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

    
814

    
815
            if (bDrawShapes) {
816

    
817
                    try {
818
                            double dpi = 72;
819

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

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

    
848
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
849

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

    
853

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

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

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

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

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

    
919
                                                    csSym = (CartographicSupport) sym;
920
                                            }
921

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

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

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

    
941

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

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

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

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

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

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

    
1046
    public void createSpatialIndex() {
1047
        createSpatialIndex(null);
1048
    }
1049

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

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

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

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

    
1070
        return s.queryByRect(rect);
1071
    }
1072

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

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

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

    
1091
        return item;
1092
    }
1093

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

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

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

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

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

    
1179
        return typeShape;
1180
    }
1181

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

    
1217
            IVectorialDatabaseDriver dbDriver = (IVectorialDatabaseDriver) source
1218
                    .getDriver();
1219

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

    
1238
            VectorialDriver driver = source.getDriver();
1239

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

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

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

    
1283
        super.setXMLEntity(xml);
1284
        legend = LegendFactory.createFromXML03(xml.getChild(0));
1285

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

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

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

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

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

    
1333
                            String recordsetName = xml.getStringProperty("recordset-name");
1334

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

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

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

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

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

    
1486
                }else if(!containsIsLabeled){
1487
                                    isLabeled = false;
1488
                    }
1489

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

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

    
1521
            }
1522

    
1523

    
1524
    }
1525

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

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

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

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

    
1572

    
1573
    }
1574

    
1575

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

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

    
1592
    public boolean isJoined() {
1593
        return bHasJoin;
1594
    }
1595

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

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

    
1623
        if (getISpatialIndex() != null)
1624
            return true;
1625
        return false;
1626
    }
1627

    
1628
    public void setIsJoined(boolean hasJoin) {
1629
        bHasJoin = hasJoin;
1630
    }
1631

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

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

    
1653
                SelectableDataSource ds = source.getRecordset();
1654

    
1655
                if (ds == null) {
1656
                    return null;
1657
                }
1658

    
1659
                sds = ds;
1660
                getSelectionSupport().addSelectionListener(this);
1661

    
1662
        }
1663
        return sds;
1664
    }
1665

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

    
1691

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

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

    
1738
        setSpatialCacheEnabled(b);
1739
        callEditionChanged(LayerEvent
1740
                .createEditionChangedEvent(this, "edition"));
1741

    
1742
    }
1743

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

    
1757
    public void clearSpatialCache()
1758
    {
1759
        spatialCache.clearAll();
1760
    }
1761

    
1762
    public boolean isSpatialCacheEnabled() {
1763
        return spatialCacheEnabled;
1764
    }
1765

    
1766
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1767
        this.spatialCacheEnabled = spatialCacheEnabled;
1768
    }
1769

    
1770
    public SpatialCache getSpatialCache() {
1771
        return spatialCache;
1772
    }
1773

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

    
1782
    }
1783

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

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

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

    
1821
    }
1822

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

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

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

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

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

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

    
1867
    }
1868

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

    
1881
        clonedLayer.setLegend((IVectorLegend)getLegend().cloneLegend());
1882

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

    
1888
        return clonedLayer;
1889
    }
1890

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

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

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

    
1909
                        Rectangle2D geomBounds = geom.getBounds2D();
1910

    
1911
                //        ICoordTrans ct = getCoordTrans();
1912

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

    
1921
                        double dist1Pixel = viewPort.getDist1pixel();
1922

    
1923
                        onePoint = (geomBounds.getWidth()  <= dist1Pixel
1924
                                         && geomBounds.getHeight() <= dist1Pixel);
1925

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

    
1934
                        }
1935

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

    
1945
    public boolean isLabeled() {
1946
        return isLabeled;
1947
    }
1948

    
1949
    public void setIsLabeled(boolean isLabeled) {
1950
        this.isLabeled = isLabeled;
1951
    }
1952

    
1953
    public ILabelingStrategy getLabelingStrategy() {
1954
        return strategy;
1955
    }
1956

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

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

    
1980

    
1981
    //M?todos para el uso de HyperLinks en capas FLyerVect
1982

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

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

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

    
2034
        public void selectionChanged(SelectionEvent e) {
2035
                this.updateDrawVersion();
2036
        }
2037

    
2038
        public void afterFieldEditEvent(AfterFieldEditEvent e) {
2039
                this.updateDrawVersion();
2040
        }
2041

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

    
2045
        }
2046

    
2047
        public void beforeFieldEditEvent(BeforeFieldEditEvent e) {
2048

    
2049
        }
2050

    
2051
        public void beforeRowEditEvent(IRow feat, BeforeRowEditEvent e) {
2052

    
2053
        }
2054

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

    
2060
        }
2061

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

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

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