/**
* Copyright 2005-2014 Restlet
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can
* select the license that you prefer but you may not use this file except in
* compliance with one of these Licenses.
*
* You can obtain a copy of the Apache 2.0 license at
* http://www.opensource.org/licenses/apache-2.0
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://restlet.com/products/restlet-framework
*
* Restlet is a registered trademark of Restlet S.A.S.
*/
package org.restlet.ext.jaxrs.internal.wrappers.params;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.logging.Logger;
import javax.ws.rs.WebApplicationException;
import org.restlet.Request;
import org.restlet.ext.jaxrs.internal.exceptions.ConvertRepresentationException;
import org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList.ParamGetter;
import org.restlet.representation.Representation;
/**
* An {@link EntityGetter} for Restlet {@link Representation}s.
*
* @author Stephan Koops
*/
public abstract class ReprEntityGetter implements ParamGetter {
/**
* EntityGetter, if there is a constructor with two arguments: Class and
* Representation
*/
static class ClassReprEntityGetter extends ReprEntityGetter {
private final Class<?> clazz;
ClassReprEntityGetter(Class<?> genClass, Constructor<?> constructor) {
super(constructor);
this.clazz = genClass;
}
@Override
Representation createInstance(Representation entity)
throws IllegalArgumentException, InstantiationException,
IllegalAccessException, InvocationTargetException {
return this.constr.newInstance(this.clazz, entity);
}
}
/**
* EntityGetter, if Representation could directly be injected
*/
static class DirectReprEntityGetter implements ParamGetter {
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList.ParamGetter#getValue()
*/
public Object getValue() throws InvocationTargetException,
ConvertRepresentationException, WebApplicationException {
return Request.getCurrent().getEntity();
}
}
/**
* EntityGetter, if there is a constructor with two arguments:
* Representation and Class
*/
static class ReprClassEntityGetter extends ReprEntityGetter {
private final Class<?> clazz;
ReprClassEntityGetter(Constructor<?> constructor, Class<?> genClass) {
super(constructor);
this.clazz = genClass;
}
@Override
Representation createInstance(Representation entity)
throws IllegalArgumentException, InstantiationException,
IllegalAccessException, InvocationTargetException {
return this.constr.newInstance(entity, this.clazz);
}
}
/**
* EntityGetter, if there is a constructor for only the entity.
*/
static class ReprOnlyEntityGetter extends ReprEntityGetter {
/**
* @param constructor
*/
ReprOnlyEntityGetter(Constructor<?> constructor) {
super(constructor);
}
@Override
Representation createInstance(Representation entity)
throws IllegalArgumentException, InstantiationException,
IllegalAccessException, InvocationTargetException {
return this.constr.newInstance(entity);
}
}
/**
* Creates an EntityGetter for the given values, or null, if it is not
* available.
*
* @param representationType
* @param convToGen
* @param logger
* @return the ParamGetter
*/
public static ParamGetter create(Class<?> representationType,
Type convToGen, Logger logger) {
if (representationType.equals(Representation.class)) {
return new DirectReprEntityGetter();
}
try {
return new ReprOnlyEntityGetter(
representationType.getConstructor(Representation.class));
} catch (SecurityException e) {
logger.warning("The constructor " + representationType
+ "(Representation) is not accessable.");
} catch (NoSuchMethodException e) {
// try next
}
if (!(convToGen instanceof ParameterizedType)) {
return null;
}
final ParameterizedType pType = (ParameterizedType) convToGen;
final Type[] typeArgs = pType.getActualTypeArguments();
if (typeArgs.length != 1) {
return null;
}
final Type typeArg = typeArgs[0];
if (!(typeArg instanceof Class<?>)) {
return null;
}
final Class<?> genClass = (Class<?>) typeArg;
try {
return new ReprClassEntityGetter(representationType.getConstructor(
Representation.class, Class.class), genClass);
} catch (SecurityException e) {
logger.warning("The constructor " + representationType
+ "(Representation) is not accessable.");
} catch (NoSuchMethodException e) {
// try next
}
try {
return new ClassReprEntityGetter(genClass,
representationType.getConstructor(Class.class,
Representation.class));
} catch (SecurityException e) {
logger.warning("The constructor " + representationType
+ "(Representation) is not accessable.");
return null;
} catch (NoSuchMethodException e) {
return null;
}
}
final Constructor<? extends Representation> constr;
@SuppressWarnings("unchecked")
ReprEntityGetter(Constructor<?> constr) {
this.constr = (Constructor<? extends Representation>) constr;
}
abstract Representation createInstance(Representation entity)
throws IllegalArgumentException, InstantiationException,
IllegalAccessException, InvocationTargetException;
/**
* @return the class of the {@link Representation}.
*/
private Class<? extends Representation> getReprClass() {
return this.constr.getDeclaringClass();
}
/**
* @see org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList.ParamGetter#getValue()
*/
public Object getValue() throws InvocationTargetException,
ConvertRepresentationException, WebApplicationException {
try {
final Request request = Request.getCurrent();
if (!request.isEntityAvailable()
|| request.getEntity().getSize() == 0) {
return null;
}
final Representation entity = request.getEntity();
if ((entity == null)/* || (entity is not empty) */) {
return null;
}
return createInstance(entity);
} catch (IllegalArgumentException e) {
throw ConvertRepresentationException.object(getReprClass(),
"the message body", e);
} catch (InstantiationException e) {
throw ConvertRepresentationException.object(getReprClass(),
"the message body", e);
} catch (IllegalAccessException e) {
throw ConvertRepresentationException.object(getReprClass(),
"the message body", e);
}
}
}