content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.camel.quarkus.component.cxf.soap.server.it;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.StringReader;
  import java.nio.charset.StandardCharsets;
  import java.nio.file.Files;
  import java.nio.file.Path;
  import java.nio.file.Paths;
  import java.util.ArrayList;
  import java.util.List;
  
  import javax.xml.parsers.DocumentBuilder;
  import javax.xml.parsers.DocumentBuilderFactory;
  import javax.xml.parsers.ParserConfigurationException;
  import javax.xml.transform.Transformer;
  import javax.xml.transform.TransformerException;
  import javax.xml.transform.TransformerFactory;
  import javax.xml.transform.dom.DOMSource;
  import javax.xml.transform.stream.StreamResult;
  
  import org.w3c.dom.Document;
  import org.w3c.dom.Node;
  import org.w3c.dom.NodeList;
  
  import org.xml.sax.InputSource;
  import org.xml.sax.SAXException;
  
  import io.quarkus.test.junit.QuarkusTest;
  import io.restassured.RestAssured;
  import org.junit.jupiter.api.Assertions;
  import org.junit.jupiter.api.Test;
  
  @QuarkusTest
  public class Java2wsTest {
  
      @Test
      public void java2WsCodeFirstService()
              throws IOException, ParserConfigurationException, SAXException, TransformerException {
          String servedWsdl = RestAssured.given()
                  .get("/soapservice/codefirst?wsdl")
                  .then()
                  .statusCode(200)
                  .extract().body().asString();
          servedWsdl = normalizeNsPrefixes(servedWsdl);
          Path generatedPath = Paths.get("target/Java2wsTest/CodeFirstService-from-java2ws.wsdl");
          try (InputStream in = Files.newInputStream(generatedPath)) {
              final String java2WsGeneratedWsdl = new String(in.readAllBytes(), StandardCharsets.UTF_8);
  
              /* We have to compare on DOM level so that different order of XML attributes, etc. does not make the test fail */
              DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
              dbf.setNamespaceAware(true);
              dbf.setCoalescing(true);
              dbf.setIgnoringElementContentWhitespace(true);
              dbf.setIgnoringComments(true);
              DocumentBuilder db = dbf.newDocumentBuilder();
  
              final Document generatedDoc = parse(db, java2WsGeneratedWsdl);
              final Document servedDoc = parse(db, servedWsdl);
  
              boolean equal = generatedDoc.isEqualNode(servedDoc);
              String mode = this.getClass().getSimpleName().endsWith("IT") ? "native" : "jvm";
              Path servedPath = Paths.get("target/Java2wsTest/CodeFirstService-served-normalized-" + mode + ".wsdl")
                      .toAbsolutePath();
              Path generatedNormalizedPath = Paths.get("target/Java2wsTest/CodeFirstService-from-java2ws-normalized.wsdl")
                      .toAbsolutePath();
              save(servedDoc, servedPath);
              save(generatedDoc, generatedNormalizedPath);
              if (!equal) {
                  Assertions.fail(
                          "The WSDL generated by java2ws and the WSDL served by the application are not equal XML documents. You may want to compare "
                                  + generatedNormalizedPath + " vs. " + servedPath);
              }
  
          }
      }
  
      protected String normalizeNsPrefixes(String servedWsdl) {
          /*
           * ns1 does not seem to be used anywhere in the WSDL document so it should be fine to remove it.
           * At the same time it is the only difference against the document produced by java2ws which is also fine
           */
          return servedWsdl.replace("xmlns:ns1=\"http://schemas.xmlsoap.org/soap/http\"", "");
      }
  
      static void save(Document doc, Path path) throws TransformerException, IOException {
          Files.createDirectories(path.getParent());
          Transformer t = TransformerFactory.newDefaultInstance().newTransformer();
          t.transform(new DOMSource(doc), new StreamResult(path.toFile()));
      }
  
      static Document parse(DocumentBuilder db, String wsdlDoc) throws SAXException, IOException {
          Document doc = db.parse(new InputSource(new StringReader(wsdlDoc)));
  
          /*
           * There is some default :9090 location in the generated WSDL so we remove the whole address node from both
           */
          NodeList adrNodes = doc.getElementsByTagNameNS("http://schemas.xmlsoap.org/wsdl/soap/", "address");
          List<Node> adrNodesList = new ArrayList<>();
          for (int i = 0; i < adrNodes.getLength(); i++) {
              adrNodesList.add(adrNodes.item(i));
          }
          for (Node node : adrNodesList) {
              node.getParentNode().removeChild(node);
          }
          doc.normalizeDocument();
          return doc;
      }
  
  }
  