/*
 * Copyright 2002-2008 the original author or authors.
 *
 * 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 integration.anyframe.services.query;

import integration.anyframe.services.AbstractTest;

import java.util.ArrayList;
import java.util.List;

import anyframe.core.query.IQueryService;

public class QueryServiceTestDynamic extends AbstractTest {

	public static void main(String[] args) throws Exception {
		QueryServiceTestDynamic queryTest = new QueryServiceTestDynamic();
		// 1. initialize context
		queryTest.setup();
		queryTest.testDynamicQueryUsingNamedParameter();
		queryTest.testDynamicQueryUsingTextreplace();
		queryTest.testDynamicQueryUsingCondition();

		queryTest.teardown();

		System.out.println("Successful!!!!!");

	}

	protected void setup() {
		super.setup();
		try {
			testInit();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 테스트 코드를 샐행하기 위한 data table 생성
	 */
	public void testInit() throws Exception {
		IQueryService queryService = (IQueryService) context
				.getBean("queryService");
		queryService.updateBySQL("DROP TABLE TBL_USER IF EXISTS",
				new String[] {}, new Object[] {});
		queryService.updateBySQL("CREATE TABLE TBL_USER ( "
				+ "LOGON_ID  VARCHAR(20), " + "PASSWORD VARCHAR(20),"
				+ "NAME VARCHAR(20)," + "PRIMARY KEY (LOGON_ID))",
				new String[] {}, new Object[] {});
		queryService.createBySQL(
				"INSERT INTO TBL_USER VALUES ('admin', 'admin', 'ADMIN')",
				new String[] {}, new Object[] {});
		queryService.createBySQL(
				"INSERT INTO TBL_USER VALUES ('test', 'test123', 'TESTER')",
				new String[] {}, new Object[] {});
	}

	/**
	 * Named Parameter를 이용해서 query id가 'getLogonIdByNamedParam'인 Dynamic 쿼리문을 실행한다.
	 * getLogonIdByNamedParam : key가 lowId, highId인 Named Parameter의 값을 key=value 형태로 Query 
	 * 서비스에 전달하면 Query 서비스는 해당 value를 PreparedStatement에 셋팅하고 해당 쿼리문을 실행한다.
	 * 이 메소드에서는 "lowId = a", "highId = z"라는 paramter를  Object[] 형태로 Query 서비스에 전달하고 있으며, 
	 * 이 때 실행되는 쿼리문은 다음과 같다.
	 * <pre>
	 * SELECT LOGON_ID FROM TBL_USER WHERE LOGON_ID BETWEEN 'a' AND 'z'
	 * </pre>
	 */
	public void testDynamicQueryUsingNamedParameter() throws Exception {
		IQueryService queryService = (IQueryService) context
				.getBean("queryService");

		Object[] iVal = new Object[2];
		iVal[0] = "lowId=a";
		iVal[1] = "highId=z";
		ArrayList rtList = (ArrayList) (queryService.find(
				"getLogonIdByNamedParam", iVal));
		if (rtList.size() != 2) {
			throw new Exception("Dynamic Query Using NamedParameter failed");
		}
	}

	/**
	 * {{치환문자열키}}를 이용해서  query id가 'getEmployeesByTextReplacement'인 Dynamic 쿼리문을 실행한다.
	 * getEmployeesByTextReplacement : key가 schema, sortColumn인 치환문자열의 값을 key=value 형태로 Query 
	 * 서비스에 전달하면 Query 서비스는 해당 value를 문자열로 그대로 치환해서 사용한다. 
	 * 이 메소드에서는 "schema=TBL_USER", "sortColumn=NAME"라는 parameter를 Object[] 형태로 Query 서비스에 전달하고 
	 * 있으며, 이 때 실행되는 쿼리문은 다음과 같다.
	 * <pre>
	 * SELECT * FROM TBL_USER ORDER BY NAME
	 * </pre>
	 */
	public void testDynamicQueryUsingTextreplace() throws Exception {
		IQueryService queryService = (IQueryService) context
				.getBean("queryService");

		Object[] iVal = new Object[2];
		iVal[0] = "schema=TBL_USER";
		iVal[1] = "sortColumn=NAME";
		ArrayList rtList = (ArrayList) (queryService.find(
				"getEmployeesByTextReplacement", iVal));
		if (rtList.size() != 2) {
			throw new Exception("Dynamic Query Using Text replace failed");
		}
	}

	/**
	 * 조건분기를 위한 #if를 이용해서  query id가 'getLogonIdByIf'인 Dynamic 쿼리문을 실행한다.
	 * getLogonIdByIf : key가 id인 parameter의 값이 Null이 아니고, 빈 문자열도 아니라면, #if문 내에 포함된 WHERE절이 
	 * 실행될 쿼리문에 포함된다. (#if문이 끝나는 지점에는 반드시 #end를 정의해주어야 함에 유의하자.)
	 * 또한, WHERE절 내에서는  '%' || :logonId || '%'와 같은 형태의 문장을 사용하고 있는데 이것은 Named Parameter의 값에 
	 * 앞뒤로 %를 붙인 형태의 문자열을 만들어 내기 위함이다. 
	 * (이 때, '%', ||, :logonId 사이에는 빈 칸을 두어야 WHERE절이 정상적으로 동작한다. )
	 * 이 메소드에서는 "id=test", "sortColumn=NAME" 라는 parameter를 Object[] 형태로 Query 서비스에 전달하고 있으며
	 * 실행되는 쿼리문은 다음과 같다.
	 * <pre>
	 * SELECT LOGON_ID 
	 * FROM TBL_USER 
	 * WHERE LOGON_ID like '%test%' 
	 * ORDER BY NAME
	 * </pre>
	 */
	public void testDynamicQueryUsingCondition() throws Exception {
		IQueryService queryService = (IQueryService) context
				.getBean("queryService");

		Object[] iVal = new Object[3];
		iVal[0] = "id=yes";
		iVal[1] = "logonId=test";
		iVal[2] = "sortColumn=NAME";
		ArrayList rtList = (ArrayList) (queryService.find("getLogonIdByIf",
				iVal));
		if (rtList.size() != 1) {
			throw new Exception("Dynamic Query Using Condition failed");
		}
	}

	/**
	 * Loop를 위한 #foreach를 이용해서  query id가 'getLogonIdByForeach'인 Dynamic 쿼리문을 실행한다.
	 * getLogonIdByForeach : key가 logonIdList인  parameter의 값은 List 형태이며, List에서 순서대로 추출된 값들은 내부적으로 
	 * logonId라는 변수에 셋팅된다. logonId는 Query 서비스에 전달되어야 하는 입력 parameter가 아니다.
	 * velocityCount가 1인 경우 즉, 첫번째 Loop일 경우 logonIdList의 첫번째 값이 그대로 추가되고 그 이후부터는 ,를 붙인 값이 추가되게 
	 * 된다. (#foreach, #if문이 끝나는 지점에는 반드시 #end를 정의해주어야 함에 유의하자.)
	 * 이 메소드에서는 logonIdList의 값이 "admin", "test"라는 두개의 문자열로 구성된 ArrayList를 Object[] 형태로 Query 서비스에
	 * 전달하고 있으며 실행되는 쿼리문은 다음과 같다.
	 * <pre>
	 * SELECT LOGON_ID, NAME 
	 * FROM TBL_USER 
	 * WHERE LOGON_ID IN ('admin', 'test') 
	 * ORDER BY NAME 
	 * </pre>
	 */	
	public void testDynamicQueryUsingLoop() throws Exception {
		IQueryService queryService = (IQueryService) context
				.getBean("queryService");

		List logonIdList = new ArrayList();
		logonIdList.add("admin");
		logonIdList.add("test");

		Object[] iVal = new Object[1];
		iVal[0] = "logonIdList=" + logonIdList;

		ArrayList rtList = (ArrayList) (queryService.find(
				"getLogonIdByForeach", iVal));

		if (rtList.size() != 1) {
			throw new Exception("Dynamic Query Using Condition failed");
		}
	}

	protected String[] getConfigLocations() {
		return new String[] {
				"classpath*:/common/applicationContext-*.xml",
				"classpath*:/services/datasource/applicationContext-datasource-common.xml",
				"classpath*:/services/query/applicationContext-query-common.xml",
				"classpath*:/services/query/applicationContext-query-sqlloader.xml" };
	}
}

