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 @ 43999

History | View | Annotate | Download (17.5 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.project.documents.Document;
13
import org.gvsig.app.project.documents.view.ViewDocument;
14
import org.gvsig.app.project.documents.view.ViewManager;
15
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
16
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
17
import org.gvsig.expressionevaluator.Interpreter;
18
import org.gvsig.expressionevaluator.spi.AbstractFunction;
19
import org.gvsig.expressionevaluator.spi.AbstractSymbolTable;
20
import org.gvsig.fmap.crs.CRSFactory;
21
import org.gvsig.fmap.dal.feature.Feature;
22
import org.gvsig.fmap.dal.feature.FeatureQuery;
23
import org.gvsig.fmap.dal.feature.FeatureSelection;
24
import org.gvsig.fmap.dal.feature.FeatureSet;
25
import org.gvsig.fmap.dal.feature.FeatureStore;
26
import org.gvsig.fmap.geom.Geometry;
27
import org.gvsig.fmap.mapcontext.MapContext;
28
import org.gvsig.fmap.mapcontext.layers.FLayer;
29
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
30
import org.gvsig.fmap.mapcontrol.AreaAndPerimeterCalculator;
31

    
32
/**
33
 *
34
 * @author jjdelcerro
35
 */
36
@SuppressWarnings("UseSpecificCatch")
37
public class ProjectSymbolTable extends AbstractSymbolTable {
38

    
39
    private abstract class CachedValue<T> {
40

    
41
        T value = null;
42
        long lastAccess = 0;
43

    
44
        protected abstract void reload();
45

    
46
        public boolean isExpired() {
47
            long now = System.currentTimeMillis();
48
            return now - lastAccess > 3000;
49
        }
50

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

    
60
    private class ProjectValue extends CachedValue<Project> {
61

    
62
        @Override
63
        protected void reload() {
64
            value = ProjectManager.getInstance().getCurrentProject();
65
        }
66

    
67
    }
68

    
69
    private class PropertiesValue extends CachedValue<Map<File, Properties>> {
70

    
71
        @Override
72
        protected void reload() {
73
            value = new HashMap<>();
74
        }
75
    }
76

    
77
    private class CurrentProjectFunction extends AbstractFunction {
78

    
79
        public CurrentProjectFunction() {
80
            super(
81
                    "Project",
82
                    "project",
83
                    Range.is(0),
84
                    "Access to the current project loaded in gvSIG desktop.\n",
85
                    "project()",
86
                    null,
87
                    "Project"
88
            );
89
        }
90

    
91
        @Override
92
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
93
            return currentProject.get();
94
        }
95

    
96
    }
97

    
98
    private class FirstSelectedFeatureFunction extends AbstractFunction {
99

    
100
        public FirstSelectedFeatureFunction() {
101
            super(
102
                    "Project",
103
                    "firstSelectedFeature",
104
                    Range.between(3, 4),
105
                    "Access to the first selected feature of the layer, and "
106
                    + "return the value of the attribute.",
107
                    "firstSelectedFeature({{view}}, layer, attribute, defaulValue)",
108
                    new String[]{
109
                        "view - String value with the name of a view",
110
                        "layer - String value with the name of a layer in the indicated view",
111
                        "attribute - String value with the name of the attribute in the indicated layer",
112
                        "defaultValue - Optional. Value to use if the indicated "
113
                        + "attribute can not be accessed. For example, if the "
114
                        + "view or layer does not exist, or it does not have "
115
                        + "selected elements."
116
                    },
117
                    "Object"
118
            );
119
        }
120

    
121
        @Override
122
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
123
            Object defaultValue = null;
124
            String viewName = getStr(args, 0);
125
            String layerName = getStr(args, 1);
126
            String attrName = getStr(args, 2);
127
            if (args.length == 4) {
128
                defaultValue = getObject(args, 3);
129
            }
130
            try {
131
                Project project = currentProject.get();
132
                ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
133
                if (view == null) {
134
                    return defaultValue;
135
                }
136
                FLayer layer = view.getLayer(layerName);
137
                if (!(layer instanceof FLyrVect)) {
138
                    return defaultValue;
139
                }
140
                FeatureSelection selection = ((FLyrVect) layer).getFeatureStore().getFeatureSelection();
141
                if (selection == null || selection.isEmpty()) {
142
                    return defaultValue;
143
                }
144
                Feature feature = selection.first();
145
                if (feature == null) {
146
                    return defaultValue;
147
                }
148
                return feature.get(attrName);
149
            } catch (Exception ex) {
150
                return defaultValue;
151
            }
152
        }
153

    
154
    }
155

    
156
    private class FirstFeatureFunction extends AbstractFunction {
157

    
158
        public FirstFeatureFunction() {
159
            super(
160
                    "Project",
161
                    "firstFeature",
162
                    Range.between(3, 6),
163
                    "Access to the first feature of the layer, and "
164
                    + "return the value of the attribute.",
165
                    "firstFeature({{view}}, layer, attribute, filter, order, defaulValue)",
166
                    new String[]{
167
                        "view - String value with the name of a view",
168
                        "layer - String value with the name of a layer in the indicated view",
169
                        "attribute - String value with the name of the attribute in the indicated layer",
170
                        "filter - Optional. String value with a filter expression",
171
                        "order - Optional. String value with the order. must be a string with the names of separate fields with commas",
172
                        "defaultValue - Optional. Value to use if the indicated "
173
                        + "attribute can not be accessed. For example, if the "
174
                        + "view or layer does not exist."
175
                    },
176
                    "Object"
177
            );
178
        }
179

    
180
        @Override
181
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
182
            Object defaultValue = null;
183
            String filter = null;
184
            String order = null;
185
            String viewName = getStr(args, 0);
186
            String layerName = getStr(args, 1);
187
            String attrName = getStr(args, 2);
188
            switch (args.length) {
189
                case 4:
190
                    filter = getStr(args, 3);
191
                    break;
192
                case 5:
193
                    filter = getStr(args, 3);
194
                    order = getStr(args, 4);
195
                    break;
196
                case 6:
197
                    filter = getStr(args, 3);
198
                    order = getStr(args, 4);
199
                    defaultValue = getObject(args, 6);
200
                    break;
201
            }
202
            try {
203
                Project project = currentProject.get();
204
                ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
205
                if (view == null) {
206
                    return defaultValue;
207
                }
208
                FLayer layer = view.getLayer(layerName);
209
                if (!(layer instanceof FLyrVect)) {
210
                    return defaultValue;
211
                }
212
                FeatureStore store = ((FLyrVect) layer).getFeatureStore();
213
                FeatureSet set;
214
                if (filter == null && order == null) {
215
                    set = store.getFeatureSet();
216
                } else {
217
                    FeatureQuery query = store.createFeatureQuery();
218
                    if (filter != null) {
219
                        query.addFilter(filter);
220
                    }
221
                    if (order != null) {
222
                        query.getOrder().add(order);
223
                    }
224
                    set = store.getFeatureSet(query);
225
                }
226
                Feature feature = set.first();
227
                if (feature == null) {
228
                    return defaultValue;
229
                }
230
                return feature.get(attrName);
231
            } catch (Exception ex) {
232
                return defaultValue;
233
            }
234
        }
235

    
236
    }
