View Javadoc

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