Author: sebb
Date: Mon Sep  7 20:55:39 2009
New Revision: 812274

URL: http://svn.apache.org/viewvc?rev=812274&view=rev
Log:
Add TestBean Table Editor support.
[code copied from branches/java1.5_prototype-was_trunk]

Added:
    
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java  
 (with props)
    
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java
   (with props)
Modified:
    
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/BeanInfoSupport.java
    
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/TestBeanHelper.java
    
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/GenericTestBeanCustomizer.java
    
jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/gui/ObjectTableModel.java
    jakarta/jmeter/trunk/xdocs/changes.xml

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/BeanInfoSupport.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/BeanInfoSupport.java?rev=812274&r1=812273&r2=812274&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/BeanInfoSupport.java 
(original)
+++ 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/BeanInfoSupport.java 
Mon Sep  7 20:55:39 2009
@@ -72,6 +72,8 @@
 
     public static final String NOT_OTHER = GenericTestBeanCustomizer.NOT_OTHER;
 
+    public static final String MULTILINE = "multiline";
+
     public static final String DEFAULT = GenericTestBeanCustomizer.DEFAULT;
 
     public static final String RESOURCE_BUNDLE = 
GenericTestBeanCustomizer.RESOURCE_BUNDLE;

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/TestBeanHelper.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/TestBeanHelper.java?rev=812274&r1=812273&r2=812274&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/TestBeanHelper.java 
(original)
+++ 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/TestBeanHelper.java 
Mon Sep  7 20:55:39 2009
@@ -22,9 +22,16 @@
 import java.beans.PropertyDescriptor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.LinkedList;
 
+import org.apache.jmeter.testbeans.gui.TableEditor;
 import org.apache.jmeter.testelement.TestElement;
+import org.apache.jmeter.testelement.property.CollectionProperty;
 import org.apache.jmeter.testelement.property.JMeterProperty;
+import org.apache.jmeter.testelement.property.MultiProperty;
+import org.apache.jmeter.testelement.property.PropertyIterator;
+import org.apache.jmeter.testelement.property.TestElementProperty;
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.jorphan.util.Converter;
 import org.apache.log.Logger;
@@ -67,7 +74,7 @@
                 // Obtain a value of the appropriate type for this property.
                 JMeterProperty jprop = el.getProperty(desc[x].getName());
                 Class<?> type = desc[x].getPropertyType();
-                Object value = Converter.convert(jprop.getStringValue(), type);
+                Object value = unwrapProperty(desc[x], jprop, type);
 
                 if (log.isDebugEnabled()) {
                     log.debug("Setting " + jprop.getName() + "=" + value);
@@ -90,6 +97,54 @@
     }
 
     /**
+     * @param desc
+     * @param x
+     * @param jprop
+     * @param type
+     * @return
+     */
+    private static Object unwrapProperty(PropertyDescriptor desc, 
JMeterProperty jprop, Class<?> type) {
+        Object value;
+        if(jprop instanceof TestElementProperty)
+        {
+            TestElement te = ((TestElementProperty)jprop).getElement();
+            if(te instanceof TestBean)
+            {
+                prepare(te);
+            }
+            value = te;
+        }
+        else if(jprop instanceof MultiProperty)
+        {
+            value = 
unwrapCollection((MultiProperty)jprop,(String)desc.getValue(TableEditor.CLASSNAME));
+        }
+        else value = Converter.convert(jprop.getStringValue(), type);
+        return value;
+    }
+    
+    private static Object unwrapCollection(MultiProperty prop,String type)
+    {
+        if(prop instanceof CollectionProperty)
+        {
+            Collection<Object> values = new LinkedList<Object>();
+            PropertyIterator iter = prop.iterator();
+            while(iter.hasNext())
+            {
+                try
+                {
+                    
values.add(unwrapProperty(null,iter.next(),Class.forName(type)));
+                }
+                catch(Exception e)
+                {
+                    log.error("Couldn't convert object: " + 
prop.getObjectValue() + " to " + type,e);
+                }
+            }
+            return values;
+        }
+        return null;
+    }
+
+    /**
      * Utility method that invokes a method and does the error handling around
      * the invocation.
      *
@@ -101,7 +156,7 @@
         try {
             return method.invoke(invokee, params);
         } catch (IllegalArgumentException e) {
-            log.error("This should never happen.", e);
+            log.error("This should never happen. 
"+invokee.getClass().getName()+" "+method.getName()+" "+params.length+" 
"+params[0].getClass().getName(), e);
             throw new Error(e.toString()); // Programming error: bail out.
         } catch (IllegalAccessException e) {
             log.error("This should never happen.", e);

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/GenericTestBeanCustomizer.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/GenericTestBeanCustomizer.java?rev=812274&r1=812273&r2=812274&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/GenericTestBeanCustomizer.java
 (original)
+++ 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/GenericTestBeanCustomizer.java
 Mon Sep  7 20:55:39 2009
@@ -220,6 +220,10 @@
                     log.debug("Editor for property " + name + " is wrapped in 
" + propertyEditor);
                 }
             }
+            if(propertyEditor instanceof TestBeanPropertyEditor)
+            {
+                
((TestBeanPropertyEditor)propertyEditor).setDescriptor(descriptors[i]);
+            }
             if (propertyEditor.getCustomEditor() instanceof JScrollPane) {
                 scrollerCount++;
             }

Added: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java?rev=812274&view=auto
==============================================================================
--- 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java 
(added)
+++ 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java 
Mon Sep  7 20:55:39 2009
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.testbeans.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.beans.PropertyDescriptor;
+import java.beans.PropertyEditorSupport;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.CellEditor;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+
+import org.apache.jmeter.testelement.property.TestElementProperty;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.gui.ObjectTableModel;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.jorphan.reflect.Functor;
+import org.apache.log.Logger;
+
+public class TableEditor extends PropertyEditorSupport implements 
FocusListener,TestBeanPropertyEditor,TableModelListener {
+       private static final Logger log = LoggingManager.getLoggerForClass();
+       
+       public static final String CLASSNAME = "tableObject.classname"; // 
$NON-NLS-1$
+       public static final String HEADERS = "table.headers"; // $NON-NLS-1$
+       public static final String OBJECT_PROPERTIES = 
"tableObject.properties"; // $NON-NLS-1$
+       
+       private JTable table;
+       private ObjectTableModel model;
+       private Class<?> clazz;
+       private PropertyDescriptor descriptor;
+       private final JButton addButton,removeButton,clearButton;
+
+       public TableEditor() {
+               addButton = new JButton(JMeterUtils.getResString("add")); // 
$NON-NLS-1$
+               addButton.addActionListener(new AddListener());
+               removeButton = new JButton(JMeterUtils.getResString("remove")); 
// $NON-NLS-1$
+               removeButton.addActionListener(new RemoveListener());
+               clearButton = new JButton(JMeterUtils.getResString("clear")); 
// $NON-NLS-1$
+               clearButton.addActionListener(new ClearListener());
+       }
+
+       @Override
+    public String getAsText() {
+               return null;
+       }
+
+       @Override
+    public Component getCustomEditor() {
+               JComponent pane = makePanel();
+               pane.doLayout();
+               pane.validate();
+               return pane;
+       }
+       
+       private JComponent makePanel()
+       {
+               JPanel p = new JPanel(new BorderLayout());
+               JScrollPane scroller = new JScrollPane(table);
+               scroller.setPreferredSize(scroller.getMinimumSize());
+               p.add(scroller,BorderLayout.CENTER);
+               JPanel south = new JPanel();
+               south.add(addButton);
+               south.add(removeButton);
+               south.add(clearButton);
+               p.add(south,BorderLayout.SOUTH);
+               return p;
+       }
+
+       @Override
+    public Object getValue() {
+               return model.getObjectList();
+       }
+
+       @Override
+    public void setAsText(String text) throws IllegalArgumentException {
+               //not interested in this method.                
+       }
+
+       @Override
+    public void setValue(Object value) {
+               if(value != null)
+               {
+                       model.setRows(convertCollection((Collection<?>)value));
+               }
+               else model.clearData();
+               this.firePropertyChange();
+       }
+       
+       private Collection<Object> convertCollection(Collection<?> values)
+       {
+               List<Object> l = new LinkedList<Object>();
+               for(Object obj : values)
+               {
+                       if(obj instanceof TestElementProperty)
+                       {
+                               l.add(((TestElementProperty)obj).getElement());
+                       }
+                       else
+                       {
+                               l.add(obj);
+                       }
+               }
+               return l;
+       }
+
+       @Override
+    public boolean supportsCustomEditor() {
+               return true;
+       }
+
+       /**
+        * For the table editor, the tag must simply be the name of the class 
of object it will hold 
+        * where each row holds one object. 
+        */
+       public void setDescriptor(PropertyDescriptor descriptor) {
+               try {
+                       this.descriptor = descriptor;
+                       clazz = 
Class.forName((String)descriptor.getValue(CLASSNAME));
+                       initializeModel();
+               } catch (ClassNotFoundException e) {
+                       throw new RuntimeException("The Table Editor requires 
one TAG be set - the name of the object to represent a row",e);
+               }
+       }
+       
+       void initializeModel()
+       {
+               if(clazz == String.class)
+               {
+                       model = new 
ObjectTableModel((String[])descriptor.getValue(HEADERS),new Functor[0],new 
Functor[0],new Class[]{String.class});
+                       model.addTableModelListener(this);
+               }
+               else
+               {
+                       String[] props = 
(String[])descriptor.getValue(OBJECT_PROPERTIES);
+                       Functor[] writers = new Functor[props.length];
+                       Functor[] readers = new Functor[props.length];
+                       Class<?>[] editors = new Class[props.length];
+                       int count = 0;
+                       for(String propName : props)
+                       {
+                               propName = 
propName.substring(0,1).toUpperCase() + propName.substring(1);
+                               writers[count] = createWriter(clazz,propName);
+                               readers[count] = createReader(clazz,propName);
+                               editors[count] = 
getArgForWriter(clazz,propName);
+                               count++;
+                       }
+                       model = new 
ObjectTableModel((String[])descriptor.getValue(HEADERS),readers,writers,editors);
+                       model.addTableModelListener(this);
+               }
+               table = new JTable(model);
+               table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+               table.addFocusListener(this);
+       }
+       
+       Functor createWriter(Class<?> c,String propName)
+       {
+               String setter = "set" + propName; // $NON-NLS-1$
+               return new Functor(setter);
+       }
+       
+       Functor createReader(Class<?> c,String propName)
+       {
+               String getter = "get" + propName; // $NON-NLS-1$
+               try
+               {
+                       c.getMethod(getter,new Class[0]);
+                       return new Functor(getter);
+               }
+               catch(Exception e) { return new Functor("is" + propName); }
+       }
+       
+       Class<?> getArgForWriter(Class<?> c,String propName)
+       {
+               String setter = "set" + propName; // $NON-NLS-1$
+               for(Method m : c.getMethods())
+               {
+                       if(m.getName().equals(setter))
+                       {
+                               return m.getParameterTypes()[0];
+                       }
+               }
+               return null;
+       }
+
+       public void tableChanged(TableModelEvent e) {
+               this.firePropertyChange();              
+       }
+
+       public void focusGained(FocusEvent e) {
+               
+       }
+
+       public void focusLost(FocusEvent e) {
+               CellEditor ce = 
table.getCellEditor(table.getEditingRow(),table.getEditingColumn());
+               Component editor = table.getEditorComponent();
+               if(ce != null && (editor == null || editor != 
e.getOppositeComponent()))
+               {
+                       ce.stopCellEditing();
+               }
+               else if(editor != null)
+               {
+                       editor.addFocusListener(this);
+               }
+               this.firePropertyChange();
+       }
+       
+       private class AddListener implements ActionListener
+       {
+               public void actionPerformed(ActionEvent e)
+               {
+                       try
+                       {
+                               model.addRow(clazz.newInstance());
+                       }catch(Exception err)
+                       {
+                               log.error("The class type given to TableEditor 
was not instantiable. ",err);
+                       }
+               }
+       }
+       
+       private class RemoveListener implements ActionListener
+       {
+               public void actionPerformed(ActionEvent e)
+               {
+                       model.removeRow(table.getSelectedRow());
+               }
+       }
+       
+       private class ClearListener implements ActionListener
+       {
+               public void actionPerformed(ActionEvent e)
+               {
+                       model.clearData();
+               }
+       }
+
+}

Propchange: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java?rev=812274&view=auto
==============================================================================
--- 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java
 (added)
+++ 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java
 Mon Sep  7 20:55:39 2009
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.testbeans.gui;
+
+import java.beans.PropertyDescriptor;
+import java.beans.PropertyEditor;
+
+public interface TestBeanPropertyEditor extends PropertyEditor {
+       
+       public void setDescriptor(PropertyDescriptor descriptor);
+
+}

Propchange: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: 
jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/gui/ObjectTableModel.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/gui/ObjectTableModel.java?rev=812274&r1=812273&r2=812274&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/gui/ObjectTableModel.java 
(original)
+++ 
jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/gui/ObjectTableModel.java 
Mon Sep  7 20:55:39 2009
@@ -235,6 +235,7 @@
      *
      * @return false if at least one Functor cannot be found.
      */
+    @SuppressWarnings("deprecation")
     public boolean checkFunctors(Object _value, Class<?> caller){
         Object value;
         if (_value == null && objectClass != null) {
@@ -270,4 +271,16 @@
         }
         return status;
     }
+
+    public Object getObjectList() { // used by TableEditor
+        return objects;
+    }
+
+    public void setRows(Iterable<?> rows) { // used by TableEditor
+        clearData();
+        for(Object val : rows)
+        {
+            addRow(val);
+        }
+    }
 }

Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=812274&r1=812273&r2=812274&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Mon Sep  7 20:55:39 2009
@@ -147,6 +147,7 @@
 
 <h2>Non-functional changes</h2>
 <ul>
+<li>Add TestBean Table Editor support</li>
 </ul>
 
 </section> 



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to