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

graphql.servlet.internal.VariableMapper Maven / Gradle / Ivy

There is a newer version: 16.0.0
Show newest version
package graphql.servlet.internal;

import javax.servlet.http.Part;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public class VariableMapper {
    private static final Pattern PERIOD = Pattern.compile("\\.");

    private static final Mapper> MAP_MAPPER = new Mapper>() {
        @Override
        public Object set(Map location, String target, Part value) {
            return location.put(target, value);
        }

        @Override
        public Object recurse(Map location, String target) {
            return location.get(target);
        }
    };
    private static final Mapper> LIST_MAPPER = new Mapper>() {
        @Override
        public Object set(List location, String target, Part value) {
            return location.set(Integer.parseInt(target), value);
        }

        @Override
        public Object recurse(List location, String target) {
            return location.get(Integer.parseInt(target));
        }
    };

    public static void mapVariable(String objectPath, Map variables, Part part) {
        String[] segments = PERIOD.split(objectPath);

        if (segments.length < 2) {
            throw new RuntimeException("object-path in map must have at least two segments");
        } else if (!"variables".equals(segments[0])) {
            throw new RuntimeException("can only map into variables");
        }

        Object currentLocation = variables;
        for (int i = 1; i < segments.length; i++) {
            String segmentName = segments[i];
            Mapper mapper = determineMapper(currentLocation, objectPath, segmentName);

            if (i == segments.length - 1) {
                if (null != mapper.set(currentLocation, segmentName, part)) {
                    throw new RuntimeException("expected null value when mapping " + objectPath);
                }
            } else {
                currentLocation = mapper.recurse(currentLocation, segmentName);
                if (null == currentLocation) {
                    throw new RuntimeException("found null intermediate value when trying to map " + objectPath);
                }
            }
        }
    }

    private static Mapper determineMapper(Object currentLocation, String objectPath, String segmentName) {
        if (currentLocation instanceof Map) {
            return MAP_MAPPER;
        } else if (currentLocation instanceof List) {
            return LIST_MAPPER;
        }

        throw new RuntimeException("expected a map or list at " + segmentName + " when trying to map " + objectPath);
    }

    interface Mapper {
        Object set(T location, String target, Part value);

        Object recurse(T location, String target);
    }
}