package system.servlets;

import system.util.*;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.lang.*;
import java.sql.*;


/**
 * This is wr_src_Server servlet. It handels the requests from wrServer servlet.
 * @author: Nikolai Rangelov
 */
public class wr_src_Server extends RemoteHttpServlet implements wr_src_ServerRMI {
	private static Connection wr_srcdbConn = null; // Connection to local DB
	private static LogPrinter wr_srcLog = null;
	private static volatile byte ServletState = Constants.NOT_INITED;
	public static volatile Object SynchroRegistering = null;
	public static volatile Object SynchroReconn = null;
	public static volatile Object SynchroInit = null;
	private static volatile boolean IsReconn = false;
	private static String db_Drivers = null;
	private static String db_host = null;
	private static String db_user = null;
	private static String db_password = null;
	private static String wr_srcLogPath = null;
	private static int ScreenLogLevel = -1;
	private static int FileLogLevel = -1;
	private static volatile byte ServletErrorState = Constants.NO_ERROR;
/**
 * The method destroys wr_src_Server servlet. It calls the wr_srcServerDeInit() method to deinit the servlet.
 */

public void destroy() {
	wr_srcServerDeInit();
	ServletState = Constants.NOT_INITED;
	ServletErrorState = Constants.NO_ERROR;
	super.destroy();
}
/**
 * Inits the wr_src_Server servlet and DO NOT call wr_srcServerInit() (method that makes the primary init).
 * <br> Initialisation is done by request from wrServer.
 */

public void init(ServletConfig config) throws ServletException {
	super.init(config);
	//	initRMI();
	SynchroRegistering = null;
	SynchroRegistering = new Object();
	SynchroReconn = null;
	SynchroReconn = new Object();
	SynchroInit = null;
	SynchroInit = new Object();
}
/**
 * This method serves the requests (http values) from wrServer. It also handles
 * <br> other requests but they are explained in the servlet documentation. 
 */

public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
	res.setContentType("text/html");
	PrintWriter out = res.getWriter();
	String RT = req.getParameter(Constants.cs_ReqType);
	if (RT != null) {
		switch (Byte.valueOf(RT).byteValue()) {
			case (Constants.TASK_INIT_LITTLE) :
				byte PrevState = ServletState;
				if (ServletState != Constants.INITING) {
					ServletState = Constants.INITING;
					String tdb_Drivers = null;
					String tdb_host = null;
					String tdb_user = null;
					String tdb_password = null;
					String twr_srcLogPath = null;
					int tSLL = -1;
					int tFLL = -1;
					try {
						if ((tdb_Drivers = req.getParameter(dbFields.db_Drivers)) == null) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((tdb_host = req.getParameter(dbFields.db_host)) == null) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((tdb_user = req.getParameter(dbFields.db_user)) == null) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((tdb_password = req.getParameter(dbFields.db_password)) == null) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((twr_srcLogPath = req.getParameter(Constants.wr_srcLogPath)) == null) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((tSLL = Integer.valueOf(req.getParameter(Constants.ScreenLogLevel)).intValue()) < 0) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((tFLL = Integer.valueOf(req.getParameter(Constants.FileLogLevel)).intValue()) < 0) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
					} catch (Exception e) {
						out.print(ServletState);
						out.close();
						ServletState = PrevState;
						return;
					}
					try {
						if (wr_srcServerInit(twr_srcLogPath, tSLL, tFLL, tdb_Drivers, tdb_host, tdb_user, tdb_password) != Constants.RETRY) {
							if (wr_srcLog != null)
								wr_srcLog.log("wr_src_Server (service) : Error in init process.", LogPrinter.ERROR);
							out.print(ServletState);
							out.close();
							return;
						}
					} catch (Exception e) {
						if (wr_srcLog != null)
							wr_srcLog.log("wr_src_Server (service) : Exception in init process.", LogPrinter.ERROR);
						out.print(ServletState);
						out.close();
						ServletState = PrevState;
						return;
					}
				} else {
					wr_srcLog.log("wr_src_Server (service) : Servlet is being inited at the moment by another user.", LogPrinter.INFO);
					wr_srcLog.flush();
				}
				out.print(ServletState);
				out.close();
				if (ServletState == Constants.READY)
					wr_srcLog.log("wr_src_Server (service) : Servlet is inited and ready to work.", LogPrinter.INFO);
				wr_srcLog.log("wr_src_Server (service) : ServletState is " + ServletState, LogPrinter.INFO);
				wr_srcLog.flush();
				return;
			case (Constants.TASK_CHANGE_LOG_LEVELS) :
				int LogLevel = -1;
				String Level = null;
				Level = req.getParameter(Constants.FileLogLevel);
				if (Level == null) {
					out.println("A change for File Log Level not requested. It is " + wr_srcLog.getLogLevel() + ". It won't be changed. Query is : " + req.getQueryString());
					wr_srcLog.log("wr_src_Server (service) : File Log Level not requested. It won't be changed. Query is : " + req.getQueryString(), LogPrinter.INFO);
				} else {
					try {
						LogLevel = Integer.valueOf(Level).intValue();
						if (LogLevel > -1 && LogLevel <= LogPrinter.ALL) {
							wr_srcLog.setLogLevel(LogLevel);
							out.println("File Log Level changed to " + LogLevel + ".");
							wr_srcLog.log("wr_src_Server (service) : File Log Level changed " + LogLevel + ".", LogPrinter.INFO);
						} else {
							out.println("File Log Level NOT changed becausse it is not valid (" + LogLevel + "). Current File Log Level is : " + wr_srcLog.getLogLevel());
							wr_srcLog.log("wr_src_Server (service) : Not a valid File Log Level sent (" + LogLevel + ").", LogPrinter.ERROR);
							wr_srcLog.flush();
						}
					} catch (Exception e) {
						out.println("Error in request sequence for File Log Level. Qurey is : " + req.getQueryString() + ". Current File Log Level is : " + wr_srcLog.getLogLevel());
						wr_srcLog.log("wr_src_Server (service) : Error in request sequence for File Log Level. Qurey is : " + req.getQueryString() + ". Current File Log Level is : " + wr_srcLog.getLogLevel(), LogPrinter.ERROR);
						wr_srcLog.flush();
					}
				}
				out.print("<br>");
				Level = req.getParameter(Constants.ScreenLogLevel);
				if (Level == null) {
					out.println("A change for Screen Log Level not requested. It is " + wr_srcLog.getScreenLogLevel() + ". It won't be changed. Query is : " + req.getQueryString());
					wr_srcLog.log("wr_src_Server (service) : Screen Log Level not requested. It won't be changed. Query is : " + req.getQueryString(), LogPrinter.INFO);
				} else {
					try {
						LogLevel = Integer.valueOf(Level).intValue();
						if (LogLevel > -1 && LogLevel <= LogPrinter.ALL) {
							wr_srcLog.setScreenLogLevel(LogLevel);
							out.println("Screen Log Level changed to " + LogLevel + ".");
							wr_srcLog.log("wr_src_Server (service) : Screen Log Level changed " + LogLevel + ".", LogPrinter.INFO);
						} else {
							out.println("Screen Log Level NOT changed becausse it is not valid (" + LogLevel + "). Current Screen Log Level is : " + wr_srcLog.getLogLevel());
							wr_srcLog.log("wr_src_Server (service) : Not a valid Screen Log Level sent (" + LogLevel + ").", LogPrinter.ERROR);
							wr_srcLog.flush();
						}
					} catch (Exception e) {
						out.println("Error in request sequence for Screen Log Level. Qurey is : " + req.getQueryString() + ". Current File Log Level is : " + wr_srcLog.getScreenLogLevel());
						wr_srcLog.log("wr_src_Server (service) : Error in request sequence for Screen Log Level. Qurey is : " + req.getQueryString() + ". Current Screen Log Level is : " + wr_srcLog.getScreenLogLevel(), LogPrinter.ERROR);
						wr_srcLog.flush();
					}
				}
				wr_srcLog.flush();
				out.close();
				return;
			case (Constants.TASK_GET_SERVLET_STATE) :
				out.print(ServletState);
				out.close();
				wr_srcLog.log("wr_src_Server (service) : ServletState is " + ServletState, LogPrinter.INFO);
				wr_srcLog.flush();
				return;
			case (Constants.TASK_GET_SERVLET_ERROR_STATE) :
				out.print(ServletErrorState);
				out.close();
				wr_srcLog.log("wr_src_Server (service) : ServletErrorState is " + ServletErrorState, LogPrinter.INFO);
				wr_srcLog.flush();
				return;
			case (Constants.TASK_CLOSE_DIRECT) :
				if (!wr_srcServerDeInit())
					wr_srcLog.log("wr_src_Server (service) : Servlet deinitialisation faild but servlet is deinited (hard way).", LogPrinter.ERROR);
				else
					wr_srcLog.log("wr_src_Server (service) : Servlet deinited.", LogPrinter.INFO);
				wr_srcLog.flush();
				out.print(ServletState);
				out.close();
				return;
			default :
				out.close();
				wr_srcLog.log("wr_src_Server (service) : Error in argument ReqType.", LogPrinter.ERROR);
				wr_srcLog.flush();
				return;
		} //switch
	} //if(ReqType);		
	long wrKey = Constants.No_Key;
	int srcKey = 0;
	try {
		wrKey = Long.valueOf(req.getParameter(Constants.cs_WR_KEY)).longValue();
		srcKey = Integer.valueOf(req.getParameter(Constants.cs_SRC_KEY)).intValue();
	} catch (Exception e) {
		wr_srcLog.log("wr_rw_Server (service) : Error in parameters send from wrServer.", LogPrinter.ERROR);
		wr_srcLog.flush();
		out.close();
		return;
	}
	try {
		wr_srcMethodFlow(wrKey, srcKey);
	} catch (Exception e) {
		wr_srcLog.log("wr_src_Server (service) : wr_srcMethodFlow failed.", LogPrinter.ERROR);
		wr_srcLog.flush();
	}
	out.close();
	return;
}
/**
 * This method checks the tables in 'wr_src_Relations' DB. If a table is missing then the method creates it.
 * @return boolean 
 *	       <br> true  - if the method succeed
 * 		   <br> false - if the method failed
 */
