diff --git a/e2e-tests/README.md b/e2e-tests/README.md index c0e787296a..87aa9244b3 100644 --- a/e2e-tests/README.md +++ b/e2e-tests/README.md @@ -2,9 +2,18 @@ This directory contains automated end-to-end tests for Aerie. -## Getting Started +## Running + +`AUTH_TYPE` must be set to `none` in order to run end-to-end tests. +A Docker stack with authorization disabled is available within this directory. +To spin up this stack run: + +```sh +docker compose -f docker-compose-test.yml up +``` + +After starting the development Docker compose stack the following commands can be issued to run these tests: ```sh -npm install -npm test +npm install && npm test ``` diff --git a/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/types/RealDynamics.java b/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/types/RealDynamics.java index 9ad7a0b96b..19933402f7 100644 --- a/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/types/RealDynamics.java +++ b/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/types/RealDynamics.java @@ -1,5 +1,6 @@ package gov.nasa.jpl.aerie.merlin.protocol.types; +import java.util.Objects; import java.util.Optional; /** @@ -27,15 +28,15 @@ public static RealDynamics linear(final double initial, final double rate) { } - public final RealDynamics scaledBy(final double scalar) { + public RealDynamics scaledBy(final double scalar) { return linear(this.initial * scalar, this.rate * scalar); } - public final RealDynamics plus(final RealDynamics other) { + public RealDynamics plus(final RealDynamics other) { return linear(this.initial + other.initial, this.rate + other.rate); } - public final RealDynamics minus(final RealDynamics other) { + public RealDynamics minus(final RealDynamics other) { return this.plus(other.scaledBy(-1.0)); } @@ -94,15 +95,20 @@ public final RealDynamics minus(final RealDynamics other) { @Override - public final String toString() { + public String toString() { return "λt. " + this.initial + " + t * " + this.rate; } @Override - public final boolean equals(final Object o) { + public boolean equals(final Object o) { if (!(o instanceof RealDynamics)) return false; final var other = (RealDynamics) o; return (this.initial == other.initial) && (this.rate == other.rate); } + + @Override + public int hashCode() { + return Objects.hash(initial, rate); + } } diff --git a/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/types/ValueSchema.java b/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/types/ValueSchema.java index 4a165eb611..d45affa98f 100644 --- a/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/types/ValueSchema.java +++ b/merlin-sdk/src/main/java/gov/nasa/jpl/aerie/merlin/protocol/types/ValueSchema.java @@ -22,10 +22,7 @@ */ // TODO: We will likely want to extend ValueSchema to support common semantic types // such as DateTime objects (which might otherwise be serialized as strings). -public abstract class ValueSchema { - // Closed type family -- the only legal subclasses are those defined within the body of - // this class definition. - private ValueSchema() {} +public sealed interface ValueSchema { /** * Calls the appropriate method of the passed Visitor depending on the kind of data @@ -36,7 +33,7 @@ private ValueSchema() {} * @return The result of calling `visitor.onX()`, where `X` depends on the kind of data * contained in this object. */ - public abstract T match(Visitor visitor); + T match(Visitor visitor); /** * An operation to be performed over the schema described by a ValueSchema. @@ -50,7 +47,7 @@ private ValueSchema() {} * * @param The return type of the operation represented by this Visitor. */ - public interface Visitor { + interface Visitor { T onReal(); T onInt(); T onBoolean(); @@ -62,88 +59,66 @@ public interface Visitor { T onVariant(List variants); } - /** - * Creates a {@link ValueSchema} representing the domain of real numbers. - * - * @return A new {@link ValueSchema} representing the domain of real numbers. - */ - private static ValueSchema ofReal() { - return new ValueSchema() { - @Override - public T match(final Visitor visitor) { - return visitor.onReal(); - } - }; + record RealSchema() implements ValueSchema { + @Override + public T match(final Visitor visitor) { + return visitor.onReal(); + } } - /** - * Creates a {@link ValueSchema} representing the domain of integers. - * - * @return A new {@link ValueSchema} representing the domain of integers. - */ - private static ValueSchema ofInt() { - return new ValueSchema() { - @Override - public T match(final Visitor visitor) { - return visitor.onInt(); - } - }; + record IntSchema() implements ValueSchema { + @Override + public T match(final Visitor visitor) { + return visitor.onInt(); + } } - /** - * Creates a {@link ValueSchema} representing a {@link boolean} type. - * - * @return A new {@link ValueSchema} representing a {@link boolean} type. - */ - private static ValueSchema ofBoolean() { - return new ValueSchema() { - @Override - public T match(final Visitor visitor) { - return visitor.onBoolean(); - } - }; + record BooleanSchema() implements ValueSchema { + @Override + public T match(final Visitor visitor) { + return visitor.onBoolean(); + } } - /** - * Creates a {@link ValueSchema} representing a {@link String} type. - * - * @return A new {@link ValueSchema} representing a {@link String} type. - */ - private static ValueSchema ofString() { - return new ValueSchema() { - @Override - public T match(final Visitor visitor) { - return visitor.onString(); - } - }; + record StringSchema() implements ValueSchema { + @Override + public T match(final Visitor visitor) { + return visitor.onString(); + } } - /** - * Creates a {@link ValueSchema} representing a {@link Duration} type. - * - * @return A new {@link ValueSchema} representing a {@link Duration} type. - */ - private static ValueSchema ofDuration() { - return new ValueSchema() { - @Override - public T match(final Visitor visitor) { - return visitor.onDuration(); - } - }; + record DurationSchema() implements ValueSchema { + @Override + public T match(final Visitor visitor) { + return visitor.onDuration(); + } } - /** - * Creates a {@link ValueSchema} representing a {@link Path} type. - * - * @return A new {@link ValueSchema} representing a {@link Path} type. - */ - private static ValueSchema ofPath() { - return new ValueSchema() { - @Override - public T match(final Visitor visitor) { - return visitor.onPath(); - } - }; + record PathSchema() implements ValueSchema { + @Override + public T match(final Visitor visitor) { + return visitor.onPath(); + } + } + + record SeriesSchema(ValueSchema value) implements ValueSchema { + @Override + public T match(final Visitor visitor) { + return visitor.onSeries(value); + } + } + + record StructSchema(Map value) implements ValueSchema { + @Override + public T match(final Visitor visitor) { + return visitor.onStruct(value); + } + } + + record VariantSchema(List variants) implements ValueSchema { + public T match(final Visitor visitor) { + return visitor.onVariant(variants); + } } /** @@ -153,14 +128,9 @@ public T match(final Visitor visitor) { * @param value A {@link ValueSchema}. * @return A new {@link ValueSchema} representing a homogeneous list of elements. */ - public static ValueSchema ofSeries(final ValueSchema value) { + static ValueSchema ofSeries(final ValueSchema value) { Objects.requireNonNull(value); - return new ValueSchema() { - @Override - public T match(final Visitor visitor) { - return visitor.onSeries(value); - } - }; + return new SeriesSchema(value); } /** @@ -170,15 +140,10 @@ public T match(final Visitor visitor) { * @param map Any set of named {@link ValueSchema}s. * @return A new {@link ValueSchema} representing a heterogeneous set of named {@link ValueSchema}s. */ - public static ValueSchema ofStruct(final Map map) { + static ValueSchema ofStruct(final Map map) { for (final var v : Objects.requireNonNull(map).values()) Objects.requireNonNull(v); final var value = Map.copyOf(map); - return new ValueSchema() { - @Override - public T match(final Visitor visitor) { - return visitor.onStruct(value); - } - }; + return new StructSchema(value); } /** @@ -186,21 +151,17 @@ public T match(final Visitor visitor) { * * @return A new {@link ValueSchema} representing an {@link Enum} type. */ - public static ValueSchema ofVariant(final List variants) { + static ValueSchema ofVariant(final List variants) { Objects.requireNonNull(variants); - return new ValueSchema() { - public T match(final Visitor visitor) { - return visitor.onVariant(variants); - } - }; + return new VariantSchema(variants); } - public static final ValueSchema REAL = ofReal(); - public static final ValueSchema INT = ofInt(); - public static final ValueSchema BOOLEAN = ofBoolean(); - public static final ValueSchema STRING = ofString(); - public static final ValueSchema DURATION = ofDuration(); - public static final ValueSchema PATH = ofPath(); + ValueSchema REAL = new RealSchema(); + ValueSchema INT = new IntSchema(); + ValueSchema BOOLEAN = new BooleanSchema(); + ValueSchema STRING = new StringSchema(); + ValueSchema DURATION = new DurationSchema(); + ValueSchema PATH = new PathSchema(); /** * Provides a default case on top of the base Visitor. @@ -210,7 +171,7 @@ public T match(final Visitor visitor) { * * @param The return type of the operation represented by this {@link Visitor}. */ - public static abstract class DefaultVisitor implements Visitor { + abstract class DefaultVisitor implements Visitor { protected abstract T onDefault(); @Override @@ -282,7 +243,7 @@ public Optional onVariant(final List variants) { * @return A non-empty {@link Optional} if this object represents a real number. * Otherwise, returns an empty {@link Optional}. */ - public Optional asReal() { + default Optional asReal() { return this.match(new OptionalVisitor<>() { @Override public Optional onReal() { @@ -297,7 +258,7 @@ public Optional onReal() { * @return A non-empty {@link Optional} if this object represents an integer. * Otherwise, returns an empty {@link Optional}. */ - public Optional asInt() { + default Optional asInt() { return this.match(new OptionalVisitor<>() { @Override public Optional onInt() { @@ -312,7 +273,7 @@ public Optional onInt() { * @return A non-empty {@link Optional} if this object represents an boolean. * Otherwise, returns an empty {@link Optional}. */ - public Optional asBoolean() { + default Optional asBoolean() { return this.match(new OptionalVisitor<>() { @Override public Optional onBoolean() { @@ -327,7 +288,7 @@ public Optional onBoolean() { * @return A non-empty {@link Optional} if this object represents a String. * Otherwise, returns an empty {@link Optional}. */ - public Optional asString() { + default Optional asString() { return this.match(new OptionalVisitor<>() { @Override public Optional onString() { @@ -342,7 +303,7 @@ public Optional onString() { * @return A non-empty {@link Optional} if this object represents a Duration. * Otherwise, returns an empty {@link Optional}. */ - public Optional asDuration() { + default Optional asDuration() { return this.match(new OptionalVisitor<>() { @Override public Optional onDuration() { @@ -357,7 +318,7 @@ public Optional onDuration() { * @return A non-empty {@link Optional} if this object represents a Path. * Otherwise, returns an empty {@link Optional}. */ - public Optional asPath() { + default Optional asPath() { return this.match(new OptionalVisitor<>() { @Override public Optional onPath() { @@ -372,7 +333,7 @@ public Optional onPath() { * @return An {@link Optional} containing a schema for elements of a homogeneous list if this * object represents a series. Otherwise, returns an empty {@link Optional}. */ - public Optional asSeries() { + default Optional asSeries() { return this.match(new OptionalVisitor<>() { @Override public Optional onSeries(final ValueSchema value) { @@ -387,7 +348,7 @@ public Optional onSeries(final ValueSchema value) { * @return An {@link Optional} containing a map if this object represents a map. * Otherwise, returns an empty {@link Optional}. */ - public Optional> asStruct() { + default Optional> asStruct() { return this.match(new OptionalVisitor<>() { @Override public Optional> onStruct(final Map value) { @@ -402,7 +363,7 @@ public Optional> onStruct(final Map> asVariant() { + default Optional> asVariant() { return this.match(new OptionalVisitor<>() { @Override public Optional> onVariant(final List variants) { @@ -410,113 +371,9 @@ public Optional> onVariant(final List variants) { } }); } - - @Override - public String toString() { - return this.match(new Visitor<>() { - @Override - public String onReal() { - return "ValueSchema.REAL"; - } - - @Override - public String onInt() { - return "ValueSchema.INT"; - } - - @Override - public String onBoolean() { - return "ValueSchema.BOOLEAN"; - } - - @Override - public String onString() { - return "ValueSchema.STRING"; - } - - @Override - public String onDuration() { - return "ValueSchema.DURATION"; - } - - @Override - public String onPath() { - return "ValueSchema.PATH"; - } - - @Override - public String onSeries(final ValueSchema value) { - return "[" + value + "]"; - } - - @Override - public String onStruct(final Map value) { - return String.valueOf(value); - } - - @Override - public String onVariant(final List variants) { - return "ValueSchema.VARIANT(" + variants.toString() + ")"; - } - }); - } - - @Override - public boolean equals(final Object o) { - if (!(o instanceof ValueSchema)) return false; - final var other = (ValueSchema) o; - - return this.match(new Visitor<>() { - @Override - public Boolean onReal() { - return other.asReal().isPresent(); - } - - @Override - public Boolean onInt() { - return other.asInt().isPresent(); - } - - @Override - public Boolean onBoolean() { - return other.asBoolean().isPresent(); - } - - @Override - public Boolean onString() { - return other.asString().isPresent(); - } - - @Override - public Boolean onDuration() { - return other.asDuration().isPresent(); - } - - @Override - public Boolean onPath() { - return other.asPath().isPresent(); - } - - @Override - public Boolean onSeries(final ValueSchema value) { - return other.asSeries().map(x -> x.equals(value)).orElse(false); - } - - @Override - public Boolean onStruct(final Map value) { - return other.asStruct().map(x -> x.equals(value)).orElse(false); - } - - @Override - public Boolean onVariant(final List variants) { - return other.asVariant().map(x -> x.equals(variants)).orElse(false); - } - }); - } - /** * @param key The unique internal name of this variant * @param label The user-facing presentation of this variant */ - public record Variant(String key, String label) {} + record Variant(String key, String label) {} } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/ActivityInstance.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/ActivityInstance.java index 0e45f3122a..bf4fe09784 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/ActivityInstance.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/ActivityInstance.java @@ -38,4 +38,9 @@ public boolean equals(final Object object) { && Objects.equals(this.arguments, other.arguments) ); } + + @Override + public int hashCode() { + return Objects.hash(type, startTimestamp, arguments); + } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/MissionModelJar.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/MissionModelJar.java index 38b988349c..1ca70fd370 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/MissionModelJar.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/MissionModelJar.java @@ -4,42 +4,53 @@ import java.util.Objects; public final class MissionModelJar { - public String name; - public String version; - public String mission; - public String owner; - - /** - * The path to the Mission Model JAR - * - * File at this location should not - * be deleted except by its owner - */ - public Path path; - - public MissionModelJar() {} - - public MissionModelJar(final MissionModelJar other) { - this.name = other.name; - this.version = other.version; - this.mission = other.mission; - this.owner = other.owner; - this.path = other.path; - } - - @Override - public boolean equals(final Object object) { - if (object.getClass() != MissionModelJar.class) { - return false; - } - - final MissionModelJar other = (MissionModelJar)object; - return - ( Objects.equals(this.name, other.name) - && Objects.equals(this.version, other.version) - && Objects.equals(this.mission, other.mission) - && Objects.equals(this.owner, other.owner) - && Objects.equals(this.path, other.path) - ); - } + public String name; + public String version; + public String mission; + public String owner; + + /** + * The path to the Mission Model JAR + * + * File at this location should not + * be deleted except by its owner + */ + public Path path; + + public MissionModelJar() {} + + public MissionModelJar(final MissionModelJar other) { + this.name = other.name; + this.version = other.version; + this.mission = other.mission; + this.owner = other.owner; + this.path = other.path; + } + + @Override + public boolean equals(final Object object) { + if (object.getClass() != MissionModelJar.class) { + return false; + } + + final MissionModelJar other = (MissionModelJar)object; + return + ( Objects.equals(this.name, other.name) + && Objects.equals(this.version, other.version) + && Objects.equals(this.mission, other.mission) + && Objects.equals(this.owner, other.owner) + && Objects.equals(this.path, other.path) + ); + } + + @Override + public int hashCode() { + return Objects.hash( + name, + version, + mission, + owner, + path + ); + } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/NewPlan.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/NewPlan.java index 9401f83304..e45352555c 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/NewPlan.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/NewPlan.java @@ -66,4 +66,16 @@ public boolean equals(final Object object) { && Objects.equals(this.configuration, other.configuration) ); } + + @Override + public int hashCode() { + return Objects.hash( + name, + missionModelId, + startTimestamp, + endTimestamp, + activityInstances, + configuration + ); + } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/Plan.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/Plan.java index 275530be27..e1a617cee4 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/Plan.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/Plan.java @@ -65,4 +65,16 @@ public boolean equals(final Object object) { && Objects.equals(this.configuration, other.configuration) ); } + + @Override + public int hashCode() { + return Objects.hash( + name, + missionModelId, + startTimestamp, + endTimestamp, + activityInstances, + configuration + ); + } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/Timestamp.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/Timestamp.java index 74d0096a9c..16932f0fde 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/Timestamp.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/models/Timestamp.java @@ -10,7 +10,7 @@ import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; -public class Timestamp { +public record Timestamp(ZonedDateTime time) { // This builder must be used to get optional subsecond values // See: https://stackoverflow.com/questions/30090710/java-8-datetimeformatter-parsing-for-optional-fractional-seconds-of-varying-sign public static final DateTimeFormatter format = @@ -19,18 +19,12 @@ public class Timestamp { .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true) .toFormatter(); - public final ZonedDateTime time; - - private Timestamp(final ZonedDateTime timestamp) { - this.time = timestamp; - } - private Timestamp(String timestamp) throws DateTimeParseException { - time = LocalDateTime.parse(timestamp, format).atZone(ZoneOffset.UTC); + this(LocalDateTime.parse(timestamp, format).atZone(ZoneOffset.UTC)); } public Timestamp(Instant instant) { - time = instant.atZone(ZoneOffset.UTC); + this(instant.atZone(ZoneOffset.UTC)); } public static Timestamp fromString(String timestamp) throws DateTimeParseException { @@ -49,16 +43,8 @@ public Instant toInstant() { return time.toInstant(); } + @Override public String toString() { return format.format(time); } - - public boolean equals(final Object object) { - if (!(object instanceof Timestamp)) { - return false; - } - - final var other = (Timestamp)object; - return this.time.equals(other.time); - } } diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PreparedStatements.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PreparedStatements.java index cf41e81ada..1c882cf819 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PreparedStatements.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/remotes/postgres/PreparedStatements.java @@ -23,7 +23,7 @@ private PreparedStatements() {} public static void setTimestamp(final PreparedStatement statement, final int parameter, final Timestamp argument) throws SQLException { - statement.setString(parameter, TIMESTAMP_FORMAT.format(argument.time)); + statement.setString(parameter, TIMESTAMP_FORMAT.format(argument.time())); } public static void setParameters(final PreparedStatement statement, final int parameter, final List parameters) diff --git a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/Breadcrumb.java b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/Breadcrumb.java index 6ac4976eaf..6155ed915e 100644 --- a/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/Breadcrumb.java +++ b/merlin-server/src/main/java/gov/nasa/jpl/aerie/merlin/server/services/Breadcrumb.java @@ -1,64 +1,33 @@ package gov.nasa.jpl.aerie.merlin.server.services; -import java.util.Objects; +public interface Breadcrumb { -public abstract class Breadcrumb { - private Breadcrumb() {} - - public interface Visitor { + interface Visitor { T onListIndex(int index); T onMapIndex(String index); } - public abstract T match(final Visitor visitor); - - static public Breadcrumb of(final String index) { - final class MapBreadcrumb extends Breadcrumb { - private String getIndex() { - return index; - } + T match(final Visitor visitor); + static Breadcrumb of(final String index) { + record MapBreadcrumb(String index) implements Breadcrumb { @Override public T match(final Visitor visitor) { return visitor.onMapIndex(index); } - - @Override - public boolean equals(final Object object) { - return (object instanceof MapBreadcrumb && Objects.equals(((MapBreadcrumb)object).getIndex(), index)); - } - - @Override - public String toString() { - return "\"" + index + "\""; - } } - return new MapBreadcrumb(); + return new MapBreadcrumb(index); } - static public Breadcrumb of(final int index) { - final class ListBreadcrumb extends Breadcrumb { - private int getIndex() { - return index; - } - + static Breadcrumb of(final int index) { + record ListBreadcrumb(int index) implements Breadcrumb { @Override public T match(final Visitor visitor) { return visitor.onListIndex(index); } - - @Override - public boolean equals(final Object object) { - return (object instanceof ListBreadcrumb && Objects.equals(((ListBreadcrumb)object).getIndex(), index)); - } - - @Override - public String toString() { - return String.valueOf(index); - } } - return new ListBreadcrumb(); + return new ListBreadcrumb(index); } } diff --git a/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/models/Timestamp.java b/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/models/Timestamp.java index e6fb44b391..c8459e74c0 100644 --- a/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/models/Timestamp.java +++ b/scheduler-server/src/main/java/gov/nasa/jpl/aerie/scheduler/server/models/Timestamp.java @@ -10,7 +10,7 @@ import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; -public class Timestamp { +public record Timestamp(ZonedDateTime time) { // This builder must be used to get optional subsecond values // See: https://stackoverflow.com/questions/30090710/java-8-datetimeformatter-parsing-for-optional-fractional-seconds-of-varying-sign public static final DateTimeFormatter format = @@ -19,18 +19,12 @@ public class Timestamp { .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true) .toFormatter(); - public final ZonedDateTime time; - - private Timestamp(final ZonedDateTime timestamp) { - this.time = timestamp; - } - private Timestamp(String timestamp) throws DateTimeParseException { - time = LocalDateTime.parse(timestamp, format).atZone(ZoneOffset.UTC); + this(LocalDateTime.parse(timestamp, format).atZone(ZoneOffset.UTC)); } public Timestamp(Instant instant) { - time = instant.atZone(ZoneOffset.UTC); + this(instant.atZone(ZoneOffset.UTC)); } public static Timestamp fromString(String timestamp) throws DateTimeParseException { @@ -49,16 +43,8 @@ public Instant toInstant() { return time.toInstant(); } + @Override public String toString() { return format.format(time); } - - public boolean equals(final Object object) { - if (!(object instanceof Timestamp)) { - return false; - } - - final var other = (Timestamp)object; - return this.time.equals(other.time); - } } diff --git a/scheduler/build.gradle b/scheduler/build.gradle index 26509ddb35..63480b1584 100644 --- a/scheduler/build.gradle +++ b/scheduler/build.gradle @@ -39,5 +39,5 @@ dependencies { testImplementation 'com.google.truth.extensions:truth-java8-extension:1.1.3' //for when aerielander will be published //testImplementation 'gov.nasa.jpl.aerie:aerielander:0.11.0-SNAPSHOT-+' - testImplementation files('src/test/resources/gov/nasa/jpl/aerie/scheduler/aerie-lander-0.11.1-SNAPSHOT.jar') + testImplementation files('src/test/resources/gov/nasa/jpl/aerie/scheduler/aerielander.jar') } diff --git a/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/constraints/timeexpressions/TimeExpressionBefore.java b/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/constraints/timeexpressions/TimeExpressionBefore.java index 5273da66f8..079efee5d3 100644 --- a/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/constraints/timeexpressions/TimeExpressionBefore.java +++ b/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/constraints/timeexpressions/TimeExpressionBefore.java @@ -20,31 +20,17 @@ public TimeExpressionBefore(final TimeExpression expr, final String name) { @Override public Window computeTime(final SimulationResults simulationResults, final Plan plan, final Window interval) { - var origin = expr.computeTime(simulationResults, plan, interval); + final var origin = expr.computeTime(simulationResults, plan, interval); assert(origin.isSingleton()); - Duration from = origin.start; + final var from = origin.start; Duration res = from; for (final var entry : this.operations) { res = TimeUtility.performOperation(entry.getKey(), res, entry.getValue()); } - Window retRange; - - //if we want an range of possibles - if (res.compareTo(from) > 0) { - retRange = Window.between(from, res); - } else { - retRange = Window.between(res, from); - } - return retRange; - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TimeExpressionBefore that = (TimeExpressionBefore) o; - return Objects.equals(expr, that.expr) && Objects.equals(operations, that.operations); + return res.compareTo(from) > 0 ? // If we want a range of possibles + Window.between(from, res) : + Window.between(res, from); } } diff --git a/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/constraints/timeexpressions/TimeExpressionConstant.java b/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/constraints/timeexpressions/TimeExpressionConstant.java index 92bace9ab5..159d156a51 100644 --- a/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/constraints/timeexpressions/TimeExpressionConstant.java +++ b/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/constraints/timeexpressions/TimeExpressionConstant.java @@ -21,12 +21,4 @@ public TimeExpressionConstant(final Duration instant) { public Window computeTime(final SimulationResults simulationResults, final Plan plan, final Window interval) { return Window.at(this.instant); } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TimeExpressionConstant that = (TimeExpressionConstant) o; - return Objects.equals(instant, that.instant) && Objects.equals(operations, that.operations); - } } diff --git a/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/ActivityType.java b/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/ActivityType.java index e0741d1e34..cd2a825ddc 100644 --- a/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/ActivityType.java +++ b/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/ActivityType.java @@ -150,4 +150,8 @@ public boolean equals(final Object o) { && Objects.equals(this.specType, that.specType); } + @Override + public int hashCode() { + return name.hashCode(); + } } diff --git a/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/PlanInMemory.java b/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/PlanInMemory.java index 2821ce0ec3..5930c322ba 100644 --- a/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/PlanInMemory.java +++ b/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/PlanInMemory.java @@ -117,7 +117,7 @@ public void remove(ActivityInstance act) { actsById.remove(act.getId()); var acts = actsByTime.get(act.getStartTime()); if (acts != null) acts.remove(act); - acts = actsByType.get(act.getType().getName()); + acts = actsByType.get(act.getType()); if (acts != null) acts.remove(act); actsSet.remove(act); } diff --git a/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/Problem.java b/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/Problem.java index fa7cf1997f..45e5e890ee 100644 --- a/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/Problem.java +++ b/scheduler/src/main/java/gov/nasa/jpl/aerie/scheduler/model/Problem.java @@ -46,7 +46,6 @@ public class Problem { * container of all goals in the problem, indexed by name */ protected final List goalsOrderedByPriority = new ArrayList<>(); - private final java.util.HashMap goalsByName = new java.util.HashMap<>(); /** * activity type definitions in the mission model, indexed by name diff --git a/scheduler/src/test/resources/gov/nasa/jpl/aerie/scheduler/aerie-lander-0.11.1-SNAPSHOT.jar b/scheduler/src/test/resources/gov/nasa/jpl/aerie/scheduler/aerielander.jar similarity index 88% rename from scheduler/src/test/resources/gov/nasa/jpl/aerie/scheduler/aerie-lander-0.11.1-SNAPSHOT.jar rename to scheduler/src/test/resources/gov/nasa/jpl/aerie/scheduler/aerielander.jar index 6682213ef8..ae2c5e5397 100644 Binary files a/scheduler/src/test/resources/gov/nasa/jpl/aerie/scheduler/aerie-lander-0.11.1-SNAPSHOT.jar and b/scheduler/src/test/resources/gov/nasa/jpl/aerie/scheduler/aerielander.jar differ