Statistics
| Revision:

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

History | View | Annotate | Download (75.8 KB)

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

    
43
import java.awt.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
                   if (getStrategy() != null) {
637
                           getStrategy().draw(image, g, viewPort, cancel);
638
                   }
639
                   else {
640
                           _draw(image, g, viewPort, cancel, scale);
641
                   }
642
//            } else {
643
////                    moved up to FLayers
644
////                    if (isWithinScale(scale)) {
645
//
646
//
647
//                            // Las que solo tienen etiquetado sin pintar el shape,
648
//                            // no pasamos por ellas
649
//                            boolean bDrawShapes = true;
650
//                            if (legend instanceof SingleSymbolLegend) {
651
//                                    if (legend.getDefaultSymbol().isShapeVisible() == false)
652
//                                            bDrawShapes = false;
653
//                            }
654
//                            if (bDrawShapes) {
655
//                                    Strategy strategy = StrategyManager.getStrategy(this);
656
//                                    try {
657
//                                            prepareDrawing(image, g, viewPort);
658
//                                            strategy.draw(image, g, viewPort, cancel);
659
//                                    } catch (ReadDriverException e) {
660
//                                            this.setVisible(false);
661
//                                            this.setActive(false);
662
//                                            throw e;
663
//                                    }
664
//                            }
665
//                            if (getVirtualLayers() != null) {
666
//                                    getVirtualLayers().draw(image, g, viewPort, cancel, scale);
667
//                            }
668
////                    }
669
//            }
670
    }
671

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

    
681
    }
682

    
683
    public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
684
                    double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
685
            // TEST METHOD
686

    
687

    
688
                    /* SVN */
689

    
690
    /*        boolean bDrawShapes = true;
691
            if (legend instanceof SingleSymbolLegend) {
692
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
693
            }
694

695

696
            if (bDrawShapes) {
697
                    double dpi = 72;
698

699
                    PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
700
                    if (resolution.equals(PrintQuality.NORMAL)){
701
                            dpi = 300;
702
                    } else if (resolution.equals(PrintQuality.HIGH)){
703
                            dpi = 600;
704
                    } else if (resolution.equals(PrintQuality.DRAFT)){
705
                            dpi = 72;
706
                    }
707

708

709
                    try {
710
                            prepareDrawing(null, g, viewPort);
711
                            ArrayList<String> fieldList = new ArrayList<String>();
712
                            String[] aux;
713

714
                            // fields from legend
715
                            if (legend instanceof IClassifiedVectorLegend) {
716
                                    aux = ((IClassifiedVectorLegend) legend).
717
                                                                            getClassifyingFieldNames();
718
                                    for (int i = 0; i < aux.length; i++) {
719
                                            fieldList.add(aux[i]);
720
                                    }
721
                            }
722

723
                            // fields from labeling
724
                            if (isLabeled()) {
725
                                    aux = getLabelingStrategy().getUsedFields();
726
                                    for (int i = 0; i < aux.length; i++) {
727
                                            fieldList.add(aux[i]);
728
                                    }
729
                            }
730

731
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
732

733
                            // if layer has map levels it will use a ZSort
734
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
735

736

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

746
                                    // Iteration over each feature
747
                                    while ( !cancel.isCanceled() && it.hasNext()) {
748
                                            IFeature feat = it.next();
749
                                            IGeometry geom = feat.getGeometry();
750

751
                                            // retreive the symbol associated to such feature
752
                                            ISymbol sym = legend.getSymbolByFeature(feat);
753

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

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

781
                                            // Check if this symbol is sized with CartographicSupport
782
                                            CartographicSupport csSym = null;
783
                                            int symbolType = sym.getSymbolType();
784
                                            boolean bDrawCartographicSupport = false;
785

786
                                            if (   symbolType == FShape.POINT
787
                                                            || symbolType == FShape.LINE
788
                                                            || sym instanceof CartographicSupport) {
789

790
                                                    csSym = (CartographicSupport) sym;
791
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
792
                                            }
793

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

796
                                            if (!bDrawCartographicSupport) {
797
                                                    geom.drawInts(g, viewPort, sym, null);
798
                                            } else {
799
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym);
800
                                            }
801

802
                                    }
803
                                    it.closeIterator();
804
                            }
805
                    } catch (ReadDriverException e) {
806
                            this.setVisible(false);
807
                            this.setActive(false);
808
                            throw e;
809
                    }
810
        */
811

    
812

    
813
            // TEST METHOD
814
            boolean bDrawShapes = true;
815
            if (legend instanceof SingleSymbolLegend) {
816
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
817
            }
818

    
819

    
820
            if (bDrawShapes) {
821

    
822
                    try {
823
                            double dpi = 72;
824

    
825
                            PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
826
                            if (resolution.equals(PrintQuality.NORMAL)){
827
                                    dpi = 300;
828
                            } else if (resolution.equals(PrintQuality.HIGH)){
829
                                    dpi = 600;
830
                            } else if (resolution.equals(PrintQuality.DRAFT)){
831
                                    dpi = 72;
832
                            }
833
                            ArrayList<String> fieldList = new ArrayList<String>();
834
                            String[] aux;
835

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

    
853
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
854

    
855
                            // if layer has map levels it will use a ZSort
856
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
857

    
858

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

    
880
                                    // Iteration over each feature
881
                                    while ( !cancel.isCanceled() && it.hasNext()) {
882
                                            IFeature feat = it.next();
883
                                            IGeometry geom = feat.getGeometry();
884

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

    
916
                                            // Check if this symbol is sized with CartographicSupport
917
                                            CartographicSupport csSym = null;
918
                                            int symbolType = sym.getSymbolType();
919

    
920
                                            if (   symbolType == FShape.POINT
921
                                                            || symbolType == FShape.LINE
922
                                                            || sym instanceof CartographicSupport) {
923

    
924
                                                    csSym = (CartographicSupport) sym;
925
                                            }
926

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

    
929
                                            if (csSym == null) {
930
                                                    geom.drawInts(g, viewPort, sym, null);
931
                                            } else {
932
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym, cancel);
933
                                            }
934

    
935
                                    }
936
                                    it.closeIterator();
937
                            }
938
                    } catch (ReadDriverException e) {
939
                            this.setVisible(false);
940
                            this.setActive(false);
941
                            throw e;
942
                    }
943
            }
944
    }
945

    
946

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

    
968
    public void deleteSpatialIndex() {
969
        //must we delete possible spatial indexes files?
970
        spatialIndex = null;
971
    }
972

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

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

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

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

    
1053
    public void createSpatialIndex() {
1054
        createSpatialIndex(null);
1055
    }
1056

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

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

    
1068
    public void process(FeatureVisitor visitor, Rectangle2D rect)
1069
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
1070
        Strategy s = StrategyManager.getStrategy(this);
1071
        s.process(visitor, rect);
1072
    }
1073

    
1074
    public FBitSet queryByRect(Rectangle2D rect) throws ReadDriverException, VisitorException {
1075
        Strategy s = StrategyManager.getStrategy(this);
1076

    
1077
        return s.queryByRect(rect);
1078
    }
1079

    
1080
    public FBitSet queryByPoint(Point2D p, double tolerance)
1081
            throws ReadDriverException, VisitorException {
1082
        Strategy s = StrategyManager.getStrategy(this);
1083
        return s.queryByPoint(p, tolerance);
1084
    }
1085

    
1086
    public FBitSet queryByShape(IGeometry g, int relationship)
1087
            throws ReadDriverException, VisitorException {
1088
        Strategy s = StrategyManager.getStrategy(this);
1089
        return s.queryByShape(g, relationship);
1090
    }
1091

    
1092
    public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancel) throws ReadDriverException, VisitorException {
1093
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(p);
1094
        FBitSet bs = queryByPoint(pReal, tolerance);
1095
        VectorialXMLItem[] item = new VectorialXMLItem[1];
1096
        item[0] = new VectorialXMLItem(bs, this);
1097

    
1098
        return item;
1099
    }
