com.sillelien.dollar.api.types.DollarFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.sillelien.dollar.api.types.DollarFactory.java

Source

/*
 * Copyright (c) 2014-2015 Neil Ellis
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sillelien.dollar.api.types;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.sillelien.dollar.api.*;
import com.sillelien.dollar.api.collections.*;
import com.sillelien.dollar.api.exceptions.DollarFailureException;
import com.sillelien.dollar.api.json.DecodeException;
import com.sillelien.dollar.api.json.ImmutableJsonObject;
import com.sillelien.dollar.api.json.JsonArray;
import com.sillelien.dollar.api.json.JsonObject;
import com.sillelien.dollar.api.json.impl.Json;
import com.sillelien.dollar.api.monitor.DollarMonitor;
import com.sillelien.dollar.api.script.SourceSegment;
import com.sillelien.dollar.api.uri.URI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.json.JSONArray;
import org.json.JSONObject;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;

import static com.sillelien.dollar.api.DollarStatic.$void;

public class DollarFactory {
    /**
     * The constant VALUE_KEY.
     */
    public static final String VALUE_KEY = "value";
    /**
     * The constant VALUE_KEY.
     */
    public static final String POSITIVE_KEY = "positive";
    /**
     * The constant TYPE_KEY.
     */
    public static final String TYPE_KEY = "$type";
    /**
     * The constant LOWERBOUND_KEY.
     */
    public static final String LOWERBOUND_KEY = "lower";
    /**
     * The constant UPPERBOUND_KEY.
     */
    public static final String UPPERBOUND_KEY = "upper";
    /**
     * The constant TEXT_KEY.
     */
    public static final String TEXT_KEY = "text";
    /**
     * The constant MILLISECOND_KEY.
     */
    public static final String MILLISECOND_KEY = "millis";
    /**
     * The constant TRUE.
     */
    public static final var TRUE = wrap(new DollarBoolean(ImmutableList.of(), true));
    /**
     * The constant FALSE.
     */
    public static final var FALSE = wrap(new DollarBoolean(ImmutableList.of(), false));
    /**
     * The constant VOID.
     */
    public static final var VOID = wrap(new DollarVoid());
    /**
     * The constant DOUBLE_ZERO.
     */
    public static final var DOUBLE_ZERO = wrap(new DollarDecimal(ImmutableList.of(), 0.0));
    /**
     * The constant INTEGER_ZERO.
     */
    public static final var INTEGER_ZERO = wrap(new DollarInteger(ImmutableList.of(), 0L));

    public static final var INFINITY = wrap(new DollarInfinity(true));

    /**
     * The Monitor.
     */
    static DollarMonitor monitor = DollarStatic.monitor();
    /**
     * The constant tracer.
     */
    @NotNull
    static StateTracer tracer = DollarStatic.tracer();

    /**
     * From value.
     *
     * @param o      the o
     * @param errors the errors
     *
     * @return the var
     */
    @SafeVarargs
    @NotNull
    public static var fromValue(Object o, @NotNull ImmutableList<Throwable>... errors) {
        return create(ImmutableList.copyOf(errors), o);
    }

    /**
     * From value.
     *
     * @return the var
     */
    @NotNull
    public static var fromValue() {
        return create(ImmutableList.of(), new JsonObject());
    }

    @NotNull
    private static var create(@NotNull ImmutableList<Throwable> errors, @Nullable Object o) {
        if (o == null) {
            if (errors.size() == 0) {
                return VOID;
            }
            return wrap(new DollarVoid(errors));
        }
        if (o instanceof var) {
            return (var) o;
        }
        if (o instanceof Boolean) {
            if (errors.size() == 0) {
                if ((Boolean) o) {
                    return TRUE;
                } else {
                    return FALSE;
                }
            }
            return wrap(new DollarBoolean(errors, (Boolean) o));
        }

        if (o instanceof Pipeable) {
            return wrap((var) java.lang.reflect.Proxy.newProxyInstance(DollarStatic.class.getClassLoader(),
                    new Class<?>[] { var.class }, new DollarLambda((Pipeable) o)));
        }
        if (o instanceof File) {
            try {
                try (FileInputStream stream = new FileInputStream((File) o)) {
                    return create(errors, stream);
                }
            } catch (IOException e) {
                return failure(e);
            }
        }
        if (o instanceof JsonArray) {
            return wrap(new DollarList(errors, (JsonArray) o));
        }
        if (o instanceof JsonObject) {
            return wrap(new DollarMap(errors, new ImmutableJsonObject((JsonObject) o)));
        }
        if (o instanceof JSONObject || o instanceof ObjectNode) {
            return wrap(new DollarMap(errors, new JsonObject(o.toString())));
        }
        if (o instanceof JSONArray || o instanceof ArrayNode) {
            return wrap(new DollarList(errors, new JsonArray(o.toString())));
        }
        if (o instanceof ImmutableMap) {
            return wrap(new DollarMap(errors, ((ImmutableMap<?, ?>) o).mutable()));
        }
        if (o instanceof Map) {
            return wrap(new DollarMap(errors, (Map) o));
        }
        if (o instanceof ImmutableList) {
            return wrap(new DollarList(errors, (ImmutableList<?>) o));
        }
        if (o instanceof List) {
            return wrap(new DollarList(errors, ImmutableList.copyOf((List) o)));
        }
        if (o instanceof Collection) {
            return wrap(new DollarList(errors, ImmutableList.copyOf(new ArrayList<>((Collection<?>) o))));
        }
        if (o.getClass().isArray()) {
            return wrap(new DollarList(errors, (Object[]) o));
        }
        if (o instanceof URI) {
            return wrap(new DollarURI(errors, (URI) o));
        }
        if (o instanceof java.net.URI || o instanceof java.net.URL) {
            return wrap(new DollarURI(errors, URI.parse(o.toString())));
        }
        if (o instanceof Date) {
            return wrap(new DollarDate(errors, ((Date) o).getTime()));
        }
        if (o instanceof LocalDateTime) {
            return wrap(new DollarDate(errors, (LocalDateTime) o));
        }
        if (o instanceof Instant) {
            return wrap(new DollarDate(errors, (Instant) o));
        }
        if (o instanceof Double) {
            if (errors.size() == 0 && (Double) o == 0.0) {
                return DOUBLE_ZERO;
            }
            return wrap(new DollarDecimal(errors, (Double) o));
        }
        if (o instanceof BigDecimal) {
            if (errors.size() == 0 && ((BigDecimal) o).doubleValue() == 0.0) {
                return DOUBLE_ZERO;
            }
            return wrap(new DollarDecimal(errors, ((BigDecimal) o).doubleValue()));
        }
        if (o instanceof Float) {
            if (errors.size() == 0 && (Float) o == 0.0) {
                return DOUBLE_ZERO;
            }
            return wrap(new DollarDecimal(errors, ((Float) o).doubleValue()));
        }
        if (o instanceof Long) {
            if (errors.size() == 0 && (Long) o == 0) {
                return INTEGER_ZERO;
            }
            return wrap(new DollarInteger(errors, (Long) o));
        }
        if (o instanceof Integer) {
            if (errors.size() == 0 && (Integer) o == 0) {
                return INTEGER_ZERO;
            }
            return wrap(new DollarInteger(errors, ((Integer) o).longValue()));
        }
        if (o instanceof Short) {
            if (errors.size() == 0 && (Short) o == 0) {
                return INTEGER_ZERO;
            }
            return wrap(new DollarInteger(errors, ((Short) o).longValue()));
        }
        if (o instanceof Range) {
            return wrap(new DollarRange(errors, (Range) o));
        }
        if (o instanceof ImmutableJsonObject) {
            return wrap(new DollarMap(errors, (ImmutableJsonObject) o));
        }
        if (o instanceof InputStream) {
            try {
                return create(errors, CollectionUtil.fromStream((InputStream) o));
            } catch (IOException e) {
                return failure(e);
            }
        }
        if (o instanceof String) {
            if (((String) o).matches("^[a-zA-Z0-9]+$")) {
                return wrap(new DollarString(errors, (String) o));

            } else if (((String) o).matches("^\\s*\\[.*")) {
                return wrap(new DollarList(errors, new JsonArray(o.toString())));
            } else if (((String) o).matches("^\\s*\\{.*")) {
                try {
                    return wrap(new DollarMap(errors, new JsonObject((String) o)));
                } catch (DecodeException de) {
                    de.printStackTrace(System.err);
                    return wrap(new DollarString(errors, (String) o));
                }
            } else {
                return wrap(new DollarString(errors, (String) o));
            }
        }
        JsonObject json;
        if (o instanceof MultiMap) {
            json = DollarStatic.mapToJson((MultiMap) o);
        } else {
            json = Json.fromJavaObject(o);
        }
        return wrap(new DollarMap(errors, json));
    }

    //
    //    /**
    //     * From gson object.
    //     *
    //     * @param o the o
    //     * @return the var
    //     */
    //    @NotNull
    //    public static var fromGsonObject(Object o) {
    //        Gson gson = new Gson();
    //        String json = gson.toJson(o);
    //        return create(ImmutableList.<Throwable>of(), json);
    //    }

    /**
     * From value.
     *
     * @param o the o
     * @return the var
     */
    @NotNull
    public static var fromValue(Object o) {
        return fromValue(o, ImmutableList.of());
    }

    /**
     * Failure var.
     *
     * @param errorType the failure type
     * @return the var
     */
    @NotNull
    public static var failure(ErrorType errorType) {
        if (DollarStatic.getConfig().failFast()) {
            throw new DollarFailureException(errorType);
        } else {
            return wrap(new DollarError(errorType, ""));
        }
    }

    /**
     * Wrap var.
     *
     * @param value the value
     * @return the var
     */
    @NotNull
    public static var wrap(var value) {
        return wrap(value, DollarStatic.monitor(), DollarStatic.tracer());
    }

    @NotNull
    private static var wrap(var value, DollarMonitor monitor, StateTracer tracer) {
        final var val;
        if (DollarStatic.getConfig().wrapForMonitoring()) {
            val = new DollarWrapper(value, monitor, tracer);
        } else {
            val = value;
        }
        if (DollarStatic.getConfig().wrapForGuards()) {
            return (var) java.lang.reflect.Proxy.newProxyInstance(DollarStatic.class.getClassLoader(),
                    new Class<?>[] { var.class }, new DollarGuard(val));
        } else {
            return val;
        }

    }

    /**
     * Failure var.
     *
     * @param errorType the failure type
     * @param t the t
     * @param quiet to always avoid failing fast
     * @return the var
     */
    @NotNull
    public static var failure(ErrorType errorType, @NotNull Throwable t, boolean quiet) {
        if (DollarStatic.getConfig().failFast() && !quiet) {
            throw new DollarFailureException(t, errorType);
        } else {
            //            t.printStackTrace(System.err);
            return wrap(new DollarError(ImmutableList.of(t), errorType, t.getMessage()));
        }
    }

    /**
     * Failure var.
     *
     * @param errorType the failure type
     * @param t the t
     * @return the var
     */
    @NotNull
    public static var failure(ErrorType errorType, @NotNull Throwable t) {
        if (DollarStatic.getConfig().failFast()) {
            throw new DollarFailureException(t, errorType);
        } else {
            //            t.printStackTrace(System.err);
            return wrap(new DollarError(ImmutableList.of(t), errorType, t.getMessage()));
        }
    }

    /**
     * Failure var.
     *
     * @param errorType the failure type
     * @param message   the message
     * @return the var
     */
    @NotNull
    public static var failure(ErrorType errorType, String message) {
        if (DollarStatic.getConfig().failFast()) {
            throw new DollarFailureException(errorType, message);
        } else {
            return wrap(new DollarError(ImmutableList.of(new DollarException(message)), errorType, message));
        }
    }

    /**
     * Failure var.
     *
     * @param errorType the failure type
     * @param message   the message
     * @param quiet     the quiet
     * @return the var
     */
    @NotNull
    public static var failure(ErrorType errorType, String message, boolean quiet) {
        if (DollarStatic.getConfig().failFast() && !quiet) {
            throw new DollarFailureException(errorType, message);
        } else {
            return wrap(new DollarError(ImmutableList.of(new DollarException(message)), errorType, message));
        }
    }

    /**
     * Failure var.
     *
     * @param throwable the throwable
     * @return the var
     */
    @NotNull
    public static var failure(@NotNull Throwable throwable) {
        return failure(ErrorType.EXCEPTION, throwable, false);
    }

    /**
     * New void.
     *
     * @return the var
     */
    @NotNull
    public static var newVoid() {
        return wrap(new DollarVoid());
    }

    /**
     * From string value.
     *
     * @param body the body
     * @return the var
     */
    @NotNull
    public static var fromStringValue(@NotNull String body) {
        return wrap(new DollarString(ImmutableList.of(), body));
    }

    /**
     * From string value.
     *
     * @param body the body
     * @return the var
     */
    @SafeVarargs
    @NotNull
    public static var fromStringValue(@NotNull String body, ImmutableList<Throwable>... errors) {
        return wrap(new DollarString(ImmutableList.copyOf(errors), body));
    }

    /**
     * From lambda.
     *
     * @param pipeable the pipeable
     * @return the var
     */
    @NotNull
    public static var fromLambda(Pipeable pipeable) {
        return fromValue(pipeable);
    }

    /**
     * From uRI.
     *
     * @param from the from
     * @return the var
     */
    @NotNull
    public static var fromURI(@NotNull var from) {
        if (from.uri()) {
            return from;
        } else {
            return fromURI(from.$S());
        }
    }

    /**
     * From uRI.
     *
     * @param uri the uri
     * @return the var
     */
    @NotNull
    public static var fromURI(String uri) {
        try {
            return wrap(new DollarURI(ImmutableList.of(), URI.parse(uri)));
        } catch (Exception e) {
            return DollarStatic.handleError(e, null);
        }
    }

    /**
     * From stream.
     *
     * @param type the type
     * @param rawBody the raw body
     * @return the var
     * @throws IOException the iO exception
     */
    @NotNull
    public static var fromStream(SerializedType type, InputStream rawBody) throws IOException {
        if (type == SerializedType.JSON) {
            ObjectMapper mapper = new ObjectMapper();
            final JsonNode jsonNode = mapper.readTree(rawBody);
            if (jsonNode.isArray()) {
                return create(ImmutableList.<Throwable>of(), jsonNode);
            } else if (jsonNode.isObject()) {
                return create(ImmutableList.<Throwable>of(), jsonNode);
            } else {
                throw new DollarException("Could not deserialize JSON, not array or object");
            }
        } else {
            throw new DollarException("Could not deserialize " + type);
        }
    }

    /**
     * From future.
     *
     * @param future the future
     * @return the var
     */
    @NotNull
    public static var fromFuture(@NotNull Future<var> future) {
        return wrap((var) java.lang.reflect.Proxy.newProxyInstance(DollarStatic.class.getClassLoader(),
                new Class<?>[] { var.class }, new DollarLambda(i -> future.get(), false)));
    }

    /**
     * Failure with source.
     *
     * @param errorType the failure type
     * @param throwable the throwable
     * @param source the source
     * @return the var
     */
    @NotNull
    public static var failureWithSource(ErrorType errorType, Throwable throwable, @Nullable SourceSegment source) {
        if (source == null) {
            throw new NullPointerException();
        }
        if (DollarStatic.getConfig().failFast()) {
            final DollarFailureException dollarFailureException = new DollarFailureException(throwable, errorType);
            dollarFailureException.addSource(source);
            throw dollarFailureException;
        } else {
            return wrap(new DollarError(ImmutableList.of(throwable), errorType, null));
        }
    }

    /**
     * Block collection.
     *
     * @param var the var
     * @return the var
     */
    @NotNull
    public static var blockCollection(List<var> var) {
        return wrap(new DollarBlockCollection(var));
    }

    /**
     * Deserialize var.
     *
     * @param s the s
     * @return the var
     */
    @NotNull
    public static var deserialize(String s) {
        JsonObject jsonObject = new JsonObject(s);
        return fromJson(jsonObject);
    }

    @NotNull
    private static var fromJson(@NotNull JsonObject jsonObject) {
        final Type type;
        if (!jsonObject.containsField(TYPE_KEY)) {
            type = Type.MAP;
        } else {
            type = Type.valueOf(jsonObject.getString(TYPE_KEY));
        }

        if (type.equals(Type.VOID)) {
            return $void();
        } else if (type.equals(Type.INTEGER)) {
            return fromValue(jsonObject.getLong(VALUE_KEY));
        } else if (type.equals(Type.BOOLEAN)) {
            return fromValue(jsonObject.getBoolean(VALUE_KEY));
        } else if (type.equals(Type.DATE)) {
            return wrap(new DollarDate(ImmutableList.of(), Instant.parse(jsonObject.getString(TEXT_KEY))));
        } else if (type.equals(Type.DECIMAL)) {
            return fromValue(jsonObject.getNumber(VALUE_KEY));
        } else if (type.equals(Type.LIST)) {
            final JsonArray array = jsonObject.getArray(VALUE_KEY);
            ArrayList<Object> arrayList = new ArrayList<>();
            for (Object o : array) {
                arrayList.add(fromJson(o));
            }
            return wrap(new DollarList(ImmutableList.of(), ImmutableList.copyOf(arrayList)));
        } else if (type.equals(Type.MAP)) {
            final JsonObject json;
            json = jsonObject;
            LinkedHashMap<String, Object> map = new LinkedHashMap<>();
            final Set<String> fieldNames = json.getFieldNames();
            for (String fieldName : fieldNames) {
                if (!fieldName.equals(TYPE_KEY)) {
                    map.put(fieldName, fromJson(json.get(fieldName)));
                }
            }
            return wrap(new DollarMap(ImmutableList.of(), map));
        } else if (type.equals(Type.ERROR)) {
            final String errorType = jsonObject.getString("errorType");
            final String errorMessage = jsonObject.getString("errorMessage");
            return wrap(new DollarError(ImmutableList.<Throwable>of(), ErrorType.valueOf(errorType), errorMessage));
        } else if (type.equals(Type.RANGE)) {
            final var lower = fromJson(jsonObject.get(LOWERBOUND_KEY));
            final var upper = fromJson(jsonObject.get(UPPERBOUND_KEY));
            return wrap(new DollarRange(ImmutableList.of(), lower, upper));
        } else if (type.equals(Type.URI)) {
            return wrap(new DollarURI(ImmutableList.of(), URI.parse(jsonObject.getString(VALUE_KEY))));
        } else if (type.equals(Type.INFINITY)) {
            return wrap(new DollarInfinity(ImmutableList.of(), jsonObject.getBoolean(POSITIVE_KEY)));
        } else if (type.equals(Type.STRING)) {
            if (!(jsonObject.get(VALUE_KEY) instanceof String)) {
                System.out.println(jsonObject.get(VALUE_KEY));
            }
            return wrap(new DollarString(ImmutableList.of(), jsonObject.getString(VALUE_KEY)));
        } else {
            throw new DollarException("Unrecognized type " + type);
        }
    }

    @NotNull
    private static var fromJson(@Nullable Object value) {
        if (value == null) {
            return $void();
        } else if (value instanceof LinkedHashMap) {
            JsonObject json = new JsonObject((Map<String, Object>) value);
            //            if (json.containsField(TYPE_KEY)) {
            return fromJson(json);
            //            } else {
            //                return fromValue(value);
            //            }
        } else if (value instanceof ArrayList) {
            ArrayList list = (ArrayList) value;
            ArrayList<var> result = new ArrayList<>();
            for (Object o : list) {
                result.add(fromJson(o));
            }
            return fromValue(result);

        } else if (value instanceof JsonObject) {
            if (((JsonObject) value).containsField(TYPE_KEY)) {
                return fromJson((JsonObject) value);
            } else {
                return fromValue(value);
            }
        } else if (value instanceof JsonArray) {
            return fromValue(value);
        } else if (value instanceof String) {
            return fromValue(value);
        } else if (value instanceof Number) {
            return fromValue(value);
        } else if (value instanceof Boolean) {
            return fromValue(value);
        } else if (value instanceof byte[]) {
            return fromValue(value);
        } else {
            throw new DollarException("Unrecognized type " + value.getClass() + " for " + value);
        }
    }

    /**
     * Serialize string.
     *
     * @param value the value
     * @return the string
     */
    public static String serialize(@NotNull var value) {
        final Object jsonObject = toJson(value._fixDeep());
        return jsonObject.toString();
    }

    @NotNull
    private static JsonObject valueToJson(@NotNull var value) {
        final JsonObject jsonObject = new JsonObject();
        jsonObject.putString(TYPE_KEY, value.$type().name());
        jsonObject.putValue(VALUE_KEY, value.toJavaObject());
        return jsonObject;
    }

    /**
     * To json.
     *
     * @param value the value
     * @return the object
     */
    @Nullable
    public static Object toJson(@NotNull var value) {
        Type i = value.$type();
        if (i.equals(Type.VOID) || i.equals(Type.INTEGER) || i.equals(Type.BOOLEAN) || i.equals(Type.DECIMAL)
                || i.equals(Type.STRING)) {
            return value.toJavaObject();
        } else if (i.equals(Type.DATE)) {
            final JsonObject jsonObject = new JsonObject();
            jsonObject.putString(TYPE_KEY, value.$type().name());
            jsonObject.putString(TEXT_KEY, value.$S());
            jsonObject.putNumber(MILLISECOND_KEY, (long) (value.toDouble() * 24 * 60 * 60 * 1000));
            return jsonObject;
        } else if (i.equals(Type.URI)) {
            final JsonObject uriJsonObject = new JsonObject();
            uriJsonObject.putString(TYPE_KEY, value.$type().name());
            uriJsonObject.putString(VALUE_KEY, value.$S());
            return uriJsonObject;
        } else if (i.equals(Type.ERROR)) {
            final JsonObject errorJsonObject = new JsonObject();
            errorJsonObject.putString(TYPE_KEY, value.$type().name());
            errorJsonObject.putValue(VALUE_KEY, value.toJsonType());
            return errorJsonObject;
        } else if (i.equals(Type.INFINITY)) {
            final JsonObject infinityJsonObject = new JsonObject();
            infinityJsonObject.putString(TYPE_KEY, value.$type().name());
            infinityJsonObject.putValue(POSITIVE_KEY, value.positive());
            return infinityJsonObject;
        } else if (i.equals(Type.LIST) || i.equals(Type.QUEUE)) {
            final JsonArray array = new JsonArray();
            ImmutableList<var> arrayList = value.toVarList();
            for (var v : arrayList) {
                array.add(toJson(v));
            }

            return array;
        } else if (i.equals(Type.MAP)) {
            final JsonObject json = new JsonObject();
            ImmutableMap<var, var> map = value.toVarMap();
            final Set<var> fieldNames = map.keySet();
            for (var fieldName : fieldNames) {
                var v = map.get(fieldName);
                json.putValue(fieldName.toString(), toJson(v));
            }
            final JsonObject containerObject = new JsonObject();
            //            json.putString(TYPE_KEY, value.$type().name());
            return json;
        } else if (i.equals(Type.RANGE)) {
            final JsonObject rangeObject = new JsonObject();
            rangeObject.putString(TYPE_KEY, value.$type().name());
            final Range range = value.toJavaObject();
            rangeObject.putValue(LOWERBOUND_KEY, toJson(range.lowerEndpoint()));
            rangeObject.putValue(UPPERBOUND_KEY, toJson(range.upperEndpoint()));
            return rangeObject;
        } else if (i.equals(Type.ANY)) {
            return null;
        } else {
            throw new DollarException("Unrecognized type " + value.$type());
        }
    }

    /**
     * From range.
     *
     * @param from the from
     * @param to   the to
     *
     * @return the var
     */
    @NotNull
    public static var fromRange(var from, var to) {
        return wrap(new DollarRange(ImmutableList.of(), from, to));
    }

    @SafeVarargs
    @NotNull
    public static var infinity(boolean positive, ImmutableList<Throwable>... errors) {
        return wrap(new DollarInfinity(ImmutableList.copyOf(errors), positive));
    }

    @SafeVarargs
    @NotNull
    public static var newNull(Type type, ImmutableList<Throwable>... errors) {
        return new DollarNull(ImmutableList.copyOf(errors), type);
    }

    @NotNull
    public static var fromYaml(String yamlString) {
        Yaml yaml = new Yaml();
        return wrap(fromValue(yaml.load(yamlString)));
    }

    public static var fromYaml(File yamlFile) {
        Yaml yaml = new Yaml();
        try (FileInputStream fileInputStream = new FileInputStream(yamlFile)) {
            return wrap(fromValue(yaml.load(fileInputStream)));
        } catch (FileNotFoundException e) {
            return failure(e);
        } catch (IOException e) {
            return failure(e);
        }
    }

    @NotNull
    public static var fromMap(ImmutableMap<var, var> entries) {
        return wrap(new DollarMap(ImmutableList.of(), entries.mutable()));
    }

    @NotNull
    public static var fromList(ImmutableList<var> vars) {
        return wrap(new DollarList(ImmutableList.of(), vars));
    }

    @NotNull
    public static var fromList(ArrayList<var> vars) {
        return wrap(new DollarList(ImmutableList.of(), ImmutableList.copyOf(vars)));
    }

    @NotNull
    public static var fromQueue(LinkedBlockingDeque<var> linkedBlockingDeque) {
        return wrap(new DollarQueue(ImmutableList.of(), linkedBlockingDeque));
    }

    public static var fromPair(Object k, Object v) {
        ImmutableList<Throwable> empty = ImmutableList.of();
        return wrap(new DollarMap(empty, ImmutableMap.of(create(empty, k), create(empty, v))));
    }
}