@Test
  public void shouldDeleteEarlierFormIfBothNewerAndOlderMotherFormWithSameInstanceIdHasNullDate() {
    NewForm persistedForm = new NewForm();
    persistedForm.setInstanceId("e34707f8-80c8-4198-bf99-c11c90ba5c98");

    persistedForm.setCaste("OldCaste");
    persistedForm.setServerDateModified(null);
    template.save(persistedForm);

    final String newCaste = "NewCaste";

    Map<String, String> motherFormValues =
        new HashMap<String, String>() {
          {
            put("caseId", "94d5374f-290e-409f-bc57-86c2e4bcc43f");
            put("serverDateModified", null);
            put("userId", "89fda0284e008d2e0c980fb13fa0e5bb");
            put("xmlns", "http://bihar.commcarehq.org/pregnancy/new");
            put("instanceId", "e34707f8-80c8-4198-bf99-c11c90ba5c98");
            put("caste", newCaste);
          }
        };

    careService.processAndSaveForms(motherFormValues, new ArrayList<Map<String, String>>());

    List<NewForm> newFormsFromDb = template.loadAll(NewForm.class);
    assertEquals(1, newFormsFromDb.size());
    assertNull(newFormsFromDb.get(0).getDateModified());
    assertEquals(newCaste, newFormsFromDb.get(0).getCaste());
  }
  @Test
  public void shouldNotDeleteEarlierFormIfNewerMotherFormWithSameInstanceIdHasOldDate() {
    NewForm persistedForm = new NewForm();
    persistedForm.setInstanceId("e34707f8-80c8-4198-bf99-c11c90ba5c98");
    final Date oldFormModifiedDate = DateTime.parse("2012-07-20T12:02:59.923+05:30").toDate();
    persistedForm.setServerDateModified(oldFormModifiedDate);
    persistedForm.setDateModified(oldFormModifiedDate);
    template.save(persistedForm);

    final String newFormModifiedOn = "2012-07-10T12:02:59.923+05:30";

    Map<String, String> motherFormValues =
        new HashMap<String, String>() {
          {
            put("caseId", "94d5374f-290e-409f-bc57-86c2e4bcc43f");
            put("dateModified", newFormModifiedOn);
            put("serverDateModified", newFormModifiedOn);
            put("userId", "89fda0284e008d2e0c980fb13fa0e5bb");
            put("xmlns", "http://bihar.commcarehq.org/pregnancy/new");
            put("instanceId", "e34707f8-80c8-4198-bf99-c11c90ba5c98");
          }
        };

    careService.processAndSaveForms(motherFormValues, new ArrayList<Map<String, String>>());

    List<NewForm> newFormsFromDb = template.loadAll(NewForm.class);
    assertEquals(1, newFormsFromDb.size());
    assertEquals(oldFormModifiedDate, newFormsFromDb.get(0).getDateModified());
  }
  @Test
  public void shouldSaveChildForm() {
    ArrayList<Map<String, String>> childFormValues = new ArrayList<>();
    HashMap<String, String> childFormValue = new HashMap<>();
    childFormValue.put("caseId", "94d5374f-290e-409f-bc57-86c2e4bcc43f");
    childFormValue.put("xmlns", "http://bihar.commcarehq.org/pregnancy/registration");
    childFormValue.put("childName", "suraj");
    childFormValue.put("birthStatus", "healthy");
    childFormValue.put("instanceId", "ff2eb090-03a9-4f23-afed-cf6012784c55");
    childFormValue.put("flw", "89fda0284e008d2e0c980fb13fa0e5bb");
    childFormValue.put("timeStart", "2013-03-03T10:31:51.045+05:30");
    childFormValue.put("timeEnd", "2013-03-03T10:38:52.804+05:30");
    childFormValue.put("dateModified", "2013-03-03T10:38:52.804+05:30");

    childFormValues.add(childFormValue);

    careService.processAndSaveForms(null, childFormValues);

    List<RegistrationChildForm> registrationChildForms =
        template.loadAll(RegistrationChildForm.class);
    assertEquals(1, registrationChildForms.size());

    RegistrationChildForm expectedForm = getExpectedForm("94d5374f-290e-409f-bc57-86c2e4bcc43f");

    assertReflectionEqualsWithIgnore(
        expectedForm,
        registrationChildForms.get(0),
        new String[] {"id", "flw", "childCase", "creationTime", "lastModifiedTime"});

    List<Flw> flws = template.loadAll(Flw.class);
    assertEquals(1, flws.size());
    assertEquals("89fda0284e008d2e0c980fb13fa0e5bb", flws.get(0).getFlwId());
  }
  @Test
  public void shouldNotSaveMotherOrChildFormsIfNullAndEmpty() {
    careService.processAndSaveForms(null, new ArrayList<Map<String, String>>());

    List<MotherCase> mothers = template.loadAll(MotherCase.class);
    assertTrue(mothers.isEmpty());

    List<ChildCase> children = template.loadAll(ChildCase.class);
    assertTrue(children.isEmpty());
  }
  @Test
  public void shouldSaveFlwOnceForMotherAndChild() {
    final String flwId = "89fda0284e008d2e0c980fb13fa0e5bb";
    Flw flw = new FlwBuilder().flwId(flwId).build();
    final String instanceId = "e34707f8-80c8-4198-bf99-c11c90ba5c98";
    HashMap<String, String> motherCase =
        new HashMap<String, String>() {
          {
            put("caseId", "3e8998ce-b19f-4fa7-b1a1-721b6951e3cf");
            put("userId", flwId);
            put("flw", flwId);
            put("instanceId", instanceId);
            put("xmlns", "http://bihar.commcarehq.org/pregnancy/registration");
          }
        };

    final HashMap<String, String> child1 =
        new HashMap<String, String>() {
          {
            put("caseId", "3e8998ce-b19f-4fa7-b1a1-721b6951e3c1");
            put("userId", flwId);
            put("flw", flwId);
            put("instanceId", instanceId);
            put("xmlns", "http://bihar.commcarehq.org/pregnancy/registration");
          }
        };

    final HashMap<String, String> child2 =
        new HashMap<String, String>() {
          {
            put("caseId", "3e8998ce-b19f-4fa7-b1a1-721b6951e3c2");
            put("userId", flwId);
            put("flw", flwId);
            put("instanceId", instanceId);
            put("xmlns", "http://bihar.commcarehq.org/pregnancy/registration");
          }
        };

    careService.processAndSaveForms(
        motherCase,
        new ArrayList<Map<String, String>>() {
          {
            add(child1);
            add(child2);
          }
        });

    List<Flw> actualFlws = template.loadAll(Flw.class);
    assertEquals(1, actualFlws.size());

    assertReflectionEqualsWithIgnore(
        flw, actualFlws.get(0), new String[] {"id", "creationTime", "lastModifiedTime"});
  }
  @Test
  public void shouldNotThrowExceptionIfXmlnsNotRecognized() {
    Map<String, String> motherFormValuesWithoutXmlns =
        motherFormValues(
            "94d5374f-290e-409f-bc57-86c2e4bcc43f", "89fda0284e008d2e0c980fb13fa0e5bb");
    motherFormValuesWithoutXmlns.put("xmlns", "randomurl");

    try {
      careService.processAndSaveForms(
          motherFormValuesWithoutXmlns, new ArrayList<Map<String, String>>());
    } catch (Exception e) {
      fail("The exception should not have been thrown: " + e.getMessage());
    }
  }
  @Test
  public void
      shouldSaveChildFormByDeletingOlderFormIfFormWithSameInstanceIdAndCaseIdExistsAlready() {
    final String instanceId = "e34707f8-80c8-4198-bf99-c11c90ba5c98";
    final String caseId = "3e8998ce-b19f-4fa7-b1a1-721b6951e3cf";
    final Date oldFormModifiedDate = DateTime.parse("2012-07-10T12:02:59.923+05:30").toDate();

    ChildCase persistedChildCase = new ChildCase();
    persistedChildCase.setCaseId(caseId);

    final DeathChildForm persistedForm = new DeathChildForm();
    persistedForm.setInstanceId(instanceId);
    persistedForm.setChildCase(persistedChildCase);
    persistedForm.setDateModified(oldFormModifiedDate);
    persistedForm.setServerDateModified(oldFormModifiedDate);
    template.save(persistedForm);

    final String newFormModifiedOn = "2012-07-20T12:02:59.923+05:30";
    final Date newFormModifiedDate = DateTime.parse(newFormModifiedOn).toDate();
    final HashMap<String, String> deathChildFormValues =
        new HashMap<String, String>() {
          {
            put("caseId", caseId);
            put("dateModified", newFormModifiedOn);
            put("serverDateModified", newFormModifiedOn);
            put("userId", "89fda0284e008d2e0c980fb13fa0e5bb");
            put("close", "true");
            put("instanceId", instanceId);
            put("xmlns", "http://bihar.commcarehq.org/pregnancy/death");
          }
        };

    careService.processAndSaveForms(
        null,
        new ArrayList<Map<String, String>>() {
          {
            add(deathChildFormValues);
          }
        });

    List<DeathChildForm> deathChildForms = template.loadAll(DeathChildForm.class);
    assertEquals(1, deathChildForms.size());
    assertEquals(newFormModifiedDate, deathChildForms.get(0).getDateModified());
  }
  @Test
  public void shouldSaveMotherFormForExistingCase() {
    MotherCase motherCase = new MotherCase();
    motherCase.setCaseId("94d5374f-290e-409f-bc57-86c2e4bcc43f");
    template.save(motherCase);
    Flw flw = new Flw();
    flw.setFlwId("89fda0284e008d2e0c980fb13fa0e5bb");
    template.save(flw);
    Map<String, String> motherForm = motherFormValues(motherCase.getCaseId(), flw.getFlwId());

    careService.processAndSaveForms(motherForm, new ArrayList<Map<String, String>>());

    List<MotherCase> persistedMotherCases = template.loadAll(MotherCase.class);
    assertEquals(1, persistedMotherCases.size());
    List<NewForm> newForms = template.loadAll(NewForm.class);
    assertEquals(1, newForms.size());
    NewForm expectedForm = expectedForm(motherCase, flw);
    assertReflectionEqualsWithIgnore(
        expectedForm, newForms.get(0), new String[] {"id", "creationTime", "lastModifiedTime"});
  }
  @Test
  public void shouldSaveMotherFormAndCreateNewCase() {
    Map<String, String> motherForm =
        motherFormValues(
            "94d5374f-290e-409f-bc57-86c2e4bcc43f", "89fda0284e008d2e0c980fb13fa0e5bb");

    careService.processAndSaveForms(motherForm, new ArrayList<Map<String, String>>());

    List<MotherCase> persistedMotherCases = template.loadAll(MotherCase.class);
    assertEquals(1, persistedMotherCases.size());
    List<NewForm> newForms = template.loadAll(NewForm.class);
    assertEquals(1, newForms.size());
    NewForm expectedForm =
        expectedForm(
            new MotherCaseBuilder().caseId("94d5374f-290e-409f-bc57-86c2e4bcc43f").build(),
            new FlwBuilder().flwId("89fda0284e008d2e0c980fb13fa0e5bb").build());
    assertReflectionEqualsWithIgnore(
        expectedForm, newForms.get(0), new String[] {"id", "creationTime", "flw", "motherCase"});
    assertEquals(
        "94d5374f-290e-409f-bc57-86c2e4bcc43f", newForms.get(0).getMotherCase().getCaseId());
    assertEquals("89fda0284e008d2e0c980fb13fa0e5bb", newForms.get(0).getFlw().getFlwId());
  }