<commit_before>package edu.wustl.cab2b.server.path;

import static edu.wustl.cab2b.common.errorcodes.ErrorCodeConstants.DB_0003;
import static edu.wustl.cab2b.common.errorcodes.ErrorCodeConstants.DE_0004;
import static edu.wustl.cab2b.common.errorcodes.ErrorCodeConstants.IO_0001;
import static edu.wustl.cab2b.common.util.Constants.CONNECTOR;
import static edu.wustl.cab2b.server.path.PathConstants.ASSOCIATION_FILE_NAME;
import static edu.wustl.cab2b.server.path.PathConstants.FIELD_SEPARATOR;
import static edu.wustl.cab2b.server.path.PathConstants.INTER_MODEL_ASSOCIATION_FILE_NAME;
import static edu.wustl.cab2b.server.path.PathConstants.INTRA_MODEL_ASSOCIATION_FILE_NAME;
import static edu.wustl.cab2b.server.path.PathConstants.PATH_FILE_NAME;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import edu.common.dynamicextensions.domaininterface.AssociationInterface;
import edu.common.dynamicextensions.domaininterface.AttributeInterface;
import edu.common.dynamicextensions.domaininterface.EntityGroupInterface;
import edu.common.dynamicextensions.domaininterface.EntityInterface;
import edu.common.dynamicextensions.domaininterface.SemanticPropertyInterface;
import edu.common.dynamicextensions.entitymanager.EntityManager;
import edu.common.dynamicextensions.entitymanager.EntityManagerInterface;
import edu.common.dynamicextensions.exception.DynamicExtensionsApplicationException;
import edu.common.dynamicextensions.exception.DynamicExtensionsSystemException;
import edu.wustl.cab2b.common.exception.RuntimeException;
import edu.wustl.cab2b.common.util.IdGenerator;
import edu.wustl.cab2b.common.util.PropertyLoader;
import edu.wustl.cab2b.common.util.Utility;
import edu.wustl.cab2b.server.path.PathConstants.AssociationType;
import edu.wustl.cab2b.server.path.pathgen.GraphPathFinder;
import edu.wustl.cab2b.server.path.pathgen.Path;
import edu.wustl.cab2b.server.path.pathgen.PathToFileWriter;
import edu.wustl.cab2b.server.util.DataFileLoaderInterface;
import edu.wustl.cab2b.server.util.SQLQueryUtil;
import edu.wustl.cab2b.server.util.ServerProperties;
import edu.wustl.common.util.logger.Logger;

/**
 * This class builds all paths for a Domain Model of an application.<br>
 * This class acts as a Controller that calls different utility classes to build
 * all possible non-redundent paths for a given model. It also loads the
 * generated paths to database.<br>
 * This class decides whether to create a storage table for entity or not based
 * on {@link edu.wustl.cab2b.server.path.PathConstants#CREATE_TABLE_FOR_ENTITY}
 * To create a table for entity set this to TRUE before calling this code else
 * set it to false. <b> NOTE : </b> It does not creates PATH table. It assumes
 * that the table is already been present in database.<br>
 * 
 * @author <NAME>
 * @author Munesh
 */
public class PathBuilder {
    private static final int PATH_MAX_LENGTH = 6;

    /**
     * This facilitates fast path building
     */
    private static HashMap<String, EntityGroupInterface> shortNameVsEntityGroup = new HashMap<String, EntityGroupInterface>();

    /**
     * This facilitates fast path transformation
     */
    private static HashMap<Long, AssociationInterface> idVsAssociation = new HashMap<Long, AssociationInterface>();

    /**
     * This facilitates fast path transformation
     */
    private static HashMap<String, List<AssociationInterface>> srcDesVsAssociations = new HashMap<String, List<AssociationInterface>>();

    private static DataFileLoaderInterface dataFileLoader;

    /**
     * Builds all non-redundent paths for traversal between classes from a given
     * domain model. This method is to be called at server startup. It writes
     * all paths to {@link PathConstants#PATH_FILE_NAME} and stores paths to
     * database
     * 
     * @param connection -
     *            Database connection to use to fire SQLs.
     */
    private static void buildAndLoadAllModels(Connection connection) {
        File file = new File(PATH_FILE_NAME);
        if (file.exists() && !file.delete()) {
            throw new RuntimeException("Could not delete " + PATH_FILE_NAME);
        }
        Logger.out.info("Deleted the file : " + PATH_FILE_NAME);
        String[] applicationNames = PropertyLoader.getAllApplications();
        for (String applicationName : applicationNames) {
            Logger.out.info("Processing : " + applicationName);
            String path = PropertyLoader.getModelPath(applicationName);
            DomainModelParser parser = new DomainModelParser(path);
            DomainModelProcessor processor = null;
            try {
                processor = new DomainModelProcessor(parser, applicationName);
                storeModelAndGeneratePaths(processor, applicationName, connection, true);
            } catch (DynamicExtensionsSystemException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw new RuntimeException("got DynamicExtensionsSystemException in buildAndLoadAllModels", e);
            } catch (DynamicExtensionsApplicationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw new RuntimeException("got DynamicExtensionsApplicationException in buildAndLoadAllModels", e);
            }
        }
        transformAndLoadPaths(connection);

        if (applicationNames.length < 2)
            return;
        /* ------------------------------------------------------------------------- 
            TODO need to check whether we should remove this code or not
        ---------------------------------------------------------------------------*/

//        for (int i = 0; i < applicationNames.length; i++) {
//            for (int j = i + 1; j < applicationNames.length; j++) {
//                EntityGroupInterface leftEntityGroup = shortNameVsEntityGroup.get(applicationNames[i]);
//                EntityGroupInterface rightEntityGroup = shortNameVsEntityGroup.get(applicationNames[j]);
//                storeInterModelConnections(leftEntityGroup, rightEntityGroup, connection);
//            }
//        }
    }

    /**
     * Builds all non-redundent paths for traversal between classes from a given
     * domain model. This method is used to load models one at a time. All inter
     * model associations which current model has with already loaded models are
     * also stored. It writes all paths to {@link PathConstants#PATH_FILE_NAME}
     * and stores paths to database
     * 
     * @param connection -
     *            Database connection to use to fire SQLs.
     * @param xmlFilePath
     *            The file system path from where the the domain model extract
     *            is present
     * @param applicationName
     *            Name of the application. The Entity Group will have this as
     *            its shoprt name.
     *            
     * @param maxPathLength max length (no. of classes) in path.
     */
    public static void loadSingleModel(Connection connection, String xmlFilePath, String applicationName,
                                       int maxPathLength) {
        DomainModelParser parser = new DomainModelParser(xmlFilePath);
        loadSingleModelFromParserObject(connection, parser, applicationName, maxPathLength);
    }

    /**
     * Builds all non-redundant paths, with a specified max length, for traversal between classes from a given
     * domain model. This method is used to load models one at a time. All inter
     * model associations which current model has with already loaded models are
     * also stored. It writes all paths to {@link PathConstants#PATH_FILE_NAME}
     * and stores paths to database
     * 
     * @param connection -
     *            Database connection to use to fire SQLs.
     * @param parser
     *            DomainModelParser object
     * @param applicationName
     *            Name of the application. The Entity Group will have this as
     *            its shoprt name.
     * @param maxPathLength max length (no. of classes) in path.
     */
    public static void loadSingleModelFromParserObject(Connection connection, DomainModelParser parser,
                                                       String applicationName, int maxPathLength) {
        DomainModelProcessor processor = null;
        try {
            processor = new DomainModelProcessor(parser, applicationName);
        } catch (DynamicExtensionsSystemException e) {
            Logger.out.error("Exception while loading model in DE", e);
            throw new RuntimeException("Exception while loading model in DE", e);
        } catch (DynamicExtensionsApplicationException e) {
            Logger.out.error("Exception while loading model in DE", e);<commit_msg>Added synchronized to methods to avoid concurrent inserts<commit_after>package edu.wustl.cab2b.server.path;

import static edu.wustl.cab2b.common.errorcodes.ErrorCodeConstants.DB_0003;
import static edu.wustl.cab2b.common.errorcodes.ErrorCodeConstants.DE_0004;
import static edu.wustl.cab2b.common.errorcodes.ErrorCodeConstants.IO_0001;
import static edu.wustl.cab2b.common.util.Constants.CONNECTOR;
import static edu.wustl.cab2b.server.path.PathConstants.ASSOCIATION_FILE_NAME;
import static edu.wustl.cab2b.server.path.PathConstants.FIELD_SEPARATOR;
import static edu.wustl.cab2b.server.path.PathConstants.INTER_MODEL_ASSOCIATION_FILE_NAME;
import static edu.wustl.cab2b.server.path.PathConstants.INTRA_MODEL_ASSOCIATION_FILE_NAME;
import static edu.wustl.cab2b.server.path.PathConstants.PATH_FILE_NAME;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import edu.common.dynamicextensions.domaininterface.AssociationInterface;
import edu.common.dynamicextensions.domaininterface.AttributeInterface;
import edu.common.dynamicextensions.domaininterface.EntityGroupInterface;
import edu.common.dynamicextensions.domaininterface.EntityInterface;
import edu.common.dynamicextensions.domaininterface.SemanticPropertyInterface;
import edu.common.dynamicextensions.entitymanager.EntityManager;
import edu.common.dynamicextensions.entitymanager.EntityManagerInterface;
import edu.common.dynamicextensions.exception.DynamicExtensionsApplicationException;
import edu.common.dynamicextensions.exception.DynamicExtensionsSystemException;
import edu.wustl.cab2b.common.exception.RuntimeException;
import edu.wustl.cab2b.common.util.IdGenerator;
import edu.wustl.cab2b.common.util.PropertyLoader;
import edu.wustl.cab2b.common.util.Utility;
import edu.wustl.cab2b.server.path.PathConstants.AssociationType;
import edu.wustl.cab2b.server.path.pathgen.GraphPathFinder;
import edu.wustl.cab2b.server.path.pathgen.Path;
import edu.wustl.cab2b.server.path.pathgen.PathToFileWriter;
import edu.wustl.cab2b.server.util.DataFileLoaderInterface;
import edu.wustl.cab2b.server.util.SQLQueryUtil;
import edu.wustl.cab2b.server.util.ServerProperties;
import edu.wustl.common.util.logger.Logger;

/**
 * This class builds all paths for a Domain Model of an application.<br>
 * This class acts as a Controller that calls different utility classes to build
 * all possible non-redundent paths for a given model. It also loads the
 * generated paths to database.<br>
 * This class decides whether to create a storage table for entity or not based
 * on {@link edu.wustl.cab2b.server.path.PathConstants#CREATE_TABLE_FOR_ENTITY}
 * To create a table for entity set this to TRUE before calling this code else
 * set it to false. <b> NOTE : </b> It does not creates PATH table. It assumes
 * that the table is already been present in database.<br>
 * 
 * @author <NAME>
 * @author Munesh
 */
public class PathBuilder {
    private static final int PATH_MAX_LENGTH = 6;

    /**
     * This facilitates fast path building
     */
    private static HashMap<String, EntityGroupInterface> shortNameVsEntityGroup = new HashMap<String, EntityGroupInterface>();

    /**
     * This facilitates fast path transformation
     */
    private static HashMap<Long, AssociationInterface> idVsAssociation = new HashMap<Long, AssociationInterface>();

    /**
     * This facilitates fast path transformation
     */
    private static HashMap<String, List<AssociationInterface>> srcDesVsAssociations = new HashMap<String, List<AssociationInterface>>();

    private static DataFileLoaderInterface dataFileLoader;

    /**
     * Builds all non-redundent paths for traversal between classes from a given
     * domain model. This method is to be called at server startup. It writes
     * all paths to {@link PathConstants#PATH_FILE_NAME} and stores paths to
     * database
     * 
     * @param connection -
     *            Database connection to use to fire SQLs.
     */
    private static synchronized void buildAndLoadAllModels(Connection connection) {
        File file = new File(PATH_FILE_NAME);
        if (file.exists() && !file.delete()) {
            throw new RuntimeException("Could not delete " + PATH_FILE_NAME);
        }
        Logger.out.info("Deleted the file : " + PATH_FILE_NAME);
        String[] applicationNames = PropertyLoader.getAllApplications();
        for (String applicationName : applicationNames) {
            Logger.out.info("Processing : " + applicationName);
            String path = PropertyLoader.getModelPath(applicationName);
            DomainModelParser parser = new DomainModelParser(path);
            DomainModelProcessor processor = null;
            try {
                processor = new DomainModelProcessor(parser, applicationName);
                storeModelAndGeneratePaths(processor, applicationName, connection, true);
            } catch (DynamicExtensionsSystemException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw new RuntimeException("got DynamicExtensionsSystemException in buildAndLoadAllModels", e);
            } catch (DynamicExtensionsApplicationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw new RuntimeException("got DynamicExtensionsApplicationException in buildAndLoadAllModels", e);
            }
        }
        transformAndLoadPaths(connection);

        if (applicationNames.length < 2)
            return;
        /* ------------------------------------------------------------------------- 
            TODO need to check whether we should remove this code or not
        ---------------------------------------------------------------------------*/

//        for (int i = 0; i < applicationNames.length; i++) {
//            for (int j = i + 1; j < applicationNames.length; j++) {
//                EntityGroupInterface leftEntityGroup = shortNameVsEntityGroup.get(applicationNames[i]);
//                EntityGroupInterface rightEntityGroup = shortNameVsEntityGroup.get(applicationNames[j]);
//                storeInterModelConnections(leftEntityGroup, rightEntityGroup, connection);
//            }
//        }
    }

    /**
     * Builds all non-redundent paths for traversal between classes from a given
     * domain model. This method is used to load models one at a time. All inter
     * model associations which current model has with already loaded models are
     * also stored. It writes all paths to {@link PathConstants#PATH_FILE_NAME}
     * and stores paths to database
     * 
     * @param connection -
     *            Database connection to use to fire SQLs.
     * @param xmlFilePath
     *            The file system path from where the the domain model extract
     *            is present
     * @param applicationName
     *            Name of the application. The Entity Group will have this as
     *            its shoprt name.
     *            
     * @param maxPathLength max length (no. of classes) in path.
     */
    public static synchronized void loadSingleModel(Connection connection, String xmlFilePath, String applicationName,
                                       int maxPathLength) {
        DomainModelParser parser = new DomainModelParser(xmlFilePath);
        loadSingleModelFromParserObject(connection, parser, applicationName, maxPathLength);
    }

    /**
     * Builds all non-redundant paths, with a specified max length, for traversal between classes from a given
     * domain model. This method is used to load models one at a time. All inter
     * model associations which current model has with already loaded models are
     * also stored. It writes all paths to {@link PathConstants#PATH_FILE_NAME}
     * and stores paths to database
     * 
     * @param connection -
     *            Database connection to use to fire SQLs.
     * @param parser
     *            DomainModelParser object
     * @param applicationName
     *            Name of the application. The Entity Group will have this as
     *            its shoprt name.
     * @param maxPathLength max length (no. of classes) in path.
     */
    public static synchronized void loadSingleModelFromParserObject(Connection connection, DomainModelParser parser,
                                                       String applicationName, int maxPathLength) {
        DomainModelProcessor processor = null;
        try {
            processor = new DomainModelProcessor(parser, applicationName);
        } catch (DynamicExtensionsSystemException e) {
            Logger.out.error("Exception while loading model in DE", e);
            throw new RuntimeException("Exception while loading model in DE", e);
        } catch (DynamicExtensionsApplicationException e) {
            Logger.out.error("Exception while loading model in DE", e);
{'fraction_non_alphanumeric': 0.09138479797162431, 'fraction_numerical': 0.004099908291525058, 'mean_word_length': 2.9806742538114666, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3139208', 'n_tokens_mistral': 4891, 'n_tokens_neox': 4762, 'n_words': 1379}