/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2010, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.test.ws.jaxws.jbws3041;

import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.EndpointReference;
import javax.xml.ws.Holder;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.soap.AddressingFeature;
import javax.xml.ws.wsaddressing.W3CEndpointReference;

import junit.framework.Test;

import org.jboss.wsf.common.DOMUtils;
import org.jboss.wsf.test.JBossWSTest;
import org.jboss.wsf.test.JBossWSTestSetup;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * [JBWS-3041] support for EPRs specified in WSDL.
 *
 * @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a>
 */
public class JBWS3041TestCase extends JBossWSTest
{

   private static final WebServiceFeature[] ADDRESSING_ENABLED = { new AddressingFeature(true) };
   private EPRInWsdlTestService service;
   private W3CEndpointReference epr;
   private Test1 port;

   public static Test suite()
   {
      return new JBossWSTestSetup(JBWS3041TestCase.class, "jaxws-jbws3041.war");
   }

   public void setUp() throws Exception
   {
      if (this.port == null)
      {
         URL wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-jbws3041/Endpoint?wsdl");
         this.service = new EPRInWsdlTestService(wsdlURL);
         this.port = (Test1) this.service.getPort(Test1.class, ADDRESSING_ENABLED);
         final BindingProvider bp = (BindingProvider) this.port;
         this.epr = (W3CEndpointReference) bp.getEndpointReference();
      }
   }

   public void testGetEPRAndVerifyMetaDataAndRefParamsTest1() throws Exception
   {
      final Holder<DataType> holder = this.newHolder("GetEPRAndVerifyMetaDataAndRefParamsTest1");

      this.port.testOperation(holder);
   }

   public void testGetPortAndVerifyRefParamsAreSentTest1() throws Exception
   {
      final Holder<DataType> holder = this.newHolder("GetPortAndVerifyRefParamsAreSentTest1");
      final Test1 testPort = (Test1) this.service.getPort(Test1.class, ADDRESSING_ENABLED);

      testPort.testOperation(holder);
   }

   public void testGetPortAndVerifyRefParamsAreSentTest2() throws Exception
   {
      final Holder<DataType> holder = this.newHolder("GetPortAndVerifyRefParamsAreSentTest2");
      final Test1 testPort = (Test1) this.service.getPort(this.epr, Test1.class, ADDRESSING_ENABLED);

      testPort.testOperation(holder);
   }

   public void testGetPortAndVerifyModifiedRefParamsAreSentTest3() throws Exception
   {
      final Holder<DataType> holder = this.newHolder("GetPortAndVerifyModifiedRefParamsAreSentTest3");
      final W3CEndpointReference epr = this.newModifiedEPR();
      final Test1 testPort = (Test1) this.service.getPort(epr, Test1.class, ADDRESSING_ENABLED);
      
      testPort.testOperation(holder);
   }
   
   private W3CEndpointReference newModifiedEPR()
   {
      final DOMResult temp = new DOMResult();
      this.epr.writeTo(temp);
      final Node eprElement = temp.getNode();
      this.changeNodeValue(eprElement, new QName("http://eprinwsdltestservice.org/myns1", "MyParam1"), "MyValue1");
      this.changeNodeValue(eprElement, new QName("http://eprinwsdltestservice.org/myns2", "MyParam2"), "MyValue2");
      
      return (W3CEndpointReference) EndpointReference.readFrom(new DOMSource(eprElement));
   }

   private Holder<DataType> newHolder(final String param)
   {
      final DataType datatype = new DataType();
      datatype.setParam(param);
      final Holder<DataType> data = new Holder<DataType>();
      data.value = datatype;

      return data;
   }

   private void changeNodeValue(Node eprElement, QName paramQName, String newValue)
   {
      final Element paramElement = DOMUtils.getFirstChildElement(eprElement, paramQName, true);

      if (paramElement != null)
      {
         NodeList nl = paramElement.getChildNodes();
         for (int i = 0; i < nl.getLength(); i++)
         {
            Node node = nl.item(i);
            if (node.getNodeType() == Node.TEXT_NODE)
            {
               node.setNodeValue(newValue);
               break;
            }
         }
      }
   }
}
