-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Group 2: Refactoring and documentation of ImportCSV.java #19
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,10 +13,10 @@ | |
|
||
import java.text.ParseException; | ||
import java.text.SimpleDateFormat; | ||
import java.util.ArrayList; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
@RestController | ||
@CrossOrigin(exposedHeaders = "errors, content-type") | ||
|
@@ -26,114 +26,198 @@ public class ImportCSV { | |
@Autowired | ||
private ClinicService clinicService; | ||
|
||
|
||
/** importPets: Parses a csv message and adds/deletes pets from the clinicService | ||
* @param csv | ||
* @return ResponseEntity<List<Pet>> | ||
*/ | ||
@PreAuthorize("hasRole(@roles.OWNER_ADMIN)") | ||
@RequestMapping(value = "importPets", | ||
method = RequestMethod.POST, | ||
consumes = "text/plain", | ||
produces = "application/json") | ||
public ResponseEntity<List<Pet>> importPets(@RequestBody String csv) { | ||
|
||
int i = 0; | ||
List<Pet> pets = new LinkedList<Pet>(); | ||
Pet pet; | ||
|
||
do { | ||
pet = new Pet(); | ||
|
||
String field = ""; | ||
while (i < csv.length() && csv.charAt(i) != ';') { | ||
field += csv.charAt(i++); | ||
// the method has to renamed - it doesn't just import, it also deletes | ||
List<Pet> petsToAdd = new LinkedList<>(); | ||
List<Pet> petsToDelete = new LinkedList<>(); | ||
for (String line : csv.split("\\r?\\n")) { | ||
String[] fields = line.split(";"); | ||
|
||
if (fields.length < 5) { | ||
return errorResponse("not enough values"); | ||
} | ||
i++; | ||
|
||
pet.setName(field); | ||
Pet pet = new Pet(); | ||
pet.setName(fields[0]); | ||
SettingResponse settingResponse; | ||
|
||
field = ""; | ||
while (i < csv.length() && csv.charAt(i) != ';') { | ||
field += csv.charAt(i++); | ||
} | ||
i++; | ||
|
||
try { | ||
pet.setBirthDate((new SimpleDateFormat("yyyy-MM-dd")).parse(field)); | ||
} catch (ParseException e) { | ||
HttpHeaders headers = new HttpHeaders(); | ||
headers.add("errors", "date " + field + " not valid"); | ||
return new ResponseEntity<List<Pet>>(headers, HttpStatus.BAD_REQUEST); | ||
settingResponse = setDateOfBirth(pet, fields[1]); | ||
if (!settingResponse.isSuccessful) { | ||
return errorResponse(settingResponse.errorMessage); | ||
} | ||
|
||
field = ""; | ||
while (i < csv.length() && csv.charAt(i) != ';') { | ||
field += csv.charAt(i++); | ||
} | ||
i++; | ||
|
||
if (pet != null) { | ||
ArrayList<PetType> ts = (ArrayList<PetType>) clinicService.findPetTypes(); | ||
for (int j = 0; j < ts.size(); j++) { | ||
if (ts.get(j).getName().toLowerCase().equals(field)) { | ||
pet.setType(ts.get(j)); | ||
break; | ||
} | ||
} | ||
settingResponse = setPetType(pet, fields[2]); | ||
if (!settingResponse.isSuccessful) { | ||
return errorResponse(settingResponse.errorMessage); | ||
} | ||
|
||
field = ""; | ||
while (i < csv.length() && (csv.charAt(i) != ';' && csv.charAt(i) != '\n')) { | ||
field += csv.charAt(i++); | ||
settingResponse = setOwner(pet, fields[3]); | ||
if (!settingResponse.isSuccessful) { | ||
return errorResponse(settingResponse.errorMessage); | ||
} | ||
|
||
if (pet != null) { | ||
String owner = field; | ||
List<Owner> matchingOwners = clinicService.findAllOwners() | ||
.stream() | ||
.filter(o -> o.getLastName().equals(owner)) | ||
.collect(Collectors.toList()); | ||
|
||
if (matchingOwners.size() == 0) { | ||
HttpHeaders headers = new HttpHeaders(); | ||
headers.add("errors", "Owner not found"); | ||
return new ResponseEntity<List<Pet>>(headers, HttpStatus.BAD_REQUEST); | ||
} | ||
if (matchingOwners.size() > 1) { | ||
HttpHeaders headers = new HttpHeaders(); | ||
headers.add("errors", "Owner not unique"); | ||
return new ResponseEntity<List<Pet>>(headers, HttpStatus.BAD_REQUEST); | ||
} | ||
pet.setOwner(matchingOwners.iterator().next()); | ||
String action = fields[4]; | ||
if (action.equalsIgnoreCase("add")) { | ||
petsToAdd.add(pet); | ||
} else if (action.equalsIgnoreCase("delete")) { | ||
petsToDelete.add(pet); | ||
} else { | ||
return errorResponse("invalid action"); | ||
} | ||
} | ||
|
||
for (Pet p : petsToAdd) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice to also see such a solution ... you are the first ones so far that moved this functionality to end if all pets can be parsed... |
||
clinicService.savePet(p); | ||
} | ||
|
||
for (Pet p : petsToDelete) { | ||
deletePet(p); | ||
} | ||
|
||
return new ResponseEntity<>( | ||
Stream.concat( | ||
petsToAdd.stream(), | ||
petsToDelete.stream() | ||
).collect(Collectors.toList()), | ||
HttpStatus.OK | ||
); | ||
} | ||
|
||
if (csv.charAt(i) == ';') { | ||
i++; | ||
|
||
field = ""; | ||
while (i < csv.length() && csv.charAt(i) != '\n') { | ||
field += csv.charAt(i++); | ||
} | ||
|
||
if (field.toLowerCase().equals("add")) { | ||
clinicService.savePet(pet); | ||
} else { | ||
for (Pet q : pet.getOwner().getPets()) { | ||
if (q.getName().equals(pet.getName())) { | ||
if (q.getType().getId().equals(pet.getType().getId())) { | ||
if (pet.getBirthDate().equals(q.getBirthDate())) { | ||
clinicService.deletePet(q); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
private static class SettingResponse { | ||
public boolean isSuccessful; | ||
public String errorMessage; | ||
|
||
} else { | ||
clinicService.savePet(pet); | ||
} | ||
i++; | ||
public SettingResponse() { | ||
this.isSuccessful = true; | ||
this.errorMessage = null; | ||
} | ||
|
||
public SettingResponse(String errorMessage) { | ||
this.isSuccessful = false; | ||
this.errorMessage = errorMessage; | ||
} | ||
} | ||
|
||
|
||
/** errorResponse: Creates an Http message with a bad request and a user defined message (headerValue). | ||
* @param headerValue | ||
* @return ResponseEntity<List<Pet>> | ||
*/ | ||
private ResponseEntity<List<Pet>> errorResponse(String headerValue) { | ||
HttpHeaders headers = new HttpHeaders(); | ||
headers.add("errors", headerValue); | ||
return new ResponseEntity<>(headers, HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
|
||
/** setDateOfBirth: Set's birthday to a pet, by parsing a string into a date. | ||
* @param pet | ||
* @param dateOfBirth | ||
* @return SettingResponse | ||
*/ | ||
private SettingResponse setDateOfBirth(Pet pet, String dateOfBirth) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like that you extracted and created this and the below functions, which fulfill one single purpose, are small and you also kept the indentations small :) |
||
try { | ||
pet.setBirthDate((new SimpleDateFormat("yyyy-MM-dd")).parse(dateOfBirth)); | ||
return new SettingResponse(); | ||
} catch (ParseException e) { | ||
return new SettingResponse("date " + dateOfBirth + " not valid"); | ||
} | ||
} | ||
|
||
|
||
/** setPetType: Assigns a pet type to a pet. | ||
* @param pet | ||
* @param petTypeName | ||
* @return SettingResponse | ||
*/ | ||
private SettingResponse setPetType(Pet pet, String petTypeName) { | ||
PetType petType = findPetTypeByName(petTypeName); | ||
if (petType != null) { | ||
pet.setType(petType); | ||
return new SettingResponse(); | ||
} | ||
return new SettingResponse("type " + petTypeName + " not valid"); | ||
} | ||
|
||
|
||
/** setOwner: Sets an owner to a pet, returns errors if not found. | ||
* @param pet | ||
* @param ownerName | ||
* @return SettingResponse | ||
*/ | ||
private SettingResponse setOwner(Pet pet, String ownerName) { | ||
List<Owner> matchingOwners = findOwnersByName(ownerName); | ||
if (matchingOwners.size() == 1) { | ||
pet.setOwner(matchingOwners.iterator().next()); | ||
return new SettingResponse(); | ||
} else if (matchingOwners.size() > 1) { | ||
return new SettingResponse("Owner not unique"); | ||
} else { | ||
return new SettingResponse("Owner not found"); | ||
} | ||
} | ||
|
||
|
||
/** findPetTypeByName: Finds a pet in the clinicService, and returns null if not found. | ||
* @param name | ||
* @return PetType | ||
*/ | ||
private PetType findPetTypeByName(String name) { | ||
return clinicService.findPetTypes().stream().filter( | ||
petType -> name.equals(petType.getName().toLowerCase()) | ||
).findFirst().orElse(null); | ||
} | ||
|
||
pets.add(pet); | ||
|
||
/** findOwnersByName: Finds a list of owners by it's name. | ||
* @param name | ||
* @return List<Owner> | ||
*/ | ||
private List<Owner> findOwnersByName(String name) { | ||
return clinicService.findAllOwners() | ||
.stream() | ||
.filter(o -> o.getLastName().equals(name)) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
} while (i < csv.length() && pet != null); | ||
|
||
/** deletePet: Deletes a pet from the clinicService. | ||
* @param pet | ||
*/ | ||
private void deletePet(Pet pet) { | ||
for (Pet existingPet : pet.getOwner().getPets()) { | ||
if (equalPets(pet, existingPet)) { | ||
clinicService.deletePet(existingPet); | ||
} | ||
} | ||
} | ||
|
||
return new ResponseEntity<List<Pet>>(pets, HttpStatus.OK); | ||
|
||
/** equalPets: Compares if two pets are the same, by comparing name, type and birthdate. | ||
* @param pet1 | ||
* @param pet2 | ||
* @return boolean | ||
*/ | ||
private boolean equalPets(Pet pet1, Pet pet2) { | ||
if (!pet1.getName().equals(pet2.getName())) { | ||
return false; | ||
} | ||
if (!pet1.getType().getId().equals(pet2.getType().getId())) { | ||
return false; | ||
} | ||
if (!pet1.getBirthDate().equals(pet2.getBirthDate())) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could think about extracting the most contents of
importPets
to a new method, soimportPets
is only responsible about handling the request and the new method takes care of orchestrating the parsing and so on (probably you would have done this with more time :) )