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.support.propertyexpansion;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Color;
17  import java.awt.Container;
18  import java.awt.dnd.DnDConstants;
19  import java.awt.dnd.DropTarget;
20  import java.awt.event.ActionEvent;
21  
22  import javax.swing.AbstractAction;
23  import javax.swing.BorderFactory;
24  import javax.swing.JButton;
25  import javax.swing.JMenu;
26  import javax.swing.JPanel;
27  import javax.swing.JPopupMenu;
28  import javax.swing.JSeparator;
29  import javax.swing.JTextField;
30  import javax.swing.event.PopupMenuEvent;
31  import javax.swing.event.PopupMenuListener;
32  import javax.swing.text.JTextComponent;
33  
34  import org.apache.xmlbeans.XmlObject;
35  
36  import com.eviware.soapui.impl.support.AbstractHttpRequest;
37  import com.eviware.soapui.impl.support.AbstractHttpRequestInterface;
38  import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
39  import com.eviware.soapui.impl.wsdl.WsdlProject;
40  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
41  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
42  import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
43  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditor;
44  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
45  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
46  import com.eviware.soapui.model.ModelItem;
47  import com.eviware.soapui.model.TestModelItem;
48  import com.eviware.soapui.model.TestPropertyHolder;
49  import com.eviware.soapui.model.iface.Operation;
50  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
51  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionImpl;
52  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
53  import com.eviware.soapui.model.testsuite.TestProperty;
54  import com.eviware.soapui.support.StringUtils;
55  import com.eviware.soapui.support.UISupport;
56  import com.eviware.soapui.support.components.GroovyEditorComponent;
57  import com.eviware.soapui.support.components.ShowPopupAction;
58  import com.eviware.soapui.support.propertyexpansion.scrollmenu.ScrollableMenu;
59  import com.eviware.soapui.support.xml.JXEditTextArea;
60  import com.eviware.soapui.support.xml.XmlUtils;
61  
62  public class PropertyExpansionPopupListener implements PopupMenuListener
63  {
64  	private final Container targetMenu;
65  	private final ModelItem modelItem;
66  	private final PropertyExpansionTarget target;
67  
68  	public PropertyExpansionPopupListener( Container transferMenu, ModelItem modelItem, PropertyExpansionTarget target )
69  	{
70  		this.modelItem = modelItem;
71  		this.target = target;
72  		if( transferMenu instanceof ScrollableMenu )
73  			fillScrollableMenu( ( ScrollableMenu )transferMenu );
74  
75  		this.targetMenu = transferMenu;
76  	}
77  
78  	private void fillScrollableMenu( ScrollableMenu targetMenu )
79  	{
80  		WsdlTestStep testStep = null;
81  		WsdlTestCase testCase = null;
82  		WsdlTestSuite testSuite = null;
83  		WsdlProject project = null;
84  		WsdlMockService mockService = null;
85  		WsdlMockResponse mockResponse = null;
86  
87  		if( modelItem instanceof WsdlTestStep )
88  		{
89  			testStep = ( WsdlTestStep )modelItem;
90  			testCase = testStep.getTestCase();
91  			testSuite = testCase.getTestSuite();
92  			project = testSuite.getProject();
93  		}
94  		else if( modelItem instanceof WsdlTestCase )
95  		{
96  			testCase = ( WsdlTestCase )modelItem;
97  			testSuite = testCase.getTestSuite();
98  			project = testSuite.getProject();
99  		}
100 		else if( modelItem instanceof WsdlTestSuite )
101 		{
102 			testSuite = ( WsdlTestSuite )modelItem;
103 			project = testSuite.getProject();
104 		}
105 		else if( modelItem instanceof WsdlMockService )
106 		{
107 			project = ( ( WsdlMockService )modelItem ).getProject();
108 		}
109 		else if( modelItem instanceof WsdlMockResponse )
110 		{
111 			mockResponse = ( WsdlMockResponse )modelItem;
112 			mockService = ( mockResponse ).getMockOperation().getMockService();
113 			project = mockService.getProject();
114 		}
115 		else if( modelItem instanceof WsdlProject )
116 		{
117 			project = ( WsdlProject )modelItem;
118 		}
119 		else if( modelItem instanceof AbstractHttpRequestInterface<?> )
120 		{
121 			project = ( ( AbstractHttpRequest<?> )modelItem ).getOperation().getInterface().getProject();
122 		}
123 		else if( modelItem instanceof Operation )
124 		{
125 			project = ( WsdlProject )( ( Operation )modelItem ).getInterface().getProject();
126 		}
127 
128 		TestPropertyHolder globalProperties = PropertyExpansionUtils.getGlobalProperties();
129 		if( globalProperties.getProperties().size() > 0 )
130 			targetMenu.addHeader( createPropertyMenu( "Global", globalProperties ) );
131 
132 		if( project != null )
133 			targetMenu.addHeader( createPropertyMenu( "Project: [" + project.getName() + "]", project ) );
134 
135 		if( testSuite != null )
136 			targetMenu.addHeader( createPropertyMenu( "TestSuite: [" + testSuite.getName() + "]", testSuite ) );
137 
138 		if( mockService != null )
139 			targetMenu.addHeader( createPropertyMenu( "MockService: [" + mockService.getName() + "]", mockService ) );
140 
141 		if( mockResponse != null )
142 			targetMenu.addHeader( createPropertyMenu( "MockResponse: [" + mockResponse.getName() + "]", mockResponse ) );
143 
144 		if( testCase != null )
145 		{
146 			targetMenu.addHeader( createPropertyMenu( "TestCase: [" + testCase.getName() + "]", testCase ) );
147 
148 			for( int c = 0; c < testCase.getTestStepCount(); c++ )
149 			{
150 				testStep = testCase.getTestStepAt( c );
151 				if( testStep.getPropertyNames().length == 0 )
152 					continue;
153 
154 				targetMenu.add( createPropertyMenu( "Step " + ( c + 1 ) + ": [" + testStep.getName() + "]", testStep ) );
155 			}
156 		}
157 	}
158 
159 	public void popupMenuCanceled( PopupMenuEvent arg0 )
160 	{
161 	}
162 
163 	public void popupMenuWillBecomeInvisible( PopupMenuEvent arg0 )
164 	{
165 	}
166 
167 	public void popupMenuWillBecomeVisible( PopupMenuEvent arg0 )
168 	{
169 		if( targetMenu instanceof ScrollableMenu )
170 			return;
171 		// create transfer menus
172 		targetMenu.removeAll();
173 
174 		WsdlTestStep testStep = null;
175 		WsdlTestCase testCase = null;
176 		WsdlTestSuite testSuite = null;
177 		WsdlProject project = null;
178 		WsdlMockService mockService = null;
179 		WsdlMockResponse mockResponse = null;
180 
181 		if( modelItem instanceof WsdlTestStep )
182 		{
183 			testStep = ( WsdlTestStep )modelItem;
184 			testCase = testStep.getTestCase();
185 			testSuite = testCase.getTestSuite();
186 			project = testSuite.getProject();
187 		}
188 		else if( modelItem instanceof WsdlTestCase )
189 		{
190 			testCase = ( WsdlTestCase )modelItem;
191 			testSuite = testCase.getTestSuite();
192 			project = testSuite.getProject();
193 		}
194 		else if( modelItem instanceof WsdlTestSuite )
195 		{
196 			testSuite = ( WsdlTestSuite )modelItem;
197 			project = testSuite.getProject();
198 		}
199 		else if( modelItem instanceof WsdlMockService )
200 		{
201 			project = ( ( WsdlMockService )modelItem ).getProject();
202 		}
203 		else if( modelItem instanceof WsdlMockResponse )
204 		{
205 			mockResponse = ( WsdlMockResponse )modelItem;
206 			mockService = ( mockResponse ).getMockOperation().getMockService();
207 			project = mockService.getProject();
208 		}
209 		else if( modelItem instanceof WsdlProject )
210 		{
211 			project = ( WsdlProject )modelItem;
212 		}
213 		else if( modelItem instanceof AbstractHttpRequestInterface<?> )
214 		{
215 			project = ( ( AbstractHttpRequest<?> )modelItem ).getOperation().getInterface().getProject();
216 		}
217 		else if( modelItem instanceof Operation )
218 		{
219 			project = ( WsdlProject )( ( Operation )modelItem ).getInterface().getProject();
220 		}
221 
222 		TestPropertyHolder globalProperties = PropertyExpansionUtils.getGlobalProperties();
223 		if( globalProperties.getProperties().size() > 0 )
224 			targetMenu.add( createPropertyMenu( "Global", globalProperties ) );
225 
226 		if( project != null )
227 			targetMenu.add( createPropertyMenu( "Project: [" + project.getName() + "]", project ) );
228 
229 		if( testSuite != null )
230 			targetMenu.add( createPropertyMenu( "TestSuite: [" + testSuite.getName() + "]", testSuite ) );
231 
232 		if( mockService != null )
233 			targetMenu.add( createPropertyMenu( "MockService: [" + mockService.getName() + "]", mockService ) );
234 
235 		if( mockResponse != null )
236 			targetMenu.add( createPropertyMenu( "MockResponse: [" + mockResponse.getName() + "]", mockResponse ) );
237 
238 		if( testCase != null )
239 		{
240 			targetMenu.add( createPropertyMenu( "TestCase: [" + testCase.getName() + "]", testCase ) );
241 
242 			for( int c = 0; c < testCase.getTestStepCount(); c++ )
243 			{
244 				testStep = testCase.getTestStepAt( c );
245 				if( testStep.getPropertyNames().length == 0 )
246 					continue;
247 
248 				if( targetMenu.getComponentCount() == 3 )
249 					targetMenu.add( new JSeparator() );
250 
251 				targetMenu.add( createPropertyMenu( "Step " + ( c + 1 ) + ": [" + testStep.getName() + "]", testStep ) );
252 			}
253 		}
254 
255 	}
256 
257 	private JMenu createPropertyMenu( String string, TestPropertyHolder holder )
258 	{
259 		ScrollableMenu menu = new ScrollableMenu( string );
260 
261 		if( holder instanceof TestModelItem )
262 			menu.setIcon( ( ( TestModelItem )holder ).getIcon() );
263 
264 		String[] propertyNames = holder.getPropertyNames();
265 
266 		for( String name : propertyNames )
267 		{
268 			menu.add( new TransferFromPropertyActionInvoker( holder, name ) );
269 		}
270 
271 		if( holder instanceof MutableTestPropertyHolder )
272 		{
273 			menu.addHeader( new TransferFromPropertyActionInvoker( ( MutableTestPropertyHolder )holder ) );
274 		}
275 
276 		return menu;
277 	}
278 
279 	public class TransferFromPropertyActionInvoker extends AbstractAction
280 	{
281 		private TestPropertyHolder sourceStep;
282 		private String sourceProperty;
283 
284 		public TransferFromPropertyActionInvoker( TestPropertyHolder sourceStep, String sourceProperty )
285 		{
286 			super( "Property [" + sourceProperty + "]" );
287 			this.sourceStep = sourceStep;
288 			this.sourceProperty = sourceProperty;
289 		}
290 
291 		public TransferFromPropertyActionInvoker( MutableTestPropertyHolder testStep )
292 		{
293 			super( "Create new.." );
294 			this.sourceStep = testStep;
295 		}
296 
297 		public void actionPerformed( ActionEvent arg0 )
298 		{
299 			if( sourceProperty == null && sourceStep instanceof MutableTestPropertyHolder )
300 			{
301 				MutableTestPropertyHolder step = ( MutableTestPropertyHolder )sourceStep;
302 				sourceProperty = target.getNameForCreation();
303 
304 				sourceProperty = UISupport.prompt( "Specify name of source property to create", "Create source property",
305 						sourceProperty );
306 				while( sourceProperty != null && step.getProperty( sourceProperty ) != null )
307 				{
308 					sourceProperty = UISupport.prompt( "Name is taken, specify unique name of source property to create",
309 							"Create source property", sourceProperty );
310 				}
311 
312 				if( sourceProperty == null )
313 				{
314 					return;
315 				}
316 
317 				( ( MutableTestPropertyHolder )sourceStep ).addProperty( sourceProperty );
318 			}
319 
320 			String sourceXPath = "";
321 
322 			try
323 			{
324 				String val = sourceStep.getPropertyValue( sourceProperty );
325 				if( StringUtils.isNullOrEmpty( val ) )
326 				{
327 					String defaultValue = sourceStep.getProperty( sourceProperty ).getDefaultValue();
328 					if( StringUtils.hasContent( defaultValue ) )
329 					{
330 						if( UISupport.confirm( "Missing property value, use default value instead?", "Get Data" ) )
331 						{
332 							val = defaultValue;
333 						}
334 					}
335 				}
336 
337 				if( XmlUtils.seemsToBeXml( val ) )
338 				{
339 					XmlObject.Factory.parse( val );
340 					sourceXPath = UISupport.selectXPath( "Select XPath", "Select source xpath for property transfer", val,
341 							null );
342 				}
343 			}
344 			catch( Throwable e )
345 			{
346 				// just ignore.. this wasn't xml..
347 			}
348 
349 			if( StringUtils.hasContent( sourceXPath ) )
350 			{
351 				sourceXPath = XmlUtils.removeXPathNamespaceDeclarations( sourceXPath );
352 				if( sourceXPath.length() > 0 )
353 					sourceXPath = sourceXPath.replace( '\n', ' ' );
354 			}
355 
356 			TestProperty property = sourceStep.getProperty( sourceProperty );
357 			PropertyExpansion pe = new PropertyExpansionImpl( property, sourceXPath );
358 
359 			String valueForCreation = target.getValueForCreation();
360 			target.insertPropertyExpansion( pe, null );
361 
362 			if( !StringUtils.hasContent( sourceXPath ) && StringUtils.hasContent( valueForCreation )
363 					&& !property.isReadOnly() )
364 			{
365 				valueForCreation = UISupport.prompt( "Init property value to", "Get Data", valueForCreation );
366 				if( valueForCreation != null )
367 				{
368 					property.setValue( valueForCreation );
369 				}
370 			}
371 		}
372 	}
373 
374 	public static void addMenu( JPopupMenu popup, String menuName, ModelItem item, PropertyExpansionTarget component )
375 	{
376 		ScrollableMenu menu = new ScrollableMenu( menuName );
377 		popup.add( menu );
378 		popup.addPopupMenuListener( new PropertyExpansionPopupListener( menu, item, component ) );
379 	}
380 
381 	public static void enable( JTextComponent textField, ModelItem modelItem, JPopupMenu popup )
382 	{
383 		JTextComponentPropertyExpansionTarget target = new JTextComponentPropertyExpansionTarget( textField, modelItem );
384 		DropTarget dropTarget = new DropTarget( textField, new PropertyExpansionDropTarget( target ) );
385 		dropTarget.setDefaultActions( DnDConstants.ACTION_COPY_OR_MOVE );
386 
387 		textField.setComponentPopupMenu( popup );
388 
389 		if( popup != null )
390 		{
391 			PropertyExpansionPopupListener.addMenu( popup, "Get Data..", target.getContextModelItem(), target );
392 		}
393 	}
394 
395 	public static JPanel addPropertyExpansionPopup( JTextField textField, JPopupMenu popup, ModelItem modelItem )
396 	{
397 		PropertyExpansionPopupListener.enable( textField, modelItem, popup );
398 
399 		JButton popupButton = new JButton();
400 		popupButton.setAction( new ShowPopupAction( textField, popupButton ) );
401 		popupButton.setBackground( Color.WHITE );
402 		popupButton.setForeground( Color.WHITE );
403 		popupButton.setBorder( null );
404 		popupButton.setOpaque( true );
405 		JPanel panel = new JPanel( new BorderLayout() );
406 		panel.add( textField, BorderLayout.CENTER );
407 		panel.add( popupButton, BorderLayout.EAST );
408 		panel.setBorder( textField.getBorder() );
409 		textField.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
410 
411 		return panel;
412 	}
413 
414 	public static void enable( JXEditTextArea textField, ModelItem modelItem )
415 	{
416 		JXEditTextAreaPropertyExpansionTarget target = new JXEditTextAreaPropertyExpansionTarget( textField, modelItem );
417 		DropTarget dropTarget = new DropTarget( textField, new PropertyExpansionDropTarget( target ) );
418 		dropTarget.setDefaultActions( DnDConstants.ACTION_COPY_OR_MOVE );
419 
420 		JPopupMenu popup = textField.getRightClickPopup();
421 
422 		if( popup != null )
423 		{
424 			PropertyExpansionPopupListener.addMenu( popup, "Get Data..", target.getContextModelItem(), target );
425 		}
426 	}
427 
428 	public static void enable( GroovyEditor groovyEditor, ModelItem modelItem )
429 	{
430 		GroovyEditorPropertyExpansionTarget target = new GroovyEditorPropertyExpansionTarget( groovyEditor, modelItem );
431 		DropTarget dropTarget = new DropTarget( groovyEditor.getEditArea(), new PropertyExpansionDropTarget( target ) );
432 		dropTarget.setDefaultActions( DnDConstants.ACTION_COPY_OR_MOVE );
433 
434 		JPopupMenu popup = groovyEditor.getEditArea().getComponentPopupMenu();
435 
436 		if( popup != null )
437 		{
438 			ScrollableMenu menu = new ScrollableMenu( "Get Data.." );
439 			popup.insert( menu, 0 );
440 			popup.addPopupMenuListener( new PropertyExpansionPopupListener( menu, target.getContextModelItem(), target ) );
441 			popup.insert( new JSeparator(), 1 );
442 		}
443 	}
444 
445 	public static void enable( JTextComponent textField, ModelItem modelItem )
446 	{
447 		JPopupMenu popupMenu = textField.getComponentPopupMenu();
448 		if( popupMenu == null )
449 		{
450 			popupMenu = new JPopupMenu();
451 			textField.setComponentPopupMenu( popupMenu );
452 		}
453 
454 		enable( textField, modelItem, popupMenu );
455 	}
456 
457 	public static void disable( GroovyEditor editor )
458 	{
459 	}
460 
461 	public static void enable( GroovyEditorComponent gec, ModelItem modelItem )
462 	{
463 		enable( gec.getEditor(), modelItem );
464 	}
465 }