/******************************************************************************
 * Copyright (c) 2011-2012, EBM WebSourcing
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     EBM WebSourcing - initial API and implementation
 *******************************************************************************/

package org.eclipse.bpel.common.wsdl.importhelpers;

import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;

import org.eclipse.bpel.common.wsdl.parsers.WsdlParser;
import org.eclipse.emf.common.util.URI;
import org.eclipse.wst.wsdl.Definition;
import org.junit.Assert;
import org.junit.Test;

/**
 * Tests the WSDL importer helper (import and update).
 * @author Vincent Zurczak - EBM WebSourcing
 */
public class WsdlImportHelperTest {

	/**
	 * Tests the import of a simple WSDL 1.1.
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport1() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test1/tuxDroid.wsdl" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 1 );
			Assert.assertEquals( tmpDir.listFiles().length, 1 );

			File f = map.values().iterator().next();
			Assert.assertNotNull( f );
			Assert.assertEquals( f.getName(), "tuxDroid.wsdl" );

			testWsdlParsing( f, 1 );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests the import of a simple WSDL 1.1 with name conflict.
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport2() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			// First import: OK
			URL url = getClass().getResource( "/wsdls/test1/tuxDroid.wsdl" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 1 );
			File f = map.values().iterator().next();
			Assert.assertNotNull( f );
			Assert.assertEquals( f.getName(), "tuxDroid.wsdl" );

			testWsdlParsing( f, 1 );

			// Second import: should be renamed
			map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 1 );
			Assert.assertEquals( tmpDir.listFiles().length, 2 );

			f = map.values().iterator().next();
			Assert.assertNotNull( f );
			Assert.assertNotSame( f.getName(), "tuxDroid.wsdl" );

			testWsdlParsing( f, 1 );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests the import of a simple WSDL 2.0.
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport3() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test2/testwsdl20.wsdl" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 1 );
			Assert.assertEquals( tmpDir.listFiles().length, 1 );

			File f = map.values().iterator().next();
			Assert.assertNotNull( f );
			Assert.assertEquals( f.getName(), "testwsdl20.wsdl" );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests the import of a WSDL 1.1 which imports a XSD (same level).
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport4() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test3/To.wsdl" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 2 );
			Assert.assertEquals( tmpDir.listFiles().length, 2 );

			File f = map.get( url.toString());
			Assert.assertNotNull( f );
			testWsdlParsing( f, 1 );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests the import of a WSDL 1.1 which imports a XSD (1 sub-level).
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport5() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test4/To.wsdl" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 2 );
			Assert.assertEquals( tmpDir.listFiles().length, 2 );

			File level1Dir = new File( tmpDir, "level1" );
			Assert.assertTrue( level1Dir.exists());
			Assert.assertEquals( level1Dir.listFiles().length, 1 );

			File f = map.get( url.toString());
			Assert.assertNotNull( f );
			testWsdlParsing( f, 1 );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests the import of a WSDL 1.1 which imports a XSD (2 sub-levels).
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport6() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test5/To.wsdl" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 2 );
			Assert.assertEquals( tmpDir.listFiles().length, 2 );

			File level2Dir = new File( tmpDir, "level1/level2" );
			Assert.assertTrue( level2Dir.exists());
			Assert.assertEquals( level2Dir.listFiles().length, 1 );
			Assert.assertEquals( level2Dir.getParentFile().listFiles().length, 1 );

			File f = map.get( url.toString());
			Assert.assertNotNull( f );
			testWsdlParsing( f, 1 );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests the import of a WSDL 1.1 which imports several XSD (2 sub-levels).
	 * <p>
	 * And to limit the number of tests, these two XSDs import each other.
	 * This way, we can test the support of loops in the imports.
	 * </p>
	 *
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport7() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test6/To.wsdl" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 3 );
			Assert.assertEquals( tmpDir.listFiles().length, 2 );

			File level2Dir = new File( tmpDir, "level1/level2" );
			Assert.assertTrue( level2Dir.exists());
			Assert.assertEquals( level2Dir.listFiles().length, 1 );
			Assert.assertEquals( level2Dir.getParentFile().listFiles().length, 2 );

			File f = map.get( url.toString());
			Assert.assertNotNull( f );
			testWsdlParsing( f, 1 );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests the import of a XSD with an import of another XSD (upper-level => the import will be relocated).
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport8() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test6/level1/level2/To_schema1.xsd" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 2 );
			Assert.assertEquals( tmpDir.listFiles().length, 2 );

			File relocatedDir = new File( tmpDir, WsdlImportHelper.RELOCATED_DIRECTORY );
			Assert.assertTrue( relocatedDir.exists());
			Assert.assertEquals( relocatedDir.listFiles().length, 1 );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests the import of a XSD with an import of another XSD (sub-level).
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport9() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test6/level1/To_schema2.xsd" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 2 );
			Assert.assertEquals( tmpDir.listFiles().length, 2 );

			File level2Dir = new File( tmpDir, "level2" );
			Assert.assertTrue( level2Dir.exists());
			Assert.assertEquals( level2Dir.listFiles().length, 1 );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests a WSDL 1.1 which imports a WSDL and a XML schema (same level).
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport10() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test7/ToConcrete.wsdl" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 3 );
			Assert.assertEquals( tmpDir.listFiles().length, 3 );

			File f = map.get( url.toString());
			Assert.assertNotNull( f );
			Assert.assertEquals( f.getName(), "ToConcrete.wsdl" );

			testWsdlParsing( f, 2 );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests a WSDL 1.1 which imports a WSDL and a XML schema (same level).
	 * <p>
	 * There is a cyclic import in the WSDL.
	 * </p>
	 *
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport11() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test8/ToConcrete.wsdl" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 3 );
			Assert.assertEquals( tmpDir.listFiles().length, 3 );

			File f = map.get( url.toString());
			Assert.assertNotNull( f );
			Assert.assertEquals( f.getName(), "ToConcrete.wsdl" );
			testWsdlParsing( f, 2 );

			for( File ff : map.values()) {
				int index = ff.getName().lastIndexOf( '.' );
				Assert.assertTrue( index != -1 );
				String ext = ff.getName().substring( index ).toLowerCase();
				assertTrue( ".wsdl".equals( ext ) || ".xsd".equals( ext ));
			}

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests a WSDL 1.1 which imports a XML schema defined in the same file.
	 * <p>
	 * It means the WSDL has two <i>types</i> elements but with a different target name space.
	 * </p>
	 *
	 * @throws Exception
	 */
	@Test
	public void testWsdlImport12() throws Exception {

		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
		Assert.assertTrue( tmpDir.mkdir());
		try {
			URL url = getClass().getResource( "/wsdls/test9/GetQuantityAndSendOrder.wsdl" );
			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());

			Assert.assertEquals( map.size(), 1 );
			Assert.assertEquals( tmpDir.listFiles().length, 1 );

			File f = map.get( url.toString());
			Assert.assertNotNull( f );
			Assert.assertEquals( f.getName(), "GetQuantityAndSendOrder.wsdl" );

			testWsdlParsing( f, 1 );

		} finally {
			deleteFilesRecursively( tmpDir );
			Assert.assertFalse( tmpDir.exists());
		}
	}


	/**
	 * Tests a WSDL 1.1 on a remote server (renaming test).
	 * @throws Exception
	 */
//	@Test
//	public void testWsdlImport13() throws Exception {
//
//		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
//		Assert.assertTrue( tmpDir.mkdir());
//		try {
//			URL url = new URL( "http://footballpool.dataaccess.eu/data/info.wso?WSDL" );
//			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());
//
//			Assert.assertEquals( map.size(), 1 );
//			Assert.assertEquals( tmpDir.listFiles().length, 1 );
//
//			File f = map.get( url.toString());
//			Assert.assertNotNull( f );
//			Assert.assertEquals( f.getName(), "info-wso.wsdl" );
//
//			testWsdlParsing( f, 1 );
//
//		} finally {
//			deleteFilesRecursively( tmpDir );
//			Assert.assertFalse( tmpDir.exists());
//		}
//	}


	/**
	 * Tests a WSDL 1.1 generated by IIS and hosted on a remote server.
	 * <p>
	 * This test checks specific import locations.
	 * </p>
	 *
	 * @throws Exception
	 */
//	@Test
//	public void testWsdlImport14() throws Exception {
//
//		File tmpDir = new File( System.getProperty( "java.io.tmpdir" ), UUID.randomUUID().toString());
//		Assert.assertTrue( tmpDir.mkdir());
//		try {
//			URL url = new URL( "http://api7.publicaster.com/Pub7APIV2/Delivery.svc?wsdl" );
//			Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( tmpDir, url.toString());
//
//			Assert.assertEquals( map.size(), 7 );
//			Assert.assertEquals( tmpDir.listFiles().length, 7 );
//
//			File f = map.get( url.toString());
//			Assert.assertNotNull( f );
//			Assert.assertEquals( f.getName(), "Delivery-svc.wsdl" );
//
//			testWsdlParsing( f, 2 );
//
//		} finally {
//			deleteFilesRecursively( tmpDir );
//			Assert.assertFalse( tmpDir.exists());
//		}
//	}


	/**
	 * Deletes files recursively.
	 * @param files the files to delete
	 * @throws IOException if a file could not be deleted
	 */
	private static void deleteFilesRecursively( File... files ) throws IOException {

		if( files == null )
			return;

		for( File file : files ) {
			if( file.exists()) {
				if( file.isDirectory())
					deleteFilesRecursively( file.listFiles());

				if( ! file.delete())
					throw new IOException( file.getAbsolutePath() + " could not be deleted." );
			}
		}
	}


	/**
	 * Tests the parsing of an imported WSDL.
	 * @param wsdlUrl the WSDL URL
	 * @param expectedNumberOfDefinitions the number of definitions, including those found from import declarations
	 */
	private static void testWsdlParsing( File wsdlFile, int expectedNumberOfDefinitions ) {

		// Parse the imported WSDL
		URI emfUri = URI.createFileURI( wsdlFile.getAbsolutePath());
		Definition def = WsdlParser.loadWsdlDefinition( emfUri, WsdlParser.createBasicResourceSetForWsdl());
		Assert.assertNotNull( def );

		// Check the imports
		Collection<Definition> definitions = WsdlParser.loadAllWsdlDefinitions( emfUri, WsdlParser.createBasicResourceSetForWsdl());
		Assert.assertEquals( definitions.size(), expectedNumberOfDefinitions );
	}
}
