diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/temporal/TemporalFunction.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/temporal/TemporalFunction.java index 5a39f12bf3643..c1940584a17a0 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/temporal/TemporalFunction.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/temporal/TemporalFunction.java @@ -21,8 +21,6 @@ import java.time.Clock; import java.time.ZoneId; -import java.time.temporal.ChronoUnit; -import java.time.temporal.IsoFields; import java.time.temporal.TemporalUnit; import java.util.Arrays; import java.util.List; @@ -42,6 +40,7 @@ import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.procedure.Description; import org.neo4j.values.AnyValue; +import org.neo4j.values.storable.TemporalProperties; import org.neo4j.values.storable.TemporalValue; import org.neo4j.values.storable.TextValue; import org.neo4j.values.storable.Values; @@ -284,51 +283,15 @@ public T apply( Context ctx, AnyValue[] args ) throws ProcedureException if ( unit instanceof TextValue && input instanceof TemporalValue && fields instanceof MapValue ) { return function.truncate( - unit( ((TextValue) unit).stringValue() ), - (TemporalValue)input, + TemporalProperties.fromName( ((TextValue) unit).stringValue() ).unit, + (TemporalValue) input, (MapValue) fields, function.defaultZone ); } } - throw new ProcedureException( Status.Procedure.ProcedureCallFailed, "Invalid call signature for " + getClass().getSimpleName() + + throw new ProcedureException( Status.Procedure.ProcedureCallFailed, + "Invalid call signature for " + getClass().getSimpleName() + ": Provided input was " + Arrays.toString( args ) ); } - - private static TemporalUnit unit( String unit ) - { - switch ( unit ) - { - case "millennium": - return ChronoUnit.MILLENNIA; - case "century": - return ChronoUnit.CENTURIES; - case "decade": - return ChronoUnit.DECADES; - case "year": - return ChronoUnit.YEARS; - case "weekYear": - return IsoFields.WEEK_BASED_YEARS; - case "quarter": - return IsoFields.QUARTER_YEARS; - case "month": - return ChronoUnit.MONTHS; - case "week": - return ChronoUnit.WEEKS; - case "day": - return ChronoUnit.DAYS; - case "hour": - return ChronoUnit.HOURS; - case "minute": - return ChronoUnit.MINUTES; - case "second": - return ChronoUnit.SECONDS; - case "millisecond": - return ChronoUnit.MILLIS; - case "microsecond": - return ChronoUnit.MICROS; - default: - throw new IllegalArgumentException( "Unsupported unit: " + unit ); - } - } } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/DurationProperties.java b/community/values/src/main/java/org/neo4j/values/storable/DurationProperties.java new file mode 100644 index 0000000000000..7f49d3d20cd06 --- /dev/null +++ b/community/values/src/main/java/org/neo4j/values/storable/DurationProperties.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.values.storable; + +import org.neo4j.values.utils.UnsupportedTemporalUnitException; + +import static org.neo4j.values.utils.TemporalUtil.NANOS_PER_SECOND; + +public enum DurationProperties +{ + YEARS( "years" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return months / 12; + } + }, + MONTHS( "months" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return months; + } + }, + MONTHS_OF_YEAR( "monthsofyear" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return months % 12; + } + }, + MONTHS_OF_QUARTER( "monthsofquarter" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return months % 3; + } + }, + QUARTERS( "quarters" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return months / 3; + } + }, + QUARTERS_OF_YEAR( "quartersofyear" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return (months / 3) % 4; + } + }, + WEEKS( "weeks" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return days / 7; + } + }, + DAYS_OF_WEEK( "daysofweek" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return days % 7; + } + }, + DAYS( "days" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return days; + } + }, + HOURS( "hours" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return seconds / 3600; + } + }, + MINUTES_OF_HOUR( "minutesofhour" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return (seconds / 60) % 60; + } + }, + MINUTES( "minutes" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return seconds / 60; + } + }, + SECONDS_OF_MINUTE( "secondsofminute" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return seconds % 60; + } + }, + SECONDS( "seconds" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return seconds; + } + }, + MILLISECONDS_OF_SECOND( "millisecondsofsecond" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return nanos / 1000_000; + } + }, + MILLISECONDS( "milliseconds" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return seconds * 1000 + nanos / 1000_000; + } + }, + MICROSECONDS_OF_SECOND( "microsecondsofsecond" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return nanos / 1000; + } + }, + MICROSECONDS( "microseconds" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return seconds * 1000_000 + nanos / 1000; + } + }, + NANOSECONDS_OF_SECOND( "nanosecondsofsecond" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return nanos; + } + }, + NANOSECONDS( "nanoseconds" ) + { + @Override + public long asTimeStamp( long months, long days, long seconds, long nanos ) + { + return seconds * NANOS_PER_SECOND + nanos; + } + }; + + + public String propertyKey; + + DurationProperties( String propertyKey ) + { + this.propertyKey = propertyKey; + } + + public abstract long asTimeStamp( long months, long days, long seconds, long nanos ); + + public static DurationProperties fromName( String fieldName ) + { + switch ( fieldName.toLowerCase() ) + { + case "years": + return YEARS; + case "months": + return MONTHS; + case "monthsofyear": + return MONTHS_OF_YEAR; + case "monthsofquarter": + return MONTHS_OF_QUARTER; + case "quarters": + return QUARTERS; + case "quartersofyear": + return QUARTERS_OF_YEAR; + case "weeks": + return WEEKS; + case "daysofweek": + return DAYS_OF_WEEK; + case "days": + return DAYS; + case "hours": + return HOURS; + case "minutesofhour": + return MINUTES_OF_HOUR; + case "minutes": + return MINUTES; + case "secondsofminute": + return SECONDS_OF_MINUTE; + case "seconds": + return SECONDS; + case "millisecondsofsecond": + return MICROSECONDS_OF_SECOND; + case "milliseconds": + return MILLISECONDS; + case "microsecondsofsecond": + return MICROSECONDS_OF_SECOND; + case "microseconds": + return MICROSECONDS; + case "nanosecondsofsecond": + return NANOSECONDS_OF_SECOND; + case "nanoseconds": + return NANOSECONDS; + default: + throw new UnsupportedTemporalUnitException( "No such field: " + fieldName ); + } + } +} diff --git a/community/values/src/main/java/org/neo4j/values/storable/DurationValue.java b/community/values/src/main/java/org/neo4j/values/storable/DurationValue.java index 48b406694b35e..2a67abe085217 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DurationValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DurationValue.java @@ -755,73 +755,7 @@ public long get( TemporalUnit unit ) */ public LongValue get( String fieldName ) { - long val; - switch ( fieldName.toLowerCase() ) - { - case "years": - val = months / 12; - break; - case "months": - val = months; - break; - case "monthsofyear": - val = months % 12; - break; - case "monthsofquarter": - val = months % 3; - break; - case "quarters": - val = months / 3; - break; - case "quartersofyear": - val = (months / 3) % 4; - break; - case "weeks": - val = days / 7; - break; - case "daysofweek": - val = days % 7; - break; - case "days": - val = days; - break; - case "hours": - val = seconds / 3600; - break; - case "minutesofhour": - val = (seconds / 60) % 60; - break; - case "minutes": - val = seconds / 60; - break; - case "secondsofminute": - val = seconds % 60; - break; - case "seconds": - val = seconds; - break; - case "millisecondsofsecond": - val = nanos / 1000_000; - break; - case "milliseconds": - val = seconds * 1000 + nanos / 1000_000; - break; - case "microsecondsofsecond": - val = nanos / 1000; - break; - case "microseconds": - val = seconds * 1000_000 + nanos / 1000; - break; - case "nanosecondsofsecond": - val = nanos; - break; - case "nanoseconds": - val = seconds * NANOS_PER_SECOND + nanos; - break; - default: - throw new UnsupportedTemporalUnitException( "No such field: " + fieldName ); - } - + long val = DurationProperties.fromName( fieldName ).asTimeStamp( months, days, seconds, nanos ); return Values.longValue( val ); } diff --git a/community/values/src/main/java/org/neo4j/values/storable/PointProperties.java b/community/values/src/main/java/org/neo4j/values/storable/PointProperties.java new file mode 100644 index 0000000000000..cc17f46a2dbba --- /dev/null +++ b/community/values/src/main/java/org/neo4j/values/storable/PointProperties.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.values.storable; + +import org.neo4j.values.utils.InvalidValuesArgumentException; + +public enum PointProperties +{ + X( "x" ) + { + @Override + Value get( PointValue value ) + { + return value.getNthCoordinate( 0, propertyKey, false ); + } + }, + Y( "y" ) + { + @Override + Value get( PointValue value ) + { + return value.getNthCoordinate( 1, propertyKey, false ); + } + }, + Z( "z" ) + { + @Override + Value get( PointValue value ) + { + return value.getNthCoordinate( 2, propertyKey, false ); + } + }, + LONGITUDE( "longitude" ) + { + @Override + Value get( PointValue value ) + { + return value.getNthCoordinate( 0, propertyKey, true ); + } + }, + LATITUDE( "latitude" ) + { + @Override + Value get( PointValue value ) + { + return value.getNthCoordinate( 1, propertyKey, true ); + } + }, + HEIGHT( "height" ) + { + @Override + Value get( PointValue value ) + { + return value.getNthCoordinate( 2, propertyKey, true ); + } + }, + CRS( "crs" ) + { + @Override + Value get( PointValue value ) + { + return Values.stringValue( value.getCoordinateReferenceSystem().toString() ); + } + }, + SRID( "srid" ) + { + @Override + Value get( PointValue value ) + { + return Values.intValue( value.getCoordinateReferenceSystem().getCode() ); + } + }; + + public String propertyKey; + + PointProperties( String propertyKey ) + { + this.propertyKey = propertyKey; + } + + public static PointProperties fromName( String fieldName ) + { + switch ( fieldName.toLowerCase() ) + { + case "x": + return X; + case "y": + return Y; + case "z": + return Z; + case "longitude": + return LONGITUDE; + case "latitude": + return LATITUDE; + case "height": + return HEIGHT; + case "crs": + return CRS; + case "srid": + return SRID; + default: + throw new InvalidValuesArgumentException( "No such field: " + fieldName ); + } + } + + abstract Value get( PointValue value ); +} \ No newline at end of file diff --git a/community/values/src/main/java/org/neo4j/values/storable/PointValue.java b/community/values/src/main/java/org/neo4j/values/storable/PointValue.java index f769a272aab15..ea7f13f8e59d5 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/PointValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/PointValue.java @@ -505,30 +505,10 @@ else if ( crs == CoordinateReferenceSystem.WGS84_3D ) */ public Value get( String fieldName ) { - switch ( fieldName.toLowerCase() ) - { - case "x": - return getNthCoordinate( 0, fieldName, false ); - case "y": - return getNthCoordinate( 1, fieldName, false ); - case "z": - return getNthCoordinate( 2, fieldName, false ); - case "longitude": - return getNthCoordinate( 0, fieldName, true ); - case "latitude": - return getNthCoordinate( 1, fieldName, true ); - case "height": - return getNthCoordinate( 2, fieldName, true ); - case "crs": - return Values.stringValue( crs.toString() ); - case "srid": - return Values.intValue( crs.getCode() ); - default: - throw new InvalidValuesArgumentException( "No such field: " + fieldName ); - } - } - - private DoubleValue getNthCoordinate( int n, String fieldName, boolean onlyGeographic ) + return PointProperties.fromName( fieldName ).get( this ); + } + + DoubleValue getNthCoordinate( int n, String fieldName, boolean onlyGeographic ) { if ( onlyGeographic && !this.getCoordinateReferenceSystem().isGeographic() ) { diff --git a/community/values/src/main/java/org/neo4j/values/storable/TemporalProperties.java b/community/values/src/main/java/org/neo4j/values/storable/TemporalProperties.java new file mode 100644 index 0000000000000..222e21e1531e3 --- /dev/null +++ b/community/values/src/main/java/org/neo4j/values/storable/TemporalProperties.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2002-2018 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.values.storable; + +import java.time.temporal.ChronoUnit; +import java.time.temporal.IsoFields; +import java.time.temporal.TemporalUnit; + +public enum TemporalProperties +{ + MILLENNIUM( "millennium", ChronoUnit.MILLENNIA ), + CENTURY( "century", ChronoUnit.CENTURIES ), + DECADE( "decade", ChronoUnit.DECADES ), + YEAR( "year", ChronoUnit.YEARS ), + WEEK_YEAR( "weekYear", IsoFields.WEEK_BASED_YEARS ), + QUARTER( "quarter", IsoFields.QUARTER_YEARS ), + MONTH( "month", ChronoUnit.MONTHS ), + WEEK( "week", ChronoUnit.WEEKS ), + DAY( "day", ChronoUnit.DAYS ), + HOUR( "hour", ChronoUnit.HOURS ), + MINUTE( "minute", ChronoUnit.MINUTES ), + SECOND( "second", ChronoUnit.SECONDS ), + MILLISECOND( "millisecond", ChronoUnit.MILLIS ), + MICROSECOND( "microsecond", ChronoUnit.MICROS ); + + + public String propertyKey; + public TemporalUnit unit; + + TemporalProperties( String propertyKey, TemporalUnit unit ) + { + this.propertyKey = propertyKey; + this.unit = unit; + } + + public static TemporalProperties fromName( String unit ) + { + switch ( unit ) + { + case "millennium": + return MILLENNIUM; + case "century": + return CENTURY; + case "decade": + return DECADE; + case "year": + return YEAR; + case "weekYear": + return WEEK_YEAR; + case "quarter": + return QUARTER; + case "month": + return MONTH; + case "week": + return WEEK; + case "day": + return DAY; + case "hour": + return HOUR; + case "minute": + return MINUTE; + case "second": + return SECOND; + case "millisecond": + return MILLISECOND; + case "microsecond": + return MICROSECOND; + default: + throw new IllegalArgumentException( "Unsupported unit: " + unit ); + } + } +} diff --git a/community/values/src/main/java/org/neo4j/values/storable/TemporalValue.java b/community/values/src/main/java/org/neo4j/values/storable/TemporalValue.java index 7844947f3e5d8..37f62cc71f86e 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/TemporalValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/TemporalValue.java @@ -62,6 +62,9 @@ import static org.neo4j.values.storable.IntegralValue.safeCastIntegral; import static org.neo4j.values.storable.LocalDateTimeValue.localDateTime; import static org.neo4j.values.storable.NumberType.NO_NUMBER; +import static org.neo4j.values.storable.TemporalProperties.DAY; +import static org.neo4j.values.storable.TemporalProperties.MONTH; +import static org.neo4j.values.storable.TemporalProperties.YEAR; import static org.neo4j.values.storable.TimeValue.time; public abstract class TemporalValue> @@ -1161,7 +1164,7 @@ void checkAssignments() { if ( date == null ) { - assertDefinedInOrder( Pair.of( year, "year" ), Pair.of( month, "month" ), Pair.of( day, "day" ) ); + assertDefinedInOrder( Pair.of( year, YEAR.propertyKey ), Pair.of( month, MONTH.propertyKey ), Pair.of( day, DAY.propertyKey ) ); } } @@ -1170,7 +1173,7 @@ void assertFullyAssigned() { if ( date == null ) { - assertAllDefined( Pair.of( year, "year" ), Pair.of( month, "month" ), Pair.of( day, "day" ) ); + assertAllDefined( Pair.of( year, YEAR.propertyKey ), Pair.of( month, MONTH.propertyKey ), Pair.of( day, DAY.propertyKey ) ); } } }