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.support.assertions.Assertable;
47  import com.eviware.soapui.impl.wsdl.support.assertions.AssertionsListener;
48  import com.eviware.soapui.impl.wsdl.teststeps.WsdlMessageAssertion;
49  import com.eviware.soapui.impl.wsdl.teststeps.actions.AddAssertionAction;
50  import com.eviware.soapui.impl.wsdl.teststeps.assertions.AssertionError;
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             WsdlMessageAssertion 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 WsdlMessageAssertion )
128             {
129 	            WsdlMessageAssertion assertion = (WsdlMessageAssertion) 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             WsdlMessageAssertion 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       	if( value instanceof WsdlMessageAssertion )
229       	{
230       		WsdlMessageAssertion assertion = (WsdlMessageAssertion) value;
231       		setText( assertion.getName() + " - " + assertion.getStatus().toString() );
232             setIcon( assertion.getIcon() );
233       	}
234       	else if( value instanceof AssertionError )
235       	{
236             AssertionError assertion = (AssertionError) value;
237             setText( " -> " + assertion.toString() );
238             setIcon( null );
239       	}
240       	else if( value instanceof String )
241       	{
242       		setText( value.toString() );
243       	}
244       	
245           if (isSelected) 
246           {
247              setBackground(list.getSelectionBackground());
248              setForeground(list.getSelectionForeground());
249           }
250           else 
251           {
252              setBackground(list.getBackground());
253              setForeground(list.getForeground());
254           }
255           
256           setEnabled(list.isEnabled());
257           setFont(list.getFont());
258           setOpaque(true);
259           
260           return this;
261       }
262   }
263    
264    private class AssertionListModel extends AbstractListModel implements PropertyChangeListener, 
265        AssertionsListener
266    {
267    	private List<Object> items = new ArrayList<Object>();
268    	
269       public AssertionListModel()
270       {
271       	init();
272       }
273       
274       public int getSize()
275       {
276       	return items.size();
277       }
278 
279       public Object getElementAt(int index)
280       {
281       	return index >= items.size() ? null : items.get( index );
282       }
283 
284       public WsdlMessageAssertion getAssertionAt( int index )
285       {
286       	Object object = items.get( index );
287       	while( object instanceof AssertionError && index > 0 )
288       	{
289       		object = items.get( --index );
290       	}
291       	
292       	return (WsdlMessageAssertion) object;
293       }
294       
295       public void refresh()
296       {
297       	synchronized( this )
298 			{
299 				release();
300 	      	init();
301 	         fireContentsChanged( this, 0, getSize()-1 );
302 			}
303       }
304 
305 		private void init()
306 		{
307       	assertable.addAssertionsListener( this );
308 			
309          for( int c = 0; c < assertable.getAssertionCount(); c++ )
310          {
311          	WsdlMessageAssertion assertion = assertable.getAssertionAt( c );
312          	addAssertion(assertion);
313          }
314 		}
315 		
316 		public void release()
317 		{
318          items.clear();
319 
320          for( int c = 0; c < assertable.getAssertionCount(); c++ )
321          {
322          	WsdlMessageAssertion assertion = assertable.getAssertionAt( c );
323          	assertion.removePropertyChangeListener( this );
324          }
325          
326          assertable.removeAssertionsListener( this );
327 		}
328 
329 		public synchronized void propertyChange(PropertyChangeEvent evt)
330 		{
331 			if( SwingUtilities.isEventDispatchThread() )
332 				refresh();
333 			else SwingUtilities.invokeLater( new Runnable() {
334 
335 				public void run()
336 				{
337 					refresh();
338 				}} );			
339 		}
340 
341 		public void assertionAdded(WsdlMessageAssertion assertion)
342 		{
343 			synchronized( this )
344 			{
345 				int sz = getSize();
346 				addAssertion(assertion);
347       	
348 				fireIntervalAdded( this, sz, items.size()-1 );
349 			}
350 		}
351 
352 		private void addAssertion(WsdlMessageAssertion assertion)
353 		{
354 			assertion.addPropertyChangeListener( this );
355       	items.add( assertion );
356       	
357       	AssertionError[] errors = assertion.getErrors();
358       	if( errors != null)
359       	{
360       		for( int i = 0; i < errors.length; i++ )
361       		items.add( errors[i] );
362       	}
363 		}
364 
365 		public void assertionRemoved(WsdlMessageAssertion assertion)
366 		{
367 			synchronized( this )
368 			{
369 				int ix = items.indexOf( assertion );
370 				if( ix == -1 ) return;
371 	
372 				assertion.removePropertyChangeListener( this );
373 				items.remove( ix );
374 				fireIntervalRemoved( this, ix, ix );
375 				
376 				// remove associated errors
377 				while( ix < items.size() && items.get( ix ) instanceof AssertionError )
378 				{
379 					items.remove( ix );
380 					fireIntervalRemoved( this, ix, ix );
381 				}
382 			}
383 		}
384    }
385 
386 	public void release()
387 	{
388 		assertionListModel.release();
389 	}
390 	
391 	public class ConfigureAssertionAction extends AbstractAction
392    {
393       ConfigureAssertionAction()
394       {
395       	super( "Configure" );
396       	putValue( Action.SHORT_DESCRIPTION, "Configures the selection assertion" );
397       	putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ));
398       	setEnabled( false );
399       }
400 
401       public void actionPerformed( ActionEvent e )
402       {
403       	int ix = assertionList.getSelectedIndex();
404          if( ix == -1 ) return;
405          
406          WsdlMessageAssertion assertion = assertionListModel.getAssertionAt( ix );
407          if( assertion.isConfigurable() )
408          {
409             assertion.configure();
410          }
411 		   else Toolkit.getDefaultToolkit().beep();
412       }
413    }
414 
415    public class RemoveAssertionAction extends AbstractAction
416    {
417       public RemoveAssertionAction()
418       {
419       	super( "Remove Assertion" );
420       	putValue( Action.SHORT_DESCRIPTION, "Removes the selected assertion from this LoadTest" );
421       	putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/remove_assertion.gif" ));
422       	setEnabled( false );
423       }
424 
425       public void actionPerformed( ActionEvent e )
426       {
427       	int ix = assertionList.getSelectedIndex();
428          if( ix == -1 ) return;
429          
430          WsdlMessageAssertion assertion = assertionListModel.getAssertionAt( ix );
431          if( UISupport.confirm( "Remove assertion [" + assertion.getName() + "]", "Remove Assertion"))
432          {
433          	assertable.removeAssertion( assertion );
434          }
435       }
436    }
437 }