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

com.github.leeonky.jfactory.cucumber.Table Maven / Gradle / Ivy

The newest version!
package com.github.leeonky.jfactory.cucumber;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.github.leeonky.jfactory.DataParser;
import com.github.leeonky.util.BeanClass;

import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.github.leeonky.jfactory.DataParser.tryFlat;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static java.util.stream.Collectors.toCollection;
import static java.util.stream.IntStream.range;

public class Table extends ArrayList> {
    private static final ObjectMapper JSON_OBJECT_MAPPER = new ObjectMapper() {{
        configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        configure(JsonParser.Feature.ALLOW_TRAILING_COMMA, true);
    }};

    private static Function jsonDeserializer;

    static {
        resetJsonDeserializer();
    }

    public static void setJsonDeserializer(Function jsonDeserializer) {
        Table.jsonDeserializer = jsonDeserializer;
    }

    private static final ObjectMapper YAML_OBJECT_MAPPER = new ObjectMapper(new YAMLFactory()) {{
        configure(JsonParser.Feature.ALLOW_YAML_COMMENTS, true);
    }};

    @SafeVarargs
    public static Table create(Map... maps) {
        return create(asList(maps));
    }

    public static Table create(List> maps) {
        return maps.stream().map(LinkedHashMap::new).collect(toCollection(Table::new));
    }

    public static Table create(List headers, List... rows) {
        return create(headers, asList(rows));
    }

    public static Table create(List headers, List> rows) {
        return create(rows.stream().map(row -> range(0, headers.size()).boxed().
                >collect(LinkedHashMap::new,
                (map, i) -> map.put(headers.get(i), row.get(i)), LinkedHashMap::putAll)).collect(Collectors.toList()));
    }

    @SuppressWarnings("unchecked")
    public static Table create(String content) {
        try {
            Object value = jsonDeserializer.apply(content);
            return create(BeanClass.cast(value, List.class).orElseGet(() -> singletonList(value)));
        } catch (Exception e) {
            Object data = DataParser.parse(content);
            return flattenTable(data);
        }
    }

    public static Flatten flattenTable(Object data) {
        Flatten table = new Flatten();
        if (data instanceof List)
            ((List) data).forEach(list -> table.add(tryFlat(list)));
        else
            table.add(tryFlat(data));
        return table;
    }

    @SuppressWarnings("unchecked")
    public Map[] flatSub() {
        return stream().map(this::flat).toArray(Map[]::new);
    }

    public static void resetJsonDeserializer() {
        setJsonDeserializer(content -> {
            try {
                return JSON_OBJECT_MAPPER.readValue(content, Object.class);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    private  Map merge(Map m1, Map m2) {
        return new LinkedHashMap() {{
            putAll(m1);
            putAll(m2);
        }};
    }

    @SuppressWarnings("unchecked")
    private Map flatSub(String key, Object value) {
        if (value instanceof Map)
            return combineKey(flat((Map) value), key, ".");
        else if (value instanceof List)
            return combineKey(flat((List) value), key, "");
        else
            return singletonMap(key, value);
    }

    private Map combineKey(Map sub, String key, String dot) {
        Postfix postfix = new Postfix((String) sub.remove("_"));
        return sub.entrySet().stream().collect(LinkedHashMap::new,
                (map, e) -> map.put(key + postfix.apply() + dot + e.getKey(), e.getValue()), LinkedHashMap::putAll);
    }

    private Map flat(Map value) {
        return value.entrySet().stream().map(m -> flatSub(m.getKey(), m.getValue()))
                .reduce(new LinkedHashMap<>(), this::merge);
    }

    private Map flat(List list) {
        Iterator index = Stream.iterate(0, i -> i + 1).iterator();
        return list.stream().map(e -> flatSub("[" + index.next() + "]", e))
                .reduce(new LinkedHashMap<>(), this::merge);
    }

    private static class Postfix {
        private final String postfix;
        private boolean applied = false;

        public Postfix(String postfix) {
            this.postfix = postfix;
        }

        private String format(String postfix) {
            Matcher matcher = Pattern.compile("\\(?([^)!]*)\\)?(!?)").matcher(postfix);
            if (matcher.matches())
                return "(" + matcher.group(1) + ")" + matcher.group(2);
            throw new IllegalStateException("Invalid postfix: " + postfix);
        }

        public String apply() {
            return !applied && postfix != null && (applied = true) ? format(postfix) : "";
        }
    }

    public static class Flatten extends Table {

        @SuppressWarnings("unchecked")
        @Override
        public Map[] flatSub() {
            return toArray(new Map[0]);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy