Merge branch 'main' into feature/Contributing-file

This commit is contained in:
PEDSF 2020-10-23 17:12:58 +02:00
commit 45d16b636b
63 changed files with 3235 additions and 712 deletions

26
pom.xml
View file

@ -15,7 +15,6 @@
<name>petclinic</name> <name>petclinic</name>
<properties> <properties>
<!-- Generic properties --> <!-- Generic properties -->
<java.version>1.8</java.version> <java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@ -70,6 +69,14 @@
</exclusions> </exclusions>
</dependency> </dependency>
<!-- ================================================== MODELMAPPER -->
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.8</version>
<scope>compile</scope>
</dependency>
<!-- Databases - Uses H2 by default --> <!-- Databases - Uses H2 by default -->
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
@ -131,6 +138,23 @@
<artifactId>spring-boot-devtools</artifactId> <artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View file

@ -0,0 +1,50 @@
package org.springframework.samples.petclinic.common;
/**
* Class for const attributes names to prevent error with attributes names
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public final class CommonAttribute {
public static final String DESCRIPTION = "description";
public static final String NAME = "name";
public static final String NEW = "new";
public static final String OWNER = "owner";
public static final String OWNER_ID = "id";
public static final String OWNER_LAST_NAME = "lastName";
public static final String OWNER_FIRST_NAME = "firstName";
public static final String OWNER_PHONE = "telephone";
public static final String OWNER_ADDRESS = "address";
public static final String OWNER_CITY = "city";
public static final String OWNER_PETS = "pets";
public static final String PET = "pet";
public static final String SELECTIONS = "selections";
public static final String PET_BIRTH_DATE = "birthDate";
public static final String PET_NAME = "name";
public static final String PET_TYPE = "type";
public static final String VETS = "vets";
public static final String VISIT = "visit";
private CommonAttribute() {
throw new IllegalStateException("Utility class");
}
}

View file

@ -0,0 +1,36 @@
package org.springframework.samples.petclinic.common;
/**
* Class for const endpoint names to prevent error with endpoint names
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public final class CommonEndPoint {
public static final String OWNERS = "/owners";
public static final String OWNERS_FIND = "/owners/find";
public static final String OWNERS_ID = "/owners/{ownerId}";
public static final String OWNERS_ID_EDIT = "/owners/{ownerId}/edit";
public static final String OWNERS_NEW = "/owners/new";
public static final String PETS_NEW = "/pets/new";
public static final String PETS_ID_EDIT = "/pets/{petId}/edit";
public static final String VETS = "/vets";
public static final String VETS_HTML = "/vets.html";
public static final String VISITS_NEW = "/owners/*/pets/{petId}/visits/new";
public static final String VISITS_EDIT = "/owners/{ownerId}/pets/{petId}/visits/new";
private CommonEndPoint() {
throw new IllegalStateException("Utility class");
}
}

View file

@ -0,0 +1,26 @@
package org.springframework.samples.petclinic.common;
/**
* Class for const error names to prevent errors
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public final class CommonError {
public static final String DUPLICATE_ARGS = "duplicate";
public static final String DUPLICATE_MESSAGE = "already exists";
public static final String NOT_FOUND_ARGS = "notFound";
public static final String NOT_FOUND_MESSAGE = "notFound";
public static final String REQUIRED_ARGS = "required";
public static final String REQUIRED_MESSAGE = "required";
private CommonError() {
throw new IllegalStateException("Utility class");
}
}

View file

@ -0,0 +1,32 @@
package org.springframework.samples.petclinic.common;
/**
* Class for const view names to prevent error with view names
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public final class CommonView {
public static final String OWNER_OWNERS_R = "redirect:/owners/";
public static final String OWNER_OWNERS_ID_R = "redirect:/owners/{ownerId}";
public static final String OWNER_CREATE_OR_UPDATE = "owners/createOrUpdateOwnerForm";
public static final String OWNER_FIND_OWNERS = "owners/findOwners";
public static final String OWNER_OWNERS_LIST = "owners/ownersList";
public static final String OWNER_DETAILS = "owners/ownerDetails";
public static final String PET_CREATE_OR_UPDATE = "pets/createOrUpdatePetForm";
public static final String VET_VETS_LIST = "vets/vetList";
public static final String VISIT_CREATE_OR_UPDATE = "pets/createOrUpdateVisitForm";
private CommonView() {
throw new IllegalStateException("Utility class");
}
}

View file

@ -0,0 +1,152 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.controller;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonError;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.*;
import org.springframework.samples.petclinic.service.OwnerService;
import org.springframework.samples.petclinic.service.VisitService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import java.util.Collection;
import java.util.Map;
/**
* @author Juergen Hoeller
* @author Ken Krebs
* @author Arjen Poutsma
* @author Michael Isvy
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Controller
class OwnerController {
private final OwnerService ownerService;
private final VisitService visitService;
OwnerController(OwnerService ownerService, VisitService visitService) {
this.ownerService = ownerService;
this.visitService = visitService;
}
@InitBinder("owner")
public void setAllowedFields(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields(CommonAttribute.OWNER_ID);
}
@GetMapping(CommonEndPoint.OWNERS_NEW)
public String initCreationForm(Map<String, Object> model) {
OwnerDTO owner = new OwnerDTO();
model.put(CommonAttribute.OWNER, owner);
return CommonView.OWNER_CREATE_OR_UPDATE;
}
@PostMapping(CommonEndPoint.OWNERS_NEW)
public String processCreationForm(@ModelAttribute(CommonAttribute.OWNER) @Valid OwnerDTO owner,
BindingResult result) {
if (result.hasErrors()) {
return CommonView.OWNER_CREATE_OR_UPDATE;
}
else {
this.ownerService.save(owner);
return CommonView.OWNER_OWNERS_R + owner.getId();
}
}
@GetMapping(CommonEndPoint.OWNERS_FIND)
public String initFindForm(Map<String, Object> model) {
model.put(CommonAttribute.OWNER, new OwnerDTO());
return CommonView.OWNER_FIND_OWNERS;
}
@GetMapping(CommonEndPoint.OWNERS)
public String processFindForm(@ModelAttribute(CommonAttribute.OWNER) OwnerDTO owner, BindingResult result,
Map<String, Object> model) {
// allow parameterless GET request for /owners to return all records
if (owner.getLastName() == null) {
owner.setLastName(""); // empty string signifies broadest possible search
}
// find owners by last name
Collection<OwnerDTO> results = this.ownerService.findByLastName(owner.getLastName());
if (results.isEmpty()) {
// no owners found
result.rejectValue(CommonAttribute.OWNER_LAST_NAME, CommonError.NOT_FOUND_ARGS,
CommonError.NOT_FOUND_MESSAGE);
return CommonView.OWNER_FIND_OWNERS;
}
else if (results.size() == 1) {
// 1 owner found
owner = results.iterator().next();
return CommonView.OWNER_OWNERS_R + owner.getId();
}
else {
// multiple owners found
model.put(CommonAttribute.SELECTIONS, results);
return CommonView.OWNER_OWNERS_LIST;
}
}
@GetMapping(CommonEndPoint.OWNERS_ID_EDIT)
public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
OwnerDTO ownerDTO = this.ownerService.findById(ownerId);
model.addAttribute(CommonAttribute.OWNER, ownerDTO);
return CommonView.OWNER_CREATE_OR_UPDATE;
}
@PostMapping(CommonEndPoint.OWNERS_ID_EDIT)
public String processUpdateOwnerForm(@ModelAttribute(CommonAttribute.OWNER) @Valid OwnerDTO owner,
BindingResult result, @PathVariable("ownerId") int ownerId) {
if (result.hasErrors()) {
return CommonView.OWNER_CREATE_OR_UPDATE;
}
else {
owner.setId(ownerId);
this.ownerService.save(owner);
return CommonView.OWNER_OWNERS_ID_R;
}
}
/**
* Custom handler for displaying an owner.
* @param ownerId the ID of the owner to display
* @return a ModelMap with the model attributes for the view
*/
@GetMapping(CommonEndPoint.OWNERS_ID)
public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
ModelAndView modelAndView = new ModelAndView(CommonView.OWNER_DETAILS);
OwnerDTO owner = this.ownerService.findById(ownerId);
for (PetDTO petDTO : owner.getPets()) {
petDTO.setVisitsInternal(visitService.findByPetId(petDTO.getId()));
}
modelAndView.addObject(CommonAttribute.OWNER, owner);
return modelAndView;
}
}

View file

