nu.famroos.spring.hateoas.polymorphism.JsonRootRelProvider.java Source code

Java tutorial

Introduction

Here is the source code for nu.famroos.spring.hateoas.polymorphism.JsonRootRelProvider.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Stichting Yona Foundation This Source Code Form is subject to the terms of the Mozilla Public License, v.
 * 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *******************************************************************************/
package nu.famroos.spring.hateoas.polymorphism;

import java.lang.annotation.Annotation;
import java.util.Arrays;

import org.atteo.evo.inflector.English;
import org.springframework.hateoas.RelProvider;
import org.springframework.hateoas.core.DefaultRelProvider;

import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.annotation.JsonSubTypes;

/**
 * When an embedded resource is provided in a response using the {@code org.springframework.hateoas.Resources} model, this
 * provider can be configured at runtime to make any embedded values root json name be set based on the classes annotated
 * {@code JsonRootName ( " name " )}. By default Spring hateoas renders the embedded root field based on the class name with first
 * character in lowercase.
 */
public class JsonRootRelProvider implements RelProvider {
    public static final String EDIT_REL = "edit";

    private DefaultRelProvider defaultRelProvider = new DefaultRelProvider();

    @Override
    public String getItemResourceRelFor(Class<?> type) {
        Class<?> baseType = determineBaseType(type);
        JsonRootName rootName = getAnnotationByType(baseType, JsonRootName.class);
        return (rootName == null) ? defaultRelProvider.getItemResourceRelFor(baseType) : rootName.value();
    }

    @Override
    public String getCollectionResourceRelFor(Class<?> type) {
        return English.plural(getItemResourceRelFor(type));
    }

    @Override
    public boolean supports(Class<?> delimiter) {
        return defaultRelProvider.supports(delimiter);
    }

    private <T extends Annotation> T getAnnotationByType(Class<?> type, Class<T> annotationType) {
        T[] annotations = type.getAnnotationsByType(annotationType);
        return (annotations.length == 0) ? null : annotations[0];
    }

    private Class<?> determineBaseType(Class<?> type) {
        Class<?> baseType = type;
        while ((baseType = baseType.getSuperclass()) != null) {
            JsonSubTypes subtypesAnnotation = getAnnotationByType(baseType, JsonSubTypes.class);
            if (containsType(subtypesAnnotation, type)) {
                return baseType;
            }
        }
        return type;
    }

    private boolean containsType(JsonSubTypes subtypesAnnotation, Class<?> type) {
        return (subtypesAnnotation != null)
                && (Arrays.asList(subtypesAnnotation.value()).stream().anyMatch(t -> t.value() == type));
    }
}