/* * 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.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ViewForm; 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.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.ui.ISharedImages; import org.eclipse.wst.wsdl.validation.internal.IValidationMessage; import org.eclipse.wst.wsdl.validation.internal.IValidationReport; 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.ui.common.table.TableViewerSorter; 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.AbstractTableLabelProvider; import org.teiid.designer.ui.common.wizard.AbstractWizardPage; import org.teiid.designer.webservice.IWebServiceModelBuilder; import org.teiid.designer.webservice.ui.IInternalUiConstants; import org.teiid.designer.webservice.ui.util.WebServiceUiUtil; /** * * * @since 8.0 */ public class ImportWsdlValidationPage extends AbstractWizardPage implements FileUtils.Constants, IInternalUiConstants, IInternalUiConstants.HelpContexts, IInternalUiConstants.Images { /** Used as a prefix to properties file keys. */ private static final String PREFIX = I18nUtil.getPropertyPrefix(ImportWsdlValidationPage.class); private static final int SEVERITY_COLUMN = 0; private static final int MESSAGE_COLUMN = 1; private static final int OBJECT_COLUMN = 2; private static final int LINE_NUMBER_COLUMN = 3; private static final String MESSAGE_HEADER = getString("messageHeader"); //$NON-NLS-1$ private static final String OBJECT_HEADER = getString("objectHeader"); //$NON-NLS-1$ private static final String LINE_NUMBER_HEADER = getString("lineNumber"); //$NON-NLS-1$ /** <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 model builder. */ protected IWebServiceModelBuilder builder; /** Action to view selected WSDL using system editor. */ private IAction viewWsdlAction; /** The wsdl file validation warning/error table view */ private TableViewer viewer; /** * The list of WSDL validation messages. These are of type IValidationMessage. This list is filled when the validateWSDLs() * method is run. */ List wsdlValidationMessages; private boolean wsdlsHaveErrors = false; /** * Constructs a <code>WsdlValidationPage</code> using the specified builder. * * @param theBuilder the model builder * @since 4.2 */ public ImportWsdlValidationPage( IWebServiceModelBuilder theBuilder ) { super(ImportWsdlValidationPage.class.getSimpleName(), getString("title")); //$NON-NLS-1$ wsdlValidationMessages = new LinkedList(); this.builder = theBuilder; setImageDescriptor(WebServiceUiUtil.getImageDescriptor(NEW_MODEL_BANNER)); } /** * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) * @since 4.2 */ @Override public void createControl( Composite theParent ) { // // create main container // 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); createTablePanel(pnlMain); nameModified(); } /** * @see org.teiid.designer.ui.common.wizard.AbstractWizardPage#canFlipToNextPage() * @since 4.2 */ @Override public boolean canFlipToNextPage() { // if no WSDLs identified don't let the next page show. Only prevent navigation if an error // exist. return !wsdlsHaveErrors && super.canFlipToNextPage(); } /** * Constructs the table's toolbar actions. * * @param theToolBarMgr the toolbar where the actions are installed * @since 4.2 */ private void createTableActions( IToolBarManager theToolBarMgr ) { // // view action // this.viewWsdlAction = new Action(getString("action.viewWsdlFile"), IAction.AS_PUSH_BUTTON) { //$NON-NLS-1$ @Override public void run() { handleViewWsdlFile(); } }; this.viewWsdlAction.setImageDescriptor(WebServiceUiUtil.getSharedImageDescriptor(ISharedImages.IMG_OBJ_FILE)); this.viewWsdlAction.setToolTipText(getString("action.viewWsdlFile.tip")); //$NON-NLS-1$ this.viewWsdlAction.setEnabled(false); theToolBarMgr.add(this.viewWsdlAction); // update toolbar to pick up actions theToolBarMgr.update(true); } /** * Creates the context menu of the table. * * @since 4.2 */ protected void createTableContextMenu() { MenuManager mgr = new MenuManager(); mgr.add(this.viewWsdlAction); Control table = this.viewer.getControl(); table.setMenu(mgr.createContextMenu(table)); } /** * Constructs the table panel controls. * * @param theParent the parent container * @since 4.2 */ private void createTablePanel( Composite theParent ) { ViewForm viewForm = WidgetFactory.createViewForm(theParent, SWT.BORDER, GridData.FILL_BOTH, 1); viewForm.setTopLeft(WidgetFactory.createLabel(viewForm, getString("WSDL_Validation_Panel"))); //$NON-NLS-1$ Composite pnl = WidgetFactory.createPanel(viewForm, SWT.NONE, GridData.FILL_BOTH); viewForm.setContent(pnl); this.viewer = WidgetFactory.createTableViewer(pnl, SWT.FULL_SELECTION); final Table table = this.viewer.getTable(); table.setHeaderVisible(true); table.setLinesVisible(true); WidgetFactory.createTableColumn(table); WidgetFactory.createTableColumn(table, MESSAGE_HEADER); WidgetFactory.createTableColumn(table, OBJECT_HEADER); WidgetFactory.createTableColumn(table, LINE_NUMBER_HEADER); this.viewer.setContentProvider(new IStructuredContentProvider() { @Override public void dispose() { } @Override public Object[] getElements( final Object inputElement ) { return wsdlValidationMessages.toArray(); } @Override public void inputChanged( final Viewer viewer, final Object oldInput, final Object newInput ) { } }); this.viewer.setLabelProvider(new AbstractTableLabelProvider() { @Override public Image getColumnImage( final Object element, final int column ) { if (column == SEVERITY_COLUMN) { return getStatusImage(((IValidationMessage)element).getSeverity()); } return null; } @Override public String getColumnText( final Object element, final int column ) { final IValidationMessage message = (IValidationMessage)element; switch (column) { case MESSAGE_COLUMN: { final String messageString = message.getMessage(); return messageString == null ? CoreStringUtil.Constants.EMPTY_STRING : messageString; } case OBJECT_COLUMN: { // Get the file name from the URI. This is the key to the url map if this wsdl was loaded via url. String target = (String)builder.getUrlMap().get(message.getURI().substring(message.getURI().lastIndexOf('/') + 1)); // If the target is null, this wsdl was file based so we get the uri off the message if (target == null) target = message.getURI(); return target == null ? CoreStringUtil.Constants.EMPTY_STRING : target; } case LINE_NUMBER_COLUMN: { final String lineNumber = String.valueOf(message.getLine()); return lineNumber == null ? CoreStringUtil.Constants.EMPTY_STRING : lineNumber; } } return CoreStringUtil.Constants.EMPTY_STRING; } }); this.viewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick( final DoubleClickEvent event ) { } }); this.viewer.setSorter(new TableViewerSorter(this.viewer, SEVERITY_COLUMN, TableViewerSorter.ASCENDING) { @Override protected int compareColumn( final TableViewer viewer, final Object object1, final Object object2, final int column ) { if (column == SEVERITY_COLUMN) { return (((IValidationMessage)object2).getSeverity() - ((IValidationMessage)object1).getSeverity()); } return super.compareColumn(viewer, object1, object2, column); } }); this.viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged( SelectionChangedEvent theEvent ) { handleTableSelectionChanged(); } }); this.viewer.setInput(this); WidgetUtil.pack(table); // construct actions to be installed in toolbar createTableActions(WidgetFactory.createViewFormToolBar(viewForm)); // context menu for table createTableContextMenu(); } /** * @since 4.0 */ void nameModified() { validatePage(); } /** * @see org.eclipse.jface.dialogs.IDialogPage#dispose() * @since 4.2 */ @Override public void dispose() { saveState(); } /** * Override to replace the NewModelWizard settings with the section devoted to the Web Service Model Wizard. * * @see org.eclipse.jface.wizard.WizardPage#getDialogSettings() * @since 4.2 */ @Override protected IDialogSettings getDialogSettings() { IDialogSettings settings = super.getDialogSettings(); if (settings != null) { // get the right section of the NewModelWizard settings IDialogSettings temp = settings.getSection(DIALOG_SETTINGS_SECTION); if (temp == null) { settings = settings.addNewSection(DIALOG_SETTINGS_SECTION); } else { settings = temp; } } return settings; } /** * Utility to get localized text from properties file. * * @param theKey the key whose localized value is being requested * @return the localized text * @since 4.2 */ private static String getString( String theKey ) { return UTIL.getString(new StringBuffer().append(PREFIX).append(theKey).toString()); } /** * Handler for when table selection changes. * * @since 4.2 */ void handleTableSelectionChanged() { IStructuredSelection selection = (IStructuredSelection)this.viewer.getSelection(); // enable buttons this.viewWsdlAction.setEnabled(selection.size() == 1); } /** * Handler for when a request to view a WSDL file. Code copied from action that Eclipse uses to view a file using system * editor. * * @since 4.2 */ void handleViewWsdlFile() { WebServiceUiUtil.viewFile(getShell(), this.viewer.getSelection()); } /** * 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); } } } /** * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean) */ @Override public void setVisible( boolean theShowFlag ) { // initialize state if (theShowFlag) { // only restore state one time. after first time input will not be null. if (this.viewer.getInput() == null) { restoreState(); } setPageComplete(true); // always complete since no errors possible this.viewer.setInput(this); // could be any object since it is not used by the viewer // // set focus so that the help context will be correct // if (btnWorkspaceAdd != null) { // this.btnWorkspaceAdd.setFocus(); // } } super.setVisible(theShowFlag); validatePage(); } /** * Check to see if there are any validation messages for display. * * @return boolean */ public boolean hasValidationMessages() { return wsdlValidationMessages.size() > 0; } /** * Check to see if there are any validation error (not just warning) messages for display. * * @return boolean * @since 8.1 */ public boolean hasValidationErrors() { wsdlsHaveErrors = false; Iterator messageIter = wsdlValidationMessages.listIterator(); while (messageIter.hasNext()){ IValidationMessage message = (IValidationMessage)messageIter.next(); if (message.getSeverity() == IValidationMessage.SEV_ERROR){ wsdlsHaveErrors = true; } } return wsdlsHaveErrors; } /** * Setter for wsdl validation messages related to currently selected wsdl files. * * @param wsdlValidationMessageMap */ public void setValidationMessages( Map wsdlValidationMessageMap ) { Iterator wsdlIter = wsdlValidationMessageMap.values().iterator(); /* * Iterate through the list of validation messages for the currently selected wsdl files. * If the message already exists in the validation page's current list of messages, we will * not add them again. This logic is necessary to get around a bug in the wst validator * that will add new messages for the same wsdl file if it is added, removed and added again. */ while (wsdlIter.hasNext()) { IValidationReport report = (IValidationReport)wsdlIter.next(); IValidationMessage[] messages = report.getValidationMessages(); for (int i = 0; i < messages.length; i++) { if (!wsdlValidationMessages.contains(messages[i])) { boolean alreadyExists = false; for (int j = 0; j < wsdlValidationMessages.size(); j++) { IValidationMessage currentWsdlMessage = (IValidationMessage)wsdlValidationMessages.get(j); if (currentWsdlMessage.getMessage().equals(messages[i].getMessage()) && currentWsdlMessage.getLine() == messages[i].getLine()) { alreadyExists = true; break; } } if (!alreadyExists) { wsdlValidationMessages.add(messages[i]); } } } } } public void clearValidationMessages() { wsdlValidationMessages.clear(); } /** * @since 4.0 */ private void validatePage() { /* * Check to see if any WSDLs have any validation errors and/or warnings. */ if (hasValidationErrors()) { WizardUtil.setPageComplete(this, getString("One_or_more_selected_WSDL_files_have_errors"), IMessageProvider.ERROR); //$NON-NLS-1$ }else if(hasValidationMessages()){ WizardUtil.setPageComplete(this, getString("One_or_more_selected_WSDL_files_have_warnings"), IMessageProvider.WARNING); //$NON-NLS-1$ } } Image getStatusImage( final int severity ) { switch (severity) { case IValidationMessage.SEV_ERROR: { return JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_ERROR); } case IValidationMessage.SEV_WARNING: { return JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_WARNING); } default: { return null; } } } }