private String wr_srcCheckTable() {
	String result_wr_srcTable = Constants.cs_wr_srcServerTable;
	try {
		if (!dbFields.TableExists(result_wr_srcTable, wr_srcdbConn)) {
			String SQLStat = "CREATE TABLE " + result_wr_srcTable + " (" + dbFields.db_wr_src_key + " " + dbFields.db_type_wr_src_key + "," + dbFields.db_wrKey + " " + dbFields.db_type_wrKey + "," + dbFields.db_srcKey + " " + dbFields.db_type_srcKey + "," + dbFields.db_wr_src_rel_LastCount + " " + dbFields.db_type_wr_src_rel_LastCount + ")";
			if (!dbFields.CreateTable(SQLStat, wr_srcdbConn)) {
				wr_srcLog.log("wr_src_Server (wr_srcCheckTable) : Error in creating " + result_wr_srcTable + " table for " + dbFields.db_wr_srcServerDB, LogPrinter.ERROR);
				wr_srcLog.flush();
				return null;
			}
		}
		wr_srcLog.log("wr_src_Server (wr_srcCheckTable) : Table checked.", LogPrinter.INFO);
		wr_srcLog.flush();
		return result_wr_srcTable;
	} catch (SQLException e) {
		if (wr_srcdbReconnect()) {
			wr_srcLog.log("wr_src_Server (wr_srcCheckTable) : db Reconnected.", LogPrinter.INFO);
			wr_srcLog.flush();
			return wr_srcCheckTable();
		} else {
			wr_srcLog.log("wr_src_Server (wr_srcCheckTable) : SQL Statement error on checking " + result_wr_srcTable + " table. Exception : " + e, LogPrinter.ERROR);
			wr_srcLog.flush();
			return null;
		}
	} catch (Exception e) {
		wr_srcLog.log("wr_src_Server (wr_srcCheckTable) : Exception - " + e, LogPrinter.ERROR);
		wr_srcLog.flush();
		return null;
	}
}
/**
 * This method connects the wr_src_Server servlet to 'wr_src_Relations' DB
 * @return boolean 
 *	       <br> true  - if the method succeed (we have connections)
 * 		   <br> false - if the method failed (we don't have connections)
 */

