Revision 44154

View differences:

trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.impl/src/main/java/org/gvsig/fmap/dal/impl/expressionevaluator/DefaultFeatureAttributeEmulatorExpression.java
46 46
    private boolean valid;
47 47
    private String errorMessage;
48 48
    
49
    private boolean enableExceptions;
50
    
49 51
    private FilteredLogger logger;
50 52
    
51 53
    public DefaultFeatureAttributeEmulatorExpression() {
......
54 56
    public DefaultFeatureAttributeEmulatorExpression(FeatureType featureType, Expression expression) {
55 57
        this.expression = expression;
56 58
        this.checkVars(featureType);
59
        this.enableExceptions = false;
57 60
    }
58 61

  
59 62
    private FilteredLogger getLogger() {
......
95 98
        this.requiredFields = theUsedFields.toArray(new String[theUsedFields.size()]);
96 99
    }
97 100

  
101
    public boolean isEnableExceptions() {
102
        return enableExceptions;
103
    }
104

  
105
    public void setEnableExceptions(boolean enableExceptions) {
106
        this.enableExceptions = enableExceptions;
107
    }
108

  
98 109
    @Override
99 110
    public SymbolTable getSymbolTable() {
100 111
        if (this.symbolTable == null) {
......
130 141
            Object result = this.expression.execute(this.getSymbolTable());
131 142
            return result;
132 143
        } catch(Exception ex) {
144
            if( this.enableExceptions ) {
145
                throw ex;
146
            }
133 147
            this.getLogger().warn("Problems evaluating expression '"+this.expression.getPhrase()+"' with feature '"+feature.getReference().toString()+"'.", ex);
134 148
            return null;
135 149
        }
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.swing/org.gvsig.fmap.dal.swing.impl/src/main/java/org/gvsig/fmap/dal/swing/impl/featuretype/DefaultFeatureTypeAttributePanel.java
12 12
import javax.swing.SwingUtilities;
13 13
import javax.swing.event.ChangeEvent;
14 14
import javax.swing.event.ChangeListener;
15
import org.apache.commons.lang3.ArrayUtils;
15 16
import org.apache.commons.lang3.StringUtils;
16 17
import org.cresques.cts.IProjection;
17 18
import org.gvsig.expressionevaluator.Expression;
......
304 305
                default:
305 306
                    break;
306 307
            }
308
            descriptor.setDataProfileName(
309
                StringUtils.defaultIfBlank((String) this.cboDataProfile.getSelectedItem(),null)
310
            );
311

  
307 312
            if( this.chkVirtualField.isSelected() && this.pickerVirtualField.isEnabled() ) {
308 313
                Expression expression = this.pickerVirtualField.get();
309 314
                if( expression==null ) {
......
314 319
                            descriptor.getFeatureType(),
315 320
                            expression
316 321
                    );
317
                    descriptor.setFeatureAttributeEmulator(emulator);
322
                    if( !emulator.isValid() ) {
323
                        ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
324
                        dialogs.messageDialog(
325
                                i18n.getTranslation("_The_expression_of_virtual_field_is_not_valid")+
326
                                    "\n"+
327
                                    emulator.getErrorMessage(), 
328
                                i18n.getTranslation("_Warning"), 
329
                                JOptionPane.WARNING_MESSAGE
330
                        );
331
                        return null;
332
                    }
333
                    for (String requiredFieldName : emulator.getRequiredFieldNames()) {
334
                        if( StringUtils.equalsIgnoreCase(requiredFieldName, descriptor.getName()) ) {
335
                            ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
336
                            dialogs.messageDialog(
337
                                    i18n.getTranslation("_The_expression_of_virtual_field_is_not_valid")+
338
                                        "\n\n"+
339
                                        i18n.getTranslation("_The_expression_contains_a_reference_to_itself"), 
340
                                    i18n.getTranslation("_Warning"), 
341
                                    JOptionPane.WARNING_MESSAGE
342
                            );
343
                            return null;
344
                        }
345
                    }
346
                    //
347
                    // No se porque esto de abajo no funciona.
348
                    // Nunca se lanza la excepcion en el get(Feature) de
349
                    // DefaultFeatureAttributeEmulatorExpression.
350
                    //
351
//                    try {
352
//                        emulator.setEnableExceptions(true);
353
//                        descriptor.setFeatureAttributeEmulator(emulator);
354
//                        this.pickerVirtualField.getPreviewSymbolTable().value(descriptor.getName());
355
//                    } catch(Throwable ex) {
356
//                        emulator.setEnableExceptions(false);
357
//                        descriptor.setFeatureAttributeEmulator(null);
358
//                        ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
359
//                        dialogs.messageDialog(
360
//                                i18n.getTranslation("_The_expression_of_virtual_field_is_not_valid")+
361
//                                    "\n"+
362
//                                    ex.getMessage(), 
363
//                                i18n.getTranslation("_Warning"), 
364
//                                JOptionPane.WARNING_MESSAGE
365
//                        );
366
//                        return null;
367
//                    } finally {
368
//                        emulator.setEnableExceptions(false);
369
//                    }
318 370
                }
319 371
            }
