View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
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.SwingUtilities;
39  import javax.swing.event.ListSelectionEvent;
40  import javax.swing.event.ListSelectionListener;
41  import javax.swing.event.PopupMenuEvent;
42  import javax.swing.event.PopupMenuListener;
43  
44  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
45  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
46  import com.eviware.soapui.impl.wsdl.teststeps.actions.AddAssertionAction;
47  import com.eviware.soapui.model.testsuite.Assertable;
48  import com.eviware.soapui.model.testsuite.AssertionError;
49  import com.eviware.soapui.model.testsuite.AssertionsListener;
50  import com.eviware.soapui.model.testsuite.TestAssertion;
51  import com.eviware.soapui.support.UISupport;
52  import com.eviware.soapui.support.action.swing.ActionList;
53  import com.eviware.soapui.support.action.swing.ActionListBuilder;
54  import com.eviware.soapui.support.action.swing.ActionSupport;
55  import com.eviware.soapui.support.components.JXToolBar;
56  
57  /***
58   * Seperate panel for holding/managing assertions
59   * 
60   * @author ole.matzura
61   */
62  
63  public class AssertionsPanel extends JPanel
64  {
65  	private AssertionListModel assertionListModel;
66  	private JList assertionList;
67  	private JPopupMenu assertionListPopup;
68  	private final Assertable assertable;
69  	private AddAssertionAction addAssertionAction;
70  	private ConfigureAssertionAction configureAssertionAction;
71  	private RemoveAssertionAction removeAssertionAction;
72  
73  	public AssertionsPanel( Assertable assertable )
74  	{
75  		super( new BorderLayout() );
76  		this.assertable = assertable;
77  		
78        assertionListModel = new AssertionListModel();
79        assertionList = new JList( assertionListModel );
80        assertionList.setToolTipText( "Assertions for this request" );
81        assertionList.setCellRenderer( new AssertionCellRenderer() );
82        
83        assertionListPopup = new JPopupMenu();
84        addAssertionAction = new AddAssertionAction( assertable );
85  		assertionListPopup.add( addAssertionAction);
86        
87        assertionListPopup.addPopupMenuListener( new PopupMenuListener(){
88  
89           public void popupMenuWillBecomeVisible(PopupMenuEvent e)
90           {
91              while( assertionListPopup.getComponentCount() > 1 ) 
92                 assertionListPopup.remove( 1 );
93              
94              int ix = assertionList.getSelectedIndex();
95              if( ix == -1 ) 
96              {
97              	assertionListPopup.addSeparator();
98              	assertionListPopup.add( new ShowOnlineHelpAction( HelpUrls.RESPONSE_ASSERTIONS_HELP_URL ) );
99              	return;
100             }
101             
102             TestAssertion assertion = assertionListModel.getAssertionAt( ix );
103             ActionSupport.addActions( 
104             			ActionListBuilder.buildActions( assertion ), assertionListPopup );
105          }
106 
107          public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
108          {
109          }
110 
111          public void popupMenuCanceled(PopupMenuEvent e)
112          {
113          }});
114       
115       assertionList.setComponentPopupMenu( assertionListPopup );
116       
117       assertionList.addMouseListener( new MouseAdapter() {
118 
119 			public void mouseClicked(MouseEvent e)
120          {
121             if( e.getClickCount() < 2 ) return;
122 
123             int ix = assertionList.getSelectedIndex();
124             if( ix == -1 ) return;
125             
126             Object obj = assertionList.getModel().getElementAt( ix );
127             if( obj instanceof TestAssertion )
128             {
129             	TestAssertion assertion = (TestAssertion) obj;
130 	            if( assertion.isConfigurable() )
131 	               assertion.configure();
132 	            
133 	            return;
134             }
135             
136    		   if( obj instanceof AssertionError )
137    		   {
138    		   	AssertionError error = (AssertionError) obj;
139    		   	if( error.getLineNumber() >= 0 )
140    		   	{
141    		   		selectError(error);
142    		   	}
143    		   	else Toolkit.getDefaultToolkit().beep();
144    		   }
145    		   else Toolkit.getDefaultToolkit().beep();
146          }});
147       
148       assertionList.addKeyListener( new KeyAdapter() 
149       {
150       	public void keyPressed(KeyEvent e)
151    		{
152       		int ix = assertionList.getSelectedIndex();
153             if( ix == -1 ) return;
154             
155             TestAssertion assertion = assertionListModel.getAssertionAt( ix );
156             if( e.getKeyChar() == KeyEvent.VK_ENTER )
157             {
158 	            if( assertion.isConfigurable() )
159 	               assertion.configure();
160             }
161             else
162             {
163 					ActionList actions = ActionListBuilder.buildActions( assertion );
164 					if( actions != null )
165 					{
166 						actions.dispatchKeyEvent( e );
167 					}
168             }
169    		}
170       } );
171       
172       add( new JScrollPane( assertionList ), BorderLayout.CENTER );
173       add( buildToolbar(), BorderLayout.NORTH );
174    }
175 	
176 	private JComponent buildToolbar()
177 	{
178 		configureAssertionAction = new ConfigureAssertionAction();
179 		removeAssertionAction = new RemoveAssertionAction();
180 		
181 		JXToolBar toolbar = UISupport.createToolbar();
182 		addToolbarButtons( toolbar );
183 		
184 		toolbar.addGlue();
185 		toolbar.add( new ShowOnlineHelpAction( HelpUrls.REQUEST_ASSERTIONS_HELP_URL ));
186 		
187 		assertionList.addListSelectionListener( new ListSelectionListener() {
188 
189 			public void valueChanged( ListSelectionEvent e )
190 			{
191 				int ix = assertionList.getSelectedIndex();
192 				
193 				configureAssertionAction.setEnabled( ix >= 0 );
194 				removeAssertionAction.setEnabled( ix >= 0 );
195 				
196             if( ix == -1 ) return;
197             configureAssertionAction.setEnabled( assertionListModel.getAssertionAt( ix ).isConfigurable() );	
198 			}} );
199 		
200 		return toolbar;
201 	}
202 
203 	protected void addToolbarButtons( JXToolBar toolbar )
204 	{
205 		toolbar.addFixed( UISupport.createToolbarButton( addAssertionAction ));
206 		toolbar.addFixed( UISupport.createToolbarButton( configureAssertionAction ));
207 		toolbar.addFixed( UISupport.createToolbarButton( removeAssertionAction ));
208 	}
209 
210 	public void setEnabled( boolean enabled )
211 	{
212 		assertionList.setEnabled( enabled );
213 	}
214 
215    protected void selectError(AssertionError error)
216 	{
217 	}
218    
219 	private static class AssertionCellRenderer extends JLabel implements ListCellRenderer 
220    {
221       public Component getListCellRendererComponent(
222         JList list,
223         Object value,           
224         int index,               
225         boolean isSelected,      
226         boolean cellHasFocus)    
227       {
228       	setEnabled(list.isEnabled());
229       	
230       	if( value instanceof TestAssertion )
231       	{
232       		TestAssertion assertion = (TestAssertion) value;
233       		setText( assertion.getLabel() + " - " + assertion.getStatus().toString() );
234             setIcon( assertion.getIcon() );
235             
236             if( assertion.isDisabled() && isEnabled() )
237             	setEnabled( false );
238       	}
239       	else if( value instanceof AssertionError )
240       	{
241             AssertionError assertion = (AssertionError) value;
242             setText( " -> " + assertion.toString() );
243             setIcon( null );
244       	}
245       	else if( value instanceof String )
246       	{
247       		setText( value.toString() );
248       	}
249       	
250           if (isSelected) 
251           {
252              setBackground(list.getSelectionBackground());
253              setForeground(list.getSelectionForeground());
254           }
255           else 
256           {
257              setBackground(list.getBackground());
258              setForeground(list.getForeground());
259           }
260           
261           setFont(list.getFont());
262           setOpaque(true);
263           
264           return this;
265       }
266   }
267    
268    private class AssertionListModel extends AbstractListModel implements PropertyChangeListener, 
269        AssertionsListener
270    {
271    	private List<Object> items = new ArrayList<Object>();
272    	
273       public AssertionListModel()
274       {
275       	init();
276       }
277       
278       public int getSize()
279       {
280       	return items.size();
281       }
282 
283       public Object getElementAt(int index)
284       {
285       	return index >= items.size() ? null : items.get( index );
286       }
287 
288       public TestAssertion getAssertionAt( int index )
289       {
290       	Object object = items.get( index );
291       	while( object instanceof AssertionError && index > 0 )
292       	{
293       		object = items.get( --index );
294       	}
295       	
296       	return (TestAssertion) object;
297       }
298       
299       public void refresh()
300       {
301       	synchronized( this )
302 			{
303 				release();
304 	      	init();
305 	         fireContentsChanged( this, 0, getSize()-1 );
306 			}
307       }
308 
309 		private void init()
310 		{
311       	assertable.addAssertionsListener( this );
312 			
313          for( int c = 0; c < assertable.getAssertionCount(); c++ )
314          {
315          	TestAssertion assertion = assertable.getAssertionAt( c );
316          	addAssertion(assertion);
317          }
318 		}
319 		
320 		public void release()
321 		{
322          items.clear();
323 
324          for( int c = 0; c < assertable.getAssertionCount(); c++ )
325          {
326          	TestAssertion assertion = assertable.getAssertionAt( c );
327          	assertion.removePropertyChangeListener( this );
328          }
329          
330          assertable.removeAssertionsListener( this );
331 		}
332 
333 		public synchronized void propertyChange(PropertyChangeEvent evt)
334 		{
335 			if( SwingUtilities.isEventDispatchThread() )
336 				refresh();
337 			else SwingUtilities.invokeLater( new Runnable() {
338 
339 				public void run()
340 				{
341 					refresh();
342 				}} );			
343 		}
344 
345 		public void assertionAdded(TestAssertion assertion)
346 		{
347 			synchronized( this )
348 			{
349 				int sz = getSize();
350 				addAssertion(assertion);
351       	
352 				fireIntervalAdded( this, sz, items.size()-1 );
353 			}
354 		}
355 
356 		private void addAssertion(TestAssertion assertion)
357 		{
358 			assertion.addPropertyChangeListener( this );
359       	items.add( assertion );
360       	
361       	AssertionError[] errors = assertion.getErrors();
362       	if( errors != null)
363       	{
364       		for( int i = 0; i < errors.length; i++ )
365       		items.add( errors[i] );
366       	}
367 		}
368 
369 		public void assertionRemoved(TestAssertion assertion)
370 		{
371 			synchronized( this )
372 			{
373 				int ix = items.indexOf( assertion );
374 				if( ix == -1 ) return;
375 	
376 				assertion.removePropertyChangeListener( this );
377 				items.remove( ix );
378 				fireIntervalRemoved( this, ix, ix );
379 				
380 				// remove associated errors
381 				while( ix < items.size() && items.get( ix ) instanceof AssertionError )
382 				{
383 					items.remove( ix );
384 					fireIntervalRemoved( this, ix, ix );
385 				}
386 			}
387 		}
388    }
389 
390 	public void release()
391 	{
392 		assertionListModel.release();
393 	}
394 	
395 	public class ConfigureAssertionAction extends AbstractAction
396    {
397       ConfigureAssertionAction()
398       {
399       	super( "Configure" );
400       	putValue( Action.SHORT_DESCRIPTION, "Configures the selection assertion" );
401       	putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ));
402       	setEnabled( false );
403       }
404 
405       public void actionPerformed( ActionEvent e )
406       {
407       	int ix = assertionList.getSelectedIndex();
408          if( ix == -1 ) return;
409          
410          TestAssertion assertion = assertionListModel.getAssertionAt( ix );
411          if( assertion.isConfigurable() )
412          {
413             assertion.configure();
414          }
415 		   else Toolkit.getDefaultToolkit().beep();
416       }
417    }
418 
419    public class RemoveAssertionAction extends AbstractAction
420    {
421       public RemoveAssertionAction()
422       {
423       	super( "Remove Assertion" );
424       	putValue( Action.SHORT_DESCRIPTION, "Removes the selected assertion from this LoadTest" );
425       	putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/remove_assertion.gif" ));
426       	setEnabled( false );
427       }
428 
429       public void actionPerformed( ActionEvent e )
430       {
431       	int ix = assertionList.getSelectedIndex();
432          if( ix == -1 ) return;
433          
434          TestAssertion assertion = assertionListModel.getAssertionAt( ix );
435          if( UISupport.confirm( "Remove assertion [" + assertion.getName() + "]", "Remove Assertion"))
436          {
437          	assertable.removeAssertion( assertion );
438          }
439       }
440    }
441 }