//=============================================================================
// Copyright 2006-2010 Daniel W. Dyer
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//=============================================================================
package org.uncommons.watchmaker.framework.interactive;
import java.lang.reflect.Method;
import org.uncommons.util.reflection.ReflectionUtils;
/**
* Adapter class for chaining together two renderers in series to provide
* flexibility. For example, if we have a Long -> Date renderer that turns
* a number of milliseconds since epoch into a Java date, and a Date -> String
* renderer that converts a Java date into its String representation in a
* particular locale, we can combine the two to create a Long -> String renderer
* without having to write a separate implementation of the {@link Renderer}
* interface.
* @param <T> The input type for the renderer.
* @param <S> The output type for the renderer.
* @author Daniel Dyer
*/
public class RendererAdapter<T, S> implements Renderer<T, S>
{
private final Renderer<T, ?> renderer1;
private final Renderer<?, S> renderer2;
/**
* Creates an adapter that feeds the output of renderer1 into renderer2.
* @param <R> The intermediate type when transforming objects of type T to
* objects of type S.
* @param renderer1 A renderer that will translate an object of the input type
* (T) into an object of the intermediate type (R).
* @param renderer2 A renderer that will translate an object of the intermediate type
* (R) into an object of the output type (S).
*/
public <R> RendererAdapter(Renderer<T, ? extends R> renderer1,
Renderer<R, S> renderer2)
{
this.renderer1 = renderer1;
this.renderer2 = renderer2;
}
/**
* {@inheritDoc}
*/
public S render(T entity)
{
// This reflection charade is necessary because we can't convince the
// compiler that the output of renderer1 is compatible with the input
// of renderer2 without exposing a redundant "intermediate" type parameter
// in the class definition. I don't what to do that, I'd rather have
// the ugliness encapsulated here than complicate code that uses this class.
Method renderMethod = ReflectionUtils.findKnownMethod(Renderer.class,
"render",
Object.class);
return ReflectionUtils.<S>invokeUnchecked(renderMethod,
renderer2,
renderer1.render(entity));
}
}