1100

    
1101
    public void setLegend(IVectorLegend r) throws LegendLayerException {
1102
            if (this.legend == r){
1103
                    return;
1104
            }
1105
                if (this.legend != null && this.legend.equals(r)){
1106
                        return;
1107
                }
1108
        IVectorLegend oldLegend = legend;
1109

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

    
1141
                legend = r;
1142
        try {
1143
            legend.setDataSource(getRecordset());
1144
        } catch (FieldNotFoundException e1) {
1145
            throw new LegendLayerException(getName(),e1);
1146
        } catch (ReadDriverException e1) {
1147
            throw new LegendLayerException(getName(),e1);
1148
        } finally{
1149
                this.updateDrawVersion();
1150
        }
1151
        if (oldLegend != null){
1152
                oldLegend.removeLegendListener(this);
1153
        }
1154
        if (legend != null){
1155
                legend.addLegendListener(this);
1156
        }
1157
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
1158
                oldLegend, legend);
1159
        e.setLayer(this);
1160
        callLegendChanged(e);
1161
    }
1162

    
1163
    /**
1164
     * Devuelve la Leyenda de la capa.
1165
     *
1166
     * @return Leyenda.
1167
     */
1168
    public ILegend getLegend() {
1169
        return legend;
1170
    }
1171

    
1172
    /**
1173
     * Devuelve el tipo de shape que contiene la capa.
1174
     *
1175
     * @return tipo de shape.
1176
     *
1177
     * @throws DriverException
1178
     */
1179
    public int getShapeType() throws ReadDriverException {
1180
        if (typeShape == -1) {
1181
            getSource().start();
1182
            typeShape = getSource().getShapeType();
1183
            getSource().stop();
1184
        }
1185

    
1186
        return typeShape;
1187
    }
1188

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

    
1226
            IVectorialDatabaseDriver dbDriver = (IVectorialDatabaseDriver) source
1227
                    .getDriver();
1228

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

    
1247
            VectorialDriver driver = source.getDriver();
1248

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

    
1276
        // properties from ILabelable
1277
        xml.putProperty("isLabeled", isLabeled);
1278
        if (strategy != null) {
1279
            XMLEntity strategyXML = strategy.getXMLEntity();
1280
            strategyXML.putProperty("Strategy", strategy.getClassName());
1281
            xml.addChild(strategy.getXMLEntity());
1282
        }
1283
        xml.addChild(getLinkProperties().getXMLEntity());
1284
        return xml;
1285
    }
1286

    
1287
    /**
1288
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1289
     */
1290
    public void setXMLEntity03(XMLEntity xml) throws XMLException {
1291

    
1292
        super.setXMLEntity(xml);
1293
        legend = LegendFactory.createFromXML03(xml.getChild(0));
1294

    
1295
        try {
1296
            setLegend(legend);
1297
        } catch (LegendLayerException e) {
1298
            throw new XMLException(e);
1299
        }
1300

    
1301
        try {
1302
            getRecordset().getSelectionSupport()
1303
                    .setXMLEntity03(xml.getChild(1));
1304
        } catch (ReadDriverException e) {
1305
            e.printStackTrace();
1306
        }
1307
    }
1308

    
1309
    /*
1310
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1311
     */
1312
    public void setXMLEntity(XMLEntity xml) throws XMLException {
1313
        try {
1314
                    super.setXMLEntity(xml);
1315
                    XMLEntity legendXML = xml.getChild(0);
1316
                    IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1317

    
1318
                    /*
1319
                     * Parche para detectar cuando, por algun problema de persistencia
1320
                     * respecto a versiones anteriores, la leyenda que se ha cargado
1321
                     * no se corresponde con el tipo de shape de la capa.
1322
                     */
1323
                    int legShapeType = leg.getShapeType();
1324
                    if (legShapeType != 0 && legShapeType != this.getShapeType()){
1325
                            leg = LegendFactory.createSingleSymbolLegend(this.getShapeType());
1326
                                logger.warn("Legend shape type and layer shape type does not match.");
1327
                    }
1328
                    /* Fin del parche */
1329

    
1330
                    try {
1331
                            getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1332
                            // JMVIVO: Esto sirve para algo????
1333
                            /*
1334
                             *  Jaume: si, para restaurar el selectable datasource cuando se
1335
                             *  clona la capa, cuando se carga de un proyecto. Si no esta ya
1336
                             *  no se puede ni hacer consultas sql, ni hacer selecciones,
1337
                             *  ni usar la mayor parte de las herramientas.
1338
                             *
1339
                             *  Lo vuelvo a poner.
1340
                             */
1341

    
1342
                            String recordsetName = xml.getStringProperty("recordset-name");
1343

    
1344
//                            SelectableDataSource sds = new SelectableDataSource(LayerFactory
1345
//                                            .getDataSourceFactory().createRandomDataSource(
1346
//                                                            recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
1347

    
1348
                            LayerFactory.getDataSourceFactory().changeDataSourceName(
1349
                                            getSource().getRecordset().getName(), recordsetName);
1350
                            SelectableDataSource sds = new SelectableDataSource(LayerFactory
1351
                                            .getDataSourceFactory().createRandomDataSource(
1352
                                                            recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
1353

    
1354
                    } catch (NoSuchTableException e1) {
1355
                            this.setAvailable(false);
1356
                            throw new XMLException(e1);
1357
                    } catch (ReadDriverException e1) {
1358
                            this.setAvailable(false);
1359
                            throw new XMLException(e1);
1360
                    }
1361
                    // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1362
                    // el final
1363
                    // de la lectura del proyecto
1364
                    if (xml.contains("hasJoin")) {
1365
                            setIsJoined(true);
1366
                            PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1367
                    } else {
1368
                            try {
1369
                                    setLegend(leg);
1370
                            } catch (LegendLayerException e) {
1371
                                    throw new XMLException(e);
1372
                            }
1373
                    }
1374

    
1375
                    //Por compatibilidad con proyectos anteriores a la 1.0
1376
                    boolean containsIsLabeled = xml.contains("isLabeled");
1377
                    if (containsIsLabeled){
1378
                            isLabeled = xml.getBooleanProperty("isLabeled");
1379
                    }
1380
                    // set properties for ILabelable
1381
                    XMLEntity labelingXML = xml.firstChild("labelingStrategy", "labelingStrategy");
1382
                    if (labelingXML!= null) {
1383
                            if(!containsIsLabeled){
1384
                                    isLabeled = true;
1385
                            }
1386
                            try {
1387
                                    ILabelingStrategy labeling = LabelingFactory.createStrategyFromXML(labelingXML, this);
1388
                                    if (isJoined()) {
1389
                                            PostProcessSupport.addToPostProcess(this, "setLabelingStrategy", labeling, 1);
1390
                                    }
1391
                                    else
1392
                                            this.setLabelingStrategy(labeling);
1393

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

    
1495
                }else if(!containsIsLabeled){
1496
                                    isLabeled = false;
1497
                    }
1498

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

    
1522
            } catch (XMLException e) {
1523
                    this.setAvailable(false);
1524
                    this.orgXMLEntity = xml;
1525
            } catch (Exception e) {
1526
                    e.printStackTrace();
1527
                    this.setAvailable(false);
1528
                    this.orgXMLEntity = xml;
1529

    
1530
            }
1531

    
1532

    
1533
    }
1534

    
1535
    public void setXMLEntityNew(XMLEntity xml) throws XMLException {
1536
        try {
1537
            super.setXMLEntity(xml);
1538

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

    
1558
                this.setLoadSelection(xml.getChild(1));
1559
            } catch (ReadDriverException e1) {
1560
                this.setAvailable(false);
1561
                throw new XMLException(e1);
1562
            }
1563
            // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1564
            // el final
1565
            // de la lectura del proyecto
1566
            if (xml.contains("hasJoin")) {
1567
                setIsJoined(true);
1568
                PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1569
            } else {
1570
                this.setLoadLegend(leg);
1571
            }
1572

    
1573
        } catch (XMLException e) {
1574
            this.setAvailable(false);
1575
            this.orgXMLEntity = xml;
1576
        } catch (Exception e) {
1577
            this.setAvailable(false);
1578
            this.orgXMLEntity = xml;
1579
        }
1580

    
1581

    
1582
    }
1583

    
1584

    
1585
    /**
1586
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
1587
     * identifiquen la capa.
1588
     *
1589
     * @return DOCUMENT ME!
1590
     */
1591
    public String toString() {
1592
        /*
1593
         * Se usa internamente para que la parte de datos identifique de forma
1594
         * un?voca las tablas
1595
         */
1596
        String ret = super.toString();
1597

    
1598
        return "layer" + ret.substring(ret.indexOf('@') + 1);
1599
    }
1600

    
1601
    public boolean isJoined() {
1602
        return bHasJoin;
1603
    }
1604

    
1605
    /**
1606
     * Returns if a layer is spatially indexed
1607
     *
1608
     * @return if this layer has the ability to proces spatial queries without
1609
     *         secuential scans.
1610
     */
1611
    public boolean isSpatiallyIndexed() {
1612
        ReadableVectorial source = getSource();
1613
        if (source instanceof ISpatialDB)
1614
            return true;
1615

    
1616
//FIXME azabala
1617
/*
1618
 * Esto es muy dudoso, y puede cambiar.
1619
 * Estoy diciendo que las que no son fichero o no son
1620
 * BoundedShapes estan indexadas. Esto es mentira, pero
1621
 * as? quien pregunte no querr? generar el indice.
1622
 * Esta por ver si interesa generar el indice para capas
1623
 * HSQLDB, WFS, etc.
1624
 */
1625
        if(!(source instanceof VectorialFileAdapter)){
1626
            return true;
1627
        }
1628
        if (!(source.getDriver() instanceof BoundedShapes)) {
1629
            return true;
1630
        }
1631

    
1632
        if (getISpatialIndex() != null)
1633
            return true;
1634
        return false;
1635
    }
1636

    
1637
    public void setIsJoined(boolean hasJoin) {
1638
        bHasJoin = hasJoin;
1639
    }
1640

    
1641
    /**
1642
     * @return Returns the spatialIndex.
1643
     */
1644
    public ISpatialIndex getISpatialIndex() {
1645
        return spatialIndex;
1646
    }
1647
    /**
1648
     * Sets the spatial index. This could be useful if, for some
1649
     * reasons, you want to work with a distinct spatial index
1650
     * (for example, a spatial index which could makes nearest
1651
     * neighbour querys)
1652
     * @param spatialIndex
1653
     */
1654
    public void setISpatialIndex(ISpatialIndex spatialIndex){
1655
        this.spatialIndex = spatialIndex;
1656
    }
1657

    
1658
    public SelectableDataSource getRecordset() throws ReadDriverException {
1659
        if (!this.isAvailable()) return null;
1660
        if (sds == null) {
1661

    
1662
                SelectableDataSource ds = source.getRecordset();
1663

    
1664
                if (ds == null) {
1665
                    return null;
1666
                }
1667

    
1668
                sds = ds;
1669
                getSelectionSupport().addSelectionListener(this);
1670

    
1671
        }
1672
        return sds;
1673
    }
1674

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

    
1700

    
1701
                // /vea.setSpatialIndex(getSpatialIndex());
1702
                // /vea.setFullExtent(getFullExtent());
1703
                vea.setCoordTrans(getCoordTrans());
1704
                vea.startEdition(EditionEvent.GRAPHIC);
1705
                setSource(vea);
1706
                getRecordset().setSelectionSupport(
1707
                        vea.getOriginalAdapter().getRecordset()
1708
                                .getSelectionSupport());
1709

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

    
1747
        setSpatialCacheEnabled(b);
1748
        callEditionChanged(LayerEvent
1749
                .createEditionChangedEvent(this, "edition"));
1750

    
1751
    }
1752

    
1753
    /**
1754
     * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
1755
     * forma, podr?s poner leyendas basadas en el nuevo recordset
1756
     *
1757
     * @param newSds
1758
     */
1759
    public void setRecordset(SelectableDataSource newSds) {
1760
            // TODO: Deberiamos hacer comprobaciones del cambio
1761
        sds = newSds;
1762
                getSelectionSupport().addSelectionListener(this);
1763
                this.updateDrawVersion();
1764
    }
1765

    
1766
    public void clearSpatialCache()
1767
    {
1768
        spatialCache.clearAll();
1769
    }
1770

    
1771
    public boolean isSpatialCacheEnabled() {
1772
        return spatialCacheEnabled;
1773
    }
1774

    
1775
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1776
        this.spatialCacheEnabled = spatialCacheEnabled;
1777
    }
