The following example program demonstrates forms API by a)
- retrieving form metadata
...
- saving form data
...
- retrieving saved form data
...
- and
- deleting the form data.
The program is written using Java and Spring REST framework. Developers are free to choose language and tools of their choice.
Code Block |
---|
public class TestFormApis {
//
// this can be a configuration setting. For illustration purpose, API base URL is hardcoded
//
private static final String API_BASE_URL = "http://myopenspecimenserver.com/openspecimen/rest/ng";
private static RestTemplate template = new RestTemplate();
//
// Input specimen ID and this program will add destruction date, method and remove it.
//
public static void main(String[] args)
throws Exception {
if (args.length == 0) {
return;
}
//
// Step 0: Input specimen ID could come from any source.
// In this example, specimen ID is picked from command line arguments
//
Long specimenId = Long.parseLong(args[0]);
//
// Step 1: Login and get an authentication token for use in subsequent API calls
//
String token = login();
//
// Step 2: Retrieve form metadata
//
Map<String, Object> formMetadata = getFormMetadata(token, "Specimen", specimenId, "Specimen Destruction Details");
if (formMetadata == null) {
// No form with name "Specimen Destruction Details" attached at Specimen level
return;
}
//
// Step 3: Save form data
//
Long recordId = saveFormData(token, specimenId, formMetadata);
//
// Step 4: Retrieve form data
//
Map<String, Object> formData = getFormData(token, recordId, formMetadata);
//
// use the form data fields for processing
// destructionDate and destructionMethod are field names
//
System.out.println(formData.get("destructionDate"));
System.out.println(formData.get("destructionMethod"));
//
// Step 5: Delete form data
//
deleteFormData(token, recordId, formMetadata);
//
// Step 6: logout
//
logout(token);
}
private static String login() {
//
// username and password could be fetched from client configuration database
//
Map<String, Object> payload = new HashMap<>();
payload.put("loginName", "admin@admin.com");
payload.put("password", "Login420");
Map<String, Object> resp = template.postForObject(getUrl("/sessions"), payload, Map.class);
return (String) resp.get("token");
}
private static void logout(String token) {
invokeApi(HttpMethod.DELETE, "/sessions", token, null, Map.class);
}
private static Map<String, Object> getFormMetadata(String token, String entityType, Long objectId, String formName)
throws Exception {
String uri = null;
if (entityType.equals("Specimen")) {
uri = "/specimens/" + objectId + "/forms";
} else if (entityType.equals("Visit")) {
uri = "/visits/" + objectId + "/forms";
} else if (entityType.equals("CollectionProtocolRegistration")) {
uri = "/collection-protocol-registrations/" + objectId + "/forms";
} else {
throw new IllegalArgumentException("Invalid entity type: " + entityType);
}
Map[] forms = invokeApi(HttpMethod.GET, uri, token, null, Map[].class);
for (Map form : forms) {
if (Objects.equals(form.get("formCaption"), formName)) {
return form;
}
}
return null;
}
private static Long saveFormData(String token, Long specimenId, Map<String, Object> formMetadata) {
Map<String, Object> appData = new HashMap<>();
appData.put("useUdn", true); // to let API know we use human readable field names instead of cryptic ones
appData.put("formCtxtId", formMetadata.get("formCtxtId"));
appData.put("objectId", specimenId);
Calendar cal = Calendar.getInstance();
cal.set(2020, 12, 31);
long destructionDate = cal.getTimeInMillis();
Map<String, Object> formData = new HashMap<>();
formData.put("appData", appData);
//
// form field values
//
formData.put("destructionDate", destructionDate);
formData.put("destructionMethod", "Cremation");
Number formId = (Number)formMetadata.get("formId");
String uri = "/forms/" + formId + "/data";
Map savedData = invokeApi(HttpMethod.POST, uri, token, formData, Map.class);
return ((Number)savedData.get("id")).longValue();
}
private static Map<String, Object> getFormData(String token, Long recordId, Map<String, Object> formMetadata) {
Number formId = (Number)formMetadata.get("formId");
String uri = "/forms/" + formId + "/data/" + recordId;
return (Map<String, Object>)invokeApi(HttpMethod.GET, uri, token, null, Map.class);
}
private static void deleteFormData(String token, Long recordId, Map<String, Object> formMetadata) {
Number formId = (Number)formMetadata.get("formId");
String uri = "/forms/" + formId + "/data/" + recordId;
invokeApi(HttpMethod.DELETE, uri, token, null, Long.class);
}
private static <T> T invokeApi(HttpMethod httpMethod, String uri, String token, Object body, Class<T> returnType) {
ResponseEntity<T> resp = template.exchange(getUrl(uri), httpMethod, getHttpEntity(token, body), returnType);
if (resp.getStatusCode() == HttpStatus.OK) {
return resp.getBody();
}
//
// Handle API failures
//
throw new RuntimeException("Error invoking API: " + uri);
}
private static HttpEntity<?> getHttpEntity(String token) {
return getHttpEntity(token, null);
}
private static HttpEntity<?> getHttpEntity(String token, Object body) {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.set("X-OS-API-TOKEN", token); // API auth token header
return new HttpEntity<>(body, headers);
}
private static String getUrl(String uri) {
return API_BASE_URL + uri;
}
}
|