@Override
  protected void check(
      final MappedClass mc, final MappedField mf, final Set<ConstraintViolation> ve) {
    if (mf.hasAnnotation(Reference.class)) {
      final Class realType = (mf.isSingleValue()) ? mf.getType() : mf.getSubClass();

      if (realType == null) {
        throw new MappingException("Type is null for this MappedField: " + mf);
      }

      if ((!realType.isInterface()
          && mc.getMapper().getMappedClass(realType).getIdField() == null)) {
        ve.add(
            new ConstraintViolation(
                Level.FATAL,
                mc,
                mf,
                getClass(),
                mf.getFullName()
                    + " is annotated as a @"
                    + Reference.class.getSimpleName()
                    + " but the "
                    + mf.getType().getName()
                    + " class is missing the @"
                    + Id.class.getSimpleName()
                    + " annotation"));
      }
    }
  }
示例#2
0
  private List<Index> collectNestedIndexes(
      final MappedClass mc, final List<MappedClass> parentMCs) {
    List<Index> list = new ArrayList<Index>();
    for (final MappedField mf : mc.getPersistenceFields()) {
      if (!mf.isTypeMongoCompatible()
          && !mf.hasAnnotation(Reference.class)
          && !mf.hasAnnotation(Serialized.class)
          && !mf.hasAnnotation(NotSaved.class)
          && !mf.isTransient()) {

        final List<MappedClass> parents = new ArrayList<MappedClass>(parentMCs);
        parents.add(mc);

        List<MappedClass> classes = new ArrayList<MappedClass>();
        MappedClass mappedClass =
            mapper.getMappedClass(mf.isSingleValue() ? mf.getType() : mf.getSubClass());
        classes.add(mappedClass);
        classes.addAll(mapper.getSubTypes(mappedClass));
        for (MappedClass aClass : classes) {
          for (Index index : collectIndexes(aClass, parents)) {
            List<Field> fields = new ArrayList<Field>();
            for (Field field : index.fields()) {
              fields.add(
                  new FieldBuilder()
                      .value(
                          field.value().equals("$**")
                              ? field.value()
                              : mf.getNameToStore() + "." + field.value())
                      .type(field.type())
                      .weight(field.weight()));
            }
            list.add(new IndexBuilder(index).fields(fields));
          }
        }
      }
    }

    return list;
  }
示例#3
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;
  }