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

pl.fhframework.docs.exception.service.FhDocumentedExceptionServiceImpl Maven / Gradle / Ivy

package pl.fhframework.docs.exception.service;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.stereotype.Service;
import pl.fhframework.core.FhCL;
import pl.fhframework.core.FhException;
import pl.fhframework.core.documented.DocumentedClass;
import pl.fhframework.core.documented.DocumentedConstructor;
import pl.fhframework.core.documented.DocumentedParameter;
import pl.fhframework.core.logging.FhLogger;
import pl.fhframework.docs.exception.model.DescribedClass;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * Created by k.czajkowski on 28.02.2017.
 */
@Service
public class FhDocumentedExceptionServiceImpl implements FhDocumentedExceptionService {

    @Override
    public Set findSubclasses(Class clazz, String... packageName) {
        Set subclasses = new LinkedHashSet<>();
        subclasses.add(clazz);
        for (String singlePackageName : packageName) {
            Set beanDefinitions = getBeanDefinitions(singlePackageName);
            for (BeanDefinition beanDefinition : beanDefinitions) {
                try {
                    subclasses.add(getClass(beanDefinition));
                } catch (ClassNotFoundException e) {
                    FhLogger.error("Could not load class {} ", beanDefinition.getBeanClassName());
                }
            }
        }
        return subclasses;
    }

    private Class getClass(BeanDefinition def) throws ClassNotFoundException {
        return FhCL.classLoader.loadClass(def.getBeanClassName());
    }

    private Set getBeanDefinitions(String packageName) {
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AssignableTypeFilter(FhException.class));
        return provider.findCandidateComponents(packageName);
    }

    @Override
    public Map getDescription(Collection fhExceptions) {
        Map descriptionMap = new LinkedHashMap<>(fhExceptions.size());
        for (Object obj : fhExceptions) {
            Class clazz = (Class) obj;
            String description = getDescription(clazz);
            descriptionMap.put(clazz, description);
        }
        return descriptionMap;
    }

    @Override
    public String getDescription(Class clazz) {
        DocumentedClass[] declaredAnnotations = (DocumentedClass[]) clazz.getDeclaredAnnotationsByType(DocumentedClass.class);
        for (DocumentedClass annotation : declaredAnnotations) {
            return annotation.description();
        }
        FhLogger.debug(this.getClass(), logger -> logger.log("Did not find '{}' annotation in class '{}'", DocumentedClass.class.getSimpleName(), clazz.getName()));
        return "";
    }

    @Override
    public Set createDescribedExceptions(Set exceptions) {
        Map descriptions = getDescription(exceptions);
        Set describedExceptions = new LinkedHashSet<>();
        for (Map.Entry entry : descriptions.entrySet()) {
            Class documentedExceptionClass = entry.getKey();
            String clazzSimpleName = documentedExceptionClass.getSimpleName();
            String packageName = documentedExceptionClass.getPackage().toString();
            String exceptionDescription = entry.getValue();
            DescribedClass describedException = new DescribedClass(clazzSimpleName, packageName, exceptionDescription);
            describedException.setConstructors(findDescribedConstructors(documentedExceptionClass));
            describedExceptions.add(describedException);
        }
        return describedExceptions;
    }

    private List findDescribedConstructors(Class clazz) {
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        List describedConstructors = new LinkedList<>();
        for (Constructor constructor : declaredConstructors) {
            int modifiers = constructor.getModifiers();
            if (modifiers == 1) { //we want to document only public constructors
                DocumentedConstructor documentedConstructor = constructor.getDeclaredAnnotation(DocumentedConstructor.class);
                try {
                    DescribedClass.DescribedConstructor describedConstructor = createDescribedConstructor(clazz, modifiers, documentedConstructor);
                    describedConstructors.add(describedConstructor);
                } catch (NullPointerException e) {
                    //only log missing annotation,
                    FhLogger.debug(this.getClass(), logger -> logger.log("Did not find documentation for constructor {}", constructor));
                }
            }
        }
        return describedConstructors;
    }

    private DescribedClass.DescribedConstructor createDescribedConstructor(Class clazz, int modifiers, DocumentedConstructor documentedConstructor) {
        String description = documentedConstructor.description();
        DocumentedParameter[] parameters = documentedConstructor.parameters();
        List describedParameters = createDescribedParameters(parameters);
        String declaration = createConstructorDeclaration(clazz, modifiers, describedParameters);
        return createDescribedConstructor(description, describedParameters, declaration);
    }

    private DescribedClass.DescribedConstructor createDescribedConstructor(String description, List describedParameters, String declaration) {
        DescribedClass.DescribedConstructor describedConstructor = new DescribedClass.DescribedConstructor(declaration, description);
        describedConstructor.setParameters(describedParameters);
        return describedConstructor;
    }

    private List createDescribedParameters(DocumentedParameter[] params) {
        List describedParameters = new LinkedList<>();
        for (DocumentedParameter parameter : params) {
            describedParameters.add(new DescribedClass.DescribedParameter(parameter.className(), parameter.parameterName(), parameter.description()));
        }
        return describedParameters;
    }

    private String createConstructorDeclaration(Class clazz, int modifiers, List parameters) {
        StringBuilder sb = new StringBuilder(Modifier.toString(modifiers));
        sb.append(" ");
        sb.append(clazz.getSimpleName());
        sb.append("(");

        for(Iterator iterator = parameters.iterator(); iterator.hasNext();) {
            DescribedClass.DescribedParameter parameter = iterator.next();
            sb.append(parameter.getClassName());
            sb.append(" ");
            sb.append(parameter.getParameterName());
            if (iterator.hasNext()) {
                sb.append(", ");
            }
        }
        sb.append(")");
        return sb.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy