web/play-java-forms/src/main/java/play/data/Form.java
public Field field(final String key, final Lang lang) {

    // Value
    String fieldValue = null;
    Http.MultipartFormData.FilePart file = null;
    if (rawData.containsKey(key)) {
      fieldValue = rawData.get(key);
    } else if (files.containsKey(key)) {
      file = files.get(key);
    } else {
      if (value.isPresent()) {
        BeanWrapper beanWrapper = new BeanWrapperImpl(value.get());
        beanWrapper.setAutoGrowNestedPaths(true);
        String objectKey = key;
        if (rootName != null && key.startsWith(rootName + ".")) {
          objectKey = key.substring(rootName.length() + 1);
        }
        if (beanWrapper.isReadableProperty(objectKey)) {
          Object oValue = beanWrapper.getPropertyValue(objectKey);
          if (oValue != null) {
            if (oValue instanceof Http.MultipartFormData.FilePart<?>) {
              file = (Http.MultipartFormData.FilePart<?>) oValue;
            } else {
              if (formatters != null) {
                final String objectKeyFinal = objectKey;
                fieldValue =
                    withRequestLocale(
                        lang,
                        () ->
                            formatters.print(
                                beanWrapper.getPropertyTypeDescriptor(objectKeyFinal), oValue));
              } else {
                fieldValue = oValue.toString();
              }
            }
          }
        }
      }
    }

    // Format
    Tuple<String, List<Object>> format = null;
    BeanWrapper beanWrapper = new BeanWrapperImpl(blankInstance());
    beanWrapper.setAutoGrowNestedPaths(true);
    try {
      for (Annotation a : beanWrapper.getPropertyTypeDescriptor(key).getAnnotations()) {
        Class<?> annotationType = a.annotationType();
        if (annotationType.isAnnotationPresent(play.data.Form.Display.class)) {
          play.data.Form.Display d = annotationType.getAnnotation(play.data.Form.Display.class);
          if (d.name().startsWith("format.")) {
            List<Object> attributes = new ArrayList<>();
            for (String attr : d.attributes()) {
              Object attrValue = null;
              try {
                attrValue = a.getClass().getDeclaredMethod(attr).invoke(a);
              } catch (Exception e) {
                // do nothing
              }
              attributes.add(attrValue);
            }
            format = Tuple(d.name(), Collections.unmodifiableList(attributes));
          }
        }
      }
    } catch (NullPointerException e) {
      // do nothing
    }

    // Constraints
    List<Tuple<String, List<Object>>> constraints = new ArrayList<>();
    Class<?> classType = backedType;
    String leafKey = key;
    if (rootName != null && leafKey.startsWith(rootName + ".")) {
      leafKey = leafKey.substring(rootName.length() + 1);
    }
    int p = leafKey.lastIndexOf('.');
    if (p > 0) {
      classType = beanWrapper.getPropertyType(leafKey.substring(0, p));
      leafKey = leafKey.substring(p + 1);
    }
    if (classType != null && this.validatorFactory != null) {
      BeanDescriptor beanDescriptor =
          this.validatorFactory.getValidator().getConstraintsForClass(classType);
      if (beanDescriptor != null) {
        PropertyDescriptor property = beanDescriptor.getConstraintsForProperty(leafKey);
        if (property != null) {
          Annotation[] orderedAnnotations = null;
          for (Class<?> c = classType;
              c != null;
              c = c.getSuperclass()) { // we also check the fields of all superclasses
            java.lang.reflect.Field field = null;
            try {
              field = c.getDeclaredField(leafKey);
            } catch (NoSuchFieldException | SecurityException e) {
              continue;
            }
            // getDeclaredAnnotations also looks for private fields; also it provides the
            // annotations in a guaranteed order
            orderedAnnotations =
                AnnotationUtils.unwrapContainerAnnotations(field.getDeclaredAnnotations());
            break;
          }
          constraints =
              Constraints.displayableConstraint(
                  property
                      .findConstraints()
                      .unorderedAndMatchingGroups(
                          groups != null ? groups : new Class[] {Default.class})
                      .getConstraintDescriptors(),
                  orderedAnnotations);
        }
      }
    }

    return new Field(this, key, constraints, format, errors(key), fieldValue, file);
  }
