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

ch.ifocusit.plantuml.utils.ClassUtils Maven / Gradle / Ivy

/*-
 * Plantuml builder
 *
 * Copyright (C) 2023 Focus IT
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package ch.ifocusit.plantuml.utils;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.common.base.CharMatcher;

/**
 * @author Julien Boz
 */
public class ClassUtils extends org.apache.commons.lang3.ClassUtils {

    public static final String GENERICS_OPEN = "<";
    public static final String GENERICS_CLOSE = ">";
    public static final String GENERICS_SEP = ", ";
    public static final String DOLLAR = "$";

    public static String getSimpleName(Class aClass) {
        return _getSimpleName(aClass);
    }

    public static String _getSimpleName(Class aClass) {
        String className = aClass.getSimpleName();
        int lastDollarSign = className.lastIndexOf(DOLLAR);
        if (lastDollarSign != -1) {
            String innerClassName = className.substring(lastDollarSign + 1);
            // local and anonymous classes are prefixed with number (1,2,3...), anonymous classes
            // are
            // entirely numeric whereas local classes have the user supplied name as a suffix
            return CharMatcher.digit().trimLeadingFrom(innerClassName);
        }
        return className;
    }

    public static String getSimpleName(Type type) {
        if (type instanceof ParameterizedType) {
            ParameterizedType genericType = (ParameterizedType) type;
            return getSimpleName(genericType.getRawType()) + getParameterizedTypeName(genericType);
        }
        if (type instanceof Class) {
            return _getSimpleName((Class) type);
        }
        return type.getTypeName();
    }

    public static String getParameterizedTypeName(ParameterizedType genericType) {
        // manage generics
        String subtypes = Stream.of(genericType.getActualTypeArguments())
                .map(ClassUtils::getSimpleName).collect(Collectors.joining(GENERICS_SEP));
        return GENERICS_OPEN + subtypes + GENERICS_CLOSE;
    }

    public static boolean isCollection(Class aClass) {
        return Collection.class.isAssignableFrom(aClass);
    }

    public static Optional getField(Class container, Class aClass) {
        return Stream.of(container.getDeclaredFields()).filter(attr -> getConcernedTypes(attr)
                .stream().anyMatch(fieldType -> fieldType.equals(aClass))).findFirst();
    }

    public static Set getConcernedTypes(Field field) {
        Set classes = new HashSet<>();
        classes.add(field.getType());
        classes.addAll(getGenericTypes(field));
        return classes;
    }

    public static Set getConcernedTypes(Method method) {
        Set classes = new HashSet<>();
        // manage returned types
        classes.add(method.getReturnType());
        classes.addAll(getGenericTypes(method));
        // manage parameters types
        for (Parameter parameter : method.getParameters()) {
            classes.addAll(getConcernedTypes(parameter));
        }
        return classes;
    }

    public static Set getConcernedTypes(Parameter parameter) {
        Set classes = new HashSet<>();
        classes.add(parameter.getType());
        classes.addAll(getGenericTypes(parameter));
        return classes;
    }

    public static Set getGenericTypes(ParameterizedType type) {
        return Stream.of(type.getActualTypeArguments()).filter(Class.class::isInstance)
                .map(Class.class::cast).collect(Collectors.toSet());
    }

    public static Set getGenericTypes(Field field) {
        if (field.getGenericType() instanceof ParameterizedType) {
            // manage generics
            return getGenericTypes((ParameterizedType) field.getGenericType());
        }
        return new HashSet<>();
    }

    public static Set getGenericTypes(Method method) {
        if (method.getGenericReturnType() instanceof ParameterizedType) {
            // manage generics
            return getGenericTypes((ParameterizedType) method.getGenericReturnType());
        }
        return new HashSet<>();
    }

    public static Set getGenericTypes(Parameter parameter) {
        if (parameter.getParameterizedType() instanceof ParameterizedType) {
            // manage generics
            return getGenericTypes((ParameterizedType) parameter.getParameterizedType());
        }
        return new HashSet<>();
    }

    public static boolean isGetter(Method method) {
        try {
            return Stream
                    .of(Introspector.getBeanInfo(method.getDeclaringClass())
                            .getPropertyDescriptors())
                    .map(desc -> desc.getReadMethod()).filter(Objects::nonNull)
                    .anyMatch(getter -> getter.equals(method));
        } catch (IntrospectionException e) {
            throw new IllegalStateException(e);
        }
    }

    public static boolean isSetter(Method method) {
        try {
            return Stream
                    .of(Introspector.getBeanInfo(method.getDeclaringClass())
                            .getPropertyDescriptors())
                    .map(desc -> desc.getWriteMethod()).filter(Objects::nonNull)
                    .anyMatch(setter -> setter.equals(method));
        } catch (IntrospectionException e) {
            throw new IllegalStateException(e);
        }
    }

    public static boolean isNotGetterSetter(Method method) {
        return !isGetter(method) && !isSetter(method);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy