Statistics
| Revision:

svn-gvsig-desktop / branches / org.gvsig.desktop-2018a / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.mapcontext / org.gvsig.fmap.mapcontext.impl / src / main / java / org / gvsig / fmap / mapcontext / raster / impl / DefaultRasterLayer.java @ 43803

History | View | Annotate | Download (24.4 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2016 gvSIG Association
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., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.mapcontext.raster.impl;
24

    
25
import java.awt.Graphics2D;
26
import java.awt.Point;
27
import java.awt.geom.Point2D;
28
import java.awt.image.BufferedImage;
29
import java.io.File;
30
import java.util.List;
31
import java.util.Observable;
32
import java.util.Observer;
33
import java.util.Set;
34
import java.util.TreeSet;
35

    
36
import org.cresques.cts.ICoordTrans;
37
import org.slf4j.LoggerFactory;
38

    
39
import org.gvsig.compat.print.PrintAttributes;
40
import org.gvsig.fmap.dal.DataStore;
41
import org.gvsig.fmap.dal.exception.DataException;
42
import org.gvsig.fmap.dal.exception.ReadException;
43
import org.gvsig.fmap.dal.raster.api.BandAttributeDescriptor;
44
import org.gvsig.fmap.dal.raster.api.BandDescriptor;
45
import org.gvsig.fmap.dal.raster.api.RasterQuery;
46
import org.gvsig.fmap.dal.raster.api.RasterSet;
47
import org.gvsig.fmap.dal.raster.api.RasterStore;
48
import org.gvsig.fmap.dal.raster.api.RasterStoreNotification;
49
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemStoreParameters;
50
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
51
import org.gvsig.fmap.geom.GeometryLocator;
52
import org.gvsig.fmap.geom.GeometryManager;
53
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
54
import org.gvsig.fmap.geom.primitive.Envelope;
55
import org.gvsig.fmap.mapcontext.MapContextLocator;
56
import org.gvsig.fmap.mapcontext.ViewPort;
57
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
58
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
59
import org.gvsig.fmap.mapcontext.layers.FLayer;
60
import org.gvsig.fmap.mapcontext.layers.FLyrDefault;
61
import org.gvsig.fmap.mapcontext.layers.LayerInformationBuilder;
62
import org.gvsig.fmap.mapcontext.raster.api.RasterLayer;
63
import org.gvsig.fmap.mapcontext.raster.api.legend.RasterLegendEvent;
64
import org.gvsig.fmap.mapcontext.raster.api.legend.listeners.RasterLegendChangedListener;
65
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
66
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
67
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
68
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
69
import org.gvsig.metadata.exceptions.MetadataException;
70
import org.gvsig.raster.lib.buffer.api.BufferLocator;
71
import org.gvsig.raster.lib.buffer.api.OperationManager;
72
import org.gvsig.raster.lib.buffer.api.statistics.Statistics;
73
import org.gvsig.raster.lib.legend.api.RasterLegend;
74
import org.gvsig.raster.lib.legend.api.colorinterpretation.ColorInterpretation;
75
import org.gvsig.tools.ToolsLocator;
76
import org.gvsig.tools.dispose.DisposeUtils;
77
import org.gvsig.tools.dynobject.DynObjectSet;
78
import org.gvsig.tools.dynobject.DynStruct;
79
import org.gvsig.tools.dynobject.exception.DynMethodException;
80
import org.gvsig.tools.dynobject.exception.DynMethodNotSupportedException;
81
import org.gvsig.tools.exception.BaseException;
82
import org.gvsig.tools.i18n.I18nManager;
83
import org.gvsig.tools.locator.LocatorException;
84
import org.gvsig.tools.persistence.PersistenceManager;
85
import org.gvsig.tools.persistence.Persistent;
86
import org.gvsig.tools.persistence.PersistentState;
87
import org.gvsig.tools.persistence.exception.PersistenceException;
88
import org.gvsig.tools.task.Cancellable;
89
import org.gvsig.tools.task.SimpleTaskStatus;
90
import org.gvsig.tools.task.TaskStatusManager;
91
import org.gvsig.tools.util.Callable;
92

    
93
/**
94
 * Capa b?sica Raster.
95
 *
96
 */
97
public class DefaultRasterLayer extends FLyrDefault implements RasterLayer, RasterLegendChangedListener, Observer {
98

    
99
    final static private org.slf4j.Logger logger = LoggerFactory.getLogger(DefaultRasterLayer.class);
100

    
101
    private RasterStore store;
102
    private RasterLegend legend;
103
    // private Cancellable cancel;
104
    private RasterQuery baseQuery;
105
    private Statistics statistics;
106

    
107
    public static class RegisterPersistence implements Callable {
108

    
109
        public Object call() {
110
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
111
            DynStruct definition =
112
                manager.addDefinition(DefaultRasterLayer.class, "DefaultRasterLayer",
113
                    "DefaultRasterLayer Persistence definition", null, null);
114
            definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE, "FLyrDefault");
115
            definition.addDynFieldObject("legend").setClassOfValue(RasterLegend.class).setMandatory(true);
116
            definition.addDynFieldObject("store").setClassOfValue(RasterStore.class).setMandatory(true);
117
            definition.addDynFieldObject("baseQuery").setClassOfValue(RasterQuery.class).setMandatory(false);
118

    
119
            return Boolean.TRUE;
120
        }
121
    }
122

    
123
    /**
124
     * Creates a new DefaultRasterLayer
125
     *
126
     * @throws LoadLayerException
127
     */
128
    public DefaultRasterLayer() throws LoadLayerException {
129
        super();
130
    }
131

    
132
    /**
133
     * Creates a new DefaultRasterLayer
134
     *
135
     * @param store
136
     * @param legend
137
     */
138
    public DefaultRasterLayer(RasterStore store, RasterLegend legend) {
139
        super();
140
        ToolsLocator.getDisposableManager().bind(store);
141
        this.store = store;
142
        this.setLegend(legend);
143
    }
144

    
145
    public void saveToState(PersistentState state) throws PersistenceException {
146
        try {
147
            super.saveToState(state);
148

    
149
            state.set("store", (Persistent) this.store);
150
            state.set("legend", (Persistent) this.legend);
151
            state.set("baseQuery", (Persistent) this.baseQuery);
152

    
153
        } catch (PersistenceException ex) {
154
            logger.warn("Can't save to persistent state the layer '" + this.getName() + "'.");
155
            throw ex;
156
        } catch (RuntimeException ex) {
157
            logger.warn("Can't save to persistent state the layer '" + this.getName() + "'.");
158
            throw ex;
159
        }
160
    }
161

    
162
    public void loadFromState(PersistentState state) throws PersistenceException {
163

    
164
        try {
165
            super.loadFromState(state);
166

    
167
            this.store = (RasterStore) state.get("store");
168
            this.legend = (RasterLegend) state.get("legend");
169
            this.baseQuery = (RasterQuery) state.get("baseQuery");
170

    
171
        } catch (PersistenceException ex) {
172
            logger.warn("Can't load from persietent state the layer '" + this.getName() + "'.");
173
            throw ex;
174
        } catch (RuntimeException ex) {
175
            logger.warn("Can't load from persietent state the layer '" + this.getName() + "'.");
176
            throw ex;
177
        }
178

    
179
    }
180

    
181
    private void setLegend(RasterLegend legend) {
182
        if (this.legend == legend) {
183
            return;
184
        }
185
        if (this.legend != null && this.legend.equals(legend)) {
186
            return;
187
        }
188
        RasterLegend oldLegend = this.legend;
189
        if (oldLegend != null) {
190
             oldLegend.removeLegendListener( this);
191
//             oldLegend.deleteDrawingObserver(this);
192
        }
193
        this.legend = legend;
194
//        if (this.legend != null) {
195
//             this.legend.addDrawingObserver(this);
196
//             this.legend.addLegendListener( this);
197
//        }
198

    
199
        this.legend.addLegendListener(this);
200

    
201
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
202
        // FIXME: cuando se arregle LegendChangeEvent para que admita capas
203
        // raster (y no solo las ClassifiableVectorial) descomentarizar la siguiente l?nea
204
        // e.setLayer(this);
205
        updateDrawVersion();
206
        callLegendChanged(e);
207
    }
208

    
209
    /**
210
     * Devuelve la Leyenda de la capa.
211
     *
212
     * @return Leyenda.
213
     */
214
    public RasterLegend getLegend(){
215
        if (legend == null) {
216
            try {
217
                createDefaultLegend();
218
            } catch (LegendLayerException e) {
219
                throw new RuntimeException("Can't initialize legend.", e);
220
            }
221
        }
222
        return legend;
223
    }
224

    
225
    @Override
226
    public DataStore getDataStore() {
227
        return this.store;
228
    }
229

    
230
    @Override
231
    public void setDataStore(DataStore dataStore) throws LoadLayerException {
232

    
233
        if (this.store != null) {
234
//            ToolsLocator.getDisposableManager().release(this.store);
235
            DisposeUtils.disposeQuietly(this.store);
236
        }
237

    
238
        this.store = (RasterStore) dataStore;
239
        ToolsLocator.getDisposableManager().bind(dataStore);
240
        createDefaultLegend();
241
    }
242

    
243
    /**
244
     * Initializes the legend if it is not initalized yet
245
     *
246
     * @throws LegendLayerException
247
     */
248
    private void createDefaultLegend() throws LegendLayerException {
249
        RasterLegend legend = null;
250
        if (this.legend == null) {
251
            // Should be done like this but must be corrected mapContextManager
252
            // MapContextManager mapContextManager =
253
            // MapContextLocator.getMapContextManager();
254
            // Set the legend
255
            // IRasterLegend legend = (IRasterLegend)
256
            // mapContextManager.getLegend(store);
257

    
258
            // Should be moved to mapContextManager when RasterLegend implements
259
            // ILegend
260
            if (legend == null) {
261
                try {
262
                    legend = (RasterLegend) store.invokeDynMethod(RasterStore.DYNMETHOD_GETLEGEND_NAME, null);
263
                } catch (DynMethodNotSupportedException e) {
264
                    logger.debug("This store {} does not provide a legend.", store.getName());
265
                } catch (DynMethodException e) {
266
                    logger.error("Can't load the specific legend provided for the store {}.", store.getName(), e);
267
                }
268
            }
269

    
270
            if (legend == null) {
271
                throw new LegendLayerException(this.getName());
272
            }
273

    
274
            ColorInterpretation colorInterpretation = legend.getColorInterpretation();
275
            if (colorInterpretation.isPalette()) {
276
                legend.addColorTableOperation(colorInterpretation, 0);
277
            } else {
278
                legend.addLinearStretchEnhancementOperationIfNeeded(colorInterpretation, getRasterStore(), 0);
279
            }
280

    
281
            OperationManager operationManager = BufferLocator.getOperationManager();
282
            if (colorInterpretation.hasAnyHSLBand()) {
283
                legend.addHSLToRGBOperation(colorInterpretation);
284
            } else if (colorInterpretation.hasAnyCMYKBand()) {
285
                legend.addCMYKToRGBOperation(colorInterpretation);
286
            } else if (colorInterpretation.hasAnyYCBCRBand()) {
287
              //TODO: Not implemented yet, meanwhile do nothing
288
//                legend.addYCBCRToRGBOperation(colorInterpretation);
289
            }
290

    
291
            this.setLegend(legend);
292
        }
293
    }
294

    
295
    @Override
296
    public Envelope getFullEnvelope() throws ReadException {
297
        Envelope rAux;
298
        try {
299
            rAux = getRasterStore().getEnvelope();
300
        } catch (BaseException e) {
301
            throw new ReadException(getName(), e);
302
        }
303

    
304
        // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
305
        // y alto 0.
306
        if (rAux == null || rAux.isEmpty() || rAux.getMaximum(0) - rAux.getMinimum(0) == 0
307
            && rAux.getMaximum(1) - rAux.getMinimum(1) == 0) {
308
            try {
309
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
310
                rAux = geomManager.createEnvelope(0, 0, 90, 90, SUBTYPES.GEOM2D);
311
            } catch (CreateEnvelopeException e) {
312
                logger.error("Error creating the envelope", e);
313
                e.printStackTrace();
314
            }
315
        }
316
        // Si existe reproyecci?n, reproyectar el extent
317
        ICoordTrans ct = getCoordTrans();
318
        if (ct != null) {
319
            rAux = rAux.convert(ct);
320
        }
321
        return rAux;
322
    }
323

    
324
    @Override
325
    public void draw(BufferedImage image, final Graphics2D g, final ViewPort viewPort, Cancellable cancel, double scale)
326
        throws ReadException {
327
        if (legend == null) {
328
            try {
329
                createDefaultLegend();
330
            } catch (LegendLayerException e) {
331
                logger.warn("Can't initialize the legend", e);
332
                return;
333
            }
334
            return;
335
        }
336

    
337
        if (!this.isWithinScale(scale)) {
338
            return;
339
        }
340
        if (cancel.isCanceled()) {
341
            return;
342
        }
343

    
344
        RasterQuery rasterQuery = createRasterQuery();
345
        Envelope reprojectedViewPortEnvelope = (Envelope) viewPort.getAdjustedEnvelope(); // .getEnvelope();
346
        ICoordTrans ct = getCoordTrans();
347
        if (ct != null) {
348
            try {
349
                reprojectedViewPortEnvelope = (Envelope) reprojectedViewPortEnvelope.clone();
350
                reprojectedViewPortEnvelope = reprojectedViewPortEnvelope.convert(ct.getInverted());
351
            } catch (CloneNotSupportedException e) {
352
                this.setAvailable(false);
353
                this.setError(e);
354
                throw new ReadException(getName(), e);
355
            }
356
        }
357

    
358
        double pixelSize = reprojectedViewPortEnvelope.getLength(0) / (double) viewPort.getImageWidth();
359

    
360
        rasterQuery.setPixelSize(pixelSize);
361
        rasterQuery.setClip(reprojectedViewPortEnvelope);
362

    
363
        // ColorInterpretation colorInterpretation =
364
        // legend.getColorInterpretation();
365
        // String[] renderBands =
366
        // colorInterpretation.getValues();//.buildRenderBands();
367
        // for (int i = 0; i < renderBands.length; i++) {
368
        // int band = colorInterpretation.getBand(renderBands[i]);
369
        // if(band>=0){
370
        // rasterQuery.addBand(this.store.createBandQuery(band));
371
        // }
372
        // }
373

    
374
        RasterSet rasterSet = null;
375
        try {
376

    
377
            long tini = System.currentTimeMillis();
378

    
379
            // TODO Task status should be used to cancel
380
            TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
381
            final SimpleTaskStatus taskStatus = manager.createDefaultSimpleTaskStatus("Draw " + getDataStore().getName());
382

    
383
//            getRasterStore().getRasterSet(rasterQuery, new org.gvsig.tools.observer.Observer() {
384
//
385
//                @Override
386
//                public void update(org.gvsig.tools.observer.Observable buffer, Object notification) {
387
//                    ((RasterLegend) legend).draw(g, buffer, viewPort, taskStatus);
388
//                }
389
//            });
390

    
391
            rasterSet = getRasterStore().getRasterSet(rasterQuery);
392
            // BufferedImage img = rasterSet.getBufferedImage();
393
            // if (img != null) {
394
            // try {
395
            // ImageIO.write(rasterSet.getBufferedImage(), "png32", new
396
            // File("/tmp/"+rasterSet.getClass().getName()+".png"));
397
            // } catch (IOException e) {
398
            // // TODO Auto-generated catch block
399
            // e.printStackTrace();
400
            // }
401
            // }
402
            if (!rasterSet.isEmpty()) {
403
                ((RasterLegend) legend).draw(g, rasterSet, viewPort, taskStatus);
404

    
405
                logger.debug("Layer " + this.getName() + " drawn in " + (System.currentTimeMillis() - tini)
406
                    + " milliseconds.");
407
            }
408

    
409
        } catch (DataException e) {
410
            this.setAvailable(false);
411
            this.setError(e);
412
            throw new ReadException(getName(), e);
413
        } finally {
414
            if (rasterSet != null) {
415
                DisposeUtils.dispose(rasterSet);
416
                rasterSet = null;
417
            }
418
        }
419

    
420
    }
421

    
422
    @Override
423
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, double scale, PrintAttributes properties)
424
        throws ReadException {
425

    
426
        // TODO legend doesn't have print method
427
        throw new UnsupportedOperationException();
428

    
429
    }
