<commit_before>package io.cattle.platform.object.util;

import io.cattle.platform.json.JsonMapper;
import io.cattle.platform.util.type.CollectionUtils;
import io.cattle.platform.util.type.UnmodifiableMap;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.ConvertUtils;

public class DataAccessor {

    Object source;
    Object defaultValue;
    Map<String,Object> sourceMap;
    String key;
    Class<?> scope;
    String scopeKey;

    public static DataAccessor fromDataFieldOf(Object obj) {
        DataAccessor accessor = new DataAccessor();
        accessor.source = obj;
        return accessor;
    }

    public static DataAccessor fromMap(Object obj) {
        DataAccessor accessor = new DataAccessor();
        accessor.sourceMap = CollectionUtils.castMap(obj);
        return accessor;
    }

    public static DataAccessor fields(Object obj) {
        DataAccessor accessor = fromDataFieldOf(obj);
        accessor.scopeKey = DataUtils.FIELDS;

        return accessor;
    }

    public static String fieldString(Object obj, String key) {
        return fields(obj).withKey(key).as(String.class);
    }

    public static List<String> fieldStringList(Object obj, String key) {
        List<String> result = new ArrayList<String>();
        Object list = fields(obj).withKey(key).get();

        if ( list == null || !(list instanceof List) ) {
            return result;
        }

        for ( Object item : (List<?>)list ) {
            result.add(org.apache.commons.lang3.ObjectUtils.toString(item, null));
        }

        return result;
    }

    public static Long fieldLong(Object obj, String key) {
        return fields(obj).withKey(key).as(Long.class);
    }

    public static List<Long> fieldLongList(Object obj, String key) {
        List<Long> result = new ArrayList<Long>();
        Object list = fields(obj).withKey(key).get();

        if ( list == null || !(list instanceof List) ) {
            return result;
        }

        for ( Object item : (List<?>)list ) {
            if ( item == null ) {
                result.add(null);
            } else if ( item instanceof Number ) {
                result.add(((Number)item).longValue());
            } else {
                result.add(Long.parseLong(item.toString()));
            }
        }

        return result;
    }

    public static Integer fieldInteger(Object obj, String key) {
        return fields(obj).withKey(key).as(Integer.class);
    }

    public static Boolean fieldBoolean(Object obj, String key) {
        return fields(obj).withKey(key).as(Boolean.class);
    }

    public static boolean fieldBool(Object obj, String key) {
        return fields(obj).withKey(key).withDefault(false).as(Boolean.class);
    }

    public static <T> T field(Object obj, String name, JsonMapper mapper, Class<T> type) {
        return fields(obj)
                .withKey(name)
                .as(mapper, type);
    }

    public static <T> T field(Object obj, String name, Class<T> type) {
        return fields(obj)
                .withKey(name)
                .as(type);
    }

    public DataAccessor withScope(Class<?> scope) {
        this.scope = scope;
        return this;
    }

    public DataAccessor withScopeKey(String scopeKey) {
        this.scopeKey = scopeKey;
        return this;
    }

    public DataAccessor withKey(String key) {
        this.key = key;
        return this;
    }

    public DataAccessor withDefault(Object defaultValue) {
        this.defaultValue = defaultValue;
        return this;
    }

    public <T> T as(JsonMapper mapper, Class<T> clz) {
        return mapper.convertValue(get(), clz);
    }

    @SuppressWarnings("rawtypes")
    public <T> T asCollection(JsonMapper mapper, Class<? extends Collection> collectionClass, Class<?> elementsClass) {
        return mapper.convertCollectionValue(get(), collectionClass, elementsClass);
    }

    public <T> List<? extends T> asList(JsonMapper mapper, Class<T> elementsClass) {
        return asCollection(mapper, List.class, elementsClass);
    }

    @SuppressWarnings("unchecked")
    public <T> T as(Class<T> clz) {
        return (T)ConvertUtils.convert(get(), clz);
    }

    public Object get() {
        Map<String,Object> map = getTargetMap(false, true);
        Object result = key == null ? null : map.get(key);
        return result == null ? defaultValue : result;
    }

    public void set(Object value) {
        Map<String,Object> map = getTargetMap(true, false);
        if ( key != null ) {
            map.put(key, value);
        }
    }

    public void remove() {
        Map<String,Object> map = getTargetMap(true, false);
        if ( key != null ) {
            map.remove(key);
        }
    }

    protected Map<String,Object> getTargetMap(boolean addContainer, boolean read) {
        Map<String,Object> sourceMap = this.sourceMap;

        if ( sourceMap == null && source != null ) {
            sourceMap = getData(source, read);
        }

        if ( sourceMap == null ) {
            if ( ! addContainer ) {
                throw new IllegalStateException("Can not set a value on a null target");
            }
            return null;
        }

        Map<String,Object> map = sourceMap;

        if ( isScopeSet() ) {
            Object scopedMap = sourceMap.get(getScope());
            if ( scopedMap == null && addContainer ) {
                scopedMap = new HashMap<String,Object>();
                sourceMap.put(getScope(), scopedMap);
            }
            map = CollectionUtils.castMap(scopedMap);
        }

        return map;
    }

    protected static Map<String,Object> getData(Object obj, boolean read) {
        @SuppressWarnings("unchecked")
        Map<String,Object> map = (Map<String, Object>)ObjectUtils.getPropertyIgnoreErrors(obj, DataUtils.DATA);

        if ( read ) {
            return map == null ? Collections.<String,Object>emptyMap() : Collections.unmodifiableMap(map);
        } else if ( map instanceof UnmodifiableMap<?,?> ) {
            map = ((UnmodifiableMap<String,Object>)map).getModifiableCopy();
        } else if ( map == null ) {
            map = new HashMap<String, Object>();
        }<commit_msg>Use toMap in DataAccessor for safer conversion of Object to Map<commit_after>package io.cattle.platform.object.util;

import io.cattle.platform.json.JsonMapper;
import io.cattle.platform.util.type.CollectionUtils;
import io.cattle.platform.util.type.UnmodifiableMap;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.ConvertUtils;

public class DataAccessor {

    Object source;
    Object defaultValue;
    Map<String,Object> sourceMap;
    String key;
    Class<?> scope;
    String scopeKey;

    public static DataAccessor fromDataFieldOf(Object obj) {
        DataAccessor accessor = new DataAccessor();
        accessor.source = obj;
        return accessor;
    }

    public static DataAccessor fromMap(Object obj) {
        DataAccessor accessor = new DataAccessor();
        accessor.sourceMap = CollectionUtils.toMap(obj);
        return accessor;
    }

    public static DataAccessor fields(Object obj) {
        DataAccessor accessor = fromDataFieldOf(obj);
        accessor.scopeKey = DataUtils.FIELDS;

        return accessor;
    }

    public static String fieldString(Object obj, String key) {
        return fields(obj).withKey(key).as(String.class);
    }

    public static List<String> fieldStringList(Object obj, String key) {
        List<String> result = new ArrayList<String>();
        Object list = fields(obj).withKey(key).get();

        if ( list == null || !(list instanceof List) ) {
            return result;
        }

        for ( Object item : (List<?>)list ) {
            result.add(org.apache.commons.lang3.ObjectUtils.toString(item, null));
        }

        return result;
    }

    public static Long fieldLong(Object obj, String key) {
        return fields(obj).withKey(key).as(Long.class);
    }

    public static List<Long> fieldLongList(Object obj, String key) {
        List<Long> result = new ArrayList<Long>();
        Object list = fields(obj).withKey(key).get();

        if ( list == null || !(list instanceof List) ) {
            return result;
        }

        for ( Object item : (List<?>)list ) {
            if ( item == null ) {
                result.add(null);
            } else if ( item instanceof Number ) {
                result.add(((Number)item).longValue());
            } else {
                result.add(Long.parseLong(item.toString()));
            }
        }

        return result;
    }

    public static Integer fieldInteger(Object obj, String key) {
        return fields(obj).withKey(key).as(Integer.class);
    }

    public static Boolean fieldBoolean(Object obj, String key) {
        return fields(obj).withKey(key).as(Boolean.class);
    }

    public static boolean fieldBool(Object obj, String key) {
        return fields(obj).withKey(key).withDefault(false).as(Boolean.class);
    }

    public static <T> T field(Object obj, String name, JsonMapper mapper, Class<T> type) {
        return fields(obj)
                .withKey(name)
                .as(mapper, type);
    }

    public static <T> T field(Object obj, String name, Class<T> type) {
        return fields(obj)
                .withKey(name)
                .as(type);
    }

    public DataAccessor withScope(Class<?> scope) {
        this.scope = scope;
        return this;
    }

    public DataAccessor withScopeKey(String scopeKey) {
        this.scopeKey = scopeKey;
        return this;
    }

    public DataAccessor withKey(String key) {
        this.key = key;
        return this;
    }

    public DataAccessor withDefault(Object defaultValue) {
        this.defaultValue = defaultValue;
        return this;
    }

    public <T> T as(JsonMapper mapper, Class<T> clz) {
        return mapper.convertValue(get(), clz);
    }

    @SuppressWarnings("rawtypes")
    public <T> T asCollection(JsonMapper mapper, Class<? extends Collection> collectionClass, Class<?> elementsClass) {
        return mapper.convertCollectionValue(get(), collectionClass, elementsClass);
    }

    public <T> List<? extends T> asList(JsonMapper mapper, Class<T> elementsClass) {
        return asCollection(mapper, List.class, elementsClass);
    }

    @SuppressWarnings("unchecked")
    public <T> T as(Class<T> clz) {
        return (T)ConvertUtils.convert(get(), clz);
    }

    public Object get() {
        Map<String,Object> map = getTargetMap(false, true);
        Object result = key == null ? null : map.get(key);
        return result == null ? defaultValue : result;
    }

    public void set(Object value) {
        Map<String,Object> map = getTargetMap(true, false);
        if ( key != null ) {
            map.put(key, value);
        }
    }

    public void remove() {
        Map<String,Object> map = getTargetMap(true, false);
        if ( key != null ) {
            map.remove(key);
        }
    }

    protected Map<String,Object> getTargetMap(boolean addContainer, boolean read) {
        Map<String,Object> sourceMap = this.sourceMap;

        if ( sourceMap == null && source != null ) {
            sourceMap = getData(source, read);
        }

        if ( sourceMap == null ) {
            if ( ! addContainer ) {
                throw new IllegalStateException("Can not set a value on a null target");
            }
            return null;
        }

        Map<String,Object> map = sourceMap;

        if ( isScopeSet() ) {
            Object scopedMap = sourceMap.get(getScope());
            if ( scopedMap == null && addContainer ) {
                scopedMap = new HashMap<String,Object>();
                sourceMap.put(getScope(), scopedMap);
            }
            map = CollectionUtils.toMap(scopedMap);
        }

        return map;
    }

    protected static Map<String,Object> getData(Object obj, boolean read) {
        @SuppressWarnings("unchecked")
        Map<String,Object> map = (Map<String, Object>)ObjectUtils.getPropertyIgnoreErrors(obj, DataUtils.DATA);

        if ( read ) {
            return map == null ? Collections.<String,Object>emptyMap() : Collections.unmodifiableMap(map);
        } else if ( map instanceof UnmodifiableMap<?,?> ) {
            map = ((UnmodifiableMap<String,Object>)map).getModifiableCopy();
        } else if ( map == null ) {
            map = new HashMap<String, Object>();
        }
{'fraction_non_alphanumeric': 0.11389019977977033, 'fraction_numerical': 0.00015730690577316344, 'mean_word_length': 2.3434130949250593, 'pattern_counts': {'":': 0, '<': 81, '<?xml version=': 0, '>': 81, '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': '6651439', 'n_tokens_mistral': 3581, 'n_tokens_neox': 3507, 'n_words': 878}