Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.app / org.gvsig.app.mainplugin / src / main / java / org / gvsig / app / project / ProjectSymbolTable.java @ 44025

History | View | Annotate | Download (19.2 KB)

1
package org.gvsig.app.project;
2

    
3
import java.io.File;
4
import java.io.FileInputStream;
5
import java.util.HashMap;
6
import java.util.Iterator;
7
import java.util.Map;
8
import java.util.Properties;
9
import org.apache.commons.io.IOUtils;
10
import org.apache.commons.lang3.Range;
11
import org.cresques.cts.IProjection;
12
import org.gvsig.app.ApplicationLocator;
13
import org.gvsig.app.ApplicationManager;
14
import org.gvsig.app.project.documents.Document;
15
import org.gvsig.app.project.documents.view.ViewDocument;
16
import org.gvsig.app.project.documents.view.ViewManager;
17
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
18
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
19
import org.gvsig.expressionevaluator.Interpreter;
20
import org.gvsig.expressionevaluator.spi.AbstractFunction;
21
import org.gvsig.expressionevaluator.spi.AbstractSymbolTable;
22
import org.gvsig.fmap.crs.CRSFactory;
23
import org.gvsig.fmap.dal.feature.Feature;
24
import org.gvsig.fmap.dal.feature.FeatureQuery;
25
import org.gvsig.fmap.dal.feature.FeatureSelection;
26
import org.gvsig.fmap.dal.feature.FeatureSet;
27
import org.gvsig.fmap.dal.feature.FeatureStore;
28
import org.gvsig.fmap.geom.Geometry;
29
import org.gvsig.fmap.geom.primitive.Envelope;
30
import org.gvsig.fmap.mapcontext.MapContext;
31
import org.gvsig.fmap.mapcontext.layers.FLayer;
32
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
33
import org.gvsig.fmap.mapcontrol.AreaAndPerimeterCalculator;
34

    
35
/**
36
 *
37
 * @author jjdelcerro
38
 */
39
@SuppressWarnings("UseSpecificCatch")
40
public class ProjectSymbolTable extends AbstractSymbolTable {
41

    
42
    private abstract class CachedValue<T> {
43

    
44
        T value = null;
45
        long lastAccess = 0;
46

    
47
        protected abstract void reload();
48

    
49
        public boolean isExpired() {
50
            long now = System.currentTimeMillis();
51
            return now - lastAccess > 3000;
52
        }
53

    
54
        public T get() {
55
            if (isExpired()) {
56
                reload();
57
            }
58
            lastAccess = System.currentTimeMillis();
59
            return value;
60
        }
61
    }
62

    
63
    private class ProjectValue extends CachedValue<Project> {
64

    
65
        @Override
66
        protected void reload() {
67
            value = ProjectManager.getInstance().getCurrentProject();
68
        }
69

    
70
    }
71

    
72
    private class CurrentViewValue extends CachedValue<ViewDocument> {
73

    
74
        @Override
75
        protected void reload() {
76
            ApplicationManager application = ApplicationLocator.getManager();
77
            ViewDocument viewdoc = (ViewDocument) application.getActiveDocument(ViewManager.TYPENAME);
78
            value = viewdoc;
79
        }
80

    
81
    }
82

    
83
    private class CurrentViewEnvelopeValue extends CachedValue<Geometry> {
84

    
85
        @Override
86
        protected void reload() {
87
            ApplicationManager application = ApplicationLocator.getManager();
88
            ViewDocument viewdoc = (ViewDocument) application.getActiveDocument(ViewManager.TYPENAME);
89
            if( viewdoc == null ) {
90
                value = null;
91
                return;
92
            }
93
            value = viewdoc.getMapContext().getViewPort().getEnvelope().getGeometry();
94
        }
95

    
96
    }
97

    
98
    private class PropertiesValue extends CachedValue<Map<File, Properties>> {
99

    
100
        @Override
101
        protected void reload() {
102
            value = new HashMap<>();
103
        }
104
    }
105

    
106
    private class CurrentProjectFunction extends AbstractFunction {
107

    
108
        public CurrentProjectFunction() {
109
            super(
110
                    "Project",
111
                    "project",
112
                    Range.is(0),
113
                    "Access to the current project loaded in gvSIG desktop.\n",
114
                    "project()",
115
                    null,
116
                    "Project"
117
            );
118
        }
119

    
120
        @Override
121
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
122
            return currentProject.get();
123
        }
124

    
125
    }