430

    
431
    @Override
432
    public Set<RasterStore> getMetadataChildren() throws MetadataException {
433
        Set<RasterStore> ret = new TreeSet<RasterStore>();
434
        ret.add(this.store);
435
        return ret;
436
    }
437

    
438
    @Override
439
    public Object getMetadataID() throws MetadataException {
440
        return "Layer(" + this.getName() + "):" + this.store.getMetadataID();
441
    }
442

    
443
    @Override
444
    public void update(Observable observable, Object notification) {
445
        if (observable.equals(this.store)) {
446
            if (notification instanceof RasterStoreNotification) {
447
                RasterStoreNotification event = (RasterStoreNotification) notification;
448
                if (event.getType() == RasterStoreNotification.AFTER_REFRESH
449
                    || event.getType() == RasterStoreNotification.SELECTION_CHANGE) {
450
                    this.updateDrawVersion();
451
                } else if (event.getType() == RasterStoreNotification.RESOURCE_CHANGED) {
452
                    this.setAvailable(false);
453
                }
454
            }
455
        }
456
    }
457

    
458
    @Override
459
    public RasterStore getRasterStore() {
460
        return this.store;
461
    }
462

    
463
    @Override
464
    public void setBaseQuery(RasterQuery baseQuery) {
465
        this.baseQuery = baseQuery;
466
    }
