//
// DataMapWebService.java - Ask a Web Service to map values for us
//
// Use JAX-WS to query a fixed web service.
//

package nyangau.jmsadapter;

//...simports:0:
import java.util.Set;
import java.util.Map;
import java.util.List;
import java.util.LinkedList;
import java.util.ListIterator;
import java.net.URL;
import java.net.MalformedURLException;
import javax.xml.namespace.QName;
import javax.xml.ws.WebServiceException;
import nyangau.jmsadapter.mapclient.MapperService;
import nyangau.jmsadapter.mapclient.Mapper;
import nyangau.jmsadapter.mapclient.ArrayOfString;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
//...e

public class DataMapWebService extends DataMap
  {
  protected Mapper mapper;
  protected String mapping;
  protected int retryCount;
  protected int retryDelay;
  protected String retryFail;
//...sDataMapWebService:2:
public DataMapWebService(Node eDataMap)
  throws FlowProcessorException
  {
  super(eDataMap);
  NamedNodeMap nnmDataMap = eDataMap.getAttributes();
  Node aWsdl = nnmDataMap.getNamedItem("wsdl");
  if ( aWsdl == null )
    throw new FlowProcessorException("unexpected missing wsdl attribute in data map "+name+", bad jmsadapter.xsd?");
  String wsdl = aWsdl.getNodeValue();
  Node aNs = nnmDataMap.getNamedItem("namespace");
  String ns = ( aNs != null ) ? aNs.getNodeValue() : "http://www.nyangau.org/jmsadapter/mapper";
  Node aService = nnmDataMap.getNamedItem("service");
  String service = ( aService != null ) ? aService.getNodeValue() : "MapperService";
  Node aPort = nnmDataMap.getNamedItem("port");
  String port = ( aPort != null ) ? aPort.getNodeValue() : "MapperPort";
  Node aMapping = nnmDataMap.getNamedItem("mapping");
  mapping = ( aMapping != null ) ? aMapping.getNodeValue() : "";
  try
    {
    MapperService ms = new MapperService(new URL(wsdl), new QName(ns, service));
    mapper = ms.getPort(new QName(ns, port), Mapper.class);
    }
  catch ( MalformedURLException e )
    {
    throw new FlowProcessorException("bad WSDL URL in data map "+name, e);
    }
  catch ( WebServiceException e )
    {
    throw new FlowProcessorException("WebServiceException in data map "+name, e);
    }
  Node aRetryCount = nnmDataMap.getNamedItem("retrycount");
  retryCount = ( aRetryCount != null ) ? Integer.parseInt(aRetryCount.getNodeValue()) : 0;
  Node aRetryDelay = nnmDataMap.getNamedItem("retrydelay");
  retryDelay = ( aRetryDelay != null ) ? Integer.parseInt(aRetryDelay.getNodeValue()) : 0;
  Node aRetryFail = nnmDataMap.getNamedItem("retryfail");
  retryFail = ( aRetryFail != null ) ? aRetryFail.getNodeValue() : "throw";
  }
//...e
//...smap:2:
public void map(Set<String> unmapped, Map<String,String> mapped)
  throws FlowProcessorException
  {
  ArrayOfString unmappedL = new ArrayOfString();
  for ( String u : unmapped )
    unmappedL.getString().add(u);
  ArrayOfString mappedL;
  for ( int r = 0;; r++ )
    try
      {
      mappedL = mapper.map(mapping, unmappedL);
      break;
      }
    catch ( WebServiceException e )
      {
      if ( r == retryCount )
        {
        if ( retryFail.equals("throw") )
          throw new FlowProcessorException("error calling web service in data map "+name+" ("+retryCount+" retries)", e);
        else
          {
          mappedL = new ArrayOfString();
          break;
          }
        }
      try
        {
        Thread.sleep(retryDelay);
        }
      catch ( InterruptedException ei )
        {
        }
      }
  if ( mappedL.getString().size() == 1 )
    throw new FlowProcessorException("web service rejected mapping request in data map "+name+": "+mappedL.getString().get(0));
  ListIterator<String> li = mappedL.getString().listIterator();
  while ( li.hasNext() )
    {
    String k = li.next();
    if ( !li.hasNext() )
      throw new FlowProcessorException("web service didn't reply with one string or an even number in data map "+name);
    String v = li.next();
    unmapped.remove(k);
    mapped.put(k, v);
    }
  }
//...e
  }