126

    
127
    private class FirstSelectedFeatureFunction extends AbstractFunction {
128

    
129
        public FirstSelectedFeatureFunction() {
130
            super(
131
                    "Project",
132
                    "firstSelectedFeature",
133
                    Range.between(3, 4),
134
                    "Access to the first selected feature of the layer, and "
135
                    + "return the value of the attribute.",
136
                    "firstSelectedFeature({{view}}, layer, attribute, defaulValue)",
137
                    new String[]{
138
                        "view - String value with the name of a view",
139
                        "layer - String value with the name of a layer in the indicated view",
140
                        "attribute - String value with the name of the attribute in the indicated layer",
141
                        "defaultValue - Optional. Value to use if the indicated "
142
                        + "attribute can not be accessed. For example, if the "
143
                        + "view or layer does not exist, or it does not have "
144
                        + "selected elements."
145
                    },
146
                    "Object"
147
            );
148
        }
149

    
150
        @Override
151
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
152
            Object defaultValue = null;
153
            String viewName = getStr(args, 0);
154
            String layerName = getStr(args, 1);
155
            String attrName = getStr(args, 2);
156
            if (args.length == 4) {
157
                defaultValue = getObject(args, 3);
158
            }
159
            try {
160
                Project project = currentProject.get();
161
                ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
162
                if (view == null) {
163
                    return defaultValue;
164
                }
165
                FLayer layer = view.getLayer(layerName);
166
                if (!(layer instanceof FLyrVect)) {
167
                    return defaultValue;
168
                }
169
                FeatureSelection selection = ((FLyrVect) layer).getFeatureStore().getFeatureSelection();
170
                if (selection == null || selection.isEmpty()) {
171
                    return defaultValue;
172
                }
173
                Feature feature = selection.first();
174
                if (feature == null) {
175
                    return defaultValue;
176
                }
177
                return feature.get(attrName);
178
            } catch (Exception ex) {
179
                return defaultValue;
180
            }
181
        }
182

    
183
    }
184

    
185
    private class FirstFeatureFunction extends AbstractFunction {
186

    
187
        public FirstFeatureFunction() {
188
            super(
189
                    "Project",
190
                    "firstFeature",
191
                    Range.between(3, 6),
192
                    "Access to the first feature of the layer, and "
193
                    + "return the value of the attribute.",
194
                    "firstFeature({{view}}, layer, attribute, filter, order, defaulValue)",
195
                    new String[]{
196
                        "view - String value with the name of a view",
197
                        "layer - String value with the name of a layer in the indicated view",
198
                        "attribute - String value with the name of the attribute in the indicated layer",
199
                        "filter - Optional. String value with a filter expression",
200
                        "order - Optional. String value with the order. must be a string with the names of separate fields with commas",
201
                        "defaultValue - Optional. Value to use if the indicated "
202
                        + "attribute can not be accessed. For example, if the "
203
                        + "view or layer does not exist."
204
                    },
205
                    "Object"
206
            );
207
        }
208

    
209
        @Override
210
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
211
            Object defaultValue = null;
212
            String filter = null;
213
            String order = null;
214
            String viewName = getStr(args, 0);
215
            String layerName = getStr(args, 1);
216
            String attrName = getStr(args, 2);
217
            switch (args.length) {
218
                case 4:
219
                    filter = getStr(args, 3);
220
                    break;
221
                case 5:
222
                    filter = getStr(args, 3);
223
                    order = getStr(args, 4);
224
                    break;
225
                case 6:
226
                    filter = getStr(args, 3);
227
                    order = getStr(args, 4);
228
                    defaultValue = getObject(args, 6);
229
                    break;
230
            }
231
            try {
232
                Project project = currentProject.get();
233
                ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
234
                if (view == null) {
235
                    return defaultValue;
236
                }
237
                FLayer layer = view.getLayer(layerName);
238
                if (!(layer instanceof FLyrVect)) {
239
                    return defaultValue;
240
                }
241
                FeatureStore store = ((FLyrVect) layer).getFeatureStore();
242
                FeatureSet set;
243
                if (filter == null && order == null) {
244
                    set = store.getFeatureSet();
245
                } else {
246
                    FeatureQuery query = store.createFeatureQuery();
247
                    if (filter != null) {
248
                        query.addFilter(filter);
249
                    }
250
                    if (order != null) {
251
                        query.getOrder().add(order);
252
                    }
253
                    set = store.getFeatureSet(query);
254
                }
255
                Feature feature = set.first();
256
                if (feature == null) {
257
                    return defaultValue;
258
                }
259
                return feature.get(attrName);
260
            } catch (Exception ex) {
261
                return defaultValue;
262
            }
263
        }