1778

    
1779
    public SpatialCache getSpatialCache() {
1780
        return spatialCache;
1781
    }
1782

    
1783
    /**
1784
     * Siempre es un numero mayor de 1000
1785
     * @param maxFeatures
1786
     */
1787
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
1788
        if (maxFeatures > spatialCache.maxFeatures)
1789
            spatialCache.setMaxFeatures(maxFeatures);
1790

    
1791
    }
1792

    
1793
    /**
1794
     * This method returns a boolean that is used by the FPopMenu
1795
     * to make visible the properties menu or not. It is visible by
1796
     * default, and if a later don't have to show this menu only
1797
     * has to override this method.
1798
     * @return
1799
     * If the properties menu is visible (or not)
1800
     */
1801
    public boolean isPropertiesMenuVisible(){
1802
        return true;
1803
    }
1804

    
1805
    public void reload() throws ReloadLayerException {
1806
            if(this.isEditing()){
1807
            throw new ReloadLayerException(getName());
1808
            }
1809
        this.setAvailable(true);
1810
        super.reload();
1811
        this.updateDrawVersion();
1812
        try {
1813
            this.source.getDriver().reload();
1814
            if (this.getLegend() == null) {
1815
                if (this.getRecordset().getDriver() instanceof WithDefaultLegend) {
1816
                    WithDefaultLegend aux = (WithDefaultLegend) this.getRecordset().getDriver();
1817
                    this.setLegend((IVectorLegend) aux.getDefaultLegend());
1818
                    this.setLabelingStrategy(aux.getDefaultLabelingStrategy());
1819
                } else {
1820
                    this.setLegend(LegendFactory.createSingleSymbolLegend(
1821
                            this.getShapeType()));
1822
                }
1823
            }
1824

    
1825
        } catch (LegendLayerException e) {
1826
            this.setAvailable(false);
1827
            throw new ReloadLayerException(getName(),e);
1828
        } catch (ReadDriverException e) {
1829
            this.setAvailable(false);
1830
            throw new ReloadLayerException(getName(),e);
1831
        }
1832

    
1833
    }
