/** {@inheritDoc} */
  @Override
  public void createServiceImplementationFromWSDL(
      Role role,
      java.util.List<Role> refRoles,
      ProtocolModel behaviour,
      String wsdlPath,
      String wsdlLocation,
      java.util.List<String> refWsdlPaths,
      String srcFolder,
      ResourceLocator locator)
      throws Exception {
    super.createServiceImplementationFromWSDL(
        role, refRoles, behaviour, wsdlPath, wsdlLocation, refWsdlPaths, srcFolder, locator);

    // Process the service implementation class
    javax.wsdl.Definition defn = getWSDLReader().readWSDL(wsdlPath);

    if (defn != null) {

      // Use the namespace to obtain a Java package
      String pack = JavaGeneratorUtil.getJavaPackage(defn.getTargetNamespace());

      String folder = pack.replace('.', java.io.File.separatorChar);

      @SuppressWarnings("unchecked")
      java.util.Iterator<PortType> portTypes = defn.getPortTypes().values().iterator();

      while (portTypes.hasNext()) {
        PortType portType = portTypes.next();

        java.io.File f =
            new java.io.File(
                srcFolder
                    + java.io.File.separatorChar
                    + folder
                    + java.io.File.separatorChar
                    + portType.getQName().getLocalPart()
                    + "Impl.java");

        if (f.exists()) {

          makeSwitchyardService(f, portType, srcFolder);

          addServiceReferencesToImplementation(f, role, refRoles, refWsdlPaths, srcFolder);

          addServiceBehaviour(f, role, refRoles, behaviour, srcFolder, locator);
        } else {
          logger.severe("Service file '" + f.getAbsolutePath() + "' does not exist");
        }
      }

      removeWebServiceAndClientAnnotations(wsdlPath, srcFolder);

    } else {
      logger.severe("Failed to retrieve WSDL definition '" + wsdlPath + "'");
    }
  }
  /**
   * This method scans the supplied wsdl to locate the element definition and return the Java type
   * associated with its type.
   *
   * @param wsdl The WSDL
   * @param element The element
   * @param locator The locator
   * @return The Java type, or null if not found
   */
  protected String getJavaType(javax.wsdl.Definition wsdl, QName element, ResourceLocator locator) {
    return (JavaGeneratorUtil.getJavaPackage(element.getNamespaceURI())
        + "."
        + JavaGeneratorUtil.getJavaClassName(element.getLocalPart()));

    /* Return the Element as the Java type (SAVARA-379)
     *
    java.util.List<?> elems=wsdl.getTypes().getExtensibilityElements();

    if (elems != null) {
    	for (Object obj : elems) {

    		if (obj instanceof javax.wsdl.extensions.schema.Schema) {
    			javax.wsdl.extensions.schema.Schema schema=(javax.wsdl.extensions.schema.Schema)obj;

    			for (Object value : schema.getImports().values()) {
    				if (value instanceof java.util.List<?>) {
    					for (Object si : (java.util.List<?>)value) {
    						if (si instanceof javax.wsdl.extensions.schema.SchemaImport) {
    							String javaType=JavaGeneratorUtil.getElementJavaType(element,
    									((javax.wsdl.extensions.schema.SchemaImport)si).getSchemaLocationURI(), locator);

    							if (javaType != null) {
    								return (javaType);
    							}
    						}
    					}
    				}
    			}
    		}
    	}

    	logger.warning("Failed to find java type for element '"+element+
    			"' in wsdl: "+wsdl);

    } else {
    	logger.warning("Getting java type for element '"+element+
    			"' failed as unable to find extensibility elements in wsdl: "+wsdl);
    }

    return (null);
    */
  }
  public void createServiceComposite(
      Role role,
      java.util.List<Role> refRoles,
      String wsdlPath,
      java.util.List<String> refWsdlPaths,
      String resourceFolder,
      String srcFolder)
      throws Exception {
    javax.wsdl.Definition defn = getWSDLReader().readWSDL(wsdlPath);

    if (defn != null) {

      java.io.File wsdlFile = new java.io.File(wsdlPath);

      if (!wsdlFile.exists()) {
        java.net.URL url = ClassLoader.getSystemResource(wsdlPath);

        wsdlFile = new java.io.File(url.getFile());

        if (!wsdlFile.exists()) {
          logger.severe("Failed to find WSDL file '" + wsdlPath + "'");
        }
      }

      ResourceLocator locator = new DefaultResourceLocator(wsdlFile.getParentFile());

      StringBuffer composite = new StringBuffer();
      StringBuffer transformers = new StringBuffer();
      StringBuffer component = new StringBuffer();

      String targetNamespace = defn.getTargetNamespace();
      String name = role.getName();

      composite.append("<switchyard xmlns=\"urn:switchyard-config:switchyard:1.0\"\r\n");

      // TODO: May need to add other namespaces here

      composite.append("\t\ttargetNamespace=\"" + targetNamespace + "\"\r\n");
      composite.append("\t\tname=\"" + name + "\">\r\n");

      composite.append(
          "\t<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200912\"\r\n");
      composite.append("\t\t\ttargetNamespace=\"");
      composite.append(targetNamespace);
      composite.append("\"\r\n\t\t\tname=\"");
      composite.append(name);
      composite.append("\" >\r\n");

      @SuppressWarnings("unchecked")
      java.util.Iterator<PortType> portTypes = defn.getPortTypes().values().iterator();

      while (portTypes.hasNext()) {
        PortType portType = portTypes.next();

        // Define transformers
        addPortTypeTransformers(portType, true, transformers, defn, locator, srcFolder);

        String wsdlName = wsdlPath;
        int ind = wsdlName.lastIndexOf('/');

        String wsdlLocation = wsdlName;

        if (ind != -1) {
          wsdlLocation = wsdlName.substring(ind + 1);
          wsdlName =
              wsdlName.substring(ind + 1)
                  + "#wsdl.porttype("
                  + portType.getQName().getLocalPart()
                  + ")";
        }

        composite.append(
            "\t\t<service name=\""
                + portType.getQName().getLocalPart()
                + "\" promote=\""
                + portType.getQName().getLocalPart()
                + "Component/"
                + portType.getQName().getLocalPart()
                + "\">\r\n");

        composite.append("\t\t\t<interface.wsdl interface=\"wsdl/" + wsdlName + "\" />\r\n");
        composite.append(
            "\t\t\t<binding.soap xmlns=\"urn:switchyard-component-soap:config:1.0\">\r\n");
        composite.append("\t\t\t\t<wsdl>wsdl/" + wsdlLocation + "</wsdl>\r\n");
        composite.append("\t\t\t\t<socketAddr>:18001</socketAddr>\r\n");
        composite.append("\t\t\t</binding.soap>\r\n");

        composite.append("\t\t</service>\r\n");

        String pack = JavaGeneratorUtil.getJavaPackage(defn.getTargetNamespace());

        component.append(
            "\t\t<component name=\"" + portType.getQName().getLocalPart() + "Component\">\r\n");

        component.append(
            "\t\t\t<implementation.bean xmlns=\"urn:switchyard-component-bean:config:1.0\" "
                + "class=\""
                + pack
                + "."
                + portType.getQName().getLocalPart()
                + "Impl\"/>\r\n");

        component.append(
            "\t\t\t<service name=\"" + portType.getQName().getLocalPart() + "\" >\r\n");
        component.append(
            "\t\t\t\t<interface.java interface=\""
                + pack
                + "."
                + portType.getQName().getLocalPart()
                + "\"/>\r\n");
        component.append("\t\t\t</service>\r\n");

        for (int i = 0; i < refWsdlPaths.size(); i++) {
          String refWsdlPath = refWsdlPaths.get(i);
          javax.wsdl.Definition refDefn = getWSDLReader().readWSDL(refWsdlPath);

          java.io.File refWsdlFile = new java.io.File(refWsdlPath);

          if (!refWsdlFile.exists()) {
            java.net.URL url = ClassLoader.getSystemResource(refWsdlPath);

            refWsdlFile = new java.io.File(url.getFile());

            if (!refWsdlFile.exists()) {
              logger.severe("Failed to find ref WSDL file '" + refWsdlPath + "'");
            }
          }

          ResourceLocator refLocator = new DefaultResourceLocator(refWsdlFile.getParentFile());

          if (refDefn != null) {

            @SuppressWarnings("unchecked")
            java.util.Iterator<PortType> refPortTypes = refDefn.getPortTypes().values().iterator();

            while (refPortTypes.hasNext()) {
              PortType refPortType = refPortTypes.next();

              // Define transformers
              addPortTypeTransformers(
                  refPortType, false, transformers, refDefn, refLocator, srcFolder);

              String refWsdlName = refWsdlPath;

              wsdlLocation = refWsdlName;

              ind = refWsdlName.lastIndexOf('/');
              if (ind != -1) {
                wsdlLocation = refWsdlName.substring(ind + 1);
                refWsdlName =
                    refWsdlName.substring(ind + 1)
                        + "#wsdl.porttype("
                        + refPortType.getQName().getLocalPart()
                        + ")";
              }

              composite.append(
                  "\t\t<reference name=\""
                      + refPortType.getQName().getLocalPart()
                      + "\" promote=\""
                      + portType.getQName().getLocalPart()
                      + "Component/"
                      + refPortType.getQName().getLocalPart()
                      + "\" multiplicity=\"1..1\" >\r\n");

              composite.append(
                  "\t\t\t<interface.wsdl interface=\"wsdl/" + refWsdlName + "\" />\r\n");
              composite.append(
                  "\t\t\t<binding.soap xmlns=\"urn:switchyard-component-soap:config:1.0\">\r\n");
              composite.append("\t\t\t\t<wsdl>wsdl/" + wsdlLocation + "</wsdl>\r\n");
              composite.append("\t\t\t\t<socketAddr>:18001</socketAddr>\r\n");
              composite.append("\t\t\t</binding.soap>\r\n");
              composite.append("\t\t</reference>\r\n");

              String refPack = JavaGeneratorUtil.getJavaPackage(refDefn.getTargetNamespace());

              component.append(
                  "\t\t\t<reference name=\"" + refPortType.getQName().getLocalPart() + "\" >\r\n");
              component.append(
                  "\t\t\t\t<interface.java interface=\""
                      + refPack
                      + "."
                      + refPortType.getQName().getLocalPart()
                      + "\"/>\r\n");
              component.append("\t\t\t</reference>\r\n");
            }
          }
        }

        component.append("\t\t</component>\r\n");

        composite.append(component.toString());
      }

      composite.append("\t</composite>\r\n");

      if (transformers.length() > 0) {
        composite.append("\t<transforms xmlns:xform=\"urn:switchyard-config:transform:1.0\">\r\n");
        composite.append(transformers.toString());
        composite.append("\t</transforms>\r\n");
      }

      composite.append("</switchyard>\r\n");

      java.io.FileOutputStream fos =
          new java.io.FileOutputStream(
              resourceFolder + java.io.File.separatorChar + "switchyard.xml");

      fos.write(composite.toString().getBytes());

      fos.close();
    }
  }
  protected void addPortTypeTransformers(
      PortType portType,
      boolean provider,
      StringBuffer transformers,
      javax.wsdl.Definition wsdl,
      ResourceLocator locator,
      String srcFolder) {
    String attr1 = (provider ? "from" : "to");
    String attr2 = (provider ? "to" : "from");

    for (Object opobj : portType.getOperations()) {
      if (opobj instanceof javax.wsdl.Operation) {
        javax.wsdl.Operation op = (javax.wsdl.Operation) opobj;

        String qname = "";
        String javaType = "";
        String javaPackage = "";

        javax.wsdl.Part p =
            (javax.wsdl.Part) op.getInput().getMessage().getParts().values().iterator().next();
        qname = p.getElementName().toString();

        javaType = getJavaType(wsdl, p.getElementName(), locator);

        if (javaType != null) {
          int ind = javaType.lastIndexOf('.');
          if (ind != -1) {
            javaPackage = javaType.substring(0, ind);
          }
        }

        transformers.append("\t\t<xform:transform.jaxb\r\n");
        transformers.append("\t\t\t" + attr1 + "=\"" + qname + "\"\r\n");
        transformers.append("\t\t\t" + attr2 + "=\"java:" + javaType + "\"\r\n");
        transformers.append("\t\t\tcontextPath=\"" + javaPackage + "\"/>\r\n");

        if (op.getOutput() != null) {
          p = (javax.wsdl.Part) op.getOutput().getMessage().getParts().values().iterator().next();
          qname = p.getElementName().toString();

          javaType = getJavaType(wsdl, p.getElementName(), locator);

          if (javaType != null) {
            int ind = javaType.lastIndexOf('.');
            if (ind != -1) {
              javaPackage = javaType.substring(0, ind);
            }
          }

          transformers.append("\t\t<xform:transform.jaxb\r\n");
          transformers.append("\t\t\t" + attr2 + "=\"" + qname + "\"\r\n");
          transformers.append("\t\t\t" + attr1 + "=\"java:" + javaType + "\"\r\n");
          transformers.append("\t\t\tcontextPath=\"" + javaPackage + "\"/>\r\n");
        }

        for (Object faultObj : op.getFaults().values()) {
          if (faultObj instanceof javax.wsdl.Fault) {
            javax.wsdl.Fault fault = (javax.wsdl.Fault) faultObj;

            p = (javax.wsdl.Part) fault.getMessage().getParts().values().iterator().next();
            qname = p.getElementName().toString();

            String javaFaultType = getJavaType(wsdl, p.getElementName(), locator);

            String pack =
                JavaGeneratorUtil.getJavaPackage(fault.getMessage().getQName().getNamespaceURI());

            javaType =
                pack
                    + "."
                    + JavaGeneratorUtil.getJavaClassName(
                        fault.getMessage().getQName().getLocalPart());

            String transformerClassName = getFaultTransformerClassName(javaType, provider);

            String faultTransClass = pack + "." + transformerClassName;

            transformers.append("\t\t<xform:transform.java class=\"" + faultTransClass + "\"\r\n");
            transformers.append("\t\t\t" + attr2 + "=\"" + qname + "\"\r\n");
            transformers.append("\t\t\t" + attr1 + "=\"java:" + javaType + "\"/>\r\n");

            // Create transformer class
            String folder = pack.replace('.', java.io.File.separatorChar);

            String javaFile = folder + java.io.File.separator + transformerClassName;

            java.io.File jFile =
                new java.io.File(srcFolder + java.io.File.separator + javaFile + ".java");

            jFile.getParentFile().mkdirs();

            try {
              java.io.FileOutputStream fos = new java.io.FileOutputStream(jFile);

              generateFaultTransformer(qname, javaType, javaFaultType, provider, fos);

              fos.close();
            } catch (Exception e) {
              logger.log(Level.SEVERE, "Failed to create fault transformer", e);
            }
          }
        }
      }
    }
  }
  protected void addServiceReferencesToImplementation(
      java.io.File implFile,
      Role role,
      java.util.List<Role> refRoles,
      java.util.List<String> refWsdlPaths,
      String srcFolder)
      throws Exception {

    // Check that the number of reference roles and wsdl paths are the same
    if (refRoles.size() != refWsdlPaths.size()) {
      throw new IllegalArgumentException(
          "The number of reference roles and wsdl paths are not consistent");
    }

    java.io.FileInputStream fis = new java.io.FileInputStream(implFile);

    byte[] b = new byte[fis.available()];
    fis.read(b);

    StringBuffer text = new StringBuffer();
    text.append(new String(b));

    fis.close();

    int index = text.indexOf("private static final Logger");

    if (index != -1) {

      for (int i = 0; i < refRoles.size(); i++) {
        javax.wsdl.Definition refDefn = getWSDLReader().readWSDL(refWsdlPaths.get(i));

        if (refDefn != null) {

          // Use the namespace to obtain a Java package
          String refPack = JavaGeneratorUtil.getJavaPackage(refDefn.getTargetNamespace());

          @SuppressWarnings("unchecked")
          java.util.Iterator<PortType> refPortTypes = refDefn.getPortTypes().values().iterator();
          int refPortCount = 1;

          while (refPortTypes.hasNext()) {
            PortType refPortType = refPortTypes.next();
            String name = JavaBehaviourGenerator.getVariableName(refRoles.get(i).getName());

            if (refDefn.getPortTypes().size() > 1) {
              name += refPortCount;
            }

            text.insert(
                index,
                "@javax.inject.Inject @org.switchyard.component.bean.Reference\r\n    "
                    + refPack
                    + "."
                    + refPortType.getQName().getLocalPart()
                    + " _"
                    + name
                    + ";\r\n\r\n    ");
          }
        }
      }

      java.io.FileOutputStream fos = new java.io.FileOutputStream(implFile);

      fos.write(text.toString().getBytes());

      fos.close();
    } else {
      logger.severe(
          "Service implementation file '"
              + implFile.getAbsolutePath()
              + "' does not have 'private static final Logger' as location to insert references");
    }
  }