View Javadoc

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