Beispiel #1
0
 /** Return the indexes available for this field (for repeated fields ad List) */
 public List<Integer> indexes() {
   List<Integer> result = new ArrayList<Integer>();
   if (form.value().isDefined()) {
     BeanWrapper beanWrapper = new BeanWrapperImpl(form.value().get());
     beanWrapper.setAutoGrowNestedPaths(true);
     String objectKey = name;
     if (form.name() != null && name.startsWith(form.name() + ".")) {
       objectKey = name.substring(form.name().length() + 1);
     }
     if (beanWrapper.isReadableProperty(objectKey)) {
       Object value = beanWrapper.getPropertyValue(objectKey);
       if (value instanceof Collection) {
         for (int i = 0; i < ((Collection) value).size(); i++) {
           result.add(i);
         }
       }
     }
   } else {
     java.util.regex.Pattern pattern =
         java.util.regex.Pattern.compile(
             "^" + java.util.regex.Pattern.quote(name) + "\\[(\\d+)\\].*$");
     for (String key : form.data().keySet()) {
       java.util.regex.Matcher matcher = pattern.matcher(key);
       if (matcher.matches()) {
         result.add(Integer.parseInt(matcher.group(1)));
       }
     }
   }
   return result;
 }
Beispiel #2
0
  /**
   * Retrieve a field.
   *
   * @param key field name
   * @return the field (even if the field does not exist you get a field)
   */
  public Field field(String key) {

    // Value
    String fieldValue = null;
    if (data.containsKey(key)) {
      fieldValue = data.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) {
            final String objectKeyFinal = objectKey;
            fieldValue =
                withRequestLocale(
                    () ->
                        formatters.print(
                            beanWrapper.getPropertyTypeDescriptor(objectKeyFinal), oValue));
          }
        }
      }
    }

    // Error
    List<ValidationError> fieldErrors = errors.get(key);
    if (fieldErrors == null) {
      fieldErrors = new ArrayList<>();
    }

    // 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(), 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) {
      BeanDescriptor beanDescriptor =
          play.data.validation.Validation.getValidator().getConstraintsForClass(classType);
      if (beanDescriptor != null) {
        PropertyDescriptor property = beanDescriptor.getConstraintsForProperty(leafKey);
        if (property != null) {
          constraints = Constraints.displayableConstraint(property.getConstraintDescriptors());
        }
      }
    }

    return new Field(this, key, constraints, format, fieldErrors, fieldValue);
  }