public Field field(final String key, final Lang lang) {

    // Value
    String fieldValue = null;
    Http.MultipartFormData.FilePart file = null;
    if (rawData.containsKey(key)) {
      fieldValue = rawData.get(key);
    } else if (files.containsKey(key)) {
      file = files.get(key);
    } else {
      if (value.isPresent()) {
        BeanWrapper beanWrapper = new BeanWrapperImpl(value.get());
        beanWrapper.setAutoGrowNestedPaths(true);
        String objectKey = key;
        if (rootName != null && key.startsWith(rootName + ".")) {
          objectKey = key.substring(rootName.length() + 1);
        }
        if (beanWrapper.isReadableProperty(objectKey)) {
          Object oValue = beanWrapper.getPropertyValue(objectKey);
          if (oValue != null) {
            if (oValue instanceof Http.MultipartFormData.FilePart<?>) {
              file = (Http.MultipartFormData.FilePart<?>) oValue;
            } else {
              if (formatters != null) {
                final String objectKeyFinal = objectKey;
                fieldValue =
                    withRequestLocale(
                        lang,
                        () ->
                            formatters.print(
                                beanWrapper.getPropertyTypeDescriptor(objectKeyFinal), oValue));
              } else {
                fieldValue = oValue.toString();
              }
            }
          }
        }
      }
    }

    // Format
    Tuple<String, List<Object>> format = null;
    BeanWrapper beanWrapper = new BeanWrapperImpl(blankInstance());
    beanWrapper.setAutoGrowNestedPaths(true);
    try {
      for (Annotation a : beanWrapper.getPropertyTypeDescriptor(key).getAnnotations()) {
        Class<?> annotationType = a.annotationType();
        if (annotationType.isAnnotationPresent(play.data.Form.Display.class)) {
          play.data.Form.Display d = annotationType.getAnnotation(play.data.Form.Display.class);
          if (d.name().startsWith("format.")) {
            List<Object> attributes = new ArrayList<>();
            for (String attr : d.attributes()) {
              Object attrValue = null;
              try {
                attrValue = a.getClass().getDeclaredMethod(attr).invoke(a);
              } catch (Exception e) {
                // do nothing
              }
              attributes.add(attrValue);
            }
            format = Tuple(d.name(), Collections.unmodifiableList(attributes));
          }
        }
      }
    } catch (NullPointerException e) {
      // do nothing
    }

    // Constraints
    List<Tuple<String, List<Object>>> constraints = new ArrayList<>();
    Class<?> classType = backedType;
    String leafKey = key;
    if (rootName != null && leafKey.startsWith(rootName + ".")) {
      leafKey = leafKey.substring(rootName.length() + 1);
    }
    int p = leafKey.lastIndexOf('.');
    if (p > 0) {
      classType = beanWrapper.getPropertyType(leafKey.substring(0, p));
      leafKey = leafKey.substring(p + 1);
    }
    if (classType != null && this.validatorFactory != null) {
      BeanDescriptor beanDescriptor =
          this.validatorFactory.getValidator().getConstraintsForClass(classType);
      if (beanDescriptor != null) {
        PropertyDescriptor property = beanDescriptor.getConstraintsForProperty(leafKey);
        if (property != null) {
          Annotation[] orderedAnnotations = null;
          for (Class<?> c = classType;
              c != null;
              c = c.getSuperclass()) { // we also check the fields of all superclasses
            java.lang.reflect.Field field = null;
            try {
              field = c.getDeclaredField(leafKey);
            } catch (NoSuchFieldException | SecurityException e) {
              continue;
            }
            // getDeclaredAnnotations also looks for private fields; also it provides the
            // annotations in a guaranteed order
            orderedAnnotations =
                AnnotationUtils.unwrapContainerAnnotations(field.getDeclaredAnnotations());
            break;
          }
          constraints =
              Constraints.displayableConstraint(
                  property
                      .findConstraints()
                      .unorderedAndMatchingGroups(
                          groups != null ? groups : new Class[] {Default.class})
                      .getConstraintDescriptors(),
                  orderedAnnotations);
        }
      }
    }

    return new Field(this, key, constraints, format, errors(key), fieldValue, file);
  }
Retrieves a field.

@param key field name
@param lang used for formatting
@return the field (even if the field does not exist you get a field)