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

com.glookast.commons.templates.resolvers.AbstractSystemTemplateResolver Maven / Gradle / Ivy

package com.glookast.commons.templates.resolvers;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.DatabindContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase;
import lombok.SneakyThrows;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * This class resolves the type to be used when marshalling/unmarshalling Metadata|Storage Systems
 * In case no type is found but the base fields are present it defaults to Unsupported{Metadata|Storage}System
 * This ensures that newly added Systems can still be parsed (thus not breaking the API) but won't be fully
 * supported yet e.g.: the UI will list them as read-only
 */
public abstract class AbstractSystemTemplateResolver extends TypeIdResolverBase {

    private JavaType superType;

    @Override
    public void init(JavaType baseType) {
        superType = baseType;
    }

    @Override
    public JsonTypeInfo.Id getMechanism() {
        return JsonTypeInfo.Id.NAME;
    }

    @Override
    public String idFromValue(Object obj) {
        return idFromValueAndType(obj, obj.getClass());
    }

    @SneakyThrows
    @Override
    public String idFromValueAndType(Object obj, Class subType) {

        Optional foundTypeId = getAllRegisteredSubTypes(this.getSystemTypeClass())
            .stream()
            .filter(t -> t.value().equals(subType))
            .findFirst();

        return foundTypeId.map(JsonSubTypes.Type::name).orElse(this.getUnsupportedSystemTypeClass().getSimpleName());

    }

    @SneakyThrows
    @Override
    public JavaType typeFromId(DatabindContext context, String id) {

        Class subType = this.getUnsupportedSystemTypeClass();

        List subTypes = getAllRegisteredSubTypes(this.getSystemTypeClass());
        Optional foundSubType = subTypes
            .stream()
            .filter(t -> t.name().equals(id))
            .findFirst();

        if (foundSubType.isPresent()) {
            subType = Class.forName(foundSubType.get().value().getCanonicalName());
        }

        return context.constructSpecializedType(superType, subType);
    }

    public Class getSystemTypeClass() throws Exception {
        throw new Exception("This method must be overridden by concrete class");
    }

    public Class getUnsupportedSystemTypeClass() throws Exception {
        throw new Exception("This method must be overridden by concrete class");
    }

    private List getAllRegisteredSubTypes(Class templateTypeClass) throws Exception {
        
        Annotation[] annotations = templateTypeClass.getAnnotations();
        List subTypes = new ArrayList<>();

        for (Annotation annotation : annotations) {
            if (annotation instanceof JsonSubTypes) {
                JsonSubTypes.Type[] types = ((JsonSubTypes) annotation).value();
                subTypes.addAll(Arrays.asList(types));
                
                // check all descendants for more sub-types
                for (JsonSubTypes.Type type : types) {
                    Class subClass = Class.forName(type.value().getCanonicalName());
                    subTypes.addAll(getAllRegisteredSubTypes(subClass));
                }
                
            }
        }

        return subTypes;

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy