CustomerDAOImpl.java
package org.example.customerdao;
/*
* This is free and unencumbered software released into the public domain.
* Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software,
* either in source code form or as a compiled binary, for any purpose, commercial or
* non-commercial, and by any means.
*
* In jurisdictions that recognize copyright laws, the author or authors of this
* software dedicate any and all copyright interest in the software to the public domain.
* We make this dedication for the benefit of the public at large and to the detriment of
* our heirs and successors. We intend this dedication to be an overt act of relinquishment in
* perpetuity of all present and future rights to this software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* For more information, please refer to: https://unlicense.org/
*/
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.apache.commons.dbutils.DbUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.example.customer.Customer;
import org.example.customer.utility.CustomerEntity;
import org.example.customer.utility.Location;
import org.example.customer.utility.Phone;
import org.example.customerdao.utility.ErrorFormatter;
import org.example.customerdao.utility.NonDeleteableRecordException;
import org.example.websecurity.UserCredentials;
/**
* This is the CustomerDAO Implementation for the Customer DAO component of the Customer Web Application.
* This will be the primary Customer database exposure for the Customer Web Layer.
*
* @author Jonathan Earl
* @since 1.0
*
*/
public final class CustomerDAOImpl
implements CustomerDAO
{
private static final Logger LOG = LogManager.getLogger();
private DataSource myReadOnlyDS = null;
private DataSource myReadWriteDS = null;
private static final String FIND_ALL_SQL = "Select * from Customer";
private static final String FIND_BY_ID_SQL = "Select * from Customer where ID = ?";
private static final String FIND_BY_NAME_SQL = "Select * from Customer where FIRST_NAME = ? AND LAST_NAME = ?";
private static final String ADD_SQL = "Insert into Customer(FIRST_NAME,LAST_NAME,CITY,COUNTRY,PHONE)"
+ " VALUES(?,?,?,?,?)";
private static final String UPDATE_SQL = "Update Customer set FIRST_NAME = ?, LAST_NAME = ?, "
+ "CITY = ?, COUNTRY = ?, PHONE = ?"
+ " WHERE ID = ?";
private static final String IS_DELETEABLE_CUSTOMER_SQL = "Select COUNT(*) from Orders where CUSTOMER_ID = ?";
private static final String DELETE_SQL = "Delete from Customer where id = ?";
/**
* {@inheritDoc}
*/
@Override
public void setReadOnlyDS(final DataSource readOnlyDS)
{
LOG.debug("Setting the ReadOnly DataSource");
this.myReadOnlyDS = readOnlyDS;
}
/**
* {@inheritDoc}
*/
@Override
public void setReadWriteDS(final DataSource readWriteDS)
{
LOG.debug("Setting the ReadWrite DataSource");
this.myReadWriteDS = readWriteDS;
}
/**
* {@inheritDoc}
*/
@Override
public List<Customer> findAllCustomers(final UserCredentials credentials)
{
LOG.debug("findAllCustomers");
if (credentials == null || !credentials.hasRole("worker"))
{
LOG.error("findAllCustomers - Permission refused");
throw new IllegalArgumentException("Permission refused for this operation");
}
PreparedStatement findAll = null;
Connection conn = null;
ResultSet results = null;
List<Customer> data = new ArrayList<Customer>();
try
{
conn = myReadOnlyDS.getConnection();
findAll = conn.prepareStatement(FIND_ALL_SQL);
results = findAll.executeQuery();
while (results.next())
{
data.add(buildCustomer(results));
}
}
catch (SQLException sqle)
{
LOG.error("Error finding all Customers");
LOG.error(ErrorFormatter.extractError(sqle));
throw new IllegalArgumentException(sqle);
}
finally
{
DbUtils.closeQuietly(conn, findAll, results);
}
return data;
}
/**
* {@inheritDoc}
*/
@Override
public Customer findCustomerById(final UserCredentials credentials, final int id)
{
LOG.debug("findCustomerById");
if (credentials == null || !credentials.hasRole("worker"))
{
LOG.error("findCustomerById - Permission refused");
throw new IllegalArgumentException("Permission refused for this operation");
}
PreparedStatement findById = null;
Connection conn = null;
ResultSet results = null;
Customer customer = null;
try
{
conn = myReadOnlyDS.getConnection();
findById = conn.prepareStatement(FIND_BY_ID_SQL);
findById.setInt(1, id);
results = findById.executeQuery();
if (results.next())
{
customer = buildCustomer(results);
}
}
catch (SQLException sqle)
{
LOG.error("Error finding Customer by id");
LOG.error(ErrorFormatter.extractError(sqle));
throw new IllegalArgumentException(sqle);
}
finally
{
DbUtils.closeQuietly(conn, findById, results);
}
return customer;
}
/**
* {@inheritDoc}
*/
@Override
public List<Customer> findCustomersByName(final UserCredentials credentials,
final String firstName, final String lastName)
{
LOG.debug("findCustomersByName");
if (credentials == null || !credentials.hasRole("worker"))
{
LOG.error("findCustomersByName - Permission refused");
throw new IllegalArgumentException("Permission refused for this operation");
}
if (firstName == null || lastName == null)
{
LOG.error("findCustomersByName - names are required");
throw new IllegalArgumentException("A first name and a last name are required");
}
PreparedStatement findByName = null;
Connection conn = null;
ResultSet results = null;
List<Customer> data = new ArrayList<Customer>();
try
{
conn = myReadOnlyDS.getConnection();
findByName = conn.prepareStatement(FIND_BY_NAME_SQL);
findByName.setString(1, firstName);
findByName.setString(2, lastName);
results = findByName.executeQuery();
while (results.next())
{
data.add(buildCustomer(results));
}
}
catch (SQLException sqle)
{
LOG.error("Error finding Customer by name");
LOG.error(ErrorFormatter.extractError(sqle));
throw new IllegalArgumentException(sqle);
}
finally
{
DbUtils.closeQuietly(conn, findByName, results);
}
return data;
}
/**
* {@inheritDoc}
*/
@Override
public int addCustomer(final UserCredentials credentials, final Customer customer)
{
LOG.debug("addCustomer");
if (credentials == null || !credentials.hasRole("manager"))
{
LOG.error("addCustomer - Permission refused");
throw new IllegalArgumentException("Permission refused for this operation");
}
if (customer == null)
{
LOG.error("addCustomer - null Customer was provided");
throw new IllegalArgumentException("A Customer must be provided");
}
PreparedStatement addCustomer = null;
Connection conn = null;
ResultSet results = null;
int generatedId = 0;
try
{
conn = myReadWriteDS.getConnection();
addCustomer = conn.prepareStatement(ADD_SQL, PreparedStatement.RETURN_GENERATED_KEYS);
String firstName = customer.getFirstName();
String lastName = customer.getLastName();
Location location = customer.getLocation();
String city = location.getCity();
String country = location.getCountry();
Phone phone = customer.getPhone();
String number = phone.getNumber();
addCustomer.setString(1, firstName);
addCustomer.setString(2, lastName);
addCustomer.setString(3, city);
addCustomer.setString(4, country);
addCustomer.setString(5, number);
addCustomer.executeUpdate();
results = addCustomer.getGeneratedKeys();
if (results.next())
{
generatedId = results.getInt(1);
}
}
catch (SQLException sqle)
{
LOG.error("Error adding Customer");
LOG.error(ErrorFormatter.extractError(sqle));
throw new IllegalArgumentException(sqle);
}
finally
{
DbUtils.closeQuietly(conn, addCustomer, results);
}
return generatedId;
}
/**
* {@inheritDoc}
*/
@Override
public void updateCustomer(final UserCredentials credentials, final Customer customer)
{
LOG.debug("updateCustomer");
if (credentials == null || !credentials.hasRole("manager"))
{
LOG.error("updateCustomer - Permission refused");
throw new IllegalArgumentException("Permission refused for this operation");
}
if (customer == null)
{
LOG.error("updateCustomer - null Customer was provided");
throw new IllegalArgumentException("A Customer must be provided");
}
PreparedStatement updateCustomer = null;
Connection conn = null;
try
{
conn = myReadWriteDS.getConnection();
updateCustomer = conn.prepareStatement(UPDATE_SQL);
int id = customer.getId();
String firstName = customer.getFirstName();
String lastName = customer.getLastName();
Location location = customer.getLocation();
String city = location.getCity();
String country = location.getCountry();
String number = null;
Phone phone = customer.getPhone();
if (phone != null)
{
number = phone.getNumber();
}
updateCustomer.setString(1, firstName);
updateCustomer.setString(2, lastName);
updateCustomer.setString(3, city);
updateCustomer.setString(4, country);
updateCustomer.setString(5, number);
updateCustomer.setInt(6, id);
updateCustomer.executeUpdate();
}
catch (SQLException sqle)
{
LOG.error("Error updating Customer");
LOG.error(ErrorFormatter.extractError(sqle));
throw new IllegalArgumentException(sqle);
}
finally
{
DbUtils.closeQuietly(updateCustomer);
DbUtils.closeQuietly(conn);
}
}
/**
* {@inheritDoc}
* <p>
* Customers with Orders are not deleteable.
*/
@Override
public boolean isDeleteable(final UserCredentials credentials, final int id)
{
LOG.debug("isDeleteable");
if (credentials == null || !credentials.hasRole("worker"))
{
LOG.error("isDeleteable - Permission refused");
throw new IllegalArgumentException("Permission refused for this operation");
}
PreparedStatement isDeleteable = null;
Connection conn = null;
ResultSet results = null;
boolean isDeleteableResult = false;
try
{
conn = myReadOnlyDS.getConnection();
isDeleteable = conn.prepareStatement(IS_DELETEABLE_CUSTOMER_SQL);
isDeleteable.setInt(1, id);
results = isDeleteable.executeQuery();
if (results.next())
{
int count = results.getInt(1);
if (count == 0)
{
isDeleteableResult = true;
}
}
}
catch (SQLException sqle)
{
LOG.error("Error finding Customer by Order");
LOG.error(ErrorFormatter.extractError(sqle));
throw new IllegalArgumentException(sqle);
}
finally
{
DbUtils.closeQuietly(conn, isDeleteable, results);
}
return isDeleteableResult;
}
/**
* {@inheritDoc}
* <p>
* Customers with Orders are not deleteable.
*/
@Override
public boolean isDeleteable(final UserCredentials credentials, final CustomerEntity entity)
{
LOG.debug("isDeleteable");
if (credentials == null || entity == null)
{
LOG.error("isDeleteable - null Customer was provided");
throw new IllegalArgumentException("A Customer must be provided");
}
if (!(entity instanceof Customer))
{
LOG.error("isDeleteable - invalid CustomerEntity was provided");
throw new IllegalArgumentException("A Customer must be provided");
}
return isDeleteable(credentials, entity.getId());
}
/**
* {@inheritDoc}
* <p>
* Customers with Orders are not deleteable.
*/
@Override
public void deleteEntity(final UserCredentials credentials, final CustomerEntity entity)
{
LOG.debug("deleteCustomer");
if (entity == null)
{
LOG.error("deleteCustomer - null Customer was provided");
throw new IllegalArgumentException("A Customer must be provided");
}
if (!(entity instanceof Customer))
{
LOG.error("deleteCustomer - invalid CustomerEntity was provided");
throw new IllegalArgumentException("A Customer must be provided");
}
deleteEntity(credentials, entity.getId());
}
/**
* {@inheritDoc}
* <p>
* Customers with Orders are not deleteable.
*/
@Override
public void deleteEntity(final UserCredentials credentials, final int id)
{
LOG.debug("deleteCustomer");
if (credentials == null || !credentials.hasRole("manager"))
{
LOG.error("deleteCustomer - Permission refused");
throw new IllegalArgumentException("Permission refused for this operation");
}
if (!isDeleteable(credentials, id))
{
LOG.error("Customer not deleteable");
throw new NonDeleteableRecordException("This Customer is not deletable");
}
PreparedStatement deleteCustomer = null;
Connection conn = null;
try
{
conn = myReadWriteDS.getConnection();
deleteCustomer = conn.prepareStatement(DELETE_SQL);
deleteCustomer.setInt(1, id);
deleteCustomer.executeUpdate();
}
catch (SQLException sqle)
{
LOG.error("Error updating Customer");
LOG.error(ErrorFormatter.extractError(sqle));
throw new IllegalArgumentException(sqle);
}
finally
{
DbUtils.closeQuietly(deleteCustomer);
DbUtils.closeQuietly(conn);
}
}
private Customer buildCustomer(final ResultSet results) throws SQLException
{
Customer current = new Customer();
current.setId(results.getInt("ID"));
current.setFirstName(results.getString("FIRST_NAME").trim());
current.setLastName(results.getString("LAST_NAME").trim());
Location location = new Location();
location.setCity(results.getString("CITY").trim());
location.setCountry(results.getString("COUNTRY").trim());
current.setLocation(location);
Phone phone = new Phone();
phone.setNumber(results.getString("Phone").trim());
current.setPhone(phone);
LOG.trace("Found Customer: " + current.toString());
return current;
}
}