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

com.envimate.mapmate.deserialization.Deserializer Maven / Gradle / Ivy

Go to download

MapMate is a modern mapping framework in the scope of mapping data in Json, XML, or YAML format into DTOs composed and vice versa.

There is a newer version: 1.6.8
Show newest version
/*
 * Copyright (C) 2017 [Richard Hauswald, Nune Isabekyan] (envimate GmbH - https://envimate.com/)
 */

package com.envimate.mapmate.deserialization;

import com.envimate.mapmate.*;
import com.envimate.mapmate.infra.Marshaller;
import com.envimate.mapmate.validation.AggregatedValidationException;
import com.envimate.mapmate.validation.ExceptionTracker;
import com.envimate.mapmate.validation.ExceptionTracker.ExceptionEntry;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.regex.Pattern;

@SuppressWarnings({"unchecked", "CastToConcreteClass", "rawtypes"})
public final class Deserializer {

    private static final Pattern COMPILE = Pattern.compile("\"");
    private final Definitions definitions;
    private final Marshaller marshaller;

    Deserializer(final Marshaller marshaller, final Definitions definitions) {
        this.marshaller = marshaller;
        this.definitions = definitions;
    }

    public static DeserializerBuilder aDeserializer() {
        return new DeserializerBuilder();
    }

    public  T deserialize(final String input, final Class targetType) {
        Objects.requireNonNull(input, "input cannot be null");
        final ExceptionTracker exceptionTracker = new ExceptionTracker();

        final T deserialized = deserialize(input, targetType, exceptionTracker);

        final Set exceptions = exceptionTracker.resolve();
        if (!exceptions.isEmpty()) {
            throw AggregatedValidationException.fromSet(exceptions);
        }

        return deserialized;
    }

    private  T deserialize(final String input, final Class targetType, final ExceptionTracker exceptionTracker) {
        Objects.requireNonNull(input);
        if (input.isEmpty()) {
            return null;
        }

        final Definition definition = this.definitions.getDefinitionForType(targetType);
        if (definition == null) {
            throw DefinitionNotFoundException.definitionNotFound(targetType);
        }

        final String trimmedInput = input.trim();
        if (targetType.isArray() || Collection.class.isAssignableFrom(targetType)) {
            final List listInput = this.marshaller.unmarshal(trimmedInput, List.class);
            return deserializeArray(listInput, targetType, exceptionTracker);
        } else if (definition.isAggregate()) {
            final Map parsedInput = this.marshaller.unmarshal(trimmedInput, Map.class);
            return deserialize(parsedInput, targetType, exceptionTracker);
        } else if (definition.isCustomType()) {
            return deserializeCustomType(COMPILE.matcher(trimmedInput).replaceAll(""), targetType, exceptionTracker);
        } else {
            return null;
        }
    }

    private  T deserialize(final Map input, final Class targetType, final ExceptionTracker exceptionTracker) {
        final Definition definition = this.definitions.getDefinitionForType(targetType);
        return deserializeAggregate(input, (Aggregate) definition, exceptionTracker);
    }

    private  T deserializeCustomType(final String input,
                                        final Class targetType,
                                        final ExceptionTracker exceptionTracker) {
        final Definition definition = this.definitions.getDefinitionForType(targetType);
        final CustomType customType = (CustomType) definition;

        return (T) deserializeCustomType(input, customType, exceptionTracker);
    }

    private  T deserializeCustomType(final String input,
                                        final CustomType definition,
                                        final ExceptionTracker exceptionTracker) {
        try {
            return (T) definition.deserialize(input);
        } catch (final FailedToDeserializeException e) {
            exceptionTracker.track(e.getTargetCause());
            return null;
        }
    }

    @SuppressWarnings("ChainOfInstanceofChecks")
    private  T deserializeAggregate(final Map input,
                                       final Aggregate definition,
                                       final ExceptionTracker exceptionTracker) {
        final Aggregate aggregate = definition;
        if (aggregate.hasAdapter()) {
            return (T) aggregate.getAdapter().deserialize(input, this, exceptionTracker);
        }
        final Method factoryMethod = aggregate.getFactoryMethod();
        final Parameter[] parameters = factoryMethod.getParameters();
        final Object[] arguments = new Object[parameters.length];

        for (int i = 0; i < parameters.length; i++) {
            final Parameter parameter = parameters[i];
            final Object value = input.get(parameter.getName());

            Object argument = null;
            if (value instanceof String) {
                argument = deserialize((String) value,
                        parameter.getType(),
                        exceptionTracker.stepInto(parameter.getName()));
            } else if (value instanceof Map) {
                argument = deserialize((Map) value,
                        parameter.getType(),
                        exceptionTracker.stepInto(parameter.getName()));
            } else if (value instanceof List) {
                argument = deserializeArray((List) value,
                        parameter.getType(),
                        exceptionTracker.stepInto(parameter.getName()));
            }
            arguments[i] = argument;
        }

        try {
            return (T) factoryMethod.invoke(null, arguments);
        } catch (final InvocationTargetException e) {
            exceptionTracker.track(e.getTargetException());
            return null;
        } catch (IllegalArgumentException | IllegalAccessException | NullPointerException | ExceptionInInitializerError e) {
            throw DeserializationException.fromException(e);
        }
    }

    public  T deserializeArray(final List input, final Class targetType, final ExceptionTracker exceptionTracker) {
        final Object[] output = (Object[]) Array.newInstance(targetType.getComponentType(), input.size());

        for (int i = 0; i < input.size(); i++) {
            final Object value = input.get(i);
            final String indexIndication = String.format("[%s]", i);
            if (value instanceof Map) {
                output[i] = deserialize(
                        (Map) input.get(i),
                        targetType.getComponentType(),
                        exceptionTracker.stepInto(indexIndication));
            } else {
                output[i] = deserialize(
                        (String) input.get(i),
                        targetType.getComponentType(),
                        exceptionTracker.stepInto(indexIndication));
            }
        }

        return (T) output;
    }

    public Definitions getDefinitions() {
        return this.definitions;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy