Statistics
| Revision:

root / org.gvsig.legend.urbanhorizontalsignage / trunk / org.gvsig.legend.urbanhorizontalsignage / org.gvsig.legend.urbanhorizontalsignage.lib / org.gvsig.legend.urbanhorizontalsignage.lib.impl / src / main / java / org / gvsig / legend / urbanverticalsignage / lib / impl / DefaultPictureMarkerSymbolTableLegend.java @ 7109

History | View | Annotate | Download (17.9 KB)

1
package org.gvsig.legend.urbanverticalsignage.lib.impl;
2

    
3
import java.awt.Color;
4
import java.awt.geom.Point2D;
5
import java.awt.image.BufferedImage;
6
import java.net.URL;
7
import java.util.ArrayList;
8
import java.util.List;
9
import javax.annotation.processing.SupportedSourceVersion;
10
import javax.lang.model.SourceVersion;
11
import org.apache.commons.collections4.map.LRUMap;
12
import org.apache.commons.lang3.StringUtils;
13
import org.gvsig.expressionevaluator.ExpressionBuilder;
14
import org.gvsig.expressionevaluator.ExpressionUtils;
15
import org.gvsig.fmap.dal.DALLocator;
16
import org.gvsig.fmap.dal.DataTypes;
17
import org.gvsig.fmap.dal.StoresRepository;
18
import org.gvsig.fmap.dal.exception.DataException;
19
import org.gvsig.fmap.dal.feature.Feature;
20
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
21
import org.gvsig.fmap.dal.feature.FeatureStore;
22
import org.gvsig.fmap.dal.feature.FeatureType;
23
import org.gvsig.fmap.geom.Geometry;
24
import org.gvsig.fmap.geom.GeometryUtils;
25
import org.gvsig.fmap.mapcontext.MapContextException;
26
import org.gvsig.fmap.mapcontext.rendering.legend.ZSort;
27
import org.gvsig.fmap.mapcontext.rendering.legend.events.IntervalLegendEvent;
28
import org.gvsig.fmap.mapcontext.rendering.legend.events.LabelLegendEvent;
29
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
30
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
31
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
32
import org.gvsig.fmap.mapcontext.rendering.legend.events.ValueLegendEvent;
33
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
34
import org.gvsig.legend.urbanverticalsignage.lib.api.PictureMarkerSymbolTableLegend;
35
import org.gvsig.symbology.SymbologyLocator;
36
import org.gvsig.symbology.SymbologyManager;
37
import org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl.AbstractVectorialLegend;
38
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.ISimpleMarkerSymbol;
39
import org.gvsig.tools.ToolsLocator;
40
import org.gvsig.tools.dataTypes.Coercion;
41
import org.gvsig.tools.persistence.PersistentState;
42
import org.gvsig.tools.persistence.exception.PersistenceException;
43
import org.gvsig.tools.swing.api.SimpleImage;
44
import org.gvsig.tools.swing.api.ToolsSwingLocator;
45
import org.slf4j.Logger;
46
import org.slf4j.LoggerFactory;
47

    
48
@SupportedSourceVersion(SourceVersion.RELEASE_8)
49
@SuppressWarnings("UseSpecificCatch")
50
public class DefaultPictureMarkerSymbolTableLegend 
51
        extends AbstractVectorialLegend 
52
        implements PictureMarkerSymbolTableLegend 
53
{
54
    
55
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPictureMarkerSymbolTableLegend.class);
56

    
57
    private static final int IMAGESCACHE_SIZE = 100;
58
    
59
    /** 
60
     * defaultSimbol no se usa para nada. 
61
     * Lo inicializamos en el constructor a SimpleMarkerSymbol por si a caso 
62
     * alguien lo consulta, por ejemplo al persistir el ImageMarkerSimbol.
63
     */
64
    transient private final ISimpleMarkerSymbol defaultSymbol;
65
    
66
    transient private final Coercion toColor;
67
    transient private FeatureStore imagesStore;
68
    transient private ExpressionBuilder expressionBuilder;
69
    transient private final LRUMap<Object, BufferedImage[]> imagesCache;
70
    
71
    private double size;
72
    private int units;
73
    private Color lineToOffsetColor;
74
    private boolean drawLineToOffset;
75

    
76
    private String classifyingFieldName;
77
    private String offsetXFieldName;
78
    private String offsetYFieldName;
79
    private String rotationFieldName;
80
    private String lineToOffsetColorFieldlName;
81

    
82
    private String imagesTableName;
83
    private String imagesTableClassifyingFieldName;
84
    private String imageFieldName;
85
    private String imageSelectedFieldName;
86
    private SimpleImage imageNotFound;
87
    
88
    private double scale;
89
    
90
    private class MyZSort extends ZSort {
91
        
92
        public MyZSort() {
93
                super();
94
        }
95

    
96
        @Override
97
        public void legendChanged(LegendChangedEvent e) throws MapContextException {
98
//                symbols.clear();
99
//                usingZSort = false;
100
//                initialize(e.getNewLegend());
101

    
102
        }
103

    
104
        @Override
105
        public String getClassName() {
106
                return getClass().getName();
107
        }
108

    
109
        @Override
110
        public int getLevelCount() {
111
                return 2;
112
        }
113

    
114
        @Override
115
        public void setUsingZSort(boolean usingZSort) {
116
        }
117

    
118
        @Override
119
        public void setLevels(ISymbol sym, int[] values) {
120
        }
121

    
122
        @Override
123
        public void setLevels(int row, int[] values) {
124
        }
125

    
126
        @Override
127
        public int[] getLevels(ISymbol sym) {
128
                return new int[]{0,1};
129
        }
130

    
131
        @Override
132
        public int[] getLevels(int row) {
133
                return null;
134
        }
135

    
136
        @Override
137
        public boolean isUsingZSort() {
138
                return true;
139
        }
140

    
141
        @Override
142
        public ISymbol[] getSymbols() {
143
                return null;
144
        }
145

    
146
        @Override
147
        public String[] getDescriptions() {
148
            return new String[] {"line", "Image"};
149
        }
150

    
151
        @Override
152
        public int getTopLevelIndexAllowed() {
153
                return 0;
154
        }
155

    
156
        @Override
157
        public String toString() {
158
            return "Line, Image";
159
        }
160

    
161
        @Override
162
        public boolean symbolChanged(SymbolLegendEvent e) {
163
                return true;
164
        }
165

    
166
        @Override
167
        public boolean classifiedSymbolChange(SymbolLegendEvent e) {
168
                return true;
169
        }
170

    
171
        @Override
172
        public boolean intervalChange(IntervalLegendEvent e) {
173
                return false;
174
        }
175

    
176
        @Override
177
        public boolean valueChange(ValueLegendEvent e) {
178
                return false;
179
        }
180

    
181
        // TODO should not exist here
182
        @Override
183
        public boolean labelFieldChange(LabelLegendEvent e) {
184
                return false;
185
        }
186

    
187
        @Override
188
        public void legendCleared(LegendClearEvent event) {
189
        }
190
        
191
    }
192
    
193
    public DefaultPictureMarkerSymbolTableLegend() {
194
        
195
        SymbologyManager symbologyManager = SymbologyLocator.getSymbologyManager();
196
        this.scale = 1;
197
        this.defaultSymbol = symbologyManager.createSimpleMarkerSymbol();
198
        this.toColor = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.COLOR);
199
        this.size = DEFAULT_IMAGE_SIZE;
200
        this.drawLineToOffset = true;
201
        this.lineToOffsetColor = Color.DARK_GRAY;
202
        this.imagesCache = new LRUMap<>(IMAGESCACHE_SIZE);
203
        this.setZSort(new MyZSort());
204
    }
205

    
206
    @Override
207
    public ISymbol getDefaultSymbol() {
208
        return this.defaultSymbol;
209
    }
210

    
211
    @Override
212
    public void setDefaultSymbol(ISymbol is) {
213
        //DO NOTHING
214
    }
215

    
216
    private Color getColor(Feature feature, String attrname, Color defaultValue) {
217
        if( StringUtils.isBlank(attrname) ) {
218
            return defaultValue;
219
        }
220
        try {
221
            return (Color) toColor.coerce(feature.get(attrname));
222
        } catch(Exception ex) {
223
            return defaultValue;
224
        }
225
    }
226
    
227
    @Override
228
    public ISymbol getSymbolByFeature(Feature feature) throws MapContextException {
229
        ImageMarkerSymbol symbol = new ImageMarkerSymbol();
230
        
231
        Point2D.Double offset = new Point2D.Double(0,0);
232
        if( StringUtils.isNotBlank(this.offsetXFieldName)) {
233
            offset.x = feature.getDouble(this.offsetXFieldName)*this.scale;
234
        }
235
        if( StringUtils.isNotBlank(this.offsetYFieldName)) {
236
            offset.y = feature.getDouble(this.offsetYFieldName)*this.scale;
237
        }
238
        symbol.setOffset(offset);
239
        
240
        if( StringUtils.isNotBlank(this.rotationFieldName)) {
241
            symbol.setRotation(feature.getDouble(this.rotationFieldName));
242
        } else {
243
            symbol.setRotation(0);
244
        }
245
        
246
        if( drawLineToOffset && (offset.x!=0 || offset.y!=0))    {
247
            symbol.setDrawLineToOffset(true);
248
            symbol.setLineToOffsetColor(
249
                    getColor(
250
                            feature, 
251
                            this.lineToOffsetColorFieldlName, 
252
                            this.lineToOffsetColor
253
                    )
254
            );
255
        } else {
256
            symbol.setDrawLineToOffset(false);
257
            symbol.setLineToOffsetColor(Color.DARK_GRAY);
258
        }
259
        symbol.setSize(this.size*this.scale);
260
        symbol.setUnit(this.units);
261
        
262
        Object classifyingValue = feature.get(this.classifyingFieldName);
263
        BufferedImage[] images = this.getImages(classifyingValue);
264
        symbol.setImage(images[0]);
265
        symbol.setImageSel(images[1]);
266
        return symbol;
267
    }
268

    
269
    @Override
270
    public int getShapeType() {
271
        return Geometry.TYPES.POINT;
272
    }
273

    
274
    private BufferedImage[] getImages(Object classifyingValue) {
275
        
276
        BufferedImage[] images;
277
        images = this.imagesCache.get(classifyingValue);
278
        if( images!=null ) {
279
            return images;
280
        }
281
        
282
        images = new BufferedImage[] { null, null };        
283
        try {
284
            FeatureStore store = this.getImagesStore();
285
            FeatureType featureType = store.getDefaultFeatureTypeQuietly();
286
            FeatureAttributeDescriptor attr = featureType.getAttributeDescriptor(this.imagesTableClassifyingFieldName);
287
            Object value = attr.coerce(classifyingValue);
288
            ExpressionBuilder builder = this.getExpressionBuilder();
289
            String filter = builder.eq(
290
                    builder.column(this.imagesTableClassifyingFieldName),
291
                    builder.constant(value)
292
            ).toString();
293
            Feature f = store.findFirst(filter);
294
            if( f==null ) {
295
                SimpleImage image = getImageNotFound();
296
                images[0] = image.getBufferedImage();
297
                images[1] = images[0];
298
            } else {
299
                SimpleImage image = (SimpleImage) f.getFromProfile(this.imageFieldName);
300
                if( image != null ) {
301
                    images[0] = image.getBufferedImage();
302
                    images[1] = images[0];
303
                }
304
                image = (SimpleImage) f.getFromProfile(this.imageSelectedFieldName);
305
                if( image != null && !image.isEmpty() ) {
306
                    images[1] = image.getBufferedImage();
307
                }
308
            }
309
        } catch(Exception ex) {
310
            LOGGER.debug("Can't retrieve images from table '"+this.imagesTableName+"'", ex);
311
        }
312
        this.imagesCache.put(classifyingValue, images);
313
        return images;
314
    }
315
    
316
    private SimpleImage getImageNotFound() {
317
        if(this.imageNotFound == null){
318
            URL url = this.getClass().getResource("/images/picturemarkersymboltablelegend/image-not-found.png");
319
            this.imageNotFound = ToolsSwingLocator.getToolsSwingManager().createSimpleImage(url);
320
        }
321
        return this.imageNotFound;
322
    }
323
    
324
    private ExpressionBuilder getExpressionBuilder() {
325
        if( this.expressionBuilder == null ) {
326
            this.expressionBuilder = ExpressionUtils.createExpressionBuilder();
327
        }
328
        return this.expressionBuilder;
329
    }
330
    
331
    private FeatureStore getImagesStore() {
332
        if( this.imagesStore == null ) {
333
            StoresRepository repository = DALLocator.getDataManager().getStoresRepository();
334
            this.imagesStore = (FeatureStore) repository.getStore(this.imagesTableName);
335
        }
336
        return this.imagesStore;
337
    }