467

    
468
    @Override
469
    public RasterQuery getBaseQuery() {
470
        return this.baseQuery;
471
    }
472

    
473
    @Override
474
    public RasterQuery createRasterQuery() {
475
        if (this.baseQuery == null) {
476
            return this.getRasterStore().createRasterQuery();
477
        }
478
        try {
479
            return (RasterQuery) baseQuery.clone();
480
        } catch (CloneNotSupportedException ex) {
481
            throw new RuntimeException(ex);
482
        }
483
    }
484

    
485
    @Override
486
    protected void doDispose() throws BaseException {
487
        logger.debug("Dispose DefaultRasterLayer '"+(this.getDataStore()==null?"NULL":this.getDataStore().getFullName()+"'"));
488

    
489
        DisposeUtils.dispose(this.store);
490
        this.layerListeners.clear();
491
        this.store = null;
492
        this.legend = null;
493
        this.baseQuery = null;
494
    }
495

    
496
    @Override
497
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException, DataException {
498

    
499
        return getInfo(p, tolerance, cancel, true);
500
    }
501

    
502
    @Override
503
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel, boolean fast) throws LoadLayerException,
504
        DataException {
505

    
506
        Point2D infop = new Point2D.Double(p.x, p.y);
507
        org.gvsig.fmap.geom.primitive.Point pReal = this.getMapContext().getViewPort().convertToMapPoint(infop);
508

    
509
        // TODO:
510
        return null;
511
    }
