org.ldaptive.beans.spring.SpelAttributeValueMutator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ldaptive-beans Show documentation
Show all versions of ldaptive-beans Show documentation
Mapping, persistence, and code generation API for reading and writing POJOs to an LDAP directory
The newest version!
/* See LICENSE for licensing and NOTICE for copyright. */
package org.ldaptive.beans.spring;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.ldaptive.beans.Attribute;
import org.ldaptive.beans.AttributeValueMutator;
import org.ldaptive.transcode.ValueTranscoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
/**
* Attribute mutator that uses a SPEL expression and evaluation context.
*
* @author Middleware Services
*/
public class SpelAttributeValueMutator implements AttributeValueMutator
{
/** Logger for this class. */
protected final Logger logger = LoggerFactory.getLogger(getClass());
/** Attribute containing the SPEL expression. */
private final Attribute attribute;
/** SPEL expression to access values. */
private final Expression expression;
/** Evaluation context. */
private final EvaluationContext evaluationContext;
/** Custom transcoder for this attribute. */
private final ValueTranscoder transcoder;
/**
* Creates a new spel attribute value mutator.
*
* @param attr containing the SPEL configuration
* @param context containing the values
*/
public SpelAttributeValueMutator(final Attribute attr, final EvaluationContext context)
{
attribute = attr;
final ExpressionParser parser = new SpelExpressionParser();
expression = parser.parseExpression(attribute.property().length() > 0 ? attribute.property() : attribute.name());
evaluationContext = context;
if ("".equals(attribute.transcoder())) {
transcoder = null;
} else {
transcoder = parser.parseExpression(attribute.transcoder()).getValue(ValueTranscoder.class);
}
}
@Override
public String getName()
{
return attribute.name();
}
@Override
public boolean isBinary()
{
return attribute.binary();
}
@Override
public Collection getStringValues(final Object object)
{
return getValues(object, String.class);
}
@Override
public Collection getBinaryValues(final Object object)
{
return getValues(object, byte[].class);
}
/**
* Uses the configured expression and evaluation context to retrieve values from the supplied object. Values are the
* placed in a collection and returned.
*
* @param either String or byte[]
* @param object to get values from
* @param type of objects to place in the collection
*
* @return values in the supplied object
*/
protected Collection getValues(final Object object, final Class type)
{
Collection values = null;
final Object converted = expression.getValue(evaluationContext, object);
if (converted != null) {
if (converted instanceof byte[] || converted instanceof char[]) {
values = createCollection(List.class, 1);
final T value = convertValue(converted, converted.getClass(), type);
if (value != null) {
values.add(value);
}
} else if (converted.getClass().isArray()) {
final int length = Array.getLength(converted);
values = createCollection(List.class, length);
for (int i = 0; i < length; i++) {
final Object o = Array.get(converted, i);
if (o != null) {
final T value = convertValue(o, o.getClass(), type);
if (value != null) {
values.add(value);
}
}
}
} else if (Collection.class.isAssignableFrom(converted.getClass())) {
final Collection> col = (Collection>) converted;
values = createCollection(converted.getClass(), col.size());
for (Object o : col) {
if (o != null) {
final T value = convertValue(o, o.getClass(), type);
if (value != null) {
values.add(value);
}
}
}
} else {
values = createCollection(List.class, 1);
final T value = convertValue(converted, converted.getClass(), type);
if (value != null) {
values.add(value);
}
}
}
return values;
}
/**
* Converts the supplied value to the target type. If a custom transcoder has been configured it is used. Otherwise,
* the type converter from the evaluation context is used.
*
* @param either String or byte[]
* @param value to convert
* @param sourceType to convert from
* @param targetType to convert to
*
* @return converted value
*/
@SuppressWarnings("unchecked")
protected T convertValue(final Object value, final Class> sourceType, final Class targetType)
{
final T converted;
if (transcoder != null) {
if (byte[].class == targetType) {
converted = (T) transcoder.encodeBinaryValue(value);
} else if (String.class == targetType) {
converted = (T) transcoder.encodeStringValue(value);
} else {
throw new IllegalArgumentException("targetType must be either String.class or byte[].class");
}
} else {
converted = (T) evaluationContext.getTypeConverter().convertValue(
value,
TypeDescriptor.valueOf(sourceType),
TypeDescriptor.valueOf(targetType));
}
return converted;
}
@Override
public void setStringValues(final Object object, final Collection values)
{
setValues(object, values, String.class);
}
@Override
public void setBinaryValues(final Object object, final Collection values)
{
setValues(object, values, byte[].class);
}
/**
* Uses the configured expression and evaluation context to set values on the supplied object. If a custom transcoder
* has been configured it is executed on the values before they are passed to the expression.
*
* @param either String or byte[]
* @param object to set values on
* @param values to set
* @param type of objects in the collection
*/
protected void setValues(final Object object, final Collection values, final Class type)
{
if (transcoder != null) {
final Collection