Beispiel #3
0
  @SuppressWarnings("unchecked")
  static Object bindInternal(
      String name,
      Class clazz,
      Type type,
      Annotation[] annotations,
      Map<String, String[]> params,
      String suffix,
      String[] profiles) {
    try {
      Logger.trace("bindInternal: name [" + name + "] suffix [" + suffix + "]");

      String[] value = params.get(name + suffix);
      Logger.trace("bindInternal: value [" + value + "]");
      Logger.trace("bindInternal: profile [" + Utils.join(profiles, ",") + "]");
      // Let see if we have a BindAs annotation and a separator. If so, we need to split the values
      // Look up for the BindAs annotation. Extract the profile if there is any.
      // TODO: Move me somewhere else?
      if (annotations != null) {
        for (Annotation annotation : annotations) {
          if ((clazz.isArray() || Collection.class.isAssignableFrom(clazz))
              && value != null
              && value.length > 0
              && annotation.annotationType().equals(As.class)) {
            As as = ((As) annotation);
            final String separator = as.value()[0];
            value = value[0].split(separator);
          }
          if (annotation.annotationType().equals(NoBinding.class)) {
            NoBinding bind = ((NoBinding) annotation);
            String[] localUnbindProfiles = bind.value();
            Logger.trace(
                "bindInternal: localUnbindProfiles [" + Utils.join(localUnbindProfiles, ",") + "]");

            if (localUnbindProfiles != null && contains(profiles, localUnbindProfiles)) {
              return NO_BINDING;
            }
          }
        }
      }

      // Arrays types
      // The array condition is not so nice... We should find another way of doing this....
      if (clazz.isArray()
          && (clazz != byte[].class
              && clazz != byte[][].class
              && clazz != File[].class
              && clazz != Upload[].class)) {
        if (value == null) {
          value = params.get(name + suffix + "[]");
        }
        if (value == null) {
          return MISSING;
        }
        Object r = Array.newInstance(clazz.getComponentType(), value.length);
        for (int i = 0; i <= value.length; i++) {
          try {
            Array.set(r, i, directBind(name, annotations, value[i], clazz.getComponentType()));
          } catch (Exception e) {
            // ?? One item was bad
          }
        }
        return r;
      }
      // Enums
      if (Enum.class.isAssignableFrom(clazz)) {
        if (value == null || value.length == 0) {
          return MISSING;
        } else if (StringUtils.isEmpty(value[0])) {
          return null;
        }
        return Enum.valueOf(clazz, value[0]);
      }
      // Map
      if (Map.class.isAssignableFrom(clazz)) {
        Class keyClass = String.class;
        Class valueClass = String.class;
        if (type instanceof ParameterizedType) {
          keyClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[0];
          valueClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[1];
        }

        // Special case Map<String, String>
        // Multivalues composite params are binded to a Map<String, String>
        // see http://play.lighthouseapp.com/projects/57987/tickets/443
        if (keyClass == String.class && valueClass == String.class && isComposite(name, params)) {
          Map<String, String> stringMap = Utils.filterParams(params, name);
          if (stringMap.size() > 0) return stringMap;
        }

        // Search for all params
        Map<Object, Object> r = new HashMap<Object, Object>();
        for (String param : params.keySet()) {
          Pattern p = Pattern.compile("^" + name + suffix + "\\[([^\\]]+)\\](.*)$");
          Matcher m = p.matcher(param);
          if (m.matches()) {
            String key = m.group(1);
            value = params.get(param);
            Map<String, String[]> tP = new HashMap<String, String[]>();
            tP.put("key", new String[] {key});
            Object oKey = bindInternal("key", keyClass, keyClass, annotations, tP, "", value);
            if (oKey != MISSING) {
              if (isComposite(name + suffix + "[" + key + "]", params)) {
                BeanWrapper beanWrapper = getBeanWrapper(valueClass);
                Object oValue =
                    beanWrapper.bind(
                        "", type, params, name + suffix + "[" + key + "]", annotations);
                r.put(oKey, oValue);
              } else {
                tP = new HashMap<String, String[]>();
                tP.put("value", params.get(name + suffix + "[" + key + "]"));
                Object oValue =
                    bindInternal("value", valueClass, valueClass, annotations, tP, "", value);
                if (oValue != MISSING) {
                  r.put(oKey, oValue);
                } else {
                  r.put(oKey, null);
                }
              }
            }
          }
        }
        return r;
      }
      // Collections types
      if (Collection.class.isAssignableFrom(clazz)) {
        if (clazz.isInterface()) {
          if (clazz.equals(List.class)) {
            clazz = ArrayList.class;
          }
          if (clazz.equals(Set.class)) {
            clazz = HashSet.class;
          }
          if (clazz.equals(SortedSet.class)) {
            clazz = TreeSet.class;
          }
        }
        Collection r = (Collection) clazz.newInstance();
        Class componentClass = String.class;
        if (type instanceof ParameterizedType) {
          componentClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[0];
        }
        // Create a an array of the component class
        if (value != null) {
          Object customArray = Array.newInstance(componentClass, value.length);
          // custom types
          for (Class<?> c : supportedTypes.keySet()) {
            if (c.isAssignableFrom(customArray.getClass())) {
              Object[] ar =
                  (Object[])
                      supportedTypes
                          .get(c)
                          .bind("value", annotations, name, customArray.getClass(), null);
              List l = Arrays.asList(ar);
              if (clazz.equals(HashSet.class)) {
                return new HashSet(l);
              } else if (clazz.equals(TreeSet.class)) {
                return new TreeSet(l);
              }
              return l;
            }
          }
        }
        if (value == null) {
          value = params.get(name + suffix + "[]");
          if (value == null && r instanceof List) {
            for (String param : params.keySet()) {
              Pattern p = Pattern.compile("^" + escape(name + suffix) + "\\[([0-9]+)\\](.*)$");
              Matcher m = p.matcher(param);
              if (m.matches()) {
                int key = Integer.parseInt(m.group(1));
                while (((List<?>) r).size() <= key) {
                  ((List<?>) r).add(null);
                }
                if (isComposite(name + suffix + "[" + key + "]", params)) {
                  BeanWrapper beanWrapper = getBeanWrapper(componentClass);
                  Object oValue =
                      beanWrapper.bind(
                          "", type, params, name + suffix + "[" + key + "]", annotations);
                  ((List) r).set(key, oValue);
                } else {
                  Map<String, String[]> tP = new HashMap<String, String[]>();
                  tP.put("value", params.get(name + suffix + "[" + key + "]"));
                  Object oValue =
                      bindInternal(
                          "value", componentClass, componentClass, annotations, tP, "", value);
                  if (oValue != MISSING) {
                    ((List) r).set(key, oValue);
                  }
                }
              }
            }
            return r.isEmpty() ? MISSING : r;
          }
        }
        if (value == null) {
          return MISSING;
        }
        for (String v : value) {
          try {
            r.add(directBind(name, annotations, v, componentClass));
          } catch (Exception e) {
            // ?? One item was bad
            Logger.debug(e, "error:");
          }
        }
        return r;
      }

      // Assume a Bean if isComposite
      Logger.trace(
          "bindInternal: class ["
              + clazz
              + "] name ["
              + name
              + "] annotation ["
              + Utils.join(annotations, " ")
              + "] isComposite ["
              + isComposite(name + suffix, params)
              + "]");
      if (isComposite(name + suffix, params)) {
        BeanWrapper beanWrapper = getBeanWrapper(clazz);
        return beanWrapper.bind(name, type, params, suffix, annotations);
      }

      // Simple types
      if (value == null || value.length == 0) {
        return MISSING;
      }

      return directBind(name, annotations, value[0], clazz, type);
    } catch (Exception e) {
      Validation.addError(name + suffix, "validation.invalid");
      return MISSING;
    }
  }