512

    
513
    @Override
514
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p, double tolerance) throws LoadLayerException,
515
        DataException {
516
        // TODO Auto-generated method stub
517
        return null;
518
    }
519

    
520
    public String getTocImageIcon() {
521
        //FIXME: Subir esto a la clase abstracta
522
        return MapContextLocator.getMapContextManager().getIconLayer(this.getDataStore());
523
    }
524

    
525
    @Override
526
    public void setLegend(ILegend legend) {
527
        if (legend instanceof RasterLegend) {
528
            setLegend((RasterLegend) legend);
529
        } else {
530
            throw new IllegalArgumentException("The legend isn't a RasterLegend.");
531
        }
532
    }
533

    
534
    @Override
535
    public String getInfoString() {
536
        RasterStore rasterStore = this.getRasterStore();
537
        Envelope envelope = null;
538
        try {
539
            envelope = rasterStore.getEnvelope();
540
        } catch (LocatorException | DataException | CreateEnvelopeException e) {
541
        }
542
        int bands = rasterStore.getBands();
543
        I18nManager i18nManager = ToolsLocator.getI18nManager();
544
        LayerInformationBuilder builder = MapContextLocator.getMapContextManager().createLayerInformationBuilder();
545

    
546
        builder.title().labelkey("Data_source");
547
        builder.property().labelkey("Source_type").value(store.getProviderName());
548
        builder.property().labelkey("origen").value(store.getFullName());
549
        if (store.getParameters() instanceof FilesystemStoreParameters) {
550
            File f = ((FilesystemStoreParameters) (store.getParameters())).getFile();
551
            if (f != null) {
552
                builder.property().labelkey("size").value("%d bytes", f.length());
553
            }
554
        }
555

    
556
        builder.property().labelkey("_bands").value("%d", bands);
557
        builder.property().labelkey("transparency").value("%d", this.getTransparency());
558

    
559
        builder.title().labelkey("_Coordenadas_geograficas");
560
        builder.envelope().value(envelope);
561

    
562
        builder.title().labelkey("_Projection");
563
        builder.property().value(this.getProjection());
564
        builder.text().asWKT(this.getProjection());
565

    
566
        for (int i = 0; i < bands; i++) {
567
            builder.title().labelkey(i18nManager.getTranslation("_band") + " " + i);
568

    
569
            BandDescriptor bandDescriptor = rasterStore.getBandDescriptor(i);
570

    
571
            builder.property().labelkey("_name").value(bandDescriptor.getName());
572
            builder.property().labelkey("_description").value(bandDescriptor.getDescription());
573
            builder.property().labelkey("_dataType")
574
                .value(BufferLocator.getBufferManager().getTypeName(bandDescriptor.getDataType()));
575

    
576
            if (bandDescriptor.getNoData() != null) {
577
                builder.property().labelkey("_noData").value(bandDescriptor.getNoData().toString());
578
            } else {
579
                builder.property().labelkey("_noData").value(i18nManager.getTranslation("_null"));
580
            }
581

    
582
            for (BandAttributeDescriptor bandAttributeDescriptor : bandDescriptor) {
583
                builder.property().labelkey("_name").value(bandAttributeDescriptor.getName());
584
                builder.property().labelkey("_description").value(bandAttributeDescriptor.getDescription());
585
                builder.property().labelkey("_units").value(bandAttributeDescriptor.getUnits());
586

    
587
                builder.title().labelkey("_values");
588

    
589
                List<Object> attributeValues = bandAttributeDescriptor.getAvailableValues();
590

    
591
                for (Object value : attributeValues) {
592
                    if (value != null) {
593
                        builder.property().labelkey("_units").value(bandAttributeDescriptor.getUnits());
594
                    } else {
595
                        builder.property().labelkey("_units").value(bandAttributeDescriptor.getUnits());
596
                    }
597
                }
598
            }
599
        }
600

    
601
        return builder.toString();
602
    }
