/*******************************************************************************
 * Copyright (c) 2005, 2008 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
 * yyyymmdd bug      Email and other contact information
 * -------- -------- -----------------------------------------------------------
 * 20060131 121071   rsinha@ca.ibm.com - Rupam Kuehner     
 * 20060221   119111 rsinha@ca.ibm.com - Rupam Kuehner
 * 20060227   124392 rsinha@ca.ibm.com - Rupam Kuehner
 * 20060324   116750 rsinha@ca.ibm.com - Rupam Kuehner
 * 20060427   126780 rsinha@ca.ibm.com - Rupam Kuehner
 * 20070119   159458 mahutch@ca.ibm.com - Mark Hutchinson
 * 20071107   203826 kathy@ca.ibm.com - Kathy Chan
 * 20080326   221364 kathy@ca.ibm.com - Kathy Chan
 * 20080402   225378 makandre@ca.ibm.com - Andrew Mak, Client wizard runtime/server defaulting is not respecting the preference
 * 20080530   234871 makandre@ca.ibm.com - Andrew Mak, Workbench has not been created yet error in cmdline Ant
 * 20080808   243623 mahutch@ca.ibm.com - Mark Hutchinson, Improve server defaulting performance
 *******************************************************************************/

package org.eclipse.jst.ws.internal.consumption.ui.wsrt;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;

import org.eclipse.core.resources.IProject;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jst.server.core.FacetUtil;
import org.eclipse.jst.ws.internal.consumption.common.FacetMatcher;
import org.eclipse.jst.ws.internal.consumption.common.FacetUtils;
import org.eclipse.jst.ws.internal.consumption.common.RequiredFacetVersion;
import org.eclipse.jst.ws.internal.consumption.ui.ConsumptionUIMessages;
import org.eclipse.jst.ws.internal.consumption.ui.plugin.WebServiceConsumptionUIPlugin;
import org.eclipse.jst.ws.internal.consumption.ui.preferences.PersistentServerRuntimeContext;
import org.eclipse.jst.ws.internal.consumption.ui.wizard.TypeSelectionFilter2;
import org.eclipse.jst.ws.internal.data.LabelsAndIds;
import org.eclipse.jst.ws.internal.data.TypeRuntimeServer;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.command.internal.env.core.selection.SelectionList;
import org.eclipse.wst.command.internal.env.core.selection.SelectionListChoices;
import org.eclipse.wst.common.project.facet.core.IFacetedProjectTemplate;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntime;
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;
import org.eclipse.wst.ws.internal.wsrt.IWebServiceRuntime;
import org.eclipse.wst.ws.internal.wsrt.IWebServiceRuntimeChecker;
import org.eclipse.wst.ws.internal.wsrt.WebServiceScenario;

/**
 * This class contains numerous utility methods that
 * process the information provided through extension points
 * which are read in WebServiceRuntimeExtensionRegistry2:
 * <ul>
 * <li> org.eclipse.jst.ws.consumption.ui.wsImpl </li>
 * <li> org.eclipse.jst.ws.consumption.ui.wsClientImpl </li>
 * <li> org.eclipse.jst.ws.consumption.ui.runtimes </li>
 * <li> org.eclipse.jst.ws.consumption.ui.serviceRuntimes </li>
 * <li> org.eclipse.jst.ws.consumption.ui.clientRuntimes </li>
 * </ul>
 * 
 * to provide answers to common questions regarding which servers,
 * projects, and project types a particular Web service runtime
 * supports.
 * <br/><br/>
 * Teminology used in the javadoc in this class:
 * <ul>
 * <li><b>Web service scenario</b>: One of WebServiceScenario.BOTTOM_UP or WebServiceScenario.TOP_DOWN.</li> 
 * <li><b>Web service implementation type</b>: extension to org.eclipse.jst.ws.consumption.ui.wsImpl.
 * The Java representation of this is org.eclipse.jst.ws.internal.consumption.ui.wsrt.WebServiceImpl.</li>
 * <li><b>Web service type</b>: Forward slash separated concatenation of the String representation
 * of a Web service scenario and a Web service implementation type id.
 * For example, "0/org.eclipse.jst.ws.wsImpl.java", represents the bottom up Java bean Web service type.</li>
 * <li><b>Web service client implementation type</b>: extension to org.eclipse.jst.ws.consumption.ui.wsClientImpl.
 * The Java representation of this is org.eclipse.jst.ws.internal.consumption.ui.wsrt.WebServiceClientImpl.</li>
 * <li><b>Web service runtime</b>: extension to org.eclipse.jst.ws.consumption.ui.runtimes. 
 * The Java representation of this is org.eclipse.jst.ws.internal.consumption.ui.wsrt.RuntimeDescriptor</li> 
 * <li><b>serviceRuntime</b>: extension to org.eclipse.jst.ws.consumption.ui.serviceRuntimes.
 * The Java representation of this is org.eclipse.jst.ws.internal.consumption.ui.wsrt.ServiceRuntimeDescriptor</li>
 * <li><b>clientRuntime</b>: extension to org.eclipse.jst.ws.consumption.ui.clientRuntimes.
 * The Java representation of this is org.eclipse.jst.ws.internal.consumption.ui.wsrt.ClientRuntimeDescriptor</li>
 * <li><b>server type</b>: This is a server tools artifact. You see a list of these when creating a new server
 * in the tool.</li>
 * <li><b>server runtime</b>: This is a server tools artifact. You see a list of these if you go to Preferences, 
 * Server > Installed Runtimes in the tool. The Java representation of this is org.eclipse.wst.server.core.IRuntime</li>
 * <li><b>facet runtime</b>: The facet equivalent of a server runtime. The Java representation of this is 
 * org.eclipse.wst.common.project.facet.core.runtime.IRuntime. org.eclipse.jst.server.core.FacetUtil
 * provides methods to translate from a server runtime to a facet runtime and vice-versa.</li>
 * </ul>
 */
public class WebServiceRuntimeExtensionUtils2
{
  private static WebServiceRuntimeExtensionRegistry2 registry = WebServiceRuntimeExtensionRegistry2.getInstance();
  
  /**
   * Returns the RuntimeDescriptor representing the Web service runtime
   * with an id attribute equal to the provided id
   * @param id
   * @return RuntimeDescriptor representing the Web service runtime
   * with an id attribute equal to the provided id. Returns null
   * if such a RuntimeDescriptor cannot be found.
   */  
  public static RuntimeDescriptor getRuntimeById(String id)
  {
    Object result = registry.runtimes_.get(id);
    if (result!=null)
    {
      return (RuntimeDescriptor)result;
    }
    return null;        
  }
  
  /**
   * Returns the union of all project types supported by all serviceRuntimes. Used by the
   * ProjectTopology preference page. 
   * @return String[] array of template ids. The array may have 0 elements.
   */
  public static String[] getAllServiceProjectTypes()
  {
    ArrayList finalTemplateIdList = new ArrayList();
    Iterator iter = registry.serviceRuntimes_.values().iterator();

    //Loop through all the serviceRuntimes
    while (iter.hasNext())   
    {
      ServiceRuntimeDescriptor desc = (ServiceRuntimeDescriptor)iter.next();
      
      //Get the templates for this serviceRuntime
      Set templates = FacetMatchCache.getInstance().getTemplatesForServiceRuntime(desc.getId());
      
      //Add the template ids to the list if they have not already been added
      Iterator itr = templates.iterator();
      while (itr.hasNext())
      {
        IFacetedProjectTemplate template = (IFacetedProjectTemplate)itr.next();
        if (!finalTemplateIdList.contains(template.getId()))
        {
          finalTemplateIdList.add(template.getId());
        }
      }            
    }
    
    return (String[])finalTemplateIdList.toArray(new String[]{});
  }
  
  /**
   * Returns the union of all project types supported by all clientRuntimes. Used by the
   * ProjectTopology preference page. 
   * @return String[] array of template ids. The array may have 0 elements.
   */
  public static String[] getAllClientProjectTypes()
  {
    ArrayList finalTemplateIdList = new ArrayList();
    Iterator iter = registry.clientRuntimes_.values().iterator();

    //Loop through all the clientRuntimes
    while (iter.hasNext())   
    {
      ClientRuntimeDescriptor desc = (ClientRuntimeDescriptor)iter.next();
      
      //Get the templates for this clientRuntime
      Set templates = FacetMatchCache.getInstance().getTemplatesForClientRuntime(desc.getId());
      
      //Add the template ids to the list if they have not already been added
      Iterator itr = templates.iterator();
      while (itr.hasNext())
      {
        IFacetedProjectTemplate template = (IFacetedProjectTemplate)itr.next();
        if (!finalTemplateIdList.contains(template.getId()))
        {
          finalTemplateIdList.add(template.getId());
        }
      }            
    }
    
    return (String[])finalTemplateIdList.toArray(new String[]{});
  }
  
  /**
   * Returns the label of a Web service runtime given its id
   * @param runtimeId id of a Web service runtime
   * @return String the label of the Web service runtime with an id equal to runtimeId.
   * Returns null if such a Web service runtime cannot be found.
   */
  public static String getRuntimeLabelById(String runtimeId) 
  {
    RuntimeDescriptor desc = getRuntimeById(runtimeId);
    if (desc == null)
      return null;
    
    return desc.getLabel();
  }    
  
