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

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

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jst.j2ee.internal.project.IEJBNatureConstants;
import org.eclipse.jst.ws.internal.consumption.ui.wizard.IWebServiceType;
import org.eclipse.jst.ws.internal.consumption.ui.wizard.TypeSelectionFilter;
import org.eclipse.jst.ws.internal.consumption.ui.wizard.WebServiceTypeImpl;
import org.eclipse.jst.ws.internal.data.LabelsAndIds;
import org.eclipse.wst.command.internal.provisional.env.core.common.MessageUtils;
import org.eclipse.wst.command.internal.provisional.env.core.selection.SelectionList;
import org.eclipse.wst.command.internal.provisional.env.core.selection.SelectionListChoices;
import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants;
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.provisional.wsrt.IWebServiceRuntime;
import org.eclipse.wst.ws.internal.provisional.wsrt.WebServiceScenario;

public class WebServiceRuntimeExtensionUtils
{
  private static WebServiceRuntimeExtensionRegistry registry = WebServiceRuntimeExtensionRegistry.getInstance();
  private static SelectionListChoices serverToRuntimeToJ2EE_;
  private static Hashtable serverFactoryIdByLabel_;
  private static Hashtable runtimeIdByLabel_;
  
  public static IWebServiceRuntime getWebServiceRuntime( String runtimeId )
  {
	WebServiceRuntimeInfo wsrtInfo       		= getWebServiceRuntimeById(runtimeId);
	IWebServiceRuntime    webserviceRuntime     = null;
	if (wsrtInfo != null)
	{
		webserviceRuntime = wsrtInfo.getWebServiceRuntime();
	}
	
	return webserviceRuntime;
  }
  
  public static IWebServiceType getWebServiceTypeById(String id)
  {
    Object result = registry.webServiceTypes_.get(id);
	
    if (result!=null)
    {
      return (WebServiceTypeImpl)result;
    }
    return null;
  }
  
  public static WebServiceImpl getWebServiceImplById(String id)
  {
    Object result = registry.webServiceImpls_.get(id);
    if (result!=null)
    {
      return (WebServiceImpl)result;
    }
    return null;    
  }
  
  public static int getScenarioFromTypeId(String typeId)
  {
    return Integer.parseInt(typeId.substring(0,typeId.indexOf("/")));
  }
  
  public static String getImplIdFromTypeId(String typeId)
  {
    return typeId.substring(typeId.indexOf("/")+1);
  }
  /*
   * @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 id
   * of the WebServiceImpl
   */  
  public static ServiceType getServiceType(String runtimeId, String typeId)
  {
    WebServiceRuntimeInfo wsrt = getWebServiceRuntimeById(runtimeId);
    if (wsrt!=null)
    {
      int scenario = getScenarioFromTypeId(typeId);
      String implId = getImplIdFromTypeId(typeId);
      //Return the first service type that supports the impl and scenario
      ServiceType[] sts = wsrt.getServiceTypes();
      if (sts != null)
      {
        for (int i = 0; i < sts.length; i++)
        {
          String thisImplId = sts[i].getWebServiceImpl().getId();
          if (implId.equals(thisImplId))
          {
            // Check if scenario is supported
            if (sts[i].supportsScenario(scenario))
            {
              return sts[i];
            }
          }
        }
      }
    }
    
    return null;
  }
  
  public static WebServiceRuntimeInfo getWebServiceRuntimeById(String id)
  {
    Object result = registry.webServiceRuntimes_.get(id);
    if (result!=null)
    {
      return (WebServiceRuntimeInfo)result;
    }
    return null;
  }  
  
  public static WebServiceRuntimeInfo getWebServiceRuntimeByLabel(String label)
  {
    Iterator iter = registry.webServiceRuntimes_.values().iterator();
    while (iter.hasNext())
    {
      WebServiceRuntimeInfo wsr = (WebServiceRuntimeInfo)iter.next();
      if (wsr!=null) {
        if (label.equals(wsr.getLabel()))
          return wsr;
      }
    }
    return null;      
  }  

  /*
   * @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 id
   * of the WebServiceImpl
   */
  public static String[] getRuntimesByType(String typeId) 
  {
    int scenario = getScenarioFromTypeId(typeId);
    String implId = getImplIdFromTypeId(typeId);    
    ArrayList ids = new ArrayList();
    Iterator iter = registry.webServiceRuntimes_.values().iterator();
    while (iter.hasNext())
    {
      WebServiceRuntimeInfo wsr = (WebServiceRuntimeInfo)iter.next();
      ServiceType[] sts = wsr.getServiceTypes();
      if (sts != null)
      {
        for (int i = 0; i < sts.length; i++)
        {
          String thisImplId = sts[i].getWebServiceImpl().getId();
          if (implId.equals(thisImplId))
          {
            // Check if scenario is supported
            if (sts[i].supportsScenario(scenario))
            {
              ids.add(wsr.getId());
              break;
            }
          }
        }
      }
    }
    
    if (ids.size() > 0)
    {
      String[] runtimeIds = (String[])ids.toArray(new String[0]);
      return runtimeIds;
    }
    
    return null;
  }
  
  /*
   * @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 id
   * of the WebServiceImpl
   */  
  public static boolean isRuntimeSupportedForType(String typeId, String runtimeId)
  {
    String[] runtimeIds = getRuntimesByType(typeId);
    if (runtimeIds!=null)
    {
      for (int i=0; i < runtimeIds.length; i++)
      {
        if (runtimeIds[i].equals(runtimeId))
        {
          return true;
        }
      }
    }
    
    return false;
  }
  
  public static String[] getServerFactoryIdsByType(String typeId) 
  {
    String[] wsrts = getRuntimesByType(typeId);
    if (wsrts == null )
    {
      return null;
    }
      
    ArrayList ids = new ArrayList();
    for (int i=0; i<wsrts.length ;i++)
    {
      String[] fIds = getWebServiceRuntimeById(wsrts[i]).getServerFactoryIds();
      if (fIds != null)
      {
        for (int j=0; j<fIds.length; j++)
        {
          if (!ids.contains(fIds[j]))
          {
            ids.add(fIds[j]);
          }
        }
      }
    }
    
    if (ids.size() > 0)
    {
      String[] serverFactoryIds = (String[])ids.toArray(new String[0]);
      return serverFactoryIds;
    }
    
    return null;    
  }
  
  /*
   * @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 id
   * of the WebServiceImpl
   */
  public static boolean isServerSupportedForChosenType(String typeId, String serverFactoryId)
  {
    String[] fIds = getServerFactoryIdsByType(typeId);
    if (fIds == null)
    {
      return false;
    }

    for (int i=0;i<fIds.length;i++)
    {
      if (serverFactoryId.equals(fIds[i]))
      {
        return true;
      }      
    }
    
    return false;
  }
  
  /*
   * @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 id
   * of the WebServiceImpl
   */    
  public static boolean isServerRuntimeTypeSupported(String serverFactoryId, String runtimeId, String typeId)  
  {
    String[] rIds = getRuntimesByType(typeId);
    if (rIds == null)
    {
      return false;
    }
    
    for (int i = 0; i < rIds.length; i++)
    {
      if (runtimeId.equals(rIds[i]))
      {
        String[] fIds = getWebServiceRuntimeById(rIds[i]).getServerFactoryIds();
        if (fIds != null)
        {
          for (int j = 0; j < fIds.length; j++)
          {
            if (serverFactoryId.equals(fIds[j]))
            {
              // Found it!
              return true;
            }
          }
        }
      }
    }  
    
    return false;
  }
  
  public static boolean doesRuntimeSupportJ2EELevel(String j2eeVersionId, String runtimeId)
  {
    WebServiceRuntimeInfo wsrt = getWebServiceRuntimeById(runtimeId);
    if (wsrt==null)
      return false;
    
    String[] j2eeVersions = wsrt.getJ2eeLevels();
    if (j2eeVersions==null || j2eeVersions.length==0) 
      return true;
    
    for(int i=0; i<j2eeVersions.length; i++)
    {
      if (j2eeVersions[i].equals(j2eeVersionId))
      {
        return true;
      }
    }
    return false;        
  }
  
  public static boolean doesRuntimeSupportServerTarget(String serverTargetId, String runtimeId)
  {
    WebServiceRuntimeInfo wsrt = getWebServiceRuntimeById(runtimeId);
    if (wsrt==null)
      return false;
    
    String[] fIds = wsrt.getServerFactoryIds();
    for(int i=0;i<fIds.length;i++)
    {
      IServerType serverType = ServerCore.findServerType(fIds[i]);
      if (serverType == null)
        continue;
      
      String thisServerTargetId = serverType.getRuntimeType().getId(); 
      if (thisServerTargetId.equals(serverTargetId))
        return true;
    }
    
    return false;
  }

  /**
   * Returns a list of valid projects for the Web service type with an id of typeId.
   * In the case where the Web service type extension does not specify which project
   * natures are included, a array of all Web and EJB projects in the workspace will
   * be returned.
   * @param typeId
   * @return IProject[] an array of valid projects
   */
  public static IProject[] getAllProjects()
  {
    IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
    ArrayList validProjects = new ArrayList();
    for (int i = 0; i < projects.length; i++)
    {
      if (!projects[i].getName().equals("Servers") && !projects[i].getName().startsWith("."))
      {
        validProjects.add(projects[i]);
      }
    }
    
    return (IProject[])validProjects.toArray(new IProject[0]); 
    // rsktodo
    /*
    IWebServiceType wst = getWebServiceTypeById(typeId);
    if (wst != null)
    {
      IConfigurationElement elem = wst.getConfigurationElement();
      String includedNatures = elem.getAttribute("includeNatures");
      String excludedNatures = elem.getAttribute("excludeNatures");
      if (includedNatures!=null && includedNatures.length()>0)
      {
        for (int i = 0; i < projects.length; i++)
        {
          if (include(projects[i], includedNatures) && exclude(projects[i], excludedNatures))
            validProjects.add(projects[i]);
        }
        return (IProject[])validProjects.toArray(new IProject[0]);
      }
    }
    
    //If wst was null or the extension didn't specify which project natures are
    // to be included, revert to the old behaviour
    for (int j = 0; j < projects.length; j++)
    {
      if (ResourceUtils.isWebProject(projects[j]) || ResourceUtils.isEJBProject(projects[j]))
        validProjects.add(projects[j]);
    }    
    return (IProject[])validProjects.toArray(new IProject[0]);
    */
    // rsktodo
  }
  
  private static boolean include(IProject project, String include)
  {
    StringTokenizer st = new StringTokenizer(include);
    while(st.hasMoreTokens())
    {
      try
      {
        if (project.hasNature(st.nextToken()))
          return true;
      }
      catch (CoreException ce)
      {
      }
    }
    return false;
  }

  private static boolean exclude(IProject project, String exclude)
  {
    StringTokenizer st = new StringTokenizer(exclude);
    while(st.hasMoreTokens())
    {
      try
      {
        if (project.hasNature(st.nextToken()))
          return false;
      }
      catch (CoreException ce)
      {
      }
    }
    return true;
  }  
  
  public static LabelsAndIds getServiceTypeLabels()
  {
    String       pluginId = "org.eclipse.jst.ws.consumption.ui";
    MessageUtils msgUtils = new MessageUtils( pluginId + ".plugin", registry );
    
    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 = getImplIdFromTypeId(wst);
      WebServiceImpl wsimpl = WebServiceRuntimeExtensionUtils.getWebServiceImplById(implId);
      String impllabel = wsimpl.getLabel();
      ids[index]    = wst;
      String scenLabel = "";
      switch(scenario)
      {
      case WebServiceScenario.BOTTOMUP:
        scenLabel = msgUtils.getMessage(WebServiceScenario.BOTTOMUP_LABEL);
        break;
      case WebServiceScenario.TOPDOWN:
        scenLabel = msgUtils.getMessage(WebServiceScenario.TOPDOWN_LABEL);
        break; 
      default:
      }
      labels[index] = scenLabel +" "+impllabel;
      index++;
    }    
    
