package org.jboss.soa.bpel.runtime.ws;

import java.io.File;
import java.net.URL;
import java.util.List;

import javax.wsdl.Definition;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.iapi.ContextException;
import org.apache.ode.bpel.iapi.ProcessConf;
import org.jboss.soa.bpel.runtime.engine.ode.BPELEngineImpl;

public class WSDLHelper {
	
	 protected final Log log = LogFactory.getLog(getClass());

	
	 public WSDLReference createWSDLReference(BPELEngineImpl engine, QName processId, QName serviceName, String portName)
	  {
	    File targetWSDLFile = findWSDLFile(engine, processId, serviceName, portName);
	    Definition wsdlDefinition = getWSDLDefinition(engine, processId, serviceName);
	    return new WSDLReference(wsdlDefinition, targetWSDLFile.toURI());
	  }

	  private File findWSDLFile(BPELEngineImpl engine, QName processId, QName serviceName, String portName)
	  {
	    ProcessConf pconf = engine._store.getProcessConfiguration(processId);
	    List<File> files = pconf.getFiles();
	    File targetWsdlFile = null;
	    for(File f : files)
	    {
	      if(f.getName().endsWith(".wsdl"))
	      {
	        try
	        {
	          WSDLReader wsdlReader = WSDLFactory.newInstance().newWSDLReader();
	          Definition def = wsdlReader.readWSDL(f.toURL().toExternalForm());
	          URL url = new WSDLParser(def).getServiceLocationURL(serviceName, portName);
	          if(url!=null)
	          {
	            targetWsdlFile = f;
	            log.debug("Matching "+processId + " to WSDL file "+targetWsdlFile);
	            break;
	          }

	        }
	        catch (Exception e)
	        {
	          throw new RuntimeException(e);
	        }
	      }
	    }

	    if(null==targetWsdlFile)
	      throw new ContextException("Unable to find target WSDL file for "+ serviceName);

	    return targetWsdlFile;
	  }
	  
	  private Definition getWSDLDefinition(BPELEngineImpl engine, QName processId, QName serviceName)
	  {
	    ProcessConf pconf = engine._store.getProcessConfiguration(processId);
	    Definition wsdl = pconf.getDefinitionForService(serviceName);
	    if (wsdl == null)
	      throw new ContextException("Unable to access WSDL definition to activate MyRole endpoint for service " + serviceName
	          + " on process "+ processId);

	    return wsdl;
	  }
}
