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

org.neo4j.jdbc.values.Values Maven / Gradle / Ivy

/*
 * Copyright (c) 2023-2024 "Neo4j,"
 * Neo4j Sweden AB [https://neo4j.com]
 *
 * This file is part of Neo4j.
 *
 * 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
 *
 *     https://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 org.neo4j.jdbc.values;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.Period;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * Utility for wrapping regular Java types and exposing them as {@link Value} objects, and
 * vice versa.
 * 

* The long set of {@code ofXXX} methods in this class are meant to be used as arguments * for methods like {@link Value#asList(Function)}, {@link Value#asMap(Function)}, * {@link Record#asMap(Function)} and so on. * * @author Neo4j Drivers Team * @since 6.0.0 */ public final class Values { /** * The value instance of an empty map. */ public static final Value EmptyMap = value(Collections.emptyMap()); /** * The value instance of {@code NULL}. */ public static final Value NULL = NullValue.NULL; private Values() { throw new UnsupportedOperationException(); } /** * Returns a value from object. * @param value the object value * @return the array of values */ @SuppressWarnings("unchecked") public static Value value(Object value) { if (value == null) { return NullValue.NULL; } if (value instanceof Value alreadyAValue) { return alreadyAValue; } if (value instanceof Node node) { return new NodeValue(node); } if (value instanceof Relationship relationship) { return new RelationshipValue(relationship); } if (value instanceof Path path) { return new PathValue(path); } if (value instanceof AsValue) { return ((AsValue) value).asValue(); } if (value instanceof Boolean) { return value((boolean) value); } if (value instanceof String) { return value((String) value); } if (value instanceof Character) { return value((char) value); } if (value instanceof Long) { return value((long) value); } if (value instanceof Short) { return value((short) value); } if (value instanceof Byte) { return value((byte) value); } if (value instanceof Integer) { return value((int) value); } if (value instanceof Double) { return value((double) value); } if (value instanceof Float) { return value((float) value); } if (value instanceof LocalDate) { return value((LocalDate) value); } if (value instanceof OffsetTime) { return value((OffsetTime) value); } if (value instanceof LocalTime) { return value((LocalTime) value); } if (value instanceof LocalDateTime) { return value((LocalDateTime) value); } if (value instanceof OffsetDateTime) { return value((OffsetDateTime) value); } if (value instanceof ZonedDateTime) { return value((ZonedDateTime) value); } if (value instanceof IsoDuration) { return value((IsoDuration) value); } if (value instanceof Period) { return value((Period) value); } if (value instanceof Duration) { return value((Duration) value); } if (value instanceof Point) { return value((Point) value); } if (value instanceof List) { return value((List) value); } if (value instanceof Map) { return value((Map) value); } if (value instanceof Iterable) { return value((Iterable) value); } if (value instanceof Iterator) { return value((Iterator) value); } if (value instanceof Stream) { return value((Stream) value); } if (value instanceof char[]) { return value((char[]) value); } if (value instanceof byte[]) { return value((byte[]) value); } if (value instanceof boolean[]) { return value((boolean[]) value); } if (value instanceof String[]) { return value((String[]) value); } if (value instanceof long[]) { return value((long[]) value); } if (value instanceof int[]) { return value((int[]) value); } if (value instanceof short[]) { return value((short[]) value); } if (value instanceof double[]) { return value((double[]) value); } if (value instanceof float[]) { return value((float[]) value); } if (value instanceof Value[]) { return value((Value[]) value); } if (value instanceof Object[]) { return value(Arrays.asList((Object[]) value)); } throw new ValueException("Unable to convert " + value.getClass().getName() + " to Neo4j Value."); } /** * Returns an array of values from object vararg. * @param input the object value(s) * @return the array of values */ public static Value[] values(final Object... input) { return Arrays.stream(input).map(Values::value).toArray(Value[]::new); } /** * Returns a value from value vararg. * @param input the value(s) * @return the value */ public static Value value(Value... input) { var size = input.length; var values = new Value[size]; System.arraycopy(input, 0, values, 0, size); return new ListValue(values); } /** * Returns a value from byte vararg. * @param input the byte value(s) * @return the value */ public static Value value(byte... input) { return new BytesValue(input); } /** * Returns a value from string vararg. * @param input the string value(s) * @return the value */ public static Value value(String... input) { var values = Arrays.stream(input).map(StringValue::new).toArray(StringValue[]::new); return new ListValue(values); } /** * Returns a value from boolean vararg. * @param input the boolean value(s) * @return the value */ public static Value value(boolean... input) { var values = IntStream.range(0, input.length).mapToObj(i -> value(input[i])).toArray(Value[]::new); return new ListValue(values); } /** * Returns a value from char vararg. * @param input the char value(s) * @return the value */ public static Value value(char... input) { var values = IntStream.range(0, input.length).mapToObj(i -> value(input[i])).toArray(Value[]::new); return new ListValue(values); } /** * Returns a value from long vararg. * @param input the long value(s) * @return the value */ public static Value value(long... input) { var values = Arrays.stream(input).mapToObj(Values::value).toArray(Value[]::new); return new ListValue(values); } /** * Returns a value from short vararg. * @param input the short value(s) * @return the value */ public static Value value(short... input) { var values = IntStream.range(0, input.length).mapToObj(i -> value(input[i])).toArray(Value[]::new); return new ListValue(values); } /** * Returns a value from int vararg. * @param input the int value(s) * @return the value */ public static Value value(int... input) { var values = Arrays.stream(input).mapToObj(Values::value).toArray(Value[]::new); return new ListValue(values); } /** * Returns a value from double vararg. * @param input the double value(s) * @return the value */ public static Value value(double... input) { var values = Arrays.stream(input).mapToObj(Values::value).toArray(Value[]::new); return new ListValue(values); } /** * Returns a value from float vararg. * @param input the float value(s) * @return the value */ public static Value value(float... input) { var values = IntStream.range(0, input.length).mapToObj(i -> value(input[i])).toArray(Value[]::new); return new ListValue(values); } /** * Returns a value from list of objects. * @param vals the list of objects * @return the value */ public static Value value(List vals) { var values = new Value[vals.size()]; var i = 0; for (var val : vals) { values[i++] = value(val); } return new ListValue(values); } /** * Returns a value from iterable of objects. * @param val the iterable of objects * @return the value */ public static Value value(Iterable val) { return value(val.iterator()); } /** * Returns a value from iterator of objects. * @param val the iterator of objects * @return the value */ public static Value value(Iterator val) { List values = new ArrayList<>(); while (val.hasNext()) { values.add(value(val.next())); } return new ListValue(values.toArray(new Value[0])); } /** * Returns a value from stream of objects. * @param stream the stream of objects * @return the value */ public static Value value(Stream stream) { var values = stream.map(Values::value).toArray(Value[]::new); return new ListValue(values); } /** * Returns a value from char. * @param val the char value * @return the value */ public static Value value(final char val) { return new StringValue(String.valueOf(val)); } /** * Returns a value from string. * @param val the string value * @return the value */ public static Value value(final String val) { return new StringValue(val); } /** * Returns a value from long. * @param val the long value * @return the value */ public static Value value(final long val) { return new IntegerValue(val); } /** * Returns a value from int. * @param val the int value * @return the value */ public static Value value(final int val) { return new IntegerValue(val); } /** * Returns a value from double. * @param val the double value * @return the value */ public static Value value(final double val) { return new FloatValue(val); } /** * Returns a value from boolean. * @param val the boolean value * @return the value */ @SuppressWarnings("squid:S2301") public static Value value(final boolean val) { return val ? BooleanValue.TRUE : BooleanValue.FALSE; } /** * Returns a value from string to object map. * @param val the string to object map * @return the value */ public static Value value(final Map val) { Map asValues = new HashMap<>(val.size()); for (var entry : val.entrySet()) { asValues.put(entry.getKey(), value(entry.getValue())); } return new MapValue(asValues); } /** * Returns a value from local date. * @param localDate the local date value * @return the value */ public static Value value(LocalDate localDate) { return new DateValue(localDate); } /** * Returns a value from offset time. * @param offsetTime the offset time value * @return the value */ public static Value value(OffsetTime offsetTime) { return new TimeValue(offsetTime); } /** * Returns a value from local time. * @param localTime the local time value * @return the value */ public static Value value(LocalTime localTime) { return new LocalTimeValue(localTime); } /** * Returns a value from local date time. * @param localDateTime the local date time value * @return the value */ public static Value value(LocalDateTime localDateTime) { return new LocalDateTimeValue(localDateTime); } /** * Returns a value from offset date time. * @param offsetDateTime the offset date time value * @return the value */ public static Value value(OffsetDateTime offsetDateTime) { return new DateTimeValue(offsetDateTime.toZonedDateTime()); } /** * Returns a value from zoned date time. * @param zonedDateTime the zoned date time value * @return the value */ public static Value value(ZonedDateTime zonedDateTime) { return new DateTimeValue(zonedDateTime); } /** * Returns a value from period. * @param period the period value * @return the value */ public static Value value(Period period) { return value(new IsoDurationImpl(period)); } /** * Returns a value from duration. * @param duration the duration value * @return the value */ public static Value value(Duration duration) { return value(new IsoDurationImpl(duration)); } /** * Returns a value from month, day, seconds and nanoseconds values. * @param months the month value * @param days the day value * @param seconds the seconds value * @param nanoseconds the nanoseconds value * @return the value */ public static Value isoDuration(long months, long days, long seconds, int nanoseconds) { return value(new IsoDurationImpl(months, days, seconds, nanoseconds)); } /** * Returns a value from ISO duration. * @param duration the ISO duration value * @return the value */ private static Value value(IsoDuration duration) { return new DurationValue(duration); } /** * Returns a value from SRID, x and y values. * @param srid the SRID value * @param x the x value * @param y the y value * @return the value */ public static Value point(int srid, double x, double y) { return value(new Point2DImpl(srid, x, y)); } /** * Returns a value from point. * @param point the point value * @return the value */ private static Value value(Point point) { return new PointValue(point); } /** * Returns a value from SRID, x ,y and z values. * @param srid the SRID value * @param x the x value * @param y the y value * @param z the z value * @return the value */ public static Value point(int srid, double x, double y, double z) { return value(new Point3DImpl(srid, x, y, z)); } /** * Helper function for creating a map of parameters. *

* Allowed parameter types are: *

    *
  • {@link Integer}
  • *
  • {@link Long}
  • *
  • {@link Boolean}
  • *
  • {@link Double}
  • *
  • {@link Float}
  • *
  • {@link String}
  • *
  • {@link Map} with String keys and values being any type in this list
  • *
  • {@link Collection} of any type in this list
  • *
* @param keysAndValues alternating sequence of keys and values * @return map containing all parameters specified */ public static Value parameters(Object... keysAndValues) { if (keysAndValues.length % 2 != 0) { throw new ValueException("Parameters function requires an even number " + "of arguments, " + "alternating key and value. Arguments were: " + Arrays.toString(keysAndValues) + "."); } HashMap map = new HashMap<>(keysAndValues.length / 2); for (var i = 0; i < keysAndValues.length; i += 2) { var value = keysAndValues[i + 1]; assertParameter(value); map.put(keysAndValues[i].toString(), value(value)); } return value(map); } /** * The identity function for value conversion - returns the value untouched. * @return a function that returns the value passed into it - the identity function */ public static Function ofValue() { return Function.identity(); } /** * Converts values to objects using {@link Value#asObject()}. * @return a function that returns {@link Value#asObject()} of a {@link Value} */ public static Function ofObject() { return Value::asObject; } /** * Converts values to {@link Number}. * @return a function that returns {@link Value#asNumber()} of a {@link Value} */ public static Function ofNumber() { return Value::asNumber; } /** * Converts values to {@link String}. *

* If you want to access a string you've retrieved from the database, this is the * right choice. If you want to print any value for human consumption, for instance in * a log, {@link #ofToString()} is the right choice. * @return a function that returns {@link Value#asString()} of a {@link Value} */ public static Function ofString() { return Value::asString; } /** * Converts values using {@link Value#toString()}, a human-readable string description * of any value. *

* This is different from {@link #ofString()}, which returns a java {@link String} * value from a database {@link Type#STRING}. *

* If you are wanting to print any value for human consumption, this is the right * choice. If you are wanting to access a string value stored in the database, you * should use {@link #ofString()}. * @return a function that returns {@link Value#toString()} of a {@link Value} */ public static Function ofToString() { return Value::toString; } /** * Converts values to {@link Integer}. * @return a function that returns {@link Value#asInt()} of a {@link Value} */ public static Function ofInteger() { return Value::asInt; } /** * Converts values to {@link Long}. * @return a function that returns {@link Value#asLong()} of a {@link Value} */ public static Function ofLong() { return Value::asLong; } /** * Converts values to {@link Float}. * @return a function that returns {@link Value#asFloat()} of a {@link Value} */ public static Function ofFloat() { return Value::asFloat; } /** * Converts values to {@link Double}. * @return a function that returns {@link Value#asDouble()} of a {@link Value} */ public static Function ofDouble() { return Value::asDouble; } /** * Converts values to {@link Boolean}. * @return a function that returns {@link Value#asBoolean()} of a {@link Value} */ public static Function ofBoolean() { return Value::asBoolean; } /** * Converts values to {@link Map}. * @return a function that returns {@link Value#asMap()} of a {@link Value} */ public static Function> ofMap() { return MapAccessor::asMap; } /** * Converts values to {@link Map}, with the map values further converted using the * provided converter. * @param valueConverter converter to use for the values of the map * @param the type of values in the returned map * @return a function that returns {@link Value#asMap(Function)} of a {@link Value} */ public static Function> ofMap(final Function valueConverter) { return val -> val.asMap(valueConverter); } /** * Converts values to {@link Entity}. * @return a function that returns {@link Value#asEntity()} of a {@link Value} */ public static Function ofEntity() { return Value::asEntity; } /** * Converts values to {@link Long entity id}. * @return a function that returns the id an entity {@link Value} * @deprecated superseded by {@link #ofEntityElementId()}. */ @Deprecated public static Function ofEntityId() { return val -> val.asEntity().id(); } /** * Converts values to {@link String element id}. * @return a function that returns the element id of an entity {@link Value} */ public static Function ofEntityElementId() { return val -> val.asEntity().elementId(); } /** * Converts values to {@link Node}. * @return a function that returns {@link Value#asNode()} of a {@link Value} */ public static Function ofNode() { return Value::asNode; } /** * Converts values to {@link Relationship}. * @return a function that returns {@link Value#asRelationship()} of a {@link Value} */ public static Function ofRelationship() { return Value::asRelationship; } /** * Converts values to {@link Path}. * @return a function that returns {@link Value#asPath()} of a {@link Value} */ public static Function ofPath() { return Value::asPath; } /** * Converts values to {@link LocalDate}. * @return a function that returns {@link Value#asLocalDate()} of a {@link Value} */ public static Function ofLocalDate() { return Value::asLocalDate; } /** * Converts values to {@link OffsetTime}. * @return a function that returns {@link Value#asOffsetTime()} of a {@link Value} */ public static Function ofOffsetTime() { return Value::asOffsetTime; } /** * Converts values to {@link LocalTime}. * @return a function that returns {@link Value#asLocalTime()} of a {@link Value} */ public static Function ofLocalTime() { return Value::asLocalTime; } /** * Converts values to {@link LocalDateTime}. * @return a function that returns {@link Value#asLocalDateTime()} of a {@link Value} */ public static Function ofLocalDateTime() { return Value::asLocalDateTime; } /** * Converts values to {@link OffsetDateTime}. * @return a function that returns {@link Value#asOffsetDateTime()} of a {@link Value} */ public static Function ofOffsetDateTime() { return Value::asOffsetDateTime; } /** * Converts values to {@link ZonedDateTime}. * @return a function that returns {@link Value#asZonedDateTime()} of a {@link Value} */ public static Function ofZonedDateTime() { return Value::asZonedDateTime; } /** * Converts values to {@link IsoDuration}. * @return a function that returns {@link Value#asIsoDuration()} of a {@link Value} */ public static Function ofIsoDuration() { return Value::asIsoDuration; } /** * Converts values to {@link Point}. * @return a function that returns {@link Value#asPoint()} of a {@link Value} */ public static Function ofPoint() { return Value::asPoint; } /** * Converts values to {@link List} of {@link Object}. * @return a function that returns {@link Value#asList()} of a {@link Value} */ public static Function> ofList() { return Value::asList; } /** * Converts values to {@link List} of {@code T}. * @param innerMap converter for the values inside the list * @param the type of values inside the list * @return a function that returns {@link Value#asList(Function)} of a {@link Value} */ public static Function> ofList(final Function innerMap) { return value -> value.asList(innerMap); } private static void assertParameter(Object value) { if (value instanceof Node || value instanceof NodeValue) { throw new ValueException("Nodes can't be used as parameters."); } if (value instanceof Relationship || value instanceof RelationshipValue) { throw new ValueException("Relationships can't be used as parameters."); } if (value instanceof Path || value instanceof PathValue) { throw new ValueException("Paths can't be used as parameters."); } } }