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