private boolean wr_srcdbConnect() {
	try {
		Class.forName(db_Drivers).newInstance();
		wr_srcLog.log("wr_src_Server (wr_srcdbConnect) : Got a driver to " + dbFields.db_wr_srcServerDB + " db.", LogPrinter.INFO);
	} catch (Exception E) {
		wr_srcLog.log("wr_src_Server (wr_srcdbConnect) : Unable to load driver to " + dbFields.db_wr_srcServerDB + " db. \n" + E, LogPrinter.ERROR);
		wr_srcLog.flush();
		return false;
	}
	wr_srcdbConn = null;
	try {
		wr_srcdbConn = DriverManager.getConnection(db_host + dbFields.db_wr_srcServerDB, db_user, db_password);
		wr_srcLog.log("wr_src_Server (wr_srcdbConnect) : Conection to " + dbFields.db_wr_srcServerDB + " db Established.", LogPrinter.INFO);
		if (wr_srcdbConn == null || wr_srcdbConn.isClosed()) {
			wr_srcLog.flush();
			return false;
		}
		wr_srcLog.flush();
		return true;
	} catch (SQLException E) {
		wr_srcLog.log("wr_src_Server (wr_srcdbConnect) : SQLException : " + E.getMessage(), LogPrinter.ERROR);
		wr_srcLog.log("wr_src_Server (wr_srcdbConnect) : SQLState     : " + E.getSQLState(), LogPrinter.ERROR);
		wr_srcLog.log("wr_src_Server (wr_srcdbConnect) : VendorError  : " + E.getErrorCode(), LogPrinter.ERROR);
		wr_srcLog.flush();
		return false;
	}
}
/**
 * This method disconnects the wr_src_Server servlet from 'wr_src_Relations' DB softly. If there is error
 * <br>during disconneting procedure the connection is stoped in hard way (equals null).
 */
 
