Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • retrieving form metadata
  • saving form data
  • retrieving saved record ID of form data
  • retrieving form data
  • updating form data and 
  • 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);
      System.out.println("Successfully saved form record: " + recordId);
      //
      // recordId can be used to maintain a mapping between your data and OpenSpecimen form record
      // this mapping can be subsequently used for updating form record without resorting to step 4.
      //

      //
      // Step 4: Retrieve form datarecord ID
      //
      Map<String, Object> formData recordId = getFormDatagetRecordId(token, "Specimen", recordIdspecimenId, formMetadata);

            //
      // use theStep 5: Retrieve form data
fields for processing       //
destructionDate and destructionMethod are field names Map<String, Object> formData = getFormData(token,  //recordId, formMetadata);
      System.out.println(formData.get("destructionDate"));  // use the form data fields for processing
      System.out.println(formData.get("destructionMethod"));

      //
      // Step 6: Update form data
      //
      updateFormData(token, recordId, formData);

      //
      // Step 57: Delete form data
      //
      deleteFormData(token, recordId, formMetadata);

      //
      // Step 68: logout
      //
      logout(token);
   }

   private static String login() {
      //
      // username and password could be fetched from your 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);
      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) {
      formData.put("recordId", recordId);
      formData.put("destructionMethod", "Not Specified");

      Number formId = (Long)formData.get("containerId");
      String uri = "/forms/" + formId + "/data/" + recordId;
      Map savedData = invokeApi(HttpMethod.PUT, uri, token, formData, Map.class);
      return ((Number)savedData.get("id")).longValue();
   }

   private static Long getRecordId(String token, String entityType, Long objectId, Map<String, Object> formMetadata) {
      String uri = "";
      if (entityType.equals("Specimen")) {
         uri = "/specimens/";
      } else if (entityType.equals("Visit")) {
         uri = "/visits/";
      } else if (entityType.equals("CollectionProtocolRegistration")) {
         uri = "/collection-protocol-registrations/";
      }

      Long formCtxtId = (Long) formMetadata.get("formCtxtId");
      uri = String.format(uri + "%d/forms/%d/records", objectId, formCtxtId);
      Map<String, Object> entityRecs = invokeApi(HttpMethod.GET, uri, token, null, Map.class);
      Map<String, Object>[] records = (Map<String, Object>[])entityRecs.get("records");

      if (records == null || records.length == 0) {
         return null;
      }

      return (Long)records[0].get("recordId");
   }

   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;
   }
}