<commit_before>package org.jboss.da.bc.impl;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.ejb.Stateless;
import javax.inject.Inject;

import org.apache.maven.scm.ScmException;
import org.jboss.da.bc.backend.api.POMInfo;
import org.jboss.da.bc.backend.api.POMInfoGenerator;
import org.jboss.da.bc.model.BcError;
import org.jboss.da.bc.model.DependencyAnalysisStatus;
import org.jboss.da.bc.model.backend.ProjectDetail;
import org.jboss.da.bc.model.backend.ProjectHiearchy;
import org.jboss.da.common.CommunicationException;

import org.jboss.da.communication.aprox.FindGAVDependencyException;
import org.jboss.da.communication.pnc.api.PNCConnectorProvider;
import org.jboss.da.communication.pnc.api.PNCRequestException;
import org.jboss.da.communication.pom.PomAnalysisException;
import org.jboss.da.communication.scm.api.SCMConnector;

import org.jboss.da.model.rest.GAV;
import org.jboss.da.reports.api.VersionLookupResult;
import org.jboss.da.reports.backend.api.DependencyTreeGenerator;
import org.jboss.da.reports.backend.api.GAVToplevelDependencies;
import org.jboss.da.reports.backend.api.VersionFinder;
import org.slf4j.Logger;

import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

/**
 *
 * @author <NAME> <<EMAIL>>
 */
