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

poussecafe.doc.model.processstepdoc.ProcessStepDocExtractor Maven / Gradle / Ivy

There is a newer version: 0.29.0
Show newest version
package poussecafe.doc.model.processstepdoc;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import jdk.javadoc.doclet.DocletEnvironment;
import poussecafe.doc.ClassDocPredicates;
import poussecafe.doc.Logger;
import poussecafe.doc.model.AnnotationsResolver;
import poussecafe.doc.model.BoundedContextComponentDoc;
import poussecafe.doc.model.ComponentDoc;
import poussecafe.doc.model.ComponentDocFactory;
import poussecafe.doc.model.DocletAccess;
import poussecafe.doc.model.boundedcontextdoc.BoundedContextDocId;
import poussecafe.doc.model.domainprocessdoc.ComponentMethodName;
import poussecafe.doc.model.domainprocessdoc.DomainProcessDocFactory;
import poussecafe.domain.DomainEvent;
import poussecafe.domain.Service;
import poussecafe.exception.PousseCafeException;

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;

public class ProcessStepDocExtractor implements Service {

    public List extractProcessStepDocs(BoundedContextDocId boundedContextDocId, TypeElement classDoc) {
        List stepDocs = new ArrayList<>();
        for(ExecutableElement methodDoc : docletAccess.methods(classDoc)) {
            if(isProcessStep(methodDoc)) {
                List customStepSignatures = annotationsResolver.step(methodDoc);
                if(!customStepSignatures.isEmpty()) {
                    stepDocs.addAll(extractCustomSteps(boundedContextDocId, methodDoc));
                } else {
                    stepDocs.add(extractDeclaredStep(boundedContextDocId, methodDoc));
                }
            }
        }
        return stepDocs;
    }

    private DocletAccess docletAccess;

    private boolean isProcessStep(ExecutableElement methodDoc) {
        if(domainProcessDocFactory.isDomainProcessDoc((TypeElement) methodDoc.getEnclosingElement())) {
            return annotationsResolver.isStep(methodDoc);
        } else {
            Optional consumedMessage = consumedMessageExtractor.consumedMessage(methodDoc);
            List producedEvents = extractProducedEvents(methodDoc);
            return annotationsResolver.isStep(methodDoc) ||
                    (docletAccess.isPublic(methodDoc) && (consumedMessage.isPresent() || !producedEvents.isEmpty()));
        }
    }

    private DomainProcessDocFactory domainProcessDocFactory;

    private AnnotationsResolver annotationsResolver;

    private ConsumedMessageExtractor consumedMessageExtractor;

    private List extractProducedEvents(ExecutableElement methodDoc) {
        return annotationsResolver.event(methodDoc);
    }

    private List extractCustomSteps(BoundedContextDocId boundedContextDocId,
            ExecutableElement methodDoc) {
        List stepDocs = new ArrayList<>();
        List methodSignatures = customStepsSignatures(methodDoc);
        for(StepMethodSignature signature : methodSignatures) {
            Logger.info("Extracting custom step " + signature);
            ProcessStepDocId messageListenerDocId = new ProcessStepDocId(signature.toString());
            BoundedContextComponentDoc boundedContextComponentDoc = new BoundedContextComponentDoc.Builder()
                    .boundedContextDocId(boundedContextDocId)
                    .componentDoc(new ComponentDoc.Builder()
                            .name(signature.toString())
                            .description(annotationsResolver.renderCommentBody(methodDoc))
                            .build())
                    .build();
            ProcessStepDoc processStepDoc = messageListenerDocFactory.createMessageListenerDoc(messageListenerDocId,
                    boundedContextComponentDoc);
            processStepDoc.attributes().processName().value(processName(methodDoc));
            processStepDoc.attributes().stepMethodSignature().nonOptionalValue(signature);
            processStepDoc.attributes().producedEvents().value(new HashSet<>(annotationsResolver.event(methodDoc)));
            processStepDoc.attributes().fromExternals().value(new HashSet<>(annotationsResolver.fromExternal(methodDoc)));
            processStepDoc.attributes().toExternals().value(new HashSet<>(annotationsResolver.toExternal(methodDoc)));
            stepDocs.add(processStepDoc);
        }
        return stepDocs;
    }

    private List customStepsSignatures(ExecutableElement methodDoc) {
        List customStepSignatures = annotationsResolver.step(methodDoc);
        if(domainProcessDocFactory.isDomainProcessDoc((TypeElement) methodDoc.getEnclosingElement())) {
            if(customStepSignatures.size() != 1) {
                throw new PousseCafeException("Domain processes listeners must be tagged with a single step");
            }
            Optional consumedEvent = consumedEvent(methodDoc);
            ComponentMethodName componentMethodName = ComponentMethodName.parse(customStepSignatures.get(0));
            return asList(new StepMethodSignature.Builder()
                    .componentMethodName(componentMethodName)
                    .consumedMessageName(consumedEvent)
                    .build());
        } else {
            return customStepSignatures.stream().map(StepMethodSignature::parse).collect(toList());
        }
    }

    private Optional consumedEvent(ExecutableElement methodDoc) {
        List parameters = methodDoc.getParameters();
        if(parameters.isEmpty()) {
            return Optional.empty();
        }

        TypeMirror firstParameterType = parameters.get(0).asType();
        Element firstParameterElement = docletEnvironment.getTypeUtils().asElement(firstParameterType);
        if(firstParameterElement instanceof TypeElement) {
            TypeElement firstParameterTypeElement = (TypeElement) firstParameterElement;
            if(classDocPredicates.documentsWithSuperinterface(firstParameterTypeElement, DomainEvent.class)) {
                return Optional.of(firstParameterTypeElement.getQualifiedName().toString());
            } else {
                return Optional.empty();
            }
        } else {
            return Optional.empty();
        }
    }

    private DocletEnvironment docletEnvironment;

    private ClassDocPredicates classDocPredicates;

    private ProcessStepDocFactory messageListenerDocFactory;

    private Optional processName(ExecutableElement methodDoc) {
        TypeElement containingClass = (TypeElement) methodDoc.getEnclosingElement();
        List processNames = annotationsResolver.process(methodDoc);
        if(domainProcessDocFactory.isDomainProcessDoc(containingClass)) {
            return Optional.of(domainProcessDocFactory.name(containingClass));
        } else if(!processNames.isEmpty()) {
            return Optional.of(processNames.get(0));
        } else {
            return Optional.empty();
        }
    }

    private ProcessStepDoc extractDeclaredStep(BoundedContextDocId boundedContextDocId,
            ExecutableElement methodDoc) {
        Logger.info("Extracting declared step from method " + methodDoc.getSimpleName().toString());
        Optional consumedMessage = consumedMessageExtractor.consumedMessage(methodDoc);
        TypeElement enclosingType = (TypeElement) methodDoc.getEnclosingElement();
        StepMethodSignature stepMethodSignature = new StepMethodSignature.Builder()
                .componentMethodName(new ComponentMethodName.Builder()
                        .componentName(enclosingType.getSimpleName().toString())
                        .methodName(methodDoc.getSimpleName().toString())
                        .build())
                .consumedMessageName(consumedMessage)
                .build();
        ProcessStepDocId id = new ProcessStepDocId(stepMethodSignature);
        BoundedContextComponentDoc boundedContextComponentDoc = new BoundedContextComponentDoc.Builder()
                .boundedContextDocId(boundedContextDocId)
                .componentDoc(componentDocFactory.buildDoc(id.stringValue(), methodDoc))
                .build();
        ProcessStepDoc processStepDoc = messageListenerDocFactory.createMessageListenerDoc(id,
                boundedContextComponentDoc);
        processStepDoc.attributes().processName().value(processName(methodDoc));
        processStepDoc.attributes().stepMethodSignature().nonOptionalValue(stepMethodSignature);
        processStepDoc.attributes().producedEvents().value(new HashSet<>(annotationsResolver.event(methodDoc)));
        processStepDoc.attributes().fromExternals().value(new HashSet<>(annotationsResolver.fromExternal(methodDoc)));
        processStepDoc.attributes().toExternals().value(new HashSet<>(annotationsResolver.toExternal(methodDoc)));
        return processStepDoc;
    }

    private ComponentDocFactory componentDocFactory;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy