/*
 * EvolpTransformerTest.java
 * JUnit based test
 *
 * Copyright (C) 2006 - 2007 Martin Slota
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

/*
 * History:
 * v0.1 (2007-03-07): initial version
 * v0.9 (2007-05-06):
 * - some documentation added
 *
 * PENDING add more tests
 */

package lp.trans;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

import junit.framework.*;

import lp.parse.EvolpParser;
import lp.parse.LpParser;

import lp.test.util.PartReader;
import lp.test.util.TabSeparatedReader;

import lp.unit.EvolpProgram;
import lp.unit.LogicProgram;
import lp.unit.TransEvolpRuleType;
import lp.unit.TransformedEvolp;
import static lp.unit.TransEvolpRuleType.*;

/**
 * Contains tests of the {@link EvolpTransformer} class.
 *
 * @author Martin Slota
 * @version 0.9
 * @see EvolpTransformer
 */
public class EvolpTransformerTest extends TestCase {
	/**
	 * A {@link EvolpParser} instance used in the tests to convert create
	 * object representations of rules.
	 */
	protected final EvolpParser parser;
	
	/**
	 * A {@link EvolpTransformer} instance used in the tests.
	 */
	private final EvolpTransformer transformer;
	
	/**
	 * A default test case constructor.
	 *
	 * @param testName the name of the test case
	 */
	public EvolpTransformerTest(String testName) {
		super(testName);
		parser = new EvolpParser();
		transformer = new EvolpTransformer();
	}
	
	/**
	 * Tests the transformer on a simple input.
	 */
	public void testSimple() throws IOException {
		doTest("/data/EvolpTransformerSimpleTest.dat");
	}
	
	/**
	 * Tests the transformer on a more complex input (the suitcase example).
	 */
	public void testSuitcase() throws IOException {
		doTest("/data/EvolpTransformerSuitcaseTest.dat");
	}
	
	/**
	 * Reads both the input program and the expected results from the file
	 * {@code filename}.
	 *
	 * @param filename the path to the file that contains both the input program
	 * and the expected transformed program.
	 */
	protected void doTest(String filename) throws IOException {
		Reader reader = new BufferedReader(
				new InputStreamReader(getClass().getResourceAsStream(
				filename)));
		Reader sourceReader = new PartReader(reader, '$');
		parser.setInput(sourceReader);
		EvolpProgram program = parser.parseEvolp();
		TransformedEvolp transformed = transformer.transform(program);
		
		/*for (int group = 1; group <= program.getEvents().size(); group++) {
			System.out.println();
			System.out.println();
			for (TransEvolpRuleType t : TransEvolpRuleType.values()) {
				StringBuilder header = new StringBuilder();
				header.append("% ").append(t.toString());
				header.append(" in the ").append(group);
				switch (group) {
					case 1: header.append("st"); break;
					case 2: header.append("nd"); break;
					case 3: header.append("rd"); break;
					default: header.append("th");
				}
				header.append(" DLP");
				System.out.println(header);
				for (LpRule r : transformed.getGroup(group, t)) {
					System.out.println(r);
				}
				StringBuilder footer = new StringBuilder();
				footer.append("$ end of ").append(t.toString().toLowerCase());
				footer.append(" in the ").append(group);
				switch (group) {
					case 1: footer.append("st"); break;
					case 2: footer.append("nd"); break;
					case 3: footer.append("rd"); break;
					default: footer.append("th");
				}
				footer.append(" DLP $");
				System.out.println(footer);
				System.out.println();
			}
		}/**/
		
		int eventCount = program.getEvents().size();
		for (int group = 1; group <= eventCount; group++)
			for (TransEvolpRuleType type : TransEvolpRuleType.values()) {
				parser.setInput(new PartReader(sourceReader, '$'));
				LogicProgram prog = parser.parseAllRules();
				assertEquals("The part \"" + type + "(" + group + ")" +
						"\" of the transformed program not as expected!",
						prog, transformed.getGroup(group, type));
			}
			
			TabSeparatedReader tsr = new TabSeparatedReader(new PartReader(
					sourceReader, '$'));
			assertEquals("The transformed program is incomplete!",
					null, tsr.getNext());
			reader.close();
	}
}