@RequestMapping(value = "/resource", method = RequestMethod.POST)
  @ResponseStatus(HttpStatus.OK)
  public void addContent(
      @RequestParam String type,
      @RequestParam String name,
      @RequestParam String language,
      @RequestParam(required = false) String value,
      @RequestParam(required = false) MultipartFile contentFile)
      throws CMSLiteException, IOException {
    if (isBlank(type)) {
      throw new CMSLiteException("Resource type is required");
    }

    if (isBlank(name)) {
      throw new CMSLiteException("Resource name is required");
    }

    if (isBlank(language)) {
      throw new CMSLiteException("Resource language is required");
    }

    switch (type) {
      case "string":
        if (isBlank(value)) {
          throw new CMSLiteException("Resource content is required");
        }

        if (cmsLiteService.isStringContentAvailable(language, name)) {
          throw new CMSLiteException(
              String.format("Resource %s in %s language already exists.", name, language));
        }

        cmsLiteService.addContent(new StringContent(language, name, value));
        break;
      case "stream":
        if (null == contentFile) {
          throw new CMSLiteException("Resource content is required");
        }

        if (cmsLiteService.isStreamContentAvailable(language, name)) {
          throw new CMSLiteException(
              String.format("Resource %s in %s language already exists.", name, language));
        }

        String checksum = md5Hex(contentFile.getBytes());
        String contentType = contentFile.getContentType();

        cmsLiteService.addContent(
            new StreamContent(
                language,
                name,
                ArrayUtils.toObject(contentFile.getBytes()),
                checksum,
                contentType));
        break;
      default:
    }
  }
  @RequestMapping(value = "/resource/string/{language}/{name}", method = RequestMethod.POST)
  @ResponseStatus(HttpStatus.OK)
  public void editStringContent(
      @PathVariable String language, @PathVariable String name, @RequestParam String value)
      throws ContentNotFoundException, CMSLiteException, IOException {
    StringContent stringContent = cmsLiteService.getStringContent(language, name);
    stringContent.setValue(value);

    cmsLiteService.addContent(stringContent);
  }
 @RequestMapping(value = "/resource/{type}/{language}/{name}", method = RequestMethod.DELETE)
 @ResponseStatus(HttpStatus.OK)
 public void removeContent(
     @PathVariable String type, @PathVariable String language, @PathVariable String name)
     throws ContentNotFoundException {
   switch (type) {
     case "stream":
       cmsLiteService.removeStreamContent(language, name);
       break;
     case "string":
       cmsLiteService.removeStringContent(language, name);
       break;
     default:
   }
 }
  @RequestMapping(value = "/resource/stream/{language}/{name}", method = RequestMethod.POST)
  @ResponseStatus(HttpStatus.OK)
  public void editStreamContent(
      @PathVariable String language,
      @PathVariable String name,
      @RequestParam MultipartFile contentFile)
      throws ContentNotFoundException, CMSLiteException, IOException {
    StreamContent streamContent = cmsLiteService.getStreamContent(language, name);

    streamContent.setChecksum(md5Hex(contentFile.getBytes()));
    streamContent.setContentType(contentFile.getContentType());
    streamContent.setContent(ArrayUtils.toObject(contentFile.getBytes()));

    cmsLiteService.addContent(streamContent);
  }
  @RequestMapping(value = "/resource/available/{field}", method = RequestMethod.GET)
  @ResponseBody
  public Set<String> availableField(@PathVariable String field, @RequestParam String term) {
    Set<String> strings = new TreeSet<>();

    switch (field) {
      case "name":
        List<Content> contents = cmsLiteService.getAllContents();
        for (Content content : contents) {
          if (startsWith(content.getName(), term)) {
            strings.add(content.getName());
          }
        }
        break;
      case "language":
        for (Locale locale : getAvailableLocales()) {
          if (startsWithIgnoreCase(locale.getDisplayLanguage(), term)) {
            strings.add(locale.getDisplayLanguage());
          }
        }
        break;
      default:
    }

    return strings;
  }
  @RequestMapping(value = "/string/{language}/{name}", method = RequestMethod.GET)
  public void getStringContent(
      @PathVariable String language, @PathVariable String name, HttpServletResponse response)
      throws IOException {
    LOG.info(String.format("Getting resource for : string:%s:%s", language, name));

    PrintWriter writer = null;

    try {
      writer = response.getWriter();

      StringContent stringContent = cmsLiteService.getStringContent(language, name);

      response.setContentLength(stringContent.getValue().length());
      response.setContentType("text/plain");
      response.setStatus(HttpServletResponse.SC_OK);

      writer.print(stringContent.getValue());
    } catch (Exception e) {
      LOG.error(
          String.format(
              "Content not found for : string:%s:%s%n:%s",
              language, name, Arrays.toString(e.getStackTrace())));
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, NOT_FOUND_RESPONSE);
    } finally {
      IOUtils.closeQuietly(writer);
    }
  }
  @RequestMapping(value = "/resource", method = RequestMethod.GET)
  @ResponseBody
  public Resources getContents(GridSettings settings) {
    List<Content> contents = cmsLiteService.getAllContents();
    List<ResourceDto> resourceDtos = ResourceFilter.filter(settings, contents);

    Collections.sort(resourceDtos, new ResourceComparator(settings));

    return new Resources(settings, resourceDtos);
  }
  @RequestMapping(value = "/resource/{type}/{language}/{name}", method = RequestMethod.GET)
  @ResponseBody
  public Content getContent(
      @PathVariable String type, @PathVariable String language, @PathVariable String name)
      throws ContentNotFoundException {
    Content content = null;

    switch (type) {
      case "stream":
        content = cmsLiteService.getStreamContent(language, name);
        break;
      case "string":
        content = cmsLiteService.getStringContent(language, name);
        break;
      default:
    }

    return content;
  }
  @RequestMapping(value = "/resource/all/languages", method = RequestMethod.GET)
  @ResponseBody
  public Set<String> getAllLanguages() throws ContentNotFoundException {
    List<Content> contents = cmsLiteService.getAllContents();
    Set<String> strings = new TreeSet<>();

    for (Content content : contents) {
      strings.add(content.getLanguage());
    }

    return strings;
  }
  @Test
  public void shouldSendSmsWhenTwoAppointmentsAreMissed() throws Exception {
    String motechCaseId = "motechCaseId";
    String phuId = "phuId";
    String phone = "phone";
    String userId = "userId";
    String firstName = "firstName";
    String lastName = "lastName";

    Map<String, String> motherCaseFieldValues = new HashMap<>();
    motherCaseFieldValues.put(Commcare.PHU_ID, phuId);

    MotechEvent event = new MotechEvent();
    event.getParameters().put(EventKeys.MOTHER_CASE_ID, motechCaseId);

    when(commcareCaseService.getCaseByCaseId(motechCaseId)).thenReturn(motherCase);
    when(motherCase.getFieldValues()).thenReturn(motherCaseFieldValues);
    when(motherCase.getUserId()).thenReturn(userId);

    when(fixtureIdMap.getPhoneForFixture(phuId)).thenReturn(phone);

    when(commcareUserService.getCommcareUserById(userId)).thenReturn(commcareUser);
    when(commcareUser.getFirstName()).thenReturn(firstName);
    when(commcareUser.getLastName()).thenReturn(lastName);

    when(settings.getLanguage()).thenReturn(LANGUAGE);
    when(cmsLiteService.getStringContent(LANGUAGE, POST_PARTUM_VISITS_MESSAGE_NAME))
        .thenReturn(new StringContent(LANGUAGE, POST_PARTUM_VISITS_MESSAGE_NAME, "%s"));

    listener.postPartumMissedVisitHandler(event);

    ArgumentCaptor<OutgoingSms> captor = ArgumentCaptor.forClass(OutgoingSms.class);

    verify(smsService).send(captor.capture());

    OutgoingSms value = captor.getValue();

    assertEquals(asList(phone), value.getRecipients());
    assertEquals(firstName + " " + lastName, value.getMessage());
  }
  @RequestMapping(value = "/stream/{language}/{name}", method = RequestMethod.GET)
  public void getStreamContent(
      @PathVariable String language, @PathVariable String name, HttpServletResponse response)
      throws IOException {
    LOG.info(String.format("Getting resource for : stream:%s:%s", language, name));

    try (OutputStream out = response.getOutputStream()) {

      StreamContent streamContent = cmsLiteService.getStreamContent(language, name);

      response.setContentLength(streamContent.getContent().length);
      response.setContentType(streamContent.getContentType());
      response.setHeader("Accept-Ranges", "bytes");
      response.setStatus(HttpServletResponse.SC_OK);

      out.write(ArrayUtils.toPrimitive(streamContent.getContent()));
    } catch (Exception e) {
      LOG.error(
          String.format(
              "Content not found for : stream:%s:%s%n:%s",
              language, name, Arrays.toString(e.getStackTrace())));
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, NOT_FOUND_RESPONSE);
    }
  }