private void wr_srcdbDisConnect() {
	try {
		if (wr_srcdbConn != null) {
			wr_srcdbConn.close();
			wr_srcLog.log("wr_src_Server (wr_srcdbConnect) : " + dbFields.db_wr_srcServerDB + " db closed.", LogPrinter.INFO);
			wr_srcLog.flush();
			wr_srcdbConn = null;
		}
	} catch (Exception e) {
		wr_srcLog.log("wr_src_Server (wr_srcdbConnect) : Cannot close the " + dbFields.db_wr_srcServerDB + " db \n" + e, LogPrinter.ERROR);
		wr_srcLog.flush();
		return;
	}
	return;
}
/**
 * Reconnects market_rwdbConn to Market_rw DB if servlet had lost its connection.
 * @return boolean
 *	       <br> true  - if the method succeed
 * 		   <br> false - if the method failed
 */
private boolean wr_srcdbReconnect() {
	try {
		if (wr_srcdbConn == null || wr_srcdbConn.isClosed()) {		
			ServletState = Constants.CONN_ERROR;
			ServletErrorState = Constants.CONN_ERROR;
			synchronized (SynchroReconn) {
				if (ServletState == Constants.CONN_ERROR) {
					if (!IsReconn) {
						IsReconn = true;
						if (!wr_srcdbConnect()) {
							wr_srcLog.log("wr_src_Server (wr_srcdbReconnect) : wr_srcdbConnect() failure.", LogPrinter.ERROR);
							IsReconn = false;
							wr_srcLog.flush();
							return false;
						}
						IsReconn = false;
						ServletState = Constants.READY;
						ServletErrorState = Constants.NO_ERROR;
						wr_srcLog.log("wr_src_Server (wr_srcdbReconnect) : Reconnection to db done.", LogPrinter.INFO);
						return true;
					} else {
						Thread.sleep(1000);
						if (ServletState == Constants.READY) {
							return true;
						}
					}
				} else
					if (ServletState == Constants.READY) {
						return true;
					}
			}
		} else {
			wr_srcLog.log("wr_src_Server (wr_srcdbReconnect) : Possible SQL Statement error. db is connected." , LogPrinter.ERROR);
			wr_srcLog.flush();
		}
		return false;
	} catch (Exception ex) {
		wr_srcLog.log("wr_src_Server (wr_srcdbReconnect) : Exception in re-connect: " + ex, LogPrinter.ERROR);
		wr_srcLog.flush();
		return false;
	}
}
/**
 * This method calculates the last free wr_src_Key. It looks for the greatest one in the 'wr_src_Relations'
 * <br>DB and then calculates the new wr_src_Key.
 * @return wr_src_Key long - the new key;
 *	       <br> 0 - if error occures
*/
private long wr_srcGet_wr_src_key(String TableName) {
	try {
		if (!dbFields.IsEmpty(TableName, wr_srcdbConn)) {
			String SQLStat = "SELECT MAX(" + dbFields.db_wr_src_key + ") FROM " + TableName;
			long res_wrKey = -1; // It should be always -1 because in the end we have +1 DO NOT PUT IT Constant.No_Key
			try {
				Statement Stmt = wr_srcdbConn.createStatement();
				ResultSet RS = Stmt.executeQuery(SQLStat);
				if (RS.next())
					res_wrKey = RS.getLong(1);
				wr_srcLog.log("wr_src_Server (wr_srcGet_wr_src_key) : The Last free key is : " + String.valueOf(res_wrKey), LogPrinter.DEBUG);
				RS.close();
				Stmt.close();
				return (res_wrKey + 1);
			} catch (SQLException E) {
				if (wr_srcdbReconnect()) {
					wr_srcLog.log("wr_src_Server (wr_srcGet_wr_src_key) : db Reconnected.", LogPrinter.INFO);
					wr_srcLog.flush();
					return wr_srcGet_wr_src_key(TableName);
				} else {
					wr_srcLog.log("wr_src_Server (wr_srcGet_wr_src_key) : SQL Statement error - " + SQLStat + " Exception : " + E, LogPrinter.ERROR);
					wr_srcLog.flush();
					return 0;
				}
			}
		} else {
			return 1;
		}
	} catch (SQLException e) {
		if (wr_srcdbReconnect()) {
			wr_srcLog.log("wr_src_Server (wr_srcGet_wr_src_key) : db Reconnected.", LogPrinter.INFO);
			wr_srcLog.flush();
			return wr_srcGet_wr_src_key(TableName);
		} else {
			wr_srcLog.log("wr_src_Server (wr_srcGet_wr_src_key) : SQL Statement error on checking if " + TableName + " is empty. Exception : " + e, LogPrinter.ERROR);
			wr_srcLog.flush();
			return 0;
		}
	}
}
/**
 * This method does the job of this servlet. It checks the ServletState and if it is 'READY'
 * <br> continues the procedure.
 * @return boolean 
 *	       <br> true  - if the method succeed 
 * 		   <br> false - if the method failed
 */
