<commit_before>package org.jboss.shamrock.jpa;

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;

import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
import org.hibernate.protean.impl.PersistenceUnitsHolder;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.ClassType;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.shamrock.deployment.ArchiveContext;
import org.jboss.shamrock.deployment.ProcessorContext;
import org.jboss.shamrock.deployment.codegen.BytecodeRecorder;

/**
 * Scan the Jandex index to find JPA entities (and embeddables supporting entity models).
 *
 * The output is then both consumed as plain list to use as a filter for which classes
 * need to be enhanced, collect them for storage in the JPADeploymentTemplate and registered
 * for reflective access.
 * TODO some of these are going to be redundant?
 *
 * @author <NAME> <EMAIL>
 * @author <NAME>  <<EMAIL>>
 */
final class JpaJandexScavenger {

    private static final DotName JPA_ENTITY = DotName.createSimple(Entity.class.getName());
    private static final DotName EMBEDDABLE = DotName.createSimple(Embeddable.class.getName());
    private static final DotName EMBEDDED = DotName.createSimple(Embedded.class.getName());
    private static final DotName MAPPED_SUPERCLASS = DotName.createSimple(MappedSuperclass.class.getName());

    private final ArchiveContext archiveContext;
    private final ProcessorContext processorContext;

    JpaJandexScavenger(final ArchiveContext archiveContext, final ProcessorContext processorContext) {
        this.archiveContext = archiveContext;
        this.processorContext = processorContext;
    }

    public KnownDomainObjects discoverModelAndRegisterForReflection() throws IOException {
        // list all entities and create a JPADeploymentTemplate out of it
        // Not functional as we will need one deployment template per persistence unit
        final IndexView index = archiveContext.getCombinedIndex();
        final DomainObjectSet collector = new DomainObjectSet();

        enlistJPAModelClasses(JPA_ENTITY, collector, index);
        enlistJPAModelClasses(EMBEDDABLE, collector, index);
        enlistJPAModelClasses(MAPPED_SUPERCLASS, collector, index);
        enlistReturnType(collector, index);

        List<PersistenceUnitDescriptor> persistenceUnitDescriptors = PersistenceUnitsHolder.getPersistenceUnitDescriptors();
        for (PersistenceUnitDescriptor pud : persistenceUnitDescriptors) {
            enlistExplicitClasses(pud.getManagedClassNames(), collector);
        }

        collector.registerAllForReflection(processorContext);

        // TODO what priority to give JPA?
        try (BytecodeRecorder context = processorContext.addStaticInitTask(100)) {
            JPADeploymentTemplate template = context.getRecordingProxy(JPADeploymentTemplate.class);
            collector.dumpAllToJPATemplate(template);
            template.enlistPersistenceUnit();
            template.callHibernateFeatureInit();
        }


        return collector;
    }

    private void enlistExplicitClasses(List<String> managedClassNames, DomainObjectSet collector) {
        for (String className : managedClassNames) {
            // TODO add superclass for reflection
            collector.addEntity(className);
        }
    }

    private static void enlistReturnType(DomainObjectSet collector, IndexView index) {
        Collection<AnnotationInstance> annotations = index.getAnnotations(EMBEDDED);<commit_msg>[jpa] Fetch <class> from Index when available<commit_after>package org.jboss.shamrock.jpa;

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;

import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
import org.hibernate.protean.impl.PersistenceUnitsHolder;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.ClassType;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.shamrock.deployment.ArchiveContext;
import org.jboss.shamrock.deployment.ProcessorContext;
import org.jboss.shamrock.deployment.codegen.BytecodeRecorder;

/**
 * Scan the Jandex index to find JPA entities (and embeddables supporting entity models).
 *
 * The output is then both consumed as plain list to use as a filter for which classes
 * need to be enhanced, collect them for storage in the JPADeploymentTemplate and registered
 * for reflective access.
 * TODO some of these are going to be redundant?
 *
 * @author <NAME> <EMAIL>
 * @author <NAME>  <<EMAIL>>
 */
final class JpaJandexScavenger {

    private static final DotName JPA_ENTITY = DotName.createSimple(Entity.class.getName());
    private static final DotName EMBEDDABLE = DotName.createSimple(Embeddable.class.getName());
    private static final DotName EMBEDDED = DotName.createSimple(Embedded.class.getName());
    private static final DotName MAPPED_SUPERCLASS = DotName.createSimple(MappedSuperclass.class.getName());

    private final ArchiveContext archiveContext;
    private final ProcessorContext processorContext;

    JpaJandexScavenger(final ArchiveContext archiveContext, final ProcessorContext processorContext) {
        this.archiveContext = archiveContext;
        this.processorContext = processorContext;
    }

    public KnownDomainObjects discoverModelAndRegisterForReflection() throws IOException {
        // list all entities and create a JPADeploymentTemplate out of it
        // Not functional as we will need one deployment template per persistence unit
        final IndexView index = archiveContext.getCombinedIndex();
        final DomainObjectSet collector = new DomainObjectSet();

        enlistJPAModelClasses(JPA_ENTITY, collector, index);
        enlistJPAModelClasses(EMBEDDABLE, collector, index);
        enlistJPAModelClasses(MAPPED_SUPERCLASS, collector, index);
        enlistReturnType(collector, index);

        List<PersistenceUnitDescriptor> persistenceUnitDescriptors = PersistenceUnitsHolder.getPersistenceUnitDescriptors();
        for (PersistenceUnitDescriptor pud : persistenceUnitDescriptors) {
            enlistExplicitClasses(pud.getManagedClassNames(), collector, index);
        }

        collector.registerAllForReflection(processorContext);

        // TODO what priority to give JPA?
        try (BytecodeRecorder context = processorContext.addStaticInitTask(100)) {
            JPADeploymentTemplate template = context.getRecordingProxy(JPADeploymentTemplate.class);
            collector.dumpAllToJPATemplate(template);
            template.enlistPersistenceUnit();
            template.callHibernateFeatureInit();
        }


        return collector;
    }

    private static void enlistExplicitClasses(List<String> managedClassNames, DomainObjectSet collector, IndexView index) {
        for (String className : managedClassNames) {
            DotName dotName = DotName.createSimple(className);
            boolean isInIndex = index.getClassByName(dotName) != null;
            if (isInIndex) {
                addClassHierarchyToReflectiveList(collector, index, dotName);
            }
            else {
                // We do lipstick service by manually adding explicitly the <class> reference but not navigating the hierarchy
                System.out.println("[WARNING] Did not find `" + className + "` in the indexed jars. You likely forgot to add shamrock-build.yaml in your dependency jar. See https://github.com/protean-project/shamrock/#indexing-and-application-classes for more info.");
                collector.addEntity(className);
            }
        }
    }

    private static void enlistReturnType(DomainObjectSet collector, IndexView index) {
        Collection<AnnotationInstance> annotations = index.getAnnotations(EMBEDDED);
{'fraction_non_alphanumeric': 0.07581746316924183, 'fraction_numerical': 0.0007186489399928135, 'mean_word_length': 4.082166768107121, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 1, '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': '378088', 'n_tokens_mistral': 2323, 'n_tokens_neox': 2192, 'n_words': 555}