All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fluentjdbc.DatabaseSaveBuilder Maven / Gradle / Ivy

There is a newer version: 0.5.3
Show newest version
package org.fluentjdbc;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;

@ParametersAreNonnullByDefault
public abstract class DatabaseSaveBuilder extends DatabaseStatement {

    protected List uniqueKeyFields = new ArrayList<>();
    protected List uniqueKeyValues = new ArrayList<>();

    protected List fields = new ArrayList<>();
    protected List values = new ArrayList<>();

    protected final DatabaseTable table;
    protected String idField;

    @Nullable protected T idValue;

    protected DatabaseSaveBuilder(DatabaseTable table, String idField, @Nullable T id) {
        this.table = table;
        this.idField = idField;
        this.idValue = id;
    }

    public DatabaseSaveBuilder uniqueKey(String fieldName, @Nullable Object fieldValue) {
        uniqueKeyFields.add(fieldName);
        uniqueKeyValues.add(fieldValue);
        return this;
    }

    public DatabaseSaveBuilder setField(String fieldName, @Nullable Object fieldValue) {
        fields.add(fieldName);
        values.add(fieldValue);
        return this;
    }

    @Nonnull
    public DatabaseSaveResult execute(Connection connection) throws SQLException {
        T idValue = this.idValue;
        if (idValue != null) {
            Optional isSame = tableWhereId(this.idValue).singleObject(connection, row -> shouldSkipRow(row, connection));
            if (!isSame.isPresent()) {
                insert(connection);
                return DatabaseSaveResult.inserted(idValue);
            } else if (!isSame.get()) {
                update(connection, idValue);
                return DatabaseSaveResult.updated(idValue);
            } else {
                return DatabaseSaveResult.unchanged(idValue);
            }
        } else if (hasUniqueKey()) {
            Optional isSame = table.whereAll(uniqueKeyFields, uniqueKeyValues).singleObject(connection, row -> {
                DatabaseSaveBuilder.this.idValue = getId(row);
                return shouldSkipRow(row, connection);
            });
            idValue = this.idValue;
            if (!isSame.isPresent()) {
                idValue = insert(connection);
                return DatabaseSaveResult.inserted(idValue);
            } else if (!isSame.get()) {
                update(connection, idValue);
                return DatabaseSaveResult.updated(idValue);
            } else {
                return DatabaseSaveResult.unchanged(idValue);
            }
        } else {
            idValue = insert(connection);
            return DatabaseSaveResult.inserted(idValue);
        }
    }

    protected DatabaseSimpleQueryBuilder tableWhereId(T p) {
        return table.where(idField, p);
    }

    private boolean shouldSkipRow(DatabaseRow row, Connection connection) throws SQLException {
        for (int i = 0; i < fields.size(); i++) {
            String field = fields.get(i);
            if (!dbValuesAreEqual(values.get(i), row.getObject(field), connection)) return false;
        }
        for (int i = 0; i < uniqueKeyFields.size(); i++) {
            String field = uniqueKeyFields.get(i);
            if (!dbValuesAreEqual(uniqueKeyValues.get(i), row.getObject(field), connection)) return false;
        }
        return true;
    }

    private boolean hasUniqueKey() {
        if (uniqueKeyFields.isEmpty()) return false;
        for (Object o : uniqueKeyValues) {
            if (o == null) return false;
        }
        return true;
    }

    @Nullable
    protected abstract T insert(Connection connection) throws SQLException;

    protected T update(Connection connection, T idValue) {
        tableWhereId(idValue)
                .update()
                .setFields(this.fields, this.values)
                .setFields(uniqueKeyFields, uniqueKeyValues)
                .execute(connection);
        return idValue;
    }

    @SuppressWarnings("unchecked")
    protected T getId(DatabaseRow row) throws SQLException {
        return (T) row.getObject(idField);
    }

}