ch.ifocusit.plantuml.utils.ClassUtils.java Source code

Java tutorial

Introduction

Here is the source code for ch.ifocusit.plantuml.utils.ClassUtils.java

Source

/*-
 * Plantuml builder
 *
 * Copyright (C) 2017 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 com.google.common.base.CharMatcher;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @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<Field> getField(Class container, Class aClass) {
        return Stream.of(container.getDeclaredFields())
                .filter(attr -> getConcernedTypes(attr).stream().anyMatch(fieldType -> fieldType.equals(aClass)))
                .findFirst();
    }

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

    public static Set<Class> getConcernedTypes(Method method) {
        Set<Class> 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<Class> getConcernedTypes(Parameter parameter) {
        Set<Class> classes = new HashSet<>();
        classes.add(parameter.getType());
        classes.addAll(getGenericTypes(parameter));
        return classes;
    }

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

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

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

    public static Set<Class> 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);
    }
}