237

    
238
    private class ViewFunction extends AbstractFunction {
239

    
240
        public ViewFunction() {
241
            super(
242
                    "Project",
243
                    "view",
244
                    Range.is(1),
245
                    "Access to the indicated view",
246
                    "view({{viewName}})",
247
                    new String[]{
248
                        "view - String value with the name of a view"
249
                    },
250
                    "DocumentView"
251
            );
252
        }
253

    
254
        @Override
255
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
256
            String viewName = getStr(args, 0);
257
            Project project = currentProject.get();
258
            ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
259
            return view;
260
        }
261

    
262
    }
263

    
264
    private class AreaFunction extends AbstractFunction {
265

    
266
        public AreaFunction() {
267
            super(
268
                    "Project",
269
                    "Area",
270
                    Range.between(2,3),
271
                    "Calculate the area of the geometry in the indicated units",
272
                    "Area({{geometry}}, \"m\")",
273
                    new String[]{
274
                        "geometry - Geometry",
275
                        "Projection - Optional. Projection of the geometry or a string with the projection name",
276
                        "units - String value with the name the units to use"
277
                    },
278
                    "Double"
279
            );
280
        }
281

    
282
        @Override
283
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
284
            int units = 0;
285
            IProjection proj = null;
286
            Geometry geom = getGeom(args, 0);
287
            switch( args.length ) {
288
                case 2:
289
                    units = getUnits(args, 1);
290
                    break;
291
                case 3:
292
                    proj = getProjection(args, 1);
293
                    units = getUnits(args, 2);
294
                    break;
295
            }
296
            if (proj == null) {
297
                proj = geom.getProjection();
298
            }
299
            AreaAndPerimeterCalculator calculator = new AreaAndPerimeterCalculator();
300
            double area = calculator.area(geom, proj, units);
301
            return area;
302
        }
303
    }
304

    
305
    private class PerimeterFunction extends AbstractFunction {
306

    
307
        public PerimeterFunction() {
308
            super(
309
                    "Project",
310
                    "Perimeter",
311
                    Range.between(2,3),
312
                    "Calculate the perimeter of the geometry in the indicated units",
313
                    "Perimeter({{geometry}}, \"m\")",
314
                    new String[]{
315
                        "geometry - Geometry",
316
                        "Projection - Optional. Projection of the geometry or a string with the projection name",
317
                        "units - String value with the name the units to use"
318
                    },
319
                    "Double"
320
            );
321
        }
322

    
323
        @Override
324
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
325
            int units = 0;
326
            IProjection proj = null;
327
            Geometry geom = getGeom(args, 0);
328
            switch( args.length ) {
329
                case 2:
330
                    units = getUnits(args, 1);
331
                    break;
332
                case 3:
333
                    proj = getProjection(args, 1);
334
                    units = getUnits(args, 2);
335
                    break;
336
            }
337
            if (proj == null) {
338
                proj = geom.getProjection();
339
            }
340
            AreaAndPerimeterCalculator calculator = new AreaAndPerimeterCalculator();
341
            double area = calculator.perimeter(geom, proj, units);
342
            return area;
343
        }
344
    }
345

    
346
    private class PropertyFunction extends AbstractFunction {
347

    
348
        public PropertyFunction() {
349
            super(
350
                    "Project",
351
                    "property",
352
                    Range.between(2, 3),
353
                    "Access to a property value in a properties file. If the"
354
                    + "indicated filename is not absolute, access it relative"
355
                    + "to the project.",
356
                    "property({{filename}}, name, defaultValue)",
357
                    new String[]{
358
                        "filename - String value with the name of the properties file",
359
                        "name - String value with the name of the property to retrieve from the file",
360
                        "defaultValue - Optional. Default value if can't access the file or the property",},
361
                    "String"
362
            );
363
        }
364

    
365
        @Override
366
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
367
            String filename = getStr(args, 0);
368
            String name = getStr(args, 1);
369
            String defaultValue = null;
370
            if (args.length == 3) {
371
                defaultValue = getStr(args, 2);
372
            }
373

    
374
            File file = new File(filename);
375
            if (!file.isAbsolute()) {
376
                Project project = currentProject.get();
377
                if (project.getFile() == null) {
378
                    return defaultValue;
379
                }
380
                file = new File(project.getFile().getParent(), filename);
381
            }
382
            Map<File, Properties> x = propertiesFiles.get();
383
            Properties properties = x.get(file);
384
            if (properties == null) {
385
                properties = new Properties();
386
                FileInputStream in = null;
387
                try {
388
                    in = new FileInputStream(file);
389
                    properties.load(in);
390
                } catch (Exception ex) {
391
                    return defaultValue;
392
                } finally {
393
                    IOUtils.closeQuietly(in);
394
                }
395
                x.put(file, properties);
396
            }
397
            String value = properties.getProperty(name, defaultValue);
398
            return value;
399
        }
400

    
401
    }
402

    
403
    ProjectValue currentProject = new ProjectValue();
404
    PropertiesValue propertiesFiles = new PropertiesValue();
405

    
406
    @SuppressWarnings("OverridableMethodCallInConstructor")
407
    public ProjectSymbolTable() {
408
        super("Project");
409
        this.addFunction(new CurrentProjectFunction());
410
        this.addFunction(new FirstSelectedFeatureFunction());
411
        this.addFunction(new FirstFeatureFunction());
412
        this.addFunction(new ViewFunction());
413
        this.addFunction(new PropertyFunction());
414
        this.addFunction(new AreaFunction());
415
        this.addFunction(new PerimeterFunction());
416
    }
417

    
418
    private MapContext getMapContext(Feature feature) {
419
        FeatureStore store = feature.getStore();
420
        Project project = ProjectManager.getInstance().getCurrentProject();
421
        project.getDocuments(ViewManager.TYPENAME);
422
        for (Document document : project.getDocuments(ViewManager.TYPENAME)) {
423
            ViewDocument view = (ViewDocument) document;
424
            MapContext mapContext = view.getMapContext();
425
            FLayer layer = getLayer(mapContext, store);
426
            if (layer != null) {
427
                return mapContext;
428
            }
429
        }
430
        return null;
431
    }
432

    
433
    private FLayer getLayer(MapContext mapContext, FeatureStore store) {
434
        Iterator<FLayer> it = mapContext.deepiterator();
435
        while (it.hasNext()) {
436
            FLayer layer = it.next();
437
            if (layer instanceof FLyrVect) {
438
                FeatureStore layer_store = ((FLyrVect) layer).getFeatureStore();
439
                if (layer_store == store) {
440
                    return layer;
441
                }
442
            }
443
        }
444
        return null;
445
    }
446

    
447
    private IProjection getProjection(Object[] args, int i) {
448
        Object value = args[i];
449
        if (value == null) {
450
            return null;
451
        }
452
        if (value instanceof IProjection) {
453
            return (IProjection) value;
454
        }
455
        String code = value.toString();
456
        return CRSFactory.getCRS(code);
457
    }
458

    
459
    private int getUnits(Object[] args, int i) {
460
        Object value = args[i];
461
        if (value == null) {
462
            throw new IllegalArgumentException("Illegal unit value 'null'");
463
        }
464
        if (value instanceof Number) {
465
            return ((Number) value).intValue();
466
        }
467
        String name = value.toString();
468
        String[] names = MapContext.getAreaAbbr();
469
        for (int j = 0; j < names.length; j++) {
470
            if (name.equalsIgnoreCase(names[j])) {
471
                return j;
472
            }
473
        }
474
        names = MapContext.getAreaNames();
475
        for (int j = 0; j < names.length; j++) {
476
            if (name.equalsIgnoreCase(names[j])) {
477
                return j;
478
            }
479
        }
480
        throw new IllegalArgumentException("Illegal unit name '" + name + "'");
481
    }
482

    
483
    public static void selfRegister() {
484
        ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager();
485
        manager.registerSymbolTable(new ProjectSymbolTable(), true);
486
    }
487
}