/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.webservice.ui.wizard; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TreeExpansionEvent; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.teiid.core.designer.util.CoreStringUtil; import org.teiid.core.designer.util.I18nUtil; import org.teiid.core.designer.util.FileUtils; import org.teiid.designer.metamodels.wsdl.Definitions; import org.teiid.designer.metamodels.wsdl.Operation; import org.teiid.designer.metamodels.wsdl.PortType; import org.teiid.designer.metamodels.wsdl.Service; import org.teiid.designer.ui.common.util.WidgetFactory; import org.teiid.designer.ui.common.util.WidgetUtil; import org.teiid.designer.ui.common.util.WizardUtil; import org.teiid.designer.ui.common.widget.DefaultTreeViewerController; import org.teiid.designer.ui.common.wizard.AbstractWizardPage; import org.teiid.designer.webservice.IWebServiceModelBuilder; import org.teiid.designer.webservice.IWebServiceResource; import org.teiid.designer.webservice.ui.IInternalUiConstants; import org.teiid.designer.webservice.ui.WebServiceUiPlugin; import org.teiid.designer.webservice.ui.util.WebServiceUiUtil; /** * WSDL Operations Selection page. This page of the WSDL to Relational Importer is used to select the operations in the source * wsdl that will be used to generate the relational entities. * * @since 8.0 */ public class SelectWsdlOperationsPage extends AbstractWizardPage implements Listener, FileUtils.Constants, CoreStringUtil.Constants, IInternalUiConstants.Images { /** Used as a prefix to properties file keys. */ private static final String PREFIX = I18nUtil.getPropertyPrefix(SelectWsdlOperationsPage.class); /** <code>IDialogSetting</code>s key for saved dialog height. */ private static final String DIALOG_HEIGHT = "dialogHeight"; //$NON-NLS-1$ /** <code>IDialogSetting</code>s key for saved dialog width. */ private static final String DIALOG_WIDTH = "dialogWidth"; //$NON-NLS-1$ /** <code>IDialogSetting</code>s key for saved dialog X position. */ private static final String DIALOG_X = "dialogX"; //$NON-NLS-1$ /** <code>IDialogSetting</code>s key for saved dialog Y position. */ private static final String DIALOG_Y = "dialogY"; //$NON-NLS-1$ /** The checkbox treeViewer */ private TreeViewer treeViewer; private Tree tree; boolean treeExpanded = false; private CheckboxTreeController controller; /** Buttons for tree selection */ private Button selectAllButton; private Button deselectAllButton; /** The import manager. */ IWebServiceModelBuilder importBuilder; /** The WSDL model representation */ private List wsdlDefinitions = null; HashMap definitionsLabelMap = new HashMap(); private boolean initializing = false; /** * Constructs the page with the provided import manager * * @param theImportManager the import manager object */ public SelectWsdlOperationsPage( IWebServiceModelBuilder builder ) { super(SelectWsdlOperationsPage.class.getSimpleName(), getString("title")); //$NON-NLS-1$ this.importBuilder = builder; setImageDescriptor(WebServiceUiUtil.getImageDescriptor(NEW_MODEL_BANNER)); } /** * Event handler * * @param event the Event */ @Override public void handleEvent( Event event ) { if (!initializing) { boolean validate = false; // SelectAll button selected if (event.widget == this.selectAllButton) { setAllNodesSelected(true); } // DeselectAll button selected if (event.widget == this.deselectAllButton) { setAllNodesSelected(false); } if (validate) { setPageStatus(); } } } /** * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) * @since 4.2 */ @Override public void createControl( Composite theParent ) { final int COLUMNS = 1; Composite pnlMain = WidgetFactory.createPanel(theParent, SWT.NONE, GridData.FILL_BOTH); GridLayout layout = new GridLayout(COLUMNS, false); pnlMain.setLayout(layout); setControl(pnlMain); SashForm splitter = new SashForm(pnlMain, SWT.VERTICAL); GridData gid = new GridData(); gid.grabExcessHorizontalSpace = gid.grabExcessVerticalSpace = true; gid.horizontalAlignment = gid.verticalAlignment = GridData.FILL; splitter.setLayoutData(gid); // $NON-NLS-1$ createCheckboxTreeComposite(splitter, getString("checkboxTreeGroup.title")); //$NON-NLS-1$ restoreState(); } /** * create the checkbox tree Composite * * @param parent the parent composite * @param title the group title */ private void createCheckboxTreeComposite( Composite parent, String title ) { Composite checkBoxTreeComposite = WidgetFactory.createPanel(parent, SWT.NONE, GridData.FILL_BOTH); GridLayout layout = new GridLayout(1, false); checkBoxTreeComposite.setLayout(layout); // -------------------------- // Group for checkbox tree // -------------------------- Group group = WidgetFactory.createGroup(checkBoxTreeComposite, title, GridData.FILL_BOTH, 1, 2); // ---------------------------- // TreeViewer // ---------------------------- this.controller = new CheckboxTreeController(); this.treeViewer = WidgetFactory.createTreeViewer(group, SWT.SINGLE | SWT.CHECK, GridData.FILL_BOTH, controller); this.tree = this.treeViewer.getTree(); tree.addListener(SWT.Selection, this); tree.setLayoutData(new GridData(GridData.FILL_BOTH)); this.treeViewer.setContentProvider(new CheckboxTreeContentProvider()); this.treeViewer.setLabelProvider(new CheckboxTreeLabelProvider()); this.treeViewer.setInput(null); // ---------------------------- // Select/DeSelect Buttons // ---------------------------- Composite buttonComposite = WidgetFactory.createPanel(group, SWT.NONE, GridData.FILL_VERTICAL); layout = new GridLayout(1, false); buttonComposite.setLayout(layout); this.selectAllButton = WidgetFactory.createButton(buttonComposite, getString("selectAllButton.text"), GridData.FILL_HORIZONTAL); //$NON-NLS-1$ this.selectAllButton.setToolTipText(getString("selectAllButton.tipText")); //$NON-NLS-1$ this.deselectAllButton = WidgetFactory.createButton(buttonComposite, getString("deselectAllButton.text"), GridData.FILL_HORIZONTAL); //$NON-NLS-1$ this.deselectAllButton.setToolTipText(getString("deselectAllButton.tipText")); //$NON-NLS-1$ this.selectAllButton.addListener(SWT.Selection, this); this.deselectAllButton.addListener(SWT.Selection, this); } /** * @see org.eclipse.jface.dialogs.IDialogPage#dispose() * @since 4.2 */ @Override public void dispose() { saveState(); } /** * Utility to get localized text from properties file. * * @param theKey the key whose localized value is being requested * @return the localized text */ private static String getString( String theKey ) { return IInternalUiConstants.UTIL.getString(new StringBuffer().append(PREFIX).append(theKey).toString()); } /** * Restores dialog size and position of the last time wizard ran. * * @since 4.2 */ private void restoreState() { IDialogSettings settings = getDialogSettings(); if (settings != null) { Shell shell = getContainer().getShell(); if (shell != null) { try { int x = settings.getInt(DIALOG_X); int y = settings.getInt(DIALOG_Y); int width = settings.getInt(DIALOG_WIDTH); int height = settings.getInt(DIALOG_HEIGHT); shell.setBounds(x, y, width, height); } catch (NumberFormatException theException) { // getInt(String) throws exception if not found. // just means no settings exist yet. } } } } /** * Persists dialog size and position. * * @since 4.2 */ private void saveState() { IDialogSettings settings = getDialogSettings(); if (settings != null) { Shell shell = getContainer().getShell(); if (shell != null) { Rectangle r = shell.getBounds(); settings.put(DIALOG_X, r.x); settings.put(DIALOG_Y, r.y); settings.put(DIALOG_WIDTH, r.width); settings.put(DIALOG_HEIGHT, r.height); } } } /** * Sets the wizard page status message. * * @since 4.2 */ void setPageStatus() { WizardUtil.setPageComplete(this); getContainer().updateButtons(); } @Override public void setVisible( boolean isVisible ) { if (isVisible) { definitionsLabelMap.clear(); this.wsdlDefinitions = getInputFromBuilder(); this.treeViewer.setInput(this.wsdlDefinitions); this.importBuilder.setSelectedOperations(new ArrayList()); this.treeViewer.expandToLevel(3); setAllNodesSelected(true); setPageStatus(); } super.setVisible(isVisible); } private List getInputFromBuilder() { // Go through the WSDL models and obtain all root-level WSDL objects ... List allRoots = new ArrayList(); final Collection resources = this.importBuilder.getWSDLResources(); final Iterator iter = resources.iterator(); while (iter.hasNext()) { final IWebServiceResource wsr = (IWebServiceResource)iter.next(); // Load the WSD ... final Resource emfResource = this.importBuilder.getEmfResource(wsr); if (emfResource != null) { final List roots = emfResource.getContents(); final Iterator rootIter = roots.iterator(); while (rootIter.hasNext()) { final EObject root = (EObject)rootIter.next(); if (root instanceof Definitions) { allRoots.add(root); definitionsLabelMap.put(root, "Definitions: " + emfResource.getURI()); //$NON-NLS-1$ } } } } return allRoots; } private void setAllNodesSelected( boolean bSelected ) { TreeItem[] items = tree.getItems(); for (int i = 0; i < items.length; i++) { setAllSelected(items[i], bSelected); } } private void setAllSelected( final TreeItem item, final boolean checked ) { WidgetUtil.setChecked(item, checked, false, this.controller); // Apply same checked state to any children final TreeItem[] children = item.getItems(); for (int ndx = 0; ndx < children.length; ndx++) { setAllSelected(children[ndx], checked); } } /** * Determine if the object has a 'valid' operation underneath it's heirarchy. Valid operation has 'canModel' set to true. */ boolean hasValidOperation( Object object ) { boolean hasValid = false; if (object instanceof Definitions) { List services = ((Definitions)object).getServices(); for (Iterator iter = services.iterator(); iter.hasNext();) { if (hasValidOperation(iter.next())) { hasValid = true; break; } } } else if (object instanceof Service) { List ports = ((Service)object).getPorts(); for (Iterator iter = ports.iterator(); iter.hasNext();) { if (hasValidOperation(iter.next())) { hasValid = true; break; } } } else if (object instanceof PortType) { List operations = ((PortType)object).getOperations(); for (Iterator iter = operations.iterator(); iter.hasNext();) { if (hasValidOperation(iter.next())) { hasValid = true; break; } } } else if (object instanceof Operation) { hasValid = true; // hasValid = ((Operation)object).canModel(); } return hasValid; } class CheckboxTreeLabelProvider extends LabelProvider { private final Image SERVICE_ICON_IMG = WebServiceUiPlugin.getDefault().getImage(SERVICE_ICON); private final Image PORT_ICON_IMG = WebServiceUiPlugin.getDefault().getImage(PORT_ICON); private final Image OPERATION_ICON_IMG = WebServiceUiPlugin.getDefault().getImage(OPERATION_ICON); // private final Image BINDING_ICON_IMG = WebServiceUiPlugin.getDefault().getImage(BINDING_ICON); final WorkbenchLabelProvider workbenchProvider = new WorkbenchLabelProvider(); @Override public Image getImage( final Object node ) { if (node instanceof Definitions) { return SERVICE_ICON_IMG; } else if (node instanceof PortType) { return PORT_ICON_IMG; } else if (node instanceof Operation) { return OPERATION_ICON_IMG; } return null; } @Override public String getText( final Object node ) { if (node instanceof Definitions) { String theText = (String)definitionsLabelMap.get(node); if (theText == null) { theText = "Definitions"; //$NON-NLS-1$ } return theText; } else if (node instanceof PortType) { return ((PortType)node).getName(); } else if (node instanceof Operation) { return ((Operation)node).getName(); } return "unknownElement"; //$NON-NLS-1$ } } class CheckboxTreeContentProvider implements ITreeContentProvider { @Override public void dispose() { } @Override public Object[] getChildren( final Object node ) { // if(wsdlModel!=null) { if (node instanceof Collection) { return ((Collection)node).toArray(); } else if (node instanceof Definitions) { return ((Definitions)node).getPortTypes().toArray(); } else if (node instanceof PortType) { return ((PortType)node).getOperations().toArray(); } // } return EMPTY_STRING_ARRAY; } @Override public Object[] getElements( final Object inputElement ) { return getChildren(inputElement); } @Override public Object getParent( final Object node ) { // if(wsdlModel!=null) { if (node instanceof Definitions) { return null; } if (node instanceof PortType) { return ((PortType)node).eContainer(); } else if (node instanceof Operation) { return ((Operation)node).eContainer(); } // } return null; } @Override public boolean hasChildren( final Object node ) { // if(wsdlModel!=null) { if (node instanceof Collection) { return !((Collection)node).isEmpty(); } else if (node instanceof Definitions) { return !((Definitions)node).getPortTypes().isEmpty(); } else if (node instanceof PortType) { return !((PortType)node).getOperations().isEmpty(); } // } return false; } @Override public void inputChanged( final Viewer viewer, final Object oldInput, final Object newInput ) { } } class CheckboxTreeController extends DefaultTreeViewerController { /** * @see org.teiid.designer.ui.common.widget.DefaultTreeViewerController#checkedStateToggled(org.eclipse.swt.widgets.TreeItem) */ @Override public void checkedStateToggled( TreeItem item ) { } /** * @see org.teiid.designer.ui.common.widget.ITreeViewerController#isItemCheckable(org.eclipse.swt.widgets.TreeItem) */ @Override public boolean isItemCheckable( final TreeItem item ) { final Object node = item.getData(); if (node instanceof Service || node instanceof PortType || node instanceof Operation) { return hasValidOperation(node); } return false; } /** * <p> * </p> * * @see org.teiid.designer.ui.common.widget.ITreeViewerController#update(org.eclipse.swt.widgets.TreeItem, boolean) * @since 4.0 */ @Override public void update( final TreeItem item, final boolean selected ) { Object dataObj = item.getData(); if (dataObj != null) { final boolean checked = !WidgetUtil.isUnchecked(item); if (isItemCheckable(item)) { item.setChecked(checked); } item.setGrayed(WidgetUtil.isPartiallyChecked(item)); if (selected) { updateChildren(item, checked); for (TreeItem parent = item.getParentItem(); parent != null; parent = parent.getParentItem()) { int state = PARTIALLY_CHECKED; final TreeItem[] children = parent.getItems(); for (int ndx = children.length; --ndx >= 0;) { final TreeItem child = children[ndx]; if (WidgetUtil.isPartiallyChecked(child)) { state = PARTIALLY_CHECKED; break; } final int childState = WidgetUtil.getCheckedState(child); if (state == PARTIALLY_CHECKED) { state = childState; } else if (state != childState) { state = PARTIALLY_CHECKED; break; } } if (state != WidgetUtil.getCheckedState(parent)) { WidgetUtil.setCheckedState(parent, state, false, this); } } } if (dataObj instanceof Operation && hasValidOperation(dataObj)) { updateCheckedOperations((Operation)dataObj, checked); } if (!isItemCheckable(item)) { item.setGrayed(true); item.setChecked(false); } else { item.setGrayed(false); } } } private void updateCheckedOperations( Operation operation, boolean checked ) { Collection selectedOperations = importBuilder.getSelectedOperations(); if (checked && !selectedOperations.contains(operation)) { selectedOperations.add(operation); importBuilder.setSelectedOperations(selectedOperations); setPageStatus(); } else if (!checked && selectedOperations.contains(operation)) { selectedOperations.remove(operation); importBuilder.setSelectedOperations(selectedOperations); setPageStatus(); } } /** * @since 4.0 */ private void updateChildren( final TreeItem item, final boolean checked ) { final TreeItem[] children = item.getItems(); for (int ndx = children.length; --ndx >= 0;) { final TreeItem child = children[ndx]; if (child.getData() != null) { updateChildren(child, checked); WidgetUtil.setChecked(child, checked, false, this); } } } /** * @see org.teiid.designer.ui.common.widget.ITreeViewerController#itemExpanded(org.eclipse.jface.viewers.TreeExpansionEvent) * @since 4.0 */ @Override public void itemExpanded( final TreeExpansionEvent event ) { if (treeExpanded) { super.itemExpanded(event); } else { // Do a length check on selection to avoid Array Index OOB exception if( ((TreeViewer)event.getTreeViewer()).getTree().getSelection().length > 0 ) { final TreeItem item = ((TreeViewer)event.getTreeViewer()).getTree().getSelection()[0]; if (item.getData() != null) { updateChildren(item, false); } treeExpanded = true; } } } @Override public void itemCollapsed( final TreeExpansionEvent event ) { super.itemCollapsed(event); } } }