  /**
   * Returns the RuntimeDescriptor corresponding to the Web service runtime with the provided label
   * @param label label of a Web service runtime
   * @return RuntimeDescriptor corresponding to the Web service runtime with the provided label
   * Returns null if such a Web service runtime cannot be found.
   */
  public static RuntimeDescriptor getRuntimeByLabel(String label)
  {
    Iterator iter = registry.runtimes_.values().iterator();
    while (iter.hasNext())
    {
      RuntimeDescriptor descriptor = (RuntimeDescriptor)iter.next();
      if (descriptor!=null) {
        if (label.equals(descriptor.getLabel()))
          return descriptor;
      }
    }
    return null;      
  }      

  /**
   * Returns the label of an server type given its id
   * @param serverFactoryId id of a server type
   * @return String label of the server type with an id equal to serverFactoryId.
   * Returns null if such a server type cannot be found.
   */
  public static String getServerLabelById(String serverFactoryId)
  {
    IServerType serverType = ServerCore.findServerType(serverFactoryId);
    if (serverType == null)
      return null;
    
    if (PlatformUI.isWorkbenchRunning()) {
      String serverLabel = ServerUICore.getLabelProvider().getText(serverType);   
      return serverLabel;
    }
    else
      return serverType.getName();
  }
  
  /**
   * Returns the label of an IServer given its id
   * @param instanceId id of an IServer
   * @return String label of the IServer with an id equal to instanceId.
   */  
  public static String getServerInstanceLabelFromInstanceId( String instanceId )
  {
    IServer server = ServerCore.findServer( instanceId );    
    return server.getName();
  }  

  /**
   * Returns the union of all server type ids corresponding to the facet runtimes
   * in the provided set.
   * @param facetRuntimes a set containing elements of type {@link IRuntime}.
   * @return an array of IServerType ids. The array may have 0 elements.
   */
  private static String[] getServerFactoryIdsByFacetRuntimes(Set facetRuntimes)
  {
    
    ArrayList supportedServerFactoryIds = new ArrayList();
    String[] serverTypeIds = getAllServerFactoryIdsWithRuntimes();
    Iterator itr = facetRuntimes.iterator();
    while(itr.hasNext())
    {
      IRuntime fRuntime = (IRuntime)itr.next();
      org.eclipse.wst.server.core.IRuntime sRuntime = FacetUtil.getRuntime(fRuntime);
      for (int i=0; i<serverTypeIds.length; i++)
      {
        IServerType serverType = ServerCore.findServerType(serverTypeIds[i]);
        IRuntimeType runtimeType = serverType.getRuntimeType();
        if (runtimeType != null)
        {
	        String runtimeTypeId = runtimeType.getId();
	        if (sRuntime != null && sRuntime.getRuntimeType() != null && runtimeTypeId.equals(sRuntime.getRuntimeType().getId()))
	        {
	          supportedServerFactoryIds.add(serverTypeIds[i]);          
	        }      
        }
      }
    }
    
    return (String[])supportedServerFactoryIds.toArray(new String[0]);
    
    //Temporarily return all factory ids with runtimes
    //return getAllServerFactoryIdsWithRuntimes();    
  }
  
  //Service-side utilities
  /**
   * Returns a WebServiceImpl given the id of a Web service implementation type.
   * @param id 
   * @return WebServiceImpl with the given id
   * Returns null if such a WebServiceImpl cannot be found.
   */
  public static WebServiceImpl getWebServiceImplById(String id)
  {
    Object result = registry.webServiceImpls_.get(id);
    if (result!=null)
    {
      return (WebServiceImpl)result;
    }
    return null;    
  }
  
  /**
   * Returns a {@link ServiceRuntimeDescriptor} given the id of a servicRuntime.
   * @param id of a serviceRuntime
   * @return ServiceRuntimeDescriptor with the given id
   * Returns null if such a ServiceRuntimeDescriptor cannot be found.
   */
  public static ServiceRuntimeDescriptor getServiceRuntimeDescriptorById(String id)
  {
    Object result = registry.serviceRuntimes_.get(id);
    if (result!=null)
    {
      return (ServiceRuntimeDescriptor)result;
    }
    return null;        
  }  
  
  /**
   * Returns the {@link IWebServiceRuntime} of the given serviceRuntime. Extenders provide the fully 
   * qualified name of a concrete IWebServiceRuntime in the class attribute of a serviceRuntimes extension.
   * @param serviceRuntimeId id of a serviceRuntime
   * @return IWebServiceRuntime
   */
  public static IWebServiceRuntime getServiceRuntime( String serviceRuntimeId )
  {
    ServiceRuntimeDescriptor descriptor = getServiceRuntimeDescriptorById(serviceRuntimeId);
    IWebServiceRuntime    webserviceRuntime     = null;
    if (descriptor != null)
    {
        webserviceRuntime = descriptor.getWebServiceRuntime();
    }
    
    return webserviceRuntime;
  }
  
  /**
   * Returns the id of a serviceRuntime that supports the provided Web service type, Web service runtime,
   * server type/server instance (if present), project or project type.
   * @param trs an instance of {@link TypeRuntimeServer} containing a Web service type id, Web service runtime id,
   * server type id and server instance id. The Web service type id and Web service runtime id must be non-null 
   * and non-empty. The server type id and server instance id may be null or empty.
   * @param projectName the name of an IProject thay may or mat not exist in the workspace. Must be non-null and 
   * non-empty.
   * @param templateId the id of an {@link IFacetedProjectTemplate}. Must be non-null and non-empty if
   * an IProject with the name projectName does not exist in the workspace. 
   * @return String id of a serviceRuntime that supports the provided Web service type, Web service runtime,
   * server type/server instance (if present), project or project type. Returns an empty String if no 
   * such serviceRuntime could be found.
   */
  public static String getServiceRuntimeId(TypeRuntimeServer trs, String projectName, String templateId)
  {
    boolean serverSelected = (trs.getServerId() != null) && (trs.getServerId().length() > 0); 
    //Find the first serviceRuntime that supports the implementation type, runtime, server, and project
    String[] descs = getServiceRuntimesByServiceType(trs.getTypeId(), trs.getServerId());
    for (int i=0; i<descs.length; i++)
    {
      ServiceRuntimeDescriptor desc = getServiceRuntimeDescriptorById(descs[i]);      
      if (desc.getRuntime().getId().equals(trs.getRuntimeId()))
      {
        if (serverSelected)
        {
          boolean supportsServer = doesServiceRuntimeSupportServer(desc.getId(), trs.getServerId());
          if (!supportsServer)
          {
            continue;
          }
        }
        
        IProject project = ProjectUtilities.getProject(projectName);
        if (project.exists())
        {
          if (doesServiceRuntimeSupportProject(desc.getId(), projectName))
          {
            return desc.getId();
          }
        }
        else
        {
          //Check if template is supported
          if (doesServiceRuntimeSupportTemplate(desc.getId(), templateId))
          {
            return desc.getId();
          }
        }
      }
    }
    
    return "";
    
  }  
  
  /**
   * Returns the Web service scenario from the Web service type.
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * @return int scenario (e.g. WebServiceScenario.BOTTOM_UP or WebServiceScenario.TOP_DOWN)
   */        
  public static int getScenarioFromTypeId(String typeId)
  {
    return Integer.parseInt(typeId.substring(0,typeId.indexOf("/")));
  }
  
  /**
   * Returns the Web service implemenation type id fron the Web service type id.
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * @return String the WebServiceImpl id.
   */        
  public static String getWebServiceImplIdFromTypeId(String typeId)
  {
    return typeId.substring(typeId.indexOf("/")+1);
  }    
  
  /**
   * Returns the ids of all Web service runtimes that support the given
   * Web service type.
   * 
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * 
   * @return String[] array containing the ids of all Web service runtimes that
   * support the given Web service type. The array may have 0 elements.
   */
  public static String[] getRuntimesByServiceType(String typeId) 
  {
    int scenario = getScenarioFromTypeId(typeId);
    String implId = getWebServiceImplIdFromTypeId(typeId);    
    ArrayList ids = new ArrayList();
    Iterator iter = registry.serviceRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ServiceRuntimeDescriptor desc = (ServiceRuntimeDescriptor)iter.next();
      //Check if this serviceRuntime supports the implementation type
      if (desc.getServiceImplementationType().getId().equals(implId))
      {
        switch (scenario)
        {
          case WebServiceScenario.BOTTOMUP:
            if (desc.getBottomUp())
            {
              String runtimeId = desc.getRuntime().getId(); 
              if (!ids.contains(runtimeId))
              {
                ids.add(runtimeId);
              }
            }
            break;
          case WebServiceScenario.TOPDOWN:
            if (desc.getTopDown())
            {
              String runtimeId = desc.getRuntime().getId(); 
              if (!ids.contains(runtimeId))
              {
                ids.add(runtimeId);
              }
            }
            break;
          default:          
        }
      }
    }
    
