/*
 * $Id: VKCSysParameterSerializer.java,v 1.23 2007/08/01 14:56:52 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: VKCSysParameterSerializer.java,v $
 * Revision 1.23  2007/08/01 14:56:52  marbobo
 * + WebDav-Logging implementiert
 * - Sessionbegrenzung wird nicht mehr auf WebDav angewendet
 *
 * Revision 1.22  2006/07/13 12:24:29  lawern
 * Anpassung an PostgreSql
 *
 * Revision 1.21  2006/07/12 13:46:59  marbobo
 * + SysParameter anhand der Id sortieren
 *
 * Revision 1.20  2006/07/11 23:40:04  marbobo
 * + PostgreSQL ist pingelig und erlaubt kein get/setBoolean auf Int-Spalten
 *
 * Revision 1.19  2006/04/07 09:47:06  korowa
 * retrieveEnabledVKCStreams() wurde entfernt . Der Converter soll auf DB über den ConversionRequest zugreifen.
 *
 * Revision 1.18  2006/04/04 17:04:41  marbobo
 * + retrievEnabledVKCStreams() überarbeitet so dass es auch mit dem LicenseManager funktioniert
 *
 * Revision 1.17  2006/04/04 07:35:43  korowa
 * Eine Funktion hinzugefügt , die es einem Konverter ein Zugrif auf Systemparameter VKCSTREAMS gewährt.
 *
 * Revision 1.16  2005/08/30 13:34:15  jonyp
 * make sure that a trashId changes webshares static member too
 *
 * Revision 1.15  2005/08/24 13:41:16  marbobo
 * + Permanente Parameter hinzugefügt
 *
 * Revision 1.14  2005/08/19 15:10:26  jonyp
 * support for TrashCategory
 *
 * Revision 1.13  2005/01/20 15:25:52  marbobo
 * + Anpassungen an den Methoden getRootURL() und getContextName()
 *
 * Revision 1.12  2005/01/17 21:49:57  jonyp
 * retrieve only sysparameter whisch should not be hided!!!
 *
 * Revision 1.11  2004/12/05 22:57:47  marbobo
 * + Statement auf PreparedStatement umgestellt
 *
 * Revision 1.10  2004/11/24 09:25:55  lawern
 * Hibernate ist VKC-Geschichte!
 *
 * Revision 1.9  2004/11/10 15:02:44  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.8  2004/08/20 12:45:26  koppy
 * +clearCache()
 *
 * Revision 1.7  2004/07/15 12:37:12  jonyp
 * added comment block and method to retriev all SysParameters
 *
 *
 */

package vkc.db.serializer;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Iterator;

import java.sql.Connection;

import vkc.db.entities.VKCSysParameter;
import vkc.db.helper.DBHelper;
import vkc.exception.DBException;
import vkc.misc.VKCLogManager;
import vkc.util.ObjectCloner;
import vkc.view.WebShare;

public class VKCSysParameterSerializer {
	private static final HashMap paramCache = new HashMap();
	
	private VKCSysParameterSerializer() {
	}

	/**
	 * Lädt alle verfügbaren Contexts der Systemparameter und gibt sie als
	 * HashMap zurück
	 *
	 * @return Vector von String-Objekten
	 */
	public static final List retrieveContextNames()	throws DBException {
		Connection conn = null;
		PreparedStatement pStmt = null;
		ResultSet rs = null;

		try {
			conn = WebShare.database.getConnection();
			pStmt = conn.prepareStatement("SELECT context, MIN(sysparameterid) FROM sysparameters GROUP BY context ORDER BY 2 ASC");
			rs = pStmt.executeQuery();

			List ctxs = new ArrayList();

			while (rs.next()) {
				String context = new String(rs.getString("context"));
				ctxs.add(context);
			}

			return ctxs;

		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "1", "Error occured while retrieving Contexts of Sysparameters!", e);
			throw new DBException(e);
		} finally {
			DBHelper.close(rs);
			DBHelper.close(pStmt);
			DBHelper.close(conn);
		}
	}

	/**
	 * Lädt alle verfügbaren Contexts der Systemparameter und gibt sie als
	 * HashMap zurück
	 *
	 * @return Vector von String-Objekten
	 */
	public static final HashMap retrieveContextNameKeys() throws DBException {
		Connection conn = null;
		PreparedStatement pStmt = null;
		ResultSet rs = null;

		try {
			conn = WebShare.database.getConnection();
			pStmt = conn.prepareStatement("SELECT context, context_key, MIN(sysparameterid) FROM sysparameters GROUP BY context, context_key ORDER BY 3 ASC");
			rs = pStmt.executeQuery();

			HashMap ctxs = new HashMap();

			while (rs.next()) {
				String context = new String(rs.getString("context"));
				String contextKey = new String(rs.getString("context_key"));
				ctxs.put(context, contextKey);
			}

			return ctxs;
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "1", "Error occured while retrieving Contexts of Sysparameters!", e);
			throw new DBException(e);
		} finally {
			DBHelper.close(rs);
			DBHelper.close(pStmt);
			DBHelper.close(conn);
		}
	}

	/**
	 * Lädt alle verfügbaren Contexts der Systemparameter und gibt sie als
	 * HashMap zurück
	 *
	 * @return HashMap von VKCSysParameter-Objekten
	 */
	public static final List retrieveParameters() throws DBException {
		Connection conn = null;
		PreparedStatement pStmt = null;
		ResultSet rs = null;
				
		try {
			conn = WebShare.database.getConnection();
			pStmt = conn.prepareStatement("SELECT * FROM SysParameters ORDER BY sort_rank ASC");
			rs = pStmt.executeQuery();

			List sysParameters = new ArrayList();

			while (rs.next()) {
				VKCSysParameter param = new VKCSysParameter();
				setFields(param, rs);
				
				VKCSysParameter pParam = WebShare.getPermanentSystemParameter(param.getContext(), param.getName());
				
				if (pParam != null) {
					Integer id = param.getSysParameterId();
					param = (VKCSysParameter)ObjectCloner.deepCopy(pParam);
					param.setSysParameterId(id);
				}
				
				sysParameters.add(param);
			}

			return sysParameters;
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "1", "Error retrieving VKC sysparameters", e);
			throw new DBException(e);
		} finally {
			DBHelper.close(rs);
			DBHelper.close(pStmt);
			DBHelper.close(conn);
		}
	}

	private static void setFields(VKCSysParameter param, ResultSet rs) throws SQLException {
		param.setSysParameterId(new Integer(rs.getInt("sysParameterId")));
		param.setContext(rs.getString("context"));
		param.setContextKey(rs.getString("context_key"));
		param.setName(rs.getString("name"));
		param.setNameKey(rs.getString("name_key"));
		param.setValuestring(rs.getString("valuestring"));
		param.setDescription(rs.getString("description"));
		param.setDescrKey(rs.getString("descr_key"));

        param.setSortRank(new Integer(rs.getInt("sort_rank")));
        if (rs.wasNull()) param.setSortRank(null);

        param.setDatatype(new Integer(rs.getInt("datatype")));
		if (rs.wasNull()) param.setDatatype(null);

		param.setAllowNull(rs.getInt("allowNull") != 0);
		if (rs.wasNull()) param.setAllowNull(false);

		param.setReadOnly(rs.getInt("readonly") != 0);
		if (rs.wasNull()) param.setReadOnly(true);

		param.setHide(new Integer(rs.getInt("hide")));
		if (rs.wasNull()) param.setHide(null);
	}
	
	/**
	 * Holt den Wert eines SysParameters
	 *
	 * @param name Name des Systemparameters
	 *
	 * @return VKCSysParameter
	 */
	public static final String retrieveValue(String context, String name) throws DBException {
		Connection conn = null;
		PreparedStatement pStmt = null;
		ResultSet rs = null;

		VKCSysParameter pParam = WebShare.getPermanentSystemParameter(context, name);
		
		if (pParam != null) {
			return pParam.getValuestring();
		}

		synchronized(paramCache) {
			// Wert des Systemparameters ggfs. aus dem Cache holen
			if (paramCache.containsKey(context + "_" + name)) {
				return (String)paramCache.get(context + "_" + name);
			}
		}

		try {
			conn = WebShare.database.getConnection();
			pStmt = conn.prepareStatement("SELECT * FROM SysParameters WHERE context = ? AND name = ?");
			pStmt.setString(1, context);
			pStmt.setString(2, name);
			rs = pStmt.executeQuery();

			if (rs.next()) {
				String value = rs.getString("valuestring");
				
				synchronized(paramCache) {
					// aktuellen Wert in den Cache packen
					paramCache.put(context + "_" + name, value);
				}
				
				return value;
			} 

			return null;
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "1", "Error retrieving VKC sysparameter '" + name + "' (Context: '" + context + "')", e);
			throw new DBException(e);
		} finally {
			DBHelper.close(rs);
			DBHelper.close(pStmt);
			DBHelper.close(conn);
		}
	}

	/**
	 * Ändert den Wert eines VKCSysParameters
	 *
	 * @param context
	 * @param name
	 * @param value
	 */
	public static final void saveValue(String context, String name, String value)	throws DBException {
		Connection conn = null;
		PreparedStatement pStmt = null;

		VKCSysParameter pParam = WebShare.getPermanentSystemParameter(context, name);
		
		if (pParam != null) {
			return;
		}

		synchronized(paramCache) { // Wert wird immer aus dem Cache geworfen
			paramCache.remove(context + "_" + name);
			
			if ("TRASH".equals(context) && "TrashCategoryId".equals(name)) {
			    WebShare.setTrashCategory(null);
			}
		}

		try {
			conn = WebShare.database.getConnection();
			pStmt = conn.prepareStatement("UPDATE sysparameters SET valuestring = ? WHERE context = ? AND name = ? AND readOnly = 0");
			pStmt.setString(1, value);
			pStmt.setString(2, context);
			pStmt.setString(3, name);
			pStmt.execute();

			conn.commit();
		} catch (Exception e) {
			DBHelper.rollBack(conn);
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "1", "Error saving VKC sysparameter '" + name + "'" + " (Context: '" + context + "') with value: " + value, e);
			throw new DBException(e);
		} finally {
			DBHelper.close(pStmt);
			DBHelper.close(conn);
		}
	}
    
    /**
     * Ändert den Wert eines VKCSysParameters auch wenn dieser schreibgeschützt ist.
     *
     * @param context
     * @param name
     * @param value
     */
    public static final void saveReadOnlyValue(String context, String name, String value)   throws DBException {
        Connection conn = null;
        PreparedStatement pStmt = null;

        VKCSysParameter pParam = WebShare.getPermanentSystemParameter(context, name);
        
        if (pParam != null) {
            return;
        }

        synchronized(paramCache) { // Wert wird immer aus dem Cache geworfen
            paramCache.remove(context + "_" + name);
            
            if ("TRASH".equals(context) && "TrashCategoryId".equals(name)) {
                WebShare.setTrashCategory(null);
            }
        }

        try {
            conn = WebShare.database.getConnection();
            pStmt = conn.prepareStatement("UPDATE sysparameters SET valuestring = ? WHERE context = ? AND name = ?");
            pStmt.setString(1, value);
            pStmt.setString(2, context);
            pStmt.setString(3, name);
            pStmt.execute();

            conn.commit();
        } catch (Exception e) {
            DBHelper.rollBack(conn);
            VKCLogManager.errorLog(VKCSysParameterSerializer.class, "1", "Error saving VKC sysparameter '" + name + "'" + " (Context: '" + context + "') with value: " + value, e);
            throw new DBException(e);
        } finally {
            DBHelper.close(pStmt);
            DBHelper.close(conn);
        }
    }


	/**
	 * Holt den Wert eines SysParameters (mit DefaultWertvorgabe, falls es ihn nicht gibt) 
	 * 
	 * @param context         Name des Kontextes
	 * @param name            Name des Systemparameters
	 * @param fromDB          false: Wert aus der beim Startup geladenen HashMap
	 *                        true:  Wert aus der DB-Tabelle holen
	 * @return value          Wert des Systemparameters (vom Typ String)      
	 */	
	public static String retrieveValue(String context, String name, String defaultValue) throws DBException {
    	String value = retrieveValue(context, name);

    	if (value != null) {
    		return value;
    	} 

    	return defaultValue;
	}
	
	public static int retrieveIntValue(String context, String name) throws DBException {
		return Integer.parseInt(retrieveValue(context, name));
	}

	public static int retrieveIntValue(String context, String name, int defaultValue) throws DBException {
		String value = retrieveValue(context, name);

		if (value != null) {
			return Integer.parseInt(value);
		} 

		return defaultValue;
	}

	public final static boolean isQuotaCheckingEnabled() {
		try {
			return retrieveIntValue("QUOTA", "EnableQuotaChecking", 0) != 0;
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "", e.getMessage(), e);
			
			return false;
		}
	}

	public final static boolean isProjectManagementEnabled() {
		try {
			return retrieveIntValue("PROJECTMANAGEMENT", "EnableProjectManagement", 0) != 0;
		} catch ( Exception e ) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "", e.getMessage(), e);
			
			return false;
		}
	}

	public final static boolean getListAccessibleCategoriesOnly() {
		try {
			return retrieveIntValue("CATEGORYVIEW", "ListAccessibleCategoriesOnly", 0) == 1;
		} catch ( Exception e ) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "", e.getMessage(), e);
			
			return false;
		}
	}

	public final static boolean getDisplayAscii() {
		try {
			return retrieveIntValue("CATEGORYVIEW", "ShowDisplayAscii", 0) != 0;
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "", e.getMessage(), e);
			
			return false;
		}
	}

	/**
	 * Method returns the (absolute) root URL (only Hostname without Contextname) 
	 * of the current web application. It is guaranteed that the returned URL ends
	 * without a slash.
	 * <p>
	 * @return webapplication root URL (only Hostname without Contextname)
	 */
	public final static String getRootURL() {
		try {
			String value = retrieveValue("MAIL", "RootURL", "");
			
			return value.trim().endsWith("/") ? value.trim().substring(0, value.trim().lastIndexOf("/")) : value.trim();
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "", e.getMessage(), e);
			
			return "";
		}
	}
	
	public final static int getProjectsRootCategoryId() {
		try {
			return retrieveIntValue("PROJECTMANAGEMENT", "ProjectRootCategoryId", 0);
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "", e.getMessage(), e);
			
			return 0;
		}
	}

	public final static int getTemplatesRootCategoryId() {
		try {
			return retrieveIntValue("PROJECTMANAGEMENT", "TemplatesRootCategoryId", 0);
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "", e.getMessage(), e);
			
			return 0;
		}
	}

	public final static int getFunctionalViewsRootCategoryId() {
		try {
			return retrieveIntValue("FUNCTIONALVIEW", "FunctionalViewRootCategoryId", 0);
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "", e.getMessage(), e);
			
			return 0;
		}
	}	

	public final static int getTrashCategoryId() {
		try {
			return retrieveIntValue("TRASH", "TrashCategoryId", 0);
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "", e.getMessage(), e);
			
			return 0;
		}
	}	

	public final static boolean isTrashEnabled() {
		try {
			return retrieveIntValue("TRASH", "EnableTrash", 0) != 0;
		} catch (Exception e) {
			VKCLogManager.errorLog(VKCSysParameterSerializer.class, "", e.getMessage(), e);
			
			return false;
		}
	}
	

	/**
	 * Method returns the HashMap of SysParameters-Objects
	 * (Key:  <context>_<name>)
	 * <p>
	 * @return HashMap of VKCSysParameters-Objects  
	 */
    public final static HashMap getAllSysParameters() throws DBException {
    	HashMap allSysParams = new HashMap();
    	List sysParameters = retrieveParameters();
    	
		for (Iterator iter = sysParameters.iterator() ; iter.hasNext() ;) {
			VKCSysParameter param = (VKCSysParameter)iter.next();
            allSysParams.put(param.getContext() + "_" + param.getName(), param);
		}
    	
    	return allSysParams;
    }
	
    /**
     * Clears the cache for the system parameters.
     * Used by the workflow-component, running within Shark.
     */
    public static final void clearCache(){
        VKCSysParameterSerializer.paramCache.clear();
    }
}