/*
* Copyright 2013 cruxframework.org.
*
* 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.cruxframework.crux.core.server.rest.core.dispatch;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.cruxframework.crux.core.server.rest.core.dispatch.MethodInvoker.RestParameterType;
import org.cruxframework.crux.core.server.rest.spi.BadRequestException;
import org.cruxframework.crux.core.server.rest.spi.HttpRequest;
import org.cruxframework.crux.core.server.rest.spi.InternalServerErrorException;
import org.cruxframework.crux.core.utils.ClassUtils;
import org.cruxframework.crux.core.utils.ClassUtils.PropertyInfo;
/**
* @author Thiago da Rosa de Bustamante
*
*/
class GroupValueInjector implements ValueInjector
{
protected ValueInjector[] params;
private PropertyInfo[] properties;
private final Class<?> baseClass;
public GroupValueInjector(RestParameterType restParameterType, Type type, String paramPrefix)
{
this.baseClass = ClassUtils.getRawType(type);
if (!isAllowedComplexType(baseClass))
{
throw new InternalServerErrorException("Invalid rest parameter for rest method: " + baseClass.getCanonicalName() + ". Type not allowed for " +
"this type of parameter. It can only be passed as a body parameter", "Can not execute requested service");
}
List<PropertyInfo> writeableProperties = new ArrayList<PropertyInfo>();
PropertyInfo[] properties = ClassUtils.extractBeanPropertiesInfo(type);
List<ValueInjector> injectors = new ArrayList<ValueInjector>();
if (properties != null)
{
for (PropertyInfo property : properties)
{
if (property.getWriteMethod() != null)
{
writeableProperties.add(property);
Type propertyType = property.getType();
if (ClassUtils.isSimpleType(propertyType))
{
switch (restParameterType)
{
case query:
injectors.add(new QueryParamInjector(propertyType, getParamName(paramPrefix, property.getName()), null));
break;
case header:
injectors.add(new HeaderParamInjector(propertyType, getParamName(paramPrefix, property.getName()), null));
break;
case form:
injectors.add(new FormParamInjector(propertyType, getParamName(paramPrefix, property.getName()), null));
break;
case cookie:
injectors.add(new CookieParamInjector(propertyType, getParamName(paramPrefix, property.getName()), null));
break;
case path:
injectors.add(new PathParamInjector(propertyType, getParamName(paramPrefix, property.getName()), null));
break;
default:
break;
}
}
else
{
injectors.add(new GroupValueInjector(restParameterType, propertyType, getParamName(paramPrefix, property.getName())));
}
}
}
}
params = injectors.toArray(new ValueInjector[injectors.size()]);
this.properties = writeableProperties.toArray(new PropertyInfo[writeableProperties.size()]);
}
private boolean isAllowedComplexType(Class<?> type)
{
if (type.isArray() || Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type))
{
return false;
}
return true;
}
private String getParamName(String paramPrefix, String name)
{
StringBuilder builder = new StringBuilder();
if (paramPrefix!= null && paramPrefix.trim().length() > 0)
{
builder.append(paramPrefix);
if (!paramPrefix.endsWith("."))
{
builder.append(".");
}
}
builder.append(name);
return builder.toString();
}
@Override
public Object inject(HttpRequest request)
{
Object result;
try
{
result = baseClass.newInstance();
for (int i=0; i< params.length; i++)
{
properties[i].getWriteMethod().invoke(result, params[i].inject(request));
}
}
catch (Exception e)
{
throw new BadRequestException("Can not read request values for ValueObject parameter: " + baseClass.getCanonicalName(),
"Can not read request parameter for path: " + request.getUri().getPath(), e);
}
return result;
}
}