/***************************************************************************
 * Copyright 2012 Kieker Project (http://kieker-monitoring.net)
 *
 * Licensed 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 kieker.webgui.persistence.impl.utility;

import java.io.IOException;
import java.net.URL;
import java.util.Collection;

import org.junit.Assert;
import org.junit.Test;

import kieker.analysis.model.analysisMetaModel.MIFilter;
import kieker.analysis.model.analysisMetaModel.MIReader;
import kieker.analysis.model.analysisMetaModel.MIRepository;
import kieker.analysis.plugin.filter.forward.CountingFilter;
import kieker.analysis.plugin.reader.timer.TimeReader;
import kieker.tools.traceAnalysis.systemModel.repository.SystemModelRepository;
import kieker.webgui.common.ClassContainer;
import kieker.webgui.common.exception.ReflectionException;

/**
 * Test class for {@link Class2ModelInstanceConverter}.
 * 
 * @author Nils Christian Ehmke
 */
public class Class2ModelInstanceConverterTest {

	private static final String KIEKER_LIB = "kieker.jar";

	/**
	 * Default constructor. <b>Do not use this constructor. This is just a test class and not to be used outside a JUnit test!</b>
	 */
	public Class2ModelInstanceConverterTest() {
		// No code necessary
	}

	/**
	 * A test which loads dynamically a reader from the Kieker library and checks the converting.
	 * 
	 * @throws ReflectionException
	 *             If something went wrong.
	 * @throws IOException
	 *             If something went wrong.
	 */
	@Test
	public void testReaderConverting() throws ReflectionException, IOException {
		final PluginFinder pluginFinder = new PluginFinder();
		final URL kiekerURL = Thread.currentThread().getContextClassLoader().getResource(KIEKER_LIB);
		final CloseableURLClassLoader classLoader = new CloseableURLClassLoader(new URL[] { kiekerURL });
		final ClassContainer classAndMethodContainer = new ClassContainer(classLoader);
		final Class2ModelInstanceConverter converter = new Class2ModelInstanceConverter();

		final Collection<Class<?>> readers = pluginFinder.getAllReadersWithinJar(kiekerURL, classLoader, classAndMethodContainer);

		// Find the class of the TimeReader
		Class<?> timeReaderClass = null;
		for (final Class<?> reader : readers) {
			if (TimeReader.class.getCanonicalName().equals(reader.getCanonicalName())) {
				timeReaderClass = reader;
				break;
			}
		}
		if (timeReaderClass == null) {
			Assert.fail("TimeReader not available");
		}

		// Convert and check the reader
		final MIReader reader = converter.convertReaderClass2ModelInstance(timeReaderClass, classAndMethodContainer);

		Assert.assertEquals("Properties are not loaded correctly", timeReaderClass.getCanonicalName(), reader.getClassname());
		Assert.assertTrue("Properties are not loaded correctly", reader.getDisplays().isEmpty());
		Assert.assertTrue("Properties are not loaded correctly", reader.getRepositories().isEmpty());
		Assert.assertEquals("Properties are not loaded correctly", 2, reader.getOutputPorts().size());
		Assert.assertEquals("Properties are not loaded correctly", 3, reader.getProperties().size());

		classLoader.close();
	}

	/**
	 * A test which loads dynamically a filter from the Kieker library and checks the converting.
	 * 
	 * @throws ReflectionException
	 *             If something went wrong.
	 * @throws IOException
	 *             If something went wrong.
	 */
	@Test
	public void testFilterConverting() throws ReflectionException, IOException {
		final PluginFinder pluginFinder = new PluginFinder();
		final URL kiekerURL = Thread.currentThread().getContextClassLoader().getResource(KIEKER_LIB);
		final CloseableURLClassLoader classLoader = new CloseableURLClassLoader(new URL[] { kiekerURL });
		final ClassContainer classAndMethodContainer = new ClassContainer(classLoader);
		final Class2ModelInstanceConverter converter = new Class2ModelInstanceConverter();

		final Collection<Class<?>> filters = pluginFinder.getAllFiltersWithinJar(kiekerURL, classLoader, classAndMethodContainer);

		// Find the class of the CountingFilter
		Class<?> countingFilterCLass = null;
		for (final Class<?> filter : filters) {
			if (CountingFilter.class.getCanonicalName().equals(filter.getCanonicalName())) {
				countingFilterCLass = filter;
				break;
			}
		}
		if (countingFilterCLass == null) {
			Assert.fail("CountingFilter not available");
		}

		// Convert and check the reader
		final MIFilter filter = converter.convertFilterClass2ModelInstance(countingFilterCLass, classAndMethodContainer);

		Assert.assertEquals("Properties are not loaded correctly", countingFilterCLass.getCanonicalName(), filter.getClassname());
		Assert.assertEquals("Properties are not loaded correctly", 2, filter.getDisplays().size());
		Assert.assertTrue("Properties are not loaded correctly", filter.getRepositories().isEmpty());
		Assert.assertEquals("Properties are not loaded correctly", 2, filter.getOutputPorts().size());
		Assert.assertEquals("Properties are not loaded correctly", 1, filter.getInputPorts().size());
		Assert.assertTrue("Properties are not loaded correctly", filter.getProperties().isEmpty());

		classLoader.close();
	}

	/**
	 * A test which loads dynamically a repository from the Kieker library and checks the converting.
	 * 
	 * @throws ReflectionException
	 *             If something went wrong.
	 * @throws IOException
	 *             If something went wrong.
	 */
	@Test
	public void testRepositoryConverting() throws ReflectionException, IOException {
		final PluginFinder pluginFinder = new PluginFinder();
		final URL kiekerURL = Thread.currentThread().getContextClassLoader().getResource(KIEKER_LIB);
		final CloseableURLClassLoader classLoader = new CloseableURLClassLoader(new URL[] { kiekerURL });
		final ClassContainer classAndMethodContainer = new ClassContainer(classLoader);
		final Class2ModelInstanceConverter converter = new Class2ModelInstanceConverter();

		final Collection<Class<?>> repositories = pluginFinder.getAllRepositoriesWithinJar(kiekerURL, classLoader, classAndMethodContainer);

		// Find the class of the SystemModelRepository
		Class<?> systemModelRepository = null;
		for (final Class<?> repository : repositories) {
			if (SystemModelRepository.class.getCanonicalName().equals(repository.getCanonicalName())) {
				systemModelRepository = repository;
				break;
			}
		}
		if (systemModelRepository == null) {
			Assert.fail("SystemModelRepository not available");
		}

		// Convert and check the reader
		final MIRepository repository = converter.convertRepositoryClass2ModelInstance(systemModelRepository, classAndMethodContainer);

		Assert.assertEquals("Properties are not loaded correctly", systemModelRepository.getCanonicalName(), repository.getClassname());
		Assert.assertTrue("Properties are not loaded correctly", repository.getProperties().isEmpty());

		classLoader.close();
	}
}
