/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.ws.internal.consumption.ui.wizard;

import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jst.ws.internal.common.J2EEUtils;
import org.eclipse.jst.ws.internal.common.ServerUtils;
import org.eclipse.jst.ws.internal.consumption.ui.plugin.WebServiceConsumptionUIPlugin;
import org.eclipse.jst.ws.internal.data.TypeRuntimeServer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
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.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.help.WorkbenchHelp;
import org.eclipse.wst.server.core.IRuntimeType;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerType;
import org.eclipse.wst.server.core.ServerCore;
import org.eclipse.wst.server.ui.ServerUICore;

public class RuntimeServerSelectionDialog extends Dialog implements Listener {

  private Shell thisShell;
  private Group viewSelectionGroup_;
  private Text messageBanner_;
  private Composite primaryGroup_;
  private Group runtimesGroup_;
  private Group serversGroup_;
  private Tree runtimesList_;
  private Tree serverList_;
  private Button viewSelectionByRuntimeButton_;
  private Button viewSelectionByServerButton_;
  private Button viewSelectionByExploreButton_;
  private Combo j2eeVersionCombo;
  /*
   * CONTEXT_ID PWRS0001 for the selection of runtime, server and project combination
   */
  private String INFOPOP_PWRS_DIALOG = WebServiceConsumptionUIPlugin.ID + ".PWRS0001";
  /* CONTEXT_ID PWRS0002 for the runtime selection on in the dailog */
  private String INFOPOP_PWRS_LIST_RUNTIMES = WebServiceConsumptionUIPlugin.ID + ".PWRS0002";
  /* CONTEXT_ID PWRS0003 for the server selection in the dialog */
  private String INFOPOP_PWRS_LIST_SERVERS = WebServiceConsumptionUIPlugin.ID + ".PWRS0003";
  /*
   * CONTEXT_ID PWRS0004 for the EJB Project combo box of the runtime selection dialog
   */
  //  private String INFOPOP_PWRS_EJB_PROJECT = WebServiceConsumptionUIPlugin.ID
  // + ".PWRS0004";
  /*
   * CONTEXT_ID PWRS0005 for the runtime view radio button of the runtime selection dialog
   */
  private String INFOPOP_PWRS_RADIO_RUNTIME = WebServiceConsumptionUIPlugin.ID + ".PWRS0005";
  /*
   * CONTEXT_ID PWRS0006 for the server view radio button of the runtime selection dialog
   */
  private String INFOPOP_PWRS_RADIO_SERVER = WebServiceConsumptionUIPlugin.ID + ".PWRS0006";
  /*
   * CONTEXT_ID PWRS0007 for the explore view radio button of the runtime selection dialog
   */
  private String INFOPOP_PWRS_RADIO_EXPLORE = WebServiceConsumptionUIPlugin.ID + ".PWRS0007";
  /*
   * CONTEXT_ID PWRS0008 for the Web Project combo box of the runtime selection dialog
   */
  //  private String INFOPOP_PWRS_COMBO_PROJECT =
  // WebServiceConsumptionUIPlugin.ID + ".PWRS0008";
  /*
   * CONTEXT_ID PWRS0009 for the J2EE version combo box of the runtime selection dialog
   */
  private String INFOPOP_PWRS_J2EE_VERSION = WebServiceConsumptionUIPlugin.ID + ".PWRS0009";

  private WebServiceServerRuntimeTypeRegistry wssrtRegistry;
  private WebServiceClientTypeRegistry wsctRegistry;
  private Hashtable serverLabels_;
  private Hashtable existingServersTable_;
  private String defaultServer_;
  private String defaultRuntime_;
  private String typeId_;
  private String clientTypeId_;
  private IWebServiceRuntime selectedRuntime_;
  private IServer selectedServer_;
  private String selectedServerLabel_;
  private String selectedServerFactoryID_;
  private boolean isExistingServer_;
  private boolean validateOn_ = false;
  private byte selectionMode_;
  private final byte MODE_SERVICE = (byte) 0;
  private final byte MODE_CLIENT = (byte) 1;
  private final String SERVER_TYPES_ICON = "icons/servers/servers_obj.gif";
  private final String EXISTING_SERVERS_ICON = "icons/servers/existing_server_obj.gif";
  private String j2eeVersion;
  private String serverInstanceID_;

  public RuntimeServerSelectionDialog(Shell shell, byte mode, TypeRuntimeServer ids, String j2eeVersion) {
    super(shell);
    selectionMode_ = mode;
    typeId_ = ids.getTypeId();
    defaultRuntime_ = ids.getRuntimeId();
    defaultServer_ = ids.getServerId();
    serverInstanceID_ = ids.getServerInstanceId();
    setIsExistingServer(ids.getServerInstanceId() != null);
    serverLabels_ = new Hashtable();
    existingServersTable_ = new Hashtable();
    wsctRegistry = WebServiceClientTypeRegistry.getInstance();
    wssrtRegistry = WebServiceServerRuntimeTypeRegistry.getInstance();
    this.j2eeVersion = j2eeVersion;
  }

  public TypeRuntimeServer getTypeRuntimeServer() {
    TypeRuntimeServer ids = new TypeRuntimeServer();

    ids.setTypeId(typeId_);
    if (selectedRuntime_ != null)
      ids.setRuntimeId(selectedRuntime_.getId());
    
    if( selectedServerFactoryID_ == null )
    {
      ids.setServerId( defaultServer_ );
      ids.setServerInstanceId( serverInstanceID_ );
    }
    else
    {
      ids.setServerId(selectedServerFactoryID_);

      if (isExistingServer_ && selectedServer_ != null) 
      {
        ids.setServerInstanceId(selectedServer_.getId());
      }
    }
    
    return ids;
  }

  public String getJ2EEVersion() {
    return j2eeVersion;
  }

  private boolean getIsExistingServer() {
    return isExistingServer_;
  }

  private void setIsExistingServer(boolean isExisting) {
    isExistingServer_ = isExisting;
  }

  protected Control createContents(Composite parent) {
    Composite comp = (Composite) super.createContents(parent);
    parent.getShell().pack();
    return comp;
  }

