<commit_before>/*
 *      Copyright (C) 2015  <EMAIL>
 *
 *      This program is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU Lesser General Public License as published by
 *      the Free Software Foundation, either version 3 of the License.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU Lesser General Public License for more details.
 *
 *      You should have received a copy of the GNU Lesser General Public License
 *      along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.openhft.chronicle.hash.serialization.internal;

import net.openhft.chronicle.hash.serialization.BytesReader;
import net.openhft.chronicle.hash.serialization.BytesWriter;
import net.openhft.chronicle.hash.serialization.DeserializationFactoryConfigurableBytesReader;
import net.openhft.compiler.CompilerUtils;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.ObjectFactory;
import net.openhft.lang.model.*;
import org.jetbrains.annotations.NotNull;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;

import static net.openhft.lang.model.DataValueGenerator.*;

public final class DataValueBytesMarshallers {

    private static final boolean dumpCode = Boolean.getBoolean("dvg.dumpCode");
    private static final Map<Class, Class> readersClassMap =
            new ConcurrentHashMap<>();
    private static final Map<Class, Class> readersWithCustomFactoriesClassMap =
            new ConcurrentHashMap<>();
    private static final Map<Class, Class> writerClassMap =
            new ConcurrentHashMap<>();

    public static <T> BytesReader<T> acquireBytesReader(Class<T> tClass) {
        Class readerClass = acquireReaderClass(tClass);
        try {
            Field instanceField = readerClass.getDeclaredField("INSTANCE");
            Object reader = instanceField.get(null);
            return (BytesReader<T>) reader;
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new AssertionError(e);
        }
    }

    public static <T> BytesWriter<T> acquireBytesWriter(Class<T> tClass) {
        Class readerClass = acquireWriterClass(tClass);
        try {
            Field instanceField = readerClass.getDeclaredField("INSTANCE");
            Object reader = instanceField.get(null);
            return (BytesWriter<T>) reader;
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new AssertionError(e);
        }
    }


    public static <T> Class acquireReaderClass(Class<T> tClass) {
        DataValueClasses.directClassFor(tClass);
        Class readerClass = readersClassMap.get(tClass);
        if (readerClass != null)
            return readerClass;
        DataValueModel<T> dvmodel = DataValueModels.acquireModel(tClass);
        for (Class clazz : dvmodel.nestedModels()) {
            // touch them to make sure they are loaded.
            Class clazz2 = acquireReaderClass(clazz);
        }
        String actual = generateBytesReader(tClass);
        if (dumpCode)
            LoggerFactory.getLogger(DataValueGenerator.class).info(actual);
        ClassLoader classLoader = tClass.getClassLoader();
        String className = bytesReaderName(tClass, false);
        try {
            readerClass = classLoader.loadClass(className);
        } catch (ClassNotFoundException ignored) {
            try {
                readerClass = CompilerUtils.CACHED_COMPILER
                        .loadFromJava(classLoader, className, actual);
            } catch (ClassNotFoundException e) {
                throw new AssertionError(e);
            }
        }
        readersClassMap.put(tClass, readerClass);
        acquireReaderWithCustomFactory(tClass);
        return readerClass;
    }

    public static <T> Class acquireWriterClass(Class<T> tClass) {
        Class writerClass = writerClassMap.get(tClass);
        if (writerClass != null)
            return writerClass;
        DataValueModel<T> dvmodel = DataValueModels.acquireModel(tClass);
        for (Class clazz : dvmodel.nestedModels()) {
            // touch them to make sure they are loaded.
            Class clazz2 = acquireWriterClass(clazz);
        }
        String actual = generateBytesWriter(tClass);
        if (dumpCode)
            LoggerFactory.getLogger(DataValueGenerator.class).info(actual);
        ClassLoader classLoader = tClass.getClassLoader();
        String className = bytesWriterName(tClass, false);
        try {
            writerClass = classLoader.loadClass(className);
        } catch (ClassNotFoundException ignored) {
            try {
                writerClass = CompilerUtils.CACHED_COMPILER
                        .loadFromJava(classLoader, className, actual);
            } catch (ClassNotFoundException e) {
                throw new AssertionError(e);
            }
        }
        writerClassMap.put(tClass, writerClass);
        return writerClass;
    }

    public static <T> Class acquireReaderWithCustomFactory(Class<T> tClass) {
        Class c = readersWithCustomFactoriesClassMap.get(tClass);
        if (c != null)
            return c;
        acquireReaderClass(tClass);
        String actual = generateWithCustomFactoryClass(tClass);<commit_msg>Avoid compiling classes several times in DataValueBytesMarshallers<commit_after>/*
 *      Copyright (C) 2015  <EMAIL>frequencytrading.<EMAIL>
 *
 *      This program is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU Lesser General Public License as published by
 *      the Free Software Foundation, either version 3 of the License.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU Lesser General Public License for more details.
 *
 *      You should have received a copy of the GNU Lesser General Public License
 *      along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.openhft.chronicle.hash.serialization.internal;

import net.openhft.chronicle.hash.serialization.BytesReader;
import net.openhft.chronicle.hash.serialization.BytesWriter;
import net.openhft.chronicle.hash.serialization.DeserializationFactoryConfigurableBytesReader;
import net.openhft.compiler.CompilerUtils;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.ObjectFactory;
import net.openhft.lang.model.*;
import org.jetbrains.annotations.NotNull;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;

import static net.openhft.lang.model.DataValueGenerator.*;

public final class DataValueBytesMarshallers {

    private static final boolean dumpCode = Boolean.getBoolean("dvg.dumpCode");
    private static final Map<Class, Class> readersClassMap =
            new ConcurrentHashMap<>();
    private static final Map<Class, Class> readersWithCustomFactoriesClassMap =
            new ConcurrentHashMap<>();
    private static final Map<Class, Class> writerClassMap =
            new ConcurrentHashMap<>();

    public static <T> BytesReader<T> acquireBytesReader(Class<T> tClass) {
        Class readerClass = acquireReaderClass(tClass);
        try {
            Field instanceField = readerClass.getDeclaredField("INSTANCE");
            Object reader = instanceField.get(null);
            return (BytesReader<T>) reader;
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new AssertionError(e);
        }
    }

    public static <T> BytesWriter<T> acquireBytesWriter(Class<T> tClass) {
        Class readerClass = acquireWriterClass(tClass);
        try {
            Field instanceField = readerClass.getDeclaredField("INSTANCE");
            Object reader = instanceField.get(null);
            return (BytesWriter<T>) reader;
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new AssertionError(e);
        }
    }


    public static <T> Class acquireReaderClass(Class<T> tClass) {
        Class readerClass = readersClassMap.get(tClass);
        if (readerClass != null)
            return readerClass;
        synchronized (readersClassMap) {
            if ((readerClass = readersClassMap.get(tClass)) != null)
                return readerClass;
            return compileReaderClass(tClass);
        }
    }

    private static <T> Class compileReaderClass(Class<T> tClass) {
        DataValueClasses.directClassFor(tClass);
        Class readerClass;
        DataValueModel<T> dvmodel = DataValueModels.acquireModel(tClass);
        for (Class clazz : dvmodel.nestedModels()) {
            // touch them to make sure they are loaded.
            Class clazz2 = acquireReaderClass(clazz);
        }
        String actual = generateBytesReader(tClass);
        if (dumpCode)
            LoggerFactory.getLogger(DataValueGenerator.class).info(actual);
        ClassLoader classLoader = tClass.getClassLoader();
        String className = bytesReaderName(tClass, false);
        try {
            readerClass = classLoader.loadClass(className);
        } catch (ClassNotFoundException ignored) {
            try {
                readerClass = CompilerUtils.CACHED_COMPILER
                        .loadFromJava(classLoader, className, actual);
            } catch (ClassNotFoundException e) {
                throw new AssertionError(e);
            }
        }
        readersClassMap.put(tClass, readerClass);
        acquireReaderWithCustomFactory(tClass);
        return readerClass;
    }

    public static <T> Class acquireWriterClass(Class<T> tClass) {
        Class writerClass = writerClassMap.get(tClass);
        if (writerClass != null)
            return writerClass;
        synchronized (writerClassMap) {
            if ((writerClass = writerClassMap.get(tClass)) != null)
                return writerClass;
            return compileWriterClass(tClass);
        }
    }

    private static <T> Class compileWriterClass(Class<T> tClass) {
        Class writerClass;
        DataValueModel<T> dvmodel = DataValueModels.acquireModel(tClass);
        for (Class clazz : dvmodel.nestedModels()) {
            // touch them to make sure they are loaded.
            Class clazz2 = acquireWriterClass(clazz);
        }
        String actual = generateBytesWriter(tClass);
        if (dumpCode)
            LoggerFactory.getLogger(DataValueGenerator.class).info(actual);
        ClassLoader classLoader = tClass.getClassLoader();
        String className = bytesWriterName(tClass, false);
        try {
            writerClass = classLoader.loadClass(className);
        } catch (ClassNotFoundException ignored) {
            try {
                writerClass = CompilerUtils.CACHED_COMPILER
                        .loadFromJava(classLoader, className, actual);
            } catch (ClassNotFoundException e) {
                throw new AssertionError(e);
            }
        }
        writerClassMap.put(tClass, writerClass);
        return writerClass;
    }

    public static <T> Class acquireReaderWithCustomFactory(Class<T> tClass) {
        Class c = readersWithCustomFactoriesClassMap.get(tClass);
        if (c != null)
            return c;
        synchronized (readersWithCustomFactoriesClassMap) {
            if ((c = readersWithCustomFactoriesClassMap.get(tClass)) != null)
                return c;
            return compileReaderWithCustomFactory(tClass);
        }
    }

    private static <T> Class compileReaderWithCustomFactory(Class<T> tClass) {
        acquireReaderClass(tClass);
        Class c;
        String actual = generateWithCustomFactoryClass(tClass);
{'fraction_non_alphanumeric': 0.08369150920444408, 'fraction_numerical': 0.0012975427783634742, 'mean_word_length': 2.7460510328068044, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 58, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '7594869', 'n_tokens_mistral': 3186, 'n_tokens_neox': 3154, 'n_words': 813}