@ -0,0 +1,126 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonError;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.*;
import org.springframework.samples.petclinic.validator.PetDTOValidator;
import org.springframework.samples.petclinic.service.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Collection;
/**
* @author Juergen Hoeller
* @author Ken Krebs
* @author Arjen Poutsma
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Controller
@RequestMapping(CommonEndPoint.OWNERS_ID)
class PetController {
private final OwnerService ownerService;
private final PetService petService;
private final PetTypeService petTypeService;
@Autowired
PetController(OwnerService ownerService, PetService petService, PetTypeService petTypeService) {
this.ownerService = ownerService;
this.petService = petService;
this.petTypeService = petTypeService;
}
@ModelAttribute("types")
public Collection<PetTypeDTO> populatePetTypes() {
return this.petService.findPetTypes();
}
@ModelAttribute("owner")
public OwnerDTO findOwner(@PathVariable("ownerId") int ownerId) {
return this.ownerService.findById(ownerId);
}
@InitBinder("owner")
public void initOwnerBinder(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields(CommonAttribute.OWNER_ID);
}
@InitBinder("pet")
public void initPetBinder(WebDataBinder dataBinder) {
dataBinder.setValidator(new PetDTOValidator());
}
@GetMapping(CommonEndPoint.PETS_NEW)
public String initCreationForm(@ModelAttribute(CommonAttribute.OWNER) OwnerDTO owner, ModelMap model) {
PetDTO pet = new PetDTO();
owner.addPet(pet);
model.put(CommonAttribute.PET, pet);
return CommonView.PET_CREATE_OR_UPDATE;
}
@PostMapping(CommonEndPoint.PETS_NEW)
public String processCreationForm(@ModelAttribute(CommonAttribute.OWNER) OwnerDTO owner,
@ModelAttribute(CommonAttribute.PET) @Valid PetDTO pet, BindingResult result, ModelMap model) {
if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null) {
result.rejectValue(CommonAttribute.NAME, CommonError.DUPLICATE_ARGS, CommonError.DUPLICATE_MESSAGE);
}
owner.addPet(pet);
if (result.hasErrors()) {
model.put(CommonAttribute.PET, pet);
return CommonView.PET_CREATE_OR_UPDATE;
}
else {
this.petService.save(pet);
return CommonView.OWNER_OWNERS_ID_R;
}
}
@GetMapping(CommonEndPoint.PETS_ID_EDIT)
public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) {
PetDTO pet = this.petService.findById(petId);
model.put(CommonAttribute.PET, pet);
return CommonView.PET_CREATE_OR_UPDATE;
}
@PostMapping(CommonEndPoint.PETS_ID_EDIT)
public String processUpdateForm(@ModelAttribute(CommonAttribute.PET) @Valid PetDTO pet, BindingResult result,
@ModelAttribute(CommonAttribute.OWNER) OwnerDTO owner, ModelMap model) {
if (result.hasErrors()) {
pet.setOwner(owner);
model.put(CommonAttribute.PET, pet);
return CommonView.PET_CREATE_OR_UPDATE;
}
else {
owner.addPet(pet);
this.petService.save(pet);
return CommonView.OWNER_OWNERS_ID_R;
}
}
}

View file

@ -13,8 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.vet; package org.springframework.samples.petclinic.controller;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.VetsDTO;
import org.springframework.samples.petclinic.service.VetService;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@ -26,32 +31,33 @@ import java.util.Map;
* @author Mark Fisher * @author Mark Fisher
* @author Ken Krebs * @author Ken Krebs
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Paul-Emmanuel DOS SANTOS FACAO
*/ */
@Controller @Controller
class VetController { class VetController {
private final VetRepository vets; private final VetService vetService;
public VetController(VetRepository clinicService) { VetController(VetService vetService) {
this.vets = clinicService; this.vetService = vetService;
} }
@GetMapping("/vets.html") @GetMapping(CommonEndPoint.VETS_HTML)
public String showVetList(Map<String, Object> model) { public String showVetList(Map<String, Object> model) {
// Here we are returning an object of type 'Vets' rather than a collection of Vet // Here we are returning an object of type 'Vets' rather than a collection of Vet
// objects so it is simpler for Object-Xml mapping // objects so it is simpler for Object-Xml mapping
Vets vets = new Vets(); VetsDTO vets = new VetsDTO();
vets.getVetList().addAll(this.vets.findAll()); vets.getVetList().addAll(this.vetService.findAll());
model.put("vets", vets); model.put(CommonAttribute.VETS, vets);
return "vets/vetList"; return CommonView.VET_VETS_LIST;
} }
@GetMapping({ "/vets" }) @GetMapping({ CommonEndPoint.VETS })
public @ResponseBody Vets showResourcesVetList() { public @ResponseBody VetsDTO showResourcesVetList() {
// Here we are returning an object of type 'Vets' rather than a collection of Vet // Here we are returning an object of type 'Vets' rather than a collection of Vet
// objects so it is simpler for JSon/Object mapping // objects so it is simpler for JSon/Object mapping
Vets vets = new Vets(); VetsDTO vets = new VetsDTO();
vets.getVetList().addAll(this.vets.findAll()); vets.getVetList().addAll(this.vetService.findAll());
return vets; return vets;
} }

View file

@ -13,14 +13,19 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.controller;
import java.util.Map; import java.util.Map;
import javax.validation.Valid; import javax.validation.Valid;
import org.springframework.samples.petclinic.visit.Visit; import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.dto.VisitDTO;
import org.springframework.samples.petclinic.service.PetService;
import org.springframework.samples.petclinic.service.VisitService;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
@ -36,17 +41,18 @@ import org.springframework.web.bind.annotation.PostMapping;
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Michael Isvy * @author Michael Isvy
* @author Dave Syer * @author Dave Syer
* @author Paul-Emmanuel DOS SANTOS FACAO
*/ */
@Controller @Controller
class VisitController { class VisitController {
private final VisitRepository visits; private final VisitService visitService;
private final PetRepository pets; private final PetService petService;
public VisitController(VisitRepository visits, PetRepository pets) { VisitController(VisitService visitService, PetService petService) {
this.visits = visits; this.visitService = visitService;
this.pets = pets; this.petService = petService;
} }
@InitBinder @InitBinder
@ -58,34 +64,35 @@ class VisitController {
* Called before each and every @RequestMapping annotated method. 2 goals: - Make sure * Called before each and every @RequestMapping annotated method. 2 goals: - Make sure
* we always have fresh data - Since we do not use the session scope, make sure that * we always have fresh data - Since we do not use the session scope, make sure that
* Pet object always has an id (Even though id is not part of the form fields) * Pet object always has an id (Even though id is not part of the form fields)
* @param petId * @param petId Pet identification
* @return Pet * @return Pet
*/ */
@ModelAttribute("visit") @ModelAttribute("visit")
public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map<String, Object> model) { public VisitDTO loadPetWithVisit(@PathVariable("petId") int petId, Map<String, Object> model) {
Pet pet = this.pets.findById(petId); PetDTO pet = this.petService.findById(petId);
pet.setVisitsInternal(this.visits.findByPetId(petId)); pet.setVisitsInternal(this.visitService.findByPetId(petId));
model.put("pet", pet); model.put(CommonAttribute.PET, pet);
Visit visit = new Visit(); VisitDTO visit = new VisitDTO();
pet.addVisit(visit); pet.addVisit(visit);
return visit; return visit;
} }
// Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called // Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called
@GetMapping("/owners/*/pets/{petId}/visits/new") @GetMapping(CommonEndPoint.VISITS_NEW)
public String initNewVisitForm(@PathVariable("petId") int petId, Map<String, Object> model) { public String initNewVisitForm(@PathVariable("petId") int petId, Map<String, Object> model) {
return "pets/createOrUpdateVisitForm"; return CommonView.VISIT_CREATE_OR_UPDATE;
} }
// Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is called // Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is called
@PostMapping("/owners/{ownerId}/pets/{petId}/visits/new") @PostMapping(CommonEndPoint.VISITS_EDIT)
public String processNewVisitForm(@Valid Visit visit, BindingResult result) { public String processNewVisitForm(@ModelAttribute(CommonAttribute.VISIT) @Valid VisitDTO visit,
BindingResult result) {
if (result.hasErrors()) { if (result.hasErrors()) {
return "pets/createOrUpdateVisitForm"; return CommonView.VISIT_CREATE_OR_UPDATE;
} }
else { else {
this.visits.save(visit); this.visitService.save(visit);
return "redirect:/owners/{ownerId}"; return CommonView.OWNER_OWNERS_ID_R;
} }
} }

View file

@ -0,0 +1,42 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.dto;
import java.io.Serializable;
/**
* Simple Data Transfert Object with an id property. Used as a base class for DTO needing
* this property.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class BaseDTO implements Serializable {
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public boolean isNew() {
return this.id == null;
}
}

View file

@ -0,0 +1,53 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.dto;
/**
* Simple Data Transfert Object with a name property to <code>BaseDTO</code>. Used as a
* base class for DTOs needing these properties.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class NamedDTO extends BaseDTO {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return this.getName();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof NamedDTO))
return false;
NamedDTO namedDTO = (NamedDTO) o;
return getName().equals(namedDTO.getName());
}
}

View file

@ -0,0 +1,150 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.dto;
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.core.style.ToStringCreator;
import org.springframework.samples.petclinic.common.CommonAttribute;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotEmpty;
import java.util.*;
/**
* Simple Data Transfert Object representing a owner.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class OwnerDTO extends PersonDTO {
@NotEmpty
private String address;
@NotEmpty
private String city;
@NotEmpty
@Digits(fraction = 0, integer = 10)
private String telephone;
private Set<PetDTO> pets;
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getTelephone() {
return this.telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
protected Set<PetDTO> getPetsInternal() {
if (this.pets == null) {
this.pets = new HashSet<>();
}
return this.pets;
}
public void setPetsInternal(Set<PetDTO> pets) {
this.pets = pets;
}
public List<PetDTO> getPets() {
List<PetDTO> sortedPets = new ArrayList<>(getPetsInternal());
PropertyComparator.sort(sortedPets, new MutableSortDefinition("name", true, true));
return Collections.unmodifiableList(sortedPets);
}
public void addPet(PetDTO pet) {
if (pet.isNew() || this.getPets() == null || !this.getPets().contains(pet)) {
getPetsInternal().add(pet);
}
pet.setOwner(this);
}
/**
* Return the Pet with the given name, or null if none found for this Owner.
* @param name to test
* @return true if pet name is already in use
*/
public PetDTO getPet(String name) {
return getPet(name, false);
}
/**
* Return the Pet with the given name, or null if none found for this Owner.
* @param name to test
* @return true if pet name is already in use
*/
public PetDTO getPet(String name, boolean ignoreNew) {
name = name.toLowerCase();
for (PetDTO pet : getPetsInternal()) {
if (!ignoreNew || !pet.isNew()) {
String compName = pet.getName();
compName = compName.toLowerCase();
if (compName.equals(name)) {
return pet;
}
}
}
return null;
}
@Override
public String toString() {
return new ToStringCreator(this).append(CommonAttribute.OWNER_ID, this.getId())
.append(CommonAttribute.NEW, this.isNew()).append(CommonAttribute.OWNER_LAST_NAME, this.getLastName())
.append(CommonAttribute.OWNER_FIRST_NAME, this.getFirstName())
.append(CommonAttribute.OWNER_ADDRESS, this.address).append(CommonAttribute.OWNER_CITY, this.city)
.append(CommonAttribute.OWNER_PHONE, this.telephone).toString();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof OwnerDTO))
return false;
OwnerDTO ownerDTO = (OwnerDTO) o;
if (!getAddress().equals(ownerDTO.getAddress()))
return false;
if (!getCity().equals(ownerDTO.getCity()))
return false;
if (!getTelephone().equals(ownerDTO.getTelephone()))
return false;
return getPets() != null ? getPets().equals(ownerDTO.getPets()) : ownerDTO.getPets() == null;
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.dto;
import javax.validation.constraints.NotEmpty;
/**
* Simple Data Transfert Object representing a person.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class PersonDTO extends BaseDTO {
@NotEmpty
private String firstName;
@NotEmpty
private String lastName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof PersonDTO))
return false;
PersonDTO personDTO = (PersonDTO) o;
if (!getFirstName().equals(personDTO.getFirstName()))
return false;
return getLastName().equals(personDTO.getLastName());
}
}

View file

@ -0,0 +1,107 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.dto;
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.util.*;
/**
* Simple Data Transfert Object representing a pet.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class PetDTO extends NamedDTO {
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate birthDate;
private PetTypeDTO type;
private OwnerDTO owner;
private Set<VisitDTO> visits = new LinkedHashSet<>();
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public LocalDate getBirthDate() {
return this.birthDate;
}
public PetTypeDTO getType() {
return this.type;
}
public void setType(PetTypeDTO type) {
this.type = type;
}
public OwnerDTO getOwner() {
return owner;
}
public void setOwner(OwnerDTO owner) {
this.owner = owner;
}
protected Set<VisitDTO> getVisitsInternal() {
if (this.visits == null) {
this.visits = new HashSet<>();
}
return this.visits;
}
public void setVisitsInternal(Collection<VisitDTO> visits) {
this.visits = new LinkedHashSet<>(visits);
}
public List<VisitDTO> getVisits() {
List<VisitDTO> sortedVisits = new ArrayList<>(getVisitsInternal());
PropertyComparator.sort(sortedVisits, new MutableSortDefinition("date", false, false));
return Collections.unmodifiableList(sortedVisits);
}
public void addVisit(VisitDTO visit) {
getVisitsInternal().add(visit);
visit.setPetId(this.getId());
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof PetDTO))
return false;
if (!super.equals(o))
return false;
PetDTO petDTO = (PetDTO) o;
if (!getBirthDate().equals(petDTO.getBirthDate()))
return false;
if (!getType().equals(petDTO.getType()))
return false;
if (getOwner() != null ? !getOwner().getId().equals(petDTO.getOwner().getId()) : petDTO.getOwner() != null)
return false;
return getVisits() != null ? getVisits().equals(petDTO.getVisits()) : petDTO.getVisits() == null;
}
}

View file

@ -0,0 +1,15 @@
package org.springframework.samples.petclinic.dto;
/**
* Simple Data Transfert Object representing PetType.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class PetTypeDTO extends NamedDTO {
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
}

View file

@ -0,0 +1,12 @@
package org.springframework.samples.petclinic.dto;
import java.io.Serializable;
/**
* Simple Data Transfert Object representing a list of specialities.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class SpecialtyDTO extends NamedDTO implements Serializable {
}

View file

@ -0,0 +1,74 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.dto;
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.samples.petclinic.model.Specialty;
import javax.xml.bind.annotation.XmlElement;
import java.util.*;
/**
* Simple Data Transfert Object representing a vet.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class VetDTO extends PersonDTO {
private Set<SpecialtyDTO> specialties;
protected Set<SpecialtyDTO> getSpecialtiesInternal() {
if (this.specialties == null) {
this.specialties = new HashSet<>();
}
return this.specialties;
}
protected void setSpecialtiesInternal(Set<SpecialtyDTO> specialties) {
this.specialties = specialties;
}
@XmlElement
public List<SpecialtyDTO> getSpecialties() {
List<SpecialtyDTO> sortedSpecs = new ArrayList<>(getSpecialtiesInternal());
PropertyComparator.sort(sortedSpecs, new MutableSortDefinition("name", true, true));
return Collections.unmodifiableList(sortedSpecs);
}
public int getNrOfSpecialties() {
return getSpecialtiesInternal().size();
}
public void addSpecialty(SpecialtyDTO specialty) {
getSpecialtiesInternal().add(specialty);
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof VetDTO))
return false;
if (!super.equals(o))
return false;
VetDTO vetDTO = (VetDTO) o;
return getSpecialties().equals(vetDTO.getSpecialties());
}
}

View file

@ -0,0 +1,37 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.dto;
import java.util.ArrayList;
import java.util.List;
/**
* Simple Data Transfert Object representing a list of veterinarians.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class VetsDTO {
private List<VetDTO> vets;
public List<VetDTO> getVetList() {
if (vets == null) {
vets = new ArrayList<>();
}
return vets;
}
}

View file

@ -0,0 +1,84 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.dto;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotEmpty;
import java.time.LocalDate;
/**
* Simple Data Transfert Object representing a visit.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class VisitDTO extends BaseDTO {
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate date;
@NotEmpty
private String description;
private Integer petId;
/**
* Creates a new instance of Visit for the current date
*/
public VisitDTO() {
this.date = LocalDate.now();
}
public LocalDate getDate() {
return this.date;
}
public void setDate(LocalDate date) {
this.date = date;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getPetId() {
return this.petId;
}
public void setPetId(Integer petId) {
this.petId = petId;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof VisitDTO))
return false;
VisitDTO visitDTO = (VisitDTO) o;
if (!getDate().equals(visitDTO.getDate()))
return false;
if (!getDescription().equals(visitDTO.getDescription()))
return false;
return getPetId().equals(visitDTO.getPetId());
}
}

View file

@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.formatter;
import java.text.ParseException; import java.text.ParseException;
import java.util.Collection; import java.util.Collection;
import java.util.Locale; import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.Formatter; import org.springframework.format.Formatter;
import org.springframework.samples.petclinic.dto.PetTypeDTO;
import org.springframework.samples.petclinic.service.PetService;
import org.springframework.samples.petclinic.service.PetTypeService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -34,24 +36,23 @@ import org.springframework.stereotype.Component;
* @author Michael Isvy * @author Michael Isvy
*/ */
@Component @Component
public class PetTypeFormatter implements Formatter<PetType> { public class PetTypeFormatter implements Formatter<PetTypeDTO> {
private final PetRepository pets; private final PetService petService;
@Autowired public PetTypeFormatter(PetService petService) {
public PetTypeFormatter(PetRepository pets) { this.petService = petService;
this.pets = pets;
} }
@Override @Override
public String print(PetType petType, Locale locale) { public String print(PetTypeDTO petType, Locale locale) {
return petType.getName(); return petType.getName();
} }
@Override @Override
public PetType parse(String text, Locale locale) throws ParseException { public PetTypeDTO parse(String text, Locale locale) throws ParseException {
Collection<PetType> findPetTypes = this.pets.findPetTypes(); Collection<PetTypeDTO> findPetTypes = this.petService.findPetTypes();
for (PetType type : findPetTypes) { for (PetTypeDTO type : findPetTypes) {
if (type.getName().equals(text)) { if (type.getName().equals(text)) {
return type; return type;
} }

View file

@ -44,4 +44,16 @@ public class NamedEntity extends BaseEntity {
return this.getName(); return this.getName();
} }
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof NamedEntity))
return false;
NamedEntity that = (NamedEntity) o;
return getName().equals(that.getName());
}
} }

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -32,7 +32,7 @@ import javax.validation.constraints.NotEmpty;
import org.springframework.beans.support.MutableSortDefinition; import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator; import org.springframework.beans.support.PropertyComparator;
import org.springframework.core.style.ToStringCreator; import org.springframework.core.style.ToStringCreator;
import org.springframework.samples.petclinic.model.Person; import org.springframework.samples.petclinic.common.CommonAttribute;
/** /**
* Simple JavaBean domain object representing an owner. * Simple JavaBean domain object representing an owner.
@ -104,7 +104,7 @@ public class Owner extends Person {
} }
public void addPet(Pet pet) { public void addPet(Pet pet) {
if (pet.isNew()) { if (!this.getPets().contains(pet)) {
getPetsInternal().add(pet); getPetsInternal().add(pet);
} }
pet.setOwner(this); pet.setOwner(this);
@ -140,11 +140,11 @@ public class Owner extends Person {
@Override @Override
public String toString() { public String toString() {
return new ToStringCreator(this) return new ToStringCreator(this).append(CommonAttribute.OWNER_ID, this.getId())
.append(CommonAttribute.NEW, this.isNew()).append(CommonAttribute.OWNER_LAST_NAME, this.getLastName())
.append("id", this.getId()).append("new", this.isNew()).append("lastName", this.getLastName()) .append(CommonAttribute.OWNER_FIRST_NAME, this.getFirstName())
.append("firstName", this.getFirstName()).append("address", this.address).append("city", this.city) .append(CommonAttribute.OWNER_ADDRESS, this.address).append(CommonAttribute.OWNER_CITY, this.city)
.append("telephone", this.telephone).toString(); .append(CommonAttribute.OWNER_PHONE, this.telephone).toString();
} }
} }

View file

@ -51,4 +51,18 @@ public class Person extends BaseEntity {
this.lastName = lastName; this.lastName = lastName;
} }
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Person))
return false;
Person person = (Person) o;
if (!getFirstName().equals(person.getFirstName()))
return false;
return getLastName().equals(person.getLastName());
}
} }

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.model;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
@ -34,8 +34,6 @@ import javax.persistence.Transient;
import org.springframework.beans.support.MutableSortDefinition; import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator; import org.springframework.beans.support.PropertyComparator;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.samples.petclinic.model.NamedEntity;
import org.springframework.samples.petclinic.visit.Visit;
/** /**
* Simple business object representing a pet. * Simple business object representing a pet.
@ -83,7 +81,7 @@ public class Pet extends NamedEntity {
return this.owner; return this.owner;
} }
protected void setOwner(Owner owner) { public void setOwner(Owner owner) {
this.owner = owner; this.owner = owner;
} }
@ -109,4 +107,24 @@ public class Pet extends NamedEntity {
visit.setPetId(this.getId()); visit.setPetId(this.getId());
} }
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Pet))
return false;
if (!super.equals(o))
return false;
Pet pet = (Pet) o;
if (!getBirthDate().equals(pet.getBirthDate()))
return false;
if (!getType().equals(pet.getType()))
return false;
if (getOwner() != null ? !getOwner().equals(pet.getOwner()) : pet.getOwner() != null)
return false;
return getVisits() != null ? getVisits().equals(pet.getVisits()) : pet.getVisits() == null;
}
} }

View file

@ -13,13 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.model;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Table; import javax.persistence.Table;
import org.springframework.samples.petclinic.model.NamedEntity;
/** /**
* @author Juergen Hoeller Can be Cat, Dog, Hamster... * @author Juergen Hoeller Can be Cat, Dog, Hamster...
*/ */
@ -27,4 +25,9 @@ import org.springframework.samples.petclinic.model.NamedEntity;
@Table(name = "types") @Table(name = "types")
public class PetType extends NamedEntity { public class PetType extends NamedEntity {
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
} }

View file

@ -13,15 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.vet; package org.springframework.samples.petclinic.model;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Table; import javax.persistence.Table;
import org.springframework.samples.petclinic.model.NamedEntity;
/** /**
* Models a {@link Vet Vet's} specialty (for example, dentistry). * Models a {@link Vet Vet's} specialty (for example, dentistry).
* *

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.vet; package org.springframework.samples.petclinic.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -31,7 +31,6 @@ import javax.xml.bind.annotation.XmlElement;
import org.springframework.beans.support.MutableSortDefinition; import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator; import org.springframework.beans.support.PropertyComparator;
import org.springframework.samples.petclinic.model.Person;
/** /**
* Simple JavaBean domain object representing a veterinarian. * Simple JavaBean domain object representing a veterinarian.

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.vet; package org.springframework.samples.petclinic.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.visit; package org.springframework.samples.petclinic.model;
import java.time.LocalDate; import java.time.LocalDate;
@ -23,7 +23,6 @@ import javax.persistence.Table;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.samples.petclinic.model.BaseEntity;
/** /**
* Simple JavaBean domain object representing a visit. * Simple JavaBean domain object representing a visit.
@ -77,4 +76,20 @@ public class Visit extends BaseEntity {
this.petId = petId; this.petId = petId;
} }
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Visit))
return false;
Visit visit = (Visit) o;
if (!getDate().equals(visit.getDate()))
return false;
if (!getDescription().equals(visit.getDescription()))
return false;
return getPetId().equals(visit.getPetId());
}
} }

View file

@ -1,145 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.owner;
import org.springframework.samples.petclinic.visit.VisitRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import java.util.Collection;
import java.util.Map;
/**
* @author Juergen Hoeller
* @author Ken Krebs
* @author Arjen Poutsma
* @author Michael Isvy
*/
@Controller
class OwnerController {
private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
private final OwnerRepository owners;
private VisitRepository visits;
public OwnerController(OwnerRepository clinicService, VisitRepository visits) {
this.owners = clinicService;
this.visits = visits;
}
@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("id");
}
@GetMapping("/owners/new")
public String initCreationForm(Map<String, Object> model) {
Owner owner = new Owner();
model.put("owner", owner);
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/owners/new")
public String processCreationForm(@Valid Owner owner, BindingResult result) {
if (result.hasErrors()) {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
else {
this.owners.save(owner);
return "redirect:/owners/" + owner.getId();
}
}
@GetMapping("/owners/find")
public String initFindForm(Map<String, Object> model) {
model.put("owner", new Owner());
return "owners/findOwners";
}
@GetMapping("/owners")
public String processFindForm(Owner owner, BindingResult result, Map<String, Object> model) {
// allow parameterless GET request for /owners to return all records
if (owner.getLastName() == null) {
owner.setLastName(""); // empty string signifies broadest possible search
}
// find owners by last name
Collection<Owner> results = this.owners.findByLastName(owner.getLastName());
if (results.isEmpty()) {
// no owners found
result.rejectValue("lastName", "notFound", "not found");
return "owners/findOwners";
}
else if (results.size() == 1) {
// 1 owner found
owner = results.iterator().next();
return "redirect:/owners/" + owner.getId();
}
else {
// multiple owners found
model.put("selections", results);
return "owners/ownersList";
}
}
@GetMapping("/owners/{ownerId}/edit")
public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
Owner owner = this.owners.findById(ownerId);
model.addAttribute(owner);
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/owners/{ownerId}/edit")
public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result,
@PathVariable("ownerId") int ownerId) {
if (result.hasErrors()) {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
else {
owner.setId(ownerId);
this.owners.save(owner);
return "redirect:/owners/{ownerId}";
}
}
/**
* Custom handler for displaying an owner.
* @param ownerId the ID of the owner to display
* @return a ModelMap with the model attributes for the view
*/
@GetMapping("/owners/{ownerId}")
public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
ModelAndView mav = new ModelAndView("owners/ownerDetails");
Owner owner = this.owners.findById(ownerId);
for (Pet pet : owner.getPets()) {
pet.setVisitsInternal(visits.findByPetId(pet.getId()));
}
mav.addObject(owner);
return mav;
}
}

View file

@ -1,113 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.owner;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Collection;
/**
* @author Juergen Hoeller
* @author Ken Krebs
* @author Arjen Poutsma
*/
@Controller
@RequestMapping("/owners/{ownerId}")
class PetController {
private static final String VIEWS_PETS_CREATE_OR_UPDATE_FORM = "pets/createOrUpdatePetForm";
private final PetRepository pets;
private final OwnerRepository owners;
public PetController(PetRepository pets, OwnerRepository owners) {
this.pets = pets;
this.owners = owners;
}
@ModelAttribute("types")
public Collection<PetType> populatePetTypes() {
return this.pets.findPetTypes();
}
@ModelAttribute("owner")
public Owner findOwner(@PathVariable("ownerId") int ownerId) {
return this.owners.findById(ownerId);
}
@InitBinder("owner")
public void initOwnerBinder(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("id");
}
@InitBinder("pet")
public void initPetBinder(WebDataBinder dataBinder) {
dataBinder.setValidator(new PetValidator());
}
@GetMapping("/pets/new")
public String initCreationForm(Owner owner, ModelMap model) {
Pet pet = new Pet();
owner.addPet(pet);
model.put("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/pets/new")
public String processCreationForm(Owner owner, @Valid Pet pet, BindingResult result, ModelMap model) {
if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null) {
result.rejectValue("name", "duplicate", "already exists");
}
owner.addPet(pet);
if (result.hasErrors()) {
model.put("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
}
else {
this.pets.save(pet);
return "redirect:/owners/{ownerId}";
}
}
@GetMapping("/pets/{petId}/edit")
public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) {
Pet pet = this.pets.findById(petId);
model.put("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/pets/{petId}/edit")
public String processUpdateForm(@Valid Pet pet, BindingResult result, Owner owner, ModelMap model) {
if (result.hasErrors()) {
pet.setOwner(owner);
model.put("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
}
else {
owner.addPet(pet);
this.pets.save(pet);
return "redirect:/owners/{ownerId}";
}
}
}

View file

@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.repository;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository; import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** /**
@ -32,6 +34,7 @@ import org.springframework.transaction.annotation.Transactional;
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen
* @author Michael Isvy * @author Michael Isvy
* @author Paul-Emmanuel DOS SANTOS FACAO
*/ */
public interface OwnerRepository extends Repository<Owner, Integer> { public interface OwnerRepository extends Repository<Owner, Integer> {
@ -55,6 +58,12 @@ public interface OwnerRepository extends Repository<Owner, Integer> {
@Transactional(readOnly = true) @Transactional(readOnly = true)
Owner findById(@Param("id") Integer id); Owner findById(@Param("id") Integer id);
/**
* Retrieve all {@link Owner}s from the data store
* @return a Collection of {@link Owner}s (or an empty Collection if none
*/
List<Owner> findAll();
/** /**
* Save an {@link Owner} to the data store, either inserting or updating it. * Save an {@link Owner} to the data store, either inserting or updating it.
* @param owner the {@link Owner} to save * @param owner the {@link Owner} to save

View file

@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.repository;
import java.util.List; import java.util.List;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository; import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** /**
@ -31,6 +33,7 @@ import org.springframework.transaction.annotation.Transactional;
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen
* @author Michael Isvy * @author Michael Isvy
* @author Paul-Emmanuel DOS SANTOS FACAO
*/ */
public interface PetRepository extends Repository<Pet, Integer> { public interface PetRepository extends Repository<Pet, Integer> {
@ -47,9 +50,21 @@ public interface PetRepository extends Repository<Pet, Integer> {
* @param id the id to search for * @param id the id to search for
* @return the {@link Pet} if found * @return the {@link Pet} if found
*/ */
@Transactional(readOnly = true)
Pet findById(Integer id); Pet findById(Integer id);
/**
* Retrieve all {@link Pet}d from the data store by owner id.
* @param id the id of owner to search for
* @return a Collection of {@link Pet}s
*/
List<Pet> findByOwnerId(Integer id);
/**
* Retrieve all {@link Pet}s from the data store
* @return a Collection of {@link Pet}s (or an empty Collection if none
*/
List<Pet> findAll();
/** /**
* Save a {@link Pet} to the data store, either inserting or updating it. * Save a {@link Pet} to the data store, either inserting or updating it.
* @param pet the {@link Pet} to save * @param pet the {@link Pet} to save

View file

@ -0,0 +1,51 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.PetType;
import java.util.Collection;
import java.util.List;
/**
* Repository class for <code>PetType</code> domain objects All method names are compliant
* with Spring Data naming conventions so this interface can easily be extended for Spring
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public interface PetTypeRepository extends Repository<PetType, Integer> {
/**
* Retrieve a {@link PetType} from the data store by id.
* @param id the id to search for
* @return the {@link PetType} if found
*/
PetType findById(Integer id);
/**
* Retrieve all {@link PetType}s from the data store
* @return a Collection of {@link PetType}s (or an empty Collection if none
*/
List<PetType> findAll();
/**
* Save a {@link PetType} to the data store, either inserting or updating it.
* @param petType the {@link PetType} to save
*/
void save(PetType petType);
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.Specialty;
import java.util.Collection;
import java.util.List;
/**
* Repository class for <code>Speciality</code> domain objects All method names are
* compliant with Spring Data naming conventions so this interface can easily be extended
* for Spring
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public interface SpecialtyRepository extends Repository<Specialty, Integer> {
/**
* Retrieve a {@link Specialty} from the data store by id.
* @param id the id to search for
* @return the {@link Specialty} if found
*/
Specialty findById(Integer id);
/**
* Retrieve all {@link Specialty}s from the data store
* @return a Collection of {@link Specialty}s (or an empty Collection if none
*/
List<Specialty> findAll();
/**
* Save a {@link Specialty} to the data store, either inserting or updating it.
* @param specialty the {@link Specialty} to save
*/
void save(Specialty specialty);
}

View file

@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.vet; package org.springframework.samples.petclinic.repository;
import java.util.Collection; import java.util.Collection;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.DataAccessException;
import org.springframework.data.repository.Repository; import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.Vet;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** /**
@ -32,15 +32,29 @@ import org.springframework.transaction.annotation.Transactional;
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen
* @author Michael Isvy * @author Michael Isvy
* @author Paul-Emmanuel DOS SANTOS FACAO
*/ */
public interface VetRepository extends Repository<Vet, Integer> { public interface VetRepository extends Repository<Vet, Integer> {
/**
* Retrieve a {@link Vet} from the data store by id.
* @param id the id to search for
* @return the {@link Vet} if found
*/
Vet findById(Integer id);
/** /**
* Retrieve all <code>Vet</code>s from the data store. * Retrieve all <code>Vet</code>s from the data store.
* @return a <code>Collection</code> of <code>Vet</code>s * @return a <code>Collection</code> of <code>Vet</code>s
*/ */
@Transactional(readOnly = true) @Transactional(readOnly = true)
@Cacheable("vets") @Cacheable("vets")
Collection<Vet> findAll() throws DataAccessException; Collection<Vet> findAll();
/**
* Save a {@link Vet} to the data store, either inserting or updating it.
* @param vet the {@link Vet} to save
*/
void save(Vet vet);
} }

View file

@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.visit; package org.springframework.samples.petclinic.repository;
import java.util.Collection;
import java.util.List; import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.data.repository.Repository; import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.BaseEntity; import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.model.Visit;
/** /**
* Repository class for <code>Visit</code> domain objects All method names are compliant * Repository class for <code>Visit</code> domain objects All method names are compliant
@ -31,6 +32,7 @@ import org.springframework.samples.petclinic.model.BaseEntity;
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen
* @author Michael Isvy * @author Michael Isvy
* @author Paul-Emmanuel DOS SANTOS FACAO
*/ */
public interface VisitRepository extends Repository<Visit, Integer> { public interface VisitRepository extends Repository<Visit, Integer> {
@ -39,8 +41,21 @@ public interface VisitRepository extends Repository<Visit, Integer> {
* @param visit the <code>Visit</code> to save * @param visit the <code>Visit</code> to save
* @see BaseEntity#isNew * @see BaseEntity#isNew
*/ */
void save(Visit visit) throws DataAccessException; void save(Visit visit);
/**
* Retrieve a {@link Visit} from the data store by id.
* @param id the id to search for
* @return the {@link Visit} if found
*/
Visit findById(Integer id);
List<Visit> findByPetId(Integer petId); List<Visit> findByPetId(Integer petId);
/**
* Retrieve all {@link Visit}s from the data store
* @return a Collection of {@link Visit}s (or an empty Collection if none
*/
List<Visit> findAll();
} }

View file

@ -0,0 +1,58 @@
package org.springframework.samples.petclinic.service;
import java.util.List;
/**
* Interface for all services
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public interface BaseService<E, D> {
/**
* Convert Data Transfert Object to Entity Model
* @param dto DTO
* @return Entity Model
*/
E dtoToEntity(D dto);
/**
* Convert Entity Model to Data Transfert Object
* @param entity Entity Model
* @return DTO
*/
D entityToDTO(E entity);
/**
* Convert Entities Models Collection to Data Transfert Object Collection
* @param entities Collection of Entity Model
* @return Collection of DTO
*/
List<D> entitiesToDTOS(List<E> entities);
/**
* Convert Entities Models Collection to Data Transfert Object Collection
* @param dtos Collection of DTO
* @return Collection of Entity Model
*/
List<E> dtosToEntities(List<D> dtos);
/**
* Get DTO object from repository by his ID
* @param id identify object to be found
* @return
*/
D findById(int id);
/**
* Get all DTO objects from repository
* @return
*/
List<D> findAll();
/**
* Save DTO object to repository
*/
void save(D dto);
}

View file

@ -0,0 +1,112 @@
package org.springframework.samples.petclinic.service;
import org.modelmapper.ModelMapper;
import org.modelmapper.internal.util.Lists;
import org.springframework.samples.petclinic.dto.OwnerDTO;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.repository.OwnerRepository;
import org.springframework.samples.petclinic.repository.PetRepository;
import org.springframework.samples.petclinic.repository.PetTypeRepository;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Simple Service between Owner entity and OwnerDTO Data Transfert Object.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Service("OwnerService")
public class OwnerService implements BaseService<Owner, OwnerDTO> {
private final OwnerRepository ownerRepository;
private final PetRepository petRepository;
private final ModelMapper modelMapper = new ModelMapper();
private PetService petService;
public OwnerService(OwnerRepository ownerRepository, PetRepository petRepository,
PetTypeRepository petTypeRepository, VisitRepository visitRepository) {
this.ownerRepository = ownerRepository;
this.petRepository = petRepository;
petService = new PetService(petRepository, petTypeRepository, visitRepository);
}
@Override
public Owner dtoToEntity(OwnerDTO dto) {
if (dto != null) {
Owner owner = modelMapper.map(dto, Owner.class);
dto.getPets().forEach(petDTO -> {
Pet pet = modelMapper.map(petDTO, Pet.class);
pet.setOwner(owner);
owner.addPet(pet);
});
return owner;
}
return new Owner();
}
@Override
public OwnerDTO entityToDTO(Owner entity) {
if (entity != null) {
OwnerDTO ownerDTO = modelMapper.map(entity, OwnerDTO.class);
entity.getPets().forEach(pet -> {
PetDTO petDTO = modelMapper.map(pet, PetDTO.class);
petDTO.setOwner(ownerDTO);
ownerDTO.addPet(petDTO);
});
return ownerDTO;
}
return new OwnerDTO();
}
@Override
public List<OwnerDTO> entitiesToDTOS(List<Owner> entities) {
List<OwnerDTO> dtos = new ArrayList<>();
entities.forEach(entity -> dtos.add(entityToDTO(entity)));
return dtos;
}
@Override
public List<Owner> dtosToEntities(List<OwnerDTO> dtos) {
List<Owner> entities = new ArrayList<>();
dtos.forEach(dto -> entities.add(dtoToEntity(dto)));
return entities;
}
@Override
public OwnerDTO findById(int ownerId) {
Owner owner = ownerRepository.findById(ownerId);
return entityToDTO(owner);
}
@Override
public List<OwnerDTO> findAll() {
return entitiesToDTOS(ownerRepository.findAll());
}
@Override
public void save(OwnerDTO ownerDTO) {
Owner owner = dtoToEntity(ownerDTO);
ownerRepository.save(owner);
}
public List<OwnerDTO> findByLastName(String lastName) {
Collection<Owner> owners = ownerRepository.findByLastName(lastName);
return entitiesToDTOS(Lists.from(owners.iterator()));
}
}

View file

@ -0,0 +1,134 @@
package org.springframework.samples.petclinic.service;
import org.modelmapper.ModelMapper;
import org.springframework.samples.petclinic.dto.OwnerDTO;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.dto.PetTypeDTO;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.repository.PetRepository;
import org.springframework.samples.petclinic.repository.PetTypeRepository;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* Simple Service between Pet entity and PetDTO Data Transfert Object.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Service("PetService")
public class PetService implements BaseService<Pet, PetDTO> {
private final PetRepository petRepository;
private final PetTypeService petTypeService;
private final PetTypeRepository petTypeRepository;
private final VisitService visitService;
private final ModelMapper modelMapper = new ModelMapper();
public PetService(PetRepository petRepository, PetTypeRepository petTypeRepository,
VisitRepository visitRepository) {
this.petRepository = petRepository;
this.petTypeRepository = petTypeRepository;
this.visitService = new VisitService(visitRepository);
this.petTypeService = new PetTypeService(petTypeRepository);
}
@Override
public Pet dtoToEntity(PetDTO dto) {
if (dto != null) {
Pet pet = modelMapper.map(dto, Pet.class);
Owner owner = modelMapper.map(dto.getOwner(), Owner.class);
dto.getVisits().forEach(visitDTO -> pet.addVisit(visitService.dtoToEntity(visitDTO)));
dto.getOwner().getPets().forEach(petDTO -> {
if (dto.getId() == null || petDTO.getId().equals(dto.getId())) {
owner.addPet(pet);
}
else {
Pet otherPet = modelMapper.map(petDTO, Pet.class);
otherPet.setOwner(owner);
owner.addPet(otherPet);
}
});
pet.setOwner(owner);
return pet;
}
return new Pet();
}
@Override
public PetDTO entityToDTO(Pet entity) {
if (entity != null) {
PetDTO petDTO = modelMapper.map(entity, PetDTO.class);
OwnerDTO ownerDTO = modelMapper.map(entity.getOwner(), OwnerDTO.class);
petRepository.findByOwnerId(ownerDTO.getId()).forEach(pet -> {
PetDTO otherPetDTO = modelMapper.map(pet, PetDTO.class);
otherPetDTO.setOwner(ownerDTO);
ownerDTO.addPet(otherPetDTO);
});
entity.getVisits().forEach(visit -> petDTO.addVisit(visitService.entityToDTO(visit)));
petDTO.setOwner(ownerDTO);
return petDTO;
}
return new PetDTO();
}
@Override
public List<PetDTO> entitiesToDTOS(List<Pet> entities) {
List<PetDTO> dtos = new ArrayList<>();
entities.forEach(entity -> dtos.add(entityToDTO(entity)));
return dtos;
}
@Override
public List<Pet> dtosToEntities(List<PetDTO> dtos) {
List<Pet> entities = new ArrayList<>();
dtos.forEach(dto -> entities.add(dtoToEntity(dto)));
return entities;
}
@Override
public PetDTO findById(int petId) {
Pet pet = petRepository.findById(petId);
return entityToDTO(pet);
}
@Override
public List<PetDTO> findAll() {
return entitiesToDTOS(petRepository.findAll());
}
@Override
public void save(PetDTO petDTO) {
petRepository.save(dtoToEntity(petDTO));
}
public List<PetDTO> findByOwnerId(int id) {
return entitiesToDTOS(petRepository.findByOwnerId(id));
}
public List<PetTypeDTO> findPetTypes() {
List<PetType> petTypes = petRepository.findPetTypes();
return petTypeService.entitiesToDTOS(petTypes);
}
}

View file

@ -0,0 +1,79 @@
package org.springframework.samples.petclinic.service;
import org.modelmapper.ModelMapper;
import org.springframework.samples.petclinic.dto.PetTypeDTO;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.repository.PetTypeRepository;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* Simple Service between PetType entity and PetTypeDTO Data Transfert Object.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Service("PerTypeService")
public class PetTypeService implements BaseService<PetType, PetTypeDTO> {
private final PetTypeRepository petTypeRepository;
private final ModelMapper modelMapper = new ModelMapper();
public PetTypeService(PetTypeRepository petTypeRepository) {
this.petTypeRepository = petTypeRepository;
}
@Override
public PetType dtoToEntity(PetTypeDTO dto) {
if (dto != null) {
return modelMapper.map(dto, PetType.class);
}
return new PetType();
}
@Override
public PetTypeDTO entityToDTO(PetType entity) {
if (entity != null) {
return modelMapper.map(entity, PetTypeDTO.class);
}
return new PetTypeDTO();
}
@Override
public List<PetTypeDTO> entitiesToDTOS(List<PetType> entities) {
List<PetTypeDTO> dtos = new ArrayList<>();
entities.forEach(entity -> dtos.add(entityToDTO(entity)));
return dtos;
}
@Override
public List<PetType> dtosToEntities(List<PetTypeDTO> dtos) {
List<PetType> entities = new ArrayList<>();
dtos.forEach(dto -> entities.add(dtoToEntity(dto)));
return entities;
}
@Override
public PetTypeDTO findById(int id) {
return entityToDTO(petTypeRepository.findById(id));
}
@Override
public List<PetTypeDTO> findAll() {
return entitiesToDTOS(petTypeRepository.findAll());
}
@Override
public void save(PetTypeDTO dto) {
petTypeRepository.save(dtoToEntity(dto));
}
}

View file

@ -0,0 +1,81 @@
package org.springframework.samples.petclinic.service;
import org.modelmapper.ModelMapper;
import org.springframework.samples.petclinic.dto.SpecialtyDTO;
import org.springframework.samples.petclinic.model.Specialty;
import org.springframework.samples.petclinic.repository.SpecialtyRepository;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
/**
* Simple Service between Specialty entity and SpecialtyDTO Data Transfert Object.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Service("SpecialityService")
public class SpecialtyService implements BaseService<Specialty, SpecialtyDTO> {
private final SpecialtyRepository specialtyRepository;
private final ModelMapper modelMapper = new ModelMapper();
public SpecialtyService(SpecialtyRepository specialtyRepository) {
this.specialtyRepository = specialtyRepository;
}
@Override
public Specialty dtoToEntity(SpecialtyDTO dto) {
if (dto != null) {
return modelMapper.map(dto, Specialty.class);
}
return new Specialty();
}
@Override
public SpecialtyDTO entityToDTO(Specialty entity) {
if (entity != null) {
return modelMapper.map(entity, SpecialtyDTO.class);
}
return new SpecialtyDTO();
}
@Override
public List<SpecialtyDTO> entitiesToDTOS(List<Specialty> entities) {
List<SpecialtyDTO> dtos = new ArrayList<>();
entities.forEach(entity -> dtos.add(entityToDTO(entity)));
return dtos;
}
@Override
public List<Specialty> dtosToEntities(List<SpecialtyDTO> dtos) {
List<Specialty> entities = new ArrayList<>();
dtos.forEach(dto -> entities.add(dtoToEntity(dto)));
return entities;
}
@Override
public SpecialtyDTO findById(int id) {
return entityToDTO(specialtyRepository.findById(id));
}
@Override
public List<SpecialtyDTO> findAll() {
return entitiesToDTOS(specialtyRepository.findAll());
}
@Override
public void save(SpecialtyDTO dto) {
specialtyRepository.save(dtoToEntity(dto));
}
}

View file

@ -0,0 +1,97 @@
package org.springframework.samples.petclinic.service;
import org.modelmapper.ModelMapper;
import org.modelmapper.internal.util.Lists;
import org.springframework.samples.petclinic.dto.SpecialtyDTO;
import org.springframework.samples.petclinic.dto.VetDTO;
import org.springframework.samples.petclinic.model.Specialty;
import org.springframework.samples.petclinic.repository.SpecialtyRepository;
import org.springframework.samples.petclinic.repository.VetRepository;
import org.springframework.samples.petclinic.model.Vet;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
/**
* Simple Service between Vet entity and VetDTO Data Transfert Object.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Service("VetService")
public class VetService implements BaseService<Vet, VetDTO> {
private final VetRepository vetRepository;
private final SpecialtyService specialtyService;
private final ModelMapper modelMapper = new ModelMapper();
public VetService(VetRepository vetRepository, SpecialtyRepository specialtyRepository) {
this.vetRepository = vetRepository;
this.specialtyService = new SpecialtyService(specialtyRepository);
}
@Override
public Vet dtoToEntity(VetDTO dto) {
if (dto != null) {
Vet vet = modelMapper.map(dto, Vet.class);
dto.getSpecialties().forEach(specialtyDTO -> {
Specialty specialty = specialtyService.dtoToEntity(specialtyDTO);
vet.addSpecialty(specialty);
});
return vet;
}
return new Vet();
}
@Override
public VetDTO entityToDTO(Vet entity) {
if (entity != null) {
VetDTO vetDTO = modelMapper.map(entity, VetDTO.class);
entity.getSpecialties().forEach(specialty -> {
SpecialtyDTO specialtyDTO = specialtyService.entityToDTO(specialty);
vetDTO.addSpecialty(specialtyDTO);
});
return vetDTO;
}
return new VetDTO();
}
@Override
public List<VetDTO> entitiesToDTOS(List<Vet> entities) {
List<VetDTO> dtos = new ArrayList<>();
entities.forEach(entity -> dtos.add(entityToDTO(entity)));
return dtos;
}
@Override
public List<Vet> dtosToEntities(List<VetDTO> dtos) {
List<Vet> entities = new ArrayList<>();
dtos.forEach(dto -> entities.add(dtoToEntity(dto)));
return entities;
}
@Override
public VetDTO findById(int id) {
return entityToDTO(vetRepository.findById(id));
}
public List<VetDTO> findAll() {
Collection<Vet> vets = vetRepository.findAll();
return entitiesToDTOS(Lists.from(vets.iterator()));
}
@Override
public void save(VetDTO dto) {
vetRepository.save(dtoToEntity(dto));
}
}

View file

@ -0,0 +1,93 @@
package org.springframework.samples.petclinic.service;
import org.modelmapper.ModelMapper;
import org.springframework.samples.petclinic.dto.VisitDTO;
import org.springframework.samples.petclinic.model.Visit;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
/**
* Simple Service between Visit entity and VisitDTO Data Transfert Object.
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Service("VisitService")
public class VisitService implements BaseService<Visit, VisitDTO> {
private final VisitRepository visitRepository;
private final ModelMapper modelMapper = new ModelMapper();
public VisitService(VisitRepository visitRepository) {
this.visitRepository = visitRepository;
}
@Override
public Visit dtoToEntity(VisitDTO dto) {
if (dto != null) {
return modelMapper.map(dto, Visit.class);
}
return new Visit();
}
@Override
public VisitDTO entityToDTO(Visit entity) {
if (entity != null) {
return modelMapper.map(entity, VisitDTO.class);
}
return new VisitDTO();
}
@Override
public List<VisitDTO> entitiesToDTOS(List<Visit> entities) {
List<VisitDTO> dtos = new ArrayList<>();
entities.forEach(entity -> dtos.add(entityToDTO(entity)));
return dtos;
}
@Override
public List<Visit> dtosToEntities(List<VisitDTO> dtos) {
List<Visit> entities = new ArrayList<>();
dtos.forEach(dto -> entities.add(dtoToEntity(dto)));
return entities;
}
@Override
public VisitDTO findById(int id) {
return entityToDTO(visitRepository.findById(id));
}
@Override
public List<VisitDTO> findAll() {
return entitiesToDTOS(visitRepository.findAll());
}
@Override
public void save(VisitDTO visitDTO) {
Visit visit = dtoToEntity(visitDTO);
visitRepository.save(visit);
}
public Collection<VisitDTO> findByPetId(Integer petId) {
Collection<Visit> visits = visitRepository.findByPetId(petId);
Collection<VisitDTO> visitDTOS = new HashSet<>();
for (Visit visit : visits) {
visitDTOS.add(entityToDTO(visit));
}
return visitDTOS;
}
}

View file

@ -34,9 +34,7 @@ class CacheConfiguration {
@Bean @Bean
public JCacheManagerCustomizer petclinicCacheConfigurationCustomizer() { public JCacheManagerCustomizer petclinicCacheConfigurationCustomizer() {
return cm -> { return cm -> cm.createCache("vets", cacheConfiguration());
cm.createCache("vets", cacheConfiguration());
};
} }
/** /**

View file

@ -0,0 +1,66 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.validator;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonError;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
/**
* <code>Validator</code> for <code>PetDTO</code> forms.
* <p>
* We're not using Bean Validation annotations here because it is easier to define such
* validation rule in Java.
* </p>
*
* @author Ken Krebs
* @author Juergen Hoeller
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
public class PetDTOValidator implements Validator {
@Override
public void validate(Object obj, Errors errors) {
PetDTO pet = (PetDTO) obj;
String name = pet.getName();
// name validation
if (!StringUtils.hasLength(name)) {
errors.rejectValue(CommonAttribute.PET_NAME, CommonError.REQUIRED_ARGS, CommonError.REQUIRED_MESSAGE);
}
// type validation
if (pet.isNew() && pet.getType() == null) {
errors.rejectValue(CommonAttribute.PET_TYPE, CommonError.REQUIRED_ARGS, CommonError.REQUIRED_MESSAGE);
}
// birth date validation
if (pet.getBirthDate() == null) {
errors.rejectValue(CommonAttribute.PET_BIRTH_DATE, CommonError.REQUIRED_ARGS, CommonError.REQUIRED_MESSAGE);
}
}
/**
* This Validator validates *just* Pet instances
*/
@Override
public boolean supports(Class<?> clazz) {
return PetDTO.class.isAssignableFrom(clazz);
}
}

View file

@ -13,8 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.validator;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonError;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.validation.Errors; import org.springframework.validation.Errors;
import org.springframework.validation.Validator; import org.springframework.validation.Validator;
@ -28,28 +31,27 @@ import org.springframework.validation.Validator;
* *
* @author Ken Krebs * @author Ken Krebs
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Paul-Emmanuel DOS SANTOS FACAO
*/ */
public class PetValidator implements Validator { public class PetValidator implements Validator {
private static final String REQUIRED = "required";
@Override @Override
public void validate(Object obj, Errors errors) { public void validate(Object obj, Errors errors) {
Pet pet = (Pet) obj; Pet pet = (Pet) obj;
String name = pet.getName(); String name = pet.getName();
// name validation // name validation
if (!StringUtils.hasLength(name)) { if (!StringUtils.hasLength(name)) {
errors.rejectValue("name", REQUIRED, REQUIRED); errors.rejectValue(CommonAttribute.PET_NAME, CommonError.REQUIRED_ARGS, CommonError.REQUIRED_MESSAGE);
} }
// type validation // type validation
if (pet.isNew() && pet.getType() == null) { if (pet.isNew() && pet.getType() == null) {
errors.rejectValue("type", REQUIRED, REQUIRED); errors.rejectValue(CommonAttribute.PET_TYPE, CommonError.REQUIRED_ARGS, CommonError.REQUIRED_MESSAGE);
} }
// birth date validation // birth date validation
if (pet.getBirthDate() == null) { if (pet.getBirthDate() == null) {
errors.rejectValue("birthDate", REQUIRED, REQUIRED); errors.rejectValue(CommonAttribute.PET_BIRTH_DATE, CommonError.REQUIRED_ARGS, CommonError.REQUIRED_MESSAGE);
} }
} }

View file

@ -1,6 +1,7 @@
<groups xmlns="http://www.isdc.ro/wro"> <groups xmlns="http://www.isdc.ro/wro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.isdc.ro/wro ">
<group name="petclinic"> <group name="petclinic">
<css>classpath:META-INF/resources/webjars/bootstrap/3.3.6/less/bootstrap.less</css> <css>classpath:META-INF/resources/webjars/bootstrap/3.3.6/less/bootstrap.less</css>
<css>/petclinic.less</css> <css>/petclinic.less</css>
</group> </group>
</groups> </groups>

View file

@ -19,7 +19,7 @@ package org.springframework.samples.petclinic;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.samples.petclinic.vet.VetRepository; import org.springframework.samples.petclinic.repository.VetRepository;
@SpringBootTest @SpringBootTest
class PetclinicIntegrationTests { class PetclinicIntegrationTests {

View file

@ -0,0 +1,244 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.controller;
import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import org.assertj.core.util.Lists;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.OwnerDTO;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.dto.PetTypeDTO;
import org.springframework.samples.petclinic.dto.VisitDTO;
import org.springframework.samples.petclinic.service.OwnerService;
import org.springframework.samples.petclinic.service.VisitService;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
/**
* Test class for {@link OwnerController}
*
* @author Colin But
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@WebMvcTest(OwnerController.class)
class OwnerControllerTests {
private static final int TEST_OWNER_ID = 1;
@Autowired
private MockMvc mockMvc;
@MockBean
private OwnerService owners;
@MockBean
private VisitService visits;
private OwnerDTO george;
@BeforeEach
void setup() {
george = new OwnerDTO();
george.setId(TEST_OWNER_ID);
george.setFirstName("George");
george.setLastName("Franklin");
george.setAddress("110 W. Liberty St.");
george.setCity("Madison");
george.setTelephone("6085551023");
PetDTO max = new PetDTO();
PetTypeDTO dog = new PetTypeDTO();
dog.setName("dog");
max.setId(1);
max.setType(dog);
max.setName("Max");
max.setBirthDate(LocalDate.now());
george.setPetsInternal(Collections.singleton(max));
given(this.owners.findById(TEST_OWNER_ID)).willReturn(george);
VisitDTO visit = new VisitDTO();
visit.setDate(LocalDate.now());
given(this.visits.findByPetId(max.getId())).willReturn(Collections.singletonList(visit));
}
@Test
@Tag("initCreationForm")
void testInitCreationForm() throws Exception {
mockMvc.perform(get(CommonEndPoint.OWNERS_NEW)).andExpect(status().isOk())
.andExpect(model().attributeExists(CommonAttribute.OWNER))
.andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE));
}
@Test
@Tag("processCreationForm")
void testProcessCreationFormSuccess() throws Exception {
mockMvc.perform(post("/owners/new").param(CommonAttribute.OWNER_FIRST_NAME, "Joe")
.param(CommonAttribute.OWNER_LAST_NAME, "Bloggs")
.param(CommonAttribute.OWNER_ADDRESS, "123 Caramel Street").param(CommonAttribute.OWNER_CITY, "London")
.param(CommonAttribute.OWNER_PHONE, "01316761638")).andExpect(status().is3xxRedirection());
}
@Test
@Tag("processCreationForm")
void testProcessCreationFormHasErrors() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_NEW).param(CommonAttribute.OWNER_FIRST_NAME, "Joe")
.param(CommonAttribute.OWNER_LAST_NAME, "Bloggs").param(CommonAttribute.OWNER_CITY, "London"))
.andExpect(status().isOk()).andExpect(model().attributeHasErrors(CommonAttribute.OWNER))
.andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_ADDRESS))
.andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_PHONE))
.andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE));
}
@Test
@Tag("initFindForm")
void testInitFindForm() throws Exception {
mockMvc.perform(get(CommonEndPoint.OWNERS_FIND)).andExpect(status().isOk())
.andExpect(model().attributeExists(CommonAttribute.OWNER))
.andExpect(view().name(CommonView.OWNER_FIND_OWNERS));
}
@Test
@Tag("processFindForm")
void testProcessFindFormSuccess() throws Exception {
given(this.owners.findByLastName("")).willReturn(Lists.newArrayList(george, new OwnerDTO()));
mockMvc.perform(get(CommonEndPoint.OWNERS)).andExpect(status().isOk())
.andExpect(view().name(CommonView.OWNER_OWNERS_LIST));
}
@Test
@Tag("processFindForm")
void testProcessFindFormByLastName() throws Exception {
given(this.owners.findByLastName(george.getLastName())).willReturn(Lists.newArrayList(george));
mockMvc.perform(get(CommonEndPoint.OWNERS).param(CommonAttribute.OWNER_LAST_NAME, "Franklin"))
.andExpect(status().is3xxRedirection())
.andExpect(view().name(CommonView.OWNER_OWNERS_R + TEST_OWNER_ID));
}
@Test
@Tag("processFindForm")
void testProcessFindFormNoOwnersFound() throws Exception {
mockMvc.perform(get(CommonEndPoint.OWNERS).param(CommonAttribute.OWNER_LAST_NAME, "Unknown Surname"))
.andExpect(status().isOk())
.andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_LAST_NAME))
.andExpect(model().attributeHasFieldErrorCode(CommonAttribute.OWNER, CommonAttribute.OWNER_LAST_NAME,
"notFound"))
.andExpect(view().name(CommonView.OWNER_FIND_OWNERS));
}
@Test
@Tag("initUpdateOwnerForm")
void testInitUpdateOwnerForm() throws Exception {
mockMvc.perform(get(CommonEndPoint.OWNERS_ID_EDIT, TEST_OWNER_ID)).andExpect(status().isOk())
.andExpect(model().attributeExists(CommonAttribute.OWNER))
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_LAST_NAME, is("Franklin"))))
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_FIRST_NAME, is("George"))))
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_ADDRESS, is("110 W. Liberty St."))))
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_CITY, is("Madison"))))
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_PHONE, is("6085551023"))))
.andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE));
}
@Test
@Tag("processUpdateOwnerForm")
void testProcessUpdateOwnerFormSuccess() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_ID_EDIT, TEST_OWNER_ID)
.param(CommonAttribute.OWNER_FIRST_NAME, "Joe").param(CommonAttribute.OWNER_LAST_NAME, "Bloggs")
.param(CommonAttribute.OWNER_ADDRESS, "123 Caramel Street").param(CommonAttribute.OWNER_CITY, "London")
.param(CommonAttribute.OWNER_PHONE, "01616291589")).andExpect(status().is3xxRedirection())
.andExpect(view().name(CommonView.OWNER_OWNERS_ID_R));
}
@Test
@Tag("processUpdateOwnerForm")
void testProcessUpdateOwnerFormHasErrors() throws Exception {
mockMvc.perform(
post(CommonEndPoint.OWNERS_ID_EDIT, TEST_OWNER_ID).param(CommonAttribute.OWNER_FIRST_NAME, "Joe")
.param(CommonAttribute.OWNER_LAST_NAME, "Bloggs").param(CommonAttribute.OWNER_CITY, "London"))
.andExpect(status().isOk()).andExpect(model().attributeHasErrors(CommonAttribute.OWNER))
.andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_ADDRESS))
.andExpect(model().attributeHasFieldErrors(CommonAttribute.OWNER, CommonAttribute.OWNER_PHONE))
.andExpect(view().name(CommonView.OWNER_CREATE_OR_UPDATE));
}
@Test
@Tag("processUpdateOwnerForm")
void testShowOwner() throws Exception {
mockMvc.perform(get(CommonEndPoint.OWNERS_ID, TEST_OWNER_ID)).andExpect(status().isOk())
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_LAST_NAME, is("Franklin"))))
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_FIRST_NAME, is("George"))))
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_ADDRESS, is("110 W. Liberty St."))))
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_CITY, is("Madison"))))
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_PHONE, is("6085551023"))))
.andExpect(
model().attribute(CommonAttribute.OWNER, hasProperty(CommonAttribute.OWNER_PETS, not(empty()))))
.andExpect(model().attribute(CommonAttribute.OWNER,
hasProperty(CommonAttribute.OWNER_PETS, new BaseMatcher<List<PetDTO>>() {
@Override
public boolean matches(Object item) {
@SuppressWarnings("unchecked")
List<PetDTO> pets = (List<PetDTO>) item;
PetDTO pet = pets.get(0);
if (pet.getVisits().isEmpty()) {
return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText("Max did not have any visits");
}
})))
.andExpect(view().name(CommonView.OWNER_DETAILS));
}
}

View file

@ -0,0 +1,142 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.controller;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonError;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.OwnerDTO;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.dto.PetTypeDTO;
import org.springframework.samples.petclinic.formatter.PetTypeFormatter;
import org.springframework.samples.petclinic.service.OwnerService;
import org.springframework.samples.petclinic.service.PetService;
import org.springframework.samples.petclinic.service.PetTypeService;
import org.springframework.test.web.servlet.MockMvc;
/**
* Test class for the {@link PetController}
*
* @author Colin But
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@WebMvcTest(value = PetController.class,
includeFilters = @ComponentScan.Filter(value = PetTypeFormatter.class, type = FilterType.ASSIGNABLE_TYPE))
class PetControllerTests {
private static final int TEST_OWNER_ID = 1;
private static final int TEST_PET_ID = 1;
@Autowired
private MockMvc mockMvc;
@MockBean
private PetService petService;
@MockBean
private PetTypeService petTypeService;
@MockBean
private OwnerService ownerService;
@BeforeEach
void setup() {
PetTypeDTO cat = new PetTypeDTO();
cat.setId(3);
cat.setName("hamster");
given(this.ownerService.findById(TEST_OWNER_ID)).willReturn(new OwnerDTO());
given(this.petService.findById(TEST_PET_ID)).willReturn(new PetDTO());
given(this.petService.findPetTypes()).willReturn(Lists.newArrayList(cat));
}
@Test
@Tag("initCreationForm")
void testInitCreationForm() throws Exception {
mockMvc.perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID))
.andExpect(status().isOk()).andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE))
.andExpect(model().attributeExists(CommonAttribute.PET));
}
@Test
@Tag("processCreationForm")
void testProcessCreationFormSuccess() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID)
.param(CommonAttribute.PET_NAME, "Betty").param(CommonAttribute.PET_TYPE, "hamster")
.param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")).andExpect(status().is3xxRedirection())
.andExpect(view().name(CommonView.OWNER_OWNERS_ID_R));
}
@Test
@Tag("processCreationForm")
void testProcessCreationFormHasErrors() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID)
.param(CommonAttribute.PET_NAME, "Betty").param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12"))
.andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER))
.andExpect(model().attributeHasErrors(CommonAttribute.PET))
.andExpect(model().attributeHasFieldErrors(CommonAttribute.PET, CommonAttribute.PET_TYPE))
.andExpect(model().attributeHasFieldErrorCode(CommonAttribute.PET, CommonAttribute.PET_TYPE,
CommonError.REQUIRED_ARGS))
.andExpect(status().isOk()).andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
}
@Test
@Tag("initUpdateForm")
void testInitUpdateForm() throws Exception {
mockMvc.perform(get(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, TEST_OWNER_ID, TEST_PET_ID))
.andExpect(status().isOk()).andExpect(model().attributeExists(CommonAttribute.PET))
.andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
}
@Test
@Tag("processUpdateForm")
void testProcessUpdateFormSuccess() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, TEST_OWNER_ID, TEST_PET_ID)
.param(CommonAttribute.PET_NAME, "Betty").param(CommonAttribute.PET_TYPE, "hamster")
.param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")).andExpect(status().is3xxRedirection())
.andExpect(view().name(CommonView.OWNER_OWNERS_ID_R));
}
@Test
@Tag("processUpdateForm")
void testProcessUpdateFormHasErrors() throws Exception {
mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_ID_EDIT, TEST_OWNER_ID, TEST_PET_ID)
.param(CommonAttribute.PET_NAME, "Betty").param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12"))
.andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER))
.andExpect(model().attributeHasErrors(CommonAttribute.PET)).andExpect(status().isOk())
.andExpect(view().name(CommonView.PET_CREATE_OR_UPDATE));
}
}

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.vet; package org.springframework.samples.petclinic.controller;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@ -26,16 +26,26 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import org.assertj.core.util.Lists; import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.SpecialtyDTO;
import org.springframework.samples.petclinic.dto.VetDTO;
import org.springframework.samples.petclinic.service.VetService;
import org.springframework.samples.petclinic.model.Specialty;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.ResultActions;
/** /**
* Test class for the {@link VetController} * Test class for the {@link VetController}
*
* @author Paul-Emmanuel DOS SANTOS FACAO
*/ */
@WebMvcTest(VetController.class) @WebMvcTest(VetController.class)
class VetControllerTests { class VetControllerTests {
@ -44,35 +54,39 @@ class VetControllerTests {
private MockMvc mockMvc; private MockMvc mockMvc;
@MockBean @MockBean
private VetRepository vets; private VetService vetService;
@BeforeEach @BeforeEach
void setup() { void setup() {
Vet james = new Vet(); VetDTO james = new VetDTO();
james.setFirstName("James"); james.setFirstName("James");
james.setLastName("Carter"); james.setLastName("Carter");
james.setId(1); james.setId(1);
Vet helen = new Vet(); VetDTO helen = new VetDTO();
helen.setFirstName("Helen"); helen.setFirstName("Helen");
helen.setLastName("Leary"); helen.setLastName("Leary");
helen.setId(2); helen.setId(2);
Specialty radiology = new Specialty(); SpecialtyDTO radiology = new SpecialtyDTO();
radiology.setId(1); radiology.setId(1);
radiology.setName("radiology"); radiology.setName("radiology");
helen.addSpecialty(radiology); helen.addSpecialty(radiology);
given(this.vets.findAll()).willReturn(Lists.newArrayList(james, helen)); given(this.vetService.findAll()).willReturn(Lists.newArrayList(james, helen));
} }
@Test @Test
@Tag("showVetList")
void testShowVetListHtml() throws Exception { void testShowVetListHtml() throws Exception {
mockMvc.perform(get("/vets.html")).andExpect(status().isOk()).andExpect(model().attributeExists("vets")) mockMvc.perform(get(CommonEndPoint.VETS_HTML)).andExpect(status().isOk())
.andExpect(view().name("vets/vetList")); .andExpect(model().attributeExists(CommonAttribute.VETS))
.andExpect(view().name(CommonView.VET_VETS_LIST));
} }
@Test @Test
@Tag("showResourcesVetList")
void testShowResourcesVetList() throws Exception { void testShowResourcesVetList() throws Exception {
ResultActions actions = mockMvc.perform(get("/vets").accept(MediaType.APPLICATION_JSON)) ResultActions actions = mockMvc.perform(get(CommonEndPoint.VETS).accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()); .andExpect(status().isOk());
actions.andExpect(content().contentType(MediaType.APPLICATION_JSON)) actions.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.vetList[0].id").value(1)); .andExpect(jsonPath("$.vetList[0].id").value(1));
} }

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.controller;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@ -24,11 +24,17 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.service.PetService;
import org.springframework.samples.petclinic.service.VisitService;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
/** /**
@ -45,34 +51,37 @@ class VisitControllerTests {
private MockMvc mockMvc; private MockMvc mockMvc;
@MockBean @MockBean
private VisitRepository visits; private VisitService visitService;
@MockBean @MockBean
private PetRepository pets; private PetService petService;
@BeforeEach @BeforeEach
void init() { void init() {
given(this.pets.findById(TEST_PET_ID)).willReturn(new Pet()); given(this.petService.findById(TEST_PET_ID)).willReturn(new PetDTO());
} }
@Test @Test
@Tag("initNewVisitForm")
void testInitNewVisitForm() throws Exception { void testInitNewVisitForm() throws Exception {
mockMvc.perform(get("/owners/*/pets/{petId}/visits/new", TEST_PET_ID)).andExpect(status().isOk()) mockMvc.perform(get(CommonEndPoint.VISITS_NEW, TEST_PET_ID)).andExpect(status().isOk())
.andExpect(view().name("pets/createOrUpdateVisitForm")); .andExpect(view().name(CommonView.VISIT_CREATE_OR_UPDATE));
} }
@Test @Test
@Tag("processNewVisitForm")
void testProcessNewVisitFormSuccess() throws Exception { void testProcessNewVisitFormSuccess() throws Exception {
mockMvc.perform(post("/owners/*/pets/{petId}/visits/new", TEST_PET_ID).param("name", "George") mockMvc.perform(post(CommonEndPoint.VISITS_NEW, TEST_PET_ID).param(CommonAttribute.NAME, "George")
.param("description", "Visit Description")).andExpect(status().is3xxRedirection()) .param(CommonAttribute.DESCRIPTION, "Visit Description")).andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/owners/{ownerId}")); .andExpect(view().name(CommonView.OWNER_OWNERS_ID_R));
} }
@Test @Test
@Tag("processNewVisitForm")
void testProcessNewVisitFormHasErrors() throws Exception { void testProcessNewVisitFormHasErrors() throws Exception {
mockMvc.perform(post("/owners/*/pets/{petId}/visits/new", TEST_PET_ID).param("name", "George")) mockMvc.perform(post(CommonEndPoint.VISITS_NEW, TEST_PET_ID).param(CommonAttribute.NAME, "George"))
.andExpect(model().attributeHasErrors("visit")).andExpect(status().isOk()) .andExpect(model().attributeHasErrors(CommonAttribute.VISIT)).andExpect(status().isOk())
.andExpect(view().name("pets/createOrUpdateVisitForm")); .andExpect(view().name(CommonView.VISIT_CREATE_OR_UPDATE));
} }
} }

View file

@ -0,0 +1,98 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.formater;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.samples.petclinic.dto.PetTypeDTO;
import org.springframework.samples.petclinic.formatter.PetTypeFormatter;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.service.PetService;
import org.springframework.samples.petclinic.service.PetTypeService;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
/**
* Test class for {@link PetTypeFormatter}
*
* @author Colin But
*/
@ExtendWith(MockitoExtension.class)
class PetTypeDTOFormatterTests {
@Mock
private PetService petService;
private PetTypeFormatter petTypeFormatter;
@BeforeEach
void setup() {
this.petTypeFormatter = new PetTypeFormatter(petService);
}
@Test
void testPrint() {
PetTypeDTO petType = new PetTypeDTO();
petType.setName("Hamster");
String petTypeName = this.petTypeFormatter.print(petType, Locale.ENGLISH);
assertThat(petTypeName).isEqualTo("Hamster");
}
@Test
void shouldParse() throws ParseException {
given(this.petService.findPetTypes()).willReturn(makePetTypes());
PetTypeDTO petType = petTypeFormatter.parse("Bird", Locale.ENGLISH);
assertThat(petType.getName()).isEqualTo("Bird");
}
@Test
void shouldThrowParseException() {
given(this.petService.findPetTypes()).willReturn(makePetTypes());
Assertions.assertThrows(ParseException.class, () -> petTypeFormatter.parse("Fish", Locale.ENGLISH));
}
/**
* Helper method to produce some sample pet types just for test purpose
* @return {@link Collection} of {@link PetType}
*/
private List<PetTypeDTO> makePetTypes() {
List<PetTypeDTO> petTypes = new ArrayList<>();
petTypes.add(new PetTypeDTO() {
{
setName("Dog");
}
});
petTypes.add(new PetTypeDTO() {
{
setName("Bird");
}
});
return petTypes;
}
}

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.owner; package org.springframework.samples.petclinic.formater;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
@ -28,6 +28,11 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.samples.petclinic.dto.PetTypeDTO;
import org.springframework.samples.petclinic.formatter.PetTypeFormatter;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.service.PetService;
import org.springframework.samples.petclinic.service.PetTypeService;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
@ -41,18 +46,18 @@ import static org.mockito.BDDMockito.given;
class PetTypeFormatterTests { class PetTypeFormatterTests {
@Mock @Mock
private PetRepository pets; private PetService petService;
private PetTypeFormatter petTypeFormatter; private PetTypeFormatter petTypeFormatter;
@BeforeEach @BeforeEach
void setup() { void setup() {
this.petTypeFormatter = new PetTypeFormatter(pets); this.petTypeFormatter = new PetTypeFormatter(petService);
} }
@Test @Test
void testPrint() { void testPrint() {
PetType petType = new PetType(); PetTypeDTO petType = new PetTypeDTO();
petType.setName("Hamster"); petType.setName("Hamster");
String petTypeName = this.petTypeFormatter.print(petType, Locale.ENGLISH); String petTypeName = this.petTypeFormatter.print(petType, Locale.ENGLISH);
assertThat(petTypeName).isEqualTo("Hamster"); assertThat(petTypeName).isEqualTo("Hamster");
@ -60,31 +65,29 @@ class PetTypeFormatterTests {
@Test @Test
void shouldParse() throws ParseException { void shouldParse() throws ParseException {
given(this.pets.findPetTypes()).willReturn(makePetTypes()); given(this.petService.findPetTypes()).willReturn(makePetTypes());
PetType petType = petTypeFormatter.parse("Bird", Locale.ENGLISH); PetTypeDTO petType = petTypeFormatter.parse("Bird", Locale.ENGLISH);
assertThat(petType.getName()).isEqualTo("Bird"); assertThat(petType.getName()).isEqualTo("Bird");
} }
@Test @Test
void shouldThrowParseException() throws ParseException { void shouldThrowParseException() {
given(this.pets.findPetTypes()).willReturn(makePetTypes()); given(this.petService.findPetTypes()).willReturn(makePetTypes());
Assertions.assertThrows(ParseException.class, () -> { Assertions.assertThrows(ParseException.class, () -> petTypeFormatter.parse("Fish", Locale.ENGLISH));
petTypeFormatter.parse("Fish", Locale.ENGLISH);
});
} }
/** /**
* Helper method to produce some sample pet types just for test purpose * Helper method to produce some sample pet types just for test purpose
* @return {@link Collection} of {@link PetType} * @return {@link Collection} of {@link PetType}
*/ */
private List<PetType> makePetTypes() { private List<PetTypeDTO> makePetTypes() {
List<PetType> petTypes = new ArrayList<>(); List<PetTypeDTO> petTypes = new ArrayList<>();
petTypes.add(new PetType() { petTypes.add(new PetTypeDTO() {
{ {
setName("Dog"); setName("Dog");
} }
}); });
petTypes.add(new PetType() { petTypes.add(new PetTypeDTO() {
{ {
setName("Bird"); setName("Bird");
} }

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.vet; package org.springframework.samples.petclinic.model;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.util.SerializationUtils; import org.springframework.util.SerializationUtils;

View file

@ -1,199 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.owner;
import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import org.assertj.core.util.Lists;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.samples.petclinic.visit.Visit;
import org.springframework.samples.petclinic.visit.VisitRepository;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
/**
* Test class for {@link OwnerController}
*
* @author Colin But
*/
@WebMvcTest(OwnerController.class)
class OwnerControllerTests {
private static final int TEST_OWNER_ID = 1;
@Autowired
private MockMvc mockMvc;
@MockBean
private OwnerRepository owners;
@MockBean
private VisitRepository visits;
private Owner george;
@BeforeEach
void setup() {
george = new Owner();
george.setId(TEST_OWNER_ID);
george.setFirstName("George");
george.setLastName("Franklin");
george.setAddress("110 W. Liberty St.");
george.setCity("Madison");
george.setTelephone("6085551023");
Pet max = new Pet();
PetType dog = new PetType();
dog.setName("dog");
max.setId(1);
max.setType(dog);
max.setName("Max");
max.setBirthDate(LocalDate.now());
george.setPetsInternal(Collections.singleton(max));
given(this.owners.findById(TEST_OWNER_ID)).willReturn(george);
Visit visit = new Visit();
visit.setDate(LocalDate.now());
given(this.visits.findByPetId(max.getId())).willReturn(Collections.singletonList(visit));
}
@Test
void testInitCreationForm() throws Exception {
mockMvc.perform(get("/owners/new")).andExpect(status().isOk()).andExpect(model().attributeExists("owner"))
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
}
@Test
void testProcessCreationFormSuccess() throws Exception {
mockMvc.perform(post("/owners/new").param("firstName", "Joe").param("lastName", "Bloggs")
.param("address", "123 Caramel Street").param("city", "London").param("telephone", "01316761638"))
.andExpect(status().is3xxRedirection());
}
@Test
void testProcessCreationFormHasErrors() throws Exception {
mockMvc.perform(
post("/owners/new").param("firstName", "Joe").param("lastName", "Bloggs").param("city", "London"))
.andExpect(status().isOk()).andExpect(model().attributeHasErrors("owner"))
.andExpect(model().attributeHasFieldErrors("owner", "address"))
.andExpect(model().attributeHasFieldErrors("owner", "telephone"))
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
}
@Test
void testInitFindForm() throws Exception {
mockMvc.perform(get("/owners/find")).andExpect(status().isOk()).andExpect(model().attributeExists("owner"))
.andExpect(view().name("owners/findOwners"));
}
@Test
void testProcessFindFormSuccess() throws Exception {
given(this.owners.findByLastName("")).willReturn(Lists.newArrayList(george, new Owner()));
mockMvc.perform(get("/owners")).andExpect(status().isOk()).andExpect(view().name("owners/ownersList"));
}
@Test
void testProcessFindFormByLastName() throws Exception {
given(this.owners.findByLastName(george.getLastName())).willReturn(Lists.newArrayList(george));
mockMvc.perform(get("/owners").param("lastName", "Franklin")).andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/owners/" + TEST_OWNER_ID));
}
@Test
void testProcessFindFormNoOwnersFound() throws Exception {
mockMvc.perform(get("/owners").param("lastName", "Unknown Surname")).andExpect(status().isOk())
.andExpect(model().attributeHasFieldErrors("owner", "lastName"))
.andExpect(model().attributeHasFieldErrorCode("owner", "lastName", "notFound"))
.andExpect(view().name("owners/findOwners"));
}
@Test
void testInitUpdateOwnerForm() throws Exception {
mockMvc.perform(get("/owners/{ownerId}/edit", TEST_OWNER_ID)).andExpect(status().isOk())
.andExpect(model().attributeExists("owner"))
.andExpect(model().attribute("owner", hasProperty("lastName", is("Franklin"))))
.andExpect(model().attribute("owner", hasProperty("firstName", is("George"))))
.andExpect(model().attribute("owner", hasProperty("address", is("110 W. Liberty St."))))
.andExpect(model().attribute("owner", hasProperty("city", is("Madison"))))
.andExpect(model().attribute("owner", hasProperty("telephone", is("6085551023"))))
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
}
@Test
void testProcessUpdateOwnerFormSuccess() throws Exception {
mockMvc.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID).param("firstName", "Joe")
.param("lastName", "Bloggs").param("address", "123 Caramel Street").param("city", "London")
.param("telephone", "01616291589")).andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/owners/{ownerId}"));
}
@Test
void testProcessUpdateOwnerFormHasErrors() throws Exception {
mockMvc.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID).param("firstName", "Joe")
.param("lastName", "Bloggs").param("city", "London")).andExpect(status().isOk())
.andExpect(model().attributeHasErrors("owner"))
.andExpect(model().attributeHasFieldErrors("owner", "address"))
.andExpect(model().attributeHasFieldErrors("owner", "telephone"))
.andExpect(view().name("owners/createOrUpdateOwnerForm"));
}
@Test
void testShowOwner() throws Exception {
mockMvc.perform(get("/owners/{ownerId}", TEST_OWNER_ID)).andExpect(status().isOk())
.andExpect(model().attribute("owner", hasProperty("lastName", is("Franklin"))))
.andExpect(model().attribute("owner", hasProperty("firstName", is("George"))))
.andExpect(model().attribute("owner", hasProperty("address", is("110 W. Liberty St."))))
.andExpect(model().attribute("owner", hasProperty("city", is("Madison"))))
.andExpect(model().attribute("owner", hasProperty("telephone", is("6085551023"))))
.andExpect(model().attribute("owner", hasProperty("pets", not(empty()))))
.andExpect(model().attribute("owner", hasProperty("pets", new BaseMatcher<List<Pet>>() {
@Override
public boolean matches(Object item) {
@SuppressWarnings("unchecked")
List<Pet> pets = (List<Pet>) item;
Pet pet = pets.get(0);
if (pet.getVisits().isEmpty()) {
return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText("Max did not have any visits");
}
}))).andExpect(view().name("owners/ownerDetails"));
}
}

View file

@ -1,113 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.owner;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.test.web.servlet.MockMvc;
/**
* Test class for the {@link PetController}
*
* @author Colin But
*/
@WebMvcTest(value = PetController.class,
includeFilters = @ComponentScan.Filter(value = PetTypeFormatter.class, type = FilterType.ASSIGNABLE_TYPE))
class PetControllerTests {
private static final int TEST_OWNER_ID = 1;
private static final int TEST_PET_ID = 1;
@Autowired
private MockMvc mockMvc;
@MockBean
private PetRepository pets;
@MockBean
private OwnerRepository owners;
@BeforeEach
void setup() {
PetType cat = new PetType();
cat.setId(3);
cat.setName("hamster");
given(this.pets.findPetTypes()).willReturn(Lists.newArrayList(cat));
given(this.owners.findById(TEST_OWNER_ID)).willReturn(new Owner());
given(this.pets.findById(TEST_PET_ID)).willReturn(new Pet());
}
@Test
void testInitCreationForm() throws Exception {
mockMvc.perform(get("/owners/{ownerId}/pets/new", TEST_OWNER_ID)).andExpect(status().isOk())
.andExpect(view().name("pets/createOrUpdatePetForm")).andExpect(model().attributeExists("pet"));
}
@Test
void testProcessCreationFormSuccess() throws Exception {
mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID).param("name", "Betty")
.param("type", "hamster").param("birthDate", "2015-02-12")).andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/owners/{ownerId}"));
}
@Test
void testProcessCreationFormHasErrors() throws Exception {
mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID).param("name", "Betty").param("birthDate",
"2015-02-12")).andExpect(model().attributeHasNoErrors("owner"))
.andExpect(model().attributeHasErrors("pet")).andExpect(model().attributeHasFieldErrors("pet", "type"))
.andExpect(model().attributeHasFieldErrorCode("pet", "type", "required")).andExpect(status().isOk())
.andExpect(view().name("pets/createOrUpdatePetForm"));
}
@Test
void testInitUpdateForm() throws Exception {
mockMvc.perform(get("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID))
.andExpect(status().isOk()).andExpect(model().attributeExists("pet"))
.andExpect(view().name("pets/createOrUpdatePetForm"));
}
@Test
void testProcessUpdateFormSuccess() throws Exception {
mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID).param("name", "Betty")
.param("type", "hamster").param("birthDate", "2015-02-12")).andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/owners/{ownerId}"));
}
@Test
void testProcessUpdateFormHasErrors() throws Exception {
mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID).param("name", "Betty")
.param("birthDate", "2015/02/12")).andExpect(model().attributeHasNoErrors("owner"))
.andExpect(model().attributeHasErrors("pet")).andExpect(status().isOk())
.andExpect(view().name("pets/createOrUpdatePetForm"));
}
}

View file

@ -25,15 +25,15 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.samples.petclinic.owner.Owner; import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.owner.OwnerRepository; import org.springframework.samples.petclinic.repository.OwnerRepository;
import org.springframework.samples.petclinic.owner.Pet; import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.owner.PetRepository; import org.springframework.samples.petclinic.repository.PetRepository;
import org.springframework.samples.petclinic.owner.PetType; import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.vet.Vet; import org.springframework.samples.petclinic.model.Vet;
import org.springframework.samples.petclinic.vet.VetRepository; import org.springframework.samples.petclinic.repository.VetRepository;
import org.springframework.samples.petclinic.visit.Visit; import org.springframework.samples.petclinic.model.Visit;
import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -112,10 +112,10 @@ class ClinicServiceTests {
owner.setCity("Wollongong"); owner.setCity("Wollongong");
owner.setTelephone("4444444444"); owner.setTelephone("4444444444");
this.owners.save(owner); this.owners.save(owner);
assertThat(owner.getId().longValue()).isNotEqualTo(0); assertThat(owner.getId().longValue()).isNotZero();
owners = this.owners.findByLastName("Schultz"); owners = this.owners.findByLastName("Schultz");
assertThat(owners.size()).isEqualTo(found + 1); assertThat(owners).hasSize(found + 1);
} }
@Test @Test
@ -176,7 +176,7 @@ class ClinicServiceTests {
@Test @Test
@Transactional @Transactional
void shouldUpdatePetName() throws Exception { void shouldUpdatePetName() {
Pet pet7 = this.pets.findById(7); Pet pet7 = this.pets.findById(7);
String oldName = pet7.getName(); String oldName = pet7.getName();
@ -216,7 +216,7 @@ class ClinicServiceTests {
} }
@Test @Test
void shouldFindVisitsByPetId() throws Exception { void shouldFindVisitsByPetId() {
Collection<Visit> visits = this.visits.findByPetId(7); Collection<Visit> visits = this.visits.findByPetId(7);
assertThat(visits).hasSize(2); assertThat(visits).hasSize(2);
Visit[] visitArr = visits.toArray(new Visit[visits.size()]); Visit[] visitArr = visits.toArray(new Visit[visits.size()]);

View file

@ -0,0 +1,231 @@
package org.springframework.samples.petclinic.service;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.samples.petclinic.dto.OwnerDTO;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.dto.PetTypeDTO;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.repository.OwnerRepository;
import org.springframework.samples.petclinic.repository.PetRepository;
import org.springframework.samples.petclinic.repository.PetTypeRepository;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
@Slf4j
@DataJpaTest(includeFilters = @ComponentScan.Filter(Service.class))
class OwnerServiceTest {
private final static Integer OWNER_ID = 11;
private final static String OWNER_FIRST_NAME = "Sam";
private final static String OWNER_LAST_NAME = "Schultz";
private final static String OWNER_ADDRESS = "4, Evans Street";
private final static String OWNER_CITY = "Wollongong";
private final static String OWNER_PHONE = "1234567890";
private final static Integer PET_ID = 11;
private final static String PET_NAME = "bowser";
private final static String PET_BIRTH_DATE = "2020-07-11";
@Autowired
private OwnerRepository ownerRepository;
@Autowired
private PetRepository petRepository;
@Autowired
private PetTypeRepository petTypeRepository;
@Autowired
private VisitRepository visitRepository;
private PetService petService;
private OwnerService ownerService;
private static Owner owner;
private static OwnerDTO ownerDTO;
private static Pet pet;
private static PetDTO petDTO;
@BeforeEach
void beforeEach() {
petService = new PetService(petRepository, petTypeRepository, visitRepository);
ownerService = new OwnerService(ownerRepository, petRepository, petTypeRepository, visitRepository);
PetTypeService petTypeService = new PetTypeService(petTypeRepository);
Collection<PetTypeDTO> petTypeDTOS = petService.findPetTypes();
PetTypeDTO petTypeDTO = petTypeDTOS.stream().findFirst().get();
PetType petType = petTypeService.dtoToEntity(petTypeDTO);
pet = new Pet();
pet.setId(PET_ID);
pet.setName(PET_NAME);
pet.setType(petType);
pet.setBirthDate(LocalDate.parse(PET_BIRTH_DATE));
petDTO = new PetDTO();
petDTO.setId(PET_ID);
petDTO.setName(PET_NAME);
petDTO.setType(petTypeDTO);
petDTO.setBirthDate(LocalDate.parse(PET_BIRTH_DATE));
owner = new Owner();
owner.setId(OWNER_ID);
owner.setFirstName(OWNER_FIRST_NAME);
owner.setLastName(OWNER_LAST_NAME);
owner.setAddress(OWNER_ADDRESS);
owner.setCity(OWNER_CITY);
owner.setTelephone(OWNER_PHONE);
owner.addPet(pet);
ownerDTO = new OwnerDTO();
ownerDTO.setId(OWNER_ID);
ownerDTO.setFirstName(OWNER_FIRST_NAME);
ownerDTO.setLastName(OWNER_LAST_NAME);
ownerDTO.setAddress(OWNER_ADDRESS);
ownerDTO.setCity(OWNER_CITY);
ownerDTO.setTelephone(OWNER_PHONE);
ownerDTO.addPet(petDTO);
}
@Test
@Tag("dtoToEntity")
@DisplayName("Verify the convertion from DTO to Entity")
void dtoToEntity() {
Owner found = ownerService.dtoToEntity(ownerDTO);
assertThat(found.getId()).isEqualTo(owner.getId());
assertThat(found.getFirstName()).isEqualTo(owner.getFirstName());
assertThat(found.getLastName()).isEqualTo(owner.getLastName());
assertThat(found.getAddress()).isEqualTo(owner.getAddress());
assertThat(found.getCity()).isEqualTo(owner.getCity());
assertThat(found.getTelephone()).isEqualTo(owner.getTelephone());
assertThat(found.getPets().size()).isEqualTo(owner.getPets().size());
for (Pet pet : found.getPets()) {
assertThat(owner.getPets()).extracting("id").contains(pet.getId());
}
}
@Test
@Tag("entityToDTO")
@DisplayName("Verify the convertion from Entity to DTO")
void entityToDTO() {
OwnerDTO found = ownerService.entityToDTO(owner);
assertThat(found.getId()).isEqualTo(ownerDTO.getId());
assertThat(found.getFirstName()).isEqualTo(ownerDTO.getFirstName());
assertThat(found.getLastName()).isEqualTo(ownerDTO.getLastName());
assertThat(found.getAddress()).isEqualTo(ownerDTO.getAddress());
assertThat(found.getCity()).isEqualTo(ownerDTO.getCity());
assertThat(found.getTelephone()).isEqualTo(ownerDTO.getTelephone());
assertThat(found.getPets().size()).isEqualTo(ownerDTO.getPets().size());
for (PetDTO petDTO : found.getPets()) {
assertThat(ownerDTO.getPets()).extracting("id").contains(petDTO.getId());
}
}
@Test
@Tag("dtosToEntities")
@DisplayName("Verify the convertion from DTOs list to Entities list")
void dtosToEntities() {
List<OwnerDTO> ownerDTOS = ownerService.findAll();
List<Owner> expected = new ArrayList<>();
ownerDTOS.forEach(dto -> expected.add(ownerService.dtoToEntity(dto)));
List<Owner> found = ownerService.dtosToEntities(ownerDTOS);
assertThat(found).hasSameSizeAs(expected).containsAll(expected);
}
@Test
@Tag("entitiesToDTOS")
@DisplayName("Verify the convertion from Entities list to DTOs list")
void entitiesToDTOS() {
List<OwnerDTO> expected = ownerService.findAll();
List<Owner> owners = new ArrayList<>();
expected.forEach(dto -> owners.add(ownerService.dtoToEntity(dto)));
List<OwnerDTO> found = ownerService.entitiesToDTOS(owners);
assertThat(found).hasSameSizeAs(expected).containsAll(expected);
}
@Test
@Tag("findById")
@DisplayName("Verify that we get OwnerDTO by his ID")
void findById() {
List<OwnerDTO> allDTO = ownerService.findAll();
OwnerDTO expected = allDTO.get(2);
assertThat(ownerService.findById(expected.getId())).isEqualTo(expected);
}
@Test
@Tag("findByLastName")
@DisplayName("Verify that we get OwnerDTO by his LastName")
void findByLastName() {
OwnerDTO expected = ownerService.findById(1);
Optional<OwnerDTO> found = ownerService.findByLastName(expected.getLastName()).stream().findFirst();
found.ifPresent(dto -> assertThat(dto).isEqualToComparingFieldByField(expected));
}
@Test
@Tag("findAll")
@DisplayName("Verify that the OwnerDTO list contain all previous elements and the new saved one")
void findAll() {
List<OwnerDTO> expected = ownerService.findAll();
assertThat(expected).doesNotContain(ownerDTO);
ownerService.save(ownerDTO);
List<OwnerDTO> found = ownerService.findAll();
assertThat(found).hasSize(expected.size() + 1)
.usingElementComparatorOnFields("lastName", "firstName", "address", "city", "telephone")
.contains(ownerDTO).containsAnyElementsOf(expected);
}
@Test
@Tag("save")
@DisplayName("Verify that all OwnerDTO list contain the new saved one")
void save() {
assertThat(ownerService.findAll()).doesNotContain(ownerDTO);
ownerService.save(ownerDTO);
List<OwnerDTO> found = ownerService.findAll();
assertThat(found).usingElementComparatorOnFields("lastName", "firstName", "address", "city", "telephone")
.contains(ownerDTO);
}
}

View file

@ -0,0 +1,176 @@
package org.springframework.samples.petclinic.service;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.samples.petclinic.dto.OwnerDTO;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.dto.PetTypeDTO;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.repository.PetRepository;
import org.springframework.samples.petclinic.repository.PetTypeRepository;
import org.springframework.samples.petclinic.repository.VetRepository;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
@Slf4j
@DataJpaTest(includeFilters = @ComponentScan.Filter(Service.class))
class PetServiceTest {
private final static Integer OWNER_ID = 5;
private final static Integer PET_ID = 14;
private final static String PET_NAME = "bowser";
private final static String PET_BIRTH_DATE = "2020-07-11";
@Autowired
private OwnerService ownerService;
@Autowired
private PetRepository petRepository;
@Autowired
private PetTypeRepository petTypeRepository;
@Autowired
private VisitRepository visitRepository;
private PetService petService;
private static Owner owner;
private static Pet pet;
private static PetDTO petDTO;
@BeforeEach
void beforeEach() {
this.petService = new PetService(petRepository, petTypeRepository, visitRepository);
PetTypeService petTypeService = new PetTypeService(petTypeRepository);
Collection<PetTypeDTO> petTypeDTOS = petService.findPetTypes();
PetTypeDTO petTypeDTO = petTypeDTOS.stream().findFirst().get();
PetType petType = petTypeService.dtoToEntity(petTypeDTO);
pet = new Pet();
pet.setId(PET_ID);
pet.setName(PET_NAME);
pet.setType(petType);
pet.setBirthDate(LocalDate.parse(PET_BIRTH_DATE));
petDTO = new PetDTO();
petDTO.setId(PET_ID);
petDTO.setName(PET_NAME);
petDTO.setType(petTypeDTO);
petDTO.setBirthDate(LocalDate.parse(PET_BIRTH_DATE));
OwnerDTO ownerDTO = ownerService.findById(OWNER_ID);
ownerDTO.addPet(petDTO);
pet.setOwner(ownerService.dtoToEntity(ownerDTO));
petDTO.setOwner(ownerDTO);
}
@Test
@Tag("dtoToEntity")
@DisplayName("Verify the convertion from DTO to Entity")
void dtoToEntity() {
Pet found = petService.dtoToEntity(petDTO);
assertThat(found.getId()).isEqualTo(pet.getId());
assertThat(found.getName()).isEqualTo(pet.getName());
assertThat(found.getBirthDate()).isEqualTo(pet.getBirthDate());
assertThat(found.getType()).isEqualTo(pet.getType());
assertThat(found.getOwner().getId()).isEqualTo(pet.getOwner().getId());
assertThat(found.getVisits()).isEqualTo(pet.getVisits());
}
@Test
@Tag("entityToDTO")
@DisplayName("Verify the convertion from Entity to DTO")
void entityToDTO() {
PetDTO found = petService.entityToDTO(pet);
assertThat(found.getId()).isEqualTo(petDTO.getId());
assertThat(found.getName()).isEqualTo(petDTO.getName());
assertThat(found.getBirthDate()).isEqualTo(petDTO.getBirthDate());
assertThat(found.getType()).isEqualTo(petDTO.getType());
assertThat(found.getOwner().getId()).isEqualTo(petDTO.getOwner().getId());
assertThat(found.getVisits()).isEqualTo(petDTO.getVisits());
}
@Test
@Tag("dtosToEntities")
@DisplayName("Verify the convertion from DTOs list to Entities list")
void dtosToEntities() {
List<Pet> expected = petRepository.findAll();
List<PetDTO> allDTO = petService.findAll();
List<Pet> found = petService.dtosToEntities(allDTO);
assertThat(found).hasSameSizeAs(expected).isEqualTo(expected);
}
@Test
@Tag("entitiesToDTOS")
@DisplayName("Verify the convertion from Entity to DTO")
void entitiesToDTOS() {
List<Pet> allEntity = petRepository.findAll();
List<PetDTO> expected = petService.findAll();
List<PetDTO> found = petService.entitiesToDTOS(allEntity);
assertThat(found).hasSameSizeAs(expected).isEqualTo(expected);
}
@Test
@Tag("findById")
@DisplayName("Verify that we get PetDTO by his ID")
void findById() {
List<PetDTO> allDTO = petService.findAll();
PetDTO expected = allDTO.get(2);
assertThat(petService.findById(expected.getId())).isEqualTo(expected);
}
@Test
@Tag("findAll")
@DisplayName("Verify that the PetDTO list contain all previous elements and the new saved one")
void findAll() {
List<PetDTO> expected = petService.findAll();
assertThat(expected).doesNotContain(petDTO);
petService.save(petDTO);
List<PetDTO> found = petService.findAll();
assertThat(found).hasSize(expected.size() + 1).contains(petDTO).containsAll(expected);
}
@Test
@Tag("save")
@DisplayName("Verify that all PetDTO list contain the new saved one")
void save() {
assertThat(petService.findAll()).doesNotContain(petDTO);
petService.save(petDTO);
assertThat(petService.findAll()).containsAnyOf(petDTO);
}
}

View file

@ -0,0 +1,142 @@
package org.springframework.samples.petclinic.service;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.samples.petclinic.dto.VetDTO;
import org.springframework.samples.petclinic.model.Vet;
import org.springframework.samples.petclinic.repository.SpecialtyRepository;
import org.springframework.samples.petclinic.repository.VetRepository;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@Slf4j
@DataJpaTest(includeFilters = @ComponentScan.Filter(Service.class))
class VetServiceTest {
private final static Integer VET_ID = 11;
private final static String VET_FIRST_NAME = "Sam";
private final static String VET_LAST_NAME = "Schultz";
@Autowired
private VetRepository vetRepository;
@Autowired
private SpecialtyRepository specialtyRepository;
private VetService vetService;
private static Vet vet;
private static VetDTO vetDTO;
@BeforeEach
void beforeEach() {
vetService = new VetService(vetRepository, specialtyRepository);
vet = new Vet();
vet.setId(VET_ID);
vet.setFirstName(VET_FIRST_NAME);
vet.setLastName(VET_LAST_NAME);
vetDTO = new VetDTO();
vetDTO.setId(VET_ID);
vetDTO.setFirstName(VET_FIRST_NAME);
vetDTO.setLastName(VET_LAST_NAME);
}
@Test
@Tag("dtoToEntity")
@DisplayName("Verify the convertion from DTO to Entity")
void dtoToEntity() {
Vet found = vetService.dtoToEntity(vetDTO);
assertThat(found.getId()).isEqualTo(vet.getId());
assertThat(found.getFirstName()).isEqualTo(vet.getFirstName());
assertThat(found.getLastName()).isEqualTo(vet.getLastName());
}
@Test
@Tag("entityToDTO")
@DisplayName("Verify the convertion from Entity to DTO")
void entityToDTO() {
VetDTO found = vetService.entityToDTO(vet);
assertThat(found.getId()).isEqualTo(vetDTO.getId());
assertThat(found.getFirstName()).isEqualTo(vetDTO.getFirstName());
assertThat(found.getLastName()).isEqualTo(vetDTO.getLastName());
}
@Test
@DisplayName("Verify the convertion from DTOs list to Entities list")
@Tag("dtosToEntities")
void dtosToEntities() {
List<VetDTO> vetDTOS = vetService.findAll();
List<Vet> expected = new ArrayList<>();
vetDTOS.forEach(dto -> expected.add(vetService.dtoToEntity(dto)));
Collection<Vet> found = vetService.dtosToEntities(vetDTOS);
assertThat(found).hasSameSizeAs(expected).isEqualTo(expected);
}
@Test
@Tag("entitiesToDTOS")
@DisplayName("Verify the convertion from Entities list to DTOs list")
void entitiesToDTOS() {
List<VetDTO> expected = vetService.findAll();
List<Vet> vets = new ArrayList<>();
expected.forEach(dto -> vets.add(vetService.dtoToEntity(dto)));
List<VetDTO> found = vetService.entitiesToDTOS(vets);
assertThat(found).hasSameSizeAs(expected).isEqualTo(expected);
}
@Test
@Tag("findById")
@DisplayName("Verify that we get VetDTO by his ID")
void findById() {
List<VetDTO> allDTO = vetService.findAll();
VetDTO expected = allDTO.get(2);
assertThat(vetService.findById(expected.getId())).isEqualTo(expected);
}
@Test
@Tag("findAll")
@DisplayName("Verify that the VetDTO list contain all previous elements and the new saved one")
void findAll() {
List<VetDTO> expected = vetService.findAll();
assertThat(expected).doesNotContain(vetDTO);
vetService.save(vetDTO);
List<VetDTO> found = vetService.findAll();
assertThat(found).contains(vetDTO).containsAll(expected);
}
@Test
@Tag("save")
@DisplayName("Verify that all VetDTO list contain the new saved one")
void save() {
assertThat(vetService.findAll()).doesNotContain(vetDTO);
vetService.save(vetDTO);
assertThat(vetService.findAll()).contains(vetDTO);
}
}

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.model; package org.springframework.samples.petclinic.validator;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
@ -24,6 +24,7 @@ import javax.validation.Validator;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.samples.petclinic.model.Person;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;