603

    
604
    public Statistics getStatistics(SimpleTaskStatus status) {
605
        if (statistics == null) {
606
            RasterSet rasterSet = null;
607
            try {
608
                rasterSet = getRasterStore().getRasterSet();
609
                statistics = rasterSet.getStatistics(status);
610
            } catch (DataException e) {
611
                logger.warn("Can't get layer's statistics", e);
612
            } finally {
613
                DisposeUtils.dispose(rasterSet);
614
            }
615
        }
616
        return statistics;
617
    }
618

    
619
    public void recalculateStatistics() {
620
        this.statistics = null;
621
    }
622

    
623
    @Override
624
    public FLayer cloneLayer() throws Exception {
625
        RasterLegend clonedLegend = (RasterLegend)this.legend.cloneLegend();
626
        DefaultRasterLayer cloned = new DefaultRasterLayer(this.store, clonedLegend);
627
        cloned.setName(this.getName());
628
        cloned.setProjection(this.getProjection());
629

    
630
        return cloned;
631
    }
632

    
633
    @Override
634
    public boolean symbolChanged(SymbolLegendEvent e) {
635
        //FIXME: Remove when fixed hierarchy of legend events
636
        throw new UnsupportedOperationException("There aren't any symbols in a raster legend.");
637
    }
638

    
639
    @Override
640
    public void legendCleared(LegendClearEvent event) {
641
        //FIXME: Remove when fixed hierarchy of legend events
642
        throw new UnsupportedOperationException("Can't clear a raster legend.");
643
    }
644

    
645
    @Override
646
    public boolean colorInterpretationChanged(RasterLegendEvent e) {
647
        this.updateDrawVersion();
648

    
649
        LegendChangedEvent ev = LegendChangedEvent.createLegendChangedEvent(legend, e);
650
        this.callLegendChanged(ev);
651
        return true;
652
    }
653

    
654
    @Override
655
    public boolean operationListChanged(RasterLegendEvent e) {
656
        this.updateDrawVersion();
657

    
658
        LegendChangedEvent ev = LegendChangedEvent.createLegendChangedEvent(legend, e);
659
        this.callLegendChanged(ev);
660
        return true;
661
    }
662
}