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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.jboss.da.bc.backend.api.POMInfo;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.apache.maven.scm.ScmException;
import org.jboss.da.bc.api.BuildConfigurationGenerator;
import org.jboss.da.bc.backend.api.BCSetGenerator;
import org.jboss.da.bc.backend.api.BcChecker;
import org.jboss.da.bc.backend.api.POMInfoGenerator;
import org.jboss.da.bc.backend.api.RepositoryCloner;
import org.jboss.da.bc.model.GeneratorEntity;
import org.jboss.da.bc.model.ProjectDetail;
import org.jboss.da.bc.model.ProjectHiearchy;
import org.jboss.da.communication.CommunicationException;
import org.jboss.da.communication.model.GAV;
import org.jboss.da.communication.pnc.api.PNCConnector;
import org.jboss.da.communication.pnc.model.BuildConfiguration;
import org.jboss.da.communication.pnc.model.BuildConfigurationCreate;
import org.jboss.da.communication.pom.PomAnalysisException;
import org.jboss.da.reports.api.SCMLocator;
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.jboss.da.scm.api.SCMType;
import org.slf4j.Logger;

/**
 *
 * @author <NAME> <<EMAIL>>
 */
@ApplicationScoped
public class BuildConfigurationGeneratorImpl implements BuildConfigurationGenerator {

    @Inject
    private Logger log;

    @Inject
    private PNCConnector pnc;

    @Inject
    private DependencyTreeGenerator depGenerator;

    @Inject
    private POMInfoGenerator pom;

    @Inject
    private BcChecker bcFinder;

    @Inject
    private VersionFinder versionFinder;

    @Inject
    private BCSetGenerator bcSetGenerator;

    @Inject
    private RepositoryCloner repoCloner;

    @Override
    public GeneratorEntity startBCGeneration(SCMLocator scm, String productName)
            throws CommunicationException, ScmException, PomAnalysisException {
        GAVToplevelDependencies deps = depGenerator.getToplevelDependencies(scm);
        Optional<POMInfo> pomInfo = pom.getPomInfo(scm.getScmUrl(), scm.getRevision(),
                scm.getPomPath());

        GeneratorEntity ge = new GeneratorEntity(scm, productName, deps.getGav());
        ge.setBcSetName(String.format("Build configuration set for %s", deps.getGav()));

        setProjectInfoFromPom(ge.getToplevelProject(), pomInfo);
        ge.getToplevelProject().setName(getName(deps.getGav()));

        ge.getToplevelBc().setDependencies(
                Optional.of(toProjectHierarchies(deps.getDependencies())));

        return ge;
    }

    @Override
    public GeneratorEntity iterateBCGeneration(GeneratorEntity projects)
            throws CommunicationException {
        iterateDependencies(projects.getToplevelBc(), projects);
        return projects;
    }

    @Override
    public void createBC(GeneratorEntity projects) throws Exception {
        Set<Integer> ids = create(projects.getToplevelBc());
        int productVersionId = bcSetGenerator.createProduct(projects.getName());
        bcSetGenerator.createBCSet(projects.getName(), productVersionId, new ArrayList(ids));
    }

    private ProjectHiearchy iterateDependencies(ProjectHiearchy hiearchy, GeneratorEntity entity)
            throws CommunicationException {
        Optional<Set<ProjectHiearchy>> deps = hiearchy.getDependencies();
        if (hiearchy.isSelected() && deps.isPresent()) {
            if (deps.get().isEmpty()) {
                GAV gav = hiearchy.getProject().getGav();
                hiearchy.setDependencies(getDependencies(gav, entity));
            } else {
                for (ProjectHiearchy dep : deps.get()) {
                    iterateDependencies(dep, entity);
                }
            }
        }
        return hiearchy;
    }

    /**
     * Tries to find dependencies in AProx, if not found in AProx, try to found in the original SCM
     * repository.
     */
    private Optional<Set<ProjectHiearchy>> getDependencies(GAV gav, GeneratorEntity entity) throws CommunicationException {
        Optional<GAVToplevelDependencies> gavs = depGenerator.getToplevelDependencies(gav);
        if(!gavs.isPresent()){
            ProjectDetail project = entity.getToplevelProject();
            try {
                gavs = Optional.of(depGenerator.getToplevelDependencies(project.getScmUrl(), project.getScmRevision(), gav));
            } catch (ScmException | PomAnalysisException ex) {
                return Optional.empty();
            }
        }

        return gavs.map(x -> toProjectHierarchies(x.getDependencies()));
    }

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

    /**
     * Creates new ProjectHiearchy from GAV.
     * Tries to get pom file for GAV and if
     */
    private ProjectHiearchy toProjectHiearchy(GAV gav) {
        ProjectDetail project = new ProjectDetail(gav);
        project.setName(getName(gav));
        tryGetInfoFromPom(project, gav);

        try {
            project.setInternallyBuilt(versionFinder.getBestMatchVersionFor(gav));
        } catch (CommunicationException ex) {
            log.error("Could not obtain best match version", ex);
        }

        ProjectHiearchy ph = new ProjectHiearchy(project, false);
        return ph;
    }

    /**
     * Tries to get pomfile for given GAV and fill Project detail with informations from pomfile.
     * Also tries to find if build configuration for this GAV already exists.
     */
    private void tryGetInfoFromPom(ProjectDetail project, GAV gav) {
        try {
            Optional<POMInfo> pomInfo = pom.getPomInfo(gav);

            setProjectInfoFromPom(project, pomInfo);
            setSCMData(project, pomInfo);

            Optional<BuildConfiguration> bc = findExistingBuildConfiguration(pomInfo);
            project.setBcExists(bc.isPresent());
            project.setUseExistingBc(bc.isPresent());
        } catch (Exception ex) {
            log.error("Could not obtain pom info.", ex);
        }
    }

    private Set<Integer> create(ProjectHiearchy hiearchy) throws Exception {
        Set<Integer> deps = new HashSet<>();
        if (hiearchy.isSelected()) {

            for (ProjectHiearchy dep : hiearchy.getDependencies().orElseGet(Collections::emptySet)) {
                deps.addAll(create(dep));
            }

            ProjectDetail project = hiearchy.getProject();
            BuildConfigurationCreate bcc;
            if(project.isUseExistingBc()){
                Optional<BuildConfiguration> bc = bcFinder.lookupBcByScm(project.getScmUrl(), project.getScmRevision());
                bcc = bc.orElseThrow(() -> new IllegalStateException("useExistingBC is true, but there is no BC to use."));
            }else{
                bcc = toBC(project, deps);
                if(project.isCloneRepo()){
                    String newScmUrl = repoCloner.cloneRepository(project.getScmUrl(), project.getScmRevision(), SCMType.GIT, "Repository of " + project.getGav());
                    bcc.setScmRepoURL(newScmUrl);
                }
            }
            BuildConfiguration bc = pnc.createBuildConfiguration(bcc);
            deps.add(bc.getId());
        }
        return deps;
    }

    private String getDescription(POMInfo pomInfo) {
        Optional<String> name = pomInfo.getName();

        return name.map(n -> String.format("Build Configuration for %s - %s.", pomInfo.getGav(), n))
                   .orElse(String.format("Build Configuration for %s.", pomInfo.getGav()));
    }

