1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. 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 */ 18 19 package org.apache.jmeter.protocol.ldap.config.gui; 20 21 import java.awt.BorderLayout; 22 import java.awt.Component; 23 import java.awt.FlowLayout; 24 import java.awt.event.ActionEvent; 25 import java.awt.event.ActionListener; 26 import java.util.Collection; 27 import java.util.Iterator; 28 29 import javax.swing.BorderFactory; 30 import javax.swing.Box; 31 import javax.swing.JButton; 32 import javax.swing.JLabel; 33 import javax.swing.JPanel; 34 import javax.swing.JTable; 35 import javax.swing.ListSelectionModel; 36 import javax.swing.table.TableCellEditor; 37 38 import org.apache.jmeter.config.gui.AbstractConfigGui; 39 import org.apache.jmeter.gui.util.HeaderAsPropertyRenderer; 40 import org.apache.jmeter.testelement.TestElement; 41 import org.apache.jmeter.testelement.property.PropertyIterator; 42 import org.apache.jmeter.util.JMeterUtils; 43 import org.apache.jorphan.gui.ObjectTableModel; 44 import org.apache.jorphan.reflect.Functor; 45 46 /** 47 * A GUI panel allowing the user to enter name-value argument pairs. These 48 * arguments (or parameters) are usually used to provide configuration values 49 * for some other component. 50 * 51 */ 52 53 public class LDAPArgumentsPanel extends AbstractConfigGui implements ActionListener { 54 /** Logging. */ 55 //private static final Logger log = LoggingManager.getLoggerForClass(); 56 57 /** The title label for this component. */ 58 private JLabel tableLabel; 59 60 /** The table containing the list of arguments. */ 61 private transient JTable table; 62 63 /** The model for the arguments table. */ 64 protected transient ObjectTableModel tableModel; 65 66 /** A button for adding new arguments to the table. */ 67 private JButton add; 68 69 /** A button for removing arguments from the table. */ 70 private JButton delete; 71 72 /** Command for adding a row to the table. */ 73 private static final String ADD = "add"; //$NON-NLS-1$ 74 75 /** Command for removing a row from the table. */ 76 private static final String DELETE = "delete"; //$NON-NLS-1$ 77 78 private static final String[] COLUMN_NAMES = { 79 "attribute", //$NON-NLS-1$ 80 "value", //$NON-NLS-1$ 81 "opcode", //$NON-NLS-1$ 82 "metadata" }; //$NON-NLS-1$ 83 84 /** 85 * Create a new LDAPArgumentsPanel, using the default title. 86 */ 87 public LDAPArgumentsPanel() { 88 this(JMeterUtils.getResString("paramtable")); //$NON-NLS-1$ 89 } 90 91 /** 92 * Create a new LDAPArgumentsPanel, using the specified title. 93 * 94 * @param label 95 * the title of the component 96 */ 97 public LDAPArgumentsPanel(String label) { 98 tableLabel = new JLabel(label); 99 init(); 100 } 101 102 /** 103 * This is the list of menu categories this gui component will be available 104 * under. The LDAPArgumentsPanel is not intended to be used as a standalone 105 * component, so this inplementation returns null. 106 * 107 * @return a Collection of Strings, where each element is one of the 108 * constants defined in MenuFactory 109 */ 110 public Collection getMenuCategories() { 111 return null; 112 } 113 114 public String getLabelResource() { 115 return "ldapext_sample_title"; // $NON-NLS-1$ 116 } 117 118 /* Implements JMeterGUIComponent.createTestElement() */ 119 public TestElement createTestElement() { 120 LDAPArguments args = new LDAPArguments(); 121 modifyTestElement(args); 122 // TODO: Why do we clone the return value? This is the only reference 123 // to it (right?) so we shouldn't need a separate copy. 124 return (TestElement) args.clone(); 125 } 126 127 /* Implements JMeterGUIComponent.modifyTestElement(TestElement) */ 128 public void modifyTestElement(TestElement args) { 129 stopTableEditing(); 130 Iterator modelData = tableModel.iterator(); 131 LDAPArguments arguments = null; 132 if (args instanceof LDAPArguments) { 133 arguments = (LDAPArguments) args; 134 arguments.clear(); 135 while (modelData.hasNext()) { 136 LDAPArgument arg = (LDAPArgument) modelData.next(); 137 arg.setMetaData("="); 138 arguments.addArgument(arg); 139 } 140 } 141 this.configureTestElement(args); 142 } 143 144 /** 145 * A newly created component can be initialized with the contents of a Test 146 * Element object by calling this method. The component is responsible for 147 * querying the Test Element object for the relevant information to display 148 * in its GUI. 149 * 150 * @param el 151 * the TestElement to configure 152 */ 153 public void configure(TestElement el) { 154 super.configure(el); 155 if (el instanceof LDAPArguments) { 156 tableModel.clearData(); 157 PropertyIterator iter = ((LDAPArguments) el).iterator(); 158 while (iter.hasNext()) { 159 LDAPArgument arg = (LDAPArgument) iter.next().getObjectValue(); 160 tableModel.addRow(arg); 161 } 162 } 163 checkDeleteStatus(); 164 } 165 166 /** 167 * Get the table used to enter arguments. 168 * 169 * @return the table used to enter arguments 170 */ 171 protected JTable getTable() { 172 return table; 173 } 174 175 /** 176 * Get the title label for this component. 177 * 178 * @return the title label displayed with the table 179 */ 180 protected JLabel getTableLabel() { 181 return tableLabel; 182 } 183 184 /** 185 * Get the button used to delete rows from the table. 186 * 187 * @return the button used to delete rows from the table 188 */ 189 protected JButton getDeleteButton() { 190 return delete; 191 } 192 193 /** 194 * Get the button used to add rows to the table. 195 * 196 * @return the button used to add rows to the table 197 */ 198 protected JButton getAddButton() { 199 return add; 200 } 201 202 /** 203 * Enable or disable the delete button depending on whether or not there is 204 * a row to be deleted. 205 */ 206 protected void checkDeleteStatus() { 207 // Disable DELETE if there are no rows in the table to delete. 208 if (tableModel.getRowCount() == 0) { 209 delete.setEnabled(false); 210 } else { 211 delete.setEnabled(true); 212 } 213 } 214 215 /** 216 * Clear all rows from the table. T.Elanjchezhiyan(chezhiyan@siptech.co.in) 217 */ 218 public void clear() { 219 tableModel.clearData(); 220 } 221 222 /** 223 * Invoked when an action occurs. This implementation supports the add and 224 * delete buttons. 225 * 226 * @param e 227 * the event that has occurred 228 */ 229 public void actionPerformed(ActionEvent e) { 230 String action = e.getActionCommand(); 231 if (action.equals(DELETE)) { 232 deleteArgument(); 233 } else if (action.equals(ADD)) { 234 addArgument(); 235 } 236 } 237 238 /** 239 * Remove the currently selected argument from the table. 240 */ 241 protected void deleteArgument() { 242 // If a table cell is being edited, we must cancel the editing before 243 // deleting the row 244 if (table.isEditing()) { 245 TableCellEditor cellEditor = table.getCellEditor(table.getEditingRow(), table.getEditingColumn()); 246 cellEditor.cancelCellEditing(); 247 } 248 249 int rowSelected = table.getSelectedRow(); 250 if (rowSelected >= 0) { 251 tableModel.removeRow(rowSelected); 252 tableModel.fireTableDataChanged(); 253 254 // Disable DELETE if there are no rows in the table to delete. 255 if (tableModel.getRowCount() == 0) { 256 delete.setEnabled(false); 257 } 258 259 // Table still contains one or more rows, so highlight (select) 260 // the appropriate one. 261 else { 262 int rowToSelect = rowSelected; 263 264 if (rowSelected >= tableModel.getRowCount()) { 265 rowToSelect = rowSelected - 1; 266 } 267 268 table.setRowSelectionInterval(rowToSelect, rowToSelect); 269 } 270 } 271 } 272 273 /** 274 * Add a new argument row to the table. 275 */ 276 protected void addArgument() { 277 // If a table cell is being edited, we should accept the current value 278 // and stop the editing before adding a new row. 279 stopTableEditing(); 280 281 tableModel.addRow(makeNewLDAPArgument()); 282 283 // Enable DELETE (which may already be enabled, but it won't hurt) 284 delete.setEnabled(true); 285 286 // Highlight (select) the appropriate row. 287 int rowToSelect = tableModel.getRowCount() - 1; 288 table.setRowSelectionInterval(rowToSelect, rowToSelect); 289 } 290 291 /** 292 * Create a new LDAPArgument object. 293 * 294 * @return a new LDAPArgument object 295 */ 296 protected Object makeNewLDAPArgument() { 297 return new LDAPArgument("", "", ""); 298 } 299 300 /** 301 * Stop any editing that is currently being done on the table. This will 302 * save any changes that have already been made. 303 */ 304 private void stopTableEditing() { 305 if (table.isEditing()) { 306 TableCellEditor cellEditor = table.getCellEditor(table.getEditingRow(), table.getEditingColumn()); 307 cellEditor.stopCellEditing(); 308 } 309 } 310 311 /** 312 * Initialize the table model used for the arguments table. 313 */ 314 protected void initializeTableModel() { 315 tableModel = new ObjectTableModel(new String[] { COLUMN_NAMES[0], COLUMN_NAMES[1], COLUMN_NAMES[2] }, 316 LDAPArgument.class, 317 new Functor[] { new Functor("getName"), new Functor("getValue"), new Functor("getOpcode") }, 318 new Functor[] { new Functor("setName"), new Functor("setValue"), new Functor("setOpcode") }, 319 new Class[] { String.class, String.class, String.class }); 320 } 321 322 public static boolean testFunctors(){ 323 LDAPArgumentsPanel instance = new LDAPArgumentsPanel(); 324 instance.initializeTableModel(); 325 return instance.tableModel.checkFunctors(null,instance.getClass()); 326 } 327 328 /* 329 * protected void initializeTableModel() { tableModel = new 330 * ObjectTableModel( new String[] { ArgumentsPanel.COLUMN_NAMES_0, 331 * ArgumentsPanel.COLUMN_NAMES_1, ENCODE_OR_NOT, INCLUDE_EQUALS }, new 332 * Functor[] { new Functor("getName"), new Functor("getValue"), new 333 * Functor("isAlwaysEncoded"), new Functor("isUseEquals") }, new Functor[] { 334 * new Functor("setName"), new Functor("setValue"), new 335 * Functor("setAlwaysEncoded"), new Functor("setUseEquals") }, new Class[] { 336 * String.class, String.class, Boolean.class, Boolean.class }); } 337 */ 338 /** 339 * Resize the table columns to appropriate widths. 340 * 341 * @param _table 342 * the table to resize columns for 343 */ 344 protected void sizeColumns(JTable _table) { 345 } 346 347 /** 348 * Create the main GUI panel which contains the argument table. 349 * 350 * @return the main GUI panel 351 */ 352 private Component makeMainPanel() { 353 initializeTableModel(); 354 table = new JTable(tableModel); 355 table.getTableHeader().setDefaultRenderer(new HeaderAsPropertyRenderer()); 356 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 357 return makeScrollPane(table); 358 } 359 360 /** 361 * Create a panel containing the title label for the table. 362 * 363 * @return a panel containing the title label 364 */ 365 protected Component makeLabelPanel() { 366 JPanel labelPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); 367 labelPanel.add(tableLabel); 368 return labelPanel; 369 } 370 371 /** 372 * Create a panel containing the add and delete buttons. 373 * 374 * @return a GUI panel containing the buttons 375 */ 376 private JPanel makeButtonPanel() { 377 add = new JButton(JMeterUtils.getResString("add")); //$NON-NLS-1$ 378 add.setActionCommand(ADD); 379 add.setEnabled(true); 380 381 delete = new JButton(JMeterUtils.getResString("delete")); //$NON-NLS-1$ 382 delete.setActionCommand(DELETE); 383 384 checkDeleteStatus(); 385 386 JPanel buttonPanel = new JPanel(); 387 buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); 388 add.addActionListener(this); 389 delete.addActionListener(this); 390 buttonPanel.add(add); 391 buttonPanel.add(delete); 392 return buttonPanel; 393 } 394 395 /** 396 * Initialize the components and layout of this component. 397 */ 398 private void init() { 399 setLayout(new BorderLayout()); 400 401 add(makeLabelPanel(), BorderLayout.NORTH); 402 add(makeMainPanel(), BorderLayout.CENTER); 403 // Force a minimum table height of 70 pixels 404 add(Box.createVerticalStrut(70), BorderLayout.WEST); 405 add(makeButtonPanel(), BorderLayout.SOUTH); 406 407 table.revalidate(); 408 sizeColumns(table); 409 } 410 }