320
            descriptor.setDataProfileName(
321
                StringUtils.defaultIfBlank((String) this.cboDataProfile.getSelectedItem(),null)
322
            );
323 372
        } catch (Exception ex) {
324 373
            LOGGER.warn("Can't retrieve information from user form.",ex);
325 374
            ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.api/src/main/java/org/gvsig/fmap/dal/expressionevaluator/FeatureAttributeEmulatorExpression.java
19 19

  
20 20
    public boolean isValid();
21 21
    
22
    public void setEnableExceptions(boolean enableException);
23
    
24
    public boolean isEnableExceptions();
25
    
22 26
}
trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.app/org.gvsig.app.mainplugin/src/main/resources-plugin/i18n/text.properties
1358 1358
_Tip=Sugerencia
1359 1359
_Cant_retrieve_information_from_user_form=No se puede recuperar informaci\u00f3n del formulario de usuario.
1360 1360
_See_log_for_details=Ver el registro para m\u00e1s detalles.
1361
_The_expression_of_virtual_field_is_not_valid=La expresi\u00f3n del campo virtual no es valida.
1362
_The_expression_contains_a_reference_to_itself=La expresi\u00f3n tiene una referencia a ella misma.
trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.app/org.gvsig.app.mainplugin/src/main/resources-plugin/i18n/text_en.properties
1276 1276
_Message=Message
1277 1277
_Tip=Tip
1278 1278
_Cant_retrieve_information_from_user_form=Can't retrieve information from user form.
1279
_See_log_for_details=See log for details.
1279
_See_log_for_details=See log for details.
1280
_The_expression_of_virtual_field_is_not_valid=The expression of virtual field es not valid.
1281
_The_expression_contains_a_reference_to_itself=The expression contains a reference to itself.
trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.impl/src/main/java/org/gvsig/expressionevaluator/impl/DefaultCodeBuilder.java
113 113

  
114 114
    }
115 115

  
116
    public class BaseIdentifier extends BaseCode implements Identifier {
116
    public interface RecursionControlSupport {
117
        
118
        public boolean enterCode(int max);
119
        
120
        public void exitCode();
121
        
122
        public void resetRecursionState();
123
    }
124
    
125
    private class RecursionSupport implements RecursionControlSupport {
126
    
127
        private int counter;
128
        
129
        public RecursionSupport() {
130
            this.counter = 0;
131
        }
117 132

  
118
        String name;
133
        @Override
134
        public boolean enterCode(int max) {
135
            this.counter += 1;
136
            return this.counter < max;
137
        }
119 138

  
139
        @Override
140
        public void exitCode() {
141
            this.counter -= 1;
142
        }
143

  
144
        @Override
145
        public void resetRecursionState() {
146
            this.counter = 0;
147
        }
148
        
149
    }
150
    
151
    public class BaseIdentifier extends BaseCode implements Identifier, RecursionControlSupport {
152

  
153
        private String name;
154
        private RecursionSupport recursionSupport;
155

  
120 156
        public BaseIdentifier(String name) {
121 157
            this.name = name;
158
            this.recursionSupport = new RecursionSupport();
122 159
        }
123 160

  
124 161
        @Override
......
140 177
            return builder.toString();
141 178
        }
142 179

  
180
        @Override
181
        public boolean enterCode(int max) {
182
            return this.recursionSupport.enterCode(max);
183
        }
184

  
185
        @Override
186
        public void exitCode() {
187
            this.recursionSupport.exitCode();
188
        }
189

  
190
        @Override
191
        public void resetRecursionState() {
192
            this.recursionSupport.resetRecursionState();
193
        }
194

  
143 195
    }
