package org.mongodb.morphia.query.validation; import org.mongodb.morphia.mapping.MappedField; import org.mongodb.morphia.query.FilterOperator; import java.util.List; import static java.lang.String.format; import static org.mongodb.morphia.query.FilterOperator.SIZE; import static org.mongodb.morphia.query.validation.ValueClassValidator.valueIsClassOrSubclassOf; /** * Checks if the value can have the {@code FilterOperator.ALL} operator applied to it. Since this class does not need state, and the * methods can't be static because it implements an interface, it seems to be one of the few places where the Singleton pattern seems * appropriate. */ public final class SizeOperationValidator extends OperationValidator { private static final SizeOperationValidator INSTANCE = new SizeOperationValidator(); private SizeOperationValidator() { } /** * Get the instance * * @return the Singleton instance of this validator */ public static SizeOperationValidator getInstance() { return INSTANCE; } @Override protected FilterOperator getOperator() { return SIZE; } @Override protected void validate(final MappedField mappedField, final Object value, final List<ValidationFailure> validationFailures) { if (!valueIsClassOrSubclassOf(value, Number.class)) { validationFailures.add(new ValidationFailure(format("For a $size operation, value '%s' should be an integer type. " + "Instead it was a: %s", value, value.getClass()))); } if (!CollectionTypeValidator.typeIsIterableOrArrayOrMap(mappedField.getType())) { validationFailures.add(new ValidationFailure(format("For a $size operation, field '%s' should be a List or array. " + "Instead it was a: %s", mappedField, mappedField.getType()))); } } }