Package org.jboss.aerogear.controller.util

Source Code of org.jboss.aerogear.controller.util.ParameterExtractor

/**
* JBoss, Home of Professional Open Source
* Copyright Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.jboss.aerogear.controller.util;

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.activation.MimeType;
import javax.activation.MimeTypeParseException;
import javax.servlet.http.Cookie;

import org.jboss.aerogear.controller.log.AeroGearLogger;
import org.jboss.aerogear.controller.log.ExceptionBundle;
import org.jboss.aerogear.controller.router.Consumer;
import org.jboss.aerogear.controller.router.RouteContext;
import org.jboss.aerogear.controller.router.parameter.ConstantParameter;
import org.jboss.aerogear.controller.router.parameter.Parameter;
import org.jboss.aerogear.controller.router.parameter.ReplacementParameter;
import org.jboss.aerogear.controller.router.parameter.RequestParameter;
import org.jboss.aerogear.controller.router.rest.pagination.PaginationInfo;

import br.com.caelum.iogi.Iogi;
import br.com.caelum.iogi.reflection.Target;
import br.com.caelum.iogi.util.DefaultLocaleProvider;
import br.com.caelum.iogi.util.NullDependencyProvider;

import com.google.common.base.Optional;

public class ParameterExtractor {

    private static final Iogi IOGI = new Iogi(new NullDependencyProvider(), new DefaultLocaleProvider());

    /**
     * Extracts the arguments from the current request for the target route.
     *
     * @param routeContext the {@link org.jboss.aerogear.controller.router.RouteContext}.
     * @param consumers the {@link Consumer}s that will be used to try to unmarshall the request body.
     * @return {@code Map<String, Object} containing parameter name -> value mapping.
     */
    public static Map<String, Object> extractArguments(final RouteContext routeContext, final Map<String, Consumer> consumers) throws Exception {
        final Map<String, Object> argsMap = new LinkedHashMap<String, Object>();
        final List<Parameter<?>> parameters = routeContext.getRoute().getParameters();
        final int size = parameters.size();
        for (int i = 0; i < size; i++) {
            final Parameter<?> parameter = parameters.get(i);
            switch (parameter.getParameterType()) {
                case ENTITY:
                    if (PaginationInfo.class.isAssignableFrom(parameter.getType())) {
                        break;
                    }
                    if (!addIfPresent(extractIogiParam(routeContext), "entityParam", argsMap)) {
                        argsMap.put("entityParam", extractBody(routeContext, parameter, getConsumer(routeContext, consumers, parameter)));
                    }
                    break;
                case REQUEST:
                    final RequestParameter<?> rp = (RequestParameter<?>) parameter;
                    extractRequestParam(rp.getName(), rp.getType(), rp.getDefaultValue(), argsMap, routeContext);
                    break;
                case CONSTANT:
                    final ConstantParameter<?> cp = (ConstantParameter<?>) parameter;
                    argsMap.put("constantParam-" + i, cp.getValue());
                    break;
                case REPLACEMENT:
                    final ReplacementParameter<?> replacementParam = (ReplacementParameter<?>) parameter;
                    final Map<String, Object> paramsMap = extractRequestParams(replacementParam, routeContext);
                    argsMap.put("replacementParam-" + i, RequestUtils.injectParamValues(replacementParam.getString(), paramsMap));
                    break;
            }
        }
        return argsMap;
    }
   
    private static Map<String, Object> extractRequestParam(
            final String paramName,
            final Class<?> type,
            final Optional<?> defaultValue,
            final Map<String, Object> map,
            final RouteContext routeContext) throws Exception {
        if (addIfPresent(extractParam(routeContext, paramName, type), paramName, map)) {
            return map;
        }
        if (addIfPresent(extractHeaderParam(routeContext, paramName), paramName, map)) {
            return map;
        }
        if (addIfPresent(extractCookieParam(routeContext, paramName, type), paramName, map)) {
            return map;
        }
        if (addIfPresent(extractDefaultParam(type, defaultValue), paramName, map)) {
            return map;
        }
        if (addIfPresent(extractPathParam(routeContext, paramName, type), paramName, map)) {
             return map;
        } else {
            throw ExceptionBundle.MESSAGES.missingParameterInRequest(paramName);
        }
    }
   
    private static Map<String, Object> extractRequestParams(final ReplacementParameter<?> replacementParam, final RouteContext routeContext) throws Exception {
        final Map<String, Object> map = new HashMap<String, Object>();
        for (String paramName : replacementParam.getParamNames()) {
            extractRequestParam(paramName, String.class, Optional.absent(), map, routeContext);
        }
        return map;
    }
   
    private static Optional<?> extractDefaultParam(final Class<?> type, final Optional<?> defaultValue) throws Exception {
        if(defaultValue.isPresent()) {
            return Optional.of(createInstance(type, defaultValue.get().toString()));
        }
        return Optional.absent();
    }

    private static Object extractBody(final RouteContext routeContext, final Parameter<?> parameter, final Consumer consumer) {
        return consumer.unmarshall(routeContext.getRequest(), parameter.getType());
    }
   
    private static Consumer getConsumer(final RouteContext routeContext, final Map<String, Consumer> consumers,
            final Parameter<?> parameter) {
        final Set<String> mediaTypes = routeContext.getRoute().consumes();
        final Optional<String> contentType = extractContentType(routeContext);
        if (contentType.isPresent()) {
            final Consumer consumer = consumers.get(contentType.get());
            if (consumer != null) {
                return consumer;
            }
        } else {
            for (String mediaType : mediaTypes) {
                final Consumer consumer = consumers.get(mediaType);
                if (consumer != null) {
                    return consumer;
                }
            }
        }
        throw ExceptionBundle.MESSAGES.noConsumerForMediaType(parameter, consumers.values(), mediaTypes);
    }
   
    private static Optional<String> extractContentType(final RouteContext routeContext) {
      final String contentType = routeContext.getRequest().getContentType();
      if (contentType != null) {
        try {
        MimeType mimeType = new MimeType(contentType);
        return Optional.of(mimeType.getBaseType());
      } catch (MimeTypeParseException e) {
        throw new RuntimeException("Error parsing content-type " + contentType, e);
      }
      }
      return Optional.absent();
    }
   
    public static Optional<?> extractPathParam(final RouteContext routeContext, final RequestParameter<?> param) throws Exception {
        return extractPathParam(routeContext, param.getName(), param.getType());
    }
   
    /**
     * Extracts a path parameter from the passed in request path.
     *
     * @param routeContext the {@link org.jboss.aerogear.controller.router.RouteContext} to extract a path parameter from.
     * @param paramName the name of the parameter to be extracted.
     * @param type the parameter type.
     * @return {@code Optional<String>} containing the extracted path param if present in the request path.
     */
    public static Optional<?> extractPathParam(final RouteContext routeContext, final String paramName, final Class<?> type) throws Exception {
        final String requestPath = routeContext.getRequestPath();
        final Map<String, String> pathParams = RequestUtils.mapPathParams(requestPath, routeContext.getRoute().getPath());
        if (pathParams.containsKey(paramName)) {
            final String value = pathParams.get(paramName);
            if (value != null) {
                return Optional.of(createInstance(type, pathParams.get(paramName)));
            }
        }
        return Optional.absent();
    }

    /**
     * Returns an instance of the type used in the parameter names using Iogi. </p> For example, having form parameters named
     * 'car.color', 'car.brand', this method would try to use those values to instantiate a new Car instance.
     *
     * @return {@link com.google.common.base.Optional} may contain the instantiated instance, else isPresent will return false.
     */
    public static Optional<?> extractIogiParam(final RouteContext routeContext) {
        final LinkedList<br.com.caelum.iogi.parameters.Parameter> parameters = new LinkedList<br.com.caelum.iogi.parameters.Parameter>();
        for (Map.Entry<String, String[]> entry : routeContext.getRequest().getParameterMap().entrySet()) {
            final String[] value = entry.getValue();
            if (value.length == 1) {
                parameters.add(new br.com.caelum.iogi.parameters.Parameter(entry.getKey(), value[0]));
            } else {
                AeroGearLogger.LOGGER.multivaluedParamsUnsupported();
            }
        }
        if (!parameters.isEmpty()) {
            final Class<?>[] parameterTypes = routeContext.getRoute().getTargetMethod().getParameterTypes();
            final Class<?> parameterType = parameterTypes[0];
            final Target<?> target = Target.create(parameterType, StringUtils.downCaseFirst(parameterType.getSimpleName()));
            return Optional.fromNullable(IOGI.instantiate(target,
                    parameters.toArray(new br.com.caelum.iogi.parameters.Parameter[parameters.size()])));
        }
        return Optional.absent();
    }

    private static boolean addIfPresent(final Optional<?> op, final String paramName, final Map<String, Object> args) {
        if (op.isPresent()) {
            args.put(paramName, op.get());
            return true;
        }
        return false;
    }

    private static Optional<?> extractHeaderParam(final RouteContext routeContext, final String paramName) {
        return Optional.fromNullable(routeContext.getRequest().getHeader(paramName));
    }
   
    private static Optional<?> extractCookieParam(final RouteContext routeContext, final String paramName, final Class<?> type) throws Exception {
        final Cookie[] cookies = routeContext.getRequest().getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(paramName)) {
                    return Optional.fromNullable(createInstance(type, cookie.getValue()));
                }
            }
        }
        return Optional.absent();
    }
   
    private static Optional<?> extractParam(final RouteContext routeContext, final String name, final Class<?> type) throws Exception {
        final String[] values = routeContext.getRequest().getParameterMap().get(name);
        if (values != null) {
            if (values.length == 1) {
                return Optional.of(createInstance(type, values[0]));
            } else {
                throw ExceptionBundle.MESSAGES.multivaluedParamsUnsupported(name);
            }
        }
        return Optional.absent();
    }

    private static Object createInstance(Class<?> type, String arg) throws Exception {
        final Constructor<?> constructor = type.getDeclaredConstructor(String.class);
        return constructor.newInstance(arg);
    }
}
TOP

Related Classes of org.jboss.aerogear.controller.util.ParameterExtractor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.