From 2cb61b07d51b4bcec73c167bef12ccb08dcddf3e Mon Sep 17 00:00:00 2001 From: Pontus Melke Date: Wed, 5 Sep 2018 14:41:47 +0200 Subject: [PATCH] Temporal already had enum defined Temporal already had a Field enum, remove the newly created one and join with the others --- .../planner/CheckForUnresolvedTokens.scala | 14 +- .../CheckForUnresolvedTokensTest.scala | 55 ++++++++ .../impl/proc/temporal/TemporalFunction.java | 47 ++++++- .../neo4j/values/storable/DateTimeValue.java | 93 ++++++++----- .../org/neo4j/values/storable/DateValue.java | 57 ++++---- ...ionProperties.java => DurationFields.java} | 10 +- .../neo4j/values/storable/DurationValue.java | 2 +- .../values/storable/LocalDateTimeValue.java | 23 ++-- .../neo4j/values/storable/LocalTimeValue.java | 6 +- ...{PointProperties.java => PointFields.java} | 11 +- .../org/neo4j/values/storable/PointValue.java | 2 +- .../values/storable/TemporalProperties.java | 89 ------------- .../neo4j/values/storable/TemporalValue.java | 122 ++++++++++-------- .../org/neo4j/values/storable/TimeValue.java | 7 +- 14 files changed, 297 insertions(+), 241 deletions(-) rename community/values/src/main/java/org/neo4j/values/storable/{DurationProperties.java => DurationFields.java} (97%) rename community/values/src/main/java/org/neo4j/values/storable/{PointProperties.java => PointFields.java} (95%) delete mode 100644 community/values/src/main/java/org/neo4j/values/storable/TemporalProperties.java diff --git a/community/cypher/cypher-planner-3.4/src/main/scala/org/neo4j/cypher/internal/compiler/v3_4/planner/CheckForUnresolvedTokens.scala b/community/cypher/cypher-planner-3.4/src/main/scala/org/neo4j/cypher/internal/compiler/v3_4/planner/CheckForUnresolvedTokens.scala index 477e4b97b0f1a..e0aedab51ea0a 100644 --- a/community/cypher/cypher-planner-3.4/src/main/scala/org/neo4j/cypher/internal/compiler/v3_4/planner/CheckForUnresolvedTokens.scala +++ b/community/cypher/cypher-planner-3.4/src/main/scala/org/neo4j/cypher/internal/compiler/v3_4/planner/CheckForUnresolvedTokens.scala @@ -20,16 +20,24 @@ package org.neo4j.cypher.internal.compiler.v3_4.planner import org.neo4j.cypher.internal.compiler.v3_4.phases.LogicalPlanState -import org.neo4j.cypher.internal.frontend.v3_4.ast._ import org.neo4j.cypher.internal.frontend.v3_4.notification.{InternalNotification, MissingLabelNotification, MissingPropertyNameNotification, MissingRelTypeNotification} import org.neo4j.cypher.internal.frontend.v3_4.phases.CompilationPhaseTracer.CompilationPhase.LOGICAL_PLANNING import org.neo4j.cypher.internal.frontend.v3_4.phases.{BaseContext, VisitorPhase} import org.neo4j.cypher.internal.v3_4.expressions.{LabelName, Property, PropertyKeyName, RelTypeName} +import org.neo4j.values.storable.TemporalValue.TemporalFields +import org.neo4j.values.storable.{DurationFields, PointFields, TemporalValue} + +import scala.collection.JavaConverters._ object CheckForUnresolvedTokens extends VisitorPhase[BaseContext, LogicalPlanState] { + private val specialPropertyKey: Set[String] = + (TemporalFields.allFields().asScala ++ + DurationFields.values().map(_.propertyKey) ++ + PointFields.values().map(_.propertyKey)).toSet + override def visit(value: LogicalPlanState, context: BaseContext): Unit = { - val table = value.semanticTable + val table = value.semanticTable() def isEmptyLabel(label: String) = !table.resolvedLabelNames.contains(label) def isEmptyRelType(relType: String) = !table.resolvedRelTypeNames.contains(relType) def isEmptyPropertyName(name: String) = !table.resolvedPropertyKeyNames.contains(name) @@ -41,7 +49,7 @@ object CheckForUnresolvedTokens extends VisitorPhase[BaseContext, LogicalPlanSta case rel@RelTypeName(name) if isEmptyRelType(name) => acc => (acc :+ MissingRelTypeNotification(rel.position, name), Some(identity)) - case Property(_, prop@PropertyKeyName(name)) if isEmptyPropertyName(name) => acc => + case Property(_, prop@PropertyKeyName(name)) if !specialPropertyKey(name) && isEmptyPropertyName(name) => acc => (acc :+ MissingPropertyNameNotification(prop.position, name), Some(identity)) } diff --git a/community/cypher/cypher-planner-3.4/src/test/scala/org/neo4j/cypher/internal/compiler/v3_4/planner/CheckForUnresolvedTokensTest.scala b/community/cypher/cypher-planner-3.4/src/test/scala/org/neo4j/cypher/internal/compiler/v3_4/planner/CheckForUnresolvedTokensTest.scala index 46684445e73f4..e9df70f657c21 100644 --- a/community/cypher/cypher-planner-3.4/src/test/scala/org/neo4j/cypher/internal/compiler/v3_4/planner/CheckForUnresolvedTokensTest.scala +++ b/community/cypher/cypher-planner-3.4/src/test/scala/org/neo4j/cypher/internal/compiler/v3_4/planner/CheckForUnresolvedTokensTest.scala @@ -28,6 +28,7 @@ import org.neo4j.cypher.internal.util.v3_4.test_helpers.CypherFunSuite import org.neo4j.cypher.internal.frontend.v3_4.semantics.SemanticTable import org.neo4j.cypher.internal.planner.v3_4.spi.IDPPlannerName import org.neo4j.cypher.internal.util.v3_4.{InputPosition, LabelId, PropertyKeyId, RelTypeId} +import org.neo4j.values.storable.PointFields class CheckForUnresolvedTokensTest extends CypherFunSuite with AstRewritingTestSupport with LogicalPlanConstructionTestSupport { @@ -124,6 +125,60 @@ class CheckForUnresolvedTokensTest extends CypherFunSuite with AstRewritingTestS checkForTokens(ast, semanticTable) shouldBe empty } + test("don't warn when using point properties") { + //given + val semanticTable = new SemanticTable + semanticTable.resolvedPropertyKeyNames.put("prop", PropertyKeyId(42)) + + PointFields.values().foreach { property => + //when + val ast = parse(s"MATCH (a) WHERE point(a.prop).${property.propertyKey} = 42 RETURN a") + + //then + checkForTokens(ast, semanticTable) shouldBe empty + } + } + + test("don't warn when using temporal properties") { + //given + val semanticTable = new SemanticTable + semanticTable.resolvedPropertyKeyNames.put("prop", PropertyKeyId(42)) + + PointFields.values().foreach { property => + //when + val ast = parse(s"MATCH (a) WHERE date(a.prop).${property.propertyKey} = 42 RETURN a") + + //then + checkForTokens(ast, semanticTable) shouldBe empty + } + } + + test("don't warn when using duration properties") { + //given + val semanticTable = new SemanticTable + semanticTable.resolvedPropertyKeyNames.put("prop", PropertyKeyId(42)) + + PointFields.values().foreach { property => + //when + val ast = parse(s"MATCH (a) WHERE duration(a.prop).${property.propertyKey} = 42 RETURN a") + + //then + checkForTokens(ast, semanticTable) shouldBe empty + } + } + + test("don't warn when using temporal property") { + //given + val semanticTable = new SemanticTable + semanticTable.resolvedPropertyKeyNames.put("prop", PropertyKeyId(42)) + + //when + val ast = parse("MATCH (a) WHERE point(a.prop).y = 42 RETURN a") + + //then + checkForTokens(ast, semanticTable) shouldBe empty + } + private def checkForTokens(ast: Query, semanticTable: SemanticTable): Set[InternalNotification] = { val notificationLogger = new RecordingNotificationLogger val compilationState = LogicalPlanState(queryText = "apa", startPosition = None, plannerName = IDPPlannerName, new StubSolveds, new StubCardinalities, maybeStatement = Some(ast), maybeSemanticTable = Some(semanticTable)) 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 c1940584a17a0..5a39f12bf3643 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,6 +21,8 @@ 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; @@ -40,7 +42,6 @@ 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; @@ -283,15 +284,51 @@ public T apply( Context ctx, AnyValue[] args ) throws ProcedureException if ( unit instanceof TextValue && input instanceof TemporalValue && fields instanceof MapValue ) { return function.truncate( - TemporalProperties.fromName( ((TextValue) unit).stringValue() ).unit, - (TemporalValue) input, + unit( ((TextValue) unit).stringValue() ), + (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/DateTimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java index 395a8ddea7fc0..0a9a51e5754d5 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java @@ -68,8 +68,10 @@ public final class DateTimeValue extends TemporalValue { - public static final DateTimeValue MIN_VALUE = new DateTimeValue( ZonedDateTime.of( LocalDateTime.MIN, ZoneOffset.MIN ) ); - public static final DateTimeValue MAX_VALUE = new DateTimeValue( ZonedDateTime.of( LocalDateTime.MAX, ZoneOffset.MAX ) ); + public static final DateTimeValue MIN_VALUE = + new DateTimeValue( ZonedDateTime.of( LocalDateTime.MIN, ZoneOffset.MIN ) ); + public static final DateTimeValue MAX_VALUE = + new DateTimeValue( ZonedDateTime.of( LocalDateTime.MAX, ZoneOffset.MAX ) ); public static DateTimeValue datetime( DateValue date, LocalTimeValue time, ZoneId zone ) { @@ -91,12 +93,14 @@ public static DateTimeValue datetime( public static DateTimeValue datetime( int year, int month, int day, int hour, int minute, int second, int nanoOfSecond, ZoneId zone ) { - return new DateTimeValue( assertValidArgument( () -> ZonedDateTime.of( year, month, day, hour, minute, second, nanoOfSecond, zone ) ) ); + return new DateTimeValue( assertValidArgument( + () -> ZonedDateTime.of( year, month, day, hour, minute, second, nanoOfSecond, zone ) ) ); } public static DateTimeValue datetime( long epochSecond, long nano, ZoneOffset zoneOffset ) { - return new DateTimeValue( assertValidArgument( () -> ofInstant( ofEpochSecond( epochSecond, nano ), zoneOffset ) ) ); + return new DateTimeValue( + assertValidArgument( () -> ofInstant( ofEpochSecond( epochSecond, nano ), zoneOffset ) ) ); } public static DateTimeValue datetime( ZonedDateTime datetime ) @@ -111,25 +115,29 @@ public static DateTimeValue datetime( OffsetDateTime datetime ) public static DateTimeValue datetime( long epochSecondUTC, long nano, ZoneId zone ) { - return new DateTimeValue( assertValidArgument( () -> ofInstant( ofEpochSecond( epochSecondUTC, nano ), zone ) ) ); + return new DateTimeValue( + assertValidArgument( () -> ofInstant( ofEpochSecond( epochSecondUTC, nano ), zone ) ) ); } public static DateTimeValue ofEpoch( IntegralValue epochSecondUTC, IntegralValue nano ) { long ns = safeCastIntegral( "nanosecond", nano, 0 ); - if ( ns < 0 || ns >= 1000_000_000 ) + if ( ns < 0 || ns >= 1000_000_000 ) { throw new InvalidValuesArgumentException( "Invalid nanosecond: " + ns ); } - return new DateTimeValue( assertValidArgument( () -> ofInstant( ofEpochSecond( epochSecondUTC.longValue(), ns ), UTC ) ) ); + return new DateTimeValue( + assertValidArgument( () -> ofInstant( ofEpochSecond( epochSecondUTC.longValue(), ns ), UTC ) ) ); } public static DateTimeValue ofEpochMillis( IntegralValue millisUTC ) { - return new DateTimeValue( assertValidArgument( () -> ofInstant( ofEpochMilli( millisUTC.longValue() ), UTC ) ) ); + return new DateTimeValue( + assertValidArgument( () -> ofInstant( ofEpochMilli( millisUTC.longValue() ), UTC ) ) ); } - public static DateTimeValue parse( CharSequence text, Supplier defaultZone, CSVHeaderInformation fieldsFromHeader ) + public static DateTimeValue parse( CharSequence text, Supplier defaultZone, + CSVHeaderInformation fieldsFromHeader ) { if ( fieldsFromHeader != null ) { @@ -198,8 +206,9 @@ public static DateTimeValue truncate( } else { - // Timezone needs some special handling, since the builder will shift keeping the instant instead of the local time - Map updatedFields = new HashMap<>( fields.size() + 1 ); + // Timezone needs some special handling, since the builder will shift keeping the instant instead of the + // local time + Map updatedFields = new HashMap<>( fields.size() + 1 ); for ( Map.Entry entry : fields.entrySet() ) { if ( "timezone".equals( entry.getKey() ) ) @@ -239,24 +248,28 @@ protected boolean supportsEpoch() } private final ZonedDateTime defaulZonedDateTime = - ZonedDateTime.of( Field.year.defaultValue, Field.month.defaultValue, Field.day.defaultValue, Field.hour.defaultValue, - Field.minute.defaultValue, Field.second.defaultValue, Field.nanosecond.defaultValue, timezone() ); + ZonedDateTime.of( TemporalFields.year.defaultValue, TemporalFields.month.defaultValue, + TemporalFields.day.defaultValue, TemporalFields.hour.defaultValue, + TemporalFields.minute.defaultValue, TemporalFields.second.defaultValue, + TemporalFields.nanosecond.defaultValue, timezone() ); @Override public DateTimeValue buildInternal() { - boolean selectingDate = fields.containsKey( Field.date ); - boolean selectingTime = fields.containsKey( Field.time ); - boolean selectingDateTime = fields.containsKey( Field.datetime ); - boolean selectingEpoch = fields.containsKey( Field.epochSeconds ) || fields.containsKey( Field.epochMillis ); + boolean selectingDate = fields.containsKey( TemporalFields.date ); + boolean selectingTime = fields.containsKey( TemporalFields.time ); + boolean selectingDateTime = fields.containsKey( TemporalFields.datetime ); + boolean selectingEpoch = fields.containsKey( TemporalFields.epochSeconds ) || + fields.containsKey( TemporalFields.epochMillis ); boolean selectingTimeZone; ZonedDateTime result; if ( selectingDateTime ) { - AnyValue dtField = fields.get( Field.datetime ); + AnyValue dtField = fields.get( TemporalFields.datetime ); if ( !(dtField instanceof TemporalValue) ) { - throw new InvalidValuesArgumentException( String.format( "Cannot construct date time from: %s", dtField ) ); + throw new InvalidValuesArgumentException( + String.format( "Cannot construct date time from: %s", dtField ) ); } TemporalValue dt = (TemporalValue) dtField; LocalTime timePart = dt.getTimePart( defaultZone ).toLocalTime(); @@ -266,25 +279,29 @@ public DateTimeValue buildInternal() } else if ( selectingEpoch ) { - if ( fields.containsKey( Field.epochSeconds ) ) + if ( fields.containsKey( TemporalFields.epochSeconds ) ) { - AnyValue epochField = fields.get( Field.epochSeconds ); + AnyValue epochField = fields.get( TemporalFields.epochSeconds ); if ( !(epochField instanceof IntegralValue) ) { - throw new InvalidValuesArgumentException( String.format( "Cannot construct date time from: %s", epochField ) ); + throw new InvalidValuesArgumentException( + String.format( "Cannot construct date time from: %s", epochField ) ); } IntegralValue epochSeconds = (IntegralValue) epochField; - result = assertValidArgument( () -> ZonedDateTime.ofInstant( Instant.ofEpochMilli( epochSeconds.longValue() * 1000 ), timezone() ) ); + result = assertValidArgument( () -> ZonedDateTime + .ofInstant( Instant.ofEpochMilli( epochSeconds.longValue() * 1000 ), timezone() ) ); } else { - AnyValue epochField = fields.get( Field.epochMillis ); + AnyValue epochField = fields.get( TemporalFields.epochMillis ); if ( !(epochField instanceof IntegralValue) ) { - throw new InvalidValuesArgumentException( String.format( "Cannot construct date time from: %s", epochField ) ); + throw new InvalidValuesArgumentException( + String.format( "Cannot construct date time from: %s", epochField ) ); } IntegralValue epochMillis = (IntegralValue) epochField; - result = assertValidArgument( () -> ZonedDateTime.ofInstant( Instant.ofEpochMilli( epochMillis.longValue() ), timezone() ) ); + result = assertValidArgument( () -> ZonedDateTime + .ofInstant( Instant.ofEpochMilli( epochMillis.longValue() ), timezone() ) ); } selectingTimeZone = false; } @@ -295,10 +312,11 @@ else if ( selectingTime || selectingDate ) ZoneId zoneId; if ( selectingTime ) { - AnyValue timeField = fields.get( Field.time ); + AnyValue timeField = fields.get( TemporalFields.time ); if ( !(timeField instanceof TemporalValue) ) { - throw new InvalidValuesArgumentException( String.format( "Cannot construct time from: %s", timeField ) ); + throw new InvalidValuesArgumentException( + String.format( "Cannot construct time from: %s", timeField ) ); } TemporalValue t = (TemporalValue) timeField; time = t.getTimePart( defaultZone ).toLocalTime(); @@ -314,10 +332,11 @@ else if ( selectingTime || selectingDate ) LocalDate date; if ( selectingDate ) { - AnyValue dateField = fields.get( Field.date ); + AnyValue dateField = fields.get( TemporalFields.date ); if ( !(dateField instanceof TemporalValue) ) { - throw new InvalidValuesArgumentException( String.format( "Cannot construct date from: %s", dateField ) ); + throw new InvalidValuesArgumentException( + String.format( "Cannot construct date from: %s", dateField ) ); } TemporalValue t = (TemporalValue) dateField; date = t.getDatePart(); @@ -334,12 +353,14 @@ else if ( selectingTime || selectingDate ) selectingTimeZone = false; } - if ( fields.containsKey( Field.week ) && !selectingDate && !selectingDateTime && !selectingEpoch ) + if ( fields.containsKey( TemporalFields.week ) && !selectingDate && !selectingDateTime && + !selectingEpoch ) { // Be sure to be in the start of the week based year (which can be later than 1st Jan) result = result - .with( IsoFields.WEEK_BASED_YEAR, safeCastIntegral( Field.year.name(), fields.get( Field.year ), - Field.year.defaultValue ) ) + .with( IsoFields.WEEK_BASED_YEAR, + safeCastIntegral( TemporalFields.year.name(), fields.get( TemporalFields.year ), + TemporalFields.year.defaultValue ) ) .with( IsoFields.WEEK_OF_WEEK_BASED_YEAR, 1 ) .with( ChronoField.DAY_OF_WEEK, 1 ); } @@ -638,7 +659,8 @@ static ZoneId parseZoneName( String zoneName ) } catch ( DateTimeParseException e ) { - throw new TemporalParseException( "Invalid value for TimeZone: " + e.getMessage(), e.getParsedString(), e.getErrorIndex(), e ); + throw new TemporalParseException( "Invalid value for TimeZone: " + e.getMessage(), e.getParsedString(), + e.getErrorIndex(), e ); } return parsedName; } @@ -656,7 +678,8 @@ public static ZoneId parseZoneOffsetOrZoneName( String zoneName ) } catch ( DateTimeParseException e ) { - throw new TemporalParseException( "Invalid value for TimeZone: " + e.getMessage(), e.getParsedString(), e.getErrorIndex(), e ); + throw new TemporalParseException( "Invalid value for TimeZone: " + e.getMessage(), e.getParsedString(), + e.getErrorIndex(), e ); } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/DateValue.java b/community/values/src/main/java/org/neo4j/values/storable/DateValue.java index c7127376eb9cd..1c1304cc73246 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DateValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DateValue.java @@ -301,13 +301,15 @@ public T map( ValueMapper mapper ) @Override public DateValue add( DurationValue duration ) { - return replacement( assertValidArithmetic( () -> value.plusMonths( duration.totalMonths() ).plusDays( duration.totalDays() ) ) ); + return replacement( assertValidArithmetic( + () -> value.plusMonths( duration.totalMonths() ).plusDays( duration.totalDays() ) ) ); } @Override public DateValue sub( DurationValue duration ) { - return replacement( assertValidArithmetic( () -> value.minusMonths( duration.totalMonths() ).minusDays( duration.totalDays() ) ) ); + return replacement( assertValidArithmetic( + () -> value.minusMonths( duration.totalMonths() ).minusDays( duration.totalDays() ) ) ); } @Override @@ -375,18 +377,20 @@ DateValue replacement( LocalDate date ) * */ static final String DATE_PATTERN = "(?:" - // short formats - without dashes: - + "(?[0-9]{4})(?:" - + "(?[0-9]{2})(?[0-9]{2})?|" // calendar date - + "W(?[0-9]{2})(?[0-9])?|" // week date - + (QUARTER_DATES ? "Q(?[0-9])(?[0-9]{2})?|" : "") // quarter date - + "(?[0-9]{3}))" + "|" // ordinal date - // long formats - includes dashes: - + "(?(?:[0-9]{4}|[+-][0-9]{1,9}))(?:" - + "-(?[0-9]{1,2})(?:-(?[0-9]{1,2}))?|" // calendar date - + "-W(?[0-9]{1,2})(?:-(?[0-9]))?|" // week date - + (QUARTER_DATES ? "-Q(?[0-9])(?:-(?[0-9]{1,2}))?|" : "") // quarter date - + "-(?[0-9]{3}))?" + ")"; // ordinal date + // short formats - without dashes: + + "(?[0-9]{4})(?:" + + "(?[0-9]{2})(?[0-9]{2})?|" // calendar date + + "W(?[0-9]{2})(?[0-9])?|" // week date + + (QUARTER_DATES ? "Q(?[0-9])(?[0-9]{2})?|" : "") + // quarter date + + "(?[0-9]{3}))" + "|" // ordinal date + // long formats - includes dashes: + + "(?(?:[0-9]{4}|[+-][0-9]{1,9}))(?:" + + "-(?[0-9]{1,2})(?:-(?[0-9]{1,2}))?|" // calendar date + + "-W(?[0-9]{1,2})(?:-(?[0-9]))?|" // week date + + (QUARTER_DATES ? "-Q(?[0-9])(?:-(?[0-9]{1,2}))?|" : "") + // quarter date + + "-(?[0-9]{3}))?" + ")"; // ordinal date private static final Pattern PATTERN = Pattern.compile( DATE_PATTERN ); /** @@ -394,8 +398,7 @@ DateValue replacement( LocalDate date ) * {@link #DATE_PATTERN}. The decision tree in the implementation of this method is guided by the parsing notes * for {@link #DATE_PATTERN}. * - * @param matcher - * a {@link Matcher} that matches the regular expression defined in {@link #DATE_PATTERN}. + * @param matcher a {@link Matcher} that matches the regular expression defined in {@link #DATE_PATTERN}. * @return a {@link LocalDate} parsed from the given {@link Matcher}. */ static LocalDate parseDate( Matcher matcher ) @@ -420,7 +423,7 @@ private static LocalDate parse( String month = matcher.group( MONTH ); if ( month != null ) { - return assertParsable( () -> LocalDate.of( year, parseInt( month ), optInt( matcher.group( DAY ) ) ) ); + return assertParsable( () -> LocalDate.of( year, parseInt( month ), optInt( matcher.group( DAY ) ) ) ); } String week = matcher.group( WEEK ); if ( week != null ) @@ -430,7 +433,8 @@ private static LocalDate parse( String quarter = matcher.group( QUARTER ); if ( quarter != null ) { - return assertParsable( () -> localQuarterDate( year, parseInt( quarter ), optInt( matcher.group( DOQ ) ) ) ); + return assertParsable( + () -> localQuarterDate( year, parseInt( quarter ), optInt( matcher.group( DOQ ) ) ) ); } String doy = matcher.group( DOY ); if ( doy != null ) @@ -458,7 +462,8 @@ private static LocalDate localWeekDate( int year, int week, int dayOfWeek ) // week 53 of years that don't have 53 weeks, so we have to guard for this: if ( week == 53 && withWeek.get( IsoFields.WEEK_BASED_YEAR ) != year ) { - throw new InvalidValuesArgumentException( String.format( "Year %d does not contain %d weeks.", year, week ) ); + throw new InvalidValuesArgumentException( + String.format( "Year %d does not contain %d weeks.", year, week ) ); } return withWeek.with( ChronoField.DAY_OF_WEEK, dayOfWeek ); } @@ -482,7 +487,8 @@ private static LocalDate localQuarterDate( int year, int quarter, int dayOfQuart .with( IsoFields.DAY_OF_QUARTER, dayOfQuarter ); } - static final LocalDate DEFAULT_CALENDER_DATE = LocalDate.of( Field.year.defaultValue, Field.month.defaultValue, Field.day.defaultValue ); + static final LocalDate DEFAULT_CALENDER_DATE = LocalDate + .of( TemporalFields.year.defaultValue, TemporalFields.month.defaultValue, TemporalFields.day.defaultValue ); private static class DateBuilder extends Builder { @@ -529,16 +535,17 @@ private LocalDate getDateOf( org.neo4j.values.AnyValue temporal ) public DateValue buildInternal() { LocalDate result; - if ( fields.containsKey( Field.date ) ) + if ( fields.containsKey( TemporalFields.date ) ) { - result = getDateOf( fields.get( Field.date ) ); + result = getDateOf( fields.get( TemporalFields.date ) ); } - else if ( fields.containsKey( Field.week ) ) + else if ( fields.containsKey( TemporalFields.week ) ) { // Be sure to be in the start of the week based year (which can be later than 1st Jan) result = DEFAULT_CALENDER_DATE - .with( IsoFields.WEEK_BASED_YEAR, safeCastIntegral( Field.year.name(), fields.get( Field.year ), - Field.year.defaultValue ) ) + .with( IsoFields.WEEK_BASED_YEAR, + safeCastIntegral( TemporalFields.year.name(), fields.get( TemporalFields.year ), + TemporalFields.year.defaultValue ) ) .with( IsoFields.WEEK_OF_WEEK_BASED_YEAR, 1 ) .with( ChronoField.DAY_OF_WEEK, 1 ); } diff --git a/community/values/src/main/java/org/neo4j/values/storable/DurationProperties.java b/community/values/src/main/java/org/neo4j/values/storable/DurationFields.java similarity index 97% rename from community/values/src/main/java/org/neo4j/values/storable/DurationProperties.java rename to community/values/src/main/java/org/neo4j/values/storable/DurationFields.java index 7f49d3d20cd06..a68ee29520ffc 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DurationProperties.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DurationFields.java @@ -23,7 +23,10 @@ import static org.neo4j.values.utils.TemporalUtil.NANOS_PER_SECOND; -public enum DurationProperties +/** + * Defines all valid field accessors for durations + */ +public enum DurationFields { YEARS( "years" ) { @@ -186,17 +189,16 @@ public long asTimeStamp( long months, long days, long seconds, long nanos ) } }; - public String propertyKey; - DurationProperties( String propertyKey ) + DurationFields( String propertyKey ) { this.propertyKey = propertyKey; } public abstract long asTimeStamp( long months, long days, long seconds, long nanos ); - public static DurationProperties fromName( String fieldName ) + public static DurationFields fromName( String fieldName ) { switch ( fieldName.toLowerCase() ) { 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 2a67abe085217..28b718fcdb8d9 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,7 +755,7 @@ public long get( TemporalUnit unit ) */ public LongValue get( String fieldName ) { - long val = DurationProperties.fromName( fieldName ).asTimeStamp( months, days, seconds, nanos ); + long val = DurationFields.fromName( fieldName ).asTimeStamp( months, days, seconds, nanos ); return Values.longValue( val ); } diff --git a/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java index 01067abecba77..d2c3ce452b4e5 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java @@ -149,8 +149,9 @@ public static LocalDateTimeValue truncate( } static final LocalDateTime DEFAULT_LOCAL_DATE_TIME = - LocalDateTime.of( Field.year.defaultValue, Field.month.defaultValue, Field.day.defaultValue, Field.hour.defaultValue, - Field.minute.defaultValue ); + LocalDateTime.of( TemporalFields.year.defaultValue, TemporalFields.month.defaultValue, + TemporalFields.day.defaultValue, TemporalFields.hour.defaultValue, + TemporalFields.minute.defaultValue ); static DateTimeValue.DateTimeBuilder builder( Supplier defaultZone ) { @@ -171,13 +172,13 @@ protected boolean supportsEpoch() @Override public LocalDateTimeValue buildInternal() { - boolean selectingDate = fields.containsKey( Field.date ); - boolean selectingTime = fields.containsKey( Field.time ); - boolean selectingDateTime = fields.containsKey( Field.datetime ); + boolean selectingDate = fields.containsKey( TemporalFields.date ); + boolean selectingTime = fields.containsKey( TemporalFields.time ); + boolean selectingDateTime = fields.containsKey( TemporalFields.datetime ); LocalDateTime result; if ( selectingDateTime ) { - AnyValue dtField = fields.get( Field.datetime ); + AnyValue dtField = fields.get( TemporalFields.datetime ); if ( !(dtField instanceof TemporalValue) ) { throw new InvalidValuesArgumentException( String.format( "Cannot construct local date time from: %s", dtField ) ); @@ -190,7 +191,7 @@ else if ( selectingTime || selectingDate ) LocalTime time; if ( selectingTime ) { - AnyValue timeField = fields.get( Field.time ); + AnyValue timeField = fields.get( TemporalFields.time ); if ( !(timeField instanceof TemporalValue) ) { throw new InvalidValuesArgumentException( String.format( "Cannot construct local time from: %s", timeField ) ); @@ -205,7 +206,7 @@ else if ( selectingTime || selectingDate ) LocalDate date; if ( selectingDate ) { - AnyValue dateField = fields.get( Field.date ); + AnyValue dateField = fields.get( TemporalFields.date ); if ( !(dateField instanceof TemporalValue) ) { throw new InvalidValuesArgumentException( String.format( "Cannot construct date from: %s", dateField ) ); @@ -225,12 +226,12 @@ else if ( selectingTime || selectingDate ) result = DEFAULT_LOCAL_DATE_TIME; } - if ( fields.containsKey( Field.week ) && !selectingDate && !selectingDateTime ) + if ( fields.containsKey( TemporalFields.week ) && !selectingDate && !selectingDateTime ) { // Be sure to be in the start of the week based year (which can be later than 1st Jan) result = result - .with( IsoFields.WEEK_BASED_YEAR, safeCastIntegral( Field.year.name(), fields.get( Field.year ), - Field.year.defaultValue ) ) + .with( IsoFields.WEEK_BASED_YEAR, safeCastIntegral( TemporalFields.year.name(), fields.get( TemporalFields.year ), + TemporalFields.year.defaultValue ) ) .with( IsoFields.WEEK_OF_WEEK_BASED_YEAR, 1 ) .with( ChronoField.DAY_OF_WEEK, 1 ); } diff --git a/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java index 17c519f793f6c..12b1c3ce44b2c 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java @@ -126,7 +126,7 @@ public static LocalTimeValue truncate( } } - static final LocalTime DEFAULT_LOCAL_TIME = LocalTime.of( Field.hour.defaultValue, Field.minute.defaultValue ); + static final LocalTime DEFAULT_LOCAL_TIME = LocalTime.of( TemporalFields.hour.defaultValue, TemporalFields.minute.defaultValue ); static TimeValue.TimeBuilder builder( Supplier defaultZone ) { @@ -142,9 +142,9 @@ protected boolean supportsTimeZone() public LocalTimeValue buildInternal() { LocalTime result; - if ( fields.containsKey( Field.time ) ) + if ( fields.containsKey( TemporalFields.time ) ) { - AnyValue time = fields.get( Field.time ); + AnyValue time = fields.get( TemporalFields.time ); if ( !(time instanceof TemporalValue) ) { throw new InvalidValuesArgumentException( String.format( "Cannot construct local time from: %s", time ) ); diff --git a/community/values/src/main/java/org/neo4j/values/storable/PointProperties.java b/community/values/src/main/java/org/neo4j/values/storable/PointFields.java similarity index 95% rename from community/values/src/main/java/org/neo4j/values/storable/PointProperties.java rename to community/values/src/main/java/org/neo4j/values/storable/PointFields.java index cc17f46a2dbba..e9d9467ecf280 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/PointProperties.java +++ b/community/values/src/main/java/org/neo4j/values/storable/PointFields.java @@ -21,7 +21,10 @@ import org.neo4j.values.utils.InvalidValuesArgumentException; -public enum PointProperties +/** + * Defines all valid field accessors for points + */ +public enum PointFields { X( "x" ) { @@ -90,12 +93,12 @@ Value get( PointValue value ) public String propertyKey; - PointProperties( String propertyKey ) + PointFields( String propertyKey ) { this.propertyKey = propertyKey; } - public static PointProperties fromName( String fieldName ) + public static PointFields fromName( String fieldName ) { switch ( fieldName.toLowerCase() ) { @@ -121,4 +124,4 @@ public static PointProperties fromName( String 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 ea7f13f8e59d5..9bbbeb999d7fd 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,7 +505,7 @@ else if ( crs == CoordinateReferenceSystem.WGS84_3D ) */ public Value get( String fieldName ) { - return PointProperties.fromName( fieldName ).get( this ); + return PointFields.fromName( fieldName ).get( this ); } DoubleValue getNthCoordinate( int n, String fieldName, boolean onlyGeographic ) 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 deleted file mode 100644 index 222e21e1531e3..0000000000000 --- a/community/values/src/main/java/org/neo4j/values/storable/TemporalProperties.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 37f62cc71f86e..f7a503f0f8e0e 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 @@ -42,6 +42,7 @@ import java.util.EnumMap; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; @@ -62,9 +63,6 @@ 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> @@ -301,14 +299,14 @@ public final int get( TemporalField field ) public final AnyValue get( String fieldName ) { - Field field = Field.fields.get( fieldName.toLowerCase() ); - if ( field == Field.epochSeconds || field == Field.epochMillis ) + TemporalFields field = TemporalFields.fields.get( fieldName.toLowerCase() ); + if ( field == TemporalFields.epochSeconds || field == TemporalFields.epochMillis ) { T temp = temporal(); if ( temp instanceof ChronoZonedDateTime ) { ChronoZonedDateTime zdt = (ChronoZonedDateTime) temp; - if ( field == Field.epochSeconds ) + if ( field == TemporalFields.epochSeconds ) { return Values.longValue( zdt.toInstant().toEpochMilli() / 1000 ); } @@ -322,19 +320,19 @@ public final AnyValue get( String fieldName ) throw new UnsupportedTemporalUnitException( "Epoch not supported." ); } } - if ( field == Field.timezone ) + if ( field == TemporalFields.timezone ) { return Values.stringValue( getZoneId(this::getZoneOffset).toString() ); } - if ( field == Field.offset ) + if ( field == TemporalFields.offset ) { return Values.stringValue( getZoneOffset().toString() ); } - if ( field == Field.offsetMinutes ) + if ( field == TemporalFields.offsetMinutes ) { return Values.intValue( getZoneOffset().getTotalSeconds() / 60 ); } - if ( field == Field.offsetSeconds ) + if ( field == TemporalFields.offsetSeconds ) { return Values.intValue( getZoneOffset().getTotalSeconds() ); } @@ -482,7 +480,7 @@ abstract static class Builder implements StructureBuilder fields = new EnumMap<>( Field.class ); + protected Map fields = new EnumMap<>( TemporalFields.class ); Builder( Supplier defaultZone ) { @@ -510,26 +508,31 @@ public final Result build() Temp assignAllFields( Temp temp ) { Temp result = temp; - for ( Map.Entry entry : fields.entrySet() ) + for ( Map.Entry entry : fields.entrySet() ) { - Field f = entry.getKey(); - if ( f == Field.year && fields.containsKey( Field.week ) ) + TemporalFields f = entry.getKey(); + if ( f == TemporalFields.year && fields.containsKey( TemporalFields.week ) ) { // Year can mean week-based year, if a week is specified. - result = (Temp) result.with( IsoFields.WEEK_BASED_YEAR, safeCastIntegral( f.name(), entry.getValue(), f.defaultValue ) ); + result = (Temp) result.with( IsoFields.WEEK_BASED_YEAR, + safeCastIntegral( f.name(), entry.getValue(), f.defaultValue ) ); } - else if ( !f.isGroupSelector() && f != Field.timezone && f != Field.millisecond && f != Field.microsecond && f != Field.nanosecond ) + else if ( !f.isGroupSelector() && f != TemporalFields.timezone && f != TemporalFields.millisecond && + f != TemporalFields.microsecond && f != TemporalFields.nanosecond ) { TemporalField temporalField = f.field; - result = (Temp) result.with( temporalField, safeCastIntegral( f.name(), entry.getValue(), f.defaultValue ) ); + result = (Temp) result + .with( temporalField, safeCastIntegral( f.name(), entry.getValue(), f.defaultValue ) ); } } // Assign all sub-second parts in one step if ( supportsTime() && - (fields.containsKey( Field.millisecond ) || fields.containsKey( Field.microsecond ) || fields.containsKey( Field.nanosecond )) ) + (fields.containsKey( TemporalFields.millisecond ) || + fields.containsKey( TemporalFields.microsecond ) || fields.containsKey( TemporalFields.nanosecond )) ) { - result = (Temp) result.with( Field.nanosecond.field, - validNano( fields.get( Field.millisecond ), fields.get( Field.microsecond ), fields.get( Field.nanosecond ) ) ); + result = (Temp) result.with( TemporalFields.nanosecond.field, + validNano( fields.get( TemporalFields.millisecond ), fields.get( TemporalFields.microsecond ), + fields.get( TemporalFields.nanosecond ) ) ); } return result; } @@ -537,7 +540,7 @@ else if ( !f.isGroupSelector() && f != Field.timezone && f != Field.millisecond @Override public final StructureBuilder add( String fieldName, AnyValue value ) { - Field field = Field.fields.get( fieldName.toLowerCase() ); + TemporalFields field = TemporalFields.fields.get( fieldName.toLowerCase() ); if ( field == null ) { throw new InvalidValuesArgumentException( "No such field: " + fieldName ); @@ -599,7 +602,7 @@ protected final ZoneId timezone() * All fields that can be a asigned to or read from temporals. * Make sure that writable fields defined in "decreasing" order between year and nanosecond. */ - protected enum Field + public enum TemporalFields { year( ChronoField.YEAR, 0 ), quarter( IsoFields.QUARTER_OF_YEAR, 1 ), @@ -786,11 +789,11 @@ boolean isGroupSelector() return true; } }; - private static final Map fields = new HashMap<>(); + private static final Map fields = new HashMap<>(); static { - for ( Field field : values() ) + for ( TemporalFields field : values() ) { fields.put( field.name().toLowerCase(), field ); } @@ -802,13 +805,13 @@ boolean isGroupSelector() final TemporalField field; final int defaultValue; - Field( TemporalField field, int defaultValue ) + TemporalFields( TemporalField field, int defaultValue ) { this.field = field; this.defaultValue = defaultValue; } - Field() + TemporalFields() { this.field = null; this.defaultValue = -1; @@ -832,6 +835,11 @@ void assign( Builder builder, AnyValue value ) } builder.state = builder.state.assign( this, value ); } + + public static Set allFields() + { + return fields.keySet(); + } } private static class DateTimeBuilder @@ -865,20 +873,20 @@ void checkAssignments( boolean requiresDate ) } else { - throw new InvalidValuesArgumentException( Field.year.name() + " must be specified" ); + throw new InvalidValuesArgumentException( TemporalFields.year.name() + " must be specified" ); } } time.checkAssignments(); } } - DateTimeBuilder assign( Field field, AnyValue value ) + DateTimeBuilder assign( TemporalFields field, AnyValue value ) { - if ( field == Field.datetime || field == Field.epochSeconds || field == Field.epochMillis ) + if ( field == TemporalFields.datetime || field == TemporalFields.epochSeconds || field == TemporalFields.epochMillis ) { return new SelectDateTimeDTBuilder( date, time ).assign( field, value ); } - else if ( field == Field.time || field == Field.date ) + else if ( field == TemporalFields.time || field == TemporalFields.date ) { return new SelectDateOrTimeDTBuilder( date, time ).assign( field, value ); } @@ -888,9 +896,9 @@ else if ( field == Field.time || field == Field.date ) } } - DateTimeBuilder assignToSubBuilders( Field field, AnyValue value ) + DateTimeBuilder assignToSubBuilders( TemporalFields field, AnyValue value ) { - if ( field == Field.date || field.field != null && field.field.isDateBased() ) + if ( field == TemporalFields.date || field.field != null && field.field.isDateBased() ) { if ( date == null ) { @@ -898,7 +906,7 @@ DateTimeBuilder assignToSubBuilders( Field field, AnyValue value ) } date = date.assign( field, value ); } - else if ( field == Field.time || field.field != null && field.field.isTimeBased() ) + else if ( field == TemporalFields.time || field.field != null && field.field.isTimeBased() ) { if ( time == null ) { @@ -932,13 +940,13 @@ void checkAssignments( boolean requiresDate ) } @Override - DateTimeBuilder assign( Field field, AnyValue value ) + DateTimeBuilder assign( TemporalFields field, AnyValue value ) { - if ( field == Field.date || field == Field.time ) + if ( field == TemporalFields.date || field == TemporalFields.time ) { throw new InvalidValuesArgumentException( field.name() + " cannot be selected together with datetime or epochSeconds or epochMillis." ); } - else if ( field == Field.datetime ) + else if ( field == TemporalFields.datetime ) { if ( epochSeconds != null ) { @@ -948,9 +956,9 @@ else if ( epochMillis != null ) { throw new InvalidValuesArgumentException( field.name() + " cannot be selected together with epochMillis." ); } - datetime = assignment( Field.datetime, datetime, value ); + datetime = assignment( TemporalFields.datetime, datetime, value ); } - else if ( field == Field.epochSeconds ) + else if ( field == TemporalFields.epochSeconds ) { if ( epochMillis != null ) { @@ -960,9 +968,9 @@ else if ( datetime != null ) { throw new InvalidValuesArgumentException( field.name() + " cannot be selected together with datetime." ); } - epochSeconds = assignment( Field.epochSeconds, epochSeconds, value ); + epochSeconds = assignment( TemporalFields.epochSeconds, epochSeconds, value ); } - else if ( field == Field.epochMillis ) + else if ( field == TemporalFields.epochMillis ) { if ( epochSeconds != null ) { @@ -972,7 +980,7 @@ else if ( datetime != null ) { throw new InvalidValuesArgumentException( field.name() + " cannot be selected together with datetime." ); } - epochMillis = assignment( Field.epochMillis, epochMillis, value ); + epochMillis = assignment( TemporalFields.epochMillis, epochMillis, value ); } else { @@ -990,9 +998,9 @@ private static class SelectDateOrTimeDTBuilder extends DateTimeBuilder } @Override - DateTimeBuilder assign( Field field, AnyValue value ) + DateTimeBuilder assign( TemporalFields field, AnyValue value ) { - if ( field == Field.datetime || field == Field.epochSeconds || field == Field.epochMillis ) + if ( field == TemporalFields.datetime || field == TemporalFields.epochSeconds || field == TemporalFields.epochMillis ) { throw new InvalidValuesArgumentException( field.name() + " cannot be selected together with date or time." ); } @@ -1005,7 +1013,7 @@ DateTimeBuilder assign( Field field, AnyValue value ) private abstract static class DateBuilder { - abstract DateBuilder assign( Field field, AnyValue value ); + abstract DateBuilder assign( TemporalFields field, AnyValue value ); abstract void checkAssignments(); @@ -1026,7 +1034,7 @@ private static final class ConstructTime { } - void assign( Field field, AnyValue value ) + void assign( TemporalFields field, AnyValue value ) { switch ( field ) { @@ -1082,7 +1090,7 @@ private static class ConstructDate extends DateBuilder } @Override - ConstructDate assign( Field field, AnyValue value ) + ConstructDate assign( TemporalFields field, AnyValue value ) { switch ( field ) { @@ -1120,7 +1128,7 @@ void assertFullyAssigned() { if ( date == null ) { - throw new InvalidValuesArgumentException( Field.month.name() + " must be specified" ); + throw new InvalidValuesArgumentException( TemporalFields.month.name() + " must be specified" ); } } } @@ -1137,7 +1145,7 @@ private static final class CalendarDate extends ConstructDate } @Override - ConstructDate assign( Field field, AnyValue value ) + ConstructDate assign( TemporalFields field, AnyValue value ) { switch ( field ) { @@ -1164,7 +1172,7 @@ void checkAssignments() { if ( date == null ) { - assertDefinedInOrder( Pair.of( year, YEAR.propertyKey ), Pair.of( month, MONTH.propertyKey ), Pair.of( day, DAY.propertyKey ) ); + assertDefinedInOrder( Pair.of( year, "year" ), Pair.of( month, "month" ), Pair.of( day, "day" ) ); } } @@ -1173,7 +1181,7 @@ void assertFullyAssigned() { if ( date == null ) { - assertAllDefined( Pair.of( year, YEAR.propertyKey ), Pair.of( month, MONTH.propertyKey ), Pair.of( day, DAY.propertyKey ) ); + assertAllDefined( Pair.of( year, "year" ), Pair.of( month, "month" ), Pair.of( day, "day" ) ); } } } @@ -1190,7 +1198,7 @@ private static final class WeekDate extends ConstructDate } @Override - ConstructDate assign( Field field, AnyValue value ) + ConstructDate assign( TemporalFields field, AnyValue value ) { switch ( field ) { @@ -1243,7 +1251,7 @@ private static final class QuarterDate extends ConstructDate } @Override - ConstructDate assign( Field field, AnyValue value ) + ConstructDate assign( TemporalFields field, AnyValue value ) { switch ( field ) { @@ -1295,7 +1303,7 @@ private static final class OrdinalDate extends ConstructDate } @Override - ConstructDate assign( Field field, AnyValue value ) + ConstructDate assign( TemporalFields field, AnyValue value ) { switch ( field ) { @@ -1324,7 +1332,7 @@ void assertFullyAssigned() } } - private static AnyValue assignment( Field field, AnyValue oldValue, AnyValue newValue ) + private static AnyValue assignment( TemporalFields field, AnyValue oldValue, AnyValue newValue ) { if ( oldValue != null ) { @@ -1387,9 +1395,9 @@ static ZoneId timezoneOf( AnyValue timezone ) static int validNano( AnyValue millisecond, AnyValue microsecond, AnyValue nanosecond ) { - long ms = safeCastIntegral( "millisecond", millisecond, Field.millisecond.defaultValue ); - long us = safeCastIntegral( "microsecond", microsecond, Field.microsecond.defaultValue ); - long ns = safeCastIntegral( "nanosecond", nanosecond, Field.nanosecond.defaultValue ); + long ms = safeCastIntegral( "millisecond", millisecond, TemporalFields.millisecond.defaultValue ); + long us = safeCastIntegral( "microsecond", microsecond, TemporalFields.microsecond.defaultValue ); + long ns = safeCastIntegral( "nanosecond", nanosecond, TemporalFields.nanosecond.defaultValue ); if ( ms < 0 || ms >= 1000 ) { throw new InvalidValuesArgumentException( "Invalid value for Millisecond: " + ms ); diff --git a/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java index 7dfb61d0971bd..f349ae4a5cc81 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java @@ -182,7 +182,8 @@ public static TimeValue truncate( static OffsetTime defaultTime( ZoneId zoneId ) { - return OffsetTime.of( Field.hour.defaultValue, Field.minute.defaultValue, Field.second.defaultValue, Field.nanosecond.defaultValue, + return OffsetTime.of( TemporalFields.hour.defaultValue, TemporalFields.minute.defaultValue, + TemporalFields.second.defaultValue, TemporalFields.nanosecond.defaultValue, assertValidZone( () -> ZoneOffset.of( zoneId.toString() ) ) ); } @@ -199,12 +200,12 @@ protected boolean supportsTimeZone() @Override public TimeValue buildInternal() { - boolean selectingTime = fields.containsKey( Field.time ); + boolean selectingTime = fields.containsKey( TemporalFields.time ); boolean selectingTimeZone; OffsetTime result; if ( selectingTime ) { - AnyValue time = fields.get( Field.time ); + AnyValue time = fields.get( TemporalFields.time ); if ( !(time instanceof TemporalValue) ) { throw new InvalidValuesArgumentException( String.format( "Cannot construct time from: %s", time ) );