144 196

  
145 197
    public class BaseCodes implements Codes {
......
212 264

  
213 265
    }
214 266

  
215
    public class BaseCaller extends BaseCode implements Caller {
267
    public class BaseCaller extends BaseCode implements Caller, RecursionControlSupport {
216 268

  
217 269
        private final String name;
218 270
        private final Codes args;
219 271
        private Function function;
220 272
        private final int type;
273
        private RecursionSupport recursionSupport;
221 274

  
222 275
        public BaseCaller(String name, int type, Codes args) {
223 276
            this.name = name;
224 277
            this.args = args;
225 278
            this.type = type;
226 279
            this.function = null;
280
            this.recursionSupport = new RecursionSupport();
227 281
        }
228 282

  
229 283
        @Override
......
282 336
            return builder.toString();
283 337
        }
284 338

  
339
        @Override
340
        public boolean enterCode(int max) {
341
            return this.recursionSupport.enterCode(max);
342
        }
343

  
344
        @Override
345
        public void exitCode() {
346
            this.recursionSupport.exitCode();
347
        }
348

  
349
        @Override
350
        public void resetRecursionState() {
351
            this.recursionSupport.resetRecursionState();
352
        }
285 353
    }
286 354

  
287 355
    public class BaseMethod extends BaseCaller implements Method {
trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.impl/src/main/java/org/gvsig/expressionevaluator/impl/DefaultInterpreter.java
17 17
import org.gvsig.expressionevaluator.Codes;
18 18
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
19 19
import org.gvsig.expressionevaluator.Function;
20
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.RecursionControlSupport;
20 21
import org.gvsig.expressionevaluator.impl.function.operator.BinaryOperator;
21 22
import org.gvsig.expressionevaluator.impl.function.programming.CallMethodFunction;
22 23
import org.gvsig.expressionevaluator.impl.function.operator.UnaryOperator;
......
24 25

  
25 26
public class DefaultInterpreter implements Interpreter {
26 27

  
28
    public static int DEFAULT_MAX_RECURSION_LIMIT = 20;
29
    
27 30
    private class DefaultCache implements Cache {
28 31
        
29 32
        private Map<Pair<Object,Object>,Pair<Object,Long>> data;
......
83 86
    private Double accuracy;
84 87
    private Code currentCode;
85 88
    private Cache cache;
89
    private int maxRecursionLimit;
86 90

  
87 91
    public DefaultInterpreter() {
88 92
        this.cache = new DefaultCache();
93
        this.maxRecursionLimit = DEFAULT_MAX_RECURSION_LIMIT;
89 94
    }
90 95

  
91 96
    @Override
......
95 100
        if( this.symbolTable!=null ) {
96 101
            other.symbolTable = this.symbolTable.clone();
97 102
        }
98
        
99 103
        return other;
100 104
    }
105
    
106
    public int getMaxRecursionLimit() {
107
        return this.maxRecursionLimit;
108
    }
101 109
            
110
    public void setMaxRecursionLimit(int limit) {
111
        this.maxRecursionLimit = limit;
112
    }
113
    
102 114
    @Override
103 115
    public Cache getCache() {
104 116
        return this.cache;
......
159 171
    }
160 172

  
161 173
    public Object runCode(Code code) throws Exception {
174
        RecursionControlSupport recursionControl = null;
175
        if( code instanceof RecursionControlSupport ) {
176
            recursionControl = (RecursionControlSupport) code;
177
            if( !recursionControl.enterCode(this.maxRecursionLimit) ) {
178
                recursionControl.resetRecursionState();
179
                throw new ExpressionRuntimeException(code, I18N.Maximum_recursion_limit_exceeded());
180
            }
181
        }
182
        Object value = null;
162 183
        this.currentCode = code;
163
        Object value = null;
164
        switch( code.code() ) {
165
        case Code.CONSTANT:
166
            value = ((Constant) code).value();
167
            break;
184
        try {
185
            switch( code.code() ) {
186
            case Code.CONSTANT:
187
                value = ((Constant) code).value();
188
                break;
168 189

  
169
        case Code.IDENTIFIER:
170
            String name = ((Identifier) code).name();
171
            if( !this.getSymbolTable().exists(name) ) {
172
                throw new ExpressionRuntimeException(
173
                        code, 
174
                        I18N.Undefined_variable_XIdentifierX(name),
175
                        I18N.Use_single_quotes_to_enter_literal_strings()
176
                );
177
            }
178
            value = this.getSymbolTable().value(name);
179
            break;
190
            case Code.IDENTIFIER:
191
                String name = ((Identifier) code).name();
192
                if( !this.getSymbolTable().exists(name) ) {
193
                    throw new ExpressionRuntimeException(
194
                            code, 
195
                            I18N.Undefined_variable_XIdentifierX(name),
196
                            I18N.Use_single_quotes_to_enter_literal_strings()
197
                    );
198
                }
199
                value = this.getSymbolTable().value(name);
200
                break;
180 201

  
181
        case Code.METHOD: {
182
                Method method = (Method) code;
183
                Function function = method.function();
184
                if( function == null ) {
185
                    Object obj = this.runCode(method.obj());
186
                    if( obj == null ) {
187
                        throw new NullPointerException("An object pointer was expected to invoke method "+method.methodname()+" and a null was received");
202
            case Code.METHOD: {
203
                    Method method = (Method) code;
204
                    Function function = method.function();
205
                    if( function == null ) {
206
                        Object obj = this.runCode(method.obj());
207
                        if( obj == null ) {
208
                            throw new NullPointerException("An object pointer was expected to invoke method "+method.methodname()+" and a null was received");
209
                        }
210
                        method.function(new CallMethodFunction(obj, method.methodname()));
188 211
                    }
189
                    method.function(new CallMethodFunction(obj, method.methodname()));
190 212
                }
191
            }
192
        case Code.CALLER:
193
            Caller caller = (Caller) code;
194
            Function function = caller.function();
195
            if( function == null ) {
196
                function = this.getSymbolTable().function(caller.name());
213
            case Code.CALLER:
214
                Caller caller = (Caller) code;
215
                Function function = caller.function();
197 216
                if( function == null ) {
198
                    throw new ExpressionRuntimeException(code, I18N.Undefined_function_XIdentifierX(caller.name()));
217
                    function = this.getSymbolTable().function(caller.name());
218
                    if( function == null ) {
219
                        throw new ExpressionRuntimeException(code, I18N.Undefined_function_XIdentifierX(caller.name()));
220
                    }
221
                    caller.function(function);
199 222
                }
200
                caller.function(function);
201
            }
202
            Codes args = caller.args();
203
            try {
204
                switch( caller.type() ) {
205
                case Caller.UNARY_OPERATOR:
206
                    if( args == null || args.size() != 1 ) {
207
                        throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_operator_XIdentifierX_expected_1_got_XargcX(function.name(),args==null?0:args.size()));
208
                    }
209
                    value = ((UnaryOperator) function).call(this, runCode(args.get(0)));
210
                    break;
223
                Codes args = caller.args();
224
                try {
225
                    switch( caller.type() ) {
226
                    case Caller.UNARY_OPERATOR:
227
                        if( args == null || args.size() != 1 ) {
228
                            throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_operator_XIdentifierX_expected_1_got_XargcX(function.name(),args==null?0:args.size()));
229
                        }
230
                        value = ((UnaryOperator) function).call(this, runCode(args.get(0)));
231
                        break;
211 232

  
212
                case Caller.BINARY_OPERATOR:
213
                    if( args == null || args.size() != 2 ) {
214
                        throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_operator_XIdentifierX_expected_2_got_XargcX(function.name(),args==null?0:args.size()));
215
                    }
216
                    value = ((BinaryOperator) function).call(this, runCode(args.get(0)), runCode(args.get(1)));
217
                    break;
233
                    case Caller.BINARY_OPERATOR:
234
                        if( args == null || args.size() != 2 ) {
235
                            throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_operator_XIdentifierX_expected_2_got_XargcX(function.name(),args==null?0:args.size()));
236
                        }
237
                        value = ((BinaryOperator) function).call(this, runCode(args.get(0)), runCode(args.get(1)));
238
                        break;
218 239

  
219
                case Caller.FUNCTION:
220
                    int argc = (args == null) ? 0 : args.size();
221
                    if( !function.argc().contains(argc) ) {
222
                        throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_function_XIdentifierX_expected_XexpectedX_got_XfoundX(function.name(),function.argc(),argc));
223
                    }
224
                    if( function.useArgumentsInsteadObjects() ) {
225
                        value = function.call(this, args);
226
                    } else {
227
                        Object[] argvalues = new Object[argc];
228
                        if( args != null ) {
229
                            int i = 0;
230
                            for( Code arg : args ) {
231
                                argvalues[i++] = runCode(arg);
240
                    case Caller.FUNCTION:
241
                        int argc = (args == null) ? 0 : args.size();
242
                        if( !function.argc().contains(argc) ) {
243
                            throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_function_XIdentifierX_expected_XexpectedX_got_XfoundX(function.name(),function.argc(),argc));
244
                        }
245
                        if( function.useArgumentsInsteadObjects() ) {
246
                            value = function.call(this, args);
247
                        } else {
248
                            Object[] argvalues = new Object[argc];
249
                            if( args != null ) {
250
                                int i = 0;
251
                                for( Code arg : args ) {
252
                                    argvalues[i++] = runCode(arg);
253
                                }
232 254
                            }
255
                            value = function.call(this, argvalues);
233 256
                        }
234
                        value = function.call(this, argvalues);
235 257
                    }
258
                } catch (RuntimeException ex) {
259
                    throw ex;
260
                } catch (Exception ex) {
261
                    String argsstr = "???";
262
                    try {
263
                        argsstr = args.toString();
264
                    } catch(Exception ex2) {
265
                        // Ignore.
266
                    }
267
                    throw new ExpressionRuntimeException(code, I18N.Problems_calling_function_XIdentifierX_with_args_XargsX(function.name(),argsstr));
236 268
                }
237
            } catch (RuntimeException ex) {
238
                throw ex;
239
            } catch (Exception ex) {
240
                String argsstr = "???";
241
                try {
242
                    argsstr = args.toString();
243
                } catch(Exception ex2) {
244
                    // Ignore.
245
                }
246
                throw new ExpressionRuntimeException(code, I18N.Problems_calling_function_XIdentifierX_with_args_XargsX(function.name(),argsstr));
269
                break;
270

  
247 271
            }
248
            break;
249
            
272
        } finally {
273
            this.currentCode = null;
274
            if( recursionControl!=null ) {
275
                recursionControl.exitCode();
276
            }
250 277
        }
251
        this.currentCode = null;
252 278
        return value;
253 279
    }
254 280

  
trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.impl/src/main/java/org/gvsig/expressionevaluator/impl/I18N.java
148 148
        return "The operator 'less than or equal' is '<='.";
149 149
    }
150 150

  
151
    static String Maximum_recursion_limit_exceeded() {
152
        return "Maximum recursion limit exceeded.";
153
    }
151 154

  
155

  
152 156
}

Also available in: Unified diff