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

com.dimajix.shaded.everit.schema.loader.JsonValue Maven / Gradle / Ivy

There is a newer version: 1.2.0-synapse3.3-spark3.3-hadoop3.3
Show newest version
package com.dimajix.shaded.everit.schema.loader;

import static com.dimajix.shaded.everit.schema.loader.OrgJsonUtil.toList;
import static com.dimajix.shaded.everit.schema.loader.OrgJsonUtil.toMap;
import static com.dimajix.shaded.everit.schema.loader.SpecificationVersion.DRAFT_4;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;

import com.dimajix.shaded.everit.schema.SchemaException;
import com.dimajix.shaded.json.JSONArray;
import com.dimajix.shaded.json.JSONObject;

/**
 * @author erosb
 */
class JsonValue {

    class Multiplexer {

        protected Map, Function> actions = new HashMap<>();

        Multiplexer(Class expectedType, Function mapper) {
            actions.put(expectedType, mapper);
        }

         Multiplexer orMappedTo(Class expectedType, Function mapper) {
            actions.put(expectedType, mapper);
            return this;
        }

        R requireAny() {
            if (typeOfValue() == null) {
                throw multiplexFailure();
            }
            Function consumer = (Function) actions.keySet().stream()
                    .filter(clazz -> clazz.isAssignableFrom(typeOfValue()))
                    .findFirst()
                    .map(actions::get)
                    .orElseThrow(() -> multiplexFailure());
            return consumer.apply(value());
        }

        protected SchemaException multiplexFailure() {
            return ls.createSchemaException(typeOfValue(), actions.keySet());
        }

    }

    class VoidMultiplexer extends Multiplexer {

        VoidMultiplexer(Class expectedType, Consumer consumer) {
            super(expectedType, obj -> {
                ((Consumer) consumer).accept(obj);
                return null;
            });
        }

         VoidMultiplexer or(Class expectedType, Consumer consumer) {
            actions.put(expectedType, obj -> {
                ((Consumer) consumer).accept(obj);
                return null;
            });
            return this;
        }

    }

    private class VoidMultiplexerWithSchemaPredicate extends VoidMultiplexer {

        private Consumer action;

        VoidMultiplexerWithSchemaPredicate(Consumer action) {
            super(JsonObject.class, action);
            this.action = action;
        }

        @Override Void requireAny() {
            if (typeOfValue() == Boolean.class) {
                action.accept(JsonValue.this);
                return null;
            }
            return super.requireAny();
        }

        @Override
        protected SchemaException multiplexFailure() {
            Set> expectedTypes = new HashSet<>(actions.keySet());
            expectedTypes.add(Boolean.class);
            return ls.createSchemaException(typeOfValue(), expectedTypes);
        }
    }

    private static final Function IDENTITY = e -> e;

    static final  Function identity() {
        return (Function) IDENTITY;
    }

    static JsonValue of(Object obj) {
        if (obj instanceof JsonValue) {
            return (JsonValue) obj;
        } else if (obj instanceof Map) {
            return new JsonObject((Map) obj);
        } else if (obj instanceof List) {
            return new JsonArray((List) obj);
        } else if (obj instanceof JSONObject) {
            return new JsonObject(toMap((JSONObject) obj));
        } else if (obj instanceof JSONArray) {
            return new JsonArray(toList((JSONArray) obj));
        }
        return new JsonValue(obj);
    }

    protected Object value() {
        return obj;
    }

    protected Object unwrap() {
        return value();
    }

    private final Object obj;

    protected LoadingState ls;

    protected JsonValue(Object obj) {
        this.obj = obj;
    }

    public  VoidMultiplexer canBe(Class expectedType, Consumer consumer) {
        return new VoidMultiplexer(expectedType, consumer);
    }

    public VoidMultiplexer canBeSchema(Consumer consumer) {
        if (DRAFT_4.equals(this.ls.specVersion())) {
            return new VoidMultiplexer(JsonObject.class, consumer);
        } else {
            return new VoidMultiplexerWithSchemaPredicate(consumer);
        }
    }

    public  Multiplexer canBeMappedTo(Class expectedType, Function mapper) {
        return new Multiplexer(expectedType, mapper);
    }

    protected Class typeOfValue() {
        return obj == null ? null : obj.getClass();
    }

    @Override public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        JsonValue that = (JsonValue) o;

        return Objects.equals(obj, that.obj);
    }

    @Override public int hashCode() {
        return obj != null ? obj.hashCode() : 0;
    }

    @Override public String toString() {
        return "JsonValue{" +
                "obj=" + obj +
                '}';
    }

    public String requireString() {
        return requireString(identity());
    }

    public  R requireString(Function mapper) {
        if (obj instanceof String) {
            return mapper.apply((String) obj);
        }
        throw ls.createSchemaException(typeOfValue(), String.class);
    }

    public Boolean requireBoolean() {
        return requireBoolean(identity());
    }

    public  R requireBoolean(Function mapper) {
        if (obj instanceof Boolean) {
            return mapper.apply((Boolean) obj);
        }
        throw ls.createSchemaException(typeOfValue(), Boolean.class);
    }

    public JsonObject requireObject() {
        return requireObject(identity());
    }

    public  R requireObject(Function mapper) {
        throw ls.createSchemaException(typeOfValue(), JsonObject.class);
    }

    public JsonArray requireArray() {
        return requireArray(identity());
    }

    public  R requireArray(Function mapper) {
        throw ls.createSchemaException(typeOfValue(), JsonArray.class);
    }

    public Number requireNumber() {
        return requireNumber(identity());
    }

    public  R requireNumber(Function mapper) {
        if (obj instanceof Number) {
            return mapper.apply((Number) obj);
        }
        throw ls.createSchemaException(typeOfValue(), Number.class);
    }

    public Integer requireInteger() {
        return requireInteger(identity());
    }

    public  R requireInteger(Function mapper) {
        if (obj instanceof Integer) {
            return mapper.apply((Integer) obj);
        }
        throw ls.createSchemaException(typeOfValue(), Integer.class);
    }

    protected static Object deepToOrgJson(JsonValue v) {
        if (v.unwrap() == null) {
            return JSONObject.NULL;
        }
        if (v instanceof JsonObject) {
            JSONObject obj = new JSONObject();
            ((JsonObject) v).forEach((key, value) -> obj.put(key, deepToOrgJson(value)));
            return obj;
        } else if (v instanceof JsonArray) {
            JSONArray array = new JSONArray();
            ((JsonArray) v).forEach((index, value) -> array.put(deepToOrgJson(value)));
            return array;
        } else
            return v.unwrap();
    }
}