use of org.springframework.expression.PropertyAccessor in project spring-framework by spring-projects.
the class PropertyOrFieldReference method readProperty.
/**
* Attempt to read the named property from the current context object.
* @return the value of the property
* @throws EvaluationException if any problem accessing the property or it cannot be found
*/
private TypedValue readProperty(TypedValue contextObject, EvaluationContext evalContext, String name) throws EvaluationException {
Object targetObject = contextObject.getValue();
if (targetObject == null && this.nullSafe) {
return TypedValue.NULL;
}
PropertyAccessor accessorToUse = this.cachedReadAccessor;
if (accessorToUse != null) {
try {
return accessorToUse.read(evalContext, contextObject.getValue(), name);
} catch (Exception ex) {
// This is OK - it may have gone stale due to a class change,
// let's try to get a new one and call it before giving up...
this.cachedReadAccessor = null;
}
}
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObject.getValue(), evalContext.getPropertyAccessors());
// then ask them to read it
if (accessorsToTry != null) {
try {
for (PropertyAccessor accessor : accessorsToTry) {
if (accessor.canRead(evalContext, contextObject.getValue(), name)) {
if (accessor instanceof ReflectivePropertyAccessor) {
accessor = ((ReflectivePropertyAccessor) accessor).createOptimalAccessor(evalContext, contextObject.getValue(), name);
}
this.cachedReadAccessor = accessor;
return accessor.read(evalContext, contextObject.getValue(), name);
}
}
} catch (Exception ex) {
throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_DURING_PROPERTY_READ, name, ex.getMessage());
}
}
if (contextObject.getValue() == null) {
throw new SpelEvaluationException(SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL, name);
} else {
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE, name, FormatHelper.formatClassNameForMessage(getObjectClass(contextObject.getValue())));
}
}
use of org.springframework.expression.PropertyAccessor in project spring-framework by spring-projects.
the class PropertyOrFieldReference method writeProperty.
private void writeProperty(TypedValue contextObject, EvaluationContext evalContext, String name, Object newValue) throws EvaluationException {
if (contextObject.getValue() == null && this.nullSafe) {
return;
}
PropertyAccessor accessorToUse = this.cachedWriteAccessor;
if (accessorToUse != null) {
try {
accessorToUse.write(evalContext, contextObject.getValue(), name, newValue);
return;
} catch (Exception ex) {
// This is OK - it may have gone stale due to a class change,
// let's try to get a new one and call it before giving up...
this.cachedWriteAccessor = null;
}
}
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObject.getValue(), evalContext.getPropertyAccessors());
if (accessorsToTry != null) {
try {
for (PropertyAccessor accessor : accessorsToTry) {
if (accessor.canWrite(evalContext, contextObject.getValue(), name)) {
this.cachedWriteAccessor = accessor;
accessor.write(evalContext, contextObject.getValue(), name, newValue);
return;
}
}
} catch (AccessException ex) {
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.EXCEPTION_DURING_PROPERTY_WRITE, name, ex.getMessage());
}
}
if (contextObject.getValue() == null) {
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL, name);
} else {
throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE, name, FormatHelper.formatClassNameForMessage(getObjectClass(contextObject.getValue())));
}
}
use of org.springframework.expression.PropertyAccessor in project spring-framework by spring-projects.
the class PropertyOrFieldReference method getValueInternal.
@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
TypedValue tv = getValueInternal(state.getActiveContextObject(), state.getEvaluationContext(), state.getConfiguration().isAutoGrowNullReferences());
PropertyAccessor accessorToUse = this.cachedReadAccessor;
if (accessorToUse instanceof CompilablePropertyAccessor) {
CompilablePropertyAccessor accessor = (CompilablePropertyAccessor) accessorToUse;
this.exitTypeDescriptor = CodeFlow.toDescriptor(accessor.getPropertyType());
}
return tv;
}
use of org.springframework.expression.PropertyAccessor in project spring-framework by spring-projects.
the class PropertyOrFieldReference method getPropertyAccessorsToTry.
/**
* Determines the set of property resolvers that should be used to try and access a property
* on the specified target type. The resolvers are considered to be in an ordered list,
* however in the returned list any that are exact matches for the input target type (as
* opposed to 'general' resolvers that could work for any type) are placed at the start of the
* list. In addition, there are specific resolvers that exactly name the class in question
* and resolvers that name a specific class but it is a supertype of the class we have.
* These are put at the end of the specific resolvers set and will be tried after exactly
* matching accessors but before generic accessors.
* @param contextObject the object upon which property access is being attempted
* @return a list of resolvers that should be tried in order to access the property
*/
private List<PropertyAccessor> getPropertyAccessorsToTry(Object contextObject, List<PropertyAccessor> propertyAccessors) {
Class<?> targetType = (contextObject != null ? contextObject.getClass() : null);
List<PropertyAccessor> specificAccessors = new ArrayList<>();
List<PropertyAccessor> generalAccessors = new ArrayList<>();
for (PropertyAccessor resolver : propertyAccessors) {
Class<?>[] targets = resolver.getSpecificTargetClasses();
if (targets == null) {
// generic resolver that says it can be used for any type
generalAccessors.add(resolver);
} else if (targetType != null) {
for (Class<?> clazz : targets) {
if (clazz == targetType) {
specificAccessors.add(resolver);
break;
} else if (clazz.isAssignableFrom(targetType)) {
generalAccessors.add(resolver);
}
}
}
}
List<PropertyAccessor> resolvers = new ArrayList<>();
resolvers.addAll(specificAccessors);
generalAccessors.removeAll(specificAccessors);
resolvers.addAll(generalAccessors);
return resolvers;
}
use of org.springframework.expression.PropertyAccessor in project spring-framework by spring-projects.
the class PropertyAccessTests method testAddingRemovingAccessors.
@Test
public void testAddingRemovingAccessors() {
StandardEvaluationContext ctx = new StandardEvaluationContext();
// reflective property accessor is the only one by default
List<PropertyAccessor> propertyAccessors = ctx.getPropertyAccessors();
assertEquals(1, propertyAccessors.size());
StringyPropertyAccessor spa = new StringyPropertyAccessor();
ctx.addPropertyAccessor(spa);
assertEquals(2, ctx.getPropertyAccessors().size());
List<PropertyAccessor> copy = new ArrayList<>();
copy.addAll(ctx.getPropertyAccessors());
assertTrue(ctx.removePropertyAccessor(spa));
assertFalse(ctx.removePropertyAccessor(spa));
assertEquals(1, ctx.getPropertyAccessors().size());
ctx.setPropertyAccessors(copy);
assertEquals(2, ctx.getPropertyAccessors().size());
}
Aggregations