package common.sql;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;

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

/**
 * TestLineParsedNodeItem
 *
 */
public class TestLineParsedNodeItem {

	/**
	 * アクセス設定
	 *
	 * @param f 設定対象
	 */
	private static void setAccessible(final AccessibleObject f) {
		if (!f.isAccessible()) {
			final PrivilegedAction<Void> pa = () -> {
				f.setAccessible(true);
				return null;
			};
			AccessController.doPrivileged(pa);
		}
	}

	/**
	 * 括弧パースOFFSET_LIMIT句
	 */
	@Test
	public void testLineParsedNodeItem1() {
		final LineParsedNodeItem sut = new LineParsedNodeItem(
				"OFFSET ((/*?Page*/1 - 1) * /*?Line*/20 ) LIMIT /*?Line*/20 \n");
		Assert.assertEquals(
				"OFFSET ( ( /*?Page*/1 - 1 ) * /*?Line*/20 ) LIMIT /*?Line*/20", sut.toString());
	}

	/**
	 * 括弧パースAND
	 */
	@Test
	public void testLineParsedNodeItem2() {
		final LineParsedNodeItem sut = new LineParsedNodeItem(
			"AND ((DT_DATTAI_YM = '      ' ) (( DT_DATTAI_YM >= ))/*:dtGyomu*/'200901' )");
		Assert.assertEquals(
				"AND ( ( DT_DATTAI_YM = '      ' )( ( DT_DATTAI_YM >= ) ) /*:dtGyomu*/'200901' )",
				sut.toString());
	}

	/**
	 * 括弧パース
	 */
	@Test
	public void testLineParsedNodeItem3() {
		final LineParsedNodeItem sut = new LineParsedNodeItem(
			"AND (DT_DATTAI_YM = '      ' OR DT_DATTAI_YM >= /*:dtGyomu*/'200901')");
		Assert.assertEquals(
				"AND ( DT_DATTAI_YM = '      ' OR DT_DATTAI_YM >= /*:dtGyomu*/'200901' )",
				sut.toString());
	}

	/**
	 * 括弧パースAND_OR
	 */
	@Test
	public void testLineParsedNodeItem4() {
		final LineParsedNodeItem sut = new LineParsedNodeItem(
			"AND ((DT_DATTAI_YM = '      ' AND MN_PAY > /*:mnPay*/1 ) "
			+ "OR (DT_DATTAI_YM >= /*:dtGyomu*/'200901' ))");
		Assert.assertEquals(
				"AND ( ( DT_DATTAI_YM = '      ' AND MN_PAY > /*:mnPay*/1 ) "
				+ "OR ( DT_DATTAI_YM >= /*:dtGyomu*/'200901' ) )",
				sut.toString());
	}

	/**
	 * 日時必須パース
	 */
	@Test
	public void testLineParsedNodeItem5() {
		final LineParsedNodeItem sut = new LineParsedNodeItem(
				"UPDATE_DATETIME = /*:DateTime*/TO_DATE('20091225','YYYYMMDD') ,");
		Assert.assertEquals(
				"UPDATE_DATETIME = /*:DateTime*/TO_DATE( '20091225','YYYYMMDD' ) ,",
				sut.toString());
	}

	/**
	 * 日時必須パースAND_OR句
	 */
	@Test
	public void testLineParsedNodeItem6() {
		final LineParsedNodeItem sut = new LineParsedNodeItem(
			"AND ((DT_DATTAI_YM = /*:DateTime*/TO_DATE('20091225','YYYYMMDD') "
			+ "AND MN_PAY > /*:mnPay*/0 ) OR (DT_DATTAI_YM >= /*:dtGyomu*/'200901' ))");
		Assert.assertEquals(
				"AND ( ( DT_DATTAI_YM = /*:DateTime*/TO_DATE( '20091225','YYYYMMDD' ) "
				+ "AND MN_PAY > /*:mnPay*/0 ) OR ( DT_DATTAI_YM >= /*:dtGyomu*/'200901' ) )",
				sut.toString());
	}

	/**
	 * getBindString行末スペース
	 */
	@Test
	public void testLineParsedNodeItem7() {
		final LineParsedNodeItem sut = new LineParsedNodeItem("");
		try {
			final Method m = sut.getClass().getDeclaredMethod(
					"getBindString", String.class, int.class);
			setAccessible(m);
			Assert.assertEquals("aaaaa#12345", m.invoke(sut, "aaaaa#12345)", Integer.valueOf(0)));
			Assert.assertEquals(
					"aaaaa#0.00012", m.invoke(sut, "aaaaa#0.00012, ", Integer.valueOf(0)));
			Assert.assertEquals("aaaaa#-1234", m.invoke(sut, "aaaaa#-1234 ", Integer.valueOf(0)));
			Assert.assertEquals(
					"aaaaa#-1234.53", m.invoke(sut, "aaaaa#-1234.53 ", Integer.valueOf(0)));
			Assert.assertEquals("aaaaa#-0.53", m.invoke(sut, "aaaaa#-0.53 ", Integer.valueOf(0)));
			Assert.assertEquals("aaaaa#-0.00", m.invoke(sut, "aaaaa#-0.00  ", Integer.valueOf(0)));
		} catch (final ReflectiveOperationException e) {
			Assert.fail(e.getMessage());
		}
	}
}
