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

org.eclipse.ditto.base.model.signals.AnnotationBasedJsonParsable Maven / Gradle / Ivy

/*
 * Copyright (c) 2019 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.eclipse.ditto.base.model.signals;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.eclipse.ditto.json.JsonObject;
import org.eclipse.ditto.json.JsonParseException;
import org.eclipse.ditto.json.JsonRuntimeException;
import org.eclipse.ditto.base.model.exceptions.DittoJsonException;
import org.eclipse.ditto.base.model.exceptions.DittoRuntimeException;
import org.eclipse.ditto.base.model.headers.DittoHeaders;

/**
 * Responsible for deserialization of a class of type T.
 *
 * @param  the type of the class that should be deserialized.
 */
final class AnnotationBasedJsonParsable implements JsonParsable {

    private static final Class JSON_OBJECT_PARAMETER = JsonObject.class;
    private static final Class DITTO_HEADERS_PARAMETER = DittoHeaders.class;
    private static final Class PARSE_INNER_JSON_PARAMETER = ParseInnerJson.class;

    private final String key;
    private final Method parseMethod;

    /**
     * Creates a new instance.
     *
     * @param key the API v2 key for this strategy.
     * @param parsedClass the class that should be deserialized.
     * @param parsingMethodName the name of the method that should be called on the given class in order to
     * deserialize.
     */
    AnnotationBasedJsonParsable(final String key,
            final Class parsedClass,
            final String parsingMethodName) {
        this.key = key;
        try {
            this.parseMethod = getParseMethod(parsedClass, parsingMethodName);
            final Class returnType = parseMethod.getReturnType();
            if (!parsedClass.isAssignableFrom(returnType)) {
                throw new IllegalArgumentException(
                        String.format("Parse method is invalid. Return type <%s> of parse method must be assignable " +
                                "to parsed class: <%s>.", returnType.getSimpleName(), parsedClass.getSimpleName()));
            }
        } catch (final NoSuchMethodException e) {
            throw new DeserializationStrategyNotFoundError(parsedClass, e);
        }
    }

    /**
     * The API v2 key for this strategy.
     *
     * @return the API v2 key for this strategy.
     */
    public String getKey() {
        return key;
    }


    @SuppressWarnings("unchecked")
    @Override
    public T parse(final JsonObject jsonObject, final DittoHeaders dittoHeaders) {
        try {
            return (T) parseMethod.invoke(null, jsonObject, dittoHeaders);
        } catch (final ClassCastException | IllegalAccessException e) {
            throw buildDittoJsonException(e, jsonObject, dittoHeaders);
        } catch (final InvocationTargetException e) {
            throw fromInvocationTargetException(e, jsonObject, dittoHeaders);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public T parse(final JsonObject jsonObject, final DittoHeaders dittoHeaders,
            final ParseInnerJson parseInnerJson) {
        try {
            if (parseMethod.getParameterCount() == 3) {
                return (T) parseMethod.invoke(null, jsonObject, dittoHeaders, parseInnerJson);
            } else {
                return (T) parseMethod.invoke(null, jsonObject, dittoHeaders);
            }
        } catch (final ClassCastException | IllegalAccessException e) {
            throw buildDittoJsonException(e, jsonObject, dittoHeaders);
        } catch (final InvocationTargetException e) {
            throw fromInvocationTargetException(e, jsonObject, dittoHeaders);
        }
    }

    private DittoJsonException fromInvocationTargetException(final InvocationTargetException e,
            final JsonObject jsonObject,
            final DittoHeaders dittoHeaders) {
        final Throwable targetException = e.getTargetException();

        if (targetException instanceof DittoRuntimeException) {
            throw (DittoRuntimeException) targetException;
        } else if (targetException instanceof JsonRuntimeException) {
            throw new DittoJsonException((JsonRuntimeException) targetException, dittoHeaders);
        }

        return buildDittoJsonException(targetException, jsonObject, dittoHeaders);
    }

    private DittoJsonException buildDittoJsonException(final Throwable cause,
            final JsonObject jsonObject,
            final DittoHeaders dittoHeaders) {

        return new DittoJsonException(JsonParseException.newBuilder()
                .message(String.format("Error during parsing json: <%s>", jsonObject.toString()))
                .cause(cause).build(),
                dittoHeaders);
    }

    private static Method getParseMethod(final Class parsedClass, final String methodName)
            throws NoSuchMethodException {

        try {
            return parsedClass.getMethod(methodName, JSON_OBJECT_PARAMETER, DITTO_HEADERS_PARAMETER,
                    PARSE_INNER_JSON_PARAMETER);
        } catch (final NoSuchMethodException e) {
            return parsedClass.getMethod(methodName, JSON_OBJECT_PARAMETER, DITTO_HEADERS_PARAMETER);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy