@Override
  public void createDateField(
      ClassOrInterfaceTypeDetails javaTypeDetails,
      JavaType fieldType,
      JavaSymbolName fieldName,
      boolean notNull,
      boolean nullRequired,
      boolean future,
      boolean past,
      DateFieldPersistenceType persistenceType,
      String column,
      String comment,
      DateTime dateFormat,
      DateTime timeFormat,
      String pattern,
      String value,
      boolean permitReservedWords,
      boolean transientModifier,
      List<AnnotationMetadataBuilder> extraAnnotations) {
    final String physicalTypeIdentifier = javaTypeDetails.getDeclaredByMetadataId();
    final DateField fieldDetails = new DateField(physicalTypeIdentifier, fieldType, fieldName);
    fieldDetails.setNotNull(notNull);
    fieldDetails.setNullRequired(nullRequired);
    fieldDetails.setFuture(future);
    fieldDetails.setPast(past);
    if (JdkJavaType.isDateField(fieldType)) {
      fieldDetails.setPersistenceType(persistenceType);
    }
    if (column != null) {
      fieldDetails.setColumn(column);
    }
    if (comment != null) {
      fieldDetails.setComment(comment);
    }
    if (dateFormat != null) {
      fieldDetails.setDateFormat(dateFormat);
    }
    if (timeFormat != null) {
      fieldDetails.setTimeFormat(timeFormat);
    }
    if (pattern != null) {
      fieldDetails.setPattern(pattern);
    }
    if (value != null) {
      fieldDetails.setValue(value);
    }

    if (extraAnnotations != null && !extraAnnotations.isEmpty()) {
      fieldDetails.addAnnotations(extraAnnotations);
    }

    insertField(fieldDetails, permitReservedWords, false);
  }
  /** @return a test for the merge method, if available and requested (may return null) */
  private MethodMetadataBuilder getMergeMethodTest(
      final MemberTypeAdditions mergeMethod,
      final MemberTypeAdditions findMethod,
      final MemberTypeAdditions flushMethod,
      final MethodMetadata versionAccessorMethod,
      final MethodMetadata identifierAccessorMethod) {
    if (!annotationValues.isMerge()
        || mergeMethod == null
        || versionAccessorMethod == null
        || findMethod == null
        || identifierAccessorMethod == null) {
      // User does not want this method, or core dependencies are missing
      return null;
    }

    // Prepare method signature
    JavaSymbolName methodName =
        new JavaSymbolName("test" + StringUtils.capitalize(mergeMethod.getMethodName()) + "Update");
    if (governorHasMethod(methodName)) {
      return null;
    }

    JavaType versionType = versionAccessorMethod.getReturnType();
    builder
        .getImportRegistrationResolver()
        .addImports(identifierAccessorMethod.getReturnType(), versionType);

    List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
    annotations.add(new AnnotationMetadataBuilder(TEST));

    String entityName = annotationValues.getEntity().getSimpleTypeName();

    InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
    bodyBuilder.appendFormalLine(
        entityName
            + " obj = dod."
            + dataOnDemandMetadata.getRandomPersistentEntityMethod().getMethodName().getSymbolName()
            + "();");
    bodyBuilder.appendFormalLine(
        "Assert.assertNotNull(\"Data on demand for '"
            + entityName
            + "' failed to initialize correctly\", obj);");
    bodyBuilder.appendFormalLine(
        identifierAccessorMethod.getReturnType().getSimpleTypeName()
            + " id = obj."
            + identifierAccessorMethod.getMethodName().getSymbolName()
            + "();");
    bodyBuilder.appendFormalLine(
        "Assert.assertNotNull(\"Data on demand for '"
            + entityName
            + "' failed to provide an identifier\", id);");
    bodyBuilder.appendFormalLine("obj = " + findMethod.getMethodCall() + ";");
    bodyBuilder.appendFormalLine(
        "boolean modified =  dod."
            + dataOnDemandMetadata.getModifyMethod().getMethodName().getSymbolName()
            + "(obj);");

    bodyBuilder.appendFormalLine(
        versionAccessorMethod.getReturnType().getSimpleTypeName()
            + " currentVersion = obj."
            + versionAccessorMethod.getMethodName().getSymbolName()
            + "();");

    String castStr = entityHasSuperclass ? "(" + entityName + ")" : "";
    bodyBuilder.appendFormalLine(
        entityName + " merged = " + castStr + mergeMethod.getMethodCall() + ";");

    if (flushMethod != null) {
      bodyBuilder.appendFormalLine(flushMethod.getMethodCall() + ";");
      flushMethod.copyAdditionsTo(builder, governorTypeDetails);
    }

    bodyBuilder.appendFormalLine(
        "Assert.assertEquals(\"Identifier of merged object not the same as identifier of original object\", merged."
            + identifierAccessorMethod.getMethodName().getSymbolName()
            + "(), id);");
    if (JdkJavaType.isDateField(versionType)) {
      bodyBuilder.appendFormalLine(
          "Assert.assertTrue(\"Version for '"
              + entityName
              + "' failed to increment on merge and flush directive\", (currentVersion != null && obj."
              + versionAccessorMethod.getMethodName().getSymbolName()
              + "().after(currentVersion)) || !modified);");
    } else {
      bodyBuilder.appendFormalLine(
          "Assert.assertTrue(\"Version for '"
              + entityName
              + "' failed to increment on merge and flush directive\", (currentVersion != null && obj."
              + versionAccessorMethod.getMethodName().getSymbolName()
              + "() > currentVersion) || !modified);");
    }
    mergeMethod.copyAdditionsTo(builder, governorTypeDetails);
    findMethod.copyAdditionsTo(builder, governorTypeDetails);

    MethodMetadataBuilder methodBuilder =
        new MethodMetadataBuilder(
            getId(), Modifier.PUBLIC, methodName, JavaType.VOID_PRIMITIVE, bodyBuilder);
    methodBuilder.setAnnotations(annotations);
    return methodBuilder;
  }