//lock on this user and this application to avoid any potential concurrency issues
Lock lock = getApplicationDataLock(personId, appId);
try {
lock.lock();
//get the application data for this user and application
ApplicationData applicationData = applicationDataRepository.getApplicationData(personId, appId);
//if there is no data, create an empty object to store the data in that we'll save when we're done
if (applicationData == null) {
applicationData = new ApplicationDataImpl(null, personId, appId, new HashMap<String, String>());
}
//if the fields parameter is empty, we can just use the values map directly since this is a full update
if (fields == null || fields.size() == 0) {
applicationData.setData(values);
}
//if there are keys in the values map that aren't in the fields set, its a bad request
else if (!fields.containsAll(values.keySet())) {
throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST, "Fields parameter must either be empty or contain keys " +
"for all name value pairs sent in request.");
}
//we have a partial update - we know that the fields set contains keys for all the entries in the values
//map (due to the check above), so we can just enumerate over it now to finish our work. So we want to remove
//any fields found in the fields set that are not found in the values map and update the rest.
else {
Map<String, String> data = applicationData.getData();
for (String field : fields) {
//if this field is not in the values map, its a delete
if (!values.containsKey(field)) {
data.remove(field);
} else {