예제 #1
0
  private List<Index> collectTopLevelIndexes(final MappedClass mc) {
    List<Index> list = new ArrayList<Index>();
    final List<Indexes> annotations = mc.getAnnotations(Indexes.class);
    if (annotations != null) {
      for (final Indexes indexes : annotations) {
        for (final Index index : indexes.value()) {
          Index updated = index;
          if (index.fields().length == 0) {
            LOG.warning(
                format(
                    "This index on '%s' is using deprecated configuration options.  Please update to use the "
                        + "fields value on @Index: %s",
                    mc.getClazz().getName(), index.toString()));
            updated = new IndexBuilder().migrate(index);
          }
          List<Field> fields = new ArrayList<Field>();
          for (Field field : updated.fields()) {
            fields.add(
                new FieldBuilder()
                    .value(findField(mc, index.options(), asList(field.value().split("\\."))))
                    .type(field.type())
                    .weight(field.weight()));
          }

          list.add(replaceFields(updated, fields));
        }
      }
    }
    return list;
  }
예제 #2
0
 @Override
 public Query<T> retrieveKnownFields() {
   final MappedClass mc = ds.getMapper().getMappedClass(clazz);
   final List<String> fields = new ArrayList<String>(mc.getPersistenceFields().size() + 1);
   for (final MappedField mf : mc.getPersistenceFields()) {
     fields.add(mf.getNameToStore());
   }
   retrievedFields(true, fields.toArray(new String[fields.size()]));
   return this;
 }
예제 #3
0
 @Override
 public void check(final MappedClass mc, final Set<ConstraintViolation> ve) {
   if (mc.getEmbeddedAnnotation() != null && mc.getIdField() != null) {
     ve.add(
         new ConstraintViolation(
             Level.FATAL,
             mc,
             getClass(),
             "@" + Embedded.class.getSimpleName() + " classes cannot specify a @Id field"));
   }
 }
예제 #4
0
  @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"));
      }
    }
  }
예제 #5
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;
  }
예제 #6
0
  /**
   * Creates a Query for the given type and collection
   *
   * @param clazz the type to return
   * @param coll the collection to query
   * @param ds the Datastore to use
   */
  public QueryImpl(final Class<T> clazz, final DBCollection coll, final Datastore ds) {
    super(CriteriaJoin.AND);

    setQuery(this);
    this.clazz = clazz;
    this.ds = ((org.mongodb.morphia.DatastoreImpl) ds);
    dbColl = coll;
    cache = this.ds.getMapper().createEntityCache();

    final MappedClass mc = this.ds.getMapper().getMappedClass(clazz);
    final Entity entAn = mc == null ? null : mc.getEntityAnnotation();
    if (entAn != null) {
      getOptions()
          .readPreference(
              this.ds.getMapper().getMappedClass(clazz).getEntityAnnotation().queryNonPrimary()
                  ? ReadPreference.secondaryPreferred()
                  : null);
    }
  }
예제 #7
0
  @Override
  @Deprecated
  public DBObject getFieldsObject() {
    DBObject projection = getOptions().getProjection();
    if (projection == null || projection.keySet().size() == 0) {
      return null;
    }

    final MappedClass mc = ds.getMapper().getMappedClass(clazz);

    Entity entityAnnotation = mc.getEntityAnnotation();
    final BasicDBObject fieldsFilter = copy(projection);

    if (includeFields && entityAnnotation != null && !entityAnnotation.noClassnameStored()) {
      fieldsFilter.put(Mapper.CLASS_NAME_FIELDNAME, 1);
    }

    return fieldsFilter;
  }
예제 #8
0
 @Override
 public void check(final MappedClass mc, final Set<ConstraintViolation> ve) {
   final Set<Class<?>> classesToInspect = new HashSet<Class<?>>();
   for (final Field field : ReflectionUtils.getDeclaredAndInheritedFields(mc.getClazz(), true)) {
     if (isFieldToInspect(field) && !field.isAnnotationPresent(Id.class)) {
       classesToInspect.add(field.getType());
     }
   }
   checkRecursivelyHasNoIdAnnotationPresent(classesToInspect, new HashSet<Class<?>>(), mc, ve);
 }
예제 #9
0
  private List<Index> collectIndexes(final MappedClass mc, final List<MappedClass> parentMCs) {
    if (parentMCs.contains(mc) || mc.getEmbeddedAnnotation() != null && parentMCs.isEmpty()) {
      return emptyList();
    }

    List<Index> indexes = collectTopLevelIndexes(mc);
    indexes.addAll(collectFieldIndexes(mc));
    indexes.addAll(collectNestedIndexes(mc, parentMCs));

    return indexes;
  }
예제 #10
0
 @SuppressWarnings("deprecation")
 private List<Index> collectFieldIndexes(final MappedClass mc) {
   List<Index> list = new ArrayList<Index>();
   for (final MappedField mf : mc.getPersistenceFields()) {
     if (mf.hasAnnotation(Indexed.class)) {
       final Indexed indexed = mf.getAnnotation(Indexed.class);
       list.add(convert(indexed, mf.getNameToStore()));
     } else if (mf.hasAnnotation(Text.class)) {
       final Text text = mf.getAnnotation(Text.class);
       list.add(convert(text, mf.getNameToStore()));
     }
   }
   return list;
 }
예제 #11
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;
  }
예제 #12
0
 BsonDocument calculateKeys(final MappedClass mc, final Index index) {
   BsonDocument keys = new BsonDocument();
   for (Field field : index.fields()) {
     String path;
     try {
       path =
           findField(
               mc, index.options(), new ArrayList<String>(asList(field.value().split("\\."))));
     } catch (Exception e) {
       path = field.value();
       String message =
           format(
               "The path '%s' can not be validated against '%s' and may represent an invalid index",
               path, mc.getClazz().getName());
       if (!index.options().disableValidation()) {
         throw new MappingException(message);
       }
       LOG.warning(message);
     }
     keys.putAll(toBsonDocument(path, field.type().toIndexValue()));
   }
   return keys;
 }
예제 #13
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;
  }
예제 #14
0
 private MappingException pathFail(final MappedClass mc, final List<String> path) {
   return new MappingException(
       format(
           "Could not resolve path '%s' against '%s'.", join(path, '.'), mc.getClazz().getName()));
 }