package org.jboss.resteasy.plugins.providers;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.regex.Pattern;
import javax.ws.rs.CookieParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
import org.jboss.resteasy.annotations.Separator;
import org.jboss.resteasy.core.ResteasyContext;
import org.jboss.resteasy.core.StringParameterInjector;
import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.spi.util.Types;
@Provider
public class MultiValuedParamConverterProvider implements ParamConverterProvider
{
private static final Pattern PROXY_REGEX = Pattern.compile("\\p{Punct}|\\[\\p{Punct}+\\]");
@SuppressWarnings("unchecked")
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations)
{
if (!isApplicable(annotations))
{
return null;
}
String separator = getSeparator(annotations);
Class<?> paramType = getHeaderParam(annotations);
if (Collection.class.isAssignableFrom(rawType))
{
if (!PROXY_REGEX.matcher(separator).matches())
{
LogMessages.LOGGER.invalidRegex(rawType.getName(), separator);
return null;
}
Class<?> type = null;
try
{
type = Types.getTypeArgument(genericType);
if (type == null)
{
return null;
}
}
catch (Exception e)
{
return null;
}
Constructor<?> constructor = getConstructor(rawType);
if (constructor == null)
{
return null;
}
ResteasyProviderFactory factory = ResteasyContext.getContextData(ResteasyProviderFactory.class);
StringParameterInjector stringParameterInjector = new StringParameterInjector(type, null, null, paramType, null, null, annotations, factory);
return (ParamConverter<T>) new MultiValuedCollectionParamConverter(stringParameterInjector, separator, constructor);
}
else if (rawType.isArray())
{
Class<?> type = rawType.getComponentType();
if (type.isArray() || Collection.class.isAssignableFrom(type))
{
return null;
}
ResteasyProviderFactory factory = ResteasyContext.getContextData(ResteasyProviderFactory.class);
StringParameterInjector stringParameterInjector = new StringParameterInjector(type, null, null, paramType, null, null, annotations, factory);
return (ParamConverter<T>) new MultiValuedArrayParamConverter(stringParameterInjector, separator, rawType);
}
return null;
}
private boolean isApplicable(Annotation[] annotations)
{
if (annotations == null)
{
return false;
}
for (Annotation a : annotations)
{
if (a instanceof Separator)
{
return true;
}
}
return false;
}
private Constructor<?> getConstructor(Class<?> clazz)
{
try
{
if (List.class.equals(clazz) || ArrayList.class.equals(clazz))
{
return ArrayList.class.getConstructor();
}
else if (SortedSet.class.equals(clazz) || TreeSet.class.equals(clazz))
{
return TreeSet.class.getConstructor();
}
else if (Set.class.equals(clazz) || HashSet.class.equals(clazz))
{
return HashSet.class.getConstructor();
}
else
{
return null;
}
}
catch (NoSuchMethodException e)
{
return null;
}
}
private String getSeparator(Annotation[] annotations)
{
for (Annotation a : annotations)
{
if (a instanceof Separator)
{
if ("".equals(((Separator) a).value()))
{
break;
}
return ((Separator) a).value();
}
}
for (Annotation a : annotations)
{
if (a instanceof CookieParam)
{
return "-";
}
}
return ",";
}
private Class<?> (Annotation[] annotations)
{
if (annotations == null)
{
return null;
}
for (Annotation a : annotations)
{
if (a instanceof HeaderParam)
{
return HeaderParam.class;
}
}
return null;
}
}