<commit_before>﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Cassandra;
using CqlPoco.Statements;
using CqlPoco.TypeConversion;

namespace CqlPoco
{
    internal class MapperFactory
    {
        private static readonly Type CassandraRowType = typeof (Row);
        private const BindingFlags PublicInstance = BindingFlags.Public | BindingFlags.Instance;

        // The Row.GetValue<T>(int column) instance method
        private static readonly MethodInfo GetValueOfTMethod = CassandraRowType.GetMethods(PublicInstance).Single(mi =>
        {
            if (mi.Name != "GetValue" || mi.IsGenericMethodDefinition == false)
                return false;

            Type[] genericArgs = mi.GetGenericArguments();
            if (genericArgs.Length != 1)
                return false;

            ParameterInfo[] parameters = mi.GetParameters();
            return parameters.Length == 1 && parameters[0].ParameterType == typeof (int);
        });

        // The Row.IsNull(int column) instance method
        private static readonly MethodInfo IsNullMethod = CassandraRowType.GetMethods(PublicInstance).Single(mi =>
        {
            if (mi.Name != "IsNull")
                return false;

            ParameterInfo[] parameters = mi.GetParameters();
            return parameters.Length == 1 && parameters[0].ParameterType == typeof (int);
        });

        private readonly ConcurrentDictionary<Tuple<Type, string>, Delegate> _mapperFuncCache;

        private readonly TypeConverterFactory _typeConverter;
        private readonly PocoDataFactory _pocoDataFactory;

        public MapperFactory(TypeConverterFactory typeConverter, PocoDataFactory pocoDataFactory)
        {
            if (typeConverter == null) throw new ArgumentNullException("typeConverter");
            if (pocoDataFactory == null) throw new ArgumentNullException("pocoDataFactory");
            _typeConverter = typeConverter;
            _pocoDataFactory = pocoDataFactory;

            _mapperFuncCache = new ConcurrentDictionary<Tuple<Type, string>, Delegate>();
        }

        /// <summary>
        /// Gets a mapper Func that can map from a C* row to the POCO type T for the given statement.
        /// </summary>
        public Func<Row, T> GetMapper<T>(IStatementWrapper statement, RowSet rows)
        {
            Tuple<Type, string> key = Tuple.Create(typeof (T), statement.Cql);
            Delegate mapperFunc = _mapperFuncCache.GetOrAdd(key, _ => CreateMapper<T>(rows));
            return (Func<Row, T>) mapperFunc;<commit_msg>Comment on MapperFactory<commit_after>﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Cassandra;
using CqlPoco.Statements;
using CqlPoco.TypeConversion;

namespace CqlPoco
{
    /// <summary>
    /// Component capable of getting/creating Func&lt;Row, T&gt; functions that create POCOs of type T from a Cassandra Row.
    /// </summary>
    internal class MapperFactory
    {
        private static readonly Type CassandraRowType = typeof (Row);
        private const BindingFlags PublicInstance = BindingFlags.Public | BindingFlags.Instance;

        // The Row.GetValue<T>(int column) instance method
        private static readonly MethodInfo GetValueOfTMethod = CassandraRowType.GetMethods(PublicInstance).Single(mi =>
        {
            if (mi.Name != "GetValue" || mi.IsGenericMethodDefinition == false)
                return false;

            Type[] genericArgs = mi.GetGenericArguments();
            if (genericArgs.Length != 1)
                return false;

            ParameterInfo[] parameters = mi.GetParameters();
            return parameters.Length == 1 && parameters[0].ParameterType == typeof (int);
        });

        // The Row.IsNull(int column) instance method
        private static readonly MethodInfo IsNullMethod = CassandraRowType.GetMethods(PublicInstance).Single(mi =>
        {
            if (mi.Name != "IsNull")
                return false;

            ParameterInfo[] parameters = mi.GetParameters();
            return parameters.Length == 1 && parameters[0].ParameterType == typeof (int);
        });

        private readonly TypeConverterFactory _typeConverter;
        private readonly PocoDataFactory _pocoDataFactory;
        private readonly ConcurrentDictionary<Tuple<Type, string>, Delegate> _mapperFuncCache;

        public MapperFactory(TypeConverterFactory typeConverter, PocoDataFactory pocoDataFactory)
        {
            if (typeConverter == null) throw new ArgumentNullException("typeConverter");
            if (pocoDataFactory == null) throw new ArgumentNullException("pocoDataFactory");
            _typeConverter = typeConverter;
            _pocoDataFactory = pocoDataFactory;

            _mapperFuncCache = new ConcurrentDictionary<Tuple<Type, string>, Delegate>();
        }

        /// <summary>
        /// Gets a mapper Func that can map from a C* row to the POCO type T for the given statement.
        /// </summary>
        public Func<Row, T> GetMapper<T>(IStatementWrapper statement, RowSet rows)
        {
            Tuple<Type, string> key = Tuple.Create(typeof (T), statement.Cql);
            Delegate mapperFunc = _mapperFuncCache.GetOrAdd(key, _ => CreateMapper<T>(rows));
            return (Func<Row, T>) mapperFunc;
{'fraction_non_alphanumeric': 0.09321415541773076, 'fraction_numerical': 0.0018241517694272164, 'mean_word_length': 2.807638888888889, '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': '2858112', 'n_tokens_mistral': 1402, 'n_tokens_neox': 1363, 'n_words': 378}