Skip to content
Snippets Groups Projects
DatabaseController.java 9.67 KiB
Newer Older
package de.unipotsdam.cs.toolup.database;

import de.unipotsdam.cs.toolup.exceptions.InvalidIdException;
import de.unipotsdam.cs.toolup.model.*;

import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class DatabaseController {

    public static final String TABLE_NAME_FEATURE = "feature";
    public static final String TABLE_NAME_CATEGORY = "category";
    public static final String TABLE_NAME_APPLICATION = "application";
    public static final String TABLE_NAME_APPLICATION_FEATURE = "application_has_feature";
    public static final String TABLE_NAME_APPLICATION_CATEGORY = "application_belongs_to_category";
    private static final String COLUMN_SUFFIX_UUID = "_uuid";
    private static DatabaseController instance;
    private SqlStatementFactory sqlStatementFactory;

    protected DatabaseController() throws IOException, SQLException {
        sqlStatementFactory = new SqlStatementFactory();
    }

    public static DatabaseController getInstance() throws IOException, SQLException {
        if (instance == null) {
            instance = new DatabaseController();
        }
        return instance;
    }


    public BusinessObject load(String uuid) throws SQLException, InvalidIdException {
        String tableName = BusinessObject.getTableNameFromId(uuid);

        PreparedStatement prepQuery = sqlStatementFactory.getSelectAllFrom(tableName);

        prepQuery.setString(1, uuid);
        ResultSet res = prepQuery.executeQuery();

        return BusinessObjectFactory.createBusinessObjectFromSingleResult(res);
    }


    public Set<String> loadRelatedBusinessObjectsForId(String tableName, String targetBusinessObjectType, String id) throws SQLException, InvalidIdException {

        String criteriaBusinessObjectType = BusinessObject.getTableNameFromId(id);

        PreparedStatement prepQuery = sqlStatementFactory.getSelectRelation(tableName, criteriaBusinessObjectType + COLUMN_SUFFIX_UUID);

        prepQuery.setString(1, id);

        ResultSet res = prepQuery.executeQuery();

        return getRelatedIdsFromResultSet(targetBusinessObjectType + COLUMN_SUFFIX_UUID,
                res);
    }

    private Set<String> getRelatedIdsFromResultSet(
            String resultColumnName, ResultSet res) throws SQLException {
        Set<String> relatedIds = new HashSet<>();
        while (res.next()) {
            relatedIds.add(res.getString(resultColumnName));
        }
        return relatedIds;
    }

    public Set<String> loadRelatedCategoriesForApp(String id) throws SQLException, InvalidIdException {
        return loadRelatedBusinessObjectsForId(TABLE_NAME_APPLICATION_CATEGORY, TABLE_NAME_CATEGORY, id);
    }

    public Set<String> loadRelatedApplicationsForCat(String id) throws SQLException, InvalidIdException {
        return loadRelatedBusinessObjectsForId(TABLE_NAME_APPLICATION_CATEGORY, TABLE_NAME_APPLICATION, id);
    }

    public Set<String> loadRelatedFeaturesForApp(String id) throws SQLException, InvalidIdException {
        return loadRelatedBusinessObjectsForId(TABLE_NAME_APPLICATION_FEATURE, TABLE_NAME_FEATURE, id);
    }

    public Collection<String> loadRelatedApplicationsForFeat(String id) throws SQLException, InvalidIdException {
        return loadRelatedBusinessObjectsForId(TABLE_NAME_APPLICATION_FEATURE, TABLE_NAME_APPLICATION, id);
    }


    public boolean checkIfExistsInDB(BusinessObject aBusinessObject) throws SQLException, InvalidIdException {
        return checkIfExistsInDB(aBusinessObject.getUuid());
    }

    public boolean checkIfExistsInDB(String id) throws SQLException, InvalidIdException {
        BusinessObject objectFromDB = load(id);
        return !(objectFromDB instanceof NullBusinessObject);
    }


    public void storeToDatabase(BusinessObject aBusinessObject) throws SQLException, InvalidIdException {
        boolean exists = checkIfExistsInDB(aBusinessObject);
        if (exists) {
            updateDatabase(aBusinessObject);
        } else {
            insertIntoDatabase(aBusinessObject);
        }
    }


    private void insertIntoDatabase(BusinessObject aBusinessObject)
            throws SQLException, InvalidIdException {
        String tableName = BusinessObject.getTableNameFromId(aBusinessObject.getUuid());
        insertBO(aBusinessObject, tableName);
        insertRelations(aBusinessObject, tableName);
    }


    private void insertRelations(BusinessObject aBusinessObject,
                                 String tableName) throws SQLException {
        if (aBusinessObject.getRelatedBOs().isEmpty()) return;
        switch (tableName) {
            case TABLE_NAME_APPLICATION: {
                Application app = (Application) aBusinessObject;
                insertSingleRelationInto(TABLE_NAME_APPLICATION_FEATURE, app.getUuid(), 1, app.getRelatedFeatures());
                insertSingleRelationInto(TABLE_NAME_APPLICATION_CATEGORY, app.getUuid(), 1, app.getRelatedCategories());
                break;
            }
            case TABLE_NAME_CATEGORY: {
                Category cat = (Category) aBusinessObject;
                insertSingleRelationInto(TABLE_NAME_APPLICATION_CATEGORY, cat.getUuid(), 2, cat.getRelatedApplications());
                break;
            }
            case TABLE_NAME_FEATURE: {
                Feature feat = (Feature) aBusinessObject;
                insertSingleRelationInto(TABLE_NAME_APPLICATION_FEATURE, feat.getUuid(), 2, feat.getRelatedApplications());
                break;
            }
            default:
Thiemo Belmega's avatar
Thiemo Belmega committed
                throw new UnsupportedOperationException();
        }
    }


    /**
     * @param tableName        the name of the relation table
     * @param uuid             the BO thats relations are to be stored
     * @param uuidColumnNumber column number of the BOs id in the table. 1 if BO is Application, 2 otherwise.
     * @param relatedIds       a collection of the uuid's of related BOs
     * @throws SQLException
     */
    private void insertSingleRelationInto(String tableName, String uuid,
                                          int uuidColumnNumber, Collection<String> relatedIds) throws SQLException {
        for (String foreignKey : relatedIds) {
            PreparedStatement prepQuery;
            prepQuery = sqlStatementFactory.getInsertRelation(tableName);
            prepQuery.setString(uuidColumnNumber, uuid);
            prepQuery.setString((uuidColumnNumber % 2) + 1, foreignKey);
            prepQuery.executeUpdate();
        }
    }

Thiemo Belmega's avatar
Thiemo Belmega committed
    private void updateSingleRelation(
            String tableName, String uuid, int uuidColumnNumber,
            Collection<String> relatedIds) throws SQLException {
        for (String foreignKey : relatedIds) {
            PreparedStatement prepQuery;
            prepQuery = sqlStatementFactory.getInsertRelation(tableName);
            prepQuery.setString(uuidColumnNumber, uuid);
            prepQuery.setString((uuidColumnNumber % 2) + 1, foreignKey);
            prepQuery.executeUpdate();
        }
    }


    private void insertBO(BusinessObject aBusinessObject,
                          String tableName) throws SQLException {
        PreparedStatement prepQuery;
        prepQuery = sqlStatementFactory.getInsertInto(tableName);
        prepQuery.setString(1, aBusinessObject.getUuid());
        prepQuery.setString(2, aBusinessObject.getTitle());
        prepQuery.setString(3, aBusinessObject.getDescription());
        prepQuery.executeUpdate();
    }


    private void updateDatabase(BusinessObject aBusinessObject)
            throws SQLException, InvalidIdException {
        String tableName = BusinessObject.getTableNameFromId(aBusinessObject.getUuid());
        updateBO(aBusinessObject, tableName);
        updateRelations(aBusinessObject, tableName);
    }


    private void updateRelations(BusinessObject aBusinessObject,
                                 String tableName) throws SQLException {
        if (aBusinessObject.getRelatedBOs().isEmpty()) return;
        switch (tableName) {
            case TABLE_NAME_APPLICATION: {
                Application app = (Application) aBusinessObject;
                updateSingleRelation(TABLE_NAME_APPLICATION_FEATURE, app.getUuid(), 1, app.getRelatedFeatures());
                updateSingleRelation(TABLE_NAME_APPLICATION_CATEGORY, app.getUuid(), 1, app.getRelatedCategories());
                break;
            }
            case TABLE_NAME_CATEGORY: {
                Category cat = (Category) aBusinessObject;
                updateSingleRelation(TABLE_NAME_APPLICATION_CATEGORY, cat.getUuid(), 2, cat.getRelatedApplications());
                break;
            }
            case TABLE_NAME_FEATURE: {
                Feature feat = (Feature) aBusinessObject;
                updateSingleRelation(TABLE_NAME_APPLICATION_FEATURE, feat.getUuid(), 2, feat.getRelatedApplications());
                break;
            }
            default:
Thiemo Belmega's avatar
Thiemo Belmega committed
                throw new UnsupportedOperationException();
        }
    }




    private void updateBO(BusinessObject aBusinessObject,
                          String tableName) throws SQLException {
        PreparedStatement prepQuery;
        prepQuery = sqlStatementFactory.getUpdate(tableName);
        prepQuery.setString(1, aBusinessObject.getTitle());
        prepQuery.setString(2, aBusinessObject.getDescription());
        prepQuery.setString(3, aBusinessObject.getUuid());
        prepQuery.executeUpdate();
    }


    public void deleteFromDatabase(String id) throws SQLException, InvalidIdException {
        String tableName = BusinessObject.getTableNameFromId(id);

        PreparedStatement prepQuery = sqlStatementFactory.getDeleteFrom(tableName);

        prepQuery.setString(1, id);
        prepQuery.executeUpdate();
    }


}