    return (String[])ids.toArray(new String[]{});
  }
  
  /**
   * Returns the ids of all serviceRuntimes that support the given
   * Web service type.
   * 
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * 
   * @returns String[] array containing the ids of all serviceRuntimes that
   * support the given Web service type. The array may have 0 elements.
   */
  public static String[] getServiceRuntimesByServiceType(String typeId) 
  {
    int scenario = getScenarioFromTypeId(typeId);
    String implId = getWebServiceImplIdFromTypeId(typeId);    
    ArrayList ids = new ArrayList();
    Iterator iter = registry.serviceRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ServiceRuntimeDescriptor desc = (ServiceRuntimeDescriptor)iter.next();
      //Check if this serviceRuntime supports the implementation type
      if (desc.getServiceImplementationType().getId().equals(implId))
      {
        switch (scenario)
        {
          case WebServiceScenario.BOTTOMUP:
            if (desc.getBottomUp())
            {
              String serviceRuntimeId = desc.getId(); 
              ids.add(serviceRuntimeId);
            }
            break;
          case WebServiceScenario.TOPDOWN:
            if (desc.getTopDown())
            {
              String serviceRuntimeId = desc.getId(); 
              ids.add(serviceRuntimeId);
            }
            break;
          default:          
        }
      }
    }
    
    return (String[])ids.toArray(new String[]{});
  }  
  
  /**
   * Returns the ids of all serviceRuntimes that support the given
   * Web service type, with preferred server 
   * 
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * 
   * @returns String[] array containing the ids of all serviceRuntimes that
   * support the given Web service type. The array may have 0 elements.
   */
  public static String[] getServiceRuntimesByServiceType(String typeId, String preferredServerFactoryId) 
  {
	//    PersistentServerRuntimeContext context = WebServiceConsumptionUIPlugin
	//			.getInstance().getServerRuntimeContext();
	//	String preferredRuntimeId = context.getRuntimeId();
	//	String preferredServerFactoryId = context.getServerFactoryId();

    int scenario = getScenarioFromTypeId(typeId);
    String implId = getWebServiceImplIdFromTypeId(typeId);    
    ArrayList ids = new ArrayList();
    ArrayList idsPreferredByServer = new ArrayList();
    Iterator iter = registry.serviceRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ServiceRuntimeDescriptor desc = (ServiceRuntimeDescriptor)iter.next();
      //Check if this serviceRuntime supports the implementation type
      if (desc.getServiceImplementationType().getId().equals(implId))
      {
        switch (scenario)
        {
          case WebServiceScenario.BOTTOMUP:
            if (desc.getBottomUp())
            {
              String serviceRuntimeId = desc.getId(); 
              if (desc.getRuntimePreferredServerType() != null && desc.getRuntimePreferredServerType().equals(preferredServerFactoryId))
            	  idsPreferredByServer.add(serviceRuntimeId);
              else 
            	  ids.add(serviceRuntimeId);
            }
            break;
          case WebServiceScenario.TOPDOWN:
            if (desc.getTopDown())
            {
              String serviceRuntimeId = desc.getId(); 
              if (desc.getRuntimePreferredServerType() != null && desc.getRuntimePreferredServerType().equals(preferredServerFactoryId))
            	  idsPreferredByServer.add(serviceRuntimeId);
              else 
            	  ids.add(serviceRuntimeId);
            }
            break;
          default:          
        }
      }
    }
    // append preferredRuntime after preferredRuntimeIdsListPreferredByServer
    String[] preferredRuntimeIds = new String[idsPreferredByServer.size()+ids.size()];
    Iterator itr1 = idsPreferredByServer.iterator();
    int preferredRTCounter = 0;
    while (itr1.hasNext()) {
		String runtimeId = (String) itr1.next();
		preferredRuntimeIds[preferredRTCounter++] = runtimeId;
	}
    
    Iterator itr2 = ids.iterator();  
     
    while (itr2.hasNext()) {
		String runtimeId = (String) itr2.next();
		preferredRuntimeIds[preferredRTCounter++] = runtimeId;		
	}

    return preferredRuntimeIds;
  }  
  
  /**
   * Returns whether or not the given Web service runtime supports the given 
   * Web service type.
   * 
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * 
   * @param runtimeId id of a Web service runtime
   * 
   * @return boolean <code>true</code> if the given Web service runtime supports the given 
   * Web service type. <code>false</code> otherwise.
   */ 
  public static boolean isRuntimeSupportedForServiceType(String typeId, String runtimeId)
  {
    String[] serviceRuntimeIds = getServiceRuntimesByServiceType(typeId);
    if (serviceRuntimeIds!=null)
    {
      for (int i=0; i < serviceRuntimeIds.length; i++)
      {
        ServiceRuntimeDescriptor desc = getServiceRuntimeDescriptorById(serviceRuntimeIds[i]);
        if (desc.getRuntime().getId().equals(runtimeId))
        {
          return true;
        }
      }
    }
    
    return false;
  }  
  
  /**
   * Returns the ids of all server types that support the given
   * Web service type.
   * 
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * 
   * @returns String[] array containing the ids of all server types that
   * support the given Web service type. The array may have 0 elements. 
   */
  public static String[] getServerFactoryIdsByServiceType(String typeId)
  {
    ArrayList serverFactoryIds = new ArrayList();
    String[] srts = getServiceRuntimesByServiceType(typeId);
    if (srts != null)
    {
      for (int i = 0; i < srts.length; i++)
      {
        //Get the runtimes that work for the facets required for this serviceRuntime        
        String[] fIds = getServerFactoryIdsByServiceRuntime(srts[i]);
        for (int j=0; j<fIds.length; j++)
        {
          if (!serverFactoryIds.contains(fIds[j]))
          {
            serverFactoryIds.add(fIds[j]);            
          }
        }
      }
    }
    
    return (String[])serverFactoryIds.toArray(new String[]{});
    
    //Temporarily return all server type ids.
    //return getAllServerFactoryIdsWithRuntimes();
  }
  
  /**
   * Returns whether or not the given server type supports the given 
   * Web service type.
   * 
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * 
   * @param serverFactoryId id of a server type
   * 
   * @return boolean <code>true</code> if the given server type supports the given 
   * Web service type. <code>false</code> otherwise.
   */
  public static boolean isServerSupportedForChosenServiceType(String typeId, String serverFactoryId)
  {
    String[] fIds = getServerFactoryIdsByServiceType(typeId);
    if (fIds == null)
    {
      return false;
    }

    for (int i=0;i<fIds.length;i++)
    {
      if (serverFactoryId.equals(fIds[i]))
      {
        return true;
      }      
    }
    
    return false;
  }
  
  /**
   * Returns the ids of all server types that support the given
   * serviceRuntime.
   * 
   * @param serviceRuntimeId id of a serviceRuntime
   * 
   * @returns String[] array containing the ids of all server types that
   * support the given serviceRuntime. The array may have 0 elements. 
   */   
  public static String[] getServerFactoryIdsByServiceRuntime(String serviceRuntimeId)
  {       
    ServiceRuntimeDescriptor desc = getServiceRuntimeDescriptorById(serviceRuntimeId);
    Set facetRuntimes = getRuntimes(desc.getRequiredFacetVersions());
            
    //Temporarily return all server types
    //return getAllServerFactoryIdsWithRuntimes();
    return getServerFactoryIdsByFacetRuntimes(facetRuntimes);
  } 
  

  
  /**
   * Returns whether or not the given server type supports the given 
   * serviceRuntime.
   * 
   * @param serviceRuntimeId id of a serviceRuntime
   * @param serverFactoryId id of a server type
   * 
   * @return boolean <code>true</code> if the given server type supports the given 
   * serviceRuntime. <code>false</code> otherwise.
   */  
  public static boolean doesServiceRuntimeSupportServer(String serviceRuntimeId, String serverFactoryId)
  {
    String[] serverIds = getServerFactoryIdsByServiceRuntime(serviceRuntimeId);
    for (int i=0; i<serverIds.length; i++)
    {
      if (serverIds[i].equals(serverFactoryId))
      {
        return true;
      }
    }
    
    return false;
  }
    
  /**
   * Returns the labels and ids of all Web service types. Used to populate the Web service type combo box on
   * page 1 of the Web service wizard.
   * @return {@link LabelsAndIds}
   */
  public static LabelsAndIds getServiceTypeLabels()
  {   
    LabelsAndIds labelIds = new LabelsAndIds();
    Iterator     iterator = registry.webServiceTypesList_.iterator();
    int          size     = registry.webServiceTypesList_.size();
    String[]     labels   = new String[size];
    String[]     ids      = new String[size];
    int          index    = 0;
    
    labelIds.setLabels_( labels );
    labelIds.setIds_( ids );
    
    while( iterator.hasNext() ) 
    {
      String wst = (String)iterator.next();
      int scenario = getScenarioFromTypeId(wst);
      String implId = getWebServiceImplIdFromTypeId(wst);
      WebServiceImpl wsimpl = getWebServiceImplById(implId);
      String impllabel = wsimpl.getLabel();
      ids[index]    = wst;
      String scenLabel = "";
      switch(scenario)
      {
      case WebServiceScenario.BOTTOMUP:
        scenLabel = NLS.bind(ConsumptionUIMessages.BOTTOMUP_LABEL, new String[0]);
        break;
      case WebServiceScenario.TOPDOWN:
        scenLabel = NLS.bind(ConsumptionUIMessages.TOPDOWN_LABEL, new String[0]);
        break; 
      default:
      }
      labels[index] = NLS.bind(ConsumptionUIMessages.COMBINED_TYPE_AND_RUNTIME_LABEL, new String[]{ scenLabel, impllabel });
      index++;
    }    
    
    return labelIds;
  }
  
  /**
   * Returns the id of a Web service runtime that supports the given Web service type.
   *  
   * @param typeId will be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * 
   * @return String id of a Web service runtime that supports the given Web service type. 
   * Returns null if such a Web service runtime cannot be found.
   */
  public static String getDefaultRuntimeValueFor(String typeId)
  {
    String[] srIds = getServiceRuntimesByServiceType(typeId);
    if (srIds == null)
    {
      return null;
    }
    
    PersistentServerRuntimeContext context = WebServiceConsumptionUIPlugin.getInstance().getServerRuntimeContext();
    String preferredRuntimeId = context.getRuntimeId();
    
    String runtimeId;
    
    for (int i = 0; i < srIds.length; i++) {
		runtimeId = getServiceRuntimeDescriptorById(srIds[i]).getRuntime().getId();
		if (runtimeId.equals(preferredRuntimeId)) {
			return runtimeId;
		}
	}
    
    // The preferred runtime does not support typeId.  Just return the first service runtime that does support typeId.
    ServiceRuntimeDescriptor desc = getServiceRuntimeDescriptorById(srIds[0]);
    return desc.getRuntime().getId();
  }      

  /**
   * Returns the id of a Web service client runtime that supports the given Web service client type.
   *  
   * @param typeId The client type ID. 
   * 
   * @return String id of a Web service client runtime that supports the given Web service client type. 
   * Returns null if such a Web service client runtime cannot be found.
   */
  public static String getDefaultClientRuntimeValueFor(String typeId)
  {
    String[] crIds = getClientRuntimesByType(typeId);     	
    if (crIds == null)
    {
      return null;
    }
    
    PersistentServerRuntimeContext context = WebServiceConsumptionUIPlugin.getInstance().getServerRuntimeContext();
    String preferredRuntimeId = context.getRuntimeId();
    
    String runtimeId;
    
    for (int i = 0; i < crIds.length; i++) {
		runtimeId = getClientRuntimeDescriptorById(crIds[i]).getRuntime().getId();
		if (runtimeId.equals(preferredRuntimeId)) {
			return runtimeId;
		}
	}
    
    // The preferred runtime does not support typeId.  Just return the first service runtime that does support typeId.
    ClientRuntimeDescriptor desc = getClientRuntimeDescriptorById(crIds[0]);
    return desc.getRuntime().getId();
  }
  
  /**
   * Returns the id of a server type that supports the given Web service type.
   * Returns the server type ID from the preference if it supports the typeId.
   *  
   * @param typeId will be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * 
   * @return String id of a id of a server type that supports the given Web service type. 
   * Returns null if such a server type cannot be found.
   */    
  public static String getDefaultServerValueFor(String typeId)
  {
    String[] fIds = getServerFactoryIdsByServiceType(typeId);
    if (fIds==null || fIds.length==0)
      return null;
    
    PersistentServerRuntimeContext context = WebServiceConsumptionUIPlugin.getInstance().getServerRuntimeContext();
    String preferredServerFactoryId = context.getServerFactoryId();
    for (int i = 0; i < fIds.length; i++) {
		String serverTypeId = fIds[i];
		if (serverTypeId.equals(preferredServerFactoryId)) {
			return serverTypeId;
		}
	}
    return fIds[0];
  }    
 
  /**
   * Returns the id of a server type that supports the given Web service client type.
   * Returns the server type ID from the preference if it supports the typeId.
   *   
   * @param typeId The client type ID.
   * 
   * @return String id of a id of a server type that supports the given Web service client type. 
   * Returns null if such a server type cannot be found.
   */    
	public static String getDefaultClientServerValueFor(String typeId)	{		
		PersistentServerRuntimeContext context = WebServiceConsumptionUIPlugin.getInstance().getServerRuntimeContext();
		String preferredServerFactoryId = context.getServerFactoryId();
		String first = null;//the first server found	  
	    String[] crts = getClientRuntimesByType(typeId);

	    if (crts != null)
	    {
	      for (int i = 0; i < crts.length; i++)
	      {
	        //Get the runtimes that work for the facets required for this serviceRuntime        
	    	String[] fIds = getServerFactoryIdsByClientRuntime(crts[i]);
	        for (int j=0; j<fIds.length; j++)
	        {
	          if (first == null) {
	        	  first = fIds[j];
	          }
	          if (preferredServerFactoryId.equals(fIds[j])) {
	        	  return fIds[j];//found the preferred one, stop searching and return it
	          }
	        }
	      }    
	    }
	    return first;
  }    
  

  /**
   * Returns whether or not the given combination of server type, Web service runtime, and Web service type is
   * supported. Used for validation.
   * 
   * @param serverFactoryId id of a server type
   * @param runtimeId id of a Web service runtime
   * @param typeId will be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * 
   * @return boolean <code>true</code> if the given combination of server type, Web service runtime, and Web service type is
   * supported. <code>false</code> otherwise.
   */
  public static boolean isServerRuntimeTypeSupported(String serverFactoryId, String runtimeId, String typeId)  
  {
    //Ensure there is at least one serviceRuntime that supports the given type
    String[] serviceRuntimes = getServiceRuntimesByServiceType(typeId);
    if (serviceRuntimes!=null && serviceRuntimes.length>0)
    {
      //Ensure that at least one of these server runtimes supports the given server
      for (int i=0; i<serviceRuntimes.length; i++)
      {
        ServiceRuntimeDescriptor desc = getServiceRuntimeDescriptorById(serviceRuntimes[i]);
        if (desc.getRuntime().getId().equals(runtimeId))
        {
          //Matches the type and the runtime. Check if it matches the server
          Set runtimes = getRuntimes(desc.getRequiredFacetVersions());
          String[] fIds = getServerFactoryIdsByFacetRuntimes(runtimes);
          for (int j=0; j<fIds.length; j++)
          {
            if (fIds[j].equals(serverFactoryId))
            {
              return true;
            }
          }          
        }        
      }
    }
    
    //didn't find a match. return false.
    return false;
  }  
  
  /**
   * Returns an array of Web service type ids that are suitable for the provided selection.
   * Used to default the Web service type combo box on page 1 of the Web service wizard
   * based on the user's initial selection.
   * @param selection
   * @return String[] an array of Web service type ids that are suitable for the provided selection.
   * Returns null if the selection is empty or no suitable Web service types are found.
   */
  public static String[] getWebServiceTypeBySelection(IStructuredSelection selection)
  {
    TypeSelectionFilter2 tsf = new TypeSelectionFilter2();
    String[] wst = tsf.getWebServiceTypeByInitialSelection(selection, registry.webServiceTypesList_);
    return wst == null ? null : wst;
  }    
  
  /**
   * Returns whether or not the given server type supports the given Web service runtime
   * 
   * @param runtimeId : id of a Web service runtime
   * @param factoryId : id of a server type
   * @return boolean <code>true</code> if the given server type supports the given 
   * Web service runtime for the service side. <code>false</code> otherwise.
   */
  public static boolean doesRuntimeSupportServerForServiceSide(String runtimeId, String factoryId)
  {
    //Get all the ServiceRuntimeDescriptors that point to this runtimeId
    Iterator iter = registry.serviceRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ServiceRuntimeDescriptor desc = (ServiceRuntimeDescriptor)iter.next();
      //check if this serviceRuntime points to runtimeId
      String thisRuntimeId = desc.getRuntime().getId();
      if (thisRuntimeId.equals(runtimeId))
      {
        Set facetRuntimes = getRuntimes(desc.getRequiredFacetVersions());
        String[] fIds = getServerFactoryIdsByFacetRuntimes(facetRuntimes);
        for (int j=0; j<fIds.length; j++)
        {
          if (fIds[j].equals(factoryId))
          {
            return true;
          }
        }              
      }            
    }
    
    //No serviceRuntime matched. Return false.
    return false;
  }
  
  /**
   * Returns the id of a server type that supports the given Web service runtime
   * on the service side.
   * 
   * @param runtimeId id of a Web service runtime
   * @return String the id of a server type that supports the given Web service runtime.
   * Returns null if such a server type cannot be found. 
   */
  public static String getFirstSupportedServerForServiceSide(String runtimeId)
  {
    //Get all the ServiceRuntimeDescriptors that point to this runtimeId
    Iterator iter = registry.serviceRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ServiceRuntimeDescriptor desc = (ServiceRuntimeDescriptor)iter.next();
      //check if this serviceRuntime points to runtimeId
      String thisRuntimeId = desc.getRuntime().getId();
      if (thisRuntimeId.equals(runtimeId))
      {
        Set facetRuntimes = getRuntimes(desc.getRequiredFacetVersions());
        String[] factoryIds = getServerFactoryIdsByFacetRuntimes(facetRuntimes);
        if (factoryIds!=null && factoryIds.length >0)
        {
          return factoryIds[0];
        }
      }            
    }
    
    //didn't get a single suitable server type id, return null.
    return null;
  }  
  
  /**
   * Returns the names of all projects in the workspace which support the given Web service type
   * and Web service runtime.
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * @param runtimeId id of a Web service runtime
   * @return String[] array of project names. The array may have 0 elements.
   */
  public static String[] getProjectsForServiceTypeAndRuntime(String typeId, String runtimeId)
  {
    IProject[] projects = FacetUtils.getAllProjects();
    ArrayList validProjects = new ArrayList();
    
    for (int i=0; i<projects.length;i++)
    {
      if (doesServiceTypeAndRuntimeSupportProject(typeId, runtimeId, projects[i].getName()))
      {
        validProjects.add(projects[i].getName());        
      }      
    }
    
    return (String[])validProjects.toArray(new String[0]);
    
  }
  
  /**
   * Returns whether or not the given project supports the given Web service type and Web service runtime.
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * @param runtimeId id of a Web service runtime
   * @param projectName name of an IProject in the workspace
   * @return boolean <code>true</code> if the project supports the given Web service type and 
   * Web service runtime. Returns <code>false</code>
   * <ul> 
   * <li>if the project does not support the given Web service type and Web service runtime or</li>
   * <li>if the project does not exist or</li>
   * <li>if projectName is null or empty</li>
   * </ul>
   */
  public static boolean doesServiceTypeAndRuntimeSupportProject(String typeId, String runtimeId, String projectName)
  {
    String[] descs = getServiceRuntimesByServiceType(typeId);
    for (int j = 0; j < descs.length; j++)
    {
      ServiceRuntimeDescriptor desc = getServiceRuntimeDescriptorById(descs[j]);
      if (desc.getRuntime().getId().equals(runtimeId))
      {
        if (doesServiceRuntimeSupportProject(descs[j], projectName))
        {
          return true;
        }
      }
    }
    
    return false;    
    
  }  
  
  /**
   * Returns whether or not the given project supports the given serviceRuntime.
   * @param serviceRuntimeId id of a serviceRuntime
   * @param projectName name of an IProject in the workspace
   * @return boolean <code>true</code> if the project supports the given
   * serviceRuntime. Returns <code>false</code>
   * <ul> 
   * <li>if the project does not support the given serviceRuntime or</li>
   * <li>if the project does not exist or</li>
   * <li>if projectName is null or empty</li>
   * </ul>
   */  
  public static boolean doesServiceRuntimeSupportProject(String serviceRuntimeId, String projectName)
  {
    FacetMatcher fm = FacetMatchCache.getInstance().getMatchForProject(false, serviceRuntimeId, projectName);
    if (fm != null)
    {
      return fm.isMatch();
    }
    else
    {
      return false;
    }    
  }  
  

  /**
   * Returns an array of {@link IFacetedProjectTemplate} ids that support the given Web service type
   * and Web service runtime.
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * @param runtimeId id of a Web service runtime
   * @return String[] array of {@link IFacetedProjectTemplate} ids that support the given Web service type
   * and Web service runtime. The array may have 0 elements. Returns null if no serviceRuntimes supporting
   * the given Web service type could be found.
   */
  public static String[] getServiceProjectTemplates(String typeId, String runtimeId)
  {
    String[] srIds = getServiceRuntimesByServiceType(typeId);
    if (srIds == null)
    {
      return null;
    }

    ArrayList templateIdList = new ArrayList();
    for (int i = 0; i < srIds.length; i++)
    {
      ServiceRuntimeDescriptor desc = getServiceRuntimeDescriptorById(srIds[i]);
      String thisRuntimeId = desc.getRuntime().getId();
      if (thisRuntimeId.equals(runtimeId))
      {
        //Get the templates for this serviceRuntime
        Set templates = FacetMatchCache.getInstance().getTemplatesForServiceRuntime(desc.getId());
        
        //Add the template ids to the list if they have not already been added
        Iterator itr = templates.iterator();
        while (itr.hasNext())
        {
          IFacetedProjectTemplate template = (IFacetedProjectTemplate)itr.next();
          if (!templateIdList.contains(template.getId()))
          {
            templateIdList.add(template.getId());
          }
        }
      }
      
    }  
    
    return (String[])templateIdList.toArray(new String[]{});    
  }

  /**
   * Returns whether or not the given {@link IFacetedProjectTemplate} supports the given Web service type
   * and Web service runtime.
   * @param typeId must be a String of the format "0/implId"
   * where the digit before the "/" represents the scenario
   * (e.g. WebServiceScenario.BOTTOM_UP) and the implId is the Web service implementation type id.
   * @param runtimeId id of a Web service runtime
   * @param templateId id of a {@link IFacetedProjectTemplate}
   * @return boolean <code>true</code> if the given {@link IFacetedProjectTemplate} supports the given 
   * Web service type and Web service runtime. Returns <code>false</code> otherwise. 
   */
  public static boolean doesServiceTypeAndRuntimeSupportTemplate(String typeId, String runtimeId, String templateId)
  {
    String[] srIds = getServiceRuntimesByServiceType(typeId);
    if (srIds == null)
    {
      return false;
    }

    for (int i = 0; i < srIds.length; i++)
    {
      ServiceRuntimeDescriptor desc = getServiceRuntimeDescriptorById(srIds[i]);
      String thisRuntimeId = desc.getRuntime().getId();
      if (thisRuntimeId.equals(runtimeId))
      {
        //Get the templates for this serviceRuntime
        Set templates = FacetMatchCache.getInstance().getTemplatesForServiceRuntime(srIds[i]);
        
        //Check if any of the template ids match the given one.
        Iterator itr = templates.iterator();
        while (itr.hasNext())
        {
          IFacetedProjectTemplate template = (IFacetedProjectTemplate)itr.next();
          if (template.getId().equals(templateId))
          {
            return true;
          }

        }
      }
      
    }  
    
    return false;    
  }
  
  /**
   * Returns whether or not the given {@link IFacetedProjectTemplate} supports the given serviceRuntime.
   * @param serviceRuntimeId id of a serviceRuntime
   * @param templateId id of a {@link IFacetedProjectTemplate}
   * @return boolean <code>true</code> if the given {@link IFacetedProjectTemplate} supports the given 
   * serviceRuntime. Returns <code>false</code> otherwise.
   */
  public static boolean doesServiceRuntimeSupportTemplate(String serviceRuntimeId, String templateId)
  {
    //Get the templates for this serviceRuntime
    Set templates = FacetMatchCache.getInstance().getTemplatesForServiceRuntime(serviceRuntimeId);
    IFacetedProjectTemplate checkingTemplate = ProjectFacetsManager.getTemplate(templateId);
    return templates.contains(checkingTemplate);
  }  
  
  //Client-side utilities
  /**
   * Returns a WebServiceClientImpl given the id of a Web service client implementation type.
   * @param id 
   * @return {@link WebServiceClientImpl} with the given id
   * Returns null if such a WebServiceClientImpl cannot be found.
   */  
  public static WebServiceClientImpl getWebServiceClientImplById(String id)
  {
    Object result = registry.webServiceClientImpls_.get(id);
    if (result!=null)
    {
      return (WebServiceClientImpl)result;
    }
    return null;    
  }
  
  /**
   * Returns a {@link ClientRuntimeDescriptor} given the id of a clientRuntime.
   * @param id of a clientRuntime
   * @return ClientRuntimeDescriptor with the given id
   * Returns null if such a ClientRuntimeDescriptor cannot be found.
   */  
  public static ClientRuntimeDescriptor getClientRuntimeDescriptorById(String id)
  {
    Object result = registry.clientRuntimes_.get(id);
    if (result!=null)
    {
      return (ClientRuntimeDescriptor)result;
    }
    return null;        
  }    
  
  /**
   * Returns the {@link IWebServiceRuntime} of the given clientRuntime. Extenders provide the fully 
   * qualified name of a concrete IWebServiceRuntime in the class attribute of a clientRuntimes extension.
   * @param clientRuntimeId id of a clientRuntime
   * @return IWebServiceRuntime
   */  
  public static IWebServiceRuntime getClientRuntime( String clientRuntimeId )
  {
    ClientRuntimeDescriptor descriptor = getClientRuntimeDescriptorById(clientRuntimeId);
    IWebServiceRuntime    webserviceRuntime     = null;
    if (descriptor != null)
    {
        webserviceRuntime = descriptor.getWebServiceRuntime();
    }
    
    return webserviceRuntime;
  }
  
  /**
   * Returns the id of a clientRuntime that supports the provided Web service client implementation type, Web service runtime,
   * server type/server instance (if present), project or project type.
   * @param trs an instance of {@link TypeRuntimeServer} containing a Web service client implementation type id, Web service runtime id,
   * server type id and server instance id. The Web service client implementation type id and Web service runtime id must be non-null 
   * and non-empty. The server type id and server instance id may be null or empty.
   * @param projectName the name of an IProject thay may or mat not exist in the workspace. Must be non-null and 
   * non-empty.
   * @param templateId the id of an {@link IFacetedProjectTemplate}. Must be non-null and non-empty if
   * an IProject with the name projectName does not exist in the workspace. 
   * @return String id of a clientRuntime that supports the provided Web service client implementation type, Web service runtime,
   * server type/server instance (if present), project or project type. Returns an empty String if no 
   * such clientRuntime could be found.
   */  
  public static String getClientRuntimeId(TypeRuntimeServer trs, String projectName, String templateId)
  {
    boolean serverSelected = (trs.getServerId()!=null) && (trs.getServerId().length()>0);
    //Find the first clientRuntime that supports the implementation type, runtime, server, and project
    String[] descs = getClientRuntimesByType(trs.getTypeId(), trs.getServerId());
    for (int i=0; i<descs.length; i++)
    {
      ClientRuntimeDescriptor desc = getClientRuntimeDescriptorById(descs[i]);      
      if (desc.getRuntime().getId().equals(trs.getRuntimeId()))
      {
        if (serverSelected)
        {
          boolean supportsServer = doesClientRuntimeSupportServer(desc.getId(), trs.getServerId());
          if (!supportsServer)
          {
            continue;
          }
        }
        
        IProject project = ProjectUtilities.getProject(projectName);
        if (project.exists())
        {
          if (doesClientRuntimeSupportProject(desc.getId(), projectName))
          {
            return desc.getId();
          }
        }
        else
        {
          //Check if template is supported
          if (doesClientRuntimeSupportTemplate(desc.getId(), templateId))
          {
            return desc.getId();
          }
        }
      }
    }
    
    return "";
    
  }
  
  /**
   * Returns all Web service runtime ids for the client side.
   * @return String[] array of Web service runtime ids for the client side.
   * The array may have 0 elements. 
   */
  public static String[] getAllRuntimesForClientSide() 
  {
    ArrayList runtimeIds = new ArrayList();
    Iterator iter = registry.clientRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ClientRuntimeDescriptor desc = (ClientRuntimeDescriptor)iter.next();
      String thisRuntimeId = desc.getRuntime().getId(); 
      if (!runtimeIds.contains(thisRuntimeId))
      runtimeIds.add(thisRuntimeId);
    }      
    return (String[])runtimeIds.toArray(new String[]{});
  }
  
  /**
   * Returns the ids of all clientRuntimes that support the given
   * Web service client implementation type.
   * @param clientImplId id of a Web service client implementation type
   * @returns String[] array containing the ids of all clientRuntimes that
   * support the given Web service client implementation type. The array may have 0 elements.
   */
  public static String[] getClientRuntimesByType(String clientImplId) 
  {
    ArrayList ids = new ArrayList();
    Iterator iter = registry.clientRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ClientRuntimeDescriptor desc = (ClientRuntimeDescriptor)iter.next();
      //Check if this serviceRuntime supports the implementation type
      if (desc.getClientImplementationType().getId().equals(clientImplId))
      {
        ids.add(desc.getId());
      }
    }
    
    return (String[])ids.toArray(new String[]{});
  }  
  
  /**
   * Returns the ids of all clientRuntimes that support the given
   * Web service client implementation type and the preferred server
   * @param clientImplId id of a Web service client implementation type
   * @returns String[] array containing the ids of all clientRuntimes that
   * support the given Web service client implementation type. The array may have 0 elements.
   */
  public static String[] getClientRuntimesByType(String clientImplId, String preferredServerFactoryId) 
  {
    ArrayList ids = new ArrayList();
    ArrayList idsPreferredByServer = new ArrayList();
    Iterator iter = registry.clientRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ClientRuntimeDescriptor desc = (ClientRuntimeDescriptor)iter.next();
      //Check if this serviceRuntime supports the implementation type
      if (desc.getClientImplementationType().getId().equals(clientImplId))
      {
    	  String clientRuntimeId = desc.getId();
    	  if (desc.getRuntimePreferredServerType() != null && desc.getRuntimePreferredServerType().equals(preferredServerFactoryId)) {
    		  idsPreferredByServer.add(clientRuntimeId);
    	  } else {
    		  ids.add(clientRuntimeId);
    	  }
      }
    }
    
 // append preferredRuntime after preferredRuntimeIdsListPreferredByServer
    String[] preferredRuntimeIds = new String[idsPreferredByServer.size()+ids.size()];
    Iterator itr1 = idsPreferredByServer.iterator();
    int preferredRTCounter = 0;
    while (itr1.hasNext()) {
		String runtimeId = (String) itr1.next();
		preferredRuntimeIds[preferredRTCounter++] = runtimeId;
	}
    
    Iterator itr2 = ids.iterator();  
     
    while (itr2.hasNext()) {
		String runtimeId = (String) itr2.next();
		preferredRuntimeIds[preferredRTCounter++] = runtimeId;		
	}

    return preferredRuntimeIds;
  }  
  
  /**
   * Returns the ids of all Web service runtimes that support the given
   * Web service client implementation type.
   * @param clientImplId id of a Web service client implementation type
   * @return String[] array containing the ids of all Web service runtimes that
   * support the given Web service client implementation type. The array may have 0 elements.
   */
  public static String[] getRuntimesByClientType(String clientImplId) 
  {
    ArrayList runtimeIds = new ArrayList();
    Iterator iter = registry.clientRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ClientRuntimeDescriptor desc = (ClientRuntimeDescriptor)iter.next();
      //Check if this serviceRuntime supports the implementation type
      if (desc.getClientImplementationType().getId().equals(clientImplId))
      {
        if (!runtimeIds.contains(desc.getRuntime().getId()))
        {
          runtimeIds.add(desc.getRuntime().getId());
        }
      }
    }
    
    return (String[])runtimeIds.toArray(new String[]{});
  }
  
  /**
   * Returns whether or not the given Web service runtime supports the given 
   * Web service client implementation type.
   * @param clientImplId id of a Web service client implementation type
   * @param runtimeId id of a Web service runtime
   * @return boolean <code>true</code> if the given Web service runtime supports the given 
   * Web service client implementation type. <code>false</code> otherwise.
   */
  public static boolean isRuntimeSupportedForClientType(String clientImplId, String runtimeId)
  {
    String[] clientRuntimeIds = getClientRuntimesByType(clientImplId);
    if (clientRuntimeIds!=null)
    {
      for (int i=0; i < clientRuntimeIds.length; i++)
      {
        ClientRuntimeDescriptor desc = getClientRuntimeDescriptorById(clientRuntimeIds[i]);
        if (desc.getRuntime().getId().equals(runtimeId))
        {
          return true;
        }
      }
    }
    
    return false;
  }
  
  /**
   * Returns all server type ids with configured server runtimes.
   * @return String[] array of server type ids. The array may have 0 elements.
   */
  public static String[] getAllClientServerFactoryIds() 
  {    
    //Iterator iter = registry.clientRuntimes_.values().iterator();
    //while (iter.hasNext())   
    //{
      //TODO iterate over all the server types and see if their runtime types have an
      //id that matches the runtime type of any of the runtimes.            
      // ClientRuntimeDescriptor desc = (ClientRuntimeDescriptor)iter.next();
      // Set runtimes = getRuntimes(desc.getRequiredFacetVersions());
      // IServerType[] allServerTypes = ServerCore.getServerTypes();
    //}
    //return (String[])serverFactoryIds.toArray(new String[]{});
    //Temporarily return all server types
    return getAllServerFactoryIdsWithRuntimes();    
  }
  
  /**
   * Returns the ids of all server types that support the given
   * Web service client implementation type.
   *  
   * @param clientImplId id of a Web service client implementation type
   * @return String[] array containing the ids of all server types that
   * support the given Web service client implementation type. The array may have 0 elements.
   */
  public static String[] getServerFactoryIdsByClientType(String clientImplId)
  {
    ArrayList serverFactoryIds = new ArrayList();
    String[] crts = getClientRuntimesByType(clientImplId);
    if (crts != null)
    {
      for (int i = 0; i < crts.length; i++)
      {
        //Get the runtimes that work for the facets required for this serviceRuntime        
        String[] fIds = getServerFactoryIdsByClientRuntime(crts[i]);
        for (int j=0; j<fIds.length; j++)
        {
          if (!serverFactoryIds.contains(fIds[j]))
          {
            serverFactoryIds.add(fIds[j]);            
          }
        }
      }        
    }
    
    return (String[])serverFactoryIds.toArray(new String[]{});
  }  
  
  /**
   * Returns whether or not the given server type supports the given 
   * Web service client implementation type.
   * @param clientImplId id of a Web service client implementation type
   * @param serverFactoryId id of a server type
   * @return <code>true</code> if the given server type supports the given 
   * Web service client implementation type. <code>false</code> otherwise.
   */
  public static boolean isServerSupportedForChosenClientType(String clientImplId, String serverFactoryId)
  {
    String[] fIds = getServerFactoryIdsByClientType(clientImplId);
    if (fIds == null)
    {
      return false;
    }

    for (int i=0;i<fIds.length;i++)
    {
      if (serverFactoryId.equals(fIds[i]))
      {
        return true;
      }      
    }
    
    return false;
  }  
  
  /**
   * Returns the ids of all server types that support the given
   * clientRuntime.
   * 
   * @param clientRuntimeId id of a clientRuntime
   * @return String[] array containing the ids of all server types that
   * support the given clientRuntime. The array may have 0 elements.
   */
  public static String[] getServerFactoryIdsByClientRuntime(String clientRuntimeId)
  {       
    ClientRuntimeDescriptor desc = getClientRuntimeDescriptorById(clientRuntimeId);
    Set facetRuntimes = getRuntimes(desc.getRequiredFacetVersions());

    String[] fIds = getServerFactoryIdsByFacetRuntimes(facetRuntimes);
    return fIds;    
  }    

  /**
   * Returns whether or not the given server type supports the given 
   * clientRuntime.
   * 
   * @param clientRuntimeId id of a clientRuntime
   * @param serverFactoryId id of a server type
   * @return boolean <code>true</code> if the given server type supports the given 
   * clientRuntime. <code>false</code> otherwise.
   */
  public static boolean doesClientRuntimeSupportServer(String clientRuntimeId, String serverFactoryId)
  {
    String[] serverIds = getServerFactoryIdsByClientRuntime(clientRuntimeId);
    for (int i=0; i<serverIds.length; i++)
    {
      if (serverIds[i].equals(serverFactoryId))
      {
        return true;
      }
    }
    
    return false;
  }
  
  /**
   * Returns whether or not the given server type supports the given Web service runtime
   * 
   * @param runtimeId id of a Web service runtime
   * @param factoryId id of a server type
   * @return boolean <code>true</code> if the given server type supports the given 
   * Web service runtime for the client side. <code>false</code> otherwise.
   */
  public static boolean doesRuntimeSupportServerForClientSide(String runtimeId, String factoryId)
  {
    //Get all the ClientRuntimeDescriptors that point to this runtimeId
    Iterator iter = registry.clientRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ClientRuntimeDescriptor desc = (ClientRuntimeDescriptor)iter.next();
      //check if this clientRuntime points to runtimeId
      String thisRuntimeId = desc.getRuntime().getId();
      if (thisRuntimeId.equals(runtimeId))
      {
        Set facetRuntimes = getRuntimes(desc.getRequiredFacetVersions());
        String[] fIds = getServerFactoryIdsByFacetRuntimes(facetRuntimes);
        for (int i=0; i<fIds.length; i++)
        {
          if (fIds[i].equals(factoryId))
          {
            return true;
          }
        }
      }            
    }
    
    //No match.
    return false;
  }    
  
  /**
   * Returns the id of a server type that supports the given Web service runtime
   * on the client side.
   * 
   * @param runtimeId id of a Web service runtime
   * @return String the id of a server type that supports the given Web service runtime
   * on the client side. Returns null if such a server type cannot be found.
   */
  public static String getFirstSupportedServerForClientSide(String runtimeId)
  {
    //Get all the ClientRuntimeDescriptors that point to this runtimeId
    Iterator iter = registry.clientRuntimes_.values().iterator();
    while (iter.hasNext())   
    {
      ClientRuntimeDescriptor desc = (ClientRuntimeDescriptor)iter.next();
      //check if this clientRuntime points to runtimeId
      String thisRuntimeId = desc.getRuntime().getId();
      if (thisRuntimeId.equals(runtimeId))
      {
        Set facetRuntimes = getRuntimes(desc.getRequiredFacetVersions());
        String[] factoryIds = getServerFactoryIdsByFacetRuntimes(facetRuntimes);
        if (factoryIds!=null && factoryIds.length >0)
        {
          return factoryIds[0];
        }
      }            
    }
    
    //No suitable servers found. Return null.
    return null;

  }
  

  /**
   * Returns whether or not the given combination of server type, Web service runtime, and 
   * Web service client implementation type is supported. Used for validation.
   * 
   * @param serverFactoryId id of a server type
   * @param runtimeId id of a Web service runtime
   * @param clientImplId id of a Web service client implementation type
   * @return boolean <code>true</code> if the given combination of server type, Web service runtime, 
   * and Web service client implementation type is supported. <code>false</code> otherwise.
   */
  public static boolean isServerClientRuntimeTypeSupported(String serverFactoryId, String runtimeId, String clientImplId)  
  {
    //Ensure there is at least one clientRuntime that supports the given type
    String[] clientRuntimes = getClientRuntimesByType(clientImplId);
    if (clientRuntimes!=null && clientRuntimes.length>0)
    {
      //Ensure that at least one of these server runtimes supports the given server
      for (int i=0; i<clientRuntimes.length; i++)
      {
        ClientRuntimeDescriptor desc = getClientRuntimeDescriptorById(clientRuntimes[i]);
        if (desc.getRuntime().getId().equals(runtimeId))
        {
          //Matched type and runtime. Check the server.
          String[] factoryIds = getServerFactoryIdsByClientRuntime(desc.getId());
          for (int j=0; j<factoryIds.length; j++)
          {
            if (factoryIds[j].equals(serverFactoryId))
            {
              return true;
            }
          }
        }
      }
    }
    
    //No match found. return false.
    return false;
  }    
  
  /**
   * Returns an array of {@link IFacetedProjectTemplate} ids that support the given Web service client implementation type
   * and Web service runtime.
   * 
   * @param clientImplId id of a Web service client implementation type
   * @param runtimeId id of a Web service runtime
   * @return String[] array of {@link IFacetedProjectTemplate} ids that support the given Web service client implementation type
   * and Web service runtime. The array may have 0 elements. Returns null if no clientRuntimes supporting
   * the given Web service client implementation type could be found.
   */
  public static String[] getClientProjectTemplates(String clientImplId, String runtimeId)
  {
    String[] crIds = getClientRuntimesByType(clientImplId);
    if (crIds == null)
    {
      return null;
    }

    ArrayList templateIdList = new ArrayList();
    for (int i = 0; i < crIds.length; i++)
    {
      ClientRuntimeDescriptor desc = getClientRuntimeDescriptorById(crIds[i]);
      String thisRuntimeId = desc.getRuntime().getId();
      if (thisRuntimeId.equals(runtimeId))
      {
        //Get the templates for this clientRuntime
        Set templates = FacetMatchCache.getInstance().getTemplatesForClientRuntime(desc.getId());
        
        //Add the template ids to the list if they have not already been added
        Iterator itr = templates.iterator();
        while (itr.hasNext())
        {
          IFacetedProjectTemplate template = (IFacetedProjectTemplate)itr.next();
          if (!templateIdList.contains(template.getId()))
          {
            templateIdList.add(template.getId());
          }
        }
      }
      
    }  
    
    return (String[])templateIdList.toArray(new String[]{});    
  }  
  
  /**
   * Returns whether or not the given {@link IFacetedProjectTemplate} supports the given 
   * Web service client implementation type and Web service runtime.
   * 
   * @param clientImplId id of a Web service client implementation type
   * @param runtimeId id of a Web service runtime
   * @param templateId id of a {@link IFacetedProjectTemplate}
   * @return boolean <code>true</code> if the given {@link IFacetedProjectTemplate} supports the given 
   * Web service client implementation type and Web service runtime. Returns <code>false</code> otherwise. 
   */
  public static boolean doesClientTypeAndRuntimeSupportTemplate(String clientImplId, String runtimeId, String templateId)
  {
    String[] crIds = getClientRuntimesByType(clientImplId);
    if (crIds == null)
    {
      return false;
    }

    for (int i = 0; i < crIds.length; i++)
    {
      ClientRuntimeDescriptor desc = getClientRuntimeDescriptorById(crIds[i]);
      String thisRuntimeId = desc.getRuntime().getId();
      if (thisRuntimeId.equals(runtimeId))
      {
        //Get the templates for this clientRuntime
        Set templates = FacetMatchCache.getInstance().getTemplatesForClientRuntime(crIds[i]);
        
        //Check if the template ids contains the template we're checking for
        Iterator itr = templates.iterator();
        while (itr.hasNext())
        {
          IFacetedProjectTemplate template = (IFacetedProjectTemplate)itr.next();
          if (template.getId().equals(templateId))
          {
            return true;
          }
        }
      }
      
    }  
    
    return false;    
  }  
  

  /**
   * Returns whether or not the given {@link IFacetedProjectTemplate} 
   * supports the given clientRuntime
   *  
   * @param clientRuntimeId id of a clientRuntime
   * @param templateId id of a {@link IFacetedProjectTemplate}
   * @return boolean <code>true</code> if the given {@link IFacetedProjectTemplate} supports the given 
   * clientRuntime. Returns <code>false</code> otherwise.
   */
  public static boolean doesClientRuntimeSupportTemplate(String clientRuntimeId, String templateId)
  {
    //Get the templates for this clientRuntime
    Set templates = FacetMatchCache.getInstance().getTemplatesForClientRuntime(clientRuntimeId);
    IFacetedProjectTemplate checkingTemplate = ProjectFacetsManager.getTemplate(templateId);
    return templates.contains(checkingTemplate);
  }
  
  /**
   * Returns the labels and ids of all Web service client implementation types. 
   * Used to populate the Web service client type combo box on
   * page 1 of the Web service wizard and Web service client wizard.
   * @return {@link LabelsAndIds}
   */  
  public static LabelsAndIds getClientTypeLabels()
  {
    
    LabelsAndIds labelIds = new LabelsAndIds();
    String[] idsArray = new String[0];
    String[] labelsArray = new String[0];
    labelIds.setIds_(idsArray);
    labelIds.setLabels_(labelsArray);
  
    ArrayList ids = new ArrayList();
    ArrayList labels = new ArrayList();
  
    Iterator itr = registry.clientRuntimes_.values().iterator();
    while(itr.hasNext())
    {
      ClientRuntimeDescriptor desc = (ClientRuntimeDescriptor)itr.next();
      WebServiceClientImpl thisClientImpl = desc.getClientImplementationType();
      if (!ids.contains(thisClientImpl.getId()))
      {
        ids.add(thisClientImpl.getId());
        labels.add(thisClientImpl.getLabel());
      }
    }

    if (ids.size() > 0)
    {
      idsArray = (String[]) ids.toArray(new String[0]);
      labelsArray = (String[]) labels.toArray(new String[0]);
      labelIds.setIds_(idsArray);
      labelIds.setLabels_(labelsArray);
    }

    return labelIds;

  }  
  
  /**
   * Returns all server type ids for which there are configured server runtimes
   * present in the workspace.
   * 
   * @return String[] array of server type ids for which there are configured server runtimes
   * present in the workspace. The array may have 0 elements.
   */
  public static String[] getAllServerFactoryIdsWithRuntimes()
  {
    ArrayList fids = new ArrayList();
    IServerType[] sts = ServerCore.getServerTypes();
    org.eclipse.wst.server.core.IRuntime[] rts = ServerCore.getRuntimes();
    
    for (int i=0; i<sts.length; i++)
    {
      IServerType st = sts[i];
      for (int j=0; j<rts.length; j++)
      {
    	if (st == null || st.getRuntimeType() == null) break;    	  
        org.eclipse.wst.server.core.IRuntime rt = rts[j];
        // If the server type has the same runtime type as this runtime, add it to the list
        String serverTypeRuntimeTypeId = st.getRuntimeType().getId();
        
        if (rt != null)
        {
        	IRuntimeType rtType = rt.getRuntimeType();
        	if (rtType != null)
        	{
		        String runtimeRuntimeTypeId = rtType.getId();
		        if (serverTypeRuntimeTypeId.equals(runtimeRuntimeTypeId))
		        {
		          if (!fids.contains(st.getId()))
		          {
		            fids.add(st.getId());
		          }
		        }
        	}
        }
      }
    }
   
    return (String[])fids.toArray(new String[0]);
  }
  
  /**
   * Returns the names of all projects in the workspace which support the given Web service client 
   * implementation type and Web service runtime.
   * 
   * @param typeId id of a Web service client implementation type
   * @param runtimeId id of a Web service runtime
   * @return String[] array of project names. The array may have 0 elements.
   */
  public static String[] getProjectsForClientTypeAndRuntime(String typeId, String runtimeId)
  {
    IProject[] projects = FacetUtils.getAllProjects();
    ArrayList validProjects = new ArrayList();
    
    for (int i=0; i<projects.length;i++)
    {
      if (doesClientTypeAndRuntimeSupportProject(typeId, runtimeId, projects[i].getName()))
      {
        validProjects.add(projects[i].getName());        
      }      
    }
    
    return (String[])validProjects.toArray(new String[0]);
    
  }  
  
  /**
   * Returns whether or not the given project supports the given Web service client implementation type 
   * and Web service runtime.
   * 
   * @param typeId id of a Web service client implementation type
   * @param runtimeId id of a Web service runtime
   * @param projectName name of an IProject in the workspace
   * @return boolean <code>true</code> if the project supports the given Web service type and 
   * Web service runtime. Returns <code>false</code>
   * <ul> 
   * <li>if the project does not support the given Web service client implementation type and 
   * Web service runtime or</li>
   * <li>if the project does not exist or</li>
   * <li>if projectName is null or empty</li>
   * </ul>
   */
  public static boolean doesClientTypeAndRuntimeSupportProject(String typeId, String runtimeId, String projectName)
  {
    String[] descs = getClientRuntimesByType(typeId);
    for (int j = 0; j < descs.length; j++)
    {
      ClientRuntimeDescriptor desc = getClientRuntimeDescriptorById(descs[j]);
      if (desc.getRuntime().getId().equals(runtimeId))
      {
        if (doesClientRuntimeSupportProject(descs[j], projectName))
        {
          return true;
        }
      }
    }
    
    return false;
    
    
  }  
  
  
  /**
   * Returns whether or not the given project supports the given clientRuntime.
   * @param clientRuntimeId id of a clientRuntime
   * @param projectName name of an IProject in the workspace
   * @return boolean <code>true</code> if the project supports the given
   * clientRuntime. Returns <code>false</code>
   * <ul> 
   * <li>if the project does not support the given clientRuntime or</li>
   * <li>if the project does not exist or</li>
   * <li>if projectName is null or empty</li>
   * </ul>
   */
  public static boolean doesClientRuntimeSupportProject(String clientRuntimeId, String projectName)
  {
    FacetMatcher fm = FacetMatchCache.getInstance().getMatchForProject(true, clientRuntimeId, projectName);
    if (fm != null)
    {
      return fm.isMatch();
    }
    else
    {
      return false;
    }
  }
  
  //Utilities used by the ServerRuntimePreferencePage
  
  private static SelectionListChoices serverToRuntimeToJ2EE_;
  private static Hashtable serverFactoryIdByLabel_;
  private static Hashtable runtimeIdByLabel_;
  
  /**
   * Returns the {@link SelectionListChoices} data structure representing the 
   * server type > Web service runtime > J2EE cascading lists .
   * {@link SelectionListChoices} is a data structure  which is like a cascading
   * set of lists useful for populating a group of combo boxes in which the 
   * selection in a given combo box determines the list of items used to populate
   * the combo box below it. The Server Runtime preference page contains two combo
   * boxes: one for server types and, below it, one for Web service runtimes.
   * The server type combo box is meant to contain the list of all available server types
   * that support at least one Web service runtime on either the client or service side. 
   * The Web service runtime combo box is meant to contain the subset of Web service runtimes
   * supported by the server type selected in the server type combo box.
   * The SelectionListChoices returned by this method has three lists: server types, Web service runtimes,
   * and J2EE levels. The first two lists correspond to the combo boxes on the preference
   * page and are used to populate them. The J2EE levels list is a historical remnant from
   * when J2EE levels used to be displayed on the preference page. It remains in this 
   * data structure with some hard-coded values but is not rendered to the user. 
   * 
   * @return SelectionListChoices representing the server type > Web service runtime > J2EE cascading lists
   */
  public static SelectionListChoices getServerToRuntimeToJ2EE()
  {
    if (serverToRuntimeToJ2EE_!=null)
    {
      return serverToRuntimeToJ2EE_;
    }
    
    //TODO (see bug 116025): Instead of all server type ids, we should be calculating the set of server
    //types that support at least one Web service runtime on either the client or service side.
    //Getting all server types for now.
    String[] servers = getAllServerFactoryIds();
    
    SelectionList serversList = new SelectionList(servers, 0);
    Vector choices = new Vector();
    for (int i=0; i<servers.length; i++)
    {
      choices.add(getRuntimeChoices(servers[i]));
    }
    serverToRuntimeToJ2EE_ = new SelectionListChoices(serversList, choices);
    return serverToRuntimeToJ2EE_;
    
  }

  private static SelectionListChoices getRuntimeChoices(String serverFactoryId)
  {
	//TODO (see bug 116025): Instead of all Web service runtimes, we should be 
	//calculating the subset of Web service runtimes supported by the server type
	//with id equal to serverFactoryId. Getting all the Web service runtimes for now.
    Set runtimes = registry.runtimes_.keySet();
    Iterator itr = registry.runtimes_.keySet().iterator();
    String[] runtimeIds = new String[runtimes.size()];    
    int i = 0;
    while (itr.hasNext())
    {
      String runtimeId = (String)itr.next();
      runtimeIds[i] = runtimeId;
      i++;     
    }

    SelectionList runtimesList = new SelectionList(runtimeIds, 0);
    Vector choices = new Vector();
    for (int j=0; j<runtimeIds.length; j++)
    {
      choices.add(getJ2EEChoices(runtimeIds[j]));
    }
    return new SelectionListChoices(runtimesList, choices);    
  }  
  
  private static SelectionListChoices getJ2EEChoices(String runtimeId)
  {
    //J2EE levels have been removed from the Server Runtime preference page.
    //Return some hard coded values. These will not be rendered on the preference page.
    String[] j2eeVersions = new String[]{"13", "14"};
    SelectionList j2eeVersionsList = new SelectionList(j2eeVersions, 0);
    return new SelectionListChoices(j2eeVersionsList, null);        
  }  
  
  private static String[] getAllServerFactoryIds()
  {
    //TODO (see bug 116025): Instead of all server type ids, we should be calculating the set of server
	//types that support at least one Web service runtime on either the client or service side.
	//Return all server type ids for now.
    ArrayList ids = new ArrayList();
    if (serverFactoryIdByLabel_ == null)
    {
      serverFactoryIdByLabel_ = new Hashtable();
      IServerType[] serverTypes = ServerCore.getServerTypes();
      for (int i=0; i<serverTypes.length; i++)
      {
        String id = serverTypes[i].getId();
        String label = getServerLabelById(id);
        serverFactoryIdByLabel_.put(label, id);
        ids.add(id);
      }    
    }
    else
    {
      Iterator fids =  serverFactoryIdByLabel_.values().iterator();
      while (fids.hasNext())
      {
        String fid = (String)fids.next();
        ids.add(fid);
      }           
    }
    
    if (ids.size() > 0)
    {
      String[] serverFactoryIds = (String[])ids.toArray(new String[0]);
      return serverFactoryIds;
    }
    
    return null;
  }  
    
  /**
   * Returns a server type id given the server type's label
   * @param label server type label
   * @return server type id or null if no server type with the given 
   * label is found.
   */
  public static String getServerFactoryId(String label)
  {
    if (label==null || label.length()==0)
      return null;
    
    if (serverFactoryIdByLabel_ == null)
    {
      getAllServerFactoryIds();
    }
    
    if (serverFactoryIdByLabel_.containsKey(label))
    {
      return (String)serverFactoryIdByLabel_.get(label);  
    }
    else
    {
      return null;
    }       
  }  
  
  /**
   * Returns a Web service runtime's id given its label 
   * @param label Web service runtime label
   * @return Web service runtime id or null if no
   * Web service runtime with the given label is found.
   */
  public static String getRuntimeId(String label)
  {
    
    if (label==null || label.length()==0)
      return null;
    
    if (runtimeIdByLabel_ == null)
    {
      runtimeIdByLabel_ = new Hashtable();
      Iterator iter = registry.runtimes_.values().iterator();
      while (iter.hasNext())
      {
        RuntimeDescriptor desc = (RuntimeDescriptor)iter.next();
        runtimeIdByLabel_.put(desc.getLabel(), desc.getId());        
      }      
    }
    
    return (String)runtimeIdByLabel_.get(label);    
  }    
  
    
  /**
   * Returns a set of facet runtimes that support the given
   * required facet versions.
   * @param requiredFacetVersions an array containing elements of type {@link RequiredFacetVersion}
   * @return Set set of facet runtimes that support the given required facet versions.
   * (element type: {@link IRuntime}) 
   */
  private static Set getRuntimes(RequiredFacetVersion[] requiredFacetVersions)
  {
    return FacetUtils.getRuntimes(requiredFacetVersions);
  }
  
/**
 * Get the service runtime checker class
 * @param serviceRuntimeId service runtime ID
 * @return
 */
  public static IWebServiceRuntimeChecker getServiceRuntimeChecker(String serviceRuntimeId) {
	  return getServiceRuntimeDescriptorById(serviceRuntimeId).getServiceRuntimeChecker();
	  
  }

/**
 * Get the client runtime checker class
 * @param clientRuntimeId
 * @return
 */
public static IWebServiceRuntimeChecker getClientRuntimeChecker(String clientRuntimeId) {
	  return getClientRuntimeDescriptorById(clientRuntimeId).getClientRuntimeChecker();
	  
  }

/**
 * Get the service runtime preferred server type
 * @param serviceRuntimeId service runtime ID
 * @return
 */
  public static String getServicePreferredServerType(String serviceRuntimeId) {
	  return getServiceRuntimeDescriptorById(serviceRuntimeId).getRuntimePreferredServerType();
	  
  }

/**
 * Get the client runtime preferred server type
 * @param clientRuntimeId
 * @return
 */
public static String getClientPreferredServerType(String clientRuntimeId) {
	  return getClientRuntimeDescriptorById(clientRuntimeId).getRuntimePreferredServerType();
	  
  }
}