1834

    
1835
    protected void setLoadSelection(XMLEntity xml) {
1836
        this.loadSelection = xml;
1837
    }
1838

    
1839
    protected void setLoadLegend(IVectorLegend legend) {
1840
        this.loadLegend = legend;
1841
    }
1842

    
1843
    protected void putLoadSelection() throws XMLException {
1844
        if (this.loadSelection == null) return;
1845
        try {
1846
            this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1847
        } catch (ReadDriverException e) {
1848
            throw new XMLException(e);
1849
        }
1850
        this.loadSelection = null;
1851

    
1852
    }
1853
    protected void putLoadLegend() throws LegendLayerException {
1854
        if (this.loadLegend == null) return;
1855
        this.setLegend(this.loadLegend);
1856
        this.loadLegend = null;
1857
    }
1858

    
1859
    protected void cleanLoadOptions() {
1860
        this.loadLegend = null;
1861
        this.loadSelection = null;
1862
    }
1863

    
1864
    public boolean isWritable() {
1865
        VectorialDriver drv = getSource().getDriver();
1866
        if (!drv.isWritable())
1867
            return false;
1868
        if (drv instanceof IWriteable)
1869
        {
1870
            IWriter writer = ((IWriteable)drv).getWriter();
1871
            if (writer != null)
1872
            {
1873
                if (writer instanceof ISpatialWriter)
1874
                    return true;
1875
            }
1876
        }
1877
        return false;
1878

    
1879
    }
