Skip to content

Commit

Permalink
Synchronization and Error Message for locations. (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
littlefieldnick committed Oct 22, 2018
1 parent f9391f7 commit 01b4b55
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
import org.openhds.domain.model.Location;
import org.openhds.domain.model.wrappers.Locations;
import org.openhds.domain.util.JsonShallowCopier;
import org.openhds.domain.util.ShallowCopier;
import org.openhds.task.support.FileResolver;
import org.openhds.webservice.CacheResponseWriter;
import org.openhds.webservice.FieldBuilder;
import org.openhds.webservice.WebServiceCallException;
import org.openhds.webservice.util.Synchronization;
import org.openhds.webservice.util.SynchronizationError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -34,48 +35,48 @@
@Controller
@RequestMapping("/locations2")
public class LocationResourceApi2 {
private static final Logger logger = LoggerFactory.getLogger(LocationResourceApi2.class);

private final FieldBuilder fieldBuilder;
private final LocationHierarchyService locationHierarchyService;
private final FileResolver fileResolver;

@Autowired
public LocationResourceApi2(LocationHierarchyService locationHierarchyService, FieldBuilder fieldBuilder,
FileResolver fileResolver) {
this.locationHierarchyService = locationHierarchyService;
this.fieldBuilder = fieldBuilder;
this.fileResolver = fileResolver;
}

@RequestMapping(value = "/{extId}", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<? extends Serializable> getLocationByExtId(@PathVariable String extId) {
Location location = locationHierarchyService.findLocationById(extId);
if (location == null) {
return new ResponseEntity<String>("", HttpStatus.NOT_FOUND);
}

return new ResponseEntity<Location>(JsonShallowCopier.copyLocation(location), HttpStatus.OK);
}

@RequestMapping(method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public Locations getAllLocations() {
List<Location> locations = locationHierarchyService.getAllLocations();
List<Location> copies = new ArrayList<Location>(locations.size());

for (Location loc : locations) {
Location copy = JsonShallowCopier.copyLocation(loc);
copies.add(copy);
}

Locations allLocations = new Locations();
allLocations.setLocations(copies);
allLocations.setTimestamp(new Date().getTime());
return allLocations;
}

@RequestMapping(method = RequestMethod.GET, value = "/pull/{timestamp}", produces = "application/json")
private static final Logger logger = LoggerFactory.getLogger(LocationResourceApi2.class);

private final FieldBuilder fieldBuilder;
private final LocationHierarchyService locationHierarchyService;
private final FileResolver fileResolver;

@Autowired
public LocationResourceApi2(LocationHierarchyService locationHierarchyService, FieldBuilder fieldBuilder,
FileResolver fileResolver) {
this.locationHierarchyService = locationHierarchyService;
this.fieldBuilder = fieldBuilder;
this.fileResolver = fileResolver;
}

@RequestMapping(value = "/{extId}", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<? extends Serializable> getLocationByExtId(@PathVariable String extId) {
Location location = locationHierarchyService.findLocationById(extId);
if (location == null) {
return new ResponseEntity<String>("", HttpStatus.NOT_FOUND);
}

return new ResponseEntity<Location>(JsonShallowCopier.copyLocation(location), HttpStatus.OK);
}

@RequestMapping(method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public Locations getAllLocations() {
List<Location> locations = locationHierarchyService.getAllLocations();
List<Location> copies = new ArrayList<Location>(locations.size());

for (Location loc : locations) {
Location copy = JsonShallowCopier.copyLocation(loc);
copies.add(copy);
}

Locations allLocations = new Locations();
allLocations.setLocations(copies);
allLocations.setTimestamp(new Date().getTime());
return allLocations;
}

@RequestMapping(method = RequestMethod.GET, value = "/{timestamp}", produces = "application/json")
public ResponseEntity<Locations> getUpdatedLocations(@PathVariable long timestamp) {
long time = new Date().getTime();

Expand All @@ -88,7 +89,7 @@ public ResponseEntity<Locations> getUpdatedLocations(@PathVariable long timestam
compTime = loc.getServerInsertTime();
else
compTime = loc.getServerUpdateTime();

if(timestamp <= compTime && timestamp < time) {
copies.add(JsonShallowCopier.copyLocation(loc));
}
Expand All @@ -101,40 +102,57 @@ public ResponseEntity<Locations> getUpdatedLocations(@PathVariable long timestam
return new ResponseEntity<Locations>(all, HttpStatus.ACCEPTED);
}

@RequestMapping(value="/pushUpdates", method = RequestMethod.PUT, consumes= {"application/json"}, produces = { "application/json" })
@RequestMapping(value="/bulkUpdate", method = RequestMethod.PUT, consumes= {"application/json"}, produces = { "application/json" })
public ResponseEntity<? extends Serializable> pushUpdate(@RequestBody Locations locations) {
long lastClientUpdate = locations.getTimestamp();
long time = new Date().getTime();

ConstraintViolations cv = new ConstraintViolations();

List<SynchronizationError> errors = new ArrayList<SynchronizationError>();
for(Location location: locations.getLocations()) {
ConstraintViolations cv = new ConstraintViolations();
location.setCollectedBy(fieldBuilder.referenceField(location.getCollectedBy(), cv));
location.setLocationLevel(fieldBuilder.referenceField(location.getLocationLevel(), cv));


SynchronizationError err = new SynchronizationError();
err.setEntityType("location");
err.setEntityId(location.getExtId());
err.setFieldworkerExtId(location.getCollectedBy().getExtId());
List<String> violations = new ArrayList<String>();

try {
location.setCollectedBy(fieldBuilder.referenceField(location.getCollectedBy(), cv));
location.setLocationLevel(fieldBuilder.referenceField(location.getLocationLevel(), cv));
location.setServerUpdateTime(new Date().getTime());
this.update(location, lastClientUpdate, time);
} catch(ConstraintViolations e){
return new ResponseEntity<WebServiceCallException>(new WebServiceCallException(e), HttpStatus.BAD_REQUEST);
violations.addAll(e.getViolations());
}

if(cv.hasViolations()) {
violations.addAll(cv.getViolations());
}

errors.add(err);
}

return new ResponseEntity<>(time, HttpStatus.ACCEPTED);

Synchronization sync = new Synchronization();
sync.setErrors(errors);
sync.setSyncTime(new Date().getTime());
return new ResponseEntity<Synchronization>(sync, HttpStatus.ACCEPTED);
}

public void update(Location loc, long currentTimestamp, long lastClientUpdate) throws ConstraintViolations {

if(locationHierarchyService.findLocationById(loc.getExtId()) == null) {
this.locationHierarchyService.createLocation(loc);
}

else if(loc.isDeleted()) {
if(loc.getUuid() == null)
throw new ConstraintViolations("The location uuid is null.");

this.locationHierarchyService.updateLocation(loc);
}

else if(locationHierarchyService.findLocationById(loc.getExtId()) != null){
//Set UUID to prevent assignment of a new one.
loc.setUuid(locationHierarchyService.findLocationById(loc.getExtId()).getUuid());
Expand All @@ -147,43 +165,96 @@ else if(locationHierarchyService.findLocationById(loc.getExtId()) != null){
this.locationHierarchyService.updateLocation(loc);
}
}

@RequestMapping(value = "/cached", method = RequestMethod.GET, produces = "application/json")
public void getAllCachedLocations(HttpServletResponse response) {
try {
CacheResponseWriter.writeResponse(fileResolver.resolveLocationXmlFile(), response);
} catch (IOException e) {
logger.error("Problem writing location xml file: " + e.getMessage());
}
}

@RequestMapping(method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<? extends Serializable> insert(@RequestBody Location location) {
ConstraintViolations cv = new ConstraintViolations();
location.setCollectedBy(fieldBuilder.referenceField(location.getCollectedBy(), cv));
location.setLocationLevel(fieldBuilder.referenceField(location.getLocationLevel(), cv));

if (cv.hasViolations()) {
return new ResponseEntity<WebServiceCallException>(new WebServiceCallException(cv), HttpStatus.BAD_REQUEST);
}

try {
locationHierarchyService.createLocation(location);
} catch (ConstraintViolations e) {
return new ResponseEntity<WebServiceCallException>(new WebServiceCallException(e), HttpStatus.BAD_REQUEST);
}

return new ResponseEntity<Location>(JsonShallowCopier.copyLocation(location), HttpStatus.CREATED);
}



@RequestMapping(value = "/zipped", method = RequestMethod.GET)
public void getAllZippedLocations(HttpServletResponse response) {
try {
CacheResponseWriter.writeResponse(fileResolver.resolveLocationZipFile(), response);
} catch (IOException e) {
logger.error("Problem writing location zip file: " + e.getMessage());
}
}

@RequestMapping(value = "/bulkInsert", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<? extends Serializable> bulkInsert(@RequestBody Locations locations) {
List<SynchronizationError> errors = new ArrayList<SynchronizationError>();

for(Location loc: locations.getLocations()) {
ConstraintViolations cv = new ConstraintViolations();
loc.setCollectedBy(fieldBuilder.referenceField(loc.getCollectedBy(), cv));
loc.setLocationLevel(fieldBuilder.referenceField(loc.getLocationLevel(), cv));

SynchronizationError err = new SynchronizationError();
err.setEntityType("location");
err.setEntityId(loc.getExtId());
err.setFieldworkerExtId(loc.getCollectedBy().getExtId());
List<String> violations = new ArrayList<String>();

try {
locationHierarchyService.createLocation(loc);
} catch (ConstraintViolations e) {

violations.addAll(e.getViolations());
}

// Check violations for fieldworker and location level
if(cv.hasViolations()) {
violations.addAll(cv.getViolations());
}

err.setViolations(violations);
errors.add(err);
}

Synchronization sync = new Synchronization();
sync.setErrors(errors);
sync.setSyncTime(new Date().getTime());
return new ResponseEntity<Synchronization>(sync, HttpStatus.ACCEPTED);

}


@RequestMapping(value = "/cached", method = RequestMethod.GET, produces = "application/json")
public void getAllCachedLocations(HttpServletResponse response) {
try {
CacheResponseWriter.writeResponse(fileResolver.resolveLocationXmlFile(), response);
} catch (IOException e) {
logger.error("Problem writing location xml file: " + e.getMessage());
}
}

@RequestMapping(method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<? extends Serializable> insert(@RequestBody Location location) {
List<SynchronizationError> errors = new ArrayList<SynchronizationError>();

ConstraintViolations cv = new ConstraintViolations();

SynchronizationError err = new SynchronizationError();
err.setEntityType("location");
err.setEntityId(location.getExtId());
err.setFieldworkerExtId(location.getCollectedBy().getExtId());
List<String> violations = new ArrayList<String>();

location.setCollectedBy(fieldBuilder.referenceField(location.getCollectedBy(), cv));
location.setLocationLevel(fieldBuilder.referenceField(location.getLocationLevel(), cv));

if(cv.hasViolations()) {
violations.addAll(cv.getViolations());
}

try {
locationHierarchyService.createLocation(location);
} catch (ConstraintViolations e) {
violations.addAll(e.getViolations());
}

errors.add(err);

Synchronization sync = new Synchronization();
sync.setErrors(errors);
sync.setSyncTime(new Date().getTime());
return new ResponseEntity<Synchronization>(sync, HttpStatus.CREATED);
}



@RequestMapping(value = "/zipped", method = RequestMethod.GET)
public void getAllZippedLocations(HttpServletResponse response) {
try {
CacheResponseWriter.writeResponse(fileResolver.resolveLocationZipFile(), response);
} catch (IOException e) {
logger.error("Problem writing location zip file: " + e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.openhds.webservice.util;

import java.io.Serializable;
import java.util.List;

public class Synchronization implements Serializable {

private static final long serialVersionUID = -5222233547014252574L;
private long syncTime;
private List<SynchronizationError> errors;

public long getSyncTime() {
return syncTime;
}

public void setSyncTime(long syncTime) {
this.syncTime = syncTime;
}

public List<SynchronizationError> getErrors() {
return errors;
}

public void setErrors(List<SynchronizationError> errors) {
this.errors = errors;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.openhds.webservice.util;

import java.util.List;

import org.openhds.controller.exception.*;

public class SynchronizationError {
private String entityType;
private String fieldworkerExtId;
private String entityId;
private List<String> violations;

public String getEntityType() {
return entityType;
}

public void setEntityType(String entityType) {
this.entityType = entityType;
}

public String getFieldworkerExtId() {
return fieldworkerExtId;
}

public void setFieldworkerExtId(String fieldworkerExtId) {
this.fieldworkerExtId = fieldworkerExtId;
}

public String getEntityId() {
return entityId;
}

public void setEntityId(String entityId) {
this.entityId = entityId;
}

public List<String> getViolations() {
return violations;
}

public void setViolations(List<String> violations) {
this.violations = violations;
}


}

0 comments on commit 01b4b55

Please sign in to comment.