KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jmeter > testbeans > gui > WrapperEditor


1 // $Header: /home/cvs/jakarta-jmeter/src/core/org/apache/jmeter/testbeans/gui/WrapperEditor.java,v 1.8 2004/02/10 21:24:01 jsalvata Exp $
2
/*
3  * Copyright 2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.jmeter.testbeans.gui;
18
19 import java.awt.Component JavaDoc;
20 import java.beans.PropertyChangeEvent JavaDoc;
21 import java.beans.PropertyChangeListener JavaDoc;
22 import java.beans.PropertyEditor JavaDoc;
23 import java.beans.PropertyEditorSupport JavaDoc;
24
25 import javax.swing.JOptionPane JavaDoc;
26
27 import org.apache.jmeter.util.JMeterUtils;
28 import org.apache.jorphan.logging.LoggingManager;
29 import org.apache.log.Logger;
30
31 /**
32  * This is an implementation of a full-fledged property editor, providing
33  * both object-text transformation and an editor GUI (a custom editor
34  * component), from two simpler property editors providing only one
35  * of these functionalities each, namely:
36  * <dl>
37  * <dt>typeEditor<dt>
38  * <dd>Provides suitable object-to-string and string-to-object
39  * transformation for the property's type. That is: it's a simple editor
40  * that only need to support the set/getAsText and set/getValue methods.</dd>
41  * <dt>guiEditor</dt>
42  * <dd>Provides a suitable GUI for the property, but works on
43  * [possibly null] String values. That is: it supportsCustomEditor, but
44  * get/setAsText and get/setValue are indentical.</dd>
45  * </dl>
46  * <p>
47  * The resulting editor provides optional support for null values (you
48  * can choose whether <b>null</b> is to be a valid property value).
49  * It also provides optional support for JMeter 'expressions' (you can
50  * choose whether they make valid property values).
51  *
52  * @author <a HREF="mailto:jsalvata@apache.org">Jordi Salvat i Alabart</a>
53  * @version $Revision: 1.8 $ updated on $Date: 2004/02/10 21:24:01 $
54  */