1880

    
1881
    public FLayer cloneLayer() throws Exception {
1882
        FLyrVect clonedLayer = new FLyrVect();
1883
        clonedLayer.setSource(getSource());
1884
        if (isJoined()) {
1885
                        clonedLayer.setIsJoined(true);
1886
                        clonedLayer.setRecordset(getRecordset());
1887
                }
1888
        clonedLayer.setVisible(isVisible());
1889
        clonedLayer.setISpatialIndex(getISpatialIndex());
1890
        clonedLayer.setName(getName());
1891
        clonedLayer.setCoordTrans(getCoordTrans());
1892

    
1893
        clonedLayer.setLegend((IVectorLegend)getLegend().cloneLegend());
1894

    
1895
        clonedLayer.setIsLabeled(isLabeled());
1896
        ILabelingStrategy labelingStrategy=getLabelingStrategy();
1897
        if (labelingStrategy!=null)
1898
                clonedLayer.setLabelingStrategy(labelingStrategy);
1899

    
1900
        return clonedLayer;
1901
    }
1902

    
1903
    public SelectionSupport getSelectionSupport() {
1904
                try {
1905
                        return getRecordset().getSelectionSupport();
1906
                } catch (ReadDriverException e) {
1907
                        e.printStackTrace();
1908
                }
1909
                return null;
1910
        }
1911

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

    
1916
    protected boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, IGeometry geom, int[] xyCoords) {
1917
            boolean onePoint = false;
1918
            int type=geom.getGeometryType() % FShape.Z;
1919
            if (type!=FShape.POINT && type!=FShape.MULTIPOINT && type!=FShape.NULL) {
1920

    
1921
                        Rectangle2D geomBounds = geom.getBounds2D();
1922

    
1923
                //        ICoordTrans ct = getCoordTrans();
1924

    
1925
                        // Se supone que la geometria ya esta
1926
                        // repoyectada y no hay que hacer
1927
                        // ninguna transformacion
1928
//                        if (ct!=null) {
1929
////                                geomBounds = ct.getInverted().convert(geomBounds);
1930
//                                geomBounds = ct.convert(geomBounds);
1931
//                        }
1932

    
1933
                        double dist1Pixel = viewPort.getDist1pixel();
1934

    
1935
                        onePoint = (geomBounds.getWidth()  <= dist1Pixel
1936
                                         && geomBounds.getHeight() <= dist1Pixel);
1937

    
1938
                        if (onePoint) {
1939
                                // avoid out of range exceptions
1940
                                FPoint2D p = new FPoint2D(geomBounds.getMinX(), geomBounds.getMinY());
1941
                                p.transform(viewPort.getAffineTransform());
1942
                                p.transform(graphicsTransform);
1943
                                xyCoords[0] = (int) p.getX();
1944
                                xyCoords[1] = (int) p.getY();
1945

    
1946
                        }
1947

    
1948
                }
1949
            return onePoint;
1950
    }
1951
    /*
1952
     * jaume. Stuff from ILabeled.
1953
     */
1954
    private boolean isLabeled;
1955
    private ILabelingStrategy strategy;
1956

    
1957
    public boolean isLabeled() {
1958
        return isLabeled;
1959
    }
1960

    
1961
    public void setIsLabeled(boolean isLabeled) {
1962
        this.isLabeled = isLabeled;
1963
    }
1964

    
1965
    public ILabelingStrategy getLabelingStrategy() {
1966
        return strategy;
1967
    }
1968

    
1969
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1970
        this.strategy = strategy;
1971
        try {
1972
                        strategy.setLayer(this);
1973
                } catch (ReadDriverException e) {
1974
                        // TODO Auto-generated catch block
1975
                        e.printStackTrace();
1976
                }
