/* * 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.io.File; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.help.IWorkbenchHelpSystem; import org.teiid.core.designer.util.FileUtils; import org.teiid.core.designer.util.I18nUtil; import org.teiid.core.designer.util.StringConstants; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.ui.common.InternalUiConstants; import org.teiid.designer.ui.common.product.ProductCustomizerMgr; import org.teiid.designer.ui.common.util.UiUtil; import org.teiid.designer.ui.common.util.WidgetFactory; import org.teiid.designer.ui.common.util.WidgetUtil; import org.teiid.designer.ui.common.viewsupport.StatusInfo; import org.teiid.designer.ui.common.wizard.AbstractWizardPage; import org.teiid.designer.ui.explorer.ModelExplorerLabelProvider; import org.teiid.designer.ui.viewsupport.ModelNameUtil; import org.teiid.designer.ui.viewsupport.ModelWorkspaceViewerFilter; 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 XmlModelSelectionPage extends AbstractWizardPage implements FileUtils.Constants, IInternalUiConstants, IInternalUiConstants.HelpContexts, IInternalUiConstants.Images { /** Properties key prefix. */ private static final String PREFIX = I18nUtil.getPropertyPrefix(XmlModelSelectionPage.class); /** Key for XML folder MRU list. */ private static final String XML_FOLDER_MRU = "xmlFolderList"; //$NON-NLS-1$ /** The model builder. */ private IWebServiceModelBuilder builder; /** Indicates if initial state has been restored. */ private boolean initialized; /** The XML model workspace location. */ private String modelLocation; /** The XML model name. */ private String modelName; /** Filter used in workspace selection dialogs. */ private ModelWorkspaceViewerFilter viewerFilter; /** Button to browse to choose the model location. */ private Button btnFolder; /** MRU for previously chosen locations. */ private Combo cbxFolder; /** Field for displaying model name. */ private Text txfModel; /** Checkbox indicating if a new model will be generated. */ private Button chkGenerateModel; /** * Constructs a <code>XmlModelSelectionPage</code> using the specified builder. * * @param theBuilder the model builder * @since 4.2 */ public XmlModelSelectionPage( IWebServiceModelBuilder theBuilder ) { super(XmlModelSelectionPage.class.getSimpleName(), getString("title")); //$NON-NLS-1$ this.builder = theBuilder; this.viewerFilter = new ModelWorkspaceViewerFilter(); setImageDescriptor(WebServiceUiUtil.getImageDescriptor(NEW_MODEL_BANNER)); setPageComplete(true); } /** * @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 = 3; Composite pnl = WidgetFactory.createPanel(theParent, SWT.NONE, GridData.FILL_BOTH); pnl.setLayout(new GridLayout(COLUMNS, false)); setControl(pnl); IWorkbenchHelpSystem helpSystem = UiUtil.getWorkbench().getHelpSystem(); helpSystem.setHelp(pnl, XML_MODEL_SELECTION_PAGE); // // ROW 1: GENERATE MODEL // this.chkGenerateModel = WidgetFactory.createCheckBox(pnl, getString("checkbox.generateModel"), SWT.NONE, COLUMNS, true); //$NON-NLS-1$ this.chkGenerateModel.setToolTipText(getString("checkbox.generateModel.tip")); //$NON-NLS-1$ this.chkGenerateModel.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent theEvent ) { handleGenerateModelSelected(); } }); // // ROW 2: FOLDER INFO // // folder label CLabel folderLabel = WidgetFactory.createLabel(pnl, getString("label.folder")); //$NON-NLS-1$ // folder combo this.cbxFolder = WidgetFactory.createCombo(pnl, SWT.READ_ONLY, GridData.FILL_HORIZONTAL); this.cbxFolder.addModifyListener(new ModifyListener() { @Override public void modifyText( ModifyEvent theEvent ) { handleFolderChanged(); } }); // folder browse button this.btnFolder = WidgetFactory.createButton(pnl, InternalUiConstants.Widgets.BROWSE_BUTTON); this.btnFolder.setToolTipText(getString("button.browse.folder.tip")); //$NON-NLS-1$ this.btnFolder.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent theEvent ) { handleBrowseFolderSelected(); } }); // // ROW 3: MODEL INFO // // folder label WidgetFactory.createLabel(pnl, getString("label.xmlModel")); //$NON-NLS-1$ // model combo this.txfModel = WidgetFactory.createTextField(pnl, GridData.FILL_HORIZONTAL); this.txfModel.addModifyListener(new ModifyListener() { @Override public void modifyText( ModifyEvent theEvent ) { handleModelChanged(); } }); if (ProductCustomizerMgr.getInstance().getProductCharacteristics().isHiddenProjectCentric()) { folderLabel.setVisible(false); btnFolder.setVisible(false); cbxFolder.setVisible(false); } } /** * @see org.eclipse.jface.dialogs.IDialogPage#dispose() * @since 4.2 */ @Override public void dispose() { saveFolderMru(); super.dispose(); } /** * 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; } /** * Obtains a string representation of the specified location. * * @param theContainer the location whose string representation is being requested * @return the location text * @since 4.2 */ private String getLocationText( IContainer theContainer ) { return (theContainer == null) ? "" //$NON-NLS-1$ : theContainer.getFullPath().makeRelative().toString(); } /** * Obtains an <code>IPath</code> for the XML model being generated. * * @return the path or <code>null</code> if no model is being generated or model information is not complete * @since 4.2 * @see #isModelInfoComplete() */ private IPath getModelPath() { return (this.chkGenerateModel.getSelection() && isModelInfoComplete()) ? new Path(getModelPath(this.modelLocation, this.modelName)) : null; } private String getModelPath( final String modelLocation, final String modelName ) { return new StringBuffer().append(modelLocation).append(File.separator).append(modelName).append(FILE_EXTENSION_SEPARATOR_CHAR).append(StringConstants.XMI).toString(); } /** * 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 the browse location/folder is pushed. * * @since 4.2 */ void handleBrowseFolderSelected() { this.viewerFilter.setShowModels(false); Object[] resources = WidgetUtil.showWorkspaceObjectSelectionDialog(getString("dialog.xmlModelLocationChooser.title"), //$NON-NLS-1$ getString("dialog.xmlModelLocationChooser.msg"), //$NON-NLS-1$ false, this.modelLocation, this.viewerFilter, null, new ModelExplorerLabelProvider()); if ((resources != null) && (resources.length > 0)) { setFolder(getLocationText((IContainer)resources[0])); } } /** * Handler for when the location/folder text is changed. Updates the builder and sets the page status. * * @since 4.2 */ void handleFolderChanged() { this.modelLocation = this.cbxFolder.getText(); updateModelInfo(); } /** * Handler for when the generate model checkbox is selected/deselected. Updates the builder and sets the page status. * * @since 4.2 */ void handleGenerateModelSelected() { boolean enable = this.chkGenerateModel.getSelection(); this.cbxFolder.setEnabled(enable); this.btnFolder.setEnabled(enable); this.txfModel.setEnabled(enable); updateModelInfo(); } /** * Handler for when the model name text is changed. Updates the builder and sets the page status. * * @since 4.2 */ void handleModelChanged() { this.modelName = this.txfModel.getText(); updateModelInfo(); } /** * Indicates if the XML model location and name have been set. * * @return <code>true</code>if complete; <code>false</code> otherwise. * @since 4.2 */ private boolean isModelInfoComplete() { return ((this.modelName != null) && (this.modelName.length() > 0) && (this.modelLocation != null) && (this.modelLocation.length() > 0)); } /** * Updates the MRU for the XML folder combo to agree with the dialog settings. * * @since 4.2 */ private void loadFolderMru() { IDialogSettings settings = getDialogSettings(); if (settings != null) { // get the right section String[] temp = settings.getArray(XML_FOLDER_MRU); if (temp != null) { List folders = new ArrayList(temp.length); for (int i = 0; i < temp.length; i++) { // only add if folder exists in workspace if (ModelerCore.getWorkspace().getRoot().findMember(temp[i]) != null) { folders.add(temp[i]); } } WidgetUtil.setComboItems(this.cbxFolder, folders, null, true); } } } private void saveFolderMru() { IDialogSettings settings = getDialogSettings(); // cbxFolder will be null if wizard is cancelled and this page has not be shown yet if ((settings != null) && (this.cbxFolder != null)) { WidgetUtil.saveSettings(settings, XML_FOLDER_MRU, this.cbxFolder); } } /** * Sets the folder/location into the MRU control. * * @param thePath the location/folder * @since 4.2 */ private void setFolder( String thePath ) { if (thePath != null) { int index = this.cbxFolder.indexOf(thePath); if (index == -1) { this.cbxFolder.add(thePath); index = this.cbxFolder.indexOf(thePath); } this.cbxFolder.select(index); } } /** * Sets the model name into the MRU control. * * @param theName the model name * @since 4.2 */ private void setModelName( String theName ) { this.txfModel.setText(theName); } /** * Sets the wizard page status message. * * @since 4.2 */ private void setPageStatus( IStatus theStatus ) { if (theStatus.getSeverity() == IStatus.ERROR) { setErrorMessage(theStatus.getMessage()); setPageComplete(false); } else { setErrorMessage(null); // must clear error message setMessage(theStatus.getMessage(), theStatus.getSeverity()); setPageComplete(true); } } /** * Sets page complete status and message based on the specified information and the builder's validation state. * * @param theSeverity the UI validation severity * @param theMessage the UI validation message * @since 4.2 */ private void setPageStatus( int theSeverity, String theMessage ) { IStatus builderStatus = this.builder.validateXSDNamespaces(); int builderSeverity = builderStatus.getSeverity(); if (theSeverity > builderSeverity) { setPageStatus(new StatusInfo(PLUGIN_ID, theSeverity, (theMessage == null) ? "" : theMessage)); //$NON-NLS-1$ } else if (theSeverity < builderSeverity) { setPageStatus(builderStatus); } else { String msg = null; if ((theMessage == null) || (theMessage.length() == 0)) { msg = builderStatus.getMessage(); } else { msg = new StringBuffer().append(builderStatus.getMessage()).append(" : ").append(theMessage).toString(); //$NON-NLS-1$ } setPageStatus(new StatusInfo(PLUGIN_ID, theSeverity, msg)); } } /** * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean) */ @Override public void setVisible( boolean theShowFlag ) { // initialize state if (theShowFlag) { if (!this.initialized) { // update XML folder MRU loadFolderMru(); // set initial folder and name based on web service model IPath modelPath = this.builder.getModelPath(); String name = modelPath.removeFileExtension().lastSegment() + getString("xmlModelSuffix"); //$NON-NLS-1$ this.builder.setXmlModel(modelPath.removeLastSegments(1).append(name).addFileExtension(modelPath.getFileExtension())); this.initialized = true; } // initialized model if necessary IPath xmlModel = this.builder.getXmlModel(); if (xmlModel != null) { setFolder(xmlModel.removeLastSegments(1).toOSString()); setModelName(xmlModel.removeFileExtension().lastSegment()); } // call this method to set the page status updateModelInfo(); // set focus so that the help context will be correct this.chkGenerateModel.setFocus(); } else { saveFolderMru(); // do this in order to allow finish button to be pressed prior to viewing this page setPageComplete(true); } super.setVisible(theShowFlag); } /** * Updates the model info in the model builder and then sets the page status message. * * @since 4.2 */ private void updateModelInfo() { if (this.chkGenerateModel.getSelection()) { if (isModelInfoComplete()) { // see if model exists or would be a new model String temp = null; IPath containerPath = new Path(this.modelLocation); IResource resource = ModelerCore.getWorkspace().getRoot().findMember(containerPath); if (resource != null) { IPath path = resource.getLocation(); temp = path.toOSString(); } // validate characters in the proposed name IStatus status = ModelNameUtil.validate(this.modelName, ModelerCore.MODEL_FILE_EXTENSION, resource!=null?resource.getParent():null, ModelNameUtil.IGNORE_CASE | ModelNameUtil.NO_DUPLICATE_MODEL_NAMES | ModelNameUtil.NO_EXISTING_MODEL_AT_LOCATION); if (status.getSeverity() != IStatus.ERROR ) { String name = getModelPath(temp, this.modelName); boolean exists = new File(name).exists(); if (exists) { this.builder.setXmlModel(null); setPageStatus(IStatus.ERROR, getString("page.msg.modelExists")); //$NON-NLS-1$ } else if (this.builder.getModelPath().equals(getModelPath())) { this.builder.setXmlModel(null); setPageStatus(IStatus.ERROR, getString("page.msg.sameAsWebServiceModelName")); //$NON-NLS-1$ } else { this.builder.setXmlModel(getModelPath()); setPageStatus(IStatus.OK, null); } } else { this.builder.setXmlModel(null); setPageStatus(IStatus.ERROR, getString("page.msg.modelNameInvalid")); //$NON-NLS-1$ } } else { this.builder.setXmlModel(null); setPageStatus(IStatus.ERROR, getString("page.msg.modelIncomplete")); //$NON-NLS-1$ } } else { this.builder.setXmlModel(null); setPageStatus(IStatus.OK, getString("page.msg.xmlModelNotGenerated")); //$NON-NLS-1$ } } }