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