1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.panels.iface;
14
15 import java.awt.BorderLayout;
16 import java.awt.Color;
17 import java.awt.Component;
18 import java.awt.Dimension;
19 import java.awt.event.ActionEvent;
20 import java.awt.event.MouseAdapter;
21 import java.awt.event.MouseEvent;
22 import java.io.File;
23 import java.io.StringWriter;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.Enumeration;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32
33 import javax.swing.AbstractAction;
34 import javax.swing.Action;
35 import javax.swing.BorderFactory;
36 import javax.swing.JButton;
37 import javax.swing.JComponent;
38 import javax.swing.JLabel;
39 import javax.swing.JPanel;
40 import javax.swing.JProgressBar;
41 import javax.swing.JScrollPane;
42 import javax.swing.JSplitPane;
43 import javax.swing.JTabbedPane;
44 import javax.swing.JTree;
45 import javax.swing.SwingUtilities;
46 import javax.swing.event.TreeSelectionEvent;
47 import javax.swing.event.TreeSelectionListener;
48 import javax.swing.table.AbstractTableModel;
49 import javax.swing.tree.DefaultMutableTreeNode;
50 import javax.swing.tree.DefaultTreeModel;
51 import javax.swing.tree.TreePath;
52 import javax.wsdl.BindingOperation;
53
54 import org.apache.log4j.Logger;
55 import org.apache.xmlbeans.XmlCursor;
56 import org.apache.xmlbeans.XmlLineNumber;
57 import org.apache.xmlbeans.XmlObject;
58 import org.apache.xmlbeans.XmlOptions;
59 import org.jdesktop.swingx.JXTable;
60 import org.syntax.jedit.JEditTextArea;
61 import org.w3c.dom.Element;
62
63 import com.eviware.soapui.SoapUI;
64 import com.eviware.soapui.actions.SoapUIPreferencesAction;
65 import com.eviware.soapui.impl.wsdl.WsdlInterface;
66 import com.eviware.soapui.impl.wsdl.WsdlOperation;
67 import com.eviware.soapui.impl.wsdl.actions.iface.ExportDefinitionAction;
68 import com.eviware.soapui.impl.wsdl.actions.iface.UpdateInterfaceAction;
69 import com.eviware.soapui.impl.wsdl.actions.iface.tools.wsi.WSIAnalyzeAction;
70 import com.eviware.soapui.impl.wsdl.actions.iface.tools.wsi.WSIReportPanel;
71 import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
72 import com.eviware.soapui.impl.wsdl.panels.teststeps.support.LineNumbersPanel;
73 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
74 import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
75 import com.eviware.soapui.impl.wsdl.support.xsd.SchemaUtils;
76 import com.eviware.soapui.model.ModelItem;
77 import com.eviware.soapui.model.iface.Interface;
78 import com.eviware.soapui.model.support.ProjectListenerAdapter;
79 import com.eviware.soapui.support.UISupport;
80 import com.eviware.soapui.support.action.swing.SwingActionDelegate;
81 import com.eviware.soapui.support.components.JEditorStatusBar;
82 import com.eviware.soapui.support.components.JXToolBar;
83 import com.eviware.soapui.support.components.MetricsPanel;
84 import com.eviware.soapui.support.components.ProgressDialog;
85 import com.eviware.soapui.support.components.MetricsPanel.MetricType;
86 import com.eviware.soapui.support.components.MetricsPanel.MetricsSection;
87 import com.eviware.soapui.support.types.StringList;
88 import com.eviware.soapui.support.xml.JXEditTextArea;
89 import com.eviware.soapui.support.xml.XmlUtils;
90 import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
91 import com.eviware.x.dialogs.Worker;
92 import com.eviware.x.dialogs.XProgressDialog;
93 import com.eviware.x.dialogs.XProgressMonitor;
94 import com.jgoodies.forms.builder.ButtonBarBuilder;
95
96 /***
97 * DesktopPanel for WsdlInterface. Loads all referenced wsdls/xsds for the specified WsdlInterface
98 * and displays these in seperate tabs
99 *
100 * @author Ole.Matzura
101 */
102
103 public class WsdlInterfaceDesktopPanel extends ModelItemDesktopPanel<WsdlInterface>
104 {
105 private final static Logger logger = Logger.getLogger( WsdlInterfaceDesktopPanel.class );
106 private JTabbedPane partTabs;
107 private List<JEditTextArea> editors = new ArrayList<JEditTextArea>();
108 private JTree tree;
109 private Map<String,DefaultMutableTreeNode> groupNodes = new HashMap<String,DefaultMutableTreeNode>();
110 private Map<String,TreePath> pathMap = new HashMap<String,TreePath>();
111 private List<TreePath> navigationHistory = new ArrayList<TreePath>();
112 private StringList targetNamespaces = new StringList();
113 public int historyIndex;
114 public boolean navigating;
115 private JEditorStatusBar statusBar;
116 private DefaultMutableTreeNode rootNode;
117 private DefaultTreeModel treeModel;
118 private InternalProjectListener projectListener;
119 private final WsdlInterface iface;
120 private JPanel wsiPanel;
121 private WSIReportPanel reportPanel;
122 private SaveWsiReportAction saveWsiReportAction;
123 private MetricsPanel metrics;
124
125 public WsdlInterfaceDesktopPanel(WsdlInterface iface)
126 {
127 super( iface );
128 this.iface = iface;
129
130 try
131 {
132 iface.getWsdlContext().loadIfNecessary();
133 buildUI();
134 }
135 catch( Exception e )
136 {
137 UISupport.showErrorMessage( e );
138 SwingUtilities.invokeLater( new Runnable() {
139
140 public void run()
141 {
142 SoapUI.getDesktop().closeDesktopPanel( WsdlInterfaceDesktopPanel.this );
143 }} );
144 }
145 }
146
147 private void buildUI()
148 {
149 JTabbedPane tabs = new JTabbedPane();
150 tabs.addTab( "Overview", buildInterfaceOverviewTab() );
151 tabs.addTab( "Service Endpoints", buildEndpointsTab() );
152 tabs.addTab( "WSDL Content", buildWsdlContentTab() );
153 tabs.addTab( "WS-I Compliance", buildWSITab() );
154
155 add( UISupport.createTabPanel( tabs, true ), BorderLayout.CENTER );
156 }
157
158 private Component buildWSITab()
159 {
160 wsiPanel = new JPanel( new BorderLayout() );
161 wsiPanel.setBackground( Color.WHITE );
162 wsiPanel.setOpaque( true );
163
164 wsiPanel.add( builderWsiToolbar(), BorderLayout.NORTH );
165
166 return wsiPanel;
167 }
168
169 private Component builderWsiToolbar()
170 {
171 JXToolBar toolbar = UISupport.createToolbar();
172
173 toolbar.addFixed( UISupport.createToolbarButton( new RunWSIAction() ) );
174 toolbar.addFixed( UISupport.createToolbarButton( new WSIOptionsAction() ));
175 toolbar.addRelatedGap();
176 saveWsiReportAction = new SaveWsiReportAction();
177 toolbar.addFixed( UISupport.createToolbarButton(saveWsiReportAction ));
178
179 toolbar.addGlue();
180 toolbar.addFixed( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.WSIREPORT_HELP_URL ) ) );
181
182 return toolbar;
183 }
184
185 private Component buildInterfaceOverviewTab()
186 {
187 metrics = new MetricsPanel();
188 MetricsSection section = metrics.addSection( "WSDL Definition" );
189
190 try
191 {
192 section.addMetric( "WSDL URL", MetricType.URL ).set( iface.getDefinition() );
193 section.addMetric( "Namespace" ).set( iface.getBindingName().getNamespaceURI() );
194 section.addMetric( "Binding" ).set( iface.getBindingName().getLocalPart() );
195 section.addMetric( "SOAP Version" ).set( iface.getSoapVersion().toString() );
196 section.addMetric( "Style" ).set( iface.getStyle() );
197 }
198 catch( Exception e )
199 {
200 UISupport.showErrorMessage( e );
201 }
202
203 section.finish();
204
205 metrics.addSection( "Definition Parts" );
206 section = metrics.addSection( "Operations" );
207 JXTable table = section.addTable( new OperationsTableModel() );
208 table.getColumn( 1 ).setPreferredWidth( 60 );
209 table.getColumn( 2 ).setPreferredWidth( 60 );
210 section.finish();
211
212 table.packColumn( 3, 10 );
213 if( table.getColumn( 3 ).getPreferredWidth() < 250 )
214 table.getColumn( 3 ).setPreferredWidth( 250 );
215
216 return new JScrollPane( metrics );
217 }
218
219 private Component buildEndpointsTab()
220 {
221 return iface.getProject().getEndpointStrategy().getConfigurationPanel( iface );
222 }
223
224 private JComponent buildWsdlContentTab()
225 {
226 partTabs = new JTabbedPane();
227 partTabs.setTabLayoutPolicy( JTabbedPane.SCROLL_TAB_LAYOUT );
228
229 rootNode = new DefaultMutableTreeNode( iface.getName() );
230 treeModel = new DefaultTreeModel( rootNode );
231 tree = new JTree( treeModel );
232 tree.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2) );
233 tree.setExpandsSelectedPaths( true );
234 tree.addTreeSelectionListener( new InternalTreeSelectionListener() );
235 tree.addMouseListener( new MouseAdapter() {
236
237 @Override
238 public void mouseClicked( MouseEvent arg0 )
239 {
240 if( arg0.getClickCount() > 1 )
241 {
242 TreePath selectionPath = tree.getSelectionPath();
243 if( selectionPath != null )
244 {
245 DefaultMutableTreeNode treeNode = ( DefaultMutableTreeNode ) selectionPath.getLastPathComponent();
246 Object userObject = treeNode.getUserObject();
247 if( userObject instanceof InspectItem )
248 {
249 InspectItem item = ( InspectItem ) userObject;
250 if( item != null && item.selector != null )
251 {
252 item.selector.selectNode( item );
253 }
254 }
255 }
256 }
257 }} );
258
259 JScrollPane scrollPane = new JScrollPane( tree );
260 JSplitPane split = UISupport.createHorizontalSplit( scrollPane,
261 UISupport.createTabPanel( partTabs, true ));
262
263 split.setDividerLocation( 250 );
264 split.setResizeWeight( 0.3 );
265
266 initTreeModel( iface );
267
268 JPanel panel = new JPanel( new BorderLayout() );
269
270 panel.add( split, BorderLayout.CENTER );
271 panel.add( buildToolbar(), BorderLayout.PAGE_START );
272 statusBar = new JEditorStatusBar( );
273 panel.add( statusBar, BorderLayout.PAGE_END );
274 setPreferredSize( new Dimension( 600, 500 ));
275
276 projectListener = new InternalProjectListener();
277 iface.getProject().addProjectListener( projectListener );
278
279 return panel;
280 }
281
282 private void initTreeModel( WsdlInterface iface )
283 {
284 try
285 {
286 if( iface.getWsdlContext().loadIfNecessary())
287 {
288 XProgressDialog progressDialog = UISupport.getDialogs().createProgressDialog(
289 "Loading Defintion", 3, "Initializing definition..", true );
290 Loader loader = new Loader( iface );
291
292 if( progressDialog != null )
293 progressDialog.setCancelLabel( "Run in background" );
294
295 progressDialog.run( loader );
296 loader = null;
297 treeModel.nodeStructureChanged( rootNode );
298 }
299 }
300 catch (Exception e)
301 {
302 SoapUI.logError( e );
303 }
304 }
305
306 private Component buildToolbar()
307 {
308 JXToolBar toolbar = UISupport.createToolbar();
309
310 toolbar.addFixed( UISupport.createToolbarButton( new BackwardAction() ) );
311 toolbar.addFixed( UISupport.createToolbarButton( new ForwardAction() ) );
312 toolbar.addUnrelatedGap();
313 JButton button = UISupport.createToolbarButton( SwingActionDelegate.createDelegate( UpdateInterfaceAction.SOAPUI_ACTION_ID, getModelItem(),
314 null, "/updateDefinition.gif" ));
315 button.setText( null );
316 toolbar.addFixed( button);
317 button = UISupport.createToolbarButton( SwingActionDelegate.createDelegate( ExportDefinitionAction.SOAPUI_ACTION_ID, getModelItem(),
318 null, "/exportDefinition.gif"));
319 button.setText( null );
320 toolbar.addFixed( button);
321 toolbar.addGlue();
322 button = UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.INTERFACE_HELP_URL ));
323 button.setText( null );
324 toolbar.addFixed( button);
325
326 return toolbar;
327 }
328
329 private final class InternalProjectListener extends ProjectListenerAdapter
330 {
331 @Override
332 public void interfaceUpdated( Interface iface )
333 {
334 if( iface == getModelItem() )
335 {
336 partTabs.removeAll();
337 tree.setSelectionRow( -1 );
338 rootNode.removeAllChildren();
339 editors.clear();
340 groupNodes.clear();
341 pathMap.clear();
342 targetNamespaces.clear();
343 initTreeModel( ( WsdlInterface ) iface );
344 }
345 }
346 }
347
348 private final class InternalTreeSelectionListener implements TreeSelectionListener
349 {
350 public void valueChanged( TreeSelectionEvent e )
351 {
352 TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
353 if( newLeadSelectionPath != null )
354 {
355 if( !navigating )
356 {
357
358 while( historyIndex < navigationHistory.size()-1 )
359 {
360 TreePath path = navigationHistory.remove( navigationHistory.size()-1 );
361 navigationHistory.add( historyIndex++, path );
362 }
363
364 navigationHistory.add( newLeadSelectionPath );
365 historyIndex = navigationHistory.size()-1;
366 }
367
368 DefaultMutableTreeNode tn = ( DefaultMutableTreeNode ) newLeadSelectionPath.getLastPathComponent();
369 if( tn.getUserObject() instanceof InspectItem )
370 {
371 InspectItem item = ( InspectItem ) tn.getUserObject();
372
373 partTabs.setSelectedIndex( item.getTabIndex() );
374 statusBar.setInfo( item.getDescription() );
375
376 JEditTextArea editor = editors.get( item.getTabIndex() );
377 int lineNumber = item.getLineNumber();
378 if( lineNumber > 0 && editor.getLineStartOffset( lineNumber ) >= 0 )
379 {
380 editor.setCaretPosition( editor.getLineStartOffset( lineNumber ) );
381 }
382 else
383 {
384 editor.setCaretPosition( 0 );
385 }
386 }
387
388 tree.scrollPathToVisible( newLeadSelectionPath );
389 tree.expandPath( newLeadSelectionPath );
390 }
391 }
392 }
393
394 private class Loader implements Worker
395 {
396 private static final String DEFINITION_PARTS_SECTION = "Definition Parts";
397 private ProgressDialog progressDialog;
398 private final WsdlInterface iface;
399 private JProgressBar progressBar;
400
401 public Loader( WsdlInterface iface )
402 {
403 this.iface = iface;
404 }
405
406 public Object construct( XProgressMonitor monitor )
407 {
408 MetricsSection section = metrics.getSection( DEFINITION_PARTS_SECTION );
409 section.clear();
410
411 try
412 {
413 Map<String, XmlObject> schemas = iface.getWsdlContext().getDefinitionParts();
414 int tabCount = partTabs.getTabCount();
415
416 for (Iterator<String> iter = schemas.keySet().iterator(); iter.hasNext();)
417 {
418 String url = iter.next();
419 addTab( url, schemas.get( url ) );
420 }
421
422 while( tabCount-- > 0 )
423 partTabs.remove( 0 );
424
425 return null;
426 }
427 catch (Exception e)
428 {
429 logger.error( "Failed to load WSDL; " + e.getClass().getSimpleName() + "; " + e.getMessage() );
430 add( new JLabel( "Failed to load WSDL; " + e.toString() ), BorderLayout.NORTH );
431
432 SoapUI.logError( e );
433
434 return e;
435 }
436 finally
437 {
438 section.finish();
439 }
440
441
442 }
443
444 private void addTab(String url, XmlObject xmlObject) throws Exception
445 {
446 int ix = url.startsWith( "file:" ) ? url.lastIndexOf( File.separatorChar ) : url.lastIndexOf( '/' );
447 if( ix == -1 )
448 ix = url.lastIndexOf( '/' );
449
450 String title = url.substring( ix+1);
451
452 metrics.getSection( DEFINITION_PARTS_SECTION ).addMetric( title, MetricType.URL ).set( url );
453
454 if( progressBar != null )
455 progressBar.setString( title );
456 else if( progressDialog != null )
457 progressDialog.setProgress( 1, title );
458
459 JPanel panel = new JPanel( new BorderLayout() );
460 JLabel label = new JLabel( url );
461 label.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ));
462 panel.add( label, BorderLayout.NORTH );
463
464 JXEditTextArea inputArea = JXEditTextArea.createXmlEditor( false );
465 StringWriter writer = new StringWriter();
466 XmlUtils.serializePretty( xmlObject, writer );
467 String xmlString = writer.toString();
468
469
470 xmlObject = XmlObject.Factory.parse( xmlString, new XmlOptions().setLoadLineNumbers() );
471
472 inputArea.setText( xmlString );
473 inputArea.setEditable( false );
474 inputArea.getPainter().setLineHighlightEnabled( true );
475
476 JPanel p = new JPanel( new BorderLayout() );
477 p.add( inputArea, BorderLayout.CENTER );
478 p.add( new LineNumbersPanel( inputArea ), BorderLayout.WEST );
479
480 panel.add( new JScrollPane( p ), BorderLayout.CENTER );
481 partTabs.addTab( title, panel );
482
483 if( tree != null )
484 {
485 initInspectionTree( xmlObject, inputArea );
486 }
487 }
488
489 private void initInspectionTree( XmlObject xmlObject, JXEditTextArea inputArea )
490 {
491 DefaultMutableTreeNode treeRoot = rootNode;
492
493 targetNamespaces.add( SchemaUtils.getTargetNamespace( xmlObject ));
494
495 int tabCount = partTabs.getTabCount()-1;
496 mapTreeItems( xmlObject, treeRoot, false, tabCount, "Complex Types",
497 "declare namespace xs='http://www.w3.org/2001/XMLSchema';//xs:complexType[@name!='']", "@name", true, null );
498
499 mapTreeItems( xmlObject, treeRoot, false, tabCount, "Simple Types",
500 "declare namespace xs='http://www.w3.org/2001/XMLSchema';//xs:simpleType[@name!='']", "@name", true, null );
501
502 mapTreeItems( xmlObject, treeRoot, false, tabCount, "Anonymous Complex Types",
503 "declare namespace xs='http://www.w3.org/2001/XMLSchema';//xs:complexType[not(exists(@name))]",
504 "parent::node()/@name", true, null );
505
506 mapTreeItems( xmlObject, treeRoot, false, tabCount, "Global Elements",
507 "declare namespace xs='http://www.w3.org/2001/XMLSchema';//xs:schema/xs:element[@name!='']", "@name",
508 true, new GlobalElementSelector() );
509
510 mapTreeItems( xmlObject, treeRoot, false, tabCount, "Schemas",
511 "declare namespace xs='http://www.w3.org/2001/XMLSchema';//xs:schema", "@targetNamespace", true, null );
512
513 List<DefaultMutableTreeNode> messages = mapTreeItems( xmlObject, treeRoot, false, tabCount, "Messages",
514 "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';//wsdl:message", "@name", true, null );
515
516
517 for( DefaultMutableTreeNode treeNode : messages )
518 {
519 mapTreeItems( ((InspectItem)treeNode.getUserObject()).item, treeNode, false,
520 tabCount, null, "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';wsdl:part",
521 "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';concat('part: name=[', @name, '] type=[', @type, '] element=[', @element, ']' )",
522 true, new PartSelector() );
523 }
524
525 List<DefaultMutableTreeNode> portTypes = mapTreeItems( xmlObject, treeRoot, false, tabCount, "PortTypes",
526 "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';//wsdl:portType", "@name", true, null );
527
528
529 for( DefaultMutableTreeNode treeNode : portTypes )
530 {
531 List<DefaultMutableTreeNode> operationNodes = mapTreeItems( ((InspectItem)treeNode.getUserObject()).item, treeNode, false,
532 tabCount, null, "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';wsdl:operation", "@name", true, null );
533
534 for( DefaultMutableTreeNode treeNode2 : operationNodes )
535 {
536 mapTreeItems( ((InspectItem)treeNode2.getUserObject()).item, treeNode2, false, tabCount, null,
537 "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';wsdl:*", "concat( @name, ' [', local-name(), '], message=[', @message, ']' )", false,
538 new MessageSelector());
539 }
540 }
541
542 List<DefaultMutableTreeNode> bindings = mapTreeItems( xmlObject, treeRoot, false, tabCount, "Bindings",
543 "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';//wsdl:binding",
544 "declare namespace wsdlsoap='http://schemas.xmlsoap.org/wsdl/soap/';concat( @name, ' [style=', wsdlsoap:binding[1]/@style, ']' )", true, null );
545
546 for( DefaultMutableTreeNode treeNode : bindings )
547 {
548 List<DefaultMutableTreeNode> operationNodes = mapTreeItems( ((InspectItem)treeNode.getUserObject()).item, treeNode, false,
549 tabCount, null, "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';wsdl:operation",
550 "declare namespace wsdlsoap='http://schemas.xmlsoap.org/wsdl/soap/';concat( @name, ' [soapAction=', wsdlsoap:operation/@soapAction, ']' )",
551 true, null );
552
553 for( DefaultMutableTreeNode treeNode2 : operationNodes )
554 {
555 mapTreeItems( ((InspectItem)treeNode2.getUserObject()).item, treeNode2, false, tabCount, null,
556 "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';wsdl:*", "concat( @name, ' [', local-name(), ']' )", false,
557 new BindingOperationSelector() );
558 }
559 }
560
561 List<DefaultMutableTreeNode> services = mapTreeItems( xmlObject, treeRoot, false, tabCount, "Services",
562 "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';//wsdl:service", "@name", true, null );
563
564 for( DefaultMutableTreeNode treeNode : services )
565 {
566 mapTreeItems( ((InspectItem)treeNode.getUserObject()).item, treeNode, false, tabCount, null,
567 "declare namespace wsdl='http://schemas.xmlsoap.org/wsdl/';wsdl:port", "concat( 'port: name=[', @name, '] binding=[', @binding, ']' )", true,
568 new PortSelector() );
569 }
570
571 tree.expandRow( 0 );
572 editors.add( inputArea );
573 }
574
575 public void finished()
576 {
577 if( progressDialog != null )
578 progressDialog.setVisible( false );
579
580 progressDialog = null;
581 }
582
583 public boolean onCancel()
584 {
585 progressBar = new JProgressBar(0, 1);
586 progressBar.setSize( new Dimension( 120, 20 ));
587 progressBar.setStringPainted(true);
588 progressBar.setString("Loading Definition.." );
589 progressBar.setIndeterminate(true);
590
591 ButtonBarBuilder builder = ButtonBarBuilder.createLeftToRightBuilder();
592 builder.addGlue();
593 builder.addFixed( progressBar );
594 builder.addGlue();
595 builder.setBorder( BorderFactory.createEmptyBorder( 10, 10, 10, 10 ));
596
597 partTabs.addTab( "Loading.. ", builder.getPanel() );
598 return true;
599 }
600 }
601
602 public boolean dependsOn(ModelItem modelItem)
603 {
604 return modelItem == getModelItem() || modelItem == getModelItem().getProject();
605 }
606
607 public List<DefaultMutableTreeNode> mapTreeItems( XmlObject xmlObject, DefaultMutableTreeNode treeRoot, boolean createEmpty,
608 int tabIndex, String groupName, String query, String nameQuery, boolean sort, NodeSelector selector )
609 {
610 List<DefaultMutableTreeNode> resultNodes = new ArrayList<DefaultMutableTreeNode>();
611
612 try
613 {
614 XmlObject[] items = xmlObject.selectPath( query );
615 List<DefaultMutableTreeNode> treeNodes = new ArrayList<DefaultMutableTreeNode>();
616
617 DefaultMutableTreeNode root = treeRoot;
618 if( groupName != null )
619 {
620 String groupKey = new TreePath( root.getPath() ).toString() + "/" + groupName;
621 root = groupNodes.get( groupKey );
622 if( root == null && (items.length > 0 || createEmpty))
623 {
624 root = new DefaultMutableTreeNode( groupName );
625 treeRoot.add( root );
626 groupNodes.put( groupKey, root );
627 }
628 else if( root != null )
629 {
630 Enumeration children = root.children();
631 while( children.hasMoreElements() )
632 treeNodes.add( ( DefaultMutableTreeNode ) children.nextElement() );
633 }
634 }
635
636 if( items.length == 0 )
637 return resultNodes;
638
639 for( XmlObject item : items )
640 {
641 XmlObject[] selectPath = item.selectPath( nameQuery );
642 if( selectPath.length > 0 )
643 {
644 DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode( new InspectItem( item, selectPath[0], tabIndex, selector ));
645 treeNodes.add( treeNode);
646 resultNodes.add( treeNode );
647 }
648 }
649
650 if( sort )
651 {
652 Collections.sort( treeNodes, new Comparator<DefaultMutableTreeNode>() {
653
654 public int compare( DefaultMutableTreeNode o1, DefaultMutableTreeNode o2 )
655 {
656 return o1.toString().compareTo( o2.toString() );
657 }} );
658 }
659
660 root.removeAllChildren();
661
662 for( DefaultMutableTreeNode treeNode : treeNodes )
663 {
664 root.add( treeNode );
665
666 String path = "/" + getTreeNodeName( treeNode );
667 TreePath treePath = new TreePath( treeNode.getPath());
668 while( treeNode.getParent() != null )
669 {
670 treeNode = ( DefaultMutableTreeNode ) treeNode.getParent();
671 path = "/" + getTreeNodeName( treeNode ) + path;
672 }
673
674 pathMap.put( path, treePath );
675 }
676 }
677 catch( Throwable e )
678 {
679 SoapUI.log( "Failed to map items for query [" + query + "]:[" + nameQuery + "]" );
680 SoapUI.logError( e );
681 }
682
683 return resultNodes;
684 }
685
686 private String getTreeNodeName( DefaultMutableTreeNode treeNode )
687 {
688 Object userObject = treeNode.getUserObject();
689 if( userObject instanceof InspectItem )
690 return (( InspectItem ) userObject ).getName();
691 else
692 return treeNode.toString();
693 }
694
695 private final class InspectItem
696 {
697 private final XmlObject item;
698 private String name;
699 private final int tabIndex;
700 private XmlLineNumber lineNumber;
701 private final NodeSelector selector;
702
703 public InspectItem( XmlObject item, XmlObject nameObj, int tabIndex, NodeSelector selector )
704 {
705 this.item = item;
706 this.selector = selector;
707 this.name = XmlUtils.getNodeValue( nameObj.getDomNode() );
708 if( name == null )
709 name = nameObj.toString();
710 this.tabIndex = tabIndex;
711
712 ArrayList list = new ArrayList();
713 XmlCursor cursor = item.newCursor();
714 cursor.getAllBookmarkRefs( list );
715
716 for( Object o : list )
717 if( o instanceof XmlLineNumber )
718 lineNumber = (XmlLineNumber) o;
719
720 cursor.dispose();
721 }
722
723 public String getDescription()
724 {
725 return getName() + "@" + targetNamespaces.get( tabIndex );
726 }
727
728 public String getName()
729 {
730 int ix = name.indexOf( ' ' );
731 return ix == -1 ? name : name.substring( 0, ix );
732 }
733
734 public int getTabIndex()
735 {
736 return tabIndex;
737 }
738
739 public int getLineNumber()
740 {
741 return lineNumber == null ? -1 : lineNumber.getLine()-1;
742 }
743
744 @Override
745 public String toString()
746 {
747 return name;
748 }
749
750 public NodeSelector getSelector()
751 {
752 return selector;
753 }
754
755 public Element getElement()
756 {
757 return ( Element ) item.getDomNode();
758 }
759 }
760
761 public boolean onClose( boolean canCancel )
762 {
763 if( projectListener != null )
764 getModelItem().getProject().removeProjectListener( projectListener );
765
766 return release();
767 }
768
769 private void simpleSelect( InspectItem item, String attribute, String targetGroup )
770 {
771 Element elm = item.getElement();
772 String type = elm.getAttribute( attribute );
773 if( type.length() > 0 )
774 {
775 int ix = type.indexOf( ':' );
776 if( ix != -1 )
777 type = type.substring( ix+1 );
778
779
780 TreePath treePath = pathMap.get( "/" + getModelItem().getName() + "/" + targetGroup + "/" + type );
781 if( treePath != null )
782 {
783 tree.setSelectionPath( treePath );
784 }
785 }
786 }
787
788 protected interface NodeSelector
789 {
790 public void selectNode( InspectItem item );
791 }
792
793 public class PartSelector implements NodeSelector
794 {
795 public void selectNode( InspectItem item )
796 {
797 Element elm = item.getElement();
798 String type = elm.getAttribute( "type" );
799 String element = elm.getAttribute( "element" );
800 if( type.length() > 0 )
801 {
802 simpleSelect( item, "type", "Complex Types" );
803 }
804 else if( element.length() > 0 )
805 {
806 simpleSelect( item, "element", "Global Elements" );
807 }
808 }}
809
810 public class MessageSelector implements NodeSelector
811 {
812 public void selectNode( InspectItem item )
813 {
814 simpleSelect( item, "message", "Messages" );
815 }}
816
817 public class GlobalElementSelector implements NodeSelector
818 {
819 public void selectNode( InspectItem item )
820 {
821 simpleSelect( item, "type", "Complex Types" );
822 }}
823
824 public class PortSelector implements NodeSelector
825 {
826 public void selectNode( InspectItem item )
827 {
828 simpleSelect( item, "binding", "Bindings" );
829 }}
830
831 public class BindingOperationSelector implements NodeSelector
832 {
833 public void selectNode( InspectItem item )
834 {
835 Element elm = item.getElement();
836 String name = elm.getAttribute( "name" );
837
838 Element operationElm = ( Element ) elm.getParentNode();
839 Element bindingElm = ( Element ) operationElm.getParentNode();
840
841 String type = bindingElm.getAttribute( "type" );
842
843 if( type.length() > 0 )
844 {
845 int ix = type.indexOf( ':' );
846 if( ix != -1 )
847 type = type.substring( ix+1 );
848
849 TreePath treePath = pathMap.get( "/" + getModelItem().getName() + "/PortTypes/" + type + "/" +
850 operationElm.getAttribute( "name" ) + "/" + name );
851 if( treePath != null )
852 {
853 tree.setSelectionPath( treePath );
854 }
855 }
856 }}
857
858 private class BackwardAction extends AbstractAction
859 {
860 public BackwardAction()
861 {
862 putValue( SMALL_ICON, UISupport.createImageIcon( "/arrow_left.png" ));
863 putValue( Action.SHORT_DESCRIPTION, "Navigate to previous selection" );
864 }
865
866 public void actionPerformed( ActionEvent arg0 )
867 {
868 if( historyIndex > 0 )
869 {
870 historyIndex--;
871 navigating = true;
872 tree.setSelectionPath( navigationHistory.get( historyIndex ) );
873 navigating = false;
874 }
875 }}
876
877 private class ForwardAction extends AbstractAction
878 {
879 public ForwardAction()
880 {
881 putValue( SMALL_ICON, UISupport.createImageIcon( "/arrow_right.png" ));
882 putValue( Action.SHORT_DESCRIPTION, "Navigate to next selection" );
883 }
884
885 public void actionPerformed( ActionEvent arg0 )
886 {
887 if( historyIndex < navigationHistory.size()-1 )
888 {
889 historyIndex++;
890 navigating = true;
891 tree.setSelectionPath( navigationHistory.get( historyIndex ) );
892 navigating = false;
893 }
894
895 }}
896
897 private class RunWSIAction extends AbstractAction
898 {
899 public RunWSIAction()
900 {
901 putValue( SMALL_ICON, UISupport.createImageIcon( "/run.gif" ));
902 putValue( Action.SHORT_DESCRIPTION, "Creates a WS-I report for this interface" );
903 }
904
905 public void actionPerformed( ActionEvent arg0 )
906 {
907 WSIAnalyzeAction action = new WSIAnalyzeAction()
908 {
909 @Override
910 protected void showReport( File reportFile, String configFile ) throws Exception
911 {
912 reportPanel = new WSIReportPanel( reportFile, configFile, null, false );
913 reportPanel.setPreferredSize( new Dimension( 600, 400 ));
914 if( wsiPanel.getComponentCount() > 1 )
915 wsiPanel.remove( 1 );
916
917 wsiPanel.add( reportPanel, BorderLayout.CENTER );
918 wsiPanel.revalidate();
919 saveWsiReportAction.setEnabled( true );
920 }
921 };
922
923 action.perform( getModelItem(), null );
924 }}
925
926 private class WSIOptionsAction extends AbstractAction
927 {
928 public WSIOptionsAction()
929 {
930 putValue( SMALL_ICON, UISupport.createImageIcon( "/options.gif" ));
931 putValue( Action.SHORT_DESCRIPTION, "Sets WS-I report creation options" );
932 }
933
934 public void actionPerformed( ActionEvent arg0 )
935 {
936 SoapUIPreferencesAction.getInstance().show( SoapUIPreferencesAction.WS_I_SETTINGS );
937 }
938 }
939
940 private class SaveWsiReportAction extends AbstractAction
941 {
942 public SaveWsiReportAction()
943 {
944 putValue( SMALL_ICON, UISupport.createImageIcon( "/export.gif" ));
945 putValue( Action.SHORT_DESCRIPTION, "Saved the current WS-I report to a file" );
946
947 setEnabled( false );
948 }
949
950 public void actionPerformed( ActionEvent arg0 )
951 {
952 if( reportPanel != null )
953 reportPanel.getSaveReportAction().actionPerformed( null );
954 }
955 }
956
957 private class OperationsTableModel extends AbstractTableModel
958 {
959 public int getColumnCount()
960 {
961 return 4;
962 }
963
964 public int getRowCount()
965 {
966 return iface.getOperationCount();
967 }
968
969 @Override
970 public String getColumnName( int column )
971 {
972 switch( column )
973 {
974 case 0 : return "Name";
975 case 1 : return "Use";
976 case 2 : return "One-Way";
977 case 3 : return "Action";
978 }
979
980 return null;
981 }
982
983 public Object getValueAt( int rowIndex, int columnIndex )
984 {
985 WsdlOperation operation = iface.getOperationAt( rowIndex );
986 BindingOperation bindingOperation = operation.getBindingOperation();
987
988 switch( columnIndex )
989 {
990 case 0 : return operation.getName();
991 case 1 :
992 {
993 boolean i = WsdlUtils.isInputSoapEncoded( bindingOperation );
994 boolean o = operation.isOneWay() ? false : WsdlUtils.isOutputSoapEncoded( bindingOperation );
995
996 if( o && i )
997 return "SOAP Encoding";
998 if( !o && !i )
999 return "Literal";
1000
1001 return "Mixed";
1002 }
1003 case 3 : return operation.getAction();
1004 case 2 : return Boolean.valueOf( operation.isOneWay() );
1005 }
1006
1007 return null;
1008 }}
1009 }