1977
    }
1978

    
1979
    public void drawLabels(BufferedImage image, Graphics2D g, ViewPort viewPort,
1980
                    Cancellable cancel, double scale, double dpi) throws ReadDriverException {
1981
        if (strategy!=null && isWithinScale(scale)) {
1982
                strategy.draw(image, g, viewPort, cancel, dpi);
1983
        }
1984
    }
1985
    public void printLabels(Graphics2D g, ViewPort viewPort,
1986
                    Cancellable cancel, double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
1987
        if (strategy!=null) {
1988
                strategy.print(g, viewPort, cancel, properties);
1989
        }
1990
    }
1991

    
1992

    
1993
    //M?todos para el uso de HyperLinks en capas FLyerVect
1994

    
1995
    /**
1996
     * Return true, because a Vectorial Layer supports HyperLink
1997
     */
1998
    public boolean allowLinks()
1999
    {
2000
            return true;
2001
    }
2002

    
2003
    /**
2004
         * Returns an instance of AbstractLinkProperties that contains the information
2005
         * of the HyperLink
2006
         * @return Abstra
2007
         */
2008
    public AbstractLinkProperties getLinkProperties()
2009
    {
2010
            return linkProperties;
2011
    }
2012

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

    
2046
        public void selectionChanged(SelectionEvent e) {
2047
                this.updateDrawVersion();
2048
        }
2049

    
2050
        public void afterFieldEditEvent(AfterFieldEditEvent e) {
2051
                this.updateDrawVersion();
2052
        }
2053

    
2054
        public void afterRowEditEvent(IRow feat, AfterRowEditEvent e) {
2055
                this.updateDrawVersion();
2056

    
2057
        }
2058

    
2059
        public void beforeFieldEditEvent(BeforeFieldEditEvent e) {
2060

    
2061
        }
2062

    
2063
        public void beforeRowEditEvent(IRow feat, BeforeRowEditEvent e) {
2064

    
2065
        }
2066

    
2067
        public void processEvent(EditionEvent e) {
2068
                if (e.getChangeType()== e.ROW_EDITION){
2069
                        this.updateDrawVersion();
2070
                }
2071

    
2072
        }
2073

    
2074
        public void legendCleared(LegendClearEvent event) {
2075
                this.updateDrawVersion();
2076
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
2077
                legend, legend);
2078
        this.callLegendChanged(e);
2079
        }
2080

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

    
2148
                        }
2149
                        return typeString;
2150
                }
2151
                return "";
2152
        }
2153
        public int getTypeIntVectorLayer() throws ReadDriverException {
2154
                int typeInt=0;
2155
                int typeShape=((FLyrVect)this).getShapeType();
2156
                if (FShape.MULTI==typeShape){
2157
                        ReadableVectorial rv=((FLyrVect)this).getSource();
2158
                        int i=0;
2159
                        boolean isCorrect=false;
2160
                        while(rv.getShapeCount()>i && !isCorrect){
2161
                                IGeometry geom=rv.getShape(i);
2162
                                if (geom==null){
2163
                                        i++;
2164
                                        continue;
2165
                                }
2166
                                isCorrect=true;
2167
                                if ((geom.getGeometryType() & FShape.Z) == FShape.Z){
2168
                                        typeInt=FShape.MULTI | FShape.Z;
2169
                                }else{
2170
                                        typeInt=FShape.MULTI;
2171
                                }
2172
                        }
2173
                }else{
2174
                        ReadableVectorial rv=((FLyrVect)this).getSource();
2175
                        int i=0;
2176
                        boolean isCorrect=false;
2177
                        while(rv.getShapeCount()>i && !isCorrect){
2178
                                IGeometry geom=rv.getShape(i);
2179
                                if (geom==null){
2180
                                        i++;
2181
                                        continue;
2182
                                }
2183
                                isCorrect=true;
2184
                                int type=geom.getGeometryType();
2185
                                typeInt=type;
2186
                        }
2187
                        return typeInt;
2188
                }
2189
                return typeInt;
2190
        }
2191
 }