338
    
339
    @Override
340
    public void setShapeType(int i) {
341
    }
342

    
343
    @Override
344
    public boolean isUseDefaultSymbol() {
345
        return true;
346
    }
347

    
348
    @Override
349
    public void useDefaultSymbol(boolean bln) {
350
    }
351

    
352
    @Override
353
    public boolean isSuitableForShapeType(int shapeType) {
354
        return GeometryUtils.isSubtype(Geometry.TYPES.POINT, shapeType);
355
    }
356

    
357
    @Override
358
    public void loadFromState(PersistentState state) throws PersistenceException {
359
        super.loadFromState(state);
360
        
361
        this.scale = state.getDouble("scale",1.0);
362
        this.size = state.getDouble("size",DEFAULT_IMAGE_SIZE);
363
        this.units = state.getInt("units",-1);
364
        this.lineToOffsetColor = (Color) state.get("lineToOffsetColor");
365
        this.drawLineToOffset = state.getBoolean("drawLineToOffset",true);
366
        this.classifyingFieldName = state.getString("classifyingFieldName");
367
        
368
        this.offsetXFieldName = state.getString("offsetXFieldName");
369
        this.offsetYFieldName = state.getString("offsetYFieldName");
370
        this.rotationFieldName = state.getString("rotationFieldName");
371
        this.lineToOffsetColorFieldlName = state.getString("lineToOffsetColorFieldlName");
372

    
373
        this.imagesTableName = state.getString("imagesTableName");
374
        this.imagesTableClassifyingFieldName = state.getString("imagesTableClassifyingFieldName");
375
        this.imageFieldName = state.getString("imageFieldName");
376
        this.imageSelectedFieldName = state.getString("imageSelectedFieldName");
377
        
378
        setZSort(new MyZSort());
379

    
380
        
381
    }
382

    
383
    @Override
384
    public void saveToState(PersistentState state) throws PersistenceException {
385
        super.saveToState(state);
386
        
387
        state.set("scale", this.scale);
388
        state.set("size", this.size);
389
        state.set("units", this.units);
390
        state.set("lineToOffsetColor", this.lineToOffsetColor);
391
        state.set("drawLineToOffset", this.drawLineToOffset);
392
        state.set("classifyingFieldName", this.classifyingFieldName);
393

    
394
        state.set("offsetXFieldName", this.offsetXFieldName);
395
        state.set("offsetYFieldName", this.offsetYFieldName);
396
        state.set("rotationFieldName", this.rotationFieldName);
397
        state.set("lineToOffsetColorFieldlName", this.lineToOffsetColorFieldlName);
398

    
399
        state.set("imagesTableName", this.imagesTableName);
400
        state.set("imagesTableClassifyingFieldName", this.imagesTableClassifyingFieldName);
401
        state.set("imageFieldName", this.imageFieldName);
402
        state.set("imageSelectedFieldName", this.imageSelectedFieldName);
403
        
404
    }
405

    
406
    @Override
407
    protected String[] getRequiredFeatureAttributeNames(FeatureStore fs) throws DataException {
408
        List<String> attributes = new ArrayList<>();
409
        if( StringUtils.isNotBlank(this.classifyingFieldName)) {
410
            attributes.add(this.classifyingFieldName);
411
        }
412
        if( StringUtils.isNotBlank(this.offsetXFieldName)) {
413
            attributes.add(this.offsetXFieldName);
414
        }
415
        if( StringUtils.isNotBlank(this.offsetYFieldName)) {
416
            attributes.add(this.offsetYFieldName);
417
        }
418
        if( StringUtils.isNotBlank(this.rotationFieldName)) {
419
            attributes.add(this.rotationFieldName);
420
        }
421
        if( StringUtils.isNotBlank(this.lineToOffsetColorFieldlName)) {
422
            attributes.add(this.lineToOffsetColorFieldlName);
423
        }
424
        attributes.add( fs.getDefaultFeatureType().getDefaultGeometryAttributeName() );
425
        return attributes.toArray(new String[attributes.size()]);
426
    }
427

    
428
    @Override
429
    public Color getDefaultLineToOffsetColor() {
430
        return this.lineToOffsetColor;
431
    }
432

    
433
    @Override
434
    public void setDefaultLineToOffsetColor(Color color) {
435
        this.lineToOffsetColor = color;
436
    }
437

    
438
    @Override
439
    public boolean isDrawLineToOffset() {
440
        return this.drawLineToOffset;
441
    }
442

    
443
    @Override
444
    public void setDrawLineToOffset(boolean drawLineToOffset) {
445
        this.drawLineToOffset = drawLineToOffset;
446
    }
447

    
448
    @Override
449
    public double getImageSize() {
450
        return this.size;
451
    }
452

    
453
    @Override
454
    public void setImageSize(double size) {
455
        this.size = size;
456
    }
457

    
458
    @Override
459
    public String getLineToOffsetColorFieldName() {
460
        return this.lineToOffsetColorFieldlName;
461
    }
462

    
463
    @Override
464
    public void setLineToOffsetColorFieldName(String fieldName) {
465
        this.lineToOffsetColorFieldlName = fieldName;
466
    }
467

    
468
    @Override
469
    public String getOffsetXFieldName() {
470
        return this.offsetXFieldName;
471
    }
472

    
473
    @Override
474
    public void setOffsetXFieldName(String fieldName) {
475
        this.offsetXFieldName = fieldName;
476
    }
477

    
478
    @Override
479
    public String getOffsetYFieldName() {
480
        return this.offsetYFieldName;
481
    }
482

    
483
    @Override
484
    public void setOffsetYFieldName(String fieldName) {
485
        this.offsetYFieldName = fieldName;
486
    }
487

    
488
    @Override
489
    public String getRotationFieldName() {
490
        return this.rotationFieldName;
491
    }
492

    
493
    @Override
494
    public void setRotationFieldName(String fieldName) {
495
        this.rotationFieldName = fieldName;
496
    }
497

    
498
    @Override
499
    public String getImagesTableName() {
500
        return imagesTableName;
501
    }
502

    
503
    @Override
504
    public void setImagesTableName(String imagesTableName) {
505
        this.imagesTableName = imagesTableName;
506
        this.imagesCache.clear();
507
    }
508

    
509
    @Override
510
    public String getImageFieldName() {
511
        return imageFieldName;
512
    }
513

    
514
    @Override
515
    public void setImageFieldName(String imageFieldName) {
516
        this.imageFieldName = imageFieldName;
517
        this.imagesCache.clear();
518
    }
519

    
520
    @Override
521
    public String getClassifyingFieldName() {
522
        return classifyingFieldName;
523
    }
524

    
525
    @Override
526
    public void setClassifyingFieldName(String classifyingFieldName) {
527
        this.classifyingFieldName = classifyingFieldName;
528
        this.imagesCache.clear();
529
    }
530

    
531
    @Override
532
    public String getImageSelectedFieldName() {
533
        return imageSelectedFieldName;
534
    }
535

    
536
    @Override
537
    public void setImageSelectedFieldName(String imageSelectedFieldName) {
538
        this.imageSelectedFieldName = imageSelectedFieldName;
539
        this.imagesCache.clear();
540
    }
541

    
542
    @Override
543
    public String getImagesTableClassifyingFieldName() {
544
        return imagesTableClassifyingFieldName;
545
    }
546

    
547
    @Override
548
    public void setImagesTableClassifyingFieldName(String imagesTableClassifyingFieldName) {
549
        this.imagesTableClassifyingFieldName = imagesTableClassifyingFieldName;
550
        this.imagesCache.clear();
551
    }
552

    
553
    @Override
554
    public String[] getDescriptions() {
555
        return new String[] { this.classifyingFieldName + "->" + this.imagesTableName};
556
    }
557

    
558
    @Override
559
    public ISymbol[] getSymbols() {
560
        return new ISymbol[] { this.defaultSymbol };
561
    }
562

    
563
    @Override
564
    public Object[] getValues() {
565
        return new Object[] { "" } ;
566
    }
567

    
568
    @Override
569
    public int getUnits() {
570
        return units;
571
    }
572

    
573
    @Override
574
    public void setUnits(int units) {
575
        this.units = units;
576
    }
577

    
578
    @Override
579
    public double getScale() {
580
        return scale;
581
    }
582

    
583
    @Override
584
    public void setScale(double scale) {
585
        this.scale = scale;
586
    }
587

    
588
}