Skip to content

Commit

Permalink
Merge pull request #10 from diegosneves/feat/i8
Browse files Browse the repository at this point in the history
feat/i8 📝 [CORE] - Implementar as regras para o Cadastro do Abrigo no Sistema.
  • Loading branch information
diegosneves authored Jun 14, 2024
2 parents 8e07a5b + 1e4dd6d commit cf471e3
Show file tree
Hide file tree
Showing 20 changed files with 1,182 additions and 11 deletions.
6 changes: 0 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,6 @@
<version>2.3.0</version>
</dependency>

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package diegosneves.github.conectardoacoes.core.domain.shelter.entity;

import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
import diegosneves.github.conectardoacoes.core.exception.ShelterCreationFailureException;
import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
import diegosneves.github.conectardoacoes.core.utils.UuidUtils;

import java.util.ArrayList;
import java.util.List;

import static java.util.Objects.isNull;

/**
* Implementação da interface {@link ShelterContract}, que representa um abrigo na aplicação.
* Uma instância desta classe representa um abrigo com uma identificação, um nome de referência, um endereço, um usuário responsável, e uma lista de doações.
*
* @author diegoneves
* @version 1.0.0
* @see ShelterContract
*/
public class Shelter implements ShelterContract {

public static final String ID_VALIDATION_FAILURE = "Erro ao tentar validar o ID do Abrigo";
public static final String ADDRESS_REQUIRED_ERROR = "É necessário fornecer um endereço";
public static final String DONATION_REQUIRED_ERROR = "Uma doação deve ser fornecida para adicionar ao abrigo";
public static final String RESPONSIBLE_REQUIRED_ERROR = "Um Abrigo deve possuir um responsável";
public static final String SHELTER_NAME_REQUIRED_ERROR = "Um nome de referência deve ser designado para o abrigo";

private final String id;
private String shelterName;
private Address address;
private UserContract responsibleUser;
private List<Donation> donations;


/**
* Construtor da classe {@link Shelter} que inicializa a classe com valores fornecidos e valida o conjunto de dados presentes.
*
* @param id A identificação do abrigo, que é obrigatório.
* @param shelterName O nome de referência do abrigo, que é obrigatório.
* @param address O endereço do abrigo, que é obrigatório.
* @param responsibleUser O usuário responsável pelo abrigo, que é obrigatório.
* @throws ShelterCreationFailureException se os dados fornecidos forem inválidos.
*/
public Shelter(String id, String shelterName, Address address, UserContract responsibleUser) {
this.id = id;
this.shelterName = shelterName;
this.address = address;
this.responsibleUser = responsibleUser;
this.donations = new ArrayList<>();
this.validateData();
}

/**
* Este método privado é usado para validar os dados do objeto {@link Shelter} antes de sua criação.
* Realiza uma série de verificações ignorando nulidade e vazio para garantir a integridade dos dados.
*
* <p>Os passos seguidos por este método são:
* <ul>
* <li>Invoca o método {@link UuidUtils#isValidUUID(String)} para verificar a validade do ID do Abrigo.</li>
* <li>Verifica se o campo {@link String shelterName} não é nulo e nem vazio.</li>
* <li>Verifica se o campo {@link Address address} não é nulo.</li>
* <li>Verifica se o campo {@link UserContract responsibleUser} não é nulo.</li>
* </ul>
* <p>
* Se alguma dessas verificações falhar, o método lançará uma {@link ShelterCreationFailureException}.
*
* @throws ShelterCreationFailureException é lançada se o ID do Abrigo for inválido ou se algum dos campos necessários (shelterName, address, responsibleUser) estiver faltando.
*/
private void validateData() throws ShelterCreationFailureException {
try {
UuidUtils.isValidUUID(this.id);
} catch (UuidUtilsException e) {
throw new ShelterCreationFailureException(ID_VALIDATION_FAILURE, e);
}
this.checkNotNullAndNotEmptyOrThrowException(this.shelterName, SHELTER_NAME_REQUIRED_ERROR);
this.checkNotNullAndNotEmptyOrThrowException(this.address, ADDRESS_REQUIRED_ERROR);
this.checkNotNullAndNotEmptyOrThrowException(this.responsibleUser, RESPONSIBLE_REQUIRED_ERROR);
}

/**
* Este é um método genérico usado para verificar se o objeto fornecido é nulo ou, se é uma instância de String, se é vazio.
* Em ambos os casos, ele lançará uma exceção {@link ShelterCreationFailureException}.
* <p>
* Este método é particularmente útil para validar os detalhes do abrigo durante a criação de um novo abrigo.
* Assegura que os valores de todos os campos necessários estão presentes e não são nulos ou vazios.
*
* @param <T> O tipo de objeto a ser verificado.
* @param object O objeto a ser verificado.
* @param errorMessage A mensagem de erro a ser anexada à exceção em caso de falha de validação.
* @throws ShelterCreationFailureException Se o objeto fornecido for nulo ou, se for uma instância de String, se for vazio.
*/
private <T> void checkNotNullAndNotEmptyOrThrowException(T object, String errorMessage) throws ShelterCreationFailureException {
if (isNull(object)) {
throw new ShelterCreationFailureException(errorMessage);
}
if (object instanceof String && ((String) object).trim().isEmpty()) {
throw new ShelterCreationFailureException(errorMessage);
}
}

@Override
public String getId() {
return this.id;
}

@Override
public String getShelterName() {
return this.shelterName;
}

@Override
public Address getAddress() {
return this.address;
}

@Override
public UserContract getUser() {
return this.responsibleUser;
}

@Override
public void changeShelterName(String shelterName) throws ShelterCreationFailureException {
this.checkNotNullAndNotEmptyOrThrowException(shelterName, SHELTER_NAME_REQUIRED_ERROR);
this.shelterName = shelterName;
}

@Override
public void changeAddress(Address address) throws ShelterCreationFailureException {
this.checkNotNullAndNotEmptyOrThrowException(address, ADDRESS_REQUIRED_ERROR);
this.address = address;
}

@Override
public void addDonation(Donation donation) throws ShelterCreationFailureException {
this.checkNotNullAndNotEmptyOrThrowException(donation, DONATION_REQUIRED_ERROR);
this.donations.add(donation);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package diegosneves.github.conectardoacoes.core.domain.shelter.entity;

import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
import diegosneves.github.conectardoacoes.core.exception.ShelterCreationFailureException;

/**
* Interface {@link ShelterContract} define os métodos que representam os principais comportamentos e a divulgação de informações de uma entidade {@link Shelter}.
* <p>
* Essa interface é fundamental para definir os contratos para identificação do Abrigo, gerenciamento e atualização de endereço e nome do abrigo,
* além da adição de doações e recuperação de um usuário responsável pelo abrigo.
*
* @author diegoneves
* @version 1.0.0
*/
public interface ShelterContract {

/**
* Retorna a identificação do refúgio na forma de uma String.
*
* @return uma String que representa a identificação única do refúgio
*/
String getId();

/**
* Retorna o nome do refúgio na forma de uma String.
*
* @return uma String que representa o nome do refúgio.
*/
String getShelterName();

/**
* Retorna o endereço do refúgio na forma de um objeto {@link Address}.
*
* @return um objeto Address que representa o endereço do refúgio.
*/
Address getAddress();

/**
* Este método é usado para alterar o endereço do abrigo.
* <p>
* Antes de alterar o endereço, este método verifica se o novo endereço fornecido não é nulo. Se o endereço for nulo, o método lançará uma {@link ShelterCreationFailureException}. Isto garante que o endereço do abrigo sempre seja válido.
* Se o endereço passar por esta verificação, ele será atribuído como o novo endereço do abrigo, substituindo o endereço antigo.
*
* @param address O novo endereço que deve ser atribuído ao abrigo.
* Deve ser uma instância da classe {@link Address}, que representa um endereço físico e não pode ser nulo.
* @throws ShelterCreationFailureException Se o endereço fornecido for nulo.
*/
void changeAddress(Address address) throws ShelterCreationFailureException;

/**
* Altera o nome do abrigo.
* Esse método recebe o novo nome do abrigo como parâmetro e substitui o nome atual
* armazenado no objeto {@link Shelter} pelo novo nome fornecido (não vazio e não nulo).
* Antes da atribuição, realiza uma verificação para certificar-se de que o novo
* nome do abrigo não é nulo nem vazio. Se essa verificação falhar,
* uma exceção {@link ShelterCreationFailureException} será lançada.
*
* @param shelterName O novo nome do abrigo. Este nome deve ser um valor String não nulo e não vazio.
* @throws ShelterCreationFailureException Se o parâmetro shelterName for nulo ou vazio.
*/
void changeShelterName(String shelterName) throws ShelterCreationFailureException;

/**
* Adiciona uma doação à lista de doações do abrigo.
* <p>
* Este método primeiramente verifica se a doação não é nula, se for, uma {@link ShelterCreationFailureException} será lançada com uma mensagem de erro adequada.
* Se a doação passar pela verificação, então ela é adicionada à lista interna de doações do abrigo.
*
* @param donation Um objeto da classe Donation que representa a doação que será adicionada ao abrigo.
* Se a doação for nula, o método irá lançar uma exceção.
* @throws ShelterCreationFailureException Se a doação for nula.
*/
void addDonation(Donation donation) throws ShelterCreationFailureException;

/**
* Retorna o usuário associado ao refúgio na forma de um objeto {@link UserContract}.
*
* @return um objeto {@link UserContract} que representa o usuário responsável pelo refúgio.
*/
UserContract getUser();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package diegosneves.github.conectardoacoes.core.domain.shelter.entity.value;

import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
import diegosneves.github.conectardoacoes.core.exception.AddressCreationFailureException;
import lombok.Getter;

/**
* Classe {@link Address} representa um endereço físico.
* <p>
* Um endereço é composto pela rua, número, bairro, cidade, estado e CEP (código postal).
* Cada um destes campos é uma string e é validado no momento da criação de um objeto {@link Address}.
* Se um destes campos estiver faltando ou em branco, uma exceção {@link AddressCreationFailureException} será lançada.
* <p>
* Este classe é utilizada na criação de entidades tais como {@link Shelter}, que precisam de uma representação de endereço.
*
* @author diegoneves
* @version 1.0.0
*/
@Getter
public class Address {

public static final String STREET_NAME_ERROR_MESSAGE = "Por favor, certifique-se de que o nome da rua foi inserido corretamente.";
public static final String RESIDENCE_NUMBER_ERROR_MESSAGE = "Por favor, certifique-se de que o numero da residência foi inserido corretamente.";
public static final String NEIGHBORHOOD_NAME_ERROR_MESSAGE = "Por favor, certifique-se de que o nome do bairro foi inserido corretamente.";
public static final String CITY_NAME_ERROR_MESSAGE = "Por favor, certifique-se de que o nome da cidade foi inserido corretamente.";
public static final String STATE_NAME_ERROR_MESSAGE = "Por favor, certifique-se de que o nome do Estado foi inserido corretamente.";
public static final String CEP_ERROR_MESSAGE = "Por favor, certifique-se de que o CEP foi inserido corretamente.";

private final String street;
private final String number;
private final String neighborhood;
private final String city;
private final String state;
private final String zip;

/**
* Construtor para a classe {@link Address}. Cada um dos parâmetros é usado para definir os detalhes de um endereço.
*
* @param street A string que representa a rua do endereço.
* @param number A string que representa o número da residência no endereço.
* @param neighborhood A string que representa o bairro do endereço.
* @param city A string que representa a cidade do endereço.
* @param state A string que representa o estado do endereço.
* @param zip A string que representa o código postal do endereço.
* @throws AddressCreationFailureException Se qualquer um dos parâmetros estiver nulo ou em branco.
* <p>
* Utiliza o método {@link #validateData} para garantir que cada campo fornecido é válido.
* Isso é feito através da verificação de que cada campo não seja nulo nem em branco.
* Se algum campo for inválido, será lançada uma exceção {@link AddressCreationFailureException} específica para aquele campo.
*/
public Address(String street, String number, String neighborhood, String city, String state, String zip) {
this.street = street;
this.number = number;
this.neighborhood = neighborhood;
this.city = city;
this.state = state;
this.zip = zip;
this.validateData();
}

/**
* Método sem retorno que valida os campos de um endereço.
* <p>
* Este método examina cada campo (rua, número, bairro, cidade, estado e CEP) e chama um segundo método de validação
* passando o valor atual do campo e uma mensagem de erro específica para aquele campo.<p>
* Se algum dos campos estiver nulo ou em branco, ele lançará a exceção {@link AddressCreationFailureException} com
* a mensagem de erro específica para aquele campo.
*/
private void validateData() {
this.validateData(this.street, STREET_NAME_ERROR_MESSAGE);
this.validateData(this.number, RESIDENCE_NUMBER_ERROR_MESSAGE);
this.validateData(this.neighborhood, NEIGHBORHOOD_NAME_ERROR_MESSAGE);
this.validateData(this.city, CITY_NAME_ERROR_MESSAGE);
this.validateData(this.state, STATE_NAME_ERROR_MESSAGE);
this.validateData(this.zip, CEP_ERROR_MESSAGE);
}

/**
* Método sem retorno que valida uma string representando um campo de um endereço.
*
* @param value A String contendo o valor atual do campo do endereço.
* @param errorMessage A String contendo a mensagem de erro a ser usada se a validação falhar.
* <p>
* Este método verifica se o valor passado é nulo ou está em branco.
* Se o valor estiver nulo ou em branco, ele lançará a exceção `AddressCreationFailureException` com a mensagem de erro passada.
* @throws AddressCreationFailureException Se {@code value} estiver nulo ou em branco.
*/
private void validateData(String value, String errorMessage) throws AddressCreationFailureException {
if (value == null || value.trim().isEmpty()) {
throw new AddressCreationFailureException(errorMessage);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package diegosneves.github.conectardoacoes.core.domain.shelter.entity.value;

import diegosneves.github.conectardoacoes.core.exception.DonationRegisterFailureException;
import lombok.Getter;

/**
* Entidade que representa uma doação.
* Uma doação é caracterizada pela sua descrição e quantidade.
*
* @author diegoneves
* @version 1.0.0
*/
@Getter
public class Donation {

public static final String INVALID_DESCRIPTION_ERROR = "A descrição da doação está vazia ou nula";
public static final String INVALID_QUANTITY = "A quantidade deve ser maior que zero";
public static final int DEFAULT_DONATION_AMOUNT = 1;

private String description;
private Integer amount;

/**
* Construtor da entidade Donation.
*
* @param description Descrição da doação.
* @param amount Quantidade da doação.
* @throws DonationRegisterFailureException se a descrição ou a quantidade da doação forem inválidos.
*/
public Donation(String description, Integer amount) {
this.description = description;
this.amount = this.defaultAmount(amount);
this.validateData();
}

/**
* Valida os dados da doação, lançando uma exceção quando inválidos.
*
* @throws DonationRegisterFailureException se a descrição da doação for nula ou vazia.
*/
private void validateData() throws DonationRegisterFailureException {
if (this.description == null || this.description.trim().isEmpty()) {
throw new DonationRegisterFailureException(INVALID_DESCRIPTION_ERROR);
}
}

/**
* Fornecer o valor padrão para a quantidade quando o valor informado for nulo ou inválido.
*
* @param amount O valor da quantidade informado.
* @return O valor padrão se a quantidade informada for nula ou inválida, caso contrário a quantidade informada.
* @throws DonationRegisterFailureException se a quantia é nula.
*/
private Integer defaultAmount(Integer amount) throws DonationRegisterFailureException {
if (amount == null) {
throw new DonationRegisterFailureException(INVALID_QUANTITY);
}
return (amount < DEFAULT_DONATION_AMOUNT) ? DEFAULT_DONATION_AMOUNT : amount;
}
}
Loading

0 comments on commit cf471e3

Please sign in to comment.