/** * Return the given <code>value</code> against this property, converting it to required model data type if a * {@link PropertyValueConverter} is present. * @param value Property value (can be null) * @return Model value, possibly converted using the {@link PropertyValueConverter} */ default Object getConvertedValue(T value) { return getConverter().map((c) -> (Object) c.toModel(value, this)).orElse(value); }
/** * Create a new {@link ExpressionValueConverter} using given <code>property</code>. * @param <TYPE> Expression type * @param property Property (not null) * @return If the property provides a {@link PropertyValueConverter}, return an {@link ExpressionValueConverter} * which uses the property value converter to perform conversions. Otherwise, an empty Optional is returned. */ static <TYPE> Optional<ExpressionValueConverter<TYPE, ?>> fromProperty(Property<TYPE> property) { return property.getConverter().map(c -> new DefaultPropertyExpressionValueConverter<>(property, c)); }
/** * Checks if the type of given {@link Property} is admitted as document identifier value type. Admitted types are: * {@link String}, {@link BigInteger} and {@link ObjectId}. * @param property Property to check * @return <code>true</code> if given type is admitted as document identifier type, <code>false</code> otherwise */ @SuppressWarnings("rawtypes") private static boolean isValidDocumentIdPropertyType(Property<?> property) { final Class<?> type = property.getConverter().map(c -> (Class) c.getModelType()).orElse(property.getType()); return isAdmittedDocumentIdType(type); }
/** * Decode given document into a {@link PropertyBox} using given adapter to match the document field names and * property paths. * @param context Resolution context * @param parent Optional parent field name expression * @param document Document to decode * @param propertyBox PropertyBox to use to collect the decoded values * @param adapter PropertyBox adapter * @throws InvalidExpressionException If an error occurred */ private static void decodeDocument(final MongoDocumentContext<?> context, final String parent, Map<String, Object> document, PropertyBox propertyBox, PathPropertyBoxAdapter adapter) throws InvalidExpressionException { final List<Property<?>> properties = new ArrayList<>(context.getPropertySet().asList()); document.entrySet().stream().forEach(entry -> { decodeDocumentField(context, propertyBox, adapter, parent, entry.getKey(), entry.getValue()) .ifPresent(p -> { properties.remove(p); }); }); // check properties with converter and force value set for (Property<?> property : properties) { if (property.getConverter().isPresent() && propertyBox.contains(property)) { propertyBox.setValue(property, null); } } }
/** * Check property value before putting it in PropertyBox. * @param <T> Property and value type * @param property Property * @param value Property value * @return Checked property value * @throws TypeMismatchException Value is not consistent with property type */ @SuppressWarnings("unchecked") protected <T> T checkupPropertyValue(Property<T> property, T value) throws TypeMismatchException { return validatePropertyValue(property, property.getConverter().filter(c -> isModelTypeConvertible(value, c)) .map(cv -> ((PropertyValueConverter<T, Object>) cv).fromModel(value, property)) .orElseGet(() -> checkValueTypeConsistency(property, value))); }
/** * Constructor with function argument. * @param argument Function argument (not null) * @param resultType Function result type (not null) */ @SuppressWarnings("unchecked") public AbstractPropertyQueryFunction(TypedExpression<? extends A> argument, Class<? extends T> resultType) { super(argument); ObjectUtils.argumentNotNull(resultType, "Function result type must be not null"); this.resultType = resultType; if (argument instanceof Property) { final Property<?> property = (Property<?>) argument; this.configuration = PropertyConfiguration.clone(property.getConfiguration()); if (getType() == property.getType() && property.getConverter().isPresent()) { converter = (PropertyValueConverter<T, ?>) property.getConverter().get(); } } else { this.configuration = PropertyConfiguration.create(); } }
@SuppressWarnings({ "rawtypes", "unchecked" }) @Override public T write(PropertyBox propertyBox, T instance, boolean ignoreMissing) { ObjectUtils.argumentNotNull(propertyBox, "PropertyBox must be not null"); ObjectUtils.argumentNotNull(instance, "Bean instance must be not null"); propertyBox.stream().filter(p -> !p.isReadOnly()).filter(p -> Path.class.isAssignableFrom(p.getClass())) .map(p -> (Path<?>) p).forEach(p -> { getProperty(p, ignoreMissing).ifPresent(bp -> { final Property<Object> property = ((Property) p); final Object boxValue = propertyBox.getValue(property); Object value = boxValue; // check conversion if (!TypeUtils.isAssignable(bp.getType(), property.getType())) { value = property.getConverter() .filter(c -> TypeUtils.isAssignable(bp.getType(), c.getModelType())) .map(c -> ((PropertyValueConverter) c).toModel(boxValue, property)) .orElse(boxValue); } write(bp, p.getType(), value, instance); }); }); return instance; }