Skip to content

Instantly share code, notes, and snippets.

@bion
Created January 27, 2021 19:59
Show Gist options
  • Save bion/d114a99887582777f5b5e6968460f8c8 to your computer and use it in GitHub Desktop.
Save bion/d114a99887582777f5b5e6968460f8c8 to your computer and use it in GitHub Desktop.
JsonPath approach
// <input name="applicant.employments[2].employerName" type="text" />
// employer.name
// employer.address.zip
// employer.address.street
class Update {
UpdatePath path;
Value value;
}
class UpdatePath {
// { applicant, pet's names, 1 }
// e.g. "applicant.dependents[1].employers[2].address.zip"
// becomes
// { applicant, dependents, 1, employers, 2, address, zip }
List<String> path;
List<String> getParentPath() {
return path.subList(0, path.size() - 1);
}
String getPropertyName() {
return Iterables.last(path);
}
}
class UpdateResult {
boolean success;
Map<String, String> validationMessages;
UpdateResult(success, validationMessages) {
// etc.
}
boolean isSuccess() {
return success;
}
}
class UpdateStrategyFactory {
UpdateStrategy strategyFor(ApplicationVersion version, String path) {
// get the specific application version out of the questions table
// use that to figure out which type this path corresponds to
// get the update strategy for that type
}
}
// Processing a form submission
// *************************************************************************
DynamicForm requestData = formFactory.form().bindFromRequest(request);
// form submissions include a list of updates
List<Update> updates = requestData
.getFields()
.stream()
.map(field -> new Update(field.getName(), field.getValue()));
// updates are applied
Applicant applicant = Ebean.find(Applicant.class)
.email.equalTo("rob@foo.bar")
.findOne();
DocumentContext applicantData = applicant.getObject();
List<UpdateStrategy> strategies = new ArrayList();
updates.forEach(update -> {
String parentPath = update.getParentJsonPath();
JsonNode node = applicantData.get(parentJsonPath);
if (node == null) {
// gets the JSON object for this path. if the path is
// invalid, it throws
node = answerNodeFactory.getNodeForPath(parentPath);
}
UpdateStrategy strategy = updateStrategyFactory
.strategyFor(applicant.getApplicationVersion(), parentPath);
strategy.setTargetNode(node);
strategy.setUpdate(update);
strategy.updateTarget();
});
// run validations on all "dirty" objects
Result result = ValidatorFactory.runAllFor(strategies);
// if validations pass, new state is persisted
if (result.isSuccess()) {
applicant.save();
return ok(...);
} else {
// or something like this, messages will need to be mapped to form input elements
return badRequest(formState, result.errorMessages);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment