All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mercateo.common.rest.schemagen.link.BeanParamExtractor Maven / Gradle / Ivy

There is a newer version: 0.20.0
Show newest version
/*
 * Created on 01.06.2015
 *
 * author joerg_adler
 */
package com.mercateo.common.rest.schemagen.link;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;

import org.reflections.ReflectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

public class BeanParamExtractor {
    private final static Logger logger = LoggerFactory.getLogger(BeanParamExtractor.class);

    public Map getQueryParameters(Object bean) {
        return getQueryParameters(bean, QueryParam.class, QueryParam::value, false).asMap()
                .entrySet().stream().map(this::transformAll).collect(
                        Collectors.toMap(Param::getName, Param::getValue, (a, b) -> a));
    }

    private Param transformAll(Map.Entry> entry) {
        return new Param<>(entry.getKey(), entry.getValue().stream().toArray());
    }

    public Map getPathParameters(Object bean) {
        return getQueryParameters(bean, PathParam.class, PathParam::value, true).asMap().entrySet()
                .stream().map(this::transformFirstOnly).collect(
                        Collectors.toMap(Param::getName, Param::getValue, (a, b) -> a));
    }

    private Param transformFirstOnly(Map.Entry> entry) {
        if (entry.getValue().size() != 1) {
            throw new IllegalStateException("No single occurence of a "
                    + "PathParam annotation for name " + entry.getKey());
        }
        return new Param<>(entry.getKey(), entry.getValue().stream().findFirst().get());
    }

    private  Multimap getQueryParameters(Object bean,
            Class annotationClass, Function parameterNameExtractor,
            boolean useTemplate) {
        Multimap result = ArrayListMultimap.create();
        if (bean != null) {
            @SuppressWarnings("unchecked")
            Set fields = ReflectionUtils.getAllFields(bean.getClass(), f -> f
                    .isAnnotationPresent(annotationClass));
            for (Field field : fields) {
                A annotation = field.getAnnotation(annotationClass);
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                    logger.trace("bean parameter field {} is not public", field.getName());
                }
                try {
                    String parameterName = parameterNameExtractor.apply(annotation);

                    Object parameterValue = field.get(bean);
                    if (parameterValue != null) {
                        if (parameterValue instanceof Iterable) {
                            result.putAll(parameterName, (Iterable) parameterValue);
                        } else {
                            result.put(parameterName, parameterValue);
                        }
                    } else if (useTemplate) {
                        result.put(parameterName, "{" + parameterName + "}");
                    }
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException(e);
                }
            }
        }
        return result;
    }

    private static class Param {
        private final String name;

        private final T value;

        public Param(String name, T value) {
            this.name = name;
            this.value = value;
        }

        public String getName() {
            return name;
        }

        public T getValue() {
            return value;
        }
    }
}