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

ru.tinkoff.kora.test.extension.junit5.GraphUtils Maven / Gradle / Ivy

The newest version!
package ru.tinkoff.kora.test.extension.junit5;

import ru.tinkoff.kora.application.graph.ApplicationGraphDraw;
import ru.tinkoff.kora.application.graph.Node;
import ru.tinkoff.kora.application.graph.Wrapped;
import ru.tinkoff.kora.common.Tag;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

final class GraphUtils {

    private static final Class[] TAG_ANY = new Class[]{Tag.Any.class};

    private GraphUtils() {}

    static  Set> findNodeByType(ApplicationGraphDraw graph, GraphCandidate candidate) {
        return findNodeByType(graph, candidate.type(), candidate.tagsAsArray());
    }

    @SuppressWarnings("unchecked")
    static  Set> findNodeByType(ApplicationGraphDraw graph, Type type, Class[] tags) {
        if (tags == null || tags.length == 0) {
            final Node node = (Node) graph.findNodeByType(type);
            return (node == null)
                ? Set.of()
                : Set.of(node);
        } else if (Arrays.equals(TAG_ANY, tags)) {
            final Set> nodes = new HashSet<>();
            for (var graphNode : graph.getNodes()) {
                if (graphNode.type().equals(type)) {
                    nodes.add((Node) graphNode);
                } else {
                    final Type unwrappedType = unwrap(graphNode.type());
                    if (unwrappedType.equals(type)) {
                        nodes.add((Node) graphNode);
                    }
                }
            }
            return nodes;
        } else {
            for (var graphNode : graph.getNodes()) {
                if (Arrays.equals(tags, graphNode.tags())) {
                    if (graphNode.type().equals(type)) {
                        return Set.of((Node) graphNode);
                    } else {
                        final Type unwrappedType = unwrap(graphNode.type());
                        if (unwrappedType.equals(type)) {
                            return Set.of((Node) graphNode);
                        }
                    }
                }
            }
        }

        return Set.of();
    }

    static Set> findNodeByTypeOrAssignable(ApplicationGraphDraw graph, GraphCandidate candidate) {
        return findNodeByTypeOrAssignable(graph, candidate.type(), candidate.tagsAsArray());
    }

    static Set> findNodeByTypeOrAssignable(ApplicationGraphDraw graph, Type type, Class[] tags) {
        if (tags == null || tags.length == 0) {
            final Set> nodes = new HashSet<>();
            for (var graphNode : graph.getNodes()) {
                Type graphType = graphNode.type();
                if (graphType.equals(type)) {
                    nodes.add(graphNode);
                } else {
                    final Type unwrappedType = unwrap(graphType);
                    if (unwrappedType.equals(type)) {
                        nodes.add(graphNode);
                        graphType = unwrappedType;
                    }
                }

                var typeClass = tryCastType(type);
                var graphClass = tryCastType(graphType);
                if (typeClass.isPresent() && graphClass.isPresent() && typeClass.get().isAssignableFrom(graphClass.get())) {
                    nodes.add(graphNode);
                }
            }

            return nodes;
        } else if (Arrays.equals(TAG_ANY, tags)) {
            final Set> nodes = new HashSet<>();
            for (var graphNode : graph.getNodes()) {
                Type graphType = graphNode.type();
                if (graphType.equals(type)) {
                    nodes.add(graphNode);
                } else {
                    final Type unwrappedType = unwrap(graphType);
                    if (unwrappedType.equals(type)) {
                        nodes.add(graphNode);
                        graphType = unwrappedType;
                    }
                }

                var typeClass = tryCastType(type);
                var graphClass = tryCastType(graphType);
                if (typeClass.isPresent() && graphClass.isPresent() && typeClass.get().isAssignableFrom(graphClass.get())) {
                    nodes.add(graphNode);
                }
            }

            return nodes;
        } else {
            for (var graphNode : graph.getNodes()) {
                if (Arrays.equals(tags, graphNode.tags())) {
                    if (graphNode.type().equals(type)) {
                        return Set.of(graphNode);
                    } else {
                        final Type unwrappedType = unwrap(graphNode.type());
                        if (unwrappedType.equals(type)) {
                            return Set.of(graphNode);
                        }
                    }

                    var typeClass = tryCastType(type);
                    var graphClass = tryCastType(graphNode.type());
                    var graphClassUnwrapped = tryCastType(graphNode.type());
                    if (typeClass.isPresent() && graphClass.isPresent() && typeClass.get().isAssignableFrom(graphClass.get())) {
                        return Set.of(graphNode);
                    } else if (typeClass.isPresent() && graphClassUnwrapped.isPresent() && typeClass.get().isAssignableFrom(graphClassUnwrapped.get())) {
                        return Set.of(graphNode);
                    }
                }
            }
        }

        return Set.of();
    }

    static Type unwrap(Type type) {
        if (type instanceof Class tc && Wrapped.class.isAssignableFrom(tc)) {
            return Arrays.stream(tc.getGenericInterfaces())
                .filter(i -> i instanceof ParameterizedType)
                .filter(i -> ((ParameterizedType) i).getRawType() instanceof Class rt && Wrapped.class.isAssignableFrom(rt))
                .findFirst()
                .map(i -> ((ParameterizedType) i).getActualTypeArguments()[0])
                .filter(arg -> arg instanceof Class)
                .orElse(type);
        } else if (type instanceof ParameterizedType pt && pt.getRawType() instanceof Class pct && Wrapped.class.isAssignableFrom(pct)) {
            return pt.getActualTypeArguments()[0];
        } else {
            return type;
        }
    }

    static Optional> tryCastType(Type type) {
        try {
            if (type instanceof Class tc) {
                return Optional.of(tc);
            } else if (type instanceof ParameterizedType tp) {
                return (tp.getRawType() instanceof Class)
                    ? Optional.ofNullable(((Class) tp.getRawType()))
                    : Optional.ofNullable(KoraJUnit5Extension.class.getClassLoader().loadClass(tp.getRawType().getTypeName()));
            } else {
                return Optional.empty();
            }
        } catch (ClassNotFoundException e) {
            return Optional.empty();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy