/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (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.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * 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 com.queplix.core.modules.config.utils.db;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.integrator.security.User;
import com.queplix.core.modules.config.utils.UserPropertyConfigDAO;
import com.queplix.core.modules.config.utils.UserPropertyID;
import com.queplix.core.utils.dao.AbstractDAO;
import com.queplix.core.utils.sql.SqlWrapper;
import com.queplix.core.utils.sql.SqlWrapperFactory;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * Project-specific implementation of the UserPropertyConfigDAO
 *
 * @author [ALB] Baranov Andrey
 * @version $Revision: 1.1.1.1 $ $Date: 2005/09/12 15:30:18 $
 */

public class UserPropertyConfigDAOImpl
        extends AbstractDAO implements UserPropertyConfigDAO {

    // --------------------------------------------------------------- Constants

    private static final int MAX_ID_SIZE = 512;
    private static final int MAX_VALUE_SIZE = 2048;

    // --------------------------------------------------------------- Variables

    protected SqlWrapper sqlWrapper = SqlWrapperFactory.getSqlWrapper();

    // --------------------------------------------------------------- Overrided Methods

    public int deleteUserProperty(UserPropertyID userPropertyID) {
        Connection con = null;
        PreparedStatement ps = null;

        try {
            con = sqlWrapper.doConnection();
            ps = sqlWrapper.doPreparedStatement(con, DBRealmManager.getSql(
                    "delete_user_prop"));
            ps.setString(1, userPropertyID.getId());
            ps.setLong(2, userPropertyID.getUserId());
            ps.setInt(3, userPropertyID.getUserAuthenticationType());

            return sqlWrapper.executeUpdate(ps);

        } catch (SQLException ex) {
            throw new GenericSystemException(
                    "SQL exception: " + ex.getMessage(), ex);

        } finally {
            sqlWrapper.closeConnection(con, ps);
        }
    }

    public int deleteUserPropertiesLike(User user, String likeString) {
        Connection con = null;
        PreparedStatement ps = null;

        try {
            con = sqlWrapper.doConnection();
            ps = sqlWrapper.doPreparedStatement(con, DBRealmManager.getSql(
                    "delete_user_prop_starts_with"));
            ps.setLong(1, user.getUserID());
            ps.setInt(2, user.getAuthenticationType());
            ps.setString(3, likeString + "%");

            return sqlWrapper.executeUpdate(ps);

        } catch (SQLException ex) {
            throw new GenericSystemException(
                    "SQL exception: " + ex.getMessage(), ex);

        } finally {
            sqlWrapper.closeConnection(con, ps);
        }
    }

    /*
     * No javadoc
     * @see UserPropertyConfigDAO#createUserProperty
     */
    public int createUserProperty(UserPropertyID userPropertyID,
                                  String userProperty) {

        // Checking.
        checkUserProperty(userPropertyID, userProperty);

        Connection con = null;
        PreparedStatement ps = null;

        try {
            con = sqlWrapper.doConnection();
            ps = sqlWrapper.doPreparedStatement(con, DBRealmManager.getSql(
                    "insert_user_prop"));
            ps.setString(1, userPropertyID.getId());
            ps.setLong(2, userPropertyID.getUserId());
            ps.setInt(3, userPropertyID.getUserAuthenticationType());
            ps.setString(4, userProperty);

            return sqlWrapper.executeUpdate(ps);

        } catch (SQLException ex) {
            throw new GenericSystemException(
                    "SQL exception: " + ex.getMessage(), ex);

        } finally {
            sqlWrapper.closeConnection(con, ps);
        }
    }

    /*
     * No javadoc
     * @see UserPropertyConfigDAO#updateUserProperty
     */
    public int updateUserProperty(UserPropertyID userPropertyID,
                                  String userProperty) {

        // Checking.
        checkUserProperty(userPropertyID, userProperty);

        Connection con = null;
        PreparedStatement ps = null;

        try {
            con = sqlWrapper.doConnection();
            ps = sqlWrapper.doPreparedStatement(con, DBRealmManager.getSql(
                    "update_user_prop"));
            ps.setString(1, userProperty);
            ps.setString(2, userPropertyID.getId());
            ps.setLong(3, userPropertyID.getUserId());
            ps.setInt(4, userPropertyID.getUserAuthenticationType());

            return sqlWrapper.executeUpdate(ps);

        } catch (SQLException ex) {
            throw new GenericSystemException(
                    "SQL exception: " + ex.getMessage(), ex);

        } finally {
            sqlWrapper.closeConnection(con, ps);
        }
    }

    /*
     * No javadoc
     * @see UserPropertyConfigDAO#loadUserProperty
     */
    public String loadUserProperty(UserPropertyID userPropertyID) {

        Connection con = null;
        PreparedStatement ps = null;

        String userProperty = null;

        try {
            con = sqlWrapper.doConnection();
            ps = sqlWrapper.doPreparedStatement(con, DBRealmManager.getSql(
                    "select_user_prop"));
            ps.setString(1, userPropertyID.getId());
            ps.setLong(2, userPropertyID.getUserId());
            ps.setInt(3, userPropertyID.getUserAuthenticationType());
            ResultSet rs = sqlWrapper.executeQuery(ps);
            if(rs.next()) {
                userProperty = sqlWrapper.getStringParser().getValue(rs, 1);
            }

        } catch (SQLException ex) {
            throw new GenericSystemException(
                    "SQL exception: " + ex.getMessage(), ex);
        } finally {
            sqlWrapper.closeConnection(con, ps);
        }

        return userProperty;
    }

    /*
     * No javadoc
     * @see UserPropertyConfigDAO#v
     */
    public Map<String, String> loadAllUserProperty(User user) {

        Connection con = null;
        PreparedStatement ps = null;

        Map<String, String> propMap = new HashMap<String, String>();

        try {
            con = sqlWrapper.doConnection();
            ps = sqlWrapper.doPreparedStatement(con, DBRealmManager.getSql(
                    "select_all_user_prop"));
            ps.setLong(1, user.getUserID());
            ps.setInt(2, user.getAuthenticationType());

            ResultSet rs = sqlWrapper.executeQuery(ps);
            parseResult(rs, propMap);
        } catch (SQLException ex) {
            throw new GenericSystemException(
                    "SQL exception: " + ex.getMessage(), ex);
        } finally {
            sqlWrapper.closeConnection(con, ps);
        }
        return propMap;
    }

    public Map<String, String> loadUserPropertiesLike(User user,
                                                      String propsLike) {
        Connection con = null;
        PreparedStatement ps = null;

        Map<String, String> propMap = new HashMap<String, String>();

        try {
            con = sqlWrapper.doConnection();
            ps = sqlWrapper.doPreparedStatement(con, DBRealmManager.getSql(
                    "select_user_prop_starts_with"));
            ps.setLong(1, user.getUserID());
            ps.setInt(2, user.getAuthenticationType());
            ps.setString(3, propsLike + "%");

            ResultSet rs = sqlWrapper.executeQuery(ps);
            parseResult(rs, propMap);
        } catch (SQLException ex) {
            throw new GenericSystemException(
                    "SQL exception: " + ex.getMessage(), ex);
        } finally {
            sqlWrapper.closeConnection(con, ps);
        }
        return propMap;
    }

    private void parseResult(ResultSet rs, Map<String, String> propMap)
            throws SQLException {
        while(rs.next()) {
            String propId = sqlWrapper.getStringParser().getValue(rs, 1);
            String propVal = sqlWrapper.getStringParser().getValue(rs, 2);
            propMap.put(propId, propVal);
        }
    }

    // ----------------------------------------------------------------- private methods

    // Checks user property.

    private void checkUserProperty(UserPropertyID userPropertyID,
                                   String value) {
        String id = userPropertyID.getId();

        if(id == null) {
            throw new GenericSystemException("Property ID is NULL");
        }

        if(id.length() >= MAX_ID_SIZE) {
            throw new GenericSystemException(
                    "Property ID length is greater than MAX_ID_SIZE, id=" + id);
        }

        if(value != null && value.length() >= MAX_VALUE_SIZE) {
            throw new GenericSystemException(
                    "Property value length is greater than MAX_VALUE_SIZE, "
                            + "id=" + id + ", value=" + value);
        }
    }
}
