<commit_before>package act.db.morphia.util;

import act.db.AdaptiveRecord;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.DBObject;
import org.mongodb.morphia.AbstractEntityInterceptor;
import org.mongodb.morphia.mapping.Mapper;
import org.mongodb.morphia.utils.IterHelper;
import org.osgl.$;
import org.osgl.util.C;
import org.osgl.util.S;

import java.util.Map;
import java.util.Set;

public class AdaptiveRecordMappingInterceptor extends AbstractEntityInterceptor {

    @Override
    public void prePersist(Object ent, DBObject dbObj, Mapper mapper) {
        if (null == ent) {
            return;
        }
        Class<?> c = ent.getClass();
        if (AdaptiveRecord.class.isAssignableFrom(c)) {
            AdaptiveRecord ar = $.cast(ent);
            Map<String, Object> kv = ar.internalMap();
            for (Map.Entry<String, Object> entry : kv.entrySet()) {
                dbObj.put(entry.getKey(), ValueObjectConverter.INSTANCE.encode(entry.getValue()));
            }
        }
    }

    private static final Set<String> BUILT_IN_PROPS = C.setOf("_id,className,_created,_modified,v".split(","));

    @Override
    public void postLoad(Object ent, DBObject dbObj, Mapper mapper) {
        Class<?> c = ent.getClass();
        if (AdaptiveRecord.class.isAssignableFrom(c)) {
            AdaptiveRecord ar = $.cast(ent);
            final Map<String, Object> kv = ar.internalMap();
            final AdaptiveRecord.MetaInfo metaInfo = ar.metaInfo();
            new IterHelper<>().loopMap(dbObj, new IterHelper.MapIterCallback<Object, Object>() {
                @Override
                public void eval(final Object k, final Object val) {
                    final String key = S.string(k);
                    if (BUILT_IN_PROPS.contains(key) || metaInfo.setterFieldSpecs.containsKey(key)) {
                        return;
                    }
                    kv.put(key, JSONObject.toJSON(val));
                }
            });
        }
    }
}<commit_msg>fix issue: it load mapped properties into adaptive record KV store<commit_after>package act.db.morphia.util;

import act.db.AdaptiveRecord;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.DBObject;
import org.mongodb.morphia.AbstractEntityInterceptor;
import org.mongodb.morphia.annotations.Property;
import org.mongodb.morphia.mapping.Mapper;
import org.mongodb.morphia.utils.IterHelper;
import org.osgl.$;
import org.osgl.util.C;
import org.osgl.util.S;

import javax.inject.Singleton;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Singleton
public class AdaptiveRecordMappingInterceptor extends AbstractEntityInterceptor {

    private final Set<String> BUILT_IN_PROPS = C.setOf("_id,className,_created,_modified,v".split(","));
    private final ConcurrentMap<Class<?>, Set<String>> mappedPropertiesLookup = new ConcurrentHashMap<>();

    @Override
    public void prePersist(Object ent, DBObject dbObj, Mapper mapper) {
        if (null == ent) {
            return;
        }
        Class<?> c = ent.getClass();
        if (AdaptiveRecord.class.isAssignableFrom(c)) {
            AdaptiveRecord ar = $.cast(ent);
            Map<String, Object> kv = ar.internalMap();
            for (Map.Entry<String, Object> entry : kv.entrySet()) {
                dbObj.put(entry.getKey(), ValueObjectConverter.INSTANCE.encode(entry.getValue()));
            }
        }
    }

    @Override
    public void postLoad(Object ent, DBObject dbObj, Mapper mapper) {
        final Class<?> c = ent.getClass();
        if (AdaptiveRecord.class.isAssignableFrom(c)) {
            AdaptiveRecord ar = $.cast(ent);
            final Map<String, Object> kv = ar.internalMap();
            final AdaptiveRecord.MetaInfo metaInfo = ar.metaInfo();
            new IterHelper<>().loopMap(dbObj, new IterHelper.MapIterCallback<Object, Object>() {
                @Override
                public void eval(final Object k, final Object val) {
                    final String key = S.string(k);
                    if (BUILT_IN_PROPS.contains(key) || metaInfo.setterFieldSpecs.containsKey(key) || mappedProperties(c).contains(key)) {
                        return;
                    }
                    kv.put(key, JSONObject.toJSON(val));
                }
            });
        }
    }

    private Set<String> mappedProperties(Class c) {
        Set<String> set = mappedPropertiesLookup.get(c);
        if (null == set) {
            set = findMappedProperties(c);
            mappedPropertiesLookup.putIfAbsent(c, set);
        }
        return set;
    }

    private Set<String> findMappedProperties(Class c) {
        Set<String> set = new HashSet<>();
        List<Field> fieldList = $.fieldsOf(c, true);
        for (Field field : fieldList) {
            Property property = field.getAnnotation(Property.class);
            if (null != property) {
                set.add(property.value());
            }
        }
        return set;
    }
}
{'fraction_non_alphanumeric': 0.11599297012302284, 'fraction_numerical': 0.0, 'mean_word_length': 2.4514824797843664, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, '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': '6441534', 'n_tokens_mistral': 1506, 'n_tokens_neox': 1468, 'n_words': 308}