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 |
} |