From 2335425ecc9e32886bf0c862b4ce188c896685a3 Mon Sep 17 00:00:00 2001 From: Miguel Reboiro-Jato Date: Sun, 27 Sep 2015 22:41:18 +0200 Subject: [PATCH] Adds the domain entities This commit includes the complete code for the domain entities. --- .../esei/xcs/domain/entities/AnimalType.java | 11 + .../uvigo/esei/xcs/domain/entities/Owner.java | 251 ++++++++++++++++++ .../uvigo/esei/xcs/domain/entities/Pet.java | 195 ++++++++++++++ 3 files changed, 457 insertions(+) create mode 100644 domain/src/main/java/es/uvigo/esei/xcs/domain/entities/AnimalType.java create mode 100644 domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java create mode 100644 domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Pet.java diff --git a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/AnimalType.java b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/AnimalType.java new file mode 100644 index 0000000..9c865cc --- /dev/null +++ b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/AnimalType.java @@ -0,0 +1,11 @@ +package es.uvigo.esei.xcs.domain.entities; + +/** + * The type of animal. + * + * @author Miguel Reboiro-Jato + * + */ +public enum AnimalType { + DOG, CAT, BIRD; +} diff --git a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java new file mode 100644 index 0000000..b61ae5f --- /dev/null +++ b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java @@ -0,0 +1,251 @@ +package es.uvigo.esei.xcs.domain.entities; + +import static java.util.Arrays.stream; +import static java.util.Collections.unmodifiableCollection; +import static java.util.Objects.requireNonNull; +import static org.apache.commons.lang3.Validate.inclusiveBetween; +import static org.apache.commons.lang3.Validate.matchesPattern; + +import java.io.Serializable; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Collection; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.xml.bind.annotation.adapters.HexBinaryAdapter; + +/** + * A pet owner. + * + * @author Miguel Reboiro-Jato + */ +@Entity +public class Owner implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @Column(length = 100, nullable = false) + private String login; + + @Column(length = 32, nullable = false) + private String password; + + @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true) + private Collection pets; + + // Required for JPA + Owner() {} + + /** + * Creates a new instance of {@code Owner} without pets. + * + * @param login the login that identifies the user. This parameter must be a + * non empty and non {@code null} string with a maximum length of 100 chars. + * @param password the raw password of the user. This parameter must be a + * non {@code null} string with a minimum length of 6 chars. + * + * @throws NullPointerException if a {@code null} value is passed as the + * value for any parameter. + * @throws IllegalArgumentException if value provided for any parameter is + * not valid according to its description. + */ + public Owner(String login, String password) { + this.setLogin(login); + this.changePassword(password); + this.pets = new ArrayList<>(); + } + + /** + * Creates a new instance of {@code Owner} with pets. + * + * @param login the login that identifies the user. This parameter must be a + * non empty and non {@code null} string with a maximum length of 100 chars. + * @param password the raw password of the user. This parameter must be a + * non {@code null} string with a minimum length of 4 chars. + * @param pets the pets that belong to this owner. The list of pets can be + * empty. {@code null} values are not supported. + * + * @throws NullPointerException if a {@code null} value is passed as the + * value for any parameter. + * @throws IllegalArgumentException if value provided for any parameter is + * not valid according to its description. + */ + public Owner(String login, String password, Pet ... pets) { + this.setLogin(login); + this.changePassword(password); + this.pets = new ArrayList<>(); + + stream(pets).forEach(this::addPet); + } + + /** + * Returns the login of this owner. + * + * @return the login of this owner. + */ + public String getLogin() { + return login; + } + + /** + * Sets the login of this owner. + * + * @param login the login that identifies the owner. This parameter must be + * a non empty and non {@code null} string with a maximum length of 100 + * chars. + * @throws NullPointerException if {@code null} is passed as parameter. + * @throws IllegalArgumentException if the length of the string passed is + * not valid. + */ + public void setLogin(String login) { + requireNonNull(login, "login can't be null"); + inclusiveBetween(1, 100, login.length(), "login must have a length between 1 and 100"); + + this.login = login; + } + + /** + * Returns the MD5 of the owner's password. Capital letters are used in the + * returned string. + * + * @return the MD5 of the owner's password. Capital letters are used in the + * returned string. + */ + public String getPassword() { + return password; + } + + /** + * Sets the MD5 password of the owner. The MD5 string is stored with capital + * letters. + * + * @param password the MD5 password of the user. This parameter must be a + * non {@code null} MD5 string. + * @throws NullPointerException if {@code null} is passed as parameter. + * @throws IllegalArgumentException if the string passed is not a valid MD5 + * string. + */ + public void setPassword(String password) { + requireNonNull(password, "password can't be null"); + matchesPattern(password, "[a-zA-Z0-9]{32}", "password must be a valid uppercase MD5 string"); + + this.password = password.toUpperCase(); + } + + /** + * Changes the password of the owner. This method receives the raw value of + * the password and stores it in MD5 format. + * + * @param password the raw password of the user. This parameter must be a + * non {@code null} string with a minimum length of 6 chars. + * + * @throws NullPointerException if the {@code password} is {@code null}. + * @throws IllegalArgumentException if the length of the string passed is + * not valid. + */ + public void changePassword(String password) { + requireNonNull(password, "password can't be null"); + if (password.length() < 6) + throw new IllegalArgumentException("password can't be shorter than 6"); + + try { + final MessageDigest digester = MessageDigest.getInstance("MD5"); + final HexBinaryAdapter adapter = new HexBinaryAdapter(); + + this.password = adapter.marshal(digester.digest(password.getBytes())); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("MD5 algorithm not found", e); + } + } + + /** + * Returns the pets that belongs to this owner. The collection returned is + * unmodifiable and no order are guaranteed. + * If the pet already belongs to this owner, no action will be done. + * + * @return the pets that belongs to this owner. + */ + public Collection getPets() { + return unmodifiableCollection(pets); + } + + /** + * Adds a pet to this owner. The pet's owner will be set to this instance. + * + * @param pet the pet to add to this owner. {@code null} values not + * supported. + * @throws NullPointerException if the {@code pet} is {@code null}. + */ + public void addPet(Pet pet) { + requireNonNull(pet, "pet can't be null"); + + if (!this.ownsPet(pet)) { + pet.setOwner(this); + } + } + + /** + * Removes a pet from this owner. The pet's owner will be set to + * {@code null}. + * + * @param pet the pet to remove from this owner. {@code null} values not + * supported. + * @throws NullPointerException if the {@code pet} is {@code null}. + * @throws IllegalArgumentException if the {@code pet} does not belong to + * this owner. + */ + public void removePet(Pet pet) { + requireNonNull(pet, "pet can't be null"); + + if (this.ownsPet(pet)) { + pet.setOwner(null); + } else { + throw new IllegalArgumentException("pet doesn't belong to this owner"); + } + } + + /** + * Checks if a pet belongs to this owner. + * + * @param pet the pet whose property will be checked. + * @return {@code true} if the pet belongs to this owner. {@code false} + * otherwise. + */ + public boolean ownsPet(Pet pet) { + return this.pets.contains(pet); + } + + /** + * Adds a pet directly to the pets collection of this owner if the pet does + * not already belongs to this owner. The pet's owner will not be updated. + * + * @param pet the pet to add to this owner. {@code null} values not + * supported. + * @throws NullPointerException if the {@code pet} is {@code null}. + */ + void internalAddPet(Pet pet) { + requireNonNull(pet, "pet can't be null"); + + if (!this.ownsPet(pet)) + this.pets.add(pet); + } + + /** + * Removes a pet directly from the pets collection of this owner. The pet's + * owner will not be updated. + * + * @param pet the pet to remove from this owner. {@code null} values not + * supported. + * @throws NullPointerException if the {@code pet} is {@code null}. + */ + void internalRemovePet(Pet pet) { + requireNonNull(pet, "pet can't be null"); + + this.pets.remove(pet); + } +} diff --git a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Pet.java b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Pet.java new file mode 100644 index 0000000..447fd12 --- /dev/null +++ b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Pet.java @@ -0,0 +1,195 @@ +package es.uvigo.esei.xcs.domain.entities; + +import static java.util.Objects.requireNonNull; +import static org.apache.commons.lang3.Validate.inclusiveBetween; + +import java.io.Serializable; +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +/** + * A pet. + * + * @author Miguel Reboiro-Jato + */ +@Entity +public class Pet implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue + private int id; + + @Column(length = 100, nullable = false) + private String name; + + @Column(nullable = false, length = 4) + @Enumerated(EnumType.STRING) + private AnimalType animal; + + @Column(nullable = false) + @Temporal(TemporalType.TIMESTAMP) + private Date birth; + + @ManyToOne + @JoinColumn(name = "owner") + private Owner owner; + + // Required for JPA + Pet() {} + + /** + * Creates a new instance of {@code Pet} without owner. + * + * @param name the name of the pet. This parameter must be a non empty and + * non {@code null} string with a maximum length of 100 chars. + * @param animal the type of animal. This parameter can not be {@code null}. + * @param birth the date of birth of this pet. This parameter can not be + * {@code null} and the date can not be after the current date. + * + * @throws NullPointerException if a {@code null} value is passed as the + * value for any parameter. + * @throws IllegalArgumentException if value provided for any parameter is + * not valid according to its description. + */ + public Pet(String name, AnimalType animal, Date birth) { + this(name, animal, birth, null); + } + + /** + * Creates a new instance of {@code Pet} with owner. + * + * @param name the name of the pet. This parameter must be a non empty and + * non {@code null} string with a maximum length of 100 chars. + * @param animal the type of animal. This parameter can not be {@code null}. + * @param birth the date of birth of this pet. This parameter can not be + * {@code null} and the date can not be after the current date. + * @param owner the owner of the pet. {@code null} value is valid, + * meaning that the pet has no owner. + * + * @throws NullPointerException if a {@code null} value is passed as the + * value for any parameter except for {@code owner}. + * @throws IllegalArgumentException if value provided for any parameter is + * not valid according to its description. + */ + public Pet(String name, AnimalType animal, Date birth, Owner owner) { + this.setName(name); + this.setAnimal(animal); + this.setBirth(birth); + this.setOwner(owner); + } + + /** + * Returns the name of the pet. + * + * @return the name of the pet. + */ + public String getName() { + return name; + } + + /** + * Sets the name of the pet. + * + * @param name the new name of the pet. This parameter must be a non empty + * and non {@code null} string with a maximum length of 100 chars. + * + * @throws NullPointerException if a {@code null} value is passed. + * @throws IllegalArgumentException if the length of the string passed is + * not valid. + */ + public void setName(String name) { + requireNonNull(name, "name can't be null"); + inclusiveBetween(1, 100, name.length(), "name must have a length between 1 and 100"); + + this.name = name; + } + + /** + * Returns the type of animal of this pet. + * + * @return the type of animal of this pet. + */ + public AnimalType getAnimal() { + return animal; + } + + /** + * Sets the animal type of this pet. + * + * @param animal the new animal type for this pet. This parameter can not be + * {@code null}. + * + * @throws NullPointerException if a {@code null} value is passed. + */ + public void setAnimal(AnimalType animal) { + requireNonNull(animal, "animal can't be null"); + + this.animal = animal; + } + + /** + * Returns the date of birth of this pet. + * + * @return the date of birth of this pet. + */ + public Date getBirth() { + return birth; + } + + /** + * Sets the date of birth of this pet. + * + * @param birth the new date of birth for this pet. This parameter can not + * be {@code null} and the date can not be previous to the current date. + * + * @throws NullPointerException if a {@code null} value is passed. + * @throws IllegalArgumentException if the value provided is after the + * current date. + */ + public void setBirth(Date birth) { + requireNonNull(birth, "birth can't be null"); + inclusiveBetween(new Date(0), new Date(), birth, + "birth must be previous to the current time" + ); + + this.birth = birth; + } + + /** + * Returns the owner of this pet. The value returned can be {@code null}, + * meaning that the pet has no owner. + * + * @return the owner of this pet. + */ + public Owner getOwner() { + return owner; + } + + /** + * Sets the owner of this pet. The new owner can be {@code null}, meaining + * that the pet has no owner. + * + * @param owner the new owner of the pet. {@code null} value is valid, + * meaning that the pet has no owner. + */ + public void setOwner(Owner owner) { + if (this.owner != null) + this.owner.internalRemovePet(this); + + this.owner = owner; + + if (this.owner != null) + this.owner.internalAddPet(this); + } +} -- 2.18.1