public boolean wr_srcMethodFlow(long wrKey, int srcKey) {
	// Check for the ServletState. It must be READY to continue further.
	do {
		try {
			switch (ServletState) {
				case (Constants.NOT_INITED) :
					if (wr_srcLog != null) {
						wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Servlet in not inited.", LogPrinter.ERROR);
						wr_srcLog.flush();
					}
					return false;
				case (Constants.INITING) :
					Thread.sleep(1000);
					break;
				case (Constants.INIT_ERROR) :
					if (wr_srcLog != null) {
						wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : There was error in the init process. Try to reload.", LogPrinter.ERROR);
						wr_srcLog.flush();
					}
					return false;
				case (Constants.READY) :
					break;
				case (Constants.CONN_ERROR) :
					synchronized (SynchroReconn) {
						if (!IsReconn)
							if (ServletState == Constants.CONN_ERROR) {
								IsReconn = true;
								if (!wr_srcdbConnect()) {
									IsReconn = false;
									wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Connection to " + dbFields.db_wr_srcServerDB + " cannot be re-established.", LogPrinter.ERROR);
									wr_srcLog.flush();
									return false;
								} else {
									IsReconn = false;
									ServletState = Constants.READY;
									wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Connection to " + dbFields.db_wr_srcServerDB + " re-established.", LogPrinter.INFO);
									wr_srcLog.flush();
									break;
								}
							}
					} //synchro
					break;
			} //switch			
		} catch (Exception e) {
			if (wr_srcLog != null) {
				wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : There was error in checking ServletState.", LogPrinter.ERROR);
				wr_srcLog.flush();
			}
			return false;
		}
	} while (ServletState != Constants.READY);

	//Check for the input parameters

	if (wrKey < 1) {
		wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : wrKey should be greater than 0 (" + wrKey + ")", LogPrinter.ERROR);
		wr_srcLog.flush();
		return false;
	}
	if (srcKey < 1) {
		wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : srcKey should be greater than 0 (" + srcKey + ")", LogPrinter.ERROR);
		wr_srcLog.flush();
		return false;
	}
	//Here we get the table name
	String wr_srcTable = Constants.cs_wr_srcServerTable;
	// First we Resolve the relation
	long wr_src_Key = wr_srcResolveRelation(wrKey, srcKey, wr_srcTable);
	if (Constants.Zero_Key == wr_src_Key) { // Error has occured
		wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Error in ResolveRelation() (sql statement) !!!", LogPrinter.ERROR);
		wr_srcLog.flush();
		return false;
	} else
		if ((-5) == wr_src_Key) { // Relation is being updated today so we won't do that again
			wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Relation is being updated today so it won't be again.", LogPrinter.DEBUG);
//	System.out.println("1. Relation is being updated today so we won't do that again");			
			return true;
		} else
			if (Constants.No_Key == wr_src_Key) { // The relation is not in the DB
				wr_src_Key = wr_srcRegisterRelation(wrKey, srcKey, wr_srcTable);
				if (Constants.No_Key == wr_src_Key) { // relation is insered in the DB
					wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Relation registered.", LogPrinter.DEBUG);
					return true;
				} else
					if ((-5) == wr_src_Key) { // Relation is being updated today so we won't do that again
						wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Relation is being updated today so it won't be again.", LogPrinter.DEBUG);
//	System.out.println("2. Relation is being updated today so we won't do that again");
						return true;
					} else
						if (Constants.Zero_Key == wr_src_Key) { // Error returned from Register process
							wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Error on RegisterRelation() function", LogPrinter.ERROR);
							wr_srcLog.flush();
							return false;
						} else
							if (wr_src_Key > 0) {
								// Resolve process in the Register method said that the relation is familiar and its wr_src_key is this.
								// So we update it.
								int update_res = wr_srcUpdateRelation(wr_src_Key, wr_srcTable);
								switch (update_res) {
									case (1) : // The relation is updated ok.
										wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : wrKey = " + wrKey + ", srcKey = " + srcKey + " updated in the " + wr_srcTable + " table.", LogPrinter.DEBUG);
										return true;
									case (0) : // The relation is not updated (failed)
										wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Res from updating = " + update_res + ". wr_src_Key = " + wr_src_Key + " in " + wr_srcTable + " table. Field not updated. If it has the same date then it won't be updated by mysql.", LogPrinter.ERROR);
										wr_srcLog.flush();
										return false;  //It should be
									case (-1) : // Error occured in the Update method
										wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Error in UpdateRelation() function with wrKey = " + wrKey + ", srcKey = " + srcKey + " updated in the " + wr_srcTable + " table.", LogPrinter.ERROR);
										wr_srcLog.flush();
										return false;
									default :
										if (update_res > 1) { // More than one relations updated at once. DUBLICATED relation
											wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Res from updating = " + update_res + ". wrKey = " + wrKey + ", srcKey = " + srcKey + " is DUBLICATED in " + wr_srcTable + " table.", LogPrinter.ERROR);
											wr_srcLog.flush();
											return true;
										} else { // Strange situation. Should not reach here.
											wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Res from updating = " + update_res + ". wrKey = " + wrKey + ", srcKey = " + srcKey + " in " + wr_srcTable + " table. Strange error.", LogPrinter.ERROR);
											wr_srcLog.flush();
											return false;
										}
								} //switch
							} else { // Strange thing
								wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Strange error. RegisterRelation returned less than -1. It can not be.", LogPrinter.ERROR);
								wr_srcLog.flush();
								return false;
							}
			} else {

				// Here starts updating process decided from Resolve method the relation is in the DB.

				int update = wr_srcUpdateRelation(wr_src_Key, wr_srcTable);
				switch (update) {
					case (1) : // The relation is updated ok.
						wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : wrKey = " + wrKey + ", srcKey = " + srcKey + " updated in the " + wr_srcTable + " table.", LogPrinter.DEBUG);
						return true;
					case (0) : // The relation is not updated (failed)
						wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Res from updating = " + update + ". wr_src_Key = " + wr_src_Key + " in " + wr_srcTable + " table. Field not updated. If it has the same date then it won't be updated by mysql.", LogPrinter.ERROR);
						wr_srcLog.flush();
						return false;  //It should be
					case (-1) : // Error occured in the Update method
						wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Error in UpdateRelation() function with wrKey = " + wrKey + ", srcKey = " + srcKey + " updated in the " + wr_srcTable + " table.", LogPrinter.ERROR);
						wr_srcLog.flush();
						return false;
					default :
						if (update > 1) { // More than one relations updated at once. DUBLICATED relation
							wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Res from updating = " + update + ". wrKey = " + wrKey + ", srcKey = " + srcKey + " is DUBLICATED in " + wr_srcTable + " table.", LogPrinter.ERROR);
							wr_srcLog.flush();
							return true;
						} else { // Strange situation. Should not reach here.
							wr_srcLog.log("wr_src_Server (wr_srcMethodFlow) : Res from updating = " + update + ". wrKey = " + wrKey + ", srcKey = " + srcKey + " in " + wr_srcTable + " table. Strange error.", LogPrinter.ERROR);
							wr_srcLog.flush();
							return false;
						}
				} //switch
			}
}
/**
 * Registers new relation wrKey - srcKey.
 * @return long 
 *	       <br> Constants.No_Key - if the method succeed in inserting a new field
 * 		   <br> Constants.Zero_Key - if the method failed
 *         <br> wr_src_Key - if the relation exists and update is needed
 *		   <br> -5 - if the relation do not need to be updated (its Last Count date is today)
 */
