/*******************************************************************************
 *  Copyright 2017-2018 Centre for Development of Advanced Computing(C-DAC), Pune
 *  
 * 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 cdac.medinfo.sdk.dcm30_04.services.ups.dbhelper;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;


import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITag;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;

/**
 * Unified Procedure Step Service and SOP Classes DataBase Agent provides implementation for
 * processing of queries on DataBase.
 */
public class UPSDBAgent 
{

	private static Connection objConnection = null;
	private static UPSDBAgent objUPSDBAgent= null;
	private static Object mutex = new Object();
	private UPS_DBQuery objUPS_DBQuery= null;
	private static String dbURL = null;
	private static String emdriver = null;

	/**
	 * Default Constructor of {@link UPSDBAgent}
	 * @param strConnectionString Connection String to connect DataBase
	 * @param strDriverName Database Driver Name
	 * @throws InstantiationException - thrown in case failure when an application tries to create an instance of a class using the newInstance method in class Class, but the specified class object cannot be instantiated.
	 * @throws IllegalAccessException - thrown in case failure when an application tries to reflectively create an instance (other than an array), set or get a field, or invoke a method, but the currently executing method does not have access to the definition of the specified class, field, method or constructor. 
	 * @throws ClassNotFoundException - thrown in case failure when an application tries to load in a class. 
	 * @throws SQLException - thrown in case of database access error or other errors.
	 */
	private UPSDBAgent(String strConnectionString, String strDriverName) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException 
	{
		emdriver = new String(strDriverName);
		dbURL = new String(strConnectionString);		
		Class.forName(emdriver).newInstance();
		objConnection = DriverManager.getConnection(dbURL);
		objUPS_DBQuery = new UPS_DBQuery();
		objUPS_DBQuery.setConnection(objConnection);
	}

	/**
	 * Creates instance of UPSDBAgent.
	 * @param strConnectionString Database Connection String
	 * @param strDriverName Database driver fully qualified name
	 * @return instance of UPSDBAgent.
	 * @throws SQLException  - thrown in case of database access error or other errors.
	 * @throws ClassNotFoundException  - thrown in case failure when an application tries to load in a class.
	 * @throws InstantiationException - thrown in case failure when an application tries to create an instance of a class using the newInstance method in class Class, but the specified class object cannot be instantiated.
	 * @throws IllegalAccessException - thrown in case failure when an application tries to reflectively create an instance (other than an array), set or get a field, or invoke a method, but the currently executing method does not have access to the definition of the specified class, field, method or constructor.
	 */
	public static UPSDBAgent createInstance(String strConnectionString, String strDriverName)throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException
	{
		synchronized (mutex) 
		{
			if(objUPSDBAgent == null)
				objUPSDBAgent = new UPSDBAgent(strConnectionString,strDriverName);
		}
		return objUPSDBAgent;
	}

	/**
	 * Stores specified Data set to Database. 
	 * @param objIDataSet - instance of {@link IDataSet}
	 * @return  <tt>true</tt> if Success, otherwise
	 * 			<tt>false</tt>
	 * @throws SQLException if there is database access error or other errors.
	 */
	public boolean storeInstanceInfo(IDataSet objIDataSet)throws SQLException
	{
		return objUPS_DBQuery.storeInstanceInfo(objIDataSet);
	}

	/**
	 * Depending on the keys in the IDataSet it finds the matching DataSets and returns status.
	 * According to the matched DataSets populate the collection taken as out parameter.
	 * @param objIDataSet The data set containing identifiers.
	 * @param objRstDataCollection the matched data set collection
	 * @return boolean true - if one or more matches are found
	 * 				   false - if no matches are found.
	 * @throws SQLException if there is database access error or other errors.
	 */
	public boolean find(IDataSet objIDataSet, ISingleCollection<IDataSet> objRstDataCollection) throws SQLException
	{
		return objUPS_DBQuery.find(objIDataSet, objRstDataCollection);
	}
	
	/**
	 * Stores specified Data set to Database. 
	 * @param objIDataSet - instance of {@link IDataSet}
	 * @return  <tt>true</tt> if Success, otherwise
	 * 			<tt>false</tt>
	 * @throws SQLException if there is database access error or other errors.
	 */
	public boolean storeInstanceInfoForCancle(IDataSet objIDataSet)throws SQLException
	{
		return objUPS_DBQuery.storeInstanceInfoForCancle(objIDataSet);
	}
	
	/**
	 * Checks whether provided Transaction UID is created or not.
	 * @param strSOPInstance value of SOP Instance UID 
	 * @return boolean shows status as success or failure
	 * @throws SQLException if sql operation fails
	 */
	public boolean isTransactionUIDExist(String strUID)throws SQLException
	{
		return objUPS_DBQuery.isTransactionUIDExist(strUID);
	}
	
	
	/**
	 * Updates a SOP Instance
	 * @param objIDataSet instance of Dataset
	 * @param strSOPInstanceUID value of SOPInstanceUID
	 * @return boolean - status as true or false
	 * @throws SQLException if SQL operation fails
	 */
	public boolean updateSOPInstance(IDataSet objIDataSet,String strUID)throws SQLException
	{
		return objUPS_DBQuery.updateUPSInstanceInfo(objIDataSet, strUID);
	}
	 /**
	 * Retrieve specified Data set from Database. 
	 * @param objTagCollection
	 * @param strSOPInstance
	 * @return objIDataSet
	 * @throws SQLException
	 */
	public IDataSet retrieveUPSInstanceInfo(ISingleCollection<ITag> objTagCollection, String strSOPInstance) throws SQLException {
		return objUPS_DBQuery.retrieveInstanceInfo(objTagCollection, strSOPInstance);
	}
	
	/**
	 * Checks whether provided SOP Instance is created or not.
	 * @param strSOPInstance value of SOP Instance UID 
	 * @return boolean shows status as success or failure
	 * @throws SQLException if sql operation fails
	 */
	public boolean isSOPInstanceExist(String strSOPInstance)throws SQLException
	{
		return objUPS_DBQuery.isSOPInstanceExist(strSOPInstance);
	}

	/**
	 * Stores specified Data set to Database. 
	 * @param objIDataSet - instance of {@link IDataSet}
	 * @return  <tt>true</tt> if Success, otherwise
	 * 			<tt>false</tt>
	 * @throws SQLException if there is database access error or other errors.
	 */
	public boolean storeInstanceInfoForSubscription(IDataSet objIDataSet) throws SQLException 
	{
		
		return objUPS_DBQuery.storeInstanceInfoForSubscription(objIDataSet);
	}
	/**
	 * Stores specified Data set to Database. 
	 * @param objIDataSet - instance of {@link IDataSet}
	 * @return  <tt>true</tt> if Success, otherwise
	 * 			<tt>false</tt>
	 * @throws SQLException if there is database access error or other errors.
	 */
	public boolean storeInstanceInfoForUnsubscribe(IDataSet objIDataSet) throws SQLException {
		return objUPS_DBQuery.storeInstanceInfoForUnSubscribe(objIDataSet);
	}

	 /**
	 * Retrieve specified Data set from Database. 
	 * @param objTagCollection
	 * @param strSOPInstance
	 * @return objIDataSet
	 * @throws SQLException
	 */
	public IDataSet retrieveUPSInstanceInfoForTwo(ISingleCollection<ITag> objTagCollection, String strSOPInstance) throws SQLException {
		return objUPS_DBQuery.retrieveInstanceInfoForTwo(objTagCollection, strSOPInstance);
	}
	 /**
	 * Retrieve specified Data set from Database. 
	 * @param objTagCollection
	 * @param strSOPInstance
	 * @return objIDataSet
	 * @throws SQLException
	 */
	public IDataSet retrieveUPSInstanceInfoForThree(ISingleCollection<ITag> objTagCollection, String strSOPInstance) throws SQLException {
		return objUPS_DBQuery.retrieveUPSInstanceInfoForThree(objTagCollection, strSOPInstance);
	}
	/**
	 * Check for subscription for specified SOP .
	 * @param strSOPInstance
	 * @return  <tt>true</tt> if Success, otherwise
	 * 			<tt>false</tt>
	 * @throws SQLException
	 */
	public boolean checkForSubscription(String strSOPInstance) throws SQLException 
	{
		return objUPS_DBQuery.checkForSubscription(strSOPInstance);
	}

		
}