    private String getName(GAV gav) {<commit_msg>Do not fail when repour fails to clone repo - use upstream repo<commit_after>package org.jboss.da.bc.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.jboss.da.bc.backend.api.POMInfo;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.apache.maven.scm.ScmException;
import org.jboss.da.bc.api.BuildConfigurationGenerator;
import org.jboss.da.bc.backend.api.BCSetGenerator;
import org.jboss.da.bc.backend.api.BcChecker;
import org.jboss.da.bc.backend.api.POMInfoGenerator;
import org.jboss.da.bc.backend.api.RepositoryCloner;
import org.jboss.da.bc.model.GeneratorEntity;
import org.jboss.da.bc.model.ProjectDetail;
import org.jboss.da.bc.model.ProjectHiearchy;
import org.jboss.da.communication.CommunicationException;
import org.jboss.da.communication.model.GAV;
import org.jboss.da.communication.pnc.api.PNCConnector;
import org.jboss.da.communication.pnc.model.BuildConfiguration;
import org.jboss.da.communication.pnc.model.BuildConfigurationCreate;
import org.jboss.da.communication.pom.PomAnalysisException;
import org.jboss.da.reports.api.SCMLocator;
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.jboss.da.scm.api.SCMType;
import org.slf4j.Logger;

/**
 *
 * @author <NAME> <<EMAIL>>
 */
@ApplicationScoped
public class BuildConfigurationGeneratorImpl implements BuildConfigurationGenerator {

    @Inject
    private Logger log;

    @Inject
    private PNCConnector pnc;

    @Inject
    private DependencyTreeGenerator depGenerator;

    @Inject
    private POMInfoGenerator pom;

    @Inject
    private BcChecker bcFinder;

    @Inject
    private VersionFinder versionFinder;

    @Inject
    private BCSetGenerator bcSetGenerator;

    @Inject
    private RepositoryCloner repoCloner;

    @Override
    public GeneratorEntity startBCGeneration(SCMLocator scm, String productName)
            throws CommunicationException, ScmException, PomAnalysisException {
        GAVToplevelDependencies deps = depGenerator.getToplevelDependencies(scm);
        Optional<POMInfo> pomInfo = pom.getPomInfo(scm.getScmUrl(), scm.getRevision(),
                scm.getPomPath());

        GeneratorEntity ge = new GeneratorEntity(scm, productName, deps.getGav());
        ge.setBcSetName(String.format("Build configuration set for %s", deps.getGav()));

        setProjectInfoFromPom(ge.getToplevelProject(), pomInfo);
        ge.getToplevelProject().setName(getName(deps.getGav()));

        ge.getToplevelBc().setDependencies(
                Optional.of(toProjectHierarchies(deps.getDependencies())));

        return ge;
    }

    @Override
    public GeneratorEntity iterateBCGeneration(GeneratorEntity projects)
            throws CommunicationException {
        iterateDependencies(projects.getToplevelBc(), projects);
        return projects;
    }

    @Override
    public void createBC(GeneratorEntity projects) throws Exception {
        Set<Integer> ids = create(projects.getToplevelBc());
        int productVersionId = bcSetGenerator.createProduct(projects.getName());
        bcSetGenerator.createBCSet(projects.getName(), productVersionId, new ArrayList(ids));
    }

    private ProjectHiearchy iterateDependencies(ProjectHiearchy hiearchy, GeneratorEntity entity)
            throws CommunicationException {
        Optional<Set<ProjectHiearchy>> deps = hiearchy.getDependencies();
        if (hiearchy.isSelected() && deps.isPresent()) {
            if (deps.get().isEmpty()) {
                GAV gav = hiearchy.getProject().getGav();
                hiearchy.setDependencies(getDependencies(gav, entity));
            } else {
                for (ProjectHiearchy dep : deps.get()) {
                    iterateDependencies(dep, entity);
                }
            }
        }
        return hiearchy;
    }

    /**
     * Tries to find dependencies in AProx, if not found in AProx, try to found in the original SCM
     * repository.
     */
    private Optional<Set<ProjectHiearchy>> getDependencies(GAV gav, GeneratorEntity entity) throws CommunicationException {
        Optional<GAVToplevelDependencies> gavs = depGenerator.getToplevelDependencies(gav);
        if(!gavs.isPresent()){
            ProjectDetail project = entity.getToplevelProject();
            try {
                gavs = Optional.of(depGenerator.getToplevelDependencies(project.getScmUrl(), project.getScmRevision(), gav));
            } catch (ScmException | PomAnalysisException ex) {
                return Optional.empty();
            }
        }

        return gavs.map(x -> toProjectHierarchies(x.getDependencies()));
    }

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

    /**
     * Creates new ProjectHiearchy from GAV.
     * Tries to get pom file for GAV and if
     */
    private ProjectHiearchy toProjectHiearchy(GAV gav) {
        ProjectDetail project = new ProjectDetail(gav);
        project.setName(getName(gav));
        tryGetInfoFromPom(project, gav);

        try {
            project.setInternallyBuilt(versionFinder.getBestMatchVersionFor(gav));
        } catch (CommunicationException ex) {
            log.error("Could not obtain best match version", ex);
        }

        ProjectHiearchy ph = new ProjectHiearchy(project, false);
        return ph;
    }

    /**
     * Tries to get pomfile for given GAV and fill Project detail with informations from pomfile.
     * Also tries to find if build configuration for this GAV already exists.
     */
    private void tryGetInfoFromPom(ProjectDetail project, GAV gav) {
        try {
            Optional<POMInfo> pomInfo = pom.getPomInfo(gav);

            setProjectInfoFromPom(project, pomInfo);
            setSCMData(project, pomInfo);

            Optional<BuildConfiguration> bc = findExistingBuildConfiguration(pomInfo);
            project.setBcExists(bc.isPresent());
            project.setUseExistingBc(bc.isPresent());
        } catch (Exception ex) {
            log.error("Could not obtain pom info.", ex);
        }
    }

    private Set<Integer> create(ProjectHiearchy hiearchy) throws Exception {
        Set<Integer> deps = new HashSet<>();
        if (hiearchy.isSelected()) {

            for (ProjectHiearchy dep : hiearchy.getDependencies().orElseGet(Collections::emptySet)) {
                deps.addAll(create(dep));
            }

            ProjectDetail project = hiearchy.getProject();
            BuildConfigurationCreate bcc;
            if(project.isUseExistingBc()){
                Optional<BuildConfiguration> bc = bcFinder.lookupBcByScm(project.getScmUrl(), project.getScmRevision());
                bcc = bc.orElseThrow(() -> new IllegalStateException("useExistingBC is true, but there is no BC to use."));
            }else{
                bcc = toBC(project, deps);
                if(project.isCloneRepo()){
                    try{
                        String newScmUrl = repoCloner.cloneRepository(project.getScmUrl(), project.getScmRevision(), SCMType.GIT, "Repository of " + project.getGav());
                        bcc.setScmRepoURL(newScmUrl);
                    }catch(Exception ex){
                        log.error("Failed to clone repo.", ex);
                    }
                }
            }
            BuildConfiguration bc = pnc.createBuildConfiguration(bcc);
            deps.add(bc.getId());
        }
        return deps;
    }

    private String getDescription(POMInfo pomInfo) {
        Optional<String> name = pomInfo.getName();

        return name.map(n -> String.format("Build Configuration for %s - %s.", pomInfo.getGav(), n))
                   .orElse(String.format("Build Configuration for %s.", pomInfo.getGav()));
    }

    private String getName(GAV gav) {
{'fraction_non_alphanumeric': 0.1016832488580189, 'fraction_numerical': 0.00012514861397910017, 'mean_word_length': 2.912362301101591, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 47, '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': '4048325', 'n_tokens_mistral': 4745, 'n_tokens_neox': 4543, 'n_words': 899}