All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.intelie.pipes.util.MapRow Maven / Gradle / Ivy

There is a newer version: 0.25.5
Show newest version
package net.intelie.pipes.util;

import net.intelie.pipes.Row;
import net.intelie.pipes.types.*;

import java.io.Serializable;
import java.util.*;

public class MapRow extends AbstractMap implements Serializable {
    private static final long serialVersionUID = 1L;
    private final RowFields fields;
    private final Row row;

    public MapRow(RowFields fields, Row row) {
        this.fields = fields;
        this.row = row;
    }

    public static Object getCasted(Type type, Object value) {
        if (RowType.hasFields(type) && value instanceof Row) {
            return new MapRow(RowType.getFields(type), (Row) value);
        } else if (type.isAssignableTo(Type.SEQ) && value instanceof Iterable) {
            List list = new ArrayList<>();
            Type inner = Type.extract(type, SeqType.class).type();
            for (Object o : (Iterable) value)
                list.add(getCasted(inner, o));
            return list;
        } else if (type.isAssignableTo(Type.MAP) && value instanceof Map) {
            Type keyType = MapType.getKeyType(type);
            Type valueType = MapType.getValueType(type);

            Map map = new LinkedHashMap<>();
            for (Entry entry : ((Map) value).entrySet())
                map.put(getCasted(keyType, entry.getKey()), getCasted(valueType, entry.getValue()));
            return map;
        } else {
            return type.cast(value);
        }
    }

    public Row row() {
        return row;
    }

    @Override
    public Set> entrySet() {
        return new EntrySet();
    }

    @Override
    public Object get(Object key) {
        if (!(key instanceof String)) return null;
        int i = fields.indexOf((String) key);
        return getCasted(i);
    }

    private Object getCasted(int i) {
        if (i < 0 || i >= row.size()) return null;
        Object value = row.get(i);
        Type type = fields.type(i);
        return getCasted(type, value);
    }

    @Override
    public boolean containsKey(Object key) {
        if (!(key instanceof String)) return false;
        return fields.indexOf((String) key) >= 0;
    }

    @Override
    public Object remove(Object key) {
        throw new UnsupportedOperationException();
    }

    private class EntrySet extends AbstractSet> {
        @Override
        public Iterator> iterator() {
            return new EntryIterator();
        }

        @Override
        public boolean contains(Object o) {
            if (!(o instanceof Entry)) return false;
            Object value = get(((Entry) o).getKey());
            return Objects.equals(value, ((Entry) o).getValue());
        }

        @Override
        public int size() {
            return fields.mapSize();
        }
    }

    private class EntryIterator implements Iterator> {
        private int i = -1;

        @Override
        public boolean hasNext() {
            ignoreOmitted();
            return i + 1 < fields.size();
        }

        private void ignoreOmitted() {
            while (i + 1 < fields.size() && fields.ommited(i + 1))
                i++;
        }

        @Override
        public Entry next() {
            ignoreOmitted();
            i++;
            return new SimpleImmutableEntry<>(fields.name(i), getCasted(i));
        }
    }
}