264

    
265
    }
266

    
267
    private class ViewFunction extends AbstractFunction {
268

    
269
        public ViewFunction() {
270
            super(
271
                    "Project",
272
                    "view",
273
                    Range.is(1),
274
                    "Access to the indicated view",
275
                    "view({{viewName}})",
276
                    new String[]{
277
                        "view - String value with the name of a view"
278
                    },
279
                    "DocumentView"
280
            );
281
        }
282

    
283
        @Override
284
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
285
            String viewName = getStr(args, 0);
286
            Project project = currentProject.get();
287
            ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
288
            return view;
289
        }
290

    
291
    }
292

    
293
    private class ViewBBoxFunction extends AbstractFunction {
294

    
295
        public ViewBBoxFunction() {
296
            super(
297
                    "Project",
298
                    "viewbbox",
299
                    Range.is(0),
300
                    "Return the BBox of the active view.",
301
                    "viewbbox()",
302
                    null,
303
                    "Geometry"
304
            );
305
        }
306

    
307
        @Override
308
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
309
            return currentViewEnvelope.get();
310
        }
311

    
312
    }
313

    
314
    private class AreaFunction extends AbstractFunction {
315

    
316
        public AreaFunction() {
317
            super(
318
                    "Project",
319
                    "Area",
320
                    Range.between(2,3),
321
                    "Calculate the area of the geometry in the indicated units",
322
                    "Area({{geometry}}, \"m\")",
323
                    new String[]{
324
                        "geometry - Geometry",
325
                        "Projection - Optional. Projection of the geometry or a string with the projection name",
326
                        "units - String value with the name the units to use"
327
                    },
328
                    "Double"
329
            );
330
        }
331

    
332
        @Override
333
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
334
            int units = 0;
335
            IProjection proj = null;
336
            Geometry geom = getGeom(args, 0);
337
            switch( args.length ) {
338
                case 2:
339
                    units = getUnits(args, 1);
340
                    break;
341
                case 3:
342
                    proj = getProjection(args, 1);
343
                    units = getUnits(args, 2);
344
                    break;
345
            }
346
            if (proj == null) {
347
                proj = geom.getProjection();
348
            }
349
            AreaAndPerimeterCalculator calculator = new AreaAndPerimeterCalculator();
350
            double area = calculator.area(geom, proj, units);
351
            return area;
352
        }
353
    }
354

    
355
    private class PerimeterFunction extends AbstractFunction {
356

    
357
        public PerimeterFunction() {
358
            super(
359
                    "Project",
360
                    "Perimeter",
361
                    Range.between(2,3),
362
                    "Calculate the perimeter of the geometry in the indicated units",
363
                    "Perimeter({{geometry}}, \"m\")",
364
                    new String[]{
365
                        "geometry - Geometry",
366
                        "Projection - Optional. Projection of the geometry or a string with the projection name",
367
                        "units - String value with the name the units to use"
368
                    },
369
                    "Double"
370
            );
371
        }
372

    
373
        @Override
374
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
375
            int units = 0;
376
            IProjection proj = null;
377
            Geometry geom = getGeom(args, 0);
378
            switch( args.length ) {
379
                case 2:
380
                    units = getUnits(args, 1);
381
                    break;
382
                case 3:
383
                    proj = getProjection(args, 1);
384
                    units = getUnits(args, 2);
385
                    break;
386
            }
387
            if (proj == null) {
388
                proj = geom.getProjection();
389
            }
390
            AreaAndPerimeterCalculator calculator = new AreaAndPerimeterCalculator();
391
            double area = calculator.perimeter(geom, proj, units);
392
            return area;
393
        }
394
    }
395

    
396
    private class PropertyFunction extends AbstractFunction {
397

    
398
        public PropertyFunction() {
399
            super(
400
                    "Project",
401
                    "property",
402
                    Range.between(2, 3),
403
                    "Access to a property value in a properties file. If the"
404
                    + "indicated filename is not absolute, access it relative"
405
                    + "to the project.",
406
                    "property({{filename}}, name, defaultValue)",
407
                    new String[]{
408
                        "filename - String value with the name of the properties file",
409
                        "name - String value with the name of the property to retrieve from the file",
410
                        "defaultValue - Optional. Default value if can't access the file or the property",},
411
                    "String"
412
            );
413
        }
414

    
415
        @Override
416
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
417
            String filename = getStr(args, 0);
418
            String name = getStr(args, 1);
419
            String defaultValue = null;
420
            if (args.length == 3) {
421
                defaultValue = getStr(args, 2);
422
            }
423

    
424
            File file = new File(filename);
425
            if (!file.isAbsolute()) {
426
                Project project = currentProject.get();
427
                if (project.getFile() == null) {
428
                    return defaultValue;
429
                }
430
                file = new File(project.getFile().getParent(), filename);
431
            }
432
            Map<File, Properties> x = propertiesFiles.get();
433
            Properties properties = x.get(file);
434
            if (properties == null) {
435
                properties = new Properties();
436
                FileInputStream in = null;
437
                try {
438
                    in = new FileInputStream(file);
439
                    properties.load(in);
440
                } catch (Exception ex) {
441
                    return defaultValue;
442
                } finally {
443
                    IOUtils.closeQuietly(in);
444
                }
445
                x.put(file, properties);
446
            }
447
            String value = properties.getProperty(name, defaultValue);
448
            return value;
449
        }
450

    
451
    }
452

    
453
    ProjectValue currentProject = new ProjectValue();
454
    CurrentViewValue currentView = new CurrentViewValue();
455
    CurrentViewEnvelopeValue currentViewEnvelope = new CurrentViewEnvelopeValue();
456
    PropertiesValue propertiesFiles = new PropertiesValue();
457

    
458
    @SuppressWarnings("OverridableMethodCallInConstructor")
459
    public ProjectSymbolTable() {
460
        super("Project");
461
        this.addFunction(new CurrentProjectFunction());
462
        this.addFunction(new FirstSelectedFeatureFunction());
463
        this.addFunction(new FirstFeatureFunction());
464
        this.addFunction(new ViewFunction());
465
        this.addFunction(new ViewBBoxFunction());
466
        this.addFunction(new PropertyFunction());
467
        this.addFunction(new AreaFunction());
468
        this.addFunction(new PerimeterFunction());
469
    }
470

    
471
    private MapContext getMapContext(Feature feature) {
472
        FeatureStore store = feature.getStore();
473
        Project project = ProjectManager.getInstance().getCurrentProject();
474
        project.getDocuments(ViewManager.TYPENAME);
475
        for (Document document : project.getDocuments(ViewManager.TYPENAME)) {
476
            ViewDocument view = (ViewDocument) document;
477
            MapContext mapContext = view.getMapContext();
478
            FLayer layer = getLayer(mapContext, store);
479
            if (layer != null) {
480
                return mapContext;
481
            }
482
        }
483
        return null;
484
    }
485

    
486
    private FLayer getLayer(MapContext mapContext, FeatureStore store) {
487
        Iterator<FLayer> it = mapContext.deepiterator();
488
        while (it.hasNext()) {
489
            FLayer layer = it.next();
490
            if (layer instanceof FLyrVect) {
491
                FeatureStore layer_store = ((FLyrVect) layer).getFeatureStore();
492
                if (layer_store == store) {
493
                    return layer;
494
                }
495
            }
496
        }
497
        return null;
498
    }
499

    
500
    private IProjection getProjection(Object[] args, int i) {
501
        Object value = args[i];
502
        if (value == null) {
503
            return null;
504
        }
505
        if (value instanceof IProjection) {
506
            return (IProjection) value;
507
        }
508
        String code = value.toString();
509
        return CRSFactory.getCRS(code);
510
    }
511

    
512
    private int getUnits(Object[] args, int i) {
513
        Object value = args[i];
514
        if (value == null) {
515
            throw new IllegalArgumentException("Illegal unit value 'null'");
516
        }
517
        if (value instanceof Number) {
518
            return ((Number) value).intValue();
519
        }
520
        String name = value.toString();
521
        String[] names = MapContext.getAreaAbbr();
522
        for (int j = 0; j < names.length; j++) {
523
            if (name.equalsIgnoreCase(names[j])) {
524
                return j;
525
            }
526
        }
527
        names = MapContext.getAreaNames();
528
        for (int j = 0; j < names.length; j++) {
529
            if (name.equalsIgnoreCase(names[j])) {
530
                return j;
531
            }
532
        }
533
        throw new IllegalArgumentException("Illegal unit name '" + name + "'");
534
    }
535

    
536
    public static void selfRegister() {
537
        ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager();
538
        manager.registerSymbolTable(new ProjectSymbolTable(), true);
539
    }
540
}