@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class ProjectHiearchyCreator {

    @Inject
    private Logger log;

    @Inject
    private DependencyTreeGenerator depGenerator;

    @Inject
    private POMInfoGenerator pom;

    @Inject
    private SCMConnector scm;

    @Inject
    private PNCConnectorProvider pnc;

    @Inject
    private VersionFinder versionFinder;

    private ProjectHiearchy toplevel;

    private Optional<ProjectDetail.SCM> internalSCM;

    private Optional<ProjectDetail.SCM> externalSCM;

    public void iterateNextLevel(ProjectHiearchy toplevel) {
        this.toplevel = toplevel;
        this.internalSCM = toplevel.getProject().getInternalSCM();
        this.externalSCM = toplevel.getProject().getExternalSCM();

        iterate(toplevel);
    }

    public Set<ProjectHiearchy> processDependencies(ProjectHiearchy toplevel,
            Collection<GAV> dependencies) {
        this.toplevel = toplevel;
        this.internalSCM = toplevel.getProject().getInternalSCM();
        this.externalSCM = toplevel.getProject().getExternalSCM();

        return toProjectHiearchies(dependencies);
    }

    /**
     * Iterate and fill next level dependencies where selected
     */
    private void iterate(ProjectHiearchy hiearchy) {
        DependencyAnalysisStatus status = hiearchy.getAnalysisStatus();
        if (DependencyAnalysisStatus.ANALYSED.equals(status) || !hiearchy.isSelected()) {
            // Dependencies already processed, search next level
            // or this dependency is not selected, but can have selected childs
            for (ProjectHiearchy dep : hiearchy.getDependencies()) {
                iterate(dep);
            }
        } else if (DependencyAnalysisStatus.NOT_ANALYSED.equals(status)
                && hiearchy.getDependencies().isEmpty()) {
            // Dependencies not yet processed, get and process them
            setDependencies(hiearchy);
        }
    }

    /**
     * Tries to find dependencies in AProx, if not found in AProx, try to found in the original SCM
     * repository.
     * @throws PomAnalysisException 
     * @throws ScmException 
     */
    private void setDependencies(ProjectHiearchy hiearchy) {
        GAV gav = hiearchy.getProject().getGav();
        GAVToplevelDependencies dependencies;
        try {
            dependencies = depGenerator.getToplevelDependencies(gav);
            hiearchy.setDependencies(toProjectHiearchies(dependencies));
            hiearchy.setAnalysisStatus(DependencyAnalysisStatus.ANALYSED);
        } catch (CommunicationException ex) {
            log.warn("Failed to get dependencies for " + gav, ex);
            hiearchy.getProject().addError(BcError.NO_DEPENDENCY);
            hiearchy.setAnalysisStatus(DependencyAnalysisStatus.FAILED);
        } catch (FindGAVDependencyException ex) {
            try {
                // try to get dependencies from internal and external scm url instead
                // intermal scm url and revision are prioritized
                ProjectDetail.SCM scmInfo = firstOrSecond(internalSCM, externalSCM);
                dependencies = depGenerator.getToplevelDependencies(scmInfo.getUrl(),
                        scmInfo.getRevision(), gav);

                hiearchy.setDependencies(toProjectHiearchies(dependencies));
                hiearchy.setAnalysisStatus(DependencyAnalysisStatus.ANALYSED);
            } catch (ScmException ex_scm) {
                log.error("Failed while getting SCM repo", ex_scm);
                hiearchy.getProject().addError(BcError.SCM_EXCEPTION);
                hiearchy.getProject().addError(BcError.NO_DEPENDENCY);
                hiearchy.setAnalysisStatus(DependencyAnalysisStatus.FAILED);
            } catch (PomAnalysisException ex_pom) {
                log.error("Failed to analyse pom", ex_pom);
                hiearchy.getProject().addError(BcError.POM_EXCEPTION);
                hiearchy.getProject().addError(BcError.NO_DEPENDENCY);
                hiearchy.setAnalysisStatus(DependencyAnalysisStatus.FAILED);
            } catch (IllegalArgumentException ex_arg) {
                log.error("No SCM url available", ex_arg);
                hiearchy.getProject().addError(BcError.NO_SCM_URL);
                hiearchy.getProject().addError(BcError.NO_DEPENDENCY);
                hiearchy.setAnalysisStatus(DependencyAnalysisStatus.FAILED);
            }

        }
    }

    private Set<ProjectHiearchy> toProjectHiearchies(GAVToplevelDependencies deps) {
        return toProjectHiearchies(deps.getDependencies());
    }

    private Set<ProjectHiearchy> toProjectHiearchies(Collection<GAV> gavs) {
        return gavs.stream().map(dep -> toProjectHiearchy(dep)).collect(Collectors.toSet());
    }

    /**
     * Creates new ProjectHiearchy from GAV.
     */
    private ProjectHiearchy toProjectHiearchy(GAV gav) {
        ProjectDetail project = new ProjectDetail(gav);

        Optional<POMInfo> pomInfo = getPomInfo(gav);

        project.setName(getName(gav)); // name
        project.setDescription(getDescription(pomInfo, gav)); // description
        setSCMInfo(project, pomInfo); // scmUrl, useExistingBc
        findExistingBuildConfiguration(project); // bcExists, useExistingBc
        getBuiltVersions(project); // internallyBuilt, availableVersions

        return new ProjectHiearchy(project, false);
    }

    public static String getName(GAV gav) {
        return String.format("%s-%s-%s", gav.getArtifactId(), gav.getVersion(), UUID.randomUUID()
                .toString().substring(0, 5));
    }

    public static String getDescription(Optional<POMInfo> pomInfo, GAV gav) {
        Optional<String> name = pomInfo.flatMap(p -> p.getName());

        return name.map(n -> String.format("Build Configuration for %s - %s.", gav, n))<commit_msg>use parallelStream in ProjectHiearchyCreator (#411)<commit_after>package org.jboss.da.bc.impl;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.ejb.Stateless;
import javax.inject.Inject;

import org.apache.maven.scm.ScmException;
import org.jboss.da.bc.backend.api.POMInfo;
import org.jboss.da.bc.backend.api.POMInfoGenerator;
import org.jboss.da.bc.model.BcError;
import org.jboss.da.bc.model.DependencyAnalysisStatus;
import org.jboss.da.bc.model.backend.ProjectDetail;
import org.jboss.da.bc.model.backend.ProjectHiearchy;
import org.jboss.da.common.CommunicationException;

import org.jboss.da.communication.aprox.FindGAVDependencyException;
import org.jboss.da.communication.pnc.api.PNCConnectorProvider;
import org.jboss.da.communication.pnc.api.PNCRequestException;
import org.jboss.da.communication.pom.PomAnalysisException;
import org.jboss.da.communication.scm.api.SCMConnector;

import org.jboss.da.model.rest.GAV;
import org.jboss.da.reports.api.VersionLookupResult;
import org.jboss.da.reports.backend.api.DependencyTreeGenerator;
import org.jboss.da.reports.backend.api.GAVToplevelDependencies;
import org.jboss.da.reports.backend.api.VersionFinder;
import org.slf4j.Logger;

import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

/**
 *
 * @author <NAME> <<EMAIL>>
 */
@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class ProjectHiearchyCreator {

    @Inject
    private Logger log;

    @Inject
    private DependencyTreeGenerator depGenerator;

    @Inject
    private POMInfoGenerator pom;

    @Inject
    private SCMConnector scm;

    @Inject
    private PNCConnectorProvider pnc;

    @Inject
    private VersionFinder versionFinder;

    private ProjectHiearchy toplevel;

    private Optional<ProjectDetail.SCM> internalSCM;

    private Optional<ProjectDetail.SCM> externalSCM;

    public void iterateNextLevel(ProjectHiearchy toplevel) {
        this.toplevel = toplevel;
        this.internalSCM = toplevel.getProject().getInternalSCM();
        this.externalSCM = toplevel.getProject().getExternalSCM();

        iterate(toplevel);
    }

    public Set<ProjectHiearchy> processDependencies(ProjectHiearchy toplevel,
            Collection<GAV> dependencies) {
        this.toplevel = toplevel;
        this.internalSCM = toplevel.getProject().getInternalSCM();
        this.externalSCM = toplevel.getProject().getExternalSCM();

        return toProjectHiearchies(dependencies);
    }

    /**
     * Iterate and fill next level dependencies where selected
     */
    private void iterate(ProjectHiearchy hiearchy) {
        DependencyAnalysisStatus status = hiearchy.getAnalysisStatus();
        if (DependencyAnalysisStatus.ANALYSED.equals(status) || !hiearchy.isSelected()) {
            // Dependencies already processed, search next level
            // or this dependency is not selected, but can have selected childs
            for (ProjectHiearchy dep : hiearchy.getDependencies()) {
                iterate(dep);
            }
        } else if (DependencyAnalysisStatus.NOT_ANALYSED.equals(status)
                && hiearchy.getDependencies().isEmpty()) {
            // Dependencies not yet processed, get and process them
            setDependencies(hiearchy);
        }
    }

    /**
     * Tries to find dependencies in AProx, if not found in AProx, try to found in the original SCM
     * repository.
     * @throws PomAnalysisException 
     * @throws ScmException 
     */
    private void setDependencies(ProjectHiearchy hiearchy) {
        GAV gav = hiearchy.getProject().getGav();
        GAVToplevelDependencies dependencies;
        try {
            dependencies = depGenerator.getToplevelDependencies(gav);
            hiearchy.setDependencies(toProjectHiearchies(dependencies));
            hiearchy.setAnalysisStatus(DependencyAnalysisStatus.ANALYSED);
        } catch (CommunicationException ex) {
            log.warn("Failed to get dependencies for " + gav, ex);
            hiearchy.getProject().addError(BcError.NO_DEPENDENCY);
            hiearchy.setAnalysisStatus(DependencyAnalysisStatus.FAILED);
        } catch (FindGAVDependencyException ex) {
            try {
                // try to get dependencies from internal and external scm url instead
                // intermal scm url and revision are prioritized
                ProjectDetail.SCM scmInfo = firstOrSecond(internalSCM, externalSCM);
                dependencies = depGenerator.getToplevelDependencies(scmInfo.getUrl(),
                        scmInfo.getRevision(), gav);

                hiearchy.setDependencies(toProjectHiearchies(dependencies));
                hiearchy.setAnalysisStatus(DependencyAnalysisStatus.ANALYSED);
            } catch (ScmException ex_scm) {
                log.error("Failed while getting SCM repo", ex_scm);
                hiearchy.getProject().addError(BcError.SCM_EXCEPTION);
                hiearchy.getProject().addError(BcError.NO_DEPENDENCY);
                hiearchy.setAnalysisStatus(DependencyAnalysisStatus.FAILED);
            } catch (PomAnalysisException ex_pom) {
                log.error("Failed to analyse pom", ex_pom);
                hiearchy.getProject().addError(BcError.POM_EXCEPTION);
                hiearchy.getProject().addError(BcError.NO_DEPENDENCY);
                hiearchy.setAnalysisStatus(DependencyAnalysisStatus.FAILED);
            } catch (IllegalArgumentException ex_arg) {
                log.error("No SCM url available", ex_arg);
                hiearchy.getProject().addError(BcError.NO_SCM_URL);
                hiearchy.getProject().addError(BcError.NO_DEPENDENCY);
                hiearchy.setAnalysisStatus(DependencyAnalysisStatus.FAILED);
            }

        }
    }

    private Set<ProjectHiearchy> toProjectHiearchies(GAVToplevelDependencies deps) {
        return toProjectHiearchies(deps.getDependencies());
    }

    private Set<ProjectHiearchy> toProjectHiearchies(Collection<GAV> gavs) {
        return gavs.parallelStream().map(dep -> toProjectHiearchy(dep)).collect(Collectors.toSet());
    }

    /**
     * Creates new ProjectHiearchy from GAV.
     */
    private ProjectHiearchy toProjectHiearchy(GAV gav) {
        ProjectDetail project = new ProjectDetail(gav);

        Optional<POMInfo> pomInfo = getPomInfo(gav);

        project.setName(getName(gav)); // name
        project.setDescription(getDescription(pomInfo, gav)); // description
        setSCMInfo(project, pomInfo); // scmUrl, useExistingBc
        findExistingBuildConfiguration(project); // bcExists, useExistingBc
        getBuiltVersions(project); // internallyBuilt, availableVersions

        return new ProjectHiearchy(project, false);
    }

    public static String getName(GAV gav) {
        return String.format("%s-%s-%s", gav.getArtifactId(), gav.getVersion(), UUID.randomUUID()
                .toString().substring(0, 5));
    }

    public static String getDescription(Optional<POMInfo> pomInfo, GAV gav) {
        Optional<String> name = pomInfo.flatMap(p -> p.getName());

        return name.map(n -> String.format("Build Configuration for %s - %s.", gav, n))
{'fraction_non_alphanumeric': 0.09681203422577975, 'fraction_numerical': 0.0006210322936792713, 'mean_word_length': 3.1161601817665434, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7489418', 'n_tokens_mistral': 4349, 'n_tokens_neox': 4158, 'n_words': 751}