private long wr_srcRegisterRelation(long RwrKey, int RsrcKey, String Rwr_srcTableName) {
	synchronized (SynchroRegistering) {
		long wr_src_key = wr_srcResolveRelation(RwrKey, RsrcKey, Rwr_srcTableName);
		if (Constants.Zero_Key == wr_src_key) {
			wr_srcLog.log("wr_src_Server (wr_srcRegisterRelation) : Error returned from ResolveRelation().", LogPrinter.ERROR);
			wr_srcLog.flush();
			return Constants.Zero_Key;
		} else
			if ((-5) == wr_src_key) { // Relation is being updated today so we won't do that again
				wr_srcLog.log("wr_src_Server (wr_srcRegisterRelation) : Relation is being updated today so it won't be again.", LogPrinter.DEBUG);
				return wr_src_key;
			} else
				if (wr_src_key > 0) {
					wr_srcLog.log("wr_src_Server (wr_srcRegisterRelation) : ResolveRelation() returns that wr_src_Key = " + wr_src_key + " esxists.", LogPrinter.DEBUG);
					wr_srcLog.flush();
					return wr_src_key;
				}
		wr_src_key = wr_srcGet_wr_src_key(Rwr_srcTableName);
		if (wr_src_key > 0) {
			String SQLStat = "INSERT INTO " + Rwr_srcTableName + " (" + dbFields.db_wr_src_key + " ," + dbFields.db_wrKey + " ," + dbFields.db_srcKey + "," + dbFields.db_wr_src_rel_LastCount + ")values (?,?,?,?)";
			try {
				PreparedStatement stmt = wr_srcdbConn.prepareStatement(SQLStat);
				stmt.clearParameters();
				stmt.setLong(1, wr_src_key);
				stmt.setLong(2, RwrKey);
				stmt.setInt(3, RsrcKey);
				stmt.setDate(4, new java.sql.Date(System.currentTimeMillis()));
				stmt.executeUpdate();
				wr_srcLog.log("wr_src_Server (wr_srcRegisterRelation) : RegisterRelation - info wrKey = " + RwrKey + " and srcKey = " + RsrcKey + " inserted in " + Rwr_srcTableName + " table.", LogPrinter.DEBUG);
				return Constants.No_Key;
			} catch (SQLException e) {
				if (wr_srcdbReconnect()) {
					wr_srcLog.log("wr_src_Server (wr_srcRegisterRelation) : db Reconnected.", LogPrinter.INFO);
					wr_srcLog.flush();
					return wr_srcRegisterRelation(RwrKey, RsrcKey, Rwr_srcTableName);
				} else {
					wr_srcLog.log("wr_src_Server (wr_srcRegisterRelation) : SQL Statement error - " + SQLStat + " Exception : " + e, LogPrinter.ERROR);
					wr_srcLog.flush();
					return Constants.Zero_Key;
				}
			} catch (NumberFormatException e) {
				wr_srcLog.log("wr_src_Server (wr_srcRegisterRelation) : error format - " + SQLStat + "(" + wr_src_key + "," + RwrKey + "," + RsrcKey + ")", LogPrinter.ERROR);
				wr_srcLog.flush();
				return Constants.Zero_Key;
			}
		} else
			return Constants.Zero_Key;
	} // synchro
}
/**
 * Checks if the requested relation (with wrKey, srcKey, marketKey) exists in 'wr_src_Relations' DB.
 * @return wr_src_Key long - the unique key of the relation
 * <br> util.Constants.Zero_Key - if error has occured
 * <br> util.Constants.No_Key   - if the relation does not exists in the DB
 * <br> -5 - if the relation has the same date as today and there is no need for updating
 */

private long wr_srcResolveRelation(long pwrKey, int psrcKey, String pwr_srcTable) {
	long res_wr_src_Key = Constants.No_Key;
	java.sql.Date Last_Counted = new java.sql.Date(System.currentTimeMillis() - 90000000);
//	System.out.println("new = " + Last_Counted);
	String SQLStat = "SELECT " + dbFields.db_wr_src_key + ", " + dbFields.db_wr_src_rel_LastCount + " FROM " + pwr_srcTable + " WHERE " + dbFields.db_wrKey + " = " + String.valueOf(pwrKey) + " AND " + dbFields.db_srcKey + " = " + String.valueOf(psrcKey);
	try {
		if (wr_srcdbConn == null)
			throw new SQLException();
		Statement Stmt = wr_srcdbConn.createStatement();
		ResultSet RS = Stmt.executeQuery(SQLStat);
		if (RS.next()) {
			res_wr_src_Key = RS.getLong(1);
			Last_Counted = RS.getDate(2);
			while (RS.next()) {
				wr_srcLog.log("wr_src_Server (wr_srcResolveRelation) : INFO DUBLICATED (never will be used): wr_src_Key = " + RS.getLong(1) + " in " + pwr_srcTable + " table.", LogPrinter.ERROR);
				wr_srcLog.flush();
			}
		}
		RS.close();
		Stmt.close();
		wr_srcLog.log("wr_src_Server (wr_srcResolveRelation) : Relation has unique key : " + res_wr_src_Key + ", Last Counted on " + Last_Counted + " in " + pwr_srcTable + " table.", LogPrinter.DEBUG);

		// Here we check for a date = today

		if (Last_Counted.toString().equals(new java.sql.Date(System.currentTimeMillis()).toString())){
//			System.out.println("1.-----LasCounted field :" + Last_Counted + ": , Today is :" + Last_Counted + ":  STANA  OLE");
			wr_srcLog.log("wr_src_Server (wr_srcResolveRelation) : Relation is being updated today. It has unique key : " + res_wr_src_Key + ", Last Counted on " + Last_Counted + " in " + pwr_srcTable + " table.", LogPrinter.DEBUG);
//			System.out.println("Se varna -5");
			return -5;
		}
//			System.out.println("2.-----LasCounted field :" + Last_Counted + ": , Today is :" + Last_Counted + ":  STANA  OLE");
		return res_wr_src_Key;
	} catch (SQLException E) {
		if (wr_srcdbReconnect()) {
			wr_srcLog.log("wr_src_Server (wr_srcRegisterRelation) : db Reconnected.", LogPrinter.INFO);
			wr_srcLog.flush();
			return wr_srcResolveRelation(pwrKey, psrcKey, pwr_srcTable);
		} else {
			wr_srcLog.log("wr_src_Server (wr_srcRegisterRelation) : SQL Statement error - " + SQLStat + " Exception : " + E, LogPrinter.ERROR);
			wr_srcLog.flush();
			return Constants.Zero_Key;
		}
	}
}
/**
 * Deinits the servlet. Free all resources that the servlet had allocated with wr_srcServerInit() method.
 * @return boolean
 *	       <br> true  - if the method succeed
 * 		   <br> false - if the method failed but deinitin is done in hard way
 */
public boolean wr_srcServerDeInit() {
	try {
		if (wr_srcLog != null) {
			wr_srcLog.log("wr_src_Server (wr_srcServerDeInit) : --------- Deinitialisation begins ...", LogPrinter.INFO);
		}
		if (wr_srcdbConn != null) {
			wr_srcdbDisConnect();
		}
		wr_srcdbConn = null; // Connection to local DB
		IsReconn = false;
		db_Drivers = null;
		db_host = null;
		db_user = null;
		db_password = null;
		ScreenLogLevel = 0;
		FileLogLevel = 0;
		if (wr_srcLog != null) {
			wr_srcLog.log("wr_src_Server (wr_srcServerDeInit) : --------- Deinitialisation done.", LogPrinter.INFO);
			wr_srcLog.destroy();
		}
		wr_srcLog = null;
		return true;
	} catch (Exception e) {
		wr_srcdbConn = null; // Connection to local DB
		IsReconn = false;
		db_Drivers = null;
		db_host = null;
		db_user = null;
		db_password = null;
		ScreenLogLevel = -1;
		FileLogLevel = -1;
		wr_srcLog = null;
		return false;
	}
}
/**
 * Makes the primary init. This method allocates the base resources and sets the ServletState and <br>
 * ServletErrorState vaiables which hold the moment state of the servlet and the error(if occured).<br>
 * This method is requested by wrServer with parameters from wrServer's configuraation file.
 * @return ServletState byte - the state the servlet had fallen after execution of this method.
 */
 
public byte wr_srcServerInit(String Iwr_srcLogPath, int IScreenLogLevel, int IFileLogLevel, String Idb_Drivers, String Idb_host, String Idb_user, String Idb_password) {
	wr_srcServerDeInit();
	wr_srcLogPath = Iwr_srcLogPath;
	ScreenLogLevel = IScreenLogLevel;
	FileLogLevel = IFileLogLevel;
	db_Drivers = Idb_Drivers;
	db_host = Idb_host;
	db_user = Idb_user;
	db_password = Idb_password;
	if (wr_srcLog != null)
		wr_srcLog.flush();
	wr_srcLog = null;
	wr_srcLog = LogPrinter.makeLogPrinter(wr_srcLogPath);
	wr_srcLog.setLogLevel(FileLogLevel);
	wr_srcLog.setScreenLogLevel(ScreenLogLevel);
	if (wr_srcLog == null) {
		ServletState = Constants.INIT_ERROR;
		ServletErrorState = Constants.LOG_ERROR;
		return ServletState;
	}
	if (!wr_srcdbConnect()) {
		ServletState = Constants.INIT_ERROR;
		ServletErrorState = Constants.CONN_ERROR;		
		wr_srcLog.log("wr_src_Server (wr_srcServerInit) : Error in wr_srcServerInit() (dbConnect()).", LogPrinter.ERROR);
		wr_srcLog.flush();
		return ServletState;
	}
	if (wr_srcCheckTable() == null) {
		ServletState = Constants.INIT_ERROR;
		ServletErrorState = Constants.TABLES_ERROR;		
		wr_srcLog.log("wr_src_Server (wr_srcServerInit) : Error in creating tables.", LogPrinter.ERROR);
		wr_srcLog.flush();
		return ServletState;
	} else
		wr_srcLog.log("wr_src_Server (wr_srcServerInit) : Table is OK.", LogPrinter.INFO);
	wr_srcLog.log("wr_src_Server (wr_srcServerInit) : ---- Primery init finished. Servlet ready to work.", LogPrinter.INFO);
	wr_srcLog.flush();
	ServletState = Constants.READY;
	ServletErrorState = Constants.NO_ERROR;
	return ServletState;
}
/**
 * Updates the requested relation. It updates wr_srcLastCount propertie in 'wr_src_Relations' DB.
 * @return int
 *	       <br> number(0 ot greater than 0)  - the number of updated fields
 * 		   <br> -1 (Constants.cs_No_Key) - if the method failed
 */
private int wr_srcUpdateRelation(long wr_srcKey, String TableName) {
	String SQLStat = "UPDATE " + TableName + " SET " + dbFields.db_wr_src_rel_LastCount + " = '" + new java.sql.Date(System.currentTimeMillis()) + "' WHERE " + dbFields.db_wr_src_key + " = " + String.valueOf(wr_srcKey);
	try {
		if (wr_srcdbConn == null)
			throw new SQLException();
		Statement stmt = wr_srcdbConn.createStatement();
		int result = stmt.executeUpdate(SQLStat);
		wr_srcLog.log("wr_src_Server (wr_srcUpdateRelation) : Res = " + result + " for wr_src_Key = " + wr_srcKey + ", Table = " + TableName + " table.", LogPrinter.DEBUG);		
		stmt.close();
		return result;
	} catch (SQLException e) {
		if (wr_srcdbReconnect()) {
			wr_srcLog.log("wr_src_Server (wr_srcUpdateRelation) : db Reconnected.", LogPrinter.INFO);
			wr_srcLog.flush();
			return wr_srcUpdateRelation(wr_srcKey, TableName);
		} else {
			wr_srcLog.log("wr_src_Server (wr_srcUpdateRelation) : SQL Statement error - " + SQLStat + " Exception : " + e, LogPrinter.ERROR);
			wr_srcLog.flush();
			return Constants.No_Key;
		}
	} catch (NumberFormatException e) {
		wr_srcLog.log("wr_src_Server (wr_srcUpdateRelation) : error format - " + SQLStat, LogPrinter.ERROR);
		wr_srcLog.flush();
		return -1;
	}
}
}

