package com.blazebit.reflection; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public final class ExpressionUtils { private static final ConcurrentMap<ExpressionUtils.PropertyPathExpressionKey, PropertyPathExpression<Object, Object>> cache = new ConcurrentHashMap<ExpressionUtils.PropertyPathExpressionKey, PropertyPathExpression<Object, Object>>(); /* Without value class */ public static <X, Y> PropertyPathExpression<X, Y> getExpression( Class<X> source, String propertyPath) { return getExpression(source, propertyPath, (Class<Y>) null); } public static <X, Y> PropertyPathExpressionValueHolder<X, Y> getValueHolder( Class<X> source, X target, String propertyPath) { return getValueHolder(source, target, propertyPath, (Class<Y>) null); } /* With value class */ @SuppressWarnings("unchecked") public static <X, Y> PropertyPathExpression<X, Y> getExpression( Class<X> source, String propertyPath, Class<Y> valueClass) { final PropertyPathExpressionKey key = new PropertyPathExpressionKey( source, propertyPath); PropertyPathExpression<Object, Object> expression = cache.get(key); if (expression == null) { expression = new PropertyPathExpression<Object, Object>( (Class<Object>) source, propertyPath); final PropertyPathExpression<Object, Object> oldExpression = cache .putIfAbsent(key, expression); if (oldExpression != null) { expression = oldExpression; } } return (PropertyPathExpression<X, Y>) expression; } public static <X, Y> PropertyPathExpressionValueHolder<X, Y> getValueHolder( Class<X> source, X target, String propertyPath, Class<Y> valueClass) { return new PropertyPathExpressionValueHolder<X, Y>(target, getExpression(source, propertyPath, valueClass)); } /* With source class */ public static <X, Y> Y getValue(Class<X> source, X target, String propertyPath) { return getValue(source, target, propertyPath, (Class<Y>) null); } public static <X, Y> Y getNullSafeValue(Class<X> source, X target, String propertyPath) { return getNullSafeValue(source, target, propertyPath, (Class<Y>) null); } public static <X, Y> void setValue(Class<X> source, X target, String propertyPath, Y value) { getExpression(source, propertyPath).setValue(target, value); } /* With value class */ public static <X, Y> Y getValue(Class<X> source, X target, String propertyPath, Class<Y> valueClass) { return getExpression(source, propertyPath, valueClass).getValue(target); } public static <X, Y> Y getNullSafeValue(Class<X> source, X target, String propertyPath, Class<Y> valueClass) { return getExpression(source, propertyPath, valueClass) .getNullSafeValue(target); } /* Without source class */ public static <X, Y> Y getValue(X target, String propertyPath) { return getValue(target, propertyPath, null); } public static <X, Y> Y getNullSafeValue(X target, String propertyPath) { return getNullSafeValue(target, propertyPath, null); } @SuppressWarnings("unchecked") public static <X, Y> void setValue(X target, String propertyPath, Y value) { getExpression((Class<X>) target.getClass(), propertyPath).setValue( target, value); } /* With value class */ @SuppressWarnings("unchecked") public static <X, Y> Y getValue(X target, String propertyPath, Class<Y> valueClass) { return getExpression((Class<X>) target.getClass(), propertyPath, valueClass).getValue(target); } @SuppressWarnings("unchecked") public static <X, Y> Y getNullSafeValue(X target, String propertyPath, Class<Y> valueClass) { return target == null ? null : getExpression( (Class<X>) target.getClass(), propertyPath, valueClass) .getNullSafeValue(target); } private static class PropertyPathExpressionKey { Class<?> source; String propertyPath; public PropertyPathExpressionKey(Class<?> source, String propertyPath) { this.source = source; this.propertyPath = propertyPath; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((propertyPath == null) ? 0 : propertyPath.hashCode()); result = prime * result + ((source == null) ? 0 : source.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; PropertyPathExpressionKey other = (PropertyPathExpressionKey) obj; if (propertyPath == null) { if (other.propertyPath != null) return false; } else if (!propertyPath.equals(other.propertyPath)) return false; if (source == null) { if (other.source != null) return false; } else if (!source.equals(other.source)) return false; return true; } } private ExpressionUtils() { } }