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

package org.eclipse.wst.ws.internal.explorer.platform.uddi.actions;

import org.eclipse.wst.ws.internal.explorer.platform.datamodel.*;
import org.eclipse.wst.ws.internal.explorer.platform.perspective.*;
import org.eclipse.wst.ws.internal.explorer.platform.uddi.constants.*;
import org.eclipse.wst.ws.internal.explorer.platform.uddi.datamodel.*;
import org.eclipse.wst.ws.internal.explorer.platform.uddi.perspective.*;
import org.eclipse.wst.ws.internal.explorer.platform.uddi.util.Uddi4jHelper;
import org.eclipse.wst.ws.internal.explorer.platform.util.*;

import org.uddi4j.client.UDDIProxy;
import org.uddi4j.datatype.service.BusinessService;
import org.uddi4j.datatype.business.BusinessEntity;
import org.uddi4j.datatype.tmodel.TModel;
import org.uddi4j.datatype.*;
import org.uddi4j.response.*;
import org.uddi4j.transport.TransportException;
import org.uddi4j.util.*;
import org.uddi4j.UDDIException;

import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import java.util.*;
import java.net.*;

public class UpdateServiceAction extends UpdateAction
{
  private boolean isUpdate_;
  public UpdateServiceAction(Controller controller)
  {
    super(controller,true);
    isUpdate_ = true;
  }

  protected boolean processOthers(MultipartFormDataParser parser,FormToolPropertiesInterface formToolPI) throws MultipartFormDataException
  {
    String uuidBusinessKey = parser.getParameter(UDDIActionInputs.QUERY_INPUT_UUID_BUSINESS_KEY);
    String uuidServiceKey = parser.getParameter(UDDIActionInputs.QUERY_INPUT_UUID_SERVICE_KEY);
    String wsdlURLModifiedState = parser.getParameter(UDDIActionInputs.WSDL_URL_MODIFIED);
    String wsdlURL = parser.getParameter(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_WSDL_URL);
    String[] nameModifiedStates = parser.getParameterValues(UDDIActionInputs.NAME_MODIFIED);
    String[] nameViewIds = parser.getParameterValues(UDDIActionInputs.NAME_VIEWID);
    String[] nameLanguages = parser.getParameterValues(UDDIActionInputs.QUERY_INPUT_ADVANCED_NAME_LANGUAGE);
    String[] names = parser.getParameterValues(UDDIActionInputs.QUERY_INPUT_ADVANCED_NAME);
    String[] descriptionModifiedStates = parser.getParameterValues(UDDIActionInputs.DESCRIPTION_MODIFIED);
    String[] descriptionViewIds = parser.getParameterValues(UDDIActionInputs.DESCRIPTION_VIEWID);
    String[] descriptionLanguages = parser.getParameterValues(UDDIActionInputs.QUERY_INPUT_ADVANCED_DESCRIPTION_LANGUAGE);
    String[] descriptions = parser.getParameterValues(UDDIActionInputs.QUERY_INPUT_ADVANCED_DESCRIPTION);
    String[] catModifiedStates = parser.getParameterValues(UDDIActionInputs.CATEGORY_MODIFIED);
    String[] catViewIds = parser.getParameterValues(UDDIActionInputs.CATEGORY_VIEWID);
    String[] catTypes = parser.getParameterValues(UDDIActionInputs.QUERY_INPUT_ADVANCED_CATEGORY_TYPE);
    String[] catKeyNames = parser.getParameterValues(UDDIActionInputs.QUERY_INPUT_ADVANCED_CATEGORY_KEY_NAME);
    String[] catKeyValues = parser.getParameterValues(UDDIActionInputs.QUERY_INPUT_ADVANCED_CATEGORY_KEY_VALUE);

    boolean inputsValid = true;
    UDDIPerspective uddiPerspective = controller_.getUDDIPerspective();
    MessageQueue messageQueue = uddiPerspective.getMessageQueue();

    if (uuidBusinessKey != null)
      propertyTable_.put(UDDIActionInputs.QUERY_INPUT_UUID_BUSINESS_KEY,uuidBusinessKey);

    if (uuidServiceKey != null)
      propertyTable_.put(UDDIActionInputs.QUERY_INPUT_UUID_SERVICE_KEY,uuidServiceKey);

    if (wsdlURLModifiedState != null && wsdlURL != null)
    {
      ListElement wsdlURLListElement = (ListElement)formToolPI.getProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_WSDL_URL);
      boolean isModified = Boolean.valueOf(wsdlURLModifiedState).booleanValue();
      if (isModified)
        wsdlURLListElement = new ListElement(wsdlURL);
      else
        wsdlURL = (String)wsdlURLListElement.getObject();
      propertyTable_.put(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_WSDL_URL,wsdlURLListElement);
      if (!Validator.validateURL(wsdlURL))
      {
        inputsValid = false;
        formToolPI.flagError(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_WSDL_URL);
        messageQueue.addMessage(uddiPerspective.getMessage("MSG_ERROR_INVALID_WSDL_URL"));
      }
    }
    else
      removeProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_WSDL_URL);

    Hashtable languageHash = new Hashtable();
    if (nameModifiedStates != null && nameViewIds != null && nameLanguages != null && names != null)
    {
      Vector oldNameListElementVector = (Vector)formToolPI.getProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_NAMES);
      Vector newNameListElementVector = new Vector();
      // UDDI's save API (Appendix C of the UDDI V2 Programmers API Specification) requires the following:
      // 1) Only the first row can have a blank language.
      // 2) Only 1 name per language.
      String[] parameters = new String[2];
      parameters[0] = uddiPerspective.getMessage("FORM_LABEL_NAME");
      for (int i=0;i<names.length;i++)
      {
        parameters[1] = String.valueOf(i+1);
        Name uddi4jName;
        if (nameLanguages[i].length() > 0)
          uddi4jName = new Name(names[i],nameLanguages[i]);
        else
        {
          uddi4jName = new Name(names[i]);
          if (i != 0)
          {
            inputsValid = false;
            formToolPI.flagRowError(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_NAMES,i);
            messageQueue.addMessage(uddiPerspective.getMessage("MSG_ERROR_ROW_BLANK_LANGUAGE",parameters));
          }
        }
        if (languageHash.get(nameLanguages[i]) != null)
        {
          inputsValid = false;
          formToolPI.flagRowError(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_NAMES,i);
          messageQueue.addMessage(uddiPerspective.getMessage("MSG_ERROR_ROW_DUPLICATE_LANGUAGE",parameters));
        }
        else
          languageHash.put(nameLanguages[i],Boolean.TRUE);
        if (!Validator.validateString(names[i]))
        {
          inputsValid = false;
          formToolPI.flagRowError(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_NAMES,i);
          messageQueue.addMessage(uddiPerspective.getMessage("MSG_ERROR_ROW_INVALID_TEXT",parameters));
        }

        int nameViewId = Integer.parseInt(nameViewIds[i]);
        boolean isModified = Boolean.valueOf(nameModifiedStates[i]).booleanValue();

        if (nameViewId == -1 || isModified)
          newNameListElementVector.addElement(new ListElement(uddi4jName));
        else
          newNameListElementVector.addElement(oldNameListElementVector.elementAt(nameViewId));
      }
      reindexListElementVector(newNameListElementVector);
      propertyTable_.put(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_NAMES,newNameListElementVector);
    }
    else
    {
      removeProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_NAMES);
      inputsValid = false;
      formToolPI.flagError(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_NAMES);
      messageQueue.addMessage(uddiPerspective.getMessage("MSG_ERROR_NO_NAMES"));
    }

    if (descriptionModifiedStates != null && descriptionViewIds != null && descriptionLanguages != null && descriptions != null)
    {
      Vector oldDescriptionListElementVector = (Vector)formToolPI.getProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_DESCRIPTIONS);
      Vector newDescriptionListElementVector = new Vector();
      String[] parameters = new String[2];
      parameters[0] = uddiPerspective.getMessage("FORM_LABEL_DESCRIPTION");
      languageHash.clear();
      for (int i=0;i<descriptions.length;i++)
      {
        parameters[1] = String.valueOf(i+1);
        Description uddi4jDescription;
        if (descriptionLanguages[i].length() > 0)
          uddi4jDescription = new Description(descriptions[i],descriptionLanguages[i]);
        else
        {
          uddi4jDescription = new Description(descriptions[i]);
          if (i != 0)
          {
            inputsValid = false;
            formToolPI.flagRowError(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_DESCRIPTIONS,i);
            messageQueue.addMessage(uddiPerspective.getMessage("MSG_ERROR_ROW_BLANK_LANGUAGE",parameters));
          }
        }
        if (languageHash.get(descriptionLanguages[i]) != null)
        {
          inputsValid = false;
          formToolPI.flagRowError(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_DESCRIPTIONS,i);
          messageQueue.addMessage(uddiPerspective.getMessage("MSG_ERROR_ROW_DUPLICATE_LANGUAGE",parameters));
        }
        else
          languageHash.put(descriptionLanguages[i],Boolean.TRUE);
        if (!Validator.validateString(descriptions[i]))
        {
          inputsValid = false;
          formToolPI.flagRowError(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_DESCRIPTIONS,i);
          messageQueue.addMessage(uddiPerspective.getMessage("MSG_ERROR_ROW_INVALID_TEXT",parameters));
        }

        int descriptionViewId = Integer.parseInt(descriptionViewIds[i]);
        boolean isModified = Boolean.valueOf(descriptionModifiedStates[i]).booleanValue();

        if (descriptionViewId == -1 || isModified)
          newDescriptionListElementVector.addElement(new ListElement(uddi4jDescription));
        else
          newDescriptionListElementVector.addElement(oldDescriptionListElementVector.elementAt(descriptionViewId));
      }
      reindexListElementVector(newDescriptionListElementVector);
      propertyTable_.put(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_DESCRIPTIONS,newDescriptionListElementVector);
    }
    else
      removeProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_DESCRIPTIONS);

    if (catModifiedStates != null && catViewIds != null && catTypes != null && catKeyNames != null && catKeyValues != null)
    {
      Vector oldCatListElementVector = (Vector)formToolPI.getProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_CATEGORIES);
      Vector newCatListElementVector = new Vector();
      for (int i=0;i<catTypes.length;i++)
      {
        KeyedReference kr = new KeyedReference(catKeyNames[i],catKeyValues[i],catTypes[i]);
        int catViewId = Integer.parseInt(catViewIds[i]);
        boolean isModified = Boolean.valueOf(catModifiedStates[i]).booleanValue();
        if (catViewId == -1 || isModified)
          newCatListElementVector.addElement(new ListElement(kr));
        else
          newCatListElementVector.addElement(oldCatListElementVector.elementAt(catViewId));
      }
      reindexListElementVector(newCatListElementVector);
      propertyTable_.put(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_CATEGORIES,newCatListElementVector);
    }
    else
      removeProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_CATEGORIES);
    return inputsValid;
  }

  public final boolean refreshBusinessFromRegistry()
  {
    UDDIPerspective uddiPerspective = controller_.getUDDIPerspective();
    MessageQueue messageQueue = uddiPerspective.getMessageQueue();
    try
    {
      String uuidBusinessKey = (String)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_UUID_BUSINESS_KEY);
      RegistryElement regElement = (RegistryElement)regNode_.getTreeElement();
      UDDIProxy proxy = regElement.getProxy();
      Vector beVector = proxy.get_businessDetail(uuidBusinessKey).getBusinessEntityVector();
      BusinessEntity be;
      if (beVector.size() > 0)
        be = (BusinessEntity)beVector.get(0);
      else
        be = null;
      if (be != null)
      {
        propertyTable_.put(UDDIActionInputs.LATEST_BUSINESS,be);
        return true;
      }
    }
    catch (TransportException e)
    {
      // Feedback via Javascript popups.
    }
    catch (UDDIException e)
    {
      // Feedback via Javascript popups.
    }
    return false;
  }
  
  public final boolean refreshFromRegistry()
  {
    UDDIPerspective uddiPerspective = controller_.getUDDIPerspective();
    try
    {
      String uuidServiceKey = (String)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_UUID_SERVICE_KEY);
      RegistryElement regElement = (RegistryElement)regNode_.getTreeElement();
      UDDIProxy proxy = regElement.getProxy();
      ServiceDetail serviceDetail = proxy.get_serviceDetail(uuidServiceKey);
      Vector businessServiceVector = serviceDetail.getBusinessServiceVector();
      if (businessServiceVector.size() > 0)
      {
        propertyTable_.put(UDDIActionInputs.LATEST_OBJECT,businessServiceVector.elementAt(0));
        return true;
      }
    }
    catch (UDDIException e)
    {
      // Feedback via Javascript popups.
    }
    catch (TransportException e)
    {
      // Feedback via Javascript popups.
    }
    isUpdate_ = false;
    return false;
  }
  
  public final RegPublishTool setupRegPublishTool()
  {
    // Prepare for re-publishing a now-stale service whose business has also been eliminated.
    RegPublishTool regPublishTool = regNode_.getRegPublishTool();
    regPublishTool.setProperty(UDDIActionInputs.SUBQUERY_KEY,"");
    regPublishTool.setProperty(UDDIActionInputs.QUERY_ITEM,String.valueOf(UDDIActionInputs.QUERY_ITEM_SERVICES));
    regPublishTool.setProperty(UDDIActionInputs.QUERY_STYLE_SERVICES,String.valueOf(UDDIActionInputs.QUERY_STYLE_ADVANCED));
    
    regPublishTool.setProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_WSDL_URL,propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_WSDL_URL));
    
    Vector nameListElementVector = (Vector)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_NAMES);
    Vector descriptionListElementVector = (Vector)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_DESCRIPTIONS);
    Vector catListElementVector = (Vector)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_CATEGORIES);
    
    Vector nameVector = new Vector();
    for (int i=0;i<nameListElementVector.size();i++)
    {
      ListElement listElement = (ListElement)nameListElementVector.elementAt(i);
      Name name = (Name)listElement.getObject();
      nameVector.addElement(name);
    }
    
    Vector descriptionVector = null;
    if (descriptionListElementVector != null)
    {
      descriptionVector = new Vector();
      for (int i=0;i<descriptionListElementVector.size();i++)
      {
        ListElement listElement = (ListElement)descriptionListElementVector.elementAt(i);
        Description description = (Description)listElement.getObject();
        descriptionVector.addElement(description);
      }
    }
    else
      regPublishTool.removeProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_DESCRIPTIONS);
    
    CategoryBag catBag = null;
    if (catListElementVector != null)
    {
      catBag = new CategoryBag();
      for (int i=0;i<catListElementVector.size();i++)
      {
        ListElement listElement = (ListElement)catListElementVector.elementAt(i);
        KeyedReference kr = (KeyedReference)listElement.getObject();
        catBag.add(kr);
      }
    }
    else
      regPublishTool.removeProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_CATEGORIES);
    
    regPublishTool.setProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_NAMES,nameVector);
    if (descriptionVector != null)
      regPublishTool.setProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_DESCRIPTIONS,descriptionVector);
    if (catBag != null)
      regPublishTool.setProperty(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_CATEGORIES,catBag);
    return regPublishTool;
  }

  public final boolean run()
  {
    UDDIPerspective uddiPerspective = controller_.getUDDIPerspective();
    MessageQueue messageQueue = uddiPerspective.getMessageQueue();
    RegistryElement regElement = (RegistryElement)regNode_.getTreeElement();    
    try
    {
      BusinessEntity be = (BusinessEntity)propertyTable_.get(UDDIActionInputs.LATEST_BUSINESS);
      String publishURL = (String)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_PUBLISH_URL);
      String userId = (String)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_USERID);
      String password = (String)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_PASSWORD);
      String uuidServiceKey = (String)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_UUID_SERVICE_KEY);
      ListElement wsdlURLListElement = (ListElement)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_WSDL_URL);
      Vector nameListElementVector = (Vector)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_NAMES);
      Vector descriptionListElementVector = (Vector)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_DESCRIPTIONS);
      Vector catListElementVector = (Vector)propertyTable_.get(UDDIActionInputs.QUERY_INPUT_ADVANCED_SERVICE_CATEGORIES);

      String wsdlURL = (String)wsdlURLListElement.getObject();
            
      Vector nameVector = new Vector();
      for (int i=0;i<nameListElementVector.size();i++)
      {
        ListElement listElement = (ListElement)nameListElementVector.elementAt(i);
        Name name = (Name)listElement.getObject();
        nameVector.addElement(name);
      }

      Vector descriptionVector = null;
      if (descriptionListElementVector != null)
      {
        descriptionVector = new Vector();
        for (int i=0;i<descriptionListElementVector.size();i++)
        {
          ListElement listElement = (ListElement)descriptionListElementVector.elementAt(i);
          Description description = (Description)listElement.getObject();
          descriptionVector.addElement(description);
        }
      }

      CategoryBag catBag = null;
      if (catListElementVector != null)
      {
        catBag = new CategoryBag();
        for (int i=0;i<catListElementVector.size();i++)
        {
          ListElement listElement = (ListElement)catListElementVector.elementAt(i);
          KeyedReference kr = (KeyedReference)listElement.getObject();
          catBag.add(kr);
        }
      }

      if (!regElement.isLoggedIn())
      	regElement.performLogin(publishURL,userId,password);
      UDDIProxy proxy = regElement.getProxy();

      // Note: The JSP will prevent this routine from executing if be is null.
      Uddi4jHelper uddi4jHelper = new Uddi4jHelper();
      Definition def = uddi4jHelper.getWSDLDefinition(wsdlURL);
      
      // Publish/update the service interfaces first.
      RegPublishServiceInterfaceSimpleAction regPublishSIAction = new RegPublishServiceInterfaceSimpleAction(controller_);
      int currentNodeId = getSelectedNavigatorNode().getNodeId();
      NodeManager nodeManager = regNode_.getNodeManager();

      Hashtable tModelsTable = new Hashtable();
      TModel[] tModels = null;
      if (uddi4jHelper.isMonolithicWSDL(def))
      {
      	tModels = new TModel[1];
      	tModels[0] = uddi4jHelper.newTModel(wsdlURL, def);
      }
      else
      {
      	String[] imports = uddi4jHelper.getImports(def, wsdlURL);
      	tModels = new TModel[imports.length];
      	for (int i = 0; i < tModels.length; i++)
      	  tModels[i] = uddi4jHelper.newTModel(imports[i]);
      }
      
      if (tModels != null)
      {
      	for (int i=0;i<tModels.length;i++)
      	{
      	  boolean inputsValid = regPublishSIAction.populatePropertyTable(uddi4jHelper.getWSDL(tModels[i]), tModels[i]);
      	  if (inputsValid)
      	  {
      	    regPublishSIAction.run();
      	    Object savedTModel = regPublishSIAction.getPropertyTable().get(UDDIActionInputs.QUERY_OUTPUT_SAVED_TMODEL);
      	    if (savedTModel != null)
            {
      	      tModelsTable.put(((TModel)savedTModel).getNameString(), savedTModel);
      	    }
            // Reselect the current node.
      	    nodeManager.setSelectedNodeId(currentNodeId);
          }
      	}
      }
      
      BusinessService busService = uddi4jHelper.newBusinessService(wsdlURL, def, tModelsTable);
      if (isUpdate_)
        busService.setServiceKey(uuidServiceKey);
      busService.setBusinessKey(be.getBusinessKey());
      busService.setNameVector(nameVector);
      busService.setDescriptionVector(descriptionVector);
      busService.setCategoryBag(catBag);
      regElement.handlePreInvocation(busService);      
      Vector bsVector = new Vector();
      bsVector.add(busService);
      busService = (BusinessService)proxy.save_service(regElement.getAuthInfoString(), bsVector).getBusinessServiceVector().get(0);
      refreshNode(busService);
      if (isUpdate_)
        messageQueue.addMessage(uddiPerspective.getMessage("MSG_INFO_SERVICE_UPDATED",busService.getDefaultNameString()));
      else
        messageQueue.addMessage(uddiPerspective.getMessage("MSG_INFO_SERVICE_PUBLISHED",busService.getDefaultNameString()));
      return true;
    }
    catch (WSDLException e)
    {
      handleUnexpectedException(uddiPerspective,messageQueue,"WSDLException",e);
    }
    catch (TransportException e)
    {
      handleUnexpectedException(uddiPerspective,messageQueue,"TransportException",e);
    }
    catch (UDDIException e)
    {
      messageQueue.addMessage(uddiPerspective.getController().getMessage("MSG_ERROR_UNEXPECTED"));
      messageQueue.addMessage("UDDIException");
      messageQueue.addMessage(e.toString());
    }
    catch (MalformedURLException e)
    {
      handleUnexpectedException(uddiPerspective,messageQueue,"MalformedURLException",e);
    }    
    return false;
  }
}