    return labelIds;
  }
  
  /*
   * @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 id
   * of the WebServiceImpl
   */
  public static String getDefaultRuntimeValueFor(String typeId)
  {
    String[] rIds = getRuntimesByType(typeId);
    if (rIds == null)
    {
      return null;
    }
    
    return rIds[0];
  }    
  
  
  public static String getDefaultServerValueFor(String typeId)
  {
    String[] fIds = getServerFactoryIdsByType(typeId);
    if (fIds==null)
      return null;
    
    return fIds[0];
  }  
  
  public static String[] getWebServiceTypeBySelection(IStructuredSelection selection)
  {
    TypeSelectionFilter tsf = new TypeSelectionFilter();
    String[] wst = tsf.getWebServiceTypeByInitialSelection(selection, registry.webServiceTypesList_);
    return wst == null ? null : wst;
  }    
  /**
   * Returns true if an EJB project is needed to host a Web service
   * of the type identified by typeId. If multiple natureIds are specified in the 
   * "includeNatures" attribute, only the first one is checked. If no natureIds are specified, 
   * false is returned.
   * 
   * @deprecated  
   * 	Should be refactored in future 
   */
  public static boolean requiresEJBProject(String typeId)
  {
    IWebServiceType wst = getWebServiceTypeById(typeId);
    if (wst != null)
    {
      IConfigurationElement elem = wst.getConfigurationElement();
      String includedNatures = elem.getAttribute("includeNatures");
      if (includedNatures==null || includedNatures.length()==0)
      {
        return false;
      }
      else
      {
        StringTokenizer st = new StringTokenizer(includedNatures);
        if(st.hasMoreTokens())
        {
          String firstIncludedNature = st.nextToken();
          if (firstIncludedNature.equals(IEJBNatureConstants.NATURE_ID))
            return true;
        }
      }
    }
    return false;
  }  
  
  /*
   * @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 id
   * of the WebServiceImpl
   */
  public static boolean requiresEJBProject(String runtimeId, String typeId)
  {
    ServiceType st = getServiceType(runtimeId, typeId);
    if (st!=null)
    {
      String[] includedNatures = st.getModuleTypesInclude(getScenarioFromTypeId(typeId));
      if (includedNatures!=null && includedNatures.length>0)
      {
        if (includedNatures[0].equals(IModuleConstants.JST_EJB_MODULE))
        {
          return true;
        }
      }
    }
    
    return false;
  }  
  
  public static boolean requiresEJBModuleFor(String serverFactoryId, String runtimeId, String typeId)
  {
	  // rsktodo
	  return false;
  }  
  
  //Ported from the former WebServiceClientRegistry
  
  public static String getRuntimeLabelById(String runtimeId) 
  {
    WebServiceRuntimeInfo wsrt = getWebServiceRuntimeById(runtimeId);
    if (wsrt == null)
      return null;
    
    return wsrt.getLabel();
  }  
  
  public static String getServerLabelById(String serverFactoryId)
  {
    IServerType serverType = ServerCore.findServerType(serverFactoryId);
    if (serverType == null)
      return null;
    
    String serverLabel = ServerUICore.getLabelProvider().getText(serverType);   
    return serverLabel;
  }
  
  public static String getServerInstanceLabelFromInstanceId( String instanceId )
  {
    IServer server = ServerCore.findServer( instanceId );    
    return server.getName();
  }  
  
  public static boolean doesRuntimeSupportServer(String runtimeId, String factoryId)
  {
    WebServiceRuntimeInfo wsrt = getWebServiceRuntimeById(runtimeId);
    if (wsrt != null)
    {
      String[] fids = wsrt.getServerFactoryIds();
      if (fids!=null)
      {
        for (int i=0; i<fids.length; i++)
        {
          if (fids[i].equals(factoryId))
          {
            return true;
          }
        }
      }
    }
    return false;
  }
  
  public static String getFirstSupportedServer(String runtimeId)
  {
    WebServiceRuntimeInfo wsrt = getWebServiceRuntimeById(runtimeId);
    
    if (wsrt != null)
    {
      String[] fids = wsrt.getServerFactoryIds();
      if (fids!=null && fids.length>0)
      {
        return fids[0];
      }
    }
    
    return null;    
  }


  public static String[] getRuntimesByClientType(String clientImplId) 
  {
    ArrayList ids = new ArrayList();
    Iterator iter = registry.webServiceRuntimes_.values().iterator();
    while (iter.hasNext())
    {
      WebServiceRuntimeInfo wsr = (WebServiceRuntimeInfo)iter.next();
      ClientType[] cts = wsr.getClientTypes();
      if (cts != null)
      {
        for (int i = 0; i < cts.length; i++)
        {
          String wsClientImplId = cts[i].getWebServiceClientImpl().getId();
          if (wsClientImplId.equals(clientImplId))
          {
            ids.add(wsr.getId());
            break;
          }
        }
      }
    }
    
    if (ids.size() > 0)
    {
      String[] runtimeIds = (String[])ids.toArray(new String[0]);
      return runtimeIds;
    }
    
    return null;    
  }
  

  
  public static boolean webServiceClientRuntimeTypeExists(String serverFactoryId, String runtimeId, String clientTypeId) 
  {
    String[] rIds = getRuntimesByClientType(clientTypeId);
    if (rIds == null)
    {
      return false;
    }
    
    for (int i = 0; i < rIds.length; i++)
    {
      if (runtimeId.equals(rIds[i]))
      {
        String[] fIds = getWebServiceRuntimeById(rIds[i]).getServerFactoryIds();
        if (fIds != null)
        {
          for (int j = 0; j < fIds.length; j++)
          {
            if (serverFactoryId.equals(fIds[j]))
            {
              // Found it!
              return true;
            }
          }
        }
      }
    }  
    
    return false;
  }
  
  public static String[] getAllClientRuntimes() 
  {
    ArrayList ids = new ArrayList();
    Iterator iter = registry.webServiceRuntimes_.values().iterator();
    while (iter.hasNext())
    {
      WebServiceRuntimeInfo wsr = (WebServiceRuntimeInfo)iter.next();
      ClientType[] cts = wsr.getClientTypes();
      if (cts!=null && cts.length>0)
      {
        //this runtime supports the client scenario
        ids.add(wsr.getId());
      }
    }
    
    if (ids.size() > 0)
    {
      String[] runtimeIds = (String[])ids.toArray(new String[0]);
      return runtimeIds;
    }
    
    return null;
  }
  

  public static String[] getAllClientServerFactoryIds() 
  {    
    String[] rIds = getAllClientRuntimes();
    if (rIds==null)
      return null;
    
    ArrayList ids = new ArrayList();
    for (int i=0; i<rIds.length ;i++)
    {
      String[] fIds = getWebServiceRuntimeById(rIds[i]).getServerFactoryIds();
      if (fIds != null)
      {
        for (int j=0; j<fIds.length; j++)
        {
          if (!ids.contains(fIds[j]))
          {
            ids.add(fIds[j]);
          }
        }
      }
    }
    
    if (ids.size() > 0)
    {
      String[] serverFactoryIds = (String[])ids.toArray(new String[0]);
      return serverFactoryIds;
    }
    
    return null;
  }
  

  
  public static String[] getClientProjectTypes(String clientImplId, String runtimeId)
  {
    String[] rIds = getRuntimesByClientType(clientImplId);
    if (rIds == null)
    {
      return null;
    }
    
    for (int i = 0; i < rIds.length; i++)
    {
      if (runtimeId.equals(rIds[i]))
      {
        ClientType[] cts = getWebServiceRuntimeById(rIds[i]).getClientTypes();
        if (cts != null)
        {
          for (int j = 0; j < cts.length; j++)
          {
            String thisClientImplId = cts[j].getWebServiceClientImpl().getId();
            if (clientImplId.equals(thisClientImplId))
            {
              // Found the one!
              String[] projectTypes = cts[j].getModuleTypesInclude();
              return projectTypes;
            }
          }
        }
      }
    }  
    
    return null;    
  }
  
  public static boolean doesRuntimeSupportComponentType(String clientImplId, String runtimeId, String componentTypeId)
  {
    String[] compTypeIds = getClientProjectTypes(clientImplId, runtimeId);
    if (compTypeIds!=null)
    {
      for (int i=0; i<compTypeIds.length; i++)
      {
       if (compTypeIds[i].equals(componentTypeId))
       {
         return true;
       }
      }
    }
    
    return false;
  }
  
  public static LabelsAndIds getClientTypeLabels()
  {
    
    LabelsAndIds labelIds = new LabelsAndIds();
    String[] idsArray = new String[0];
    String[] labelsArray = new String[0];
    labelIds.setIds_(idsArray);
    labelIds.setLabels_(labelsArray);
  
    String[] rIds = getAllClientRuntimes();
    if (rIds == null)
    {
      return labelIds;
    }
  
    ArrayList ids = new ArrayList();
    ArrayList labels = new ArrayList();
  
    for (int i=0; i < rIds.length; i++)
    {
      WebServiceRuntimeInfo wsrt = getWebServiceRuntimeById(rIds[i]);
      ClientType[] cts = wsrt.getClientTypes();
      if (cts != null)
      {
        for (int j = 0; j < cts.length; j++)
        {
          ClientType ct = cts[j];
          // String id = ct.getWebServiceClientTypeId();
          String id = ct.getWebServiceClientImpl().getId();
          if (!ids.contains(id))
          {
            ids.add(id);
            labels.add(ct.getWebServiceClientImpl().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;

  }  
  
  //Utilities used by the ServerRuntimePreferencePage
  
  public static SelectionListChoices getServerToRuntimeToJ2EE()
  {
    if (serverToRuntimeToJ2EE_!=null)
    {
      return serverToRuntimeToJ2EE_;
    }
    
    //String[] servers = getStringArrayIntersection(getAllServerFactoryIds(), WebServiceClientTypeRegistry.getInstance().getAllClientServerFactoryIds());
    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)
  {
    
    String[] runtimes = getRuntimeIDsByServerFactoryID(serverFactoryId);
    SelectionList runtimesList = new SelectionList(runtimes, 0);
    Vector choices = new Vector();
    for (int i=0; i<runtimes.length; i++)
    {
      choices.add(getJ2EEChoices(runtimes[i]));
    }
    return new SelectionListChoices(runtimesList, choices);    
  }  
  
  private static SelectionListChoices getJ2EEChoices(String runtimeId)
  {
    //String[] serviceJ2EEVersions = getWebServiceRuntimeById(runtimeId).getJ2EEVersions();
    //String[] clientJ2EEVersions = WebServiceClientTypeRegistry.getInstance().getWebServiceRuntimeById(runtimeId).getJ2EEVersions();
    //String[] j2eeVersions = getStringArrayIntersection(serviceJ2EEVersions, clientJ2EEVersions);
    WebServiceRuntimeInfo wsr = getWebServiceRuntimeById(runtimeId);
    if (wsr==null)
    {
      return null;
    }
    
    String[] j2eeVersions = wsr.getJ2eeLevels();
    SelectionList j2eeVersionsList = new SelectionList(j2eeVersions, 0);
    return new SelectionListChoices(j2eeVersionsList, null);
  }  
  
  private static String[] getAllServerFactoryIds()
  {
    ArrayList ids = new ArrayList();
    if (serverFactoryIdByLabel_ == null)
    {
      serverFactoryIdByLabel_ = new Hashtable();
      Iterator iter = registry.webServiceRuntimes_.values().iterator();
      while (iter.hasNext())
      {
        WebServiceRuntimeInfo wsr = (WebServiceRuntimeInfo) iter.next();
        String[] sfids = wsr.getServerFactoryIds();
        for (int i = 0; i < sfids.length; i++)
        {
          if (!ids.contains(sfids[i]))
          {
            String label = getServerLabelById(sfids[i]);
            if (label != null)
            {
              ids.add(sfids[i]);
              serverFactoryIdByLabel_.put(label, sfids[i]);
            }
          }
        }
      }
    }
    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;
  }  
  
  private static String[] getRuntimeIDsByServerFactoryID(String serverFactoryID) 
  {
    ArrayList ids = new ArrayList();
    Iterator iter = registry.webServiceRuntimes_.values().iterator();
    while (iter.hasNext())
    {
      WebServiceRuntimeInfo wsr = (WebServiceRuntimeInfo)iter.next();
      if (doesRuntimeSupportServer(wsr.getId(), serverFactoryID))
      {
        ids.add(wsr.getId());
      }
      
    }
    
    if (ids.size() > 0)
    {
      String[] runtimeIds = (String[])ids.toArray(new String[0]);
      return runtimeIds;
    }
    
    return null;    
    
    
  }
  
  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;
    }       
  }  
  
  public static String getRuntimeId(String label)
  {
    
    if (label==null || label.length()==0)
      return null;
    
    if (runtimeIdByLabel_ == null)
    {
      runtimeIdByLabel_ = new Hashtable();
      Iterator iter = registry.webServiceRuntimes_.values().iterator();
      while (iter.hasNext())
      {
        WebServiceRuntimeInfo wsr = (WebServiceRuntimeInfo)iter.next();
        runtimeIdByLabel_.put(wsr.getLabel(), wsr.getId());        
      }      
    }
    
    return (String)runtimeIdByLabel_.get(label);    
  }    

}
