/******************************************************************************* * Copyright (c) 2012 BMW Car IT and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package org.jnario.jnario.test.util; import static com.google.common.collect.Lists.newArrayList; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.List; import com.google.common.base.Function; /** * @author Sebastian Benz - Initial contribution and API */ public class ToStringWrapper<T> implements InvocationHandler { public static class ToStringWrapperBuilder<T> { private final T toWrap; public static <T> ToStringWrapperBuilder<T> toString(T toWrap) { return new ToStringWrapperBuilder<T>(toWrap); } protected ToStringWrapperBuilder(T toWrap) { this.toWrap = toWrap; } public T with(final String identifier) { return with(new ConstantToStringFunction<T>(identifier)); } @SuppressWarnings("unchecked") public T with(ToStringFunction<T> toStringFunction) { Class<? extends Object> type = toWrap.getClass(); List<Class<?>> interfaces = newArrayList(); while (type != null) { for (Class<?> interf : type.getInterfaces()) { interfaces.add(interf); } type = type.getSuperclass(); } Object proxy = Proxy.newProxyInstance(toWrap.getClass().getClassLoader(), interfaces.toArray(new Class[interfaces.size()]), new ToStringWrapper<T>(toWrap, toStringFunction)); return (T) proxy; } } public interface ToStringFunction<T> { String describe(T toDescribe); } private final static class ConstantToStringFunction<T> implements ToStringFunction<T> { private final String identifier; private ConstantToStringFunction(String identifier) { this.identifier = identifier; } public String describe(T toDescribe) { return identifier; } } public static <T> ToStringWrapperBuilder<T> replaceToString(T toWrap) { return new ToStringWrapperBuilder<T>(toWrap); } public static <T> Function<T, T> replaceToString(final ToStringFunction<T> toStringFunction) { return new Function<T, T>() { public T apply(T from) { return replaceToString(from).with(toStringFunction); } }; } private final T toWrap; private ToStringFunction<T> toStringFunction; private ToStringWrapper(T toWrap, ToStringFunction<T> toStringFunction) { this.toWrap = toWrap; this.toStringFunction = toStringFunction; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("toString")) { return toStringFunction.describe(toWrap); } else { return method.invoke(toWrap, args); } } }