<commit_before>package com.lagunex.vertica;

import com.lagunex.util.StringUtils;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

// external dependency to connect with Vertica
import javax.sql.DataSource;

// high level external dependencies to facilitate the execution of queries
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

/**
 * Singleton that connects with the Vertica database and performs query to retrieve analytics
 * or inserts new records in the database
 * 
 * This class assumes that the following system properties are defined:
 * 
 * vertica.hostname
 * vertica.database
 * vertica.username
 * vertica.password
 * 
 * This property must be passed at runtime using Java's -D option 
 * 
 * @author <NAME>. <<EMAIL>>
 */
public class Vertica {
    private static final Logger LOGGER = Logger.getLogger(Vertica.class.getName());

    private static final String HOSTNAME = "vertica.hostname";
    private static final String DATABASE = "vertica.database";
    private static final String USERNAME = "vertica.username";
    private static final String PASSWORD = "<PASSWORD>";

    private static Vertica instance;
    public static Vertica getInstance() {
        if (instance == null) {
            instance = new Vertica();
        }
        return instance;
    }

    private final JdbcTemplate jdbcTemplate;

    private Vertica() {
        checkSystemProperties();
        DataSource dataSource = createDataSource();
        jdbcTemplate = new JdbcTemplate(dataSource); 
    }

    private void checkSystemProperties() {
        String message = "property %s not defined";
        String missingProperty = null;
        if (System.getProperty(HOSTNAME) == null) {
            missingProperty = HOSTNAME;
        } else if (System.getProperty(DATABASE) == null) {
            missingProperty = DATABASE;
        } else if (System.getProperty(PASSWORD) == null) {
            missingProperty = PASSWORD;
        } else if (System.getProperty(USERNAME) == null) {
            missingProperty = USERNAME;
        }

        if (missingProperty != null) {
            throw new RuntimeException(String.format(message, missingProperty));
        }
    }

    private DataSource createDataSource() {
        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriverClass(com.vertica.jdbc.Driver.class);
        dataSource.setUrl(String.format("jdbc:vertica://%s:5433/%s",
            System.getProperty(HOSTNAME), System.getProperty(DATABASE)
        ));
        dataSource.setUsername(System.getProperty(USERNAME));
        dataSource.setPassword(System.getProperty(PASSWORD));       
        return dataSource;
    }

    /**
     * 
     * @param tblRecord line with the info to insert. Each column separated by separator
     * @param separator String that represents the column separator in tblRecord
     * @return number of rows inserted
     */
    public int insertTweetRecord(String tblRecord, String separator) {
        String query = "insert into tweet values (?,?,?,?,?,?)";

        // we should split by separator only when it is not escaped
        Object[] args = tblRecord.split(String.format("(?<!\\\\)\\%s", separator));
        
        if (args.length != 6 && args.length != 4) { // invalid format
            LOGGER.log(Level.WARNING, "Invalid line: {0}", tblRecord);
            return 0;
        }
      
        // Restored the original message with unescaped characters and line breaks
        String unescapedMessage = StringUtils.unescape(args[1].toString(), separator);
        args[1] = StringUtils.uncollapseLines(unescapedMessage);
        if (args.length == 4) { // does not include aggregate data
            query = "insert into tweet (id, message, lang, created_at) values (?,?,?,?)";
        }
        
        return insertRecord(query, args);
    }

    /**
     * Insert a record following the insert query and returns the numbers of rows inserted
     * 
     * @param insert query to build the statement<commit_msg>fix typo in comment<commit_after>package com.lagunex.vertica;

import com.lagunex.util.StringUtils;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

// external dependency to connect with Vertica
import javax.sql.DataSource;

// high level external dependencies to facilitate the execution of queries
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

/**
 * Singleton that connects with the Vertica database and performs query to retrieve analytics
 * or inserts new records in the database
 * 
 * This class assumes that the following system properties are defined:
 * 
 * vertica.hostname
 * vertica.database
 * vertica.username
 * vertica.password
 * 
 * This property must be passed at runtime using Java's -D option 
 * 
 * @author <NAME>. <<EMAIL>>
 */
public class Vertica {
    private static final Logger LOGGER = Logger.getLogger(Vertica.class.getName());

    private static final String HOSTNAME = "vertica.hostname";
    private static final String DATABASE = "vertica.database";
    private static final String USERNAME = "vertica.username";
    private static final String PASSWORD = "<PASSWORD>";

    private static Vertica instance;
    public static Vertica getInstance() {
        if (instance == null) {
            instance = new Vertica();
        }
        return instance;
    }

    private final JdbcTemplate jdbcTemplate;

    private Vertica() {
        checkSystemProperties();
        DataSource dataSource = createDataSource();
        jdbcTemplate = new JdbcTemplate(dataSource); 
    }

    private void checkSystemProperties() {
        String message = "property %s not defined";
        String missingProperty = null;
        if (System.getProperty(HOSTNAME) == null) {
            missingProperty = HOSTNAME;
        } else if (System.getProperty(DATABASE) == null) {
            missingProperty = DATABASE;
        } else if (System.getProperty(PASSWORD) == null) {
            missingProperty = PASSWORD;
        } else if (System.getProperty(USERNAME) == null) {
            missingProperty = USERNAME;
        }

        if (missingProperty != null) {
            throw new RuntimeException(String.format(message, missingProperty));
        }
    }

    private DataSource createDataSource() {
        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriverClass(com.vertica.jdbc.Driver.class);
        dataSource.setUrl(String.format("jdbc:vertica://%s:5433/%s",
            System.getProperty(HOSTNAME), System.getProperty(DATABASE)
        ));
        dataSource.setUsername(System.getProperty(USERNAME));
        dataSource.setPassword(System.getProperty(PASSWORD));       
        return dataSource;
    }

    /**
     * 
     * @param tblRecord line with the info to insert. Each column separated by separator
     * @param separator String that represents the column separator in tblRecord
     * @return number of rows inserted
     */
    public int insertTweetRecord(String tblRecord, String separator) {
        String query = "insert into tweet values (?,?,?,?,?,?)";

        // we should split by separator only when it is not escaped
        Object[] args = tblRecord.split(String.format("(?<!\\\\)\\%s", separator));
        
        if (args.length != 6 && args.length != 4) { // invalid format
            LOGGER.log(Level.WARNING, "Invalid line: {0}", tblRecord);
            return 0;
        }
      
        // Restore the original message with unescaped characters and line breaks
        String unescapedMessage = StringUtils.unescape(args[1].toString(), separator);
        args[1] = StringUtils.uncollapseLines(unescapedMessage);
        if (args.length == 4) { // does not include aggregate data
            query = "insert into tweet (id, message, lang, created_at) values (?,?,?,?)";
        }
        
        return insertRecord(query, args);
    }

    /**
     * Insert a record following the insert query and returns the numbers of rows inserted
     * 
     * @param insert query to build the statement
{'fraction_non_alphanumeric': 0.09862202482632958, 'fraction_numerical': 0.0025054094066734997, 'mean_word_length': 2.948741007194245, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2652486', 'n_tokens_mistral': 2333, 'n_tokens_neox': 2252, 'n_words': 688}