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