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

apoc.graph.util.GraphsConfig Maven / Gradle / Ivy

There is a newer version: 5.25.1
Show newest version
package apoc.graph.util;

import org.apache.commons.collections4.MapUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static apoc.util.Util.toBoolean;

public class GraphsConfig {

    private static final Pattern MAPPING_PATTERN = Pattern.compile("^(\\w+\\s*(?::\\s*(?:\\w+)\\s*)*)\\s*(?:\\{\\s*(-?[\\*\\w!@\\.]+\\s*(?:,\\s*-?[!@\\w\\*\\.]+\\s*)*)\\})?$");

    public static class GraphMapping {

        private static final String IDS = "ids";
        private static final String VALUE_OBJECTS = "valueObjects";
        private static final String PROPERTIES = "properties";
        private static final String WILDCARD = "*";

        private List valueObjects = new ArrayList<>();
        private List ids = new ArrayList<>();
        private List properties = new ArrayList<>();
        private List labels = new ArrayList<>();

        private boolean allProps = true;

        static final GraphMapping EMPTY = new GraphMapping();

        GraphMapping(List valueObjects, List ids, List properties, List labels, boolean allProps) {
            this.allProps = allProps;
            if (valueObjects != null) this.valueObjects.addAll(valueObjects);
            if (ids != null) this.ids.addAll(ids);
            if (labels != null) this.labels.addAll(labels);
            if (!this.allProps) {
                if (properties != null) this.properties.addAll(properties);
                this.properties.addAll(this.ids);
                this.properties.addAll(this.valueObjects);
            }
        }

        GraphMapping() {}

        public List getValueObjects() {
            return valueObjects;
        }

        public List getIds() {
            return ids;
        }

        public List getProperties() {
            return properties;
        }

        public List getLabels() {
            return labels;
        }

        public boolean isAllProps() {
            return allProps;
        }

        public static GraphMapping from(String pattern) {
            Matcher matcher = MAPPING_PATTERN.matcher(pattern);
            if (!matcher.matches()) {
                throw new RuntimeException("The provided pattern " + pattern + " does not match the requirements");
            }
            List labels = Arrays.asList(matcher.group(1).split(":"));
            AtomicBoolean allProps = new AtomicBoolean(false);
            Map> map = Stream.of(matcher.group(2).split(","))
                    .map(s -> {
                        String value = s.trim();
                        String key;
                        if (value.startsWith("@")) {
                            key = VALUE_OBJECTS;
                            value = value.substring(1);
                        } else if (value.startsWith("!")) {
                            key = IDS;
                            value = value.substring(1);
                        } else {
                            key = PROPERTIES;
                        }
                        if (WILDCARD.equals(value) && key.equals(PROPERTIES)) {
                            allProps.set(true);
                            return null;
                        } else {
                            return new AbstractMap.SimpleEntry<>(key, value);
                        }
                    })
                    .filter(e -> e != null)
                    .collect(Collectors.groupingBy(Map.Entry::getKey,
                            Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
            return new GraphMapping(map.get(VALUE_OBJECTS), map.get(IDS), map.get(PROPERTIES), labels, allProps.get());
        }
    }

    private boolean write;
    private String labelField;
    private String idField;
    private boolean generateId;
    private Map mappings;
    private Map relMapping;

    private boolean skipValidation;

    public GraphsConfig(Map config) {
        if (config == null) {
            config = Collections.emptyMap();
        }
        write = toBoolean(config.getOrDefault("write", false));
        generateId = toBoolean(config.getOrDefault("generateId", true));
        idField = config.getOrDefault("idField", "id").toString();
        labelField = config.getOrDefault("labelField", "type").toString();
        mappings = toMappings((Map) config.getOrDefault("mappings", Collections.emptyMap()));
        skipValidation = toBoolean(config.getOrDefault("skipValidation", false));
        relMapping = MapUtils.emptyIfNull((Map) config.get("relMapping"));
    }

    private Map toMappings(Map mappings) {
        return mappings.entrySet().stream()
                .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), GraphMapping.from(e.getValue())))
                .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
    }

    public boolean isWrite() {
        return write;
    }

    public String getLabelField() {
        return labelField;
    }

    public String getIdField() {
        return idField;
    }

    public boolean isGenerateId() {
        return generateId;
    }

    public Map getRelMapping() {
        return relMapping;
    }

    public boolean isSkipValidation() {
        return skipValidation;
    }

    public List valueObjectForPath(String path) {
        return mappings.getOrDefault(path, GraphMapping.EMPTY).getValueObjects();
    }

    public List idsForPath(String path) {
        return mappings.getOrDefault(path, GraphMapping.EMPTY).getIds();
    }

    public List labelsForPath(String path) {
        return mappings.getOrDefault(path, GraphMapping.EMPTY).getLabels();
    }

    public List propertiesForPath(String path) {
        if (allPropertiesForPath(path)) {
            return Collections.emptyList();
        }
        // We also need to consider the properties defined in the mapping fields
        final List pathProperties = mappings.keySet()
                .stream()
                .filter(key -> key.startsWith(path))
                .map(key -> path.length() >= key.length() ? "" : key.substring(path.length() + 1))
                .map(key -> key.split("\\.")[0])
                .filter(key -> !key.isEmpty())
                .collect(Collectors.toList());
        List properties = mappings.getOrDefault(path, GraphMapping.EMPTY).getProperties();
        properties.addAll(pathProperties);
        return properties;
    }

    public boolean allPropertiesForPath(String path) {
        return mappings.getOrDefault(path, GraphMapping.EMPTY).isAllProps();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy