Exemplo n.º 1
0
  String findField(final MappedClass mc, final IndexOptions options, final List<String> path) {
    String segment = path.get(0);
    if (segment.equals("$**")) {
      return segment;
    }

    MappedField mf = mc.getMappedField(segment);
    if (mf == null) {
      mf = mc.getMappedFieldByJavaField(segment);
    }
    if (mf == null && mc.isInterface()) {
      for (final MappedClass mappedClass : mapper.getSubTypes(mc)) {
        try {
          return findField(mappedClass, options, new ArrayList<String>(path));
        } catch (MappingException e) {
          // try the next one
        }
      }
    }
    String namePath;
    if (mf != null) {
      namePath = mf.getNameToStore();
    } else {
      if (!options.disableValidation()) {
        throw pathFail(mc, path);
      } else {
        return join(path, '.');
      }
    }
    if (path.size() > 1) {
      try {
        Class concreteType = !mf.isSingleValue() ? mf.getSubClass() : mf.getConcreteType();
        namePath +=
            "."
                + findField(
                    mapper.getMappedClass(concreteType), options, path.subList(1, path.size()));
      } catch (MappingException e) {
        if (!options.disableValidation()) {
          throw pathFail(mc, path);
        } else {
          return join(path, '.');
        }
      }
    }
    return namePath;
  }
Exemplo n.º 2
0
  /** Validate the path, and value type, returning the mapped field for the field at the path */
  static MappedField validateQuery(
      final Class clazz,
      final Mapper mapper,
      final StringBuilder origProp,
      final FilterOperator op,
      final Object val,
      final boolean validateNames,
      final boolean validateTypes) {
    // TODO: cache validations (in static?).

    MappedField mf = null;
    final String prop = origProp.toString();
    boolean hasTranslations = false;

    if (validateNames) {
      final String[] parts = prop.split("\\.");
      if (clazz == null) {
        return null;
      }

      MappedClass mc = mapper.getMappedClass(clazz);
      // CHECKSTYLE:OFF
      for (int i = 0; ; ) {
        // CHECKSTYLE:ON
        final String part = parts[i];
        boolean fieldIsArrayOperator = part.equals("$");

        mf = mc.getMappedField(part);

        // translate from java field name to stored field name
        if (mf == null && !fieldIsArrayOperator) {
          mf = mc.getMappedFieldByJavaField(part);
          if (mf == null) {
            throw new ValidationException(
                format(
                    "The field '%s' could not be found in '%s' while validating - %s; if "
                        + "you wish to continue please disable validation.",
                    part, clazz.getName(), prop));
          }
          hasTranslations = true;
          parts[i] = mf.getNameToStore();
        }

        i++;
        if (mf != null && mf.isMap()) {
          // skip the map key validation, and move to the next part
          i++;
        }

        if (i >= parts.length) {
          break;
        }

        if (!fieldIsArrayOperator) {
          // catch people trying to search/update into @Reference/@Serialized fields
          if (!canQueryPast(mf)) {
            throw new ValidationException(
                format(
                    "Can not use dot-notation past '%s' could not be found in '%s' while"
                        + " validating - %s",
                    part, clazz.getName(), prop));
          }

          // get the next MappedClass for the next field validation
          mc = mapper.getMappedClass((mf.isSingleValue()) ? mf.getType() : mf.getSubClass());
        }
      }

      // record new property string if there has been a translation to any part
      if (hasTranslations) {
        origProp.setLength(0); // clear existing content
        origProp.append(parts[0]);
        for (int i = 1; i < parts.length; i++) {
          origProp.append('.');
          origProp.append(parts[i]);
        }
      }

      if (validateTypes && mf != null) {
        List<ValidationFailure> typeValidationFailures = new ArrayList<ValidationFailure>();
        boolean compatibleForType =
            isCompatibleForOperator(mc, mf, mf.getType(), op, val, typeValidationFailures);
        List<ValidationFailure> subclassValidationFailures = new ArrayList<ValidationFailure>();
        boolean compatibleForSubclass =
            isCompatibleForOperator(mc, mf, mf.getSubClass(), op, val, subclassValidationFailures);

        if ((mf.isSingleValue() && !compatibleForType)
            || mf.isMultipleValues() && !(compatibleForSubclass || compatibleForType)) {

          if (LOG.isWarningEnabled()) {
            LOG.warning(
                format(
                    "The type(s) for the query/update may be inconsistent; using an instance of type '%s' "
                        + "for the field '%s.%s' which is declared as '%s'",
                    val.getClass().getName(),
                    mf.getDeclaringClass().getName(),
                    mf.getJavaFieldName(),
                    mf.getType().getName()));
            typeValidationFailures.addAll(subclassValidationFailures);
            LOG.warning("Validation warnings: \n" + typeValidationFailures);
          }
        }
      }
    }
    return mf;
  }