55 class WrapperEditor extends PropertyEditorSupport JavaDoc
56         implements PropertyChangeListener JavaDoc
57 {
58     protected static Logger log= LoggingManager.getLoggerForClass();
59
60     /**
61      * The type's property editor.
62      */

63     PropertyEditor JavaDoc typeEditor;
64     
65     /**
66      * The gui property editor
67      */

68     PropertyEditor JavaDoc guiEditor;
69
70     /**
71      * Whether to allow <b>null</b> as a property value.
72      */

73     boolean acceptsNull;
74     
75     /**
76      * Whether to allow JMeter 'expressions' as property values.
77      */

78     boolean acceptsExpressions;
79
80     /**
81      * Whether to allow any constant values different from the provided tags.
82      */

83     boolean acceptsOther;
84
85     /**
86      * Keep track of the last valid value in the editor, so that we can
87      * revert to it if the user enters an invalid value.
88      */

89     private String JavaDoc lastValidValue= null;
90
91     /**
92      * Constructor for use when a PropertyEditor is delegating to us.
93      */

94     WrapperEditor(
95             Object JavaDoc source,
96             PropertyEditor JavaDoc typeEditor,
97             PropertyEditor JavaDoc guiEditor,
98             boolean acceptsNull,
99             boolean acceptsExpressions,
100             boolean acceptsOther,
101             Object JavaDoc defaultValue)
102     {
103         super(source);
104         initialize(typeEditor, guiEditor, acceptsNull, acceptsExpressions,
105             acceptsOther, defaultValue);
106     }
107
108     /**
109      * Constructor for use for regular instantiation and by subclasses.
110      */

111     WrapperEditor(
112             PropertyEditor JavaDoc typeEditor,
113             PropertyEditor JavaDoc guiEditor,
114             boolean acceptsNull,
115             boolean acceptsExpressions,
116             boolean acceptsOther,
117             Object JavaDoc defaultValue)
118     {
119         super();
120         initialize(typeEditor, guiEditor, acceptsNull, acceptsExpressions,
121             acceptsOther, defaultValue);
122     }
123
124     private void initialize(
125             PropertyEditor JavaDoc typeEditor,
126             PropertyEditor JavaDoc guiEditor,
127             boolean acceptsNull,
128             boolean acceptsExpressions,
129             boolean acceptsOther,
130             Object JavaDoc defaultValue)
131     {
132         this.typeEditor= typeEditor;
133         this.guiEditor= guiEditor;
134         this.acceptsNull= acceptsNull;
135         this.acceptsExpressions= acceptsExpressions;
136         this.acceptsOther= acceptsOther;
137
138         setValue(defaultValue);
139         lastValidValue= getAsText();
140
141         if (guiEditor instanceof ComboStringEditor)
142         {
143             String JavaDoc[] tags= ((ComboStringEditor)guiEditor).getTags();
144
145             // Provide an initial edit value if necessary -- this is an
146
// heuristic that tries to provide the most convenient
147
// initial edit value:
148

149             String JavaDoc v;
150             if (! acceptsOther) v="${}";
151             else if (isValidValue("")) v= "";
152             else if (acceptsExpressions) v= "${}";
153             else if (tags != null && tags.length>0) v= tags[0];
154             else v= getAsText();
155
156             ((ComboStringEditor)guiEditor).setInitialEditValue(v);
157         }
158
159         guiEditor.addPropertyChangeListener(this);
160     }
161
162     public boolean supportsCustomEditor()
163     {
164         return true;
165     }
166
167     public Component JavaDoc getCustomEditor()
168     {
169         return guiEditor.getCustomEditor();
170     }
171
172     public String JavaDoc[] getTags()
173     {
174         return guiEditor.getTags();
175     }
176
177     /**
178      * Determine wheter a string is one of the known tags.
179      *
180      * @param text
181      * @return true iif text equals one of the getTags()
182      */

183     private boolean isATag(String JavaDoc text)
184     {
185         String JavaDoc[] tags= getTags();
186         if (tags == null) return false;
187         for (int i=0; i<tags.length; i++)
188         {
189             if (tags[i].equals(text)) return true;
190         }
191         return false;
192     }
193     
194     /**
195      * Determine whether a string is a valid value for the property.
196      *
197      * @param text the value to be checked
198      * @return true iif text is a valid value
199      */

200     private boolean isValidValue(String JavaDoc text)
201     {
202         if (text == null) return acceptsNull;
203
204         if (acceptsExpressions && isExpression(text)) return true;
205
206         // Not an expression (isn't or can't be), not null.
207

208         // The known tags are assumed to be valid:
209
if (isATag(text)) return true;
210         
211         // Was not a tag, so if we can't accept other values...
212
if (! acceptsOther) return false;
213         
214         // Delegate the final check to the typeEditor:
215
try
216         {
217             typeEditor.setAsText(text);
218         }
219         catch (IllegalArgumentException JavaDoc e1)
220         {
221             // setAsText failed: not valid
222
return false;
223         }
224         // setAsText succeeded: valid
225
return true;
226     }
227
228     /**
229      * This method is used to do some low-cost defensive programming:
230      * it is called when a condition that the program logic should prevent
231      * from happening occurs. I hope this will help early detection of
232      * logical bugs in property value handling.
233      *
234      * @throws Error always throws an error.
235      */

236     private final void shouldNeverHappen() throws Error JavaDoc
237     {
238         throw new Error JavaDoc(); // Programming error: bail out.
239
}
240
241     /**
242      * Same as shouldNeverHappen(), but provide a source exception.
243      *
244      * @param e the exception that helped identify the problem
245      * @throws Error always throws one.
246      */

247     private final void shouldNeverHappen(Exception JavaDoc e) throws Error JavaDoc
248     {
249         throw new Error JavaDoc(e.toString()); // Programming error: bail out.
250
}
251
252     /**
253      * Check if a string is a valid JMeter 'expression'.
254      * <p>
255      * The current implementation is very basic: it just accepts any
256      * string containing "${" as a valid expression.
257      * TODO: improve, but keep returning true for "${}".
258      */

259     private final boolean isExpression(String JavaDoc text)
260     {
261         return text.indexOf("${") != -1;
262     }
263
264     /**
265      * Same as isExpression(String).
266      *
267      * @param text
268      * @return true iif text is a String and isExpression(text).
269      */

270     private final boolean isExpression(Object JavaDoc text)
271     {
272         return text instanceof String JavaDoc && isExpression((String JavaDoc)text);
273     }
274
275     /**
276      * @see java.beans.PropertyEditor#getValue()
277      * @see org.apache.jmeter.testelement.property.JMeterProperty
278      */

279     public Object JavaDoc getValue()
280     {
281         String JavaDoc text= (String JavaDoc)guiEditor.getValue();
282     
283         Object JavaDoc value;
284
285         if (text == null)
286         {
287             if (!acceptsNull) shouldNeverHappen();
288             value= null;
289         }
290         else
291         {
292             if (acceptsExpressions && isExpression(text))
293             {
294                 value= text;
295             }
296             else
297             {
298                 // not an expression (isn't or can't be), not null.
299

300                 // a check, just in case:
301
if (! acceptsOther && ! isATag(text)) shouldNeverHappen();
302
303                 try
304                 {
305                     typeEditor.setAsText(text);
306                 }
307                 catch (IllegalArgumentException JavaDoc e)
308                 {
309                     shouldNeverHappen(e);
310                 }
311                 value= typeEditor.getValue();
312             }
313         }
314     
315         if (log.isDebugEnabled())
316         {
317             log.debug(
318                 "->"
319                     + (value != null ? value.getClass().getName() : "NULL")
320                     + ":"
321                     + value);
322         }
323         return value;
324     }
325
326     public void setValue(Object JavaDoc value)
327     {
328         String JavaDoc text;
329
330         if (log.isDebugEnabled())
331         {
332             log.debug(
333                 "<-"
334                     + (value != null ? value.getClass().getName() : "NULL")
335                     + ":"
336                     + value);
337         }
338
339         if (value == null)
340         {
341             if (!acceptsNull) throw new IllegalArgumentException JavaDoc();
342             text= null;
343         }
344         else if (acceptsExpressions && isExpression(value))
345         {
346             text= (String JavaDoc)value;
347         }
348         else
349         {
350             // Not an expression (isn't or can't be), not null.
351
typeEditor.setValue(value); // may throw IllegalArgumentExc.
352
text= typeEditor.getAsText();
353             
354             if (! acceptsOther && ! isATag(text)) throw new IllegalArgumentException JavaDoc();
355         }
356
357         guiEditor.setValue(text);
358     }
359
360     public String JavaDoc getAsText()
361     {
362         String JavaDoc text= guiEditor.getAsText();
363     
364         if (text == null)
365         {
366             if (!acceptsNull) shouldNeverHappen();
367         }
368         else if (!acceptsExpressions || !isExpression(text))
369         {
370             // not an expression (can't be or isn't), not null.
371
try
372             {
373                 typeEditor.setAsText(text);
374             }
375             catch (IllegalArgumentException JavaDoc e)
376             {
377                 shouldNeverHappen(e);
378             }
379             text= typeEditor.getAsText();
380
381             // a check, just in case:
382
if (! acceptsOther && ! isATag(text)) shouldNeverHappen();
383         }
384     
385         if (log.isDebugEnabled())
386         {
387             log.debug("->\"" + text + "\"");
388         }
389         return text;
390     }
391
392     public void setAsText(String JavaDoc text) throws IllegalArgumentException JavaDoc
393     {
394         if (log.isDebugEnabled())
395         {
396             log.debug(text == null ? "<-null" : "<-\"" + text + "\"");
397         }
398             
399         String JavaDoc value;
400
401         if (text == null)
402         {
403             if (! acceptsNull) throw new IllegalArgumentException JavaDoc();
404             value= null;
405         }
406         else
407         {
408             if (acceptsExpressions && isExpression(text))
409             {
410                 value= text;
411             }
412             else
413             {
414                 // Some editors do tiny transformations (e.g. "true" to "True",...):
415
typeEditor.setAsText(text); // may throw IllegalArgumentException
416
value= typeEditor.getAsText();
417                 
418                 if (! acceptsOther && ! isATag(text)) throw new IllegalArgumentException JavaDoc();
419             }
420         }
421
422         guiEditor.setValue(value);
423     }
424
425     public void propertyChange(PropertyChangeEvent JavaDoc event)
426     {
427         String JavaDoc text= guiEditor.getAsText();
428         if (isValidValue(text))
429         {
430             lastValidValue= text;
431             firePropertyChange();
432         }
433         else
434         {
435             // TODO: how to bring the editor back in view & focus?
436
JOptionPane.showMessageDialog(
437                 guiEditor.getCustomEditor().getParent(),
438                 JMeterUtils.getResString("property_editor.value_is_invalid_message"),
439                 JMeterUtils.getResString("property_editor.value_is_invalid_title"),
440                 JOptionPane.WARNING_MESSAGE);
441
442             // Revert to the previous value:
443
guiEditor.setAsText(lastValidValue);
444         }
445     }
446 }
Popular Tags