  protected Control createDialogArea(Composite parent) {
    validateOn_ = false;
    thisShell = parent.getShell();
    if (thisShell == null) {
      thisShell = createShell();
    }
    Composite composite = (Composite) super.createDialogArea(parent);
    GridLayout gl;
    GridData gd;
    // Window title
    if (selectionMode_ == MODE_SERVICE)
      thisShell.setText(getMessage("%PAGE_TITLE_WS_RUNTIME_SELECTION"));
    else
      thisShell.setText(getMessage("%PAGE_TITLE_WS_CLIENT_RUNTIME_SELECTION"));
    
    WorkbenchHelp.setHelp(thisShell, new Object[] { INFOPOP_PWRS_DIALOG});
    // Dialog description banner
    messageBanner_ = new Text(composite, SWT.READ_ONLY | SWT.WRAP);
    messageBanner_.setText(getMessage("%PAGE_DESC_WS_RUNTIME_SELECTION") + "\n" + "      "); // reserves a second line for message display
    messageBanner_.setToolTipText(getMessage("%PAGE_DESC_WS_RUNTIME_SELECTION"));
    gd = new GridData(GridData.FILL_HORIZONTAL);
    messageBanner_.setLayoutData(gd);
    //  -----------------------------------------------------------------------//
    new Label(composite, SWT.HORIZONTAL);
    //  -----------------------------------------------------------------------//
    // Selection
    thisShell.setToolTipText(getMessage("%TOOLTIP_PWRS_PAGE"));
    viewSelectionGroup_ = new Group(composite, SWT.NONE);
    gl = new GridLayout();
    gl.marginHeight = 0;
    gl.marginWidth = 0;
    viewSelectionGroup_.setLayout(gl);
    gd = new GridData(GridData.FILL_HORIZONTAL);
    viewSelectionGroup_.setLayoutData(gd);
    if (selectionMode_ == MODE_SERVICE)
      viewSelectionGroup_.setText(getMessage("%LABEL_SELECTION_VIEW_TITLE"));
    else
      viewSelectionGroup_.setText(getMessage("%LABEL_CLIENT_SELECTION_VIEW_TITLE"));
    viewSelectionByServerButton_ = new Button(viewSelectionGroup_, SWT.RADIO);
    viewSelectionByServerButton_.setText(getMessage("%LABEL_SELECTION_VIEW_SERVER"));
    viewSelectionByServerButton_.addListener(SWT.Selection, this);
    viewSelectionByServerButton_.setToolTipText(getMessage("%TOOLTIP_PWRS_RADIO_SERVER"));
    viewSelectionByServerButton_.setSelection(true);
    WorkbenchHelp.setHelp(viewSelectionByServerButton_, new Object[] { INFOPOP_PWRS_RADIO_SERVER});
    viewSelectionByRuntimeButton_ = new Button(viewSelectionGroup_, SWT.RADIO);
    viewSelectionByRuntimeButton_.setText(getMessage("%LABEL_SELECTION_VIEW_RUNTIME"));
    viewSelectionByRuntimeButton_.addListener(SWT.Selection, this);
    viewSelectionByRuntimeButton_.setToolTipText(getMessage("%TOOLTIP_PWRS_RADIO_RUNTIME"));
    WorkbenchHelp.setHelp(viewSelectionByRuntimeButton_, new Object[] { INFOPOP_PWRS_RADIO_RUNTIME});
    viewSelectionByExploreButton_ = new Button(viewSelectionGroup_, SWT.RADIO);
    viewSelectionByExploreButton_.setText(getMessage("%LABEL_SELECTION_VIEW_EXPLORE"));
    viewSelectionByExploreButton_.addListener(SWT.Selection, this);
    viewSelectionByExploreButton_.setToolTipText(getMessage("%TOOLTIP_PWRS_RADIO_EXPLORE"));
    WorkbenchHelp.setHelp(viewSelectionByExploreButton_, new Object[] { INFOPOP_PWRS_RADIO_EXPLORE});
    primaryGroup_ = new Composite(composite, SWT.NONE);
    gl = new GridLayout();
    gl.numColumns = 1;
    gl.makeColumnsEqualWidth = true;
    gd = new GridData(GridData.FILL_BOTH);
    primaryGroup_.setLayout(gl);
    primaryGroup_.setLayoutData(gd);
    runtimesGroup_ = new Group(primaryGroup_, SWT.NONE);
    gl = new GridLayout();
    runtimesGroup_.setLayout(gl);
    gd = new GridData(GridData.FILL_BOTH);
    runtimesGroup_.setLayoutData(gd);
    runtimesGroup_.setText(getMessage("%LABEL_RUNTIMES_LIST"));
    runtimesList_ = new Tree(runtimesGroup_, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
    gd = new GridData(GridData.FILL_BOTH);
    runtimesList_.setLayoutData(gd);
    runtimesList_.addListener(SWT.Selection, this);
    runtimesList_.setToolTipText(getMessage("%TOOLTIP_PWRS_LIST_RUNTIMES"));
    WorkbenchHelp.setHelp(runtimesList_, new Object[] { INFOPOP_PWRS_LIST_RUNTIMES});
    //  Server labels control
    serversGroup_ = new Group(primaryGroup_, SWT.NONE);
    gl = new GridLayout();
    serversGroup_.setLayout(gl);
    gd = new GridData(GridData.FILL_BOTH);
    serversGroup_.setLayoutData(gd);
    serversGroup_.setText(getMessage("%LABEL_SERVERS_LIST"));
    serverList_ = new Tree(serversGroup_, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
    serverList_.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
    serverList_.addListener(SWT.Selection, this);
    serverList_.setToolTipText(getMessage("%TOOLTIP_PWRS_LIST_SERVERS"));
    ServersList serverList = new ServersList();
    serverList.setServerTreeItems(serverList_);
    WorkbenchHelp.setHelp(serverList_, new Object[] { INFOPOP_PWRS_LIST_SERVERS});
    setRuntimesGroup();
    // J2EE version
    Composite j2eeVersionComposite = new Composite(composite, SWT.NONE);
    gl = new GridLayout();
    gl.marginHeight = 0;
    gl.marginWidth = 0;
    gl.numColumns = 2;
    gd = new GridData(GridData.FILL_HORIZONTAL);
    j2eeVersionComposite.setLayout(gl);
    j2eeVersionComposite.setLayoutData(gd);
    Label j2eeVersionLabel = new Label(j2eeVersionComposite, SWT.NONE);
    j2eeVersionLabel.setText(getMessage("%LABEL_J2EE_VERSION"));
    j2eeVersionCombo = new Combo(j2eeVersionComposite, SWT.DROP_DOWN | SWT.READ_ONLY);
    gl = new GridLayout();
    gl.marginHeight = 0;
    gl.marginWidth = 0;
    gd = new GridData(GridData.FILL_HORIZONTAL);
    j2eeVersionCombo.setLayout(gl);
    j2eeVersionCombo.setLayoutData(gd);
    j2eeVersionCombo.addListener(SWT.Selection, this);
    j2eeVersionCombo.setToolTipText(getMessage("%TOOLTIP_PWRS_J2EE_VERSION"));
    WorkbenchHelp.setHelp(j2eeVersionCombo, new Object[] { INFOPOP_PWRS_J2EE_VERSION});
    //  -----------------------------------------------------------------------//
    new Label(composite, SWT.HORIZONTAL);
    validateOn_ = true;
    org.eclipse.jface.dialogs.Dialog.applyDialogFont(parent);
    setJ2EEVersions();
    return composite;
  }

  private void setJ2EEVersions() {
    j2eeVersionCombo.setEnabled(true);
    j2eeVersionCombo.removeAll();
    String[] versions = null;
    if (selectedRuntime_ != null)
      versions = selectedRuntime_.getJ2EEVersions();
    if (versions != null) {
      //j2eeVersionCombo.setItems(versions);
      setJ2EEComboItems(versions);
      j2eeVersionCombo.select(0);
      if (j2eeVersion != null) {
        int i = j2eeVersionCombo.indexOf(J2EEUtils.getLabelFromJ2EEVersion(j2eeVersion));
        if (i > 0)
          j2eeVersionCombo.select(i);
      }
    }
    else
      j2eeVersionCombo.setEnabled(false);
  }

  private void setJ2EEComboItems(String[] versions)
  {
    String[] j2eeLabels = new String[versions.length];
    for (int i = 0; i < versions.length; i++)
    {
      String label = J2EEUtils.getLabelFromJ2EEVersion(versions[i]);
      if (label != null && label.length() >0)
        j2eeLabels[i] = J2EEUtils.getLabelFromJ2EEVersion(versions[i]);
      else
        j2eeLabels[i] = getMessage("%LABEL_NA"); 
    }
    j2eeVersionCombo.setItems(j2eeLabels);
  }
  
  private void validateServerRuntimeSelection() {
    // Check if the extension exists
    if (selectionMode_ == MODE_SERVICE) {
      if (selectedServerFactoryID_!=null && selectedRuntime_!=null) {
      WebServiceServerRuntimeType wssrt = wssrtRegistry.getWebServiceServerRuntimeType(selectedServerFactoryID_, selectedRuntime_.getId(), typeId_);
      // rm WebServiceServerRuntimeType wssrt =
      // wssrtRegistry.getWebServiceServerRuntimeType(selectedServerFactoryID_,
      // selectedRuntime_.getId(), wse.getWebServiceType());
      // rm if (wssrt!=null &&
      // wssrtRegistry.isServerSupportedForChosenType(wse.getWebServiceType(),selectedServerFactoryID_))
      // {
      if (wssrt != null && wssrtRegistry.isServerSupportedForChosenType(typeId_, selectedServerFactoryID_)) {
        setOKStatusMessage();
      }
      else {
        setERRORStatusMessage("%MSG_INVALID_SRT_SELECTIONS");
      }
      }
    }
    else {
      // rm String clientId =
      // wsctRegistry.getClientTypeIdByName(clientScenarioId_);
      String clientId = typeId_;
      // rm String clientId =
      // wsctRegistry.getClientTypeIdByName(wse.getProxySelected());
      WebServiceServer wss = wsctRegistry.getWebServiceServerByFactoryId(selectedServerFactoryID_);

      if (wss == null || selectedRuntime_ == null || !wsctRegistry.webServiceClientRuntimeTypeExists(wss.getId(), selectedRuntime_.getId(), clientId)) {
        setERRORStatusMessage("%MSG_INVALID_SRT_SELECTIONS");
      }
      else {
        setOKStatusMessage();
      }
    }
    // Disable OK button if the runtime selection is invalid
    TreeItem[] runtimeSel = runtimesList_.getSelection();
    if (runtimeSel == null || runtimeSel.length <= 0 || runtimeSel[0].getText().length() == 0) {
      disableOKButton();
    }
    // Disable OK button if server selection is invalid
    TreeItem[] serverSel = serverList_.getSelection();
    String currentSelection = (serverSel != null && serverSel.length > 0) ? serverSel[0].getText() : "";
    if (serverSel == null || currentSelection.length() == 0) {
      disableOKButton();
    }
    if (!serverLabels_.containsKey(currentSelection) || !existingServersTable_.containsKey(currentSelection)) {
      disableOKButton();
      setOKStatusMessage();
    }
    // Disable OK button if category is selected rather than a server
    if (serverSel.length > 0 && serverSel[0].getItemCount()!=0) {
    	disableOKButton();
    }
    else {
    	enableOKButton();
    }
    
  }

  private void setOKStatusMessage() {
    messageBanner_.setText(getMessage("%PAGE_DESC_WS_RUNTIME_SELECTION"));
    Color black = new Color(thisShell.getDisplay(), 0x00, 0, 0);
    messageBanner_.setForeground(black);
    enableOKButton();
  }

  private void setERRORStatusMessage(String message) {
    messageBanner_.setText(getMessage(message));
    Color red = new Color(thisShell.getDisplay(), 0xFF, 0, 0);
    messageBanner_.setForeground(red);
    disableOKButton();
  }

  private void disableOKButton() {
    if (getButton(0) != null)
      getButton(0).setEnabled(false);
  }

  private void enableOKButton() {
    if (getButton(0) != null)
      getButton(0).setEnabled(true);
  }

  protected void okPressed() {
    setJ2EEVersionFromJ2EEVersionCombo();
    //j2eeVersion = (j2eeVersionCombo.getEnabled()) ? j2eeVersionCombo.getText() : null;
    setReturnCode(OK);
    close();
  }

  private void setJ2EEVersionFromJ2EEVersionCombo()
  {
    if (j2eeVersionCombo.getEnabled())
    {
      String j2eeLabel = j2eeVersionCombo.getText();
      String j2eeVersionString = J2EEUtils.getJ2EEVersionFromLabel(j2eeLabel);
      if (j2eeVersionString != null && j2eeVersionString.length() > 0)
        j2eeVersion = j2eeVersionString;
      else
        j2eeVersion = null;
    }
    else
      j2eeVersion = null;    
  }
  /**
   * Called when an event occurs on the page. Handles the event and revalidates the page.
   * 
   * @param event
   *          The event that occured.
   */
  public void handleEvent(Event event) {
    if (!validateOn_)
      return;
    enableOKButton();
    if (viewSelectionByRuntimeButton_ == event.widget) {
      handleRuntimeViewSelectionEvent();
      return;
    }
    else if (viewSelectionByServerButton_ == event.widget) {
      handleServerViewSelectionEvent();
      return;
    }
    else if (viewSelectionByExploreButton_ == event.widget) {
      handleExploreViewSelectionEvent();
      return;
    }
    else if (j2eeVersionCombo == event.widget) {
      setJ2EEVersionFromJ2EEVersionCombo();
      //j2eeVersion = (j2eeVersionCombo.getEnabled()) ? j2eeVersionCombo.getText() : null;
      return;
    }
    else if (runtimesList_ == event.widget) {
      TreeItem[] runtimeSel = runtimesList_.getSelection();
      processRuntimeListSelection(runtimeSel[0].getText());
      validateServerRuntimeSelection();
      setJ2EEVersions();
    }
    else if (serverList_ == event.widget) {
      processServerListSelection();
      validateServerRuntimeSelection();
    }
  }

  private void handleRuntimeViewSelectionEvent() {
    GridLayout gl = new GridLayout();
    gl.numColumns = 1;
    gl.makeColumnsEqualWidth = true;
    GridData gd = new GridData(GridData.FILL_BOTH);
    primaryGroup_.setLayout(gl);
    primaryGroup_.setLayoutData(gd);
    primaryGroup_.layout();

    // TODO: Show all runtimes, and only servers supported by current type id
  }

  // 
  // Called by handleEvent() when the user selects the layout to view
  //
  public void handleServerViewSelectionEvent() {
    GridLayout gl = new GridLayout();
    gl.numColumns = 1;
    gl.makeColumnsEqualWidth = true;
    GridData gd = new GridData(GridData.FILL_BOTH);
    primaryGroup_.setLayout(gl);
    primaryGroup_.setLayoutData(gd);
    primaryGroup_.layout();
    serversGroup_.setLocation(5, 5);
    runtimesGroup_.setLocation(4, 100);
    serversGroup_.layout();
    runtimesGroup_.layout();

    // TODO: Show all servers, and only runtimes supported by the current type id
  }

  // 
  // Called by handleEvent() when the user selects the layout to view
  //
  private void handleExploreViewSelectionEvent() {
    GridLayout gl;
    gl = (GridLayout) primaryGroup_.getLayout();
    gl.numColumns = 2;
    gl.makeColumnsEqualWidth = true;
    GridData gd = new GridData(GridData.FILL_BOTH);
    primaryGroup_.setLayout(gl);
    primaryGroup_.setLayoutData(gd);
    primaryGroup_.layout();

    // TODO: Show all servers and runtimes from the type id

  }

  private void processRuntimeListSelection(String runtimeName) {
    if (selectionMode_ == MODE_SERVICE) {
      selectedRuntime_ = wssrtRegistry.getWebServiceRuntimeByLabel(runtimeName);
    }
    else {
      selectedRuntime_ = wsctRegistry.getWebServiceRuntimeByName(runtimeName);
    }
  }

  private void processServerListSelection() {
    String currentSelection;
    TreeItem[] serverSel = serverList_.getSelection();
    if (serverSel != null && serverSel.length > 0) {
      currentSelection = serverSel[0].getText();
      if (serverLabels_.containsKey(currentSelection) || existingServersTable_.containsKey(currentSelection)) {
        if (existingServersTable_.containsKey(currentSelection)) {
          selectedServer_ = (IServer) existingServersTable_.get(currentSelection);
          selectedServerLabel_ = currentSelection;
          selectedServerFactoryID_ = selectedServer_.getServerType().getId();
        }
        else if (serverLabels_.containsKey(currentSelection)) {
          TreeItem parentItem = serverSel[0].getParentItem();
          if (parentItem != null && !parentItem.getText().equalsIgnoreCase(getMessage("%LABEL_TREE_EXISTING_SERVERS"))) {
            selectedServerLabel_ = currentSelection;
            selectedServer_ = null;
            selectedServerFactoryID_ = (String) serverLabels_.get(currentSelection);
          }
        }

        // check if isExistingServer or new ServerType
        TreeItem parentItem = serverSel[0].getParentItem();
        if (parentItem != null && parentItem.getText().equalsIgnoreCase(getMessage("%LABEL_TREE_EXISTING_SERVERS"))) {
          setIsExistingServer(true);
        }
        else {
          setIsExistingServer(false);
        }
      }
      else {
        selectedServer_ = null;
        selectedServerLabel_ = null;
        selectedServerFactoryID_ = null;
        setIsExistingServer(false);
        return;
      }      
    }
  }

  private static String getMessage(String key) {
    return WebServiceConsumptionUIPlugin.getMessage(key);
  }

  private static String getMessage(String key, Object[] args) {
    return WebServiceConsumptionUIPlugin.getMessage(key, args);
  }

  private void setRuntimesGroup() {
    runtimesList_.removeAll();
    String[] runtimes = null;

    if (selectionMode_ == MODE_SERVICE) {
      runtimes = wssrtRegistry.getRuntimesByType(typeId_);
    }
    else {
      runtimes = wsctRegistry.getAllClientRuntimes();
    }

    TreeItem[] runtimeName = new TreeItem[runtimes.length];

    if (runtimes != null) {
      for (int i = 0; i < runtimes.length; i++) {
        String runtimeLabel = getRuntimeLabel(runtimes[i]);
        runtimeName[i] = new TreeItem(runtimesList_, SWT.NONE);
        runtimeName[i].setText(runtimeLabel);

        if (runtimes[i].equalsIgnoreCase(defaultRuntime_)) {
          runtimesList_.setSelection(new TreeItem[] { runtimeName[i]});
          selectedRuntime_ = getRuntime(runtimes[i]);
        }
      }
    }
  }

  private String getRuntimeLabel(String type) {
    return getRuntime(type).getLabel();
  }

  private IWebServiceRuntime getRuntime(String type) {
    if (selectionMode_ == MODE_SERVICE) {
      return wssrtRegistry.getRuntimeById(type);
    }
    else {
      return wsctRegistry.getRuntimeById(type);
    }
  }

  // Returns the server Factory Id given a server name
  private String getServerSelectionFactoryId(String selectedServerName) {
    if (serverLabels_.containsKey(selectedServerName) && !isExistingServer_)
      return (String) serverLabels_.get(selectedServerName);
    else {
      return ((IServer) existingServersTable_.get(selectedServerName)).getServerType().getId();
    }
  }

  /**
   * 
   * ServersList class
   * 
   * Class which easily creates the Tree structure and entries for existing servers and server types
   */
  public class ServersList {

    private TreeItem[] existingServersTree;
    private TreeItem[] serverTypesTree;
    boolean existingServer = false;

    public void setServerTreeItems(Tree serversList) {
      this.setExistingServersTree(serversList);
      this.setServerTypesTree(serversList);
    }

    public void setExistingServersTree(Tree serverList) {
      String[] serverIds = this.getAllExistingServers();
      existingServersTree = new TreeItem[1];
      TreeItem[] existingServerItems = new TreeItem[serverIds.length];
      existingServersTree[0] = new TreeItem(serverList, SWT.NONE);
      existingServersTree[0].setText(getMessage("%LABEL_TREE_EXISTING_SERVERS"));
      ImageDescriptor id = WebServiceConsumptionUIPlugin.getImageDescriptor(EXISTING_SERVERS_ICON);
      if (id != null)
        existingServersTree[0].setImage(id.createImage());
      for (int k = 0; k < serverIds.length; k++) {
        IServerType serverType = ServerCore.getServerType(((IServer) existingServersTable_.get(serverIds[k])).getServerType().getId());
        if (serverType != null) {
          existingServerItems[k] = new TreeItem(existingServersTree[0], SWT.NONE);
          existingServerItems[k].setText(serverIds[k]);
          if (serverIds[k].equalsIgnoreCase(defaultServer_) && getIsExistingServer()) {
            existingServersTree[0].setExpanded(true);
            serverList.setSelection(new TreeItem[] { existingServerItems[k]});
            existingServer = true;
            RuntimeServerSelectionDialog.this.setIsExistingServer(true);
            selectedServer_ = (IServer) existingServersTable_.get(defaultServer_);
            selectedServerLabel_ = serverIds[k];
            selectedServerFactoryID_ = selectedServer_.getServerType().getId();
          }
          existingServerItems[k].setImage(ServerUICore.getLabelProvider().getImage(serverType));
        }
      }
    }

    public void setServerTypesTree(Tree serverList) {

      TreeItem[] serverTypesTree = new TreeItem[1];
      serverTypesTree[0] = new TreeItem(serverList, SWT.NONE);
      serverTypesTree[0].setText(getMessage("%LABEL_TREE_SERVER_TYPES"));
      ImageDescriptor id = WebServiceConsumptionUIPlugin.getImageDescriptor(SERVER_TYPES_ICON);
      if (id != null)
        serverTypesTree[0].setImage(id.createImage());
      Hashtable categories_ = new Hashtable();
      Hashtable categoryTreeItem = new Hashtable();
      String[] serverIds = null;
      // rm String wst = wse.getWebServiceType();
      if (selectionMode_ == MODE_SERVICE) {
        serverIds = wssrtRegistry.getServerFactoryIdsByType(typeId_);
      }
      else {
        //serverIds = wsctRegistry.getServerFactoryIdsByClientType(typeId_);
        serverIds = wsctRegistry.getAllClientServerFactoryIds();

      }
      // rm serverId =
      // wssrtRegistry.getServerFactoryIdsByType(wse.getWebServiceType());
      if (serverIds == null) {
        serverIds = getAllServerTypes();
      }
      TreeItem[] parent = new TreeItem[serverIds.length];
      TreeItem[] item = new TreeItem[serverIds.length];
      if (serverIds != null) {
        for (int i = 0; i < serverIds.length; i++) {
          String server = ServerUtils.getInstance().getServerLabelForId(serverIds[i]);
          if (server != null) {
            RuntimeServerSelectionDialog.this.serverLabels_.put(server, serverIds[i]);
            IServerType serverType = ServerCore.getServerType(serverIds[i]);
            IRuntimeType runtimeType = serverType.getRuntimeType();
            if (!categories_.containsKey(serverType) && runtimeType != null) {
              categories_.put(serverType, runtimeType);
              if (categoryTreeItem.get(runtimeType) == null) {
                String categoryText = runtimeType.getName();
                Image categoryImage = ServerUICore.getLabelProvider().getImage(runtimeType);
                parent[i] = new TreeItem(serverTypesTree[0], SWT.NONE);
                parent[i].setText(categoryText);
                parent[i].setImage(categoryImage);
                categoryTreeItem.put(runtimeType, parent[i]);
              }
              else {
                parent[i] = (TreeItem) categoryTreeItem.get(runtimeType);
              }
              String factoryText = serverType.getName();
              Image factoryImage = ServerUICore.getLabelProvider().getImage(serverType);
              item[i] = new TreeItem(parent[i], SWT.NONE);
              item[i].setText(factoryText);
              item[i].setImage(factoryImage);
              item[i].setData(serverType);
              if (factoryText.equalsIgnoreCase(defaultServer_) && !existingServer) {
                serverList.setSelection(new TreeItem[] { item[i]});
                selectedServer_ = null;
                selectedServerLabel_ = factoryText;
                selectedServerFactoryID_ = (String) serverLabels_.get(selectedServerLabel_);
              }
            }
          }
        }
      }

    }

    /**
     * Get all servers in the workspace
     * 
     * @return String[] of existing server names
     */
    private String[] getAllExistingServers() {
      Vector serverIds = new Vector();
      {
        List servers = ServerCore.getResourceManager().getServers();
        if (servers != null && !servers.isEmpty()) {
          for (int i = 0; i < servers.size(); i++) {
            IServer server = (IServer) servers.get(i);
            serverIds.add(server.getName());
            existingServersTable_.put(server.getName(), server);
          }
        }
      }
      return (String[]) serverIds.toArray(new String[serverIds.size()]);
    }

    /**
     * Get all server types available for creation
     * 
     * @return String[] of server names
     */
    private String[] getAllServerTypes() {
      Vector serverTypes_ = new Vector();
      List defaultServersList = ServerCore.getServerTypes();
      for (int i = 0; i < defaultServersList.size(); i++) {
        IServerType serverType = (IServerType) defaultServersList.get(i);
        serverTypes_.add(serverType.getId());
      }
      return (String[]) serverTypes_.toArray(new String[serverTypes_.size()]);
    }
  }
}
