1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.panels.teststeps;
14
15 import java.awt.BorderLayout;
16 import java.awt.Component;
17 import java.awt.Toolkit;
18 import java.awt.event.ActionEvent;
19 import java.awt.event.KeyAdapter;
20 import java.awt.event.KeyEvent;
21 import java.awt.event.MouseAdapter;
22 import java.awt.event.MouseEvent;
23 import java.beans.PropertyChangeEvent;
24 import java.beans.PropertyChangeListener;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import javax.swing.AbstractAction;
29 import javax.swing.AbstractListModel;
30 import javax.swing.Action;
31 import javax.swing.JComponent;
32 import javax.swing.JLabel;
33 import javax.swing.JList;
34 import javax.swing.JPanel;
35 import javax.swing.JPopupMenu;
36 import javax.swing.JScrollPane;
37 import javax.swing.ListCellRenderer;
38 import javax.swing.ListSelectionModel;
39 import javax.swing.SwingUtilities;
40 import javax.swing.event.ListSelectionEvent;
41 import javax.swing.event.ListSelectionListener;
42 import javax.swing.event.PopupMenuEvent;
43 import javax.swing.event.PopupMenuListener;
44
45 import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
46 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
47 import com.eviware.soapui.impl.wsdl.teststeps.actions.AddAssertionAction;
48 import com.eviware.soapui.model.testsuite.Assertable;
49 import com.eviware.soapui.model.testsuite.AssertionError;
50 import com.eviware.soapui.model.testsuite.AssertionsListener;
51 import com.eviware.soapui.model.testsuite.TestAssertion;
52 import com.eviware.soapui.support.UISupport;
53 import com.eviware.soapui.support.action.swing.ActionList;
54 import com.eviware.soapui.support.action.swing.ActionListBuilder;
55 import com.eviware.soapui.support.action.swing.ActionSupport;
56 import com.eviware.soapui.support.components.JXToolBar;
57
58 /***
59 * Seperate panel for holding/managing assertions
60 *
61 * @author ole.matzura
62 */
63
64 public class AssertionsPanel extends JPanel
65 {
66 private AssertionListModel assertionListModel;
67 private JList assertionList;
68 private JPopupMenu assertionListPopup;
69 private final Assertable assertable;
70 private AddAssertionAction addAssertionAction;
71 private ConfigureAssertionAction configureAssertionAction;
72 private RemoveAssertionAction removeAssertionAction;
73 private MoveAssertionUpAction moveAssertionUpAction;
74 private MoveAssertionDownAction moveAssertionDownAction;
75
76 public AssertionsPanel( Assertable assertable )
77 {
78 super( new BorderLayout() );
79 this.assertable = assertable;
80
81 assertionListModel = new AssertionListModel();
82 assertionList = new JList( assertionListModel );
83 assertionList.setToolTipText( "Assertions for this request" );
84 assertionList.setCellRenderer( new AssertionCellRenderer() );
85 assertionList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
86
87 assertionListPopup = new JPopupMenu();
88 addAssertionAction = new AddAssertionAction( assertable );
89 assertionListPopup.add( addAssertionAction );
90
91 assertionListPopup.addPopupMenuListener( new PopupMenuListener()
92 {
93
94 public void popupMenuWillBecomeVisible( PopupMenuEvent e )
95 {
96 while( assertionListPopup.getComponentCount() > 1 )
97 assertionListPopup.remove( 1 );
98
99 int ix = assertionList.getSelectedIndex();
100 if( ix == -1 )
101 {
102 assertionListPopup.addSeparator();
103 assertionListPopup.add( new ShowOnlineHelpAction( HelpUrls.RESPONSE_ASSERTIONS_HELP_URL ) );
104 return;
105 }
106
107 TestAssertion assertion = assertionListModel.getAssertionAt( ix );
108 ActionSupport.addActions( ActionListBuilder.buildActions( assertion ), assertionListPopup );
109 }
110
111 public void popupMenuWillBecomeInvisible( PopupMenuEvent e )
112 {
113 }
114
115 public void popupMenuCanceled( PopupMenuEvent e )
116 {
117 }
118 } );
119
120 assertionList.setComponentPopupMenu( assertionListPopup );
121
122 assertionList.addMouseListener( new MouseAdapter()
123 {
124
125 public void mouseClicked( MouseEvent e )
126 {
127 if( e.getClickCount() < 2 )
128 return;
129
130 int ix = assertionList.getSelectedIndex();
131 if( ix == -1 )
132 return;
133
134 Object obj = assertionList.getModel().getElementAt( ix );
135 if( obj instanceof TestAssertion )
136 {
137 TestAssertion assertion = ( TestAssertion )obj;
138 if( assertion.isConfigurable() )
139 assertion.configure();
140
141 return;
142 }
143
144 if( obj instanceof AssertionError )
145 {
146 AssertionError error = ( AssertionError )obj;
147 if( error.getLineNumber() >= 0 )
148 {
149 selectError( error );
150 }
151 else
152 Toolkit.getDefaultToolkit().beep();
153 }
154 else
155 Toolkit.getDefaultToolkit().beep();
156 }
157 } );
158
159 assertionList.addKeyListener( new KeyAdapter()
160 {
161 public void keyPressed( KeyEvent e )
162 {
163 int ix = assertionList.getSelectedIndex();
164 if( ix == -1 )
165 return;
166
167 TestAssertion assertion = assertionListModel.getAssertionAt( ix );
168 if( e.getKeyChar() == KeyEvent.VK_ENTER )
169 {
170 if( assertion.isConfigurable() )
171 assertion.configure();
172 }
173 else
174 {
175 ActionList actions = ActionListBuilder.buildActions( assertion );
176 if( actions != null )
177 {
178 actions.dispatchKeyEvent( e );
179 }
180 }
181 }
182 } );
183
184 add( new JScrollPane( assertionList ), BorderLayout.CENTER );
185 add( buildToolbar(), BorderLayout.NORTH );
186 }
187
188 private JComponent buildToolbar()
189 {
190 configureAssertionAction = new ConfigureAssertionAction();
191 removeAssertionAction = new RemoveAssertionAction();
192 moveAssertionUpAction = new MoveAssertionUpAction();
193 moveAssertionDownAction = new MoveAssertionDownAction();
194
195 JXToolBar toolbar = UISupport.createToolbar();
196 addToolbarButtons( toolbar );
197
198 toolbar.addGlue();
199 toolbar.add( new ShowOnlineHelpAction( HelpUrls.REQUEST_ASSERTIONS_HELP_URL ) );
200
201 assertionList.addListSelectionListener( new ListSelectionListener()
202 {
203
204 public void valueChanged( ListSelectionEvent e )
205 {
206 int ix = assertionList.getSelectedIndex();
207
208 configureAssertionAction.setEnabled( ix >= 0 );
209 removeAssertionAction.setEnabled( ix >= 0 );
210 moveAssertionUpAction.setEnabled( ix >= 0 );
211 moveAssertionDownAction.setEnabled( ix >= 0 );
212
213 if( ix == -1 )
214 return;
215 TestAssertion assertion = assertionListModel.getAssertionAt( ix );
216 configureAssertionAction.setEnabled( assertion != null && assertion.isConfigurable() );
217 }
218 } );
219
220 return toolbar;
221 }
222
223 protected void addToolbarButtons( JXToolBar toolbar )
224 {
225 toolbar.addFixed( UISupport.createToolbarButton( addAssertionAction ) );
226 toolbar.addFixed( UISupport.createToolbarButton( configureAssertionAction ) );
227 toolbar.addFixed( UISupport.createToolbarButton( removeAssertionAction ) );
228 toolbar.addFixed( UISupport.createToolbarButton( moveAssertionUpAction ) );
229 toolbar.addFixed( UISupport.createToolbarButton( moveAssertionDownAction ) );
230 }
231
232 public void setEnabled( boolean enabled )
233 {
234 assertionList.setEnabled( enabled );
235 }
236
237 protected void selectError( AssertionError error )
238 {
239 }
240
241 private static class AssertionCellRenderer extends JLabel implements ListCellRenderer
242 {
243 public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected,
244 boolean cellHasFocus )
245 {
246 setEnabled( list.isEnabled() );
247
248 if( value instanceof TestAssertion )
249 {
250 TestAssertion assertion = ( TestAssertion )value;
251 setText( assertion.getLabel() + " - " + assertion.getStatus().toString() );
252 setIcon( assertion.getIcon() );
253
254 if( assertion.isDisabled() && isEnabled() )
255 setEnabled( false );
256 }
257 else if( value instanceof AssertionError )
258 {
259 AssertionError assertion = ( AssertionError )value;
260 setText( " -> " + assertion.toString() );
261 setIcon( null );
262 }
263 else if( value instanceof String )
264 {
265 setText( value.toString() );
266 }
267
268 if( isSelected )
269 {
270 setBackground( list.getSelectionBackground() );
271 setForeground( list.getSelectionForeground() );
272 }
273 else
274 {
275 setBackground( list.getBackground() );
276 setForeground( list.getForeground() );
277 }
278
279 setFont( list.getFont() );
280 setOpaque( true );
281
282 return this;
283 }
284 }
285
286 private class AssertionListModel extends AbstractListModel implements PropertyChangeListener, AssertionsListener
287 {
288 private List<Object> items = new ArrayList<Object>();
289
290 public AssertionListModel()
291 {
292 init();
293 }
294
295 public int getSize()
296 {
297 return items.size();
298 }
299
300 public Object getElementAt( int index )
301 {
302 return index >= items.size() ? null : items.get( index );
303 }
304
305 public TestAssertion getAssertionAt( int index )
306 {
307 Object object = items.get( index );
308 while( !( object instanceof TestAssertion ) && index > 0 )
309 {
310 object = items.get( --index );
311 }
312
313 return ( TestAssertion )( ( object instanceof TestAssertion ) ? object : null );
314 }
315
316 public void refresh()
317 {
318 synchronized( this )
319 {
320 release();
321 init();
322 fireContentsChanged( this, 0, getSize() - 1 );
323 }
324 }
325
326 private void init()
327 {
328 assertable.addAssertionsListener( this );
329
330 for( int c = 0; c < assertable.getAssertionCount(); c++ )
331 {
332 TestAssertion assertion = assertable.getAssertionAt( c );
333 addAssertion( assertion );
334 }
335 }
336
337 public void release()
338 {
339 items.clear();
340
341 for( int c = 0; c < assertable.getAssertionCount(); c++ )
342 {
343 TestAssertion assertion = assertable.getAssertionAt( c );
344 assertion.removePropertyChangeListener( this );
345 }
346
347 assertable.removeAssertionsListener( this );
348 }
349
350 public synchronized void propertyChange( PropertyChangeEvent evt )
351 {
352 if( SwingUtilities.isEventDispatchThread() )
353 refresh();
354 else
355 SwingUtilities.invokeLater( new Runnable()
356 {
357
358 public void run()
359 {
360 refresh();
361 }
362 } );
363 }
364
365 public void assertionAdded( TestAssertion assertion )
366 {
367 synchronized( this )
368 {
369 int sz = getSize();
370 addAssertion( assertion );
371
372 fireIntervalAdded( this, sz, items.size() - 1 );
373 }
374 }
375
376 private void addAssertion( TestAssertion assertion )
377 {
378 assertion.addPropertyChangeListener( this );
379 items.add( assertion );
380
381 AssertionError[] errors = assertion.getErrors();
382 if( errors != null )
383 {
384 for( int i = 0; i < errors.length; i++ )
385 items.add( errors[i] );
386 }
387 }
388
389 public void assertionRemoved( TestAssertion assertion )
390 {
391 synchronized( this )
392 {
393 int ix = items.indexOf( assertion );
394 if( ix == -1 )
395 return;
396
397 assertion.removePropertyChangeListener( this );
398 items.remove( ix );
399 fireIntervalRemoved( this, ix, ix );
400
401
402 while( ix < items.size() && items.get( ix ) instanceof AssertionError )
403 {
404 items.remove( ix );
405 fireIntervalRemoved( this, ix, ix );
406 }
407 }
408 }
409
410 public void assertionMoved( TestAssertion newAssertion, int ix, int offset )
411 {
412 synchronized( this )
413 {
414
415 TestAssertion assertion = ( TestAssertion )items.get( ix );
416
417
418 if( ( ix == 0 && offset == -1 ) || ( ix == items.size() - 1 && offset == 1 ) )
419 {
420 return;
421 }
422
423 assertion.removePropertyChangeListener( this );
424 items.remove( ix );
425 fireIntervalRemoved( this, ix, ix );
426
427
428 while( ix < items.size() && items.get( ix ) instanceof AssertionError )
429 {
430 items.remove( ix );
431 fireIntervalRemoved( this, ix, ix );
432 }
433 newAssertion.addPropertyChangeListener( this );
434 items.add( ix + offset, newAssertion );
435 fireIntervalAdded( this, ix + offset, ix + offset );
436
437 while( ix < items.size() && items.get( ix ) instanceof AssertionError )
438 {
439 items.add( newAssertion );
440 fireIntervalAdded( this, ix + offset, ix + offset );
441 }
442 }
443 }
444
445 }
446
447 public void release()
448 {
449 assertionListModel.release();
450 }
451
452 public class ConfigureAssertionAction extends AbstractAction
453 {
454 ConfigureAssertionAction()
455 {
456 super( "Configure" );
457 putValue( Action.SHORT_DESCRIPTION, "Configures the selection assertion" );
458 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ) );
459 setEnabled( false );
460 }
461
462 public void actionPerformed( ActionEvent e )
463 {
464 int ix = assertionList.getSelectedIndex();
465 if( ix == -1 )
466 return;
467
468 TestAssertion assertion = assertionListModel.getAssertionAt( ix );
469 if( assertion.isConfigurable() )
470 {
471 assertion.configure();
472 }
473 else
474 Toolkit.getDefaultToolkit().beep();
475 }
476 }
477
478 public class RemoveAssertionAction extends AbstractAction
479 {
480 public RemoveAssertionAction()
481 {
482 super( "Remove Assertion" );
483 putValue( Action.SHORT_DESCRIPTION, "Removes the selected assertion" );
484 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/remove_assertion.gif" ) );
485 setEnabled( false );
486 }
487
488 public void actionPerformed( ActionEvent e )
489 {
490 int ix = assertionList.getSelectedIndex();
491 if( ix == -1 )
492 return;
493
494 TestAssertion assertion = assertionListModel.getAssertionAt( ix );
495 if( UISupport.confirm( "Remove assertion [" + assertion.getName() + "]", "Remove Assertion" ) )
496 {
497 assertable.removeAssertion( assertion );
498 }
499 }
500 }
501
502 private class MoveAssertionUpAction extends AbstractAction
503 {
504 public MoveAssertionUpAction()
505 {
506 super( "Move Assertion Up" );
507 putValue( Action.SHORT_DESCRIPTION, "Moves selected asertion up one row" );
508 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/up_arrow.gif" ) );
509 setEnabled( false );
510
511 }
512
513 public void actionPerformed( ActionEvent e )
514 {
515 int ix = assertionList.getSelectedIndex();
516 TestAssertion assertion = assertionListModel.getAssertionAt( ix );
517 if( ix != -1 )
518 {
519 assertion = assertable.moveAssertion( ix, -1 );
520 }
521 assertionList.setSelectedValue( assertion, true );
522 }
523 }
524
525 private class MoveAssertionDownAction extends AbstractAction
526 {
527 public MoveAssertionDownAction()
528 {
529 super( "Move Assertion Down" );
530 putValue( Action.SHORT_DESCRIPTION, "Moves selected asertion down one row" );
531 putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/down_arrow.gif" ) );
532 setEnabled( false );
533
534 }
535
536 public void actionPerformed( ActionEvent e )
537 {
538 int ix = assertionList.getSelectedIndex();
539 TestAssertion assertion = assertionListModel.getAssertionAt( ix );
540 if( ix != -1 )
541 {
542 assertion = assertable.moveAssertion( ix, 1 );
543 }
544 assertionList.setSelectedValue( assertion, true );
545 }
546 }
547 }