package org.jboss.resteasy.core.interception;
import org.jboss.resteasy.annotations.DecorateTypes;
import org.jboss.resteasy.annotations.Decorator;
import org.jboss.resteasy.core.MediaTypeMap;
import org.jboss.resteasy.spi.interception.DecoratorProcessor;
import javax.ws.rs.core.MediaType;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.List;
/**
* Finds DecoratorProcessors and calls decorates on them by introspecting annotations.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
* @see org.jboss.resteasy.spi.interception.DecoratorProcessor
* @see org.jboss.resteasy.annotations.DecorateTypes
* @see org.jboss.resteasy.annotations.Decorator
*/
public class DecoratorMatcher
{
/**
* @param targetClass i.e. Marshaller
* @param target
* @param type i.e. a JAXB annotated class
* @param annotations i.e. method or parameter annotations
* @param mediaType
* @param <T>
* @return
*/
public <T> T decorate(Class<T> targetClass, T target, Class type, Annotation[] annotations, MediaType mediaType)
{
HashMap<Class<?>, Annotation> meta = new HashMap<Class<?>, Annotation>();
if (type != null)
{
for (Annotation annotation : type.getAnnotations())
{
if (annotation.annotationType().isAnnotationPresent(Decorator.class))
{
meta.put(annotation.annotationType(), annotation);
}
}
}
// override any class level ones
if (annotations != null)
{
for (Annotation annotation : annotations)
{
Decorator decorator = annotation.annotationType().getAnnotation(Decorator.class);
if (decorator != null && targetClass.isAssignableFrom(decorator.target()))
{
meta.put(annotation.annotationType(), annotation);
}
}
}
if (meta.size() == 0) return target;
MediaTypeMap<Class<?>> typeMap = new MediaTypeMap<Class<?>>();
for (Class<?> decoratorAnnotation : meta.keySet())
{
Decorator decorator = decoratorAnnotation.getAnnotation(Decorator.class);
String[] mediaTypes = {"*/*"};
DecorateTypes produces = decorator.processor().getAnnotation(DecorateTypes.class);
if (produces != null)
{
mediaTypes = produces.value();
}
for (String pType : mediaTypes)
{
typeMap.add(MediaType.valueOf(pType), decoratorAnnotation);
}
}
List<Class<?>> list = typeMap.getPossible(mediaType);
for (Class<?> decoratorAnnotation : list)
{
Annotation annotation = meta.get(decoratorAnnotation);
Decorator decorator = decoratorAnnotation.getAnnotation(Decorator.class);
DecoratorProcessor processor = null;
try
{
processor = decorator.processor().newInstance();
}
catch (InstantiationException e)
{
throw new RuntimeException(e.getCause());
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
target = (T) processor.decorate(target, annotation, type, annotations, mediaType);
}
return target;
}
}