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));
                }
            });
        }
    }
}
@@ -176,16 +176,65 @@
 ceptor;%0A
+import org.mongodb.morphia.annotations.Property;%0A
 import o
@@ -396,123 +396,549 @@
 java
-.util.Map;%0Aimport java.util.Set;%0A%0Apublic class AdaptiveRecordMappingInterceptor extends AbstractEntityInterceptor %7B
+x.inject.Singleton;%0Aimport java.lang.reflect.Field;%0Aimport java.util.HashSet;%0Aimport java.util.List;%0Aimport java.util.Map;%0Aimport java.util.Set;%0Aimport java.util.concurrent.ConcurrentHashMap;%0Aimport java.util.concurrent.ConcurrentMap;%0A%0A@Singleton%0Apublic class AdaptiveRecordMappingInterceptor extends AbstractEntityInterceptor %7B%0A%0A    private final Set%3CString%3E BUILT_IN_PROPS = C.setOf(%22_id,className,_created,_modified,v%22.split(%22,%22));%0A    private final ConcurrentMap%3CClass%3C?%3E, Set%3CString%3E%3E mappedPropertiesLookup = new ConcurrentHashMap%3C%3E();
 %0A%0A  
@@ -1473,121 +1473,8 @@
  %7D%0A%0A
-    private static final Set%3CString%3E BUILT_IN_PROPS = C.setOf(%22_id,className,_created,_modified,v%22.split(%22,%22));%0A%0A
     
@@ -1553,32 +1553,38 @@
 pper) %7B%0A        
+final 
 Class%3C?%3E c = ent
@@ -2168,16 +2168,53 @@
 Key(key)
+ %7C%7C mappedProperties(c).contains(key)
 ) %7B%0A    
@@ -2369,10 +2369,673 @@
  %7D%0A    %7D
+%0A%0A    private Set%3CString%3E mappedProperties(Class c) %7B%0A        Set%3CString%3E set = mappedPropertiesLookup.get(c);%0A        if (null == set) %7B%0A            set = findMappedProperties(c);%0A            mappedPropertiesLookup.putIfAbsent(c, set);%0A        %7D%0A        return set;%0A    %7D%0A%0A    private Set%3CString%3E findMappedProperties(Class c) %7B%0A        Set%3CString%3E set = new HashSet%3C%3E();%0A        List%3CField%3E fieldList = $.fieldsOf(c, true);%0A        for (Field field : fieldList) %7B%0A            Property property = field.getAnnotation(Property.class);%0A            if (null != property) %7B%0A                set.add(property.value());%0A            %7D%0A        %7D%0A        return set;%0A    %7D
 %0A%7D

fix issue: it load mapped properties into adaptive record KV store