1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| static ValidatedField validateQuery(Class clazz, Mapper mapper, String propertyName, FilterOperator op, Object val, boolean validateNames, boolean validateTypes) { final ValidatedField validatedField = new ValidatedField(propertyName); if (!propertyName.startsWith("$")) { final String[] pathElements = propertyName.split("\\."); final List<String> databasePathElements = new ArrayList<>(asList(pathElements)); if (clazz == null) { return validatedField; }
MappedClass mc = mapper.getMappedClass(clazz); for (int i = 0; ; ) { final String fieldName = pathElements[i]; boolean fieldIsArrayOperator = fieldName.equals("$"); final Optional<MappedField> mf = getMappedField(fieldName, mc, databasePathElements, i, propertyName, validateNames, fieldIsArrayOperator); validatedField.mappedField = mf;
i++; if (mf.isPresent() && mf.get().isMap()) { i++; } if (i >= pathElements.length) { break; } if (!fieldIsArrayOperator) { if (validateNames && !canQueryPast(mf.get())) { throw new ValidationException( format("Cannot use dot-notation past '%s' in '%s'; found while validating - %s", fieldName, mc.getClazz().getName(), propertyName)); } if (!mf.isPresent() && mc.isInterface()) { break; } else if (!mf.isPresent()) { throw new ValidationException( format("The field '%s' could not be found in '%s'", propertyName, mc.getClazz().getName())); } MappedField mappedField = mf.get(); mc = mapper.getMappedClass((mappedField.isSingleValue()) ? mappedField.getType() : mappedField.getSubClass()); } } validatedField.databasePath = databasePathElements.stream().collect(joining("."));
if (validateTypes && validatedField.mappedField.isPresent()) { MappedField mappedField = validatedField.mappedField.get(); List<ValidationFailure> typeValidationFailures = new ArrayList<>(); boolean compatibleForType = isCompatibleForOperator( mc, mappedField, mappedField.getType(), op, val, typeValidationFailures); List<ValidationFailure> subclassValidationFailures = new ArrayList<>(); boolean compatibleForSubclass = isCompatibleForOperator( mc, mappedField, mappedField.getSubClass(), op, val, subclassValidationFailures);
if ((mappedField.isSingleValue() && !compatibleForType) || mappedField.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(), mappedField.getDeclaringClass().getName(), mappedField.getJavaFieldName(), mappedField.getType().getName())); typeValidationFailures.addAll(subclassValidationFailures); LOG.warning("Validation warnings: \n" + typeValidationFailures); } } } } return validatedField; }
|