The following example program demonstrates forms API by a)
- retrieving form metadata
...
- saving form data
- retrieving record ID of form data
- retrieving form data
- updating form data
- deleting the form data
...
The program is written using Java and Spring REST framework. Developers OpenSpecimen integration 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 dataSystem.out.println("Successfully saved form record: " + recordId); // // recordId can be used to maintain Map<String,a Object>mapping formDatabetween = getFormData(token, recordId, formMetadata); your data and OpenSpecimen form record // this mapping can //be subsequently used for updating form record //without useresorting theto form data fields for processingstep 4. // // destructionDate and destructionMethod are field names// // Step 4: Retrieve form record ID System.out.println(formData.get("destructionDate")); // System.out.println(formData.get("destructionMethod") recordId = getRecordId(token, "Specimen", specimenId, formMetadata); // // Step 5: DeleteRetrieve form data // Map<String, Object> formData = deleteFormDatagetFormData(token, recordId, formMetadata); // System.out.println(formData.get("destructionDate")); // Stepuse 6:the logoutform data fields for processing // logout(tokenSystem.out.println(formData.get("destructionMethod")); } // private static String login() { // Step 6: Update form //data // username and password could be fetched from client configuration databaseupdateFormData(token, recordId, formData); // // Step 7: Delete Map<String,form Object>data payload = new HashMap<>(); // payload.put("loginName", "admin@admin.com"); payload.put("password", "Login420"); deleteFormData(token, recordId, formMetadata); Map<String, Object> resp = template.postForObject(getUrl("/sessions"), payload, Map.class); // // Step return (String) resp.get("token");8: logout } // private static void logout(String token); { } invokeApi(HttpMethod.DELETE, "/sessions", token, null, Map.class); private static String login() { } // private static Map<String, Object> getFormMetadata(String token, String entityType, Long objectId, String formName) throws Exception { // username and password could be fetched from your client configuration database // String uri = null; Map<String, Object> payload = ifnew (entityType.equals("Specimen")) {HashMap<>(); payload.put("loginName", "admin@admin.com"); uri = "/specimens/" + objectId + "/forms"payload.put("password", "Login420"); } else if (entityType.equals("Visit")) { Map<String, Object> resp = template.postForObject(getUrl("/sessions"), payload, Map.class); return uri = "/visits/" + objectId + "/forms";(String) resp.get("token"); } private static }void else if (entityType.equals("CollectionProtocolRegistration")) { uri = "/collection-protocol-registrations/" + objectId + "/forms"; } else logout(String token) { invokeApi(HttpMethod.DELETE, "/sessions", token, null, Map.class); template.exchange(getUrl("/sessions"), HttpMethod.DELETE, getHttpEntity(token), 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 record ID on saving form data // return ((Number)savedData.get("id")).longValue(); } private static Long updateFormData(String token, Long recordId, Map<String, Object> formData) { throw new IllegalArgumentException("Invalid entity type: " + entityType);formData.put("recordId", recordId); formData.put("destructionMethod", }"Not Specified"); Map[]Number formsformId = invokeApi(HttpMethod.GET, uri, token, null, Map[].classLong)formData.get("containerId"); forString (Mapuri form : forms) { = "/forms/" + formId + "/data/" + recordId; if (Objects.equals(form.get("formCaption"), formName)) { Map savedData = invokeApi(HttpMethod.PUT, uri, token, formData, Map.class); return form((Number)savedData.get("id")).longValue(); } private }static Long getRecordId(String token, String entityType, Long }objectId, return null;Map<String, Object> formMetadata) { } String uri private= static""; Long saveFormData(String token, Long specimenId, Map<String, Object> formMetadataif (entityType.equals("Specimen")) { Map<String, Object> appDatauri = new HashMap<>(); "/specimens/"; } else if appData(entityType.putequals("useUdn", true); // to let API know we use human readable field names instead of cryptic onesVisit")) { uri = "/visits/"; } appData.put("formCtxtId", formMetadata.get("formCtxtIdelse if (entityType.equals("CollectionProtocolRegistration")); { appData.put("objectId", specimenId); uri = "/collection-protocol-registrations/"; Calendar cal = Calendar.getInstance(); } else { cal.set(2020, 12, 31); throw new IllegalArgumentException("Invalid entity longtype: destructionDate" = cal.getTimeInMillis(+ entityType); Map<String,} Object> formData = new HashMap<>(); Long formCtxtId = (Long) formDataformMetadata.putget("appDataformCtxtId", appData); // //uri form field values = String.format(uri + "%d/forms/%d/records", objectId, formCtxtId); // Map<String, Object> entityRecs = formData.put("destructionDate", destructionDate); formData.put("destructionMethod", "Cremation"invokeApi(HttpMethod.GET, uri, token, null, Map.class); Map<String, NumberObject>[] formIdrecords = (Number)formMetadataMap<String, Object>[])entityRecs.get("formIdrecords"); if (records == null || records.length String== uri0) ={ "/forms/" + formId + "/data"; return null; Map savedData = invokeApi(HttpMethod.POST, uri, token, formData, Map.class);} return ((Number)savedDataLong)records[0].get("idrecordId")).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; } } |
...