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 com.eviware.soapui.SoapUI;
16  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
17  import com.eviware.soapui.impl.wsdl.panels.support.MockTestRunContext;
18  import com.eviware.soapui.impl.wsdl.panels.support.MockTestRunner;
19  import com.eviware.soapui.impl.wsdl.panels.support.TestRunComponentEnabler;
20  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
21  import com.eviware.soapui.impl.wsdl.teststeps.*;
22  import com.eviware.soapui.impl.wsdl.teststeps.PropertyTransfersTestStep.PropertyTransferResult;
23  import com.eviware.soapui.model.ModelItem;
24  import com.eviware.soapui.model.TestModelItem;
25  import com.eviware.soapui.model.TestPropertyHolder;
26  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
27  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
28  import com.eviware.soapui.model.support.TestRunListenerAdapter;
29  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
30  import com.eviware.soapui.model.testsuite.*;
31  import com.eviware.soapui.support.DocumentListenerAdapter;
32  import com.eviware.soapui.support.UISupport;
33  import com.eviware.soapui.support.components.*;
34  import com.eviware.soapui.support.xml.XmlUtils;
35  import com.eviware.soapui.ui.desktop.DesktopPanel;
36  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
37  import org.jdesktop.swingx.JXTable;
38  
39  import javax.swing.*;
40  import javax.swing.event.ChangeEvent;
41  import javax.swing.event.ChangeListener;
42  import javax.swing.event.ListSelectionEvent;
43  import javax.swing.event.ListSelectionListener;
44  import javax.swing.table.AbstractTableModel;
45  import javax.swing.text.Document;
46  import java.awt.*;
47  import java.awt.event.ActionEvent;
48  import java.awt.event.ItemEvent;
49  import java.awt.event.ItemListener;
50  import java.beans.PropertyChangeEvent;
51  import java.beans.PropertyChangeListener;
52  import java.util.ArrayList;
53  import java.util.Arrays;
54  import java.util.Date;
55  import java.util.List;
56  
57  /***
58   * DesktopPanel for TransferResponseValuesTestStep
59   * 
60   * @author Ole.Matzura
61   */
62  
63  public class PropertyTransfersDesktopPanel extends ModelItemDesktopPanel<PropertyTransfersTestStep>
64  {
65  	private final PropertyTransfersTestStep transferStep;
66  	private DefaultListModel listModel;
67  	private JList transferList;
68  	private JTextArea sourceArea;
69  	private JTextArea targetArea;
70  	private JButton copyButton;
71  	private JButton deleteButton;
72  	private JButton declareButton;
73  	private JComboBox sourcePropertyCombo;
74  	private JComboBox targetPropertyCombo;
75  	private JComboBox sourceStepCombo;
76  	private JComboBox targetStepCombo;
77  	private DefaultComboBoxModel sourceStepModel;
78  	private DefaultComboBoxModel targetStepModel;
79  	private TestStepPropertiesListener sourceStepPropertiesListener;
80  	private TestStepPropertiesListener targetStepPropertiesListener;
81  	private TransferPropertyChangeListener transferPropertyChangeListener = new TransferPropertyChangeListener();
82  	private boolean selecting;
83  	private InternalTestSuiteListener testSuiteListener;
84  	private TestRunComponentEnabler componentEnabler;
85  	private JCheckBox failTransferCheckBox;
86  	private JButton runButton;
87  	private JButton renameButton;
88  	private JCheckBox setNullCheckBox;
89  	private JCheckBox transferTextContentCheckBox;
90  	private JCheckBox ignoreEmptyCheckBox;
91  	private JCheckBox transferAllCheckBox;
92  	private DesktopPanel resultDesktopPanel;
93  	private TransfersTableModel transferLogTableModel;
94  	private InternalTestRunListener testRunListener;
95  	private JComponentInspector<JComponent> logInspector;
96  	private JCheckBox useXQueryCheckBox;
97  	private JButton runAllButton;
98  	private JInspectorPanel inspectorPanel;
99  	private JXTable logTable;
100    private JToggleButton disableButton;
101 
102    public PropertyTransfersDesktopPanel( PropertyTransfersTestStep testStep)
103 	{
104 		super( testStep );
105 		this.transferStep = testStep;
106 		componentEnabler = new TestRunComponentEnabler( testStep.getTestCase() );
107 		
108 		buildUI();
109 		
110 		testSuiteListener = new InternalTestSuiteListener();
111 		transferStep.getTestCase().getTestSuite().addTestSuiteListener( testSuiteListener );
112 		
113 		testRunListener = new InternalTestRunListener();
114 		transferStep.getTestCase().addTestRunListener( testRunListener );
115 	}
116 
117    protected void buildUI()
118 	{
119 		JSplitPane splitPane = UISupport.createHorizontalSplit();
120 		
121 		listModel = new DefaultListModel();
122 		
123 		for( int c = 0; c < transferStep.getTransferCount(); c++ )
124 		{
125          String name = transferStep.getTransferAt( c ).getName();
126          if( transferStep.getTransferAt( c ).isDisabled())
127             name += " (disabled)";
128 
129          listModel.addElement( name );
130 		}
131 		
132 		transferList = new JList( listModel );
133 		transferList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
134 		transferList.addListSelectionListener( new TransferListSelectionListener());
135 		componentEnabler.add( transferList );
136 		
137 		JScrollPane listScrollPane = new JScrollPane( transferList );
138 		UISupport.addTitledBorder( listScrollPane, "Transfers" );
139 		
140 		JPanel p = new JPanel( new BorderLayout() );
141 		p.add( listScrollPane, BorderLayout.CENTER );
142 		p.add( createPropertiesToolbar(), BorderLayout.NORTH );
143 
144 		splitPane.setLeftComponent( p );
145 		
146 		JSplitPane innerSplit = UISupport.createVerticalSplit();
147 		innerSplit.setBorder( null );
148 		sourceArea = new JUndoableTextArea();
149 		sourceArea.setToolTipText( "XPath selection from source property" );
150 		sourceArea.setEnabled( false );
151 		sourceArea.getDocument().addDocumentListener( new SourceAreaDocumentListener());
152 		componentEnabler.add( sourceArea );
153 		
154 		targetArea = new JUndoableTextArea();
155 		targetArea.setToolTipText( "XPath target in target property" );
156 		targetArea.setEnabled( false );
157 		targetArea.getDocument().addDocumentListener( new TargetAreaDocumentListener());
158 		componentEnabler.add( targetArea );
159 		
160 		JPanel sourcePanel = new JPanel( new BorderLayout() );
161 		sourcePanel.add( new JScrollPane( sourceArea ), BorderLayout.CENTER );
162 		JXToolBar toolbar = createSourceToolbar();
163 		sourcePanel.add( toolbar, BorderLayout.NORTH );
164 		sourcePanel.setBorder( BorderFactory.createEmptyBorder( 0, 3, 3, 3 ));
165 		innerSplit.setTopComponent( sourcePanel );
166 		
167 		JPanel targetPanel = new JPanel( new BorderLayout() );
168 		targetPanel.add( new JScrollPane( targetArea ), BorderLayout.CENTER );
169 		toolbar = createTargetToolbar();
170 		targetPanel.add( toolbar, BorderLayout.NORTH );
171 		targetPanel.setBorder( BorderFactory.createEmptyBorder( 0, 3, 3, 3 ));
172 		
173 		innerSplit.setBottomComponent( targetPanel );
174 		
175 		innerSplit.setResizeWeight( 0.5 );
176 		innerSplit.setDividerLocation( 0.5 );
177 		
178 		JPanel panel = createTransferOptions();
179 		
180 		JPanel innerPanel = new JPanel( new BorderLayout() );
181 		innerPanel.add( innerSplit, BorderLayout.CENTER );
182 		innerPanel.add( panel, BorderLayout.SOUTH );
183 		innerPanel.add( createConfigToolbar(), BorderLayout.NORTH );
184 		
185 		splitPane.setRightComponent( innerPanel );
186 		splitPane.setResizeWeight( 0.1 );
187 		splitPane.setDividerLocation( 120 );
188 		
189 		inspectorPanel = JInspectorPanelFactory.build( splitPane );
190 		logInspector = new JComponentInspector<JComponent>( buildLog(), "Transfer Log (0)", "A log of performed transfers while the editor was open", true );
191 		inspectorPanel.addInspector( logInspector );
192 		add( inspectorPanel.getComponent(), BorderLayout.CENTER );
193 		
194 		setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ));
195 		setPreferredSize( new Dimension( 550, 400 ));
196 		
197 		if( listModel.getSize() > 0 ) 
198 			transferList.setSelectedIndex( 0 );
199 		
200 		componentEnabler.add( deleteButton );
201 		componentEnabler.add( declareButton );
202 		componentEnabler.add( runButton );
203 		componentEnabler.add( runAllButton );
204 		componentEnabler.add( copyButton );
205 		componentEnabler.add( renameButton );
206 		componentEnabler.add( failTransferCheckBox );
207 		componentEnabler.add( setNullCheckBox );
208 		componentEnabler.add( transferTextContentCheckBox );
209 		componentEnabler.add( ignoreEmptyCheckBox );
210 		componentEnabler.add( transferAllCheckBox );
211 		componentEnabler.add( useXQueryCheckBox );
212 	}
213 
214 	private JComponent buildLog()
215 	{
216 		JPanel logPanel = new JPanel( new BorderLayout() );
217 		
218 		transferLogTableModel = new TransfersTableModel();
219 		logTable = new JXTable( transferLogTableModel );
220 		logTable.getSelectionModel().addListSelectionListener( new ListSelectionListener() {
221 
222 			public void valueChanged(ListSelectionEvent e)
223 			{
224 				int row = logTable.getSelectedRow();
225 				if( row != -1 )
226 				{
227 					String transferName = transferLogTableModel.getValueAt(row, 1).toString();
228 					int ix = listModel.indexOf(transferName);
229 					if( ix != -1 )
230 					{
231 						transferList.setSelectedIndex(ix);
232 					}
233 				}
234 			}} );
235 		
236 		logTable.setHorizontalScrollEnabled( true );
237 		logTable.packAll();
238 		
239 		JXToolBar toolbar = UISupport.createSmallToolbar();
240 		toolbar.add( new ClearLogAction() );
241 		
242 		JScrollPane scrollPane = new JScrollPane( logTable);
243 		scrollPane.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ), 
244 					scrollPane.getBorder() ));
245 		
246 		logPanel.add( toolbar, BorderLayout.NORTH );
247 		logPanel.add( scrollPane, BorderLayout.CENTER );
248 		
249 		return logPanel;
250 	}
251 
252 	protected JXToolBar createPropertiesToolbar()
253 	{
254 		JXToolBar toolbar = UISupport.createSmallToolbar();
255 		toolbar.addFixed( UISupport.createToolbarButton( new AddAction() ) );
256 		deleteButton = UISupport.createToolbarButton( new DeleteAction() );
257 		deleteButton.setEnabled( false );
258 		toolbar.addFixed( deleteButton);
259 		copyButton = UISupport.createToolbarButton( new CopyAction() );
260 		copyButton.setEnabled( false );
261 		toolbar.addFixed( copyButton);
262 		renameButton = UISupport.createToolbarButton( new RenameAction() );
263 		renameButton.setEnabled( false );
264 		toolbar.addFixed( renameButton);
265 
266       disableButton = new JToggleButton( new DisableAction() );
267       disableButton.setPreferredSize( UISupport.TOOLBAR_BUTTON_DIMENSION );
268       disableButton.setSelectedIcon( UISupport.createImageIcon( "/bullet_red.png" ));
269       toolbar.addSeparator( );
270       toolbar.addFixed( disableButton );
271 
272 		return toolbar;
273 	}
274 	
275 	protected JXToolBar createConfigToolbar()
276 	{
277 		JXToolBar toolbar = UISupport.createToolbar();
278 		
279 		toolbar.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
280 		
281 		runButton = UISupport.createToolbarButton( new RunAction() );
282 		runButton.setEnabled( transferList.getSelectedIndex() != -1 );
283 		toolbar.addFixed( runButton);
284 		
285 		runAllButton = UISupport.createToolbarButton( new RunAllAction() );
286 		runAllButton.setEnabled( transferStep.getTransferCount() > 0 );
287 		toolbar.addFixed( runAllButton);
288 		
289 		declareButton = UISupport.createToolbarButton( new DeclareNamespacesAction() );
290 		declareButton.setEnabled( false );
291 		toolbar.addFixed( declareButton);
292 		toolbar.addGlue();
293 		toolbar.addFixed( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.TRANSFERSTEPEDITOR_HELP_URL )));
294 		return toolbar;
295 	}
296 
297 	protected JPanel createTransferOptions()
298 	{
299 		JPanel panel = new JPanel( new GridLayout( 3, 2 ));
300 		failTransferCheckBox = new JCheckBox( "Fail transfer on error", false );
301 		failTransferCheckBox.setToolTipText( "Fails the Property Transfer Step if an error occurs" );
302 		failTransferCheckBox.addChangeListener( new ChangeListener() {
303 
304 			public void stateChanged(ChangeEvent e)
305 			{
306 				PropertyTransfer currentTransfer = getCurrentTransfer();
307 				if( currentTransfer != null )
308 				{
309 					currentTransfer.setFailOnError( failTransferCheckBox.isSelected() );
310 				}
311 			}} );
312 		
313 		setNullCheckBox = new JCheckBox( "Set null on missing source", false );
314 		setNullCheckBox.setToolTipText( "Will set target to null if source is missing or null" );
315 		setNullCheckBox.addChangeListener( new ChangeListener() {
316 
317 			public void stateChanged(ChangeEvent e)
318 			{
319 				PropertyTransfer currentTransfer = getCurrentTransfer();
320 				if( currentTransfer != null )
321 				{
322 					currentTransfer.setSetNullOnMissingSource( setNullCheckBox.isSelected() );
323 				}
324 			}} );
325 		
326 		transferTextContentCheckBox = new JCheckBox( "Transfer text content", false );
327 		transferTextContentCheckBox.setToolTipText( "Will only transfer text content of source/target elements" );
328 		transferTextContentCheckBox.addChangeListener( new ChangeListener() {
329 
330 			public void stateChanged(ChangeEvent e)
331 			{
332 				PropertyTransfer currentTransfer = getCurrentTransfer();
333 				if( currentTransfer != null )
334 				{
335 					currentTransfer.setTransferTextContent( transferTextContentCheckBox.isSelected() );
336 				}
337 			}} );
338 		
339 		ignoreEmptyCheckBox = new JCheckBox( "Ignore empty/missing values", false );
340 		ignoreEmptyCheckBox.setToolTipText( "Will not transfer empty or missing values" );
341 		ignoreEmptyCheckBox.addChangeListener( new ChangeListener() {
342 
343 			public void stateChanged(ChangeEvent e)
344 			{
345 				PropertyTransfer currentTransfer = getCurrentTransfer();
346 				if( currentTransfer != null )
347 				{
348 					currentTransfer.setIgnoreEmpty( ignoreEmptyCheckBox.isSelected() );
349 				}
350 			}} );
351 		
352 		transferAllCheckBox = new JCheckBox( "Transfer to all", false );
353 		transferAllCheckBox.setToolTipText( "Will transfer to all matching target selections" );
354 		transferAllCheckBox.addChangeListener( new ChangeListener() {
355 
356 			public void stateChanged(ChangeEvent e)
357 			{
358 				PropertyTransfer currentTransfer = getCurrentTransfer();
359 				if( currentTransfer != null )
360 				{
361 					currentTransfer.setTransferToAll( transferAllCheckBox.isSelected() );
362 				}
363 			}} );
364 		
365 		useXQueryCheckBox = new JCheckBox( "Use XQuery", false );
366 		useXQueryCheckBox.setToolTipText( "Interprets the source xpath as an XQuery expression" );
367 		useXQueryCheckBox.addChangeListener( new ChangeListener() {
368 
369 			public void stateChanged(ChangeEvent e)
370 			{
371 				PropertyTransfer currentTransfer = getCurrentTransfer();
372 				if( currentTransfer != null )
373 				{
374 					currentTransfer.setUseXQuery( useXQueryCheckBox.isSelected() );
375 				}
376 			}} );
377 		
378 		panel.add( failTransferCheckBox );
379 		panel.add( setNullCheckBox );
380 		panel.add( transferTextContentCheckBox );
381 		panel.add( ignoreEmptyCheckBox );
382 		panel.add( transferAllCheckBox );
383 		panel.add( useXQueryCheckBox );
384 		panel.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
385 		return panel;
386 	}
387 
388 	protected JXToolBar createTargetToolbar()
389 	{
390 		JXToolBar toolbar;
391 		toolbar = UISupport.createToolbar();
392 		toolbar.addSpace( 3 );
393 		toolbar.addFixed( new JLabel( "<html><b>Target:</b></html>"));
394 		toolbar.addUnrelatedGap();
395 		
396 		targetStepCombo.setSelectedItem( null );
397 		targetStepCombo.setToolTipText( "The step the value will be transferred to" );
398 		targetStepCombo.setEnabled( false );
399 		targetStepCombo.addItemListener( 
400 				new StepComboItemListener( targetPropertyCombo, targetStepPropertiesListener ) );
401 		targetStepCombo.addItemListener( new ItemListener() {
402 
403 			public void itemStateChanged(ItemEvent e)
404 			{
405 				if( e.getStateChange() == ItemEvent.SELECTED && !selecting )
406 				{
407 					TestPropertyHolder targetStep = ( TestPropertyHolder ) targetStepCombo.getSelectedItem();
408 					PropertyTransfer valueTransfer = getCurrentTransfer();
409 					
410 					if( valueTransfer != null )
411 					{
412 						String name = "";
413 						
414 						if( targetStep == PropertyExpansionUtils.getGlobalProperties() )
415 							name = PropertyExpansion.GLOBAL_REFERENCE;
416 						else if( targetStep == transferStep.getTestCase().getTestSuite().getProject() )
417 							name = PropertyExpansion.PROJECT_REFERENCE;
418 						else if( targetStep == transferStep.getTestCase().getTestSuite())
419 							name = PropertyExpansion.TESTSUITE_REFERENCE;
420 						else if( targetStep == transferStep.getTestCase() )
421 							name = PropertyExpansion.TESTCASE_REFERENCE;
422 						else
423 						   name = targetStep.getModelItem().getName();
424 						
425 						valueTransfer.setTargetStepName( name );
426 					}
427 				}
428 			}} );
429 		
430 		toolbar.add( UISupport.setFixedSize( targetStepCombo, 180, 21 ) );
431 		toolbar.addUnrelatedGap();
432 		
433 		toolbar.addFixed( new JLabel( "Property:"));
434 		toolbar.addRelatedGap();
435 		
436 		targetPropertyCombo.setToolTipText( "The property the value will be transferred to" );
437 		targetPropertyCombo.setEnabled( false );
438 		targetPropertyCombo.addItemListener( new ItemListener() {
439 
440 			public void itemStateChanged(ItemEvent e)
441 			{
442 				if( e.getStateChange() == ItemEvent.SELECTED && !selecting )
443 				{
444 					TestProperty targetProperty = (TestProperty) targetPropertyCombo.getSelectedItem();
445 					PropertyTransfer valueTransfer = getCurrentTransfer();
446 					
447 					if( valueTransfer != null )
448 					{
449 						valueTransfer.setTargetPropertyName( targetProperty.getName() );
450 					}
451 				}
452 			}} );
453 		
454 		toolbar.add( UISupport.setFixedSize( targetPropertyCombo, 180, 21 ) );
455 		toolbar.addGlue();
456 		return toolbar;
457 	}
458 
459 	protected JXToolBar createSourceToolbar()
460 	{
461 		JXToolBar toolbar = UISupport.createToolbar();
462 		toolbar.addSpace( 3 );
463 		toolbar.addFixed( new JLabel( "<html><b>Source:</b></html>"));
464 		toolbar.addUnrelatedGap();
465 
466 		sourcePropertyCombo = new JComboBox();
467 		sourceStepModel = new DefaultComboBoxModel();
468 		sourceStepCombo = new JComboBox( sourceStepModel );
469 		sourceStepCombo.setRenderer( new StepComboRenderer() );
470 		sourcePropertyCombo.setRenderer( new PropertyComboRenderer() );
471 		
472 		componentEnabler.add( sourcePropertyCombo );
473 		componentEnabler.add( sourceStepCombo );
474 		
475 		targetPropertyCombo = new JComboBox();
476 		targetStepModel = new DefaultComboBoxModel();
477 		targetStepCombo = new JComboBox( targetStepModel );
478 		targetStepCombo.setRenderer( new StepComboRenderer() );
479 		targetPropertyCombo.setRenderer( new PropertyComboRenderer() );
480 		
481 		componentEnabler.add( targetPropertyCombo );
482 		componentEnabler.add( targetStepCombo );
483 		
484 		sourceStepPropertiesListener = new TestStepPropertiesListener( sourcePropertyCombo );
485 		targetStepPropertiesListener = new TestStepPropertiesListener( targetPropertyCombo );
486 		
487 		sourceStepModel.addElement( PropertyExpansionUtils.getGlobalProperties() );
488 		sourceStepModel.addElement( transferStep.getTestCase().getTestSuite().getProject() );
489 		sourceStepModel.addElement( transferStep.getTestCase().getTestSuite() );
490 		sourceStepModel.addElement( transferStep.getTestCase() );
491 		
492 		for( int c = 0; c < transferStep.getTestCase().getTestStepCount(); c++ )
493 		{
494 			WsdlTestStep testStep = transferStep.getTestCase().getTestStepAt( c );
495 			if( testStep == transferStep )
496 				continue;
497 			
498 			sourceStepModel.addElement( testStep );
499 		}
500 		
501 		for( int c = 0; c < sourceStepModel.getSize(); c++ )
502 			targetStepModel.addElement( sourceStepModel.getElementAt( c ) );
503 		
504 		sourceStepCombo.setSelectedItem( null );
505 		sourceStepCombo.setToolTipText( "The step the value will be transferred from" );
506 		sourceStepCombo.setEnabled( false );
507 		sourceStepCombo.addItemListener( 
508 				new StepComboItemListener( sourcePropertyCombo, sourceStepPropertiesListener ) );
509 		sourceStepCombo.addItemListener( new ItemListener() {
510 
511 			public void itemStateChanged(ItemEvent e)
512 			{
513 				if( e.getStateChange() == ItemEvent.SELECTED && !selecting )
514 				{
515 					TestPropertyHolder sourceStep = ( TestPropertyHolder ) sourceStepCombo.getSelectedItem();
516 					PropertyTransfer valueTransfer = getCurrentTransfer();
517 					
518 					if( valueTransfer != null )
519 					{
520 						String name = "";
521 						
522 						if( sourceStep == PropertyExpansionUtils.getGlobalProperties() )
523 							name = PropertyExpansion.GLOBAL_REFERENCE;
524 						else if( sourceStep == transferStep.getTestCase().getTestSuite().getProject() )
525 							name = PropertyExpansion.PROJECT_REFERENCE;
526 						else if( sourceStep == transferStep.getTestCase().getTestSuite())
527 							name = PropertyExpansion.TESTSUITE_REFERENCE;
528 						else if( sourceStep == transferStep.getTestCase() )
529 							name = PropertyExpansion.TESTCASE_REFERENCE;
530 						else
531 						   name = sourceStep.getModelItem().getName();
532 						
533 						valueTransfer.setSourceStepName( name );
534 					}
535 				}
536 			}} );
537 		
538 		toolbar.add( UISupport.setFixedSize( sourceStepCombo, 180, 21 ));
539 		toolbar.addUnrelatedGap();
540 		
541 		toolbar.addFixed( new JLabel( "Property:"));
542 		toolbar.addRelatedGap();
543 		
544 		sourcePropertyCombo.setToolTipText( "The property the value will be transferred from" );
545 		sourcePropertyCombo.setEnabled( false );
546 		sourcePropertyCombo.addItemListener( new ItemListener() {
547 
548 			public void itemStateChanged(ItemEvent e)
549 			{
550 				if( e.getStateChange() == ItemEvent.SELECTED && !selecting )
551 				{
552 					TestProperty sourceProperty = (TestProperty) sourcePropertyCombo.getSelectedItem();
553 					PropertyTransfer valueTransfer = getCurrentTransfer();
554 					
555 					if( valueTransfer != null )
556 					{
557 						valueTransfer.setSourcePropertyName( sourceProperty.getName() );
558 					}
559 				}
560 			}} );
561 		
562 		toolbar.add( UISupport.setFixedSize( sourcePropertyCombo, 180, 21 ) );
563 		toolbar.addGlue();
564 		return toolbar;
565 	}
566 	
567 	public PropertyTransfer getCurrentTransfer()
568 	{
569 		int ix = transferList.getSelectedIndex();
570 		return ix == -1 ? null : transferStep.getTransferAt( ix );
571 	}
572 
573 	/***
574 	 * Listen for testStep property changes and update properties combo accordingly
575 	 */
576 	
577 	private final class TestStepPropertiesListener implements TestPropertyListener
578 	{
579 		private final JComboBox combo;
580 
581 		public TestStepPropertiesListener(JComboBox combo)
582 		{
583 			this.combo = combo;
584 		}
585 
586 		public void propertyAdded(String name)
587 		{
588 			TestProperty property = combo == targetPropertyCombo ?
589 				getCurrentTransfer().getTargetStep().getProperty( name ) :
590 				getCurrentTransfer().getSourceStep().getProperty( name );
591 			
592 			combo.addItem( property );
593 			combo.setEnabled( true );
594 		}
595 
596 		public void propertyRemoved(String name)
597 		{
598 			if( ((TestProperty)combo.getSelectedItem()).getName().equals( name ))
599 				combo.setSelectedItem( null );
600 			
601 			for( int c = 0; c < combo.getItemCount(); c++ )
602 			{
603 				if( ((TestProperty)combo.getItemAt( c )).getName().equals( name ))
604 				{
605 					combo.removeItemAt( c );
606 					break;
607 				}			
608 			}
609 			
610 			combo.setEnabled( combo.getItemCount() > 0 );
611 		}
612 
613 		public void propertyRenamed(String oldName, String newName)
614 		{
615 		}
616 
617 		public void propertyValueChanged(String name, String oldValue, String newValue)
618 		{
619 		}
620 
621 		public void propertyMoved(String name, int oldIndex, int newIndex)
622 		{
623 			combo.removeItemAt( oldIndex );
624 
625 			TestProperty property = combo == targetPropertyCombo ?
626 					getCurrentTransfer().getTargetStep().getProperty( name ) :
627 					getCurrentTransfer().getSourceStep().getProperty( name );
628 					
629 			combo.insertItemAt( property, newIndex );
630 		}
631 	}
632 
633 	/***
634 	 * Listen for teststep changes and update source/target step combos accordingly
635 	 */
636 	
637 	private final class InternalTestSuiteListener extends TestSuiteListenerAdapter
638 	{
639 		public void testStepAdded(TestStep testStep, int index)
640 		{
641 			if( testStep.getTestCase() == transferStep.getTestCase() )
642 			{
643 				sourceStepModel.addElement( testStep );
644 				targetStepModel.addElement( testStep );
645 			}
646 		}
647 
648 		public void testStepMoved(TestStep testStep, int fromIndex, int offset)
649 		{
650 			if( testStep.getTestCase() == transferStep.getTestCase() )
651 			{
652 				String testStepName = testStep.getName();
653 				if( sourceStepModel.getIndexOf( testStepName ) == fromIndex )
654 				{
655 					String sourceStep = ( String ) sourceStepCombo.getSelectedItem();
656 					String sourceProperty = ( String ) sourcePropertyCombo.getSelectedItem();
657 					
658 					sourceStepModel.removeElementAt( fromIndex );
659 					if( fromIndex + offset > sourceStepModel.getSize() )
660 						sourceStepModel.addElement( testStepName );
661 					else 
662 						sourceStepModel.insertElementAt( testStepName, fromIndex + offset );
663 					
664 					sourceStepCombo.setSelectedItem( sourceStep );
665 					sourcePropertyCombo.setSelectedItem( sourceProperty );
666 				}
667 				
668 				if( targetStepModel.getIndexOf( testStepName ) == fromIndex )
669 				{
670 					String targetStep = ( String ) targetStepCombo.getSelectedItem();
671 					String targetProperty = ( String ) targetPropertyCombo.getSelectedItem();
672 					
673 					targetStepModel.removeElementAt( fromIndex );
674 					if( fromIndex + offset > targetStepModel.getSize() )
675 						targetStepModel.addElement( testStepName );
676 					else 
677 						targetStepModel.insertElementAt( testStepName, fromIndex + offset );
678 					
679 					targetStepCombo.setSelectedItem( targetStep );
680 					targetPropertyCombo.setSelectedItem( targetProperty );
681 				}
682 			}
683 		}
684 
685 		public void testStepRemoved(TestStep testStep, int index)
686 		{
687 			if( testStep.getTestCase() == transferStep.getTestCase() )
688 			{
689 				sourceStepModel.removeElement( testStep );
690 				targetStepModel.removeElement( testStep );
691 			}
692 		}
693 	}
694 
695 	/***
696 	 * Listen to step selections and update properties combo accordingly 
697 	 */
698 	
699 	private final class StepComboItemListener implements ItemListener
700 	{
701 		private final JComboBox propertyCombo;
702 		private final TestStepPropertiesListener testStepPropertiesListener;
703 		
704 		public StepComboItemListener(final JComboBox propertyCombo, TestStepPropertiesListener testStepPropertiesListener)
705 		{
706 			this.propertyCombo = propertyCombo;
707 			this.testStepPropertiesListener = testStepPropertiesListener;
708 		}
709 
710 		public void itemStateChanged(ItemEvent e)
711 		{
712 			if( e.getStateChange() == ItemEvent.SELECTED )
713 			{
714 				TestPropertyHolder selectedItem =  ( TestPropertyHolder ) e.getItem();
715 				String[] propertyNames = selectedItem.getPropertyNames();
716 				
717 				// remove read-only properties from target property
718 				if( propertyCombo == targetPropertyCombo )
719 				{
720 					List<String> names = new ArrayList<String>();
721 					for( String name : propertyNames )
722 					{
723 						TestProperty property = selectedItem.getProperty( name );
724 						if( property != null && !property.isReadOnly() )
725 							names.add( property.getName() );
726 					}
727 					
728 					propertyNames = names.toArray( new String[names.size()] );
729 				}
730 				
731 				DefaultComboBoxModel model = new DefaultComboBoxModel();
732 				for( String name : propertyNames )
733 					model.addElement( selectedItem.getProperty( name ) );
734 				
735 				propertyCombo.setModel( model);
736 				propertyCombo.setEnabled( propertyNames.length > 0 );
737 				
738 				if( propertyCombo == targetPropertyCombo )
739 					propertyCombo.setSelectedItem( getCurrentTransfer().getTargetProperty() );
740 				else
741 					propertyCombo.setSelectedItem( getCurrentTransfer().getSourceProperty() );
742 				
743 				selectedItem.addTestPropertyListener( testStepPropertiesListener );
744 			}
745 			else 
746 			{
747 				propertyCombo.removeAllItems();
748 				propertyCombo.setEnabled( false );
749 			}
750 		}
751 	}
752 
753 	/***
754 	 * Handle updates to source path
755 	 */
756 	
757 	private final class SourceAreaDocumentListener extends DocumentListenerAdapter
758 	{
759 		public void update(Document document)
760 		{
761 			int ix = transferList.getSelectedIndex();
762 			if( ix != -1 )
763 			{
764 				transferStep.getTransferAt( ix ).setSourcePath( sourceArea.getText() );
765 			}
766 		}
767 	}
768 	
769 	/***
770 	 * Handle updates to target path
771 	 */
772 	
773 	private final class TargetAreaDocumentListener extends DocumentListenerAdapter
774 	{
775 		public void update( Document document )
776 		{
777 			int ix = transferList.getSelectedIndex();
778 			if( ix != -1 )
779 			{
780 				transferStep.getTransferAt( ix ).setTargetPath( targetArea.getText() );
781 			}
782 		}
783 	}
784 
785 	/***
786 	 * Listen to selection changes in transfer list and update controls accordingly
787 	 */
788 	
789 	private final class TransferListSelectionListener implements ListSelectionListener
790 	{
791 		private PropertyTransfer transfer;
792 
793 		public void valueChanged(ListSelectionEvent e)
794 		{
795 			selecting = true;
796 			
797 			if( transfer != null )
798 			{
799 				transfer.removePropertyChangeListener( transferPropertyChangeListener );
800 			}
801 			
802 			transfer = getCurrentTransfer();
803 			
804 			if( transfer == null )
805 			{
806 				sourceArea.setText( "" );
807 				targetArea.setText( "" );
808 				
809 				sourcePropertyCombo.removeAllItems();
810 				targetPropertyCombo.removeAllItems();
811 				
812 				sourceStepCombo.setSelectedIndex( -1 );
813 				targetStepCombo.setSelectedIndex( -1 );
814 			}
815 			else
816 			{
817 				transfer.addPropertyChangeListener( transferPropertyChangeListener );
818 				
819 				sourceArea.setText( transfer.getSourcePath() );
820 				sourceArea.setCaretPosition( 0 );
821 				targetArea.setText( transfer.getTargetPath() );
822 				targetArea.setCaretPosition( 0 );
823 
824 				sourceStepCombo.setSelectedItem( transfer.getSourceStep() );
825 				sourcePropertyCombo.setSelectedItem( transfer.getSourceProperty() );
826 				
827 				targetStepCombo.setSelectedItem( transfer.getTargetStep() );
828 				targetPropertyCombo.setSelectedItem( transfer.getTargetProperty() );
829 				
830 				failTransferCheckBox.setSelected( transfer.getFailOnError() );
831 				setNullCheckBox.setSelected( transfer.getSetNullOnMissingSource() );
832 				transferTextContentCheckBox.setSelected( transfer.getTransferTextContent() );
833 				ignoreEmptyCheckBox.setSelected( transfer.getIgnoreEmpty() );
834 				transferAllCheckBox.setSelected( transfer.getTransferToAll() );
835 				useXQueryCheckBox.setSelected( transfer.getUseXQuery() );
836 
837             disableButton.setSelected( transfer.isDisabled() );
838 			}
839 			
840 			copyButton.setEnabled( transfer != null );
841 			renameButton.setEnabled( transfer != null );
842 			deleteButton.setEnabled( transfer != null );
843          disableButton.setEnabled( transfer != null );
844 			declareButton.setEnabled( transfer != null );
845 			sourceStepCombo.setEnabled( transfer != null );
846 			targetStepCombo.setEnabled( transfer != null );
847 			sourceArea.setEnabled( transfer != null );
848 			targetArea.setEnabled( transfer != null );
849 			failTransferCheckBox.setEnabled( transfer != null );
850 			setNullCheckBox.setEnabled( transfer != null );
851 			transferTextContentCheckBox.setEnabled( transfer != null );
852 			ignoreEmptyCheckBox.setEnabled( transfer != null );
853 			transferAllCheckBox.setEnabled( transfer != null );
854 			useXQueryCheckBox.setEnabled( transfer != null );
855 			
856 			runAllButton.setEnabled( transferList.getModel().getSize() > 0 );
857 			runButton.setEnabled( transfer != null );
858 
859 			sourcePropertyCombo.setEnabled( transfer != null );
860 			targetPropertyCombo.setEnabled( transfer != null );
861 			
862 			selecting = false;
863 		}
864 	}
865 	
866 	/***
867 	 * Listen to property changes and update UI objects. These may have been triggered by UI so first check
868 	 * for actual difference so we dont end up in loop.
869 	 */
870 
871 	private class TransferPropertyChangeListener implements PropertyChangeListener
872 	{
873 		public void propertyChange(PropertyChangeEvent evt)
874 		{
875 			Object newValue = evt.getNewValue();
876 			
877 			if( evt.getPropertyName().equals( PropertyTransfer.SOURCE_PATH_PROPERTY ))
878 			{
879 				if( !sourceArea.getText().equals( newValue ))
880 					sourceArea.setText( (String) newValue );
881 			}
882 			else if( evt.getPropertyName().equals( PropertyTransfer.TARGET_PATH_PROPERTY ))
883 			{
884 				if( !targetArea.getText().equals( newValue ))
885 					targetArea.setText( (String) newValue );
886 			}
887 			else if( evt.getPropertyName().equals( PropertyTransfer.SOURCE_STEP_PROPERTY ))
888 			{
889 				Object selectedItem = sourceStepCombo.getSelectedItem();
890 				if( newValue == null || selectedItem == null || !selectedItem.equals( newValue ))
891 				{
892 					selecting = true;
893 					sourceStepCombo.setSelectedItem( newValue );
894 					selecting = false;
895 				}
896 			}
897 			else if( evt.getPropertyName().equals( PropertyTransfer.TARGET_STEP_PROPERTY ))
898 			{
899 				Object selectedItem = targetStepCombo.getSelectedItem();
900 				if( newValue == null || selectedItem == null || !selectedItem.equals( newValue ))
901 				{
902 					selecting = true;
903 					targetStepCombo.setSelectedItem( newValue );
904 					selecting = false;
905 				}
906 			}
907 			else if( evt.getPropertyName().equals( PropertyTransfer.SOURCE_TYPE_PROPERTY ))
908 			{
909 				Object selectedItem = sourcePropertyCombo.getSelectedItem();
910 				if( selectedItem == null || !selectedItem.equals( newValue ))
911 					sourcePropertyCombo.setSelectedItem( newValue );
912 			}
913 			else if( evt.getPropertyName().equals( PropertyTransfer.TARGET_TYPE_PROPERTY ))
914 			{
915 				Object selectedItem = targetPropertyCombo.getSelectedItem();
916 				if( selectedItem == null || !selectedItem.equals( newValue ))
917 					targetPropertyCombo.setSelectedItem( newValue );
918 			}
919 		}
920 	}
921 	
922 	private final class AddAction extends AbstractAction
923 	{
924 		public AddAction()
925 		{
926 			putValue( Action.SHORT_DESCRIPTION, "Adds a new Property Transfer" );
927 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/add_property.gif" ));
928 		}
929 		
930 		public void actionPerformed(ActionEvent e)
931 		{
932 			String name = UISupport.prompt( "Specify name for value transfer", "Add Transfer", "" );
933 			if( name == null || name.trim().length() == 0 ) return;
934 			
935 			transferStep.addTransfer( name );
936 			
937 			listModel.addElement( name );
938 			transferList.setSelectedIndex( listModel.getSize()-1 );
939 		}
940 	}
941 	
942 	private final class CopyAction extends AbstractAction
943 	{
944 		public CopyAction()
945 		{
946 			putValue( Action.SHORT_DESCRIPTION, "Copies the selected Property Transfer" );
947 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clone_request.gif" ));
948 		}
949 		
950 		public void actionPerformed(ActionEvent e)
951 		{
952 			int ix = transferList.getSelectedIndex();
953 			PropertyTransfer config = transferStep.getTransferAt( ix );
954 			
955 			String name = UISupport.prompt( "Specify name for value transfer", "Copy Transfer", config.getName() );
956 			if( name == null || name.trim().length() == 0 ) return;
957 			
958 			PropertyTransfer transfer = transferStep.addTransfer( name );
959 			transfer.setSourceStepName( config.getSourceStepName() );
960 			transfer.setSourcePropertyName( config.getSourcePropertyName() );
961 			transfer.setSourcePath( config.getSourcePath() );
962 			transfer.setTargetStepName( config.getTargetStepName() );
963 			transfer.setTargetPropertyName( config.getTargetPropertyName() );
964 			transfer.setTargetPath( config.getTargetPath() );
965 			
966 			listModel.addElement( name );
967 			transferList.setSelectedIndex( listModel.getSize()-1 );
968 		}
969 	}
970 	
971 	private final class DeleteAction extends AbstractAction
972 	{
973 		public DeleteAction()
974 		{
975 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/remove_property.gif" ));
976 			putValue( Action.SHORT_DESCRIPTION, "Deletes the selected Property Transfer" );
977 		}
978 		
979 		public void actionPerformed(ActionEvent e)
980 		{
981 			if( UISupport.confirm( "Delete selected transfer", "Delete Transfer" )) 
982 			{
983 				transferList.setSelectedIndex( -1 );
984 				
985 				int ix = transferList.getSelectedIndex();
986 				transferStep.removeTransferAt( ix );
987 				listModel.remove( ix );
988 				
989 				if( listModel.getSize() > 0 )
990 				{
991 					transferList.setSelectedIndex( ix > listModel.getSize()-1 ? listModel.getSize()-1 : ix );
992 				}
993 			}
994 		}
995 	}
996 	
997 	private final class ClearLogAction extends AbstractAction
998 	{
999 		public ClearLogAction()
1000 		{
1001 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clear_properties.gif" ));
1002 			putValue( Action.SHORT_DESCRIPTION, "Clears the property-transfer log" );
1003 		}
1004 		
1005 		public void actionPerformed(ActionEvent e)
1006 		{
1007 			transferLogTableModel.clear();
1008 		}
1009 	}
1010 	
1011 	private final class RenameAction extends AbstractAction
1012 	{
1013 		public RenameAction()
1014 		{
1015 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/rename.gif" ));
1016 			putValue( Action.SHORT_DESCRIPTION, "Renames the selected Property Transfer" );
1017 		}
1018 		
1019 		public void actionPerformed(ActionEvent e)
1020 		{
1021 			PropertyTransfer transfer = getCurrentTransfer();
1022 			
1023 			String newName = UISupport.prompt( "Specify new name for transfer", "Rename Transfer", transfer.getName() );
1024 			
1025 			if( newName != null && !transfer.getName().equals( newName )) 
1026 			{
1027 				listModel.setElementAt( newName, transferList.getSelectedIndex() );
1028 				transfer.setName( newName );
1029 			}
1030 		}
1031 	}
1032 
1033    private final class DisableAction extends AbstractAction
1034 	{
1035 		public DisableAction()
1036 		{
1037 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/bullet_green.png" ));
1038 			putValue( Action.SHORT_DESCRIPTION, "Disables the selected Property Transfer" );
1039 		}
1040 
1041 		public void actionPerformed(ActionEvent e)
1042 		{
1043 			PropertyTransfer transfer = getCurrentTransfer();
1044          transfer.setDisabled( disableButton.isSelected() );
1045 
1046          String name = transfer.getName();
1047          if( transfer.isDisabled())
1048             name += " (disabled)";
1049 
1050          listModel.setElementAt( name, transferList.getSelectedIndex() );
1051 		}
1052 	}
1053 	
1054 	private final class DeclareNamespacesAction extends AbstractAction
1055 	{
1056 		public DeclareNamespacesAction()
1057 		{
1058 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/declareNs.gif" ));
1059 			putValue( Action.SHORT_DESCRIPTION, "Declare available response/request namespaces in source/target expressions" );
1060 		}
1061 		
1062 		public void actionPerformed(ActionEvent e)
1063 		{
1064 			try
1065 			{
1066 				TestPropertyHolder previousStep = getCurrentTransfer().getSourceStep();
1067 				
1068 				if ( previousStep instanceof WsdlTestRequestStep )
1069 				{
1070 					WsdlTestRequest testRequest = ((WsdlTestRequestStep)previousStep).getTestRequest();
1071 					sourceArea.setText( XmlUtils.declareXPathNamespaces( testRequest.getOperation().getInterface() ) + sourceArea.getText() );
1072 				}
1073 				else UISupport.showErrorMessage( "Property Source is not a Request" );
1074 
1075 				TestPropertyHolder nextStep = getCurrentTransfer().getTargetStep();
1076 				
1077 				if (nextStep instanceof WsdlTestRequestStep)
1078 				{
1079 					WsdlTestRequest testRequest = ((WsdlTestRequestStep)nextStep).getTestRequest();
1080 					targetArea.setText( XmlUtils.declareXPathNamespaces( testRequest.getOperation().getInterface()) + targetArea.getText() );
1081 				}
1082 				else UISupport.showErrorMessage( "Property Target is not a Request" );
1083 			}
1084 			catch (Exception e1)
1085 			{
1086 				UISupport.showErrorMessage( e1 );
1087 			}
1088 		}
1089 	}
1090 	
1091 	private final class RunAllAction extends AbstractAction
1092 	{
1093 		public RunAllAction()
1094 		{
1095 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_all.gif" ));
1096 			putValue( Action.SHORT_DESCRIPTION, "Runs all Property Transfers" );
1097 		}
1098 		
1099 		public void actionPerformed(ActionEvent e)
1100 		{
1101 			if( listModel.getSize() == 0 )
1102 			{
1103 				UISupport.showErrorMessage( "Missing transfers!" );
1104 				return;
1105 			}
1106 			
1107 			MockTestRunner mockRunner = new MockTestRunner( transferStep.getTestCase() );
1108 			MockTestRunContext context = new MockTestRunContext( mockRunner, transferStep );
1109 			
1110 			for( int c = 0; c < transferStep.getTransferCount(); c++ )
1111 			{
1112 				PropertyTransfer transfer = transferStep.getTransferAt(c);
1113 				PropertyTransfersTestStep.PropertyTransferResult result = (PropertyTransfersTestStep.PropertyTransferResult) transferStep.run( mockRunner, context, transfer );
1114 				transferLogTableModel.addResult( result );
1115 			}
1116 		}
1117 	}
1118 	
1119 	private final class RunAction extends AbstractAction
1120 	{
1121 		public RunAction()
1122 		{
1123 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run.gif" ));
1124 			putValue( Action.SHORT_DESCRIPTION, "Runs selected PropertyTransfer" );
1125 		}
1126 		
1127 		public void actionPerformed(ActionEvent e)
1128 		{
1129 			if( transferList.getSelectedIndex() == -1 )
1130 			{
1131 				UISupport.showErrorMessage( "No transfer selectd!" );
1132 				return;
1133 			}
1134 			
1135 			MockTestRunner mockRunner = new MockTestRunner( transferStep.getTestCase() );
1136 			MockTestRunContext context = new MockTestRunContext( mockRunner, transferStep );
1137 			PropertyTransferResult result = (PropertyTransferResult) transferStep.run( mockRunner, context, getCurrentTransfer() );
1138 			transferLogTableModel.addResult( result );
1139 		}
1140 	}
1141 	
1142 	public boolean onClose( boolean canCancel )
1143 	{
1144 		super.release();
1145 		transferStep.getTestCase().getTestSuite().removeTestSuiteListener( testSuiteListener ); 
1146 		transferStep.getTestCase().removeTestRunListener( testRunListener );
1147 		
1148 		PropertyTransfer transfer = getCurrentTransfer();
1149 		
1150 		if( transfer != null )
1151 		{
1152 			transfer.removePropertyChangeListener( transferPropertyChangeListener );
1153 		}
1154 		
1155 		TestPropertyHolder item = ( TestPropertyHolder ) sourceStepCombo.getSelectedItem();
1156 		if( item != null )
1157 		{
1158 			item.removeTestPropertyListener( sourceStepPropertiesListener );
1159 		}
1160 
1161 		item = ( TestPropertyHolder ) targetStepCombo.getSelectedItem();
1162 		if( item != null )
1163 		{
1164 			item.removeTestPropertyListener( targetStepPropertiesListener );
1165 		}
1166 
1167 		componentEnabler.release();
1168 		if( resultDesktopPanel != null )
1169 			SoapUI.getDesktop().closeDesktopPanel( resultDesktopPanel );
1170 		
1171 		return true;
1172 	}
1173 
1174 	public JComponent getComponent()
1175 	{
1176 		return this;
1177 	}
1178 	
1179 	protected JTextArea getSourceArea()
1180 	{
1181 		return sourceArea;
1182 	}
1183 
1184 	protected JTextArea getTargetArea()
1185 	{
1186 		return targetArea;
1187 	}
1188 
1189 	public boolean dependsOn(ModelItem modelItem)
1190 	{
1191 		return modelItem == transferStep || modelItem == transferStep.getTestCase() ||
1192 				modelItem == transferStep.getTestCase().getTestSuite() ||
1193 				modelItem == transferStep.getTestCase().getTestSuite().getProject();
1194 	}
1195 
1196 	public boolean selectTransfer(PropertyTransfer transfer)
1197 	{
1198 		for( int c = 0; c < transferStep.getTransferCount(); c++ )
1199 		{
1200 			if( transferStep.getTransferAt( c ) == transfer )
1201 			{
1202 				transferList.setSelectedIndex( c );
1203 				return true;
1204 			}
1205 		}
1206 		
1207 		return false;
1208 	}
1209 	
1210 	private class TransfersTableModel extends AbstractTableModel
1211 	{
1212 		private List<PropertyTransfersTestStep.PropertyTransferResult> results = new ArrayList<PropertyTransfersTestStep.PropertyTransferResult>();
1213 		
1214 		public synchronized int getRowCount()
1215 		{
1216 			int sum = 0; 
1217 			for( PropertyTransfersTestStep.PropertyTransferResult result : results )
1218 			{
1219 				sum += result.getTransferCount();
1220 			}
1221 			
1222 			return sum;
1223 		}
1224 
1225 		public synchronized void clear()
1226 		{
1227 			results.clear();
1228 			fireTableDataChanged();
1229 			logInspector.setTitle(  "Transfer Log (0)" );
1230 		}
1231 
1232 		public void addResult( PropertyTransfersTestStep.PropertyTransferResult result )
1233 		{
1234 		   int rowCount;
1235 		   synchronized(this)
1236 		   {
1237    			rowCount = getRowCount();
1238    			results.add( result );
1239          }
1240 		   
1241 		   fireTableRowsInserted( rowCount, rowCount + result.getTransferCount() );
1242 			
1243 		   logInspector.setTitle(  "Transfer Log (" + getRowCount() + ")" );
1244 			inspectorPanel.activate( logInspector );
1245 		}
1246 		
1247 		public int getColumnCount()
1248 		{
1249 			return 3;
1250 		}
1251 		
1252 		public String getColumnName(int column)
1253 		{
1254 			switch( column )
1255 			{
1256 			case 0 : return "Timestamp";
1257 			case 1 : return "Transfer Name";
1258 			case 2 : return "Transferred Values";
1259 			}
1260 			
1261 			return null;
1262 		}
1263 
1264 		public synchronized Object getValueAt(int rowIndex, int columnIndex)
1265 		{
1266 			// find correct transfer
1267 			PropertyTransfersTestStep.PropertyTransferResult result = null;
1268 			int sum = 0;
1269 			
1270 			for( int c = 0; c < results.size(); c++ )
1271 			{
1272 				if( sum + results.get( c ).getTransferCount() > rowIndex )
1273 				{
1274 					result = results.get( c );
1275 					break;
1276 				}
1277 				else
1278 				{
1279 					sum += results.get( c ).getTransferCount();
1280 				}
1281 			}
1282 			
1283 			if( result != null )
1284 			{
1285 				switch( columnIndex )
1286 				{
1287 					case 0 : return new Date( result.getTimeStamp() ).toString();
1288 					case 1 : return result.getTransferAt( rowIndex-sum ).getName();
1289 					case 2 : return Arrays.toString( result.getTransferredValuesAt( rowIndex-sum ) );
1290 				}
1291 			}
1292 			
1293 			return null;
1294 		}
1295 		
1296 	}
1297 	
1298 	private class InternalTestRunListener extends TestRunListenerAdapter
1299 	{
1300 		@Override
1301 		public void afterStep( TestRunner testRunner, TestRunContext runContext, TestStepResult result )
1302 		{
1303 			if( result.getTestStep() == transferStep )
1304 			{
1305 				transferLogTableModel.addResult( (PropertyTransferResult) result );
1306 			}
1307 		}
1308 	}
1309 	
1310 	private class StepComboRenderer extends DefaultListCellRenderer
1311 	{
1312 		@Override
1313 		public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus )
1314 		{
1315 			Component result = super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
1316 			
1317 			if( value instanceof TestModelItem )
1318 			{
1319 				TestModelItem item = ( TestModelItem ) value;
1320 				setIcon( item.getIcon() );
1321 				setText( item.getName() );
1322 			}
1323 			else if( value == PropertyExpansionUtils.getGlobalProperties())
1324 			{
1325 				setText( "Global" );
1326 			}
1327 			
1328 			return result;
1329 		}
1330 	}
1331 	
1332 	private class PropertyComboRenderer extends DefaultListCellRenderer
1333 	{
1334 		@Override
1335 		public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus )
1336 		{
1337 			Component result = super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
1338 			
1339 			if( value != null )
1340 			{
1341 				TestProperty item = ( TestProperty ) value;
1342 				setText( item.getName() );
1343 			}
1344 			
1345 			return result;
1346 		}
1347 	}
1348 }