package net.petrikainulainen.spring.datajpa.controller;
import net.petrikainulainen.spring.datajpa.dto.PersonDTO;
import net.petrikainulainen.spring.datajpa.dto.SearchDTO;
import net.petrikainulainen.spring.datajpa.model.Person;
import net.petrikainulainen.spring.datajpa.service.PersonNotFoundException;
import net.petrikainulainen.spring.datajpa.service.PersonService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
/**
* @author Petri Kainulainen
*/
@Controller
@SessionAttributes("person")
public class PersonController extends AbstractController {
private static final Logger LOGGER = LoggerFactory.getLogger(PersonController.class);
protected static final String ERROR_MESSAGE_KEY_DELETED_PERSON_WAS_NOT_FOUND = "error.message.deleted.not.found";
protected static final String ERROR_MESSAGE_KEY_EDITED_PERSON_WAS_NOT_FOUND = "error.message.edited.not.found";
protected static final String FEEDBACK_MESSAGE_KEY_PERSON_CREATED = "feedback.message.person.created";
protected static final String FEEDBACK_MESSAGE_KEY_PERSON_DELETED = "feedback.message.person.deleted";
protected static final String FEEDBACK_MESSAGE_KEY_PERSON_EDITED = "feedback.message.person.edited";
protected static final String MODEL_ATTIRUTE_PERSON = "person";
protected static final String MODEL_ATTRIBUTE_PERSONS = "persons";
protected static final String MODEL_ATTRIBUTE_SEARCH_CRITERIA = "searchCriteria";
protected static final String PERSON_ADD_FORM_VIEW = "person/create";
protected static final String PERSON_EDIT_FORM_VIEW = "person/edit";
protected static final String PERSON_LIST_VIEW = "person/list";
protected static final String PERSON_SEARCH_RESULT_VIEW = "person/searchResults";
protected static final String REQUEST_MAPPING_LIST = "/";
@Resource
private PersonService personService;
@RequestMapping(value="/person/count", method = RequestMethod.POST)
@ResponseBody
public Long count(@RequestBody SearchDTO searchCriteria) {
String searchTerm = searchCriteria.getSearchTerm();
LOGGER.debug("Finding person count for search term: " + searchTerm);
return personService.count(searchTerm);
}
/**
* Processes delete person requests.
* @param id The id of the deleted person.
* @param attributes
* @return
*/
@RequestMapping(value = "/person/delete/{id}", method = RequestMethod.GET)
public String delete(@PathVariable("id") Long id, RedirectAttributes attributes) {
LOGGER.debug("Deleting person with id: " + id);
try {
Person deleted = personService.delete(id);
addFeedbackMessage(attributes, FEEDBACK_MESSAGE_KEY_PERSON_DELETED, deleted.getName());
} catch (PersonNotFoundException e) {
LOGGER.debug("No person found with id: " + id);
addErrorMessage(attributes, ERROR_MESSAGE_KEY_DELETED_PERSON_WAS_NOT_FOUND);
}
return createRedirectViewPath(REQUEST_MAPPING_LIST);
}
/**
* Processes search person requests.
* @param searchCriteria The search criteria.
* @return
*/
@RequestMapping(value = "/person/search/page", method = RequestMethod.POST)
@ResponseBody
public List<PersonDTO> search(@RequestBody SearchDTO searchCriteria) {
LOGGER.debug("Searching persons with search criteria: " + searchCriteria);
String searchTerm = searchCriteria.getSearchTerm();
List<Person> persons = personService.search(searchTerm, searchCriteria.getPageIndex());
LOGGER.debug("Found " + persons.size() + " persons");
return constructDTOs(persons);
}
private List<PersonDTO> constructDTOs(List<Person> persons) {
List<PersonDTO> dtos = new ArrayList<PersonDTO>();
for (Person person: persons) {
PersonDTO dto = new PersonDTO();
dto.setId(person.getId());
dto.setFirstName(person.getFirstName());
dto.setLastName(person.getLastName());
dtos.add(dto);
}
return dtos;
}
/**
* Processes create person requests.
* @param model
* @return The name of the create person form view.
*/
@RequestMapping(value = "/person/create", method = RequestMethod.GET)
public String showCreatePersonForm(Model model) {
LOGGER.debug("Rendering create person form");
model.addAttribute(MODEL_ATTIRUTE_PERSON, new PersonDTO());
return PERSON_ADD_FORM_VIEW;
}
/**
* Processes the submissions of create person form.
* @param created The information of the created persons.
* @param bindingResult
* @param attributes
* @return
*/
@RequestMapping(value = "/person/create", method = RequestMethod.POST)
public String submitCreatePersonForm(@Valid @ModelAttribute(MODEL_ATTIRUTE_PERSON) PersonDTO created, BindingResult bindingResult, RedirectAttributes attributes) {
LOGGER.debug("Create person form was submitted with information: " + created);
if (bindingResult.hasErrors()) {
return PERSON_ADD_FORM_VIEW;
}
Person person = personService.create(created);
addFeedbackMessage(attributes, FEEDBACK_MESSAGE_KEY_PERSON_CREATED, person.getName());
return createRedirectViewPath(REQUEST_MAPPING_LIST);
}
/**
* Processes edit person requests.
* @param id The id of the edited person.
* @param model
* @param attributes
* @return The name of the edit person form view.
*/
@RequestMapping(value = "/person/edit/{id}", method = RequestMethod.GET)
public String showEditPersonForm(@PathVariable("id") Long id, Model model, RedirectAttributes attributes) {
LOGGER.debug("Rendering edit person form for person with id: " + id);
Person person = personService.findById(id);
if (person == null) {
LOGGER.debug("No person found with id: " + id);
addErrorMessage(attributes, ERROR_MESSAGE_KEY_EDITED_PERSON_WAS_NOT_FOUND);
return createRedirectViewPath(REQUEST_MAPPING_LIST);
}
model.addAttribute(MODEL_ATTIRUTE_PERSON, constructFormObject(person));
return PERSON_EDIT_FORM_VIEW;
}
/**
* Processes the submissions of edit person form.
* @param updated The information of the edited person.
* @param bindingResult
* @param attributes
* @return
*/
@RequestMapping(value = "/person/edit", method = RequestMethod.POST)
public String submitEditPersonForm(@Valid @ModelAttribute(MODEL_ATTIRUTE_PERSON) PersonDTO updated, BindingResult bindingResult, RedirectAttributes attributes) {
LOGGER.debug("Edit person form was submitted with information: " + updated);
if (bindingResult.hasErrors()) {
LOGGER.debug("Edit person form contains validation errors. Rendering form view.");
return PERSON_EDIT_FORM_VIEW;
}
try {
Person person = personService.update(updated);
addFeedbackMessage(attributes, FEEDBACK_MESSAGE_KEY_PERSON_EDITED, person.getName());
} catch (PersonNotFoundException e) {
LOGGER.debug("No person was found with id: " + updated.getId());
addErrorMessage(attributes, ERROR_MESSAGE_KEY_EDITED_PERSON_WAS_NOT_FOUND);
}
return createRedirectViewPath(REQUEST_MAPPING_LIST);
}
private PersonDTO constructFormObject(Person person) {
PersonDTO formObject = new PersonDTO();
formObject.setId(person.getId());
formObject.setFirstName(person.getFirstName());
formObject.setLastName(person.getLastName());
return formObject;
}
/**
* Processes requests to home page which lists all available persons.
* @param model
* @return The name of the person list view.
*/
@RequestMapping(value = REQUEST_MAPPING_LIST, method = RequestMethod.GET)
public String showList(Model model) {
LOGGER.debug("Rendering person list page");
List<Person> persons = personService.findAll();
model.addAttribute(MODEL_ATTRIBUTE_PERSONS, persons);
model.addAttribute(MODEL_ATTRIBUTE_SEARCH_CRITERIA, new SearchDTO());
return PERSON_LIST_VIEW;
}
@RequestMapping(value = "/person/search", method=RequestMethod.POST)
public String showSearchResultPage(@ModelAttribute(MODEL_ATTRIBUTE_SEARCH_CRITERIA) SearchDTO searchCriteria, Model model) {
LOGGER.debug("Rendering search result page for search criteria: " + searchCriteria);
model.addAttribute(MODEL_ATTRIBUTE_SEARCH_CRITERIA, searchCriteria);
return PERSON_SEARCH_RESULT_VIEW;
}
/**
* This setter method should only be used by unit tests
* @param personService
*/
protected void setPersonService(PersonService personService) {
this.personService = personService;
}
}