From e248725534cff454352ebbfc166e2ab3637c496d Mon Sep 17 00:00:00 2001
From: Peter Powers <pmpowers@usgs.gov>
Date: Wed, 27 Jan 2021 09:01:06 -0700
Subject: [PATCH] service updates and refactoring

---
 .../nshmp/aws/HazardResultSliceLambda.java    |   1 -
 .../aws/HazardResultsMetadataLambda.java      |   1 -
 .../nshmp/aws/HazardResultsSlicerLambda.java  |   1 -
 .../earthquake/nshmp/site/CybershakeSite.java |   1 -
 .../earthquake/nshmp/site/NshmpPolygon.java   |   1 -
 .../usgs/earthquake/nshmp/site/NshmpSite.java |   1 -
 .../usgs/earthquake/nshmp/site/NuregSite.java |   1 -
 .../nshmp/www/HazardController.java           |  37 +++--
 .../nshmp/www/meta/Constrained.java           |  10 --
 .../nshmp/www/meta/Constraints.java           |   7 -
 .../earthquake/nshmp/www/meta/MetaUtil.java   |   9 +-
 .../earthquake/nshmp/www/meta/Metadata.java   |  53 +++---
 .../www/services/DeaggEpsilonService.java     |  12 +-
 .../nshmp/www/services/HazardService.java     | 154 +++++++++++++-----
 .../nshmp/www/services/RateService.java       |  12 +-
 .../nshmp/www/services/ServicesUtil.java      |   8 +-
 .../nshmp/www/services/ServletUtil.java       |   1 +
 .../nshmp/www/services/SourceServices.java    |   3 +-
 .../usgs/earthquake/nshmp/NshmTestsLarge.java |   1 -
 .../usgs/earthquake/nshmp/NshmTestsSmall.java |   1 -
 .../nshmp/programs/HazardCurveTest.java       |   1 -
 .../earthquake/nshmp/site/NshmpSiteTests.java |   1 -
 22 files changed, 177 insertions(+), 140 deletions(-)
 delete mode 100644 src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constrained.java
 delete mode 100644 src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constraints.java

diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
index 5ba9a19fc..74f7fc811 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
@@ -46,7 +46,6 @@ import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
  *
  * The results are written to S3 as map.csv bucket.
  */
-@SuppressWarnings("unused")
 public class HazardResultSliceLambda implements RequestStreamHandler {
 
   private static final AmazonS3 S3 = AmazonS3ClientBuilder.defaultClient();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
index d7ece57af..1d7db3b60 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
@@ -43,7 +43,6 @@ import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
  * AWS Lambda function to list all hazard results in the nshmp-hazout S3 bucket
  * that contain a map.csv file.
  */
-@SuppressWarnings("unused")
 public class HazardResultsMetadataLambda implements RequestStreamHandler {
 
   private static final AmazonS3 S3 = AmazonS3ClientBuilder.defaultClient();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
index f48d7babe..ac5925f3e 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
@@ -39,7 +39,6 @@ import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
  *
  * @see HazardResultSliceLambda
  */
-@SuppressWarnings("unused")
 public class HazardResultsSlicerLambda implements RequestStreamHandler {
 
   private static final AmazonS3 S3 = AmazonS3ClientBuilder.defaultClient();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java b/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java
index 1cd89db28..712fb6fc6 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java
@@ -8,7 +8,6 @@ import gov.usgs.earthquake.nshmp.geo.Location;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum CybershakeSite implements NamedLocation {
 
   /*
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java
index 16e84e249..9699ecaf0 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java
@@ -7,7 +7,6 @@ import gov.usgs.earthquake.nshmp.geo.LocationList;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum NshmpPolygon {
 
   CEUS_CLIP(Data.CEUS_CLIP, "Central & Eastern US Map Extents"),
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java
index 370ad713f..2455bd64b 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java
@@ -18,7 +18,6 @@ import gov.usgs.earthquake.nshmp.internal.UsRegion;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum NshmpSite implements NamedLocation {
 
   // TODO move this and other nshmp specific classes to nshmp-haz
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java b/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java
index 0aba72dce..c28d33560 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java
@@ -11,7 +11,6 @@ import gov.usgs.earthquake.nshmp.internal.UsRegion;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum NuregSite implements NamedLocation {
 
   CENTRAL_IL(-90.000, 40.000),
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
index 73942632e..d678f3a50 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
@@ -1,11 +1,13 @@
 package gov.usgs.earthquake.nshmp.www;
 
+import java.util.Optional;
+
 import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet;
 import gov.usgs.earthquake.nshmp.www.services.HazardService;
-import gov.usgs.earthquake.nshmp.www.services.HazardService.Query;
+import gov.usgs.earthquake.nshmp.www.services.HazardService.QueryParameters;
 
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
@@ -69,21 +71,24 @@ public class HazardController {
   @ApiResponse(
       description = "Hazard curves",
       responseCode = "200")
-  @Get(uri = "{?longitude,latitude,vs30}")
+  @Get // (uri = "{?longitude,latitude,vs30}")
   public HttpResponse<String> doGetHazard(
       HttpRequest<?> request,
       @Schema(
           required = true,
           minimum = "-360",
-          maximum = "360") @QueryValue @Nullable Double longitude,
+          maximum = "360") @QueryValue @Nullable Optional<Double> longitude,
       @Schema(
           required = true,
           minimum = "-90",
-          maximum = "90") @QueryValue @Nullable Double latitude,
-      @Schema(required = true) @QueryValue @Nullable Integer vs30) {
-    var urlHelper = servlet.urlHelper(request);
-    var query = new Query(longitude, latitude, vs30);
-    return HazardService.handleDoGetHazard(query, urlHelper);
+          maximum = "90") @QueryValue @Nullable Optional<Double> latitude,
+      @Schema(
+          required = true) @QueryValue @Nullable Optional<Integer> vs30) {
+
+    var query = new QueryParameters(longitude, latitude, vs30);
+    return HazardService.handleDoGetHazard(
+        query,
+        servlet.urlHelper(request));
   }
 
   /**
@@ -107,15 +112,17 @@ public class HazardController {
       @Schema(
           required = true,
           minimum = "-360",
-          maximum = "360") @PathVariable @Nullable Double longitude,
+          maximum = "360") @PathVariable @Nullable Optional<Double> longitude,
       @Schema(
           required = true,
           minimum = "-90",
-          maximum = "90") @PathVariable @Nullable Double latitude,
-      @Schema(required = true) @PathVariable @Nullable Integer vs30) {
-    var urlHelper = servlet.urlHelper(request);
-    var query = new Query(longitude, latitude, vs30);
-    return HazardService.handleDoGetHazard(query, urlHelper);
-  }
+          maximum = "90") @PathVariable @Nullable Optional<Double> latitude,
+      @Schema(
+          required = true) @PathVariable @Nullable Optional<Integer> vs30) {
 
+    var query = new QueryParameters(longitude, latitude, vs30);
+    return HazardService.handleDoGetHazard(
+        query,
+        servlet.urlHelper(request));
+  }
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constrained.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constrained.java
deleted file mode 100644
index 2dbafe63b..000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constrained.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package gov.usgs.earthquake.nshmp.www.meta;
-
-/**
- * Interface implemented by enum parameters that impose restrictions on other
- * parameter choices.
- */
-@SuppressWarnings("javadoc")
-public interface Constrained {
-  public Constraints constraints();
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constraints.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constraints.java
deleted file mode 100644
index 449d3c7b8..000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constraints.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package gov.usgs.earthquake.nshmp.www.meta;
-
-/**
- * Marker interface for supported parameter lists and ; individual enums provide
- * concrete implementations.
- */
-public interface Constraints {}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
index 8e6377de3..271a99e43 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
@@ -21,7 +21,6 @@ import gov.usgs.earthquake.nshmp.gmm.GmmInput;
 import gov.usgs.earthquake.nshmp.gmm.GmmInput.Field;
 import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
 
-@SuppressWarnings("javadoc")
 public final class MetaUtil {
 
   public static <E extends Enum<E>> List<String> enumsToNameList(
@@ -46,10 +45,10 @@ public final class MetaUtil {
       jObj.addProperty("display", src.toString());
       jObj.addProperty("displayorder", src.ordinal());
 
-      if (src instanceof Constrained) {
-        Constrained cSrc = (Constrained) src;
-        jObj.add("supports", context.serialize(cSrc.constraints()));
-      }
+      // if (src instanceof Constrained) {
+      // Constrained cSrc = (Constrained) src;
+      // jObj.add("supports", context.serialize(cSrc.constraints()));
+      // }
 
       return jObj;
     }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
index e8f5a1e85..a358619db 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
@@ -1,22 +1,19 @@
 package gov.usgs.earthquake.nshmp.www.meta;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.base.Throwables;
-import com.google.gson.annotations.SerializedName;
 
 import gov.usgs.earthquake.nshmp.geo.Coordinates;
 import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 
 /**
  * Service metadata, parameterization, and constraint strings, in JSON format.
  */
-@SuppressWarnings("javadoc")
 public final class Metadata {
 
   static final String NSHMP_HAZ_URL = "https://code.usgs.gov/ghsc/nshmp/nshmp-haz";
 
-  @SuppressWarnings("unused")
   private static class Default {
 
     final String status;
@@ -32,48 +29,43 @@ public final class Metadata {
       this.status = Status.USAGE.toString();
       this.description = description;
       this.syntax = syntax;
-      this.server = serverData(1, new Timer());
+      this.server = serverData(1, Stopwatch.createStarted());
       this.parameters = parameters;
     }
   }
 
-  public static Object serverData(int threads, Timer timer) {
+  public static Object serverData(int threads, Stopwatch timer) {
     return new Server(threads, timer);
   }
 
-  @SuppressWarnings("unused")
   private static class Server {
 
     final int threads;
-    final String servlet;
-    final String calc;
+    final String timer;
+    final String version;
 
-    @SerializedName("nshmp-haz")
-    final Component nshmpHaz = NSHMP_HAZ_COMPONENT;
-
-    Server(int threads, Timer timer) {
+    Server(int threads, Stopwatch timer) {
       this.threads = threads;
-      this.servlet = timer.servletTime();
-      this.calc = timer.calcTime();
+      this.timer = timer.toString();
+      this.version = "TODO where to get version?";
     }
 
-    static Component NSHMP_HAZ_COMPONENT = new Component(
-        NSHMP_HAZ_URL,
-        Versions.NSHMP_HAZ_VERSION);
-
-    static final class Component {
-
-      final String url;
-      final String version;
-
-      Component(String url, String version) {
-        this.url = url;
-        this.version = version;
-      }
-    }
+    // static Component NSHMP_HAZ_COMPONENT = new Component(
+    // NSHMP_HAZ_URL,
+    // Versions.NSHMP_HAZ_VERSION);
+    //
+    // static final class Component {
+    //
+    // final String url;
+    // final String version;
+    //
+    // Component(String url, String version) {
+    // this.url = url;
+    // this.version = version;
+    // }
+    // }
   }
 
-  @SuppressWarnings("unused")
   public static class DefaultParameters {
 
     // final EnumParameter<Edition> edition;
@@ -132,7 +124,6 @@ public final class Metadata {
     return ServletUtil.GSON.toJson(error);
   }
 
-  @SuppressWarnings("unused")
   private static class Error {
 
     final String status = Status.ERROR.toString();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
index a7f7cf892..2f744fe86 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
@@ -11,6 +11,7 @@ import java.util.Properties;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Function;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.collect.ImmutableList;
 import com.google.common.io.Resources;
 
@@ -27,7 +28,6 @@ import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.www.DeaggEpsilonController;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
 import io.micronaut.http.HttpRequest;
@@ -81,7 +81,7 @@ public final class DeaggEpsilonService {
 
       query.checkValues();
       var data = new RequestData(query, query.vs30);
-      var response = process(data, timer, urlHelper);
+      var response = process(data, urlHelper);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -108,11 +108,11 @@ public final class DeaggEpsilonService {
 
   private static Response<RequestData, ResponseData> process(
       RequestData data,
-      Timer timer,
       UrlHelper urlHelper)
       throws InterruptedException, ExecutionException {
     var configFunction = new ConfigFunction();
     var siteFunction = new SiteFunction(data);
+    var timer = Stopwatch.createStarted();
     var hazard = ServicesUtil.calcHazard(configFunction, siteFunction);
     var deagg = Deaggregation.atImls(hazard, data.imtImls, ServletUtil.CALC_EXECUTOR);
     return new ResultBuilder()
@@ -186,7 +186,7 @@ public final class DeaggEpsilonService {
     }
   }
 
-  static final class RequestData extends HazardService.RequestData {
+  static final class RequestData extends HazardService.RequestDataOld {
     final EnumMap<Imt, Double> imtImls;
     final boolean basin;
 
@@ -242,7 +242,7 @@ public final class DeaggEpsilonService {
 
   static final class ResultBuilder {
     UrlHelper urlHelper;
-    Timer timer;
+    Stopwatch timer;
     RequestData request;
     Deaggregation deagg;
 
@@ -256,7 +256,7 @@ public final class DeaggEpsilonService {
       return this;
     }
 
-    ResultBuilder timer(Timer timer) {
+    ResultBuilder timer(Stopwatch timer) {
       this.timer = timer;
       return this;
     }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
index d0186a9bd..0a7d816d4 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
@@ -1,5 +1,6 @@
 package gov.usgs.earthquake.nshmp.www.services;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static gov.usgs.earthquake.nshmp.calc.HazardExport.curvesBySource;
 
@@ -7,9 +8,12 @@ import java.util.ArrayList;
 import java.util.EnumMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Function;
 
+import com.google.common.base.Stopwatch;
+
 import gov.usgs.earthquake.nshmp.calc.CalcConfig;
 import gov.usgs.earthquake.nshmp.calc.Hazard;
 import gov.usgs.earthquake.nshmp.calc.Site;
@@ -27,10 +31,8 @@ import gov.usgs.earthquake.nshmp.model.SourceType;
 import gov.usgs.earthquake.nshmp.www.HazardController;
 import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
-import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceRequestData;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
 import io.micronaut.http.HttpResponse;
@@ -76,17 +78,17 @@ public final class HazardService {
    * @param query The query
    * @param urlHelper The URL helper
    */
-  public static HttpResponse<String> handleDoGetHazard(Query query, UrlHelper urlHelper) {
-    try {
-      var timer = ServletUtil.timer();
+  public static HttpResponse<String> handleDoGetHazard(
+      QueryParameters query,
+      UrlHelper urlHelper) {
 
-      if (query.isNull()) {
+    try {
+      if (query.isEmpty()) {
         return handleDoGetUsage(urlHelper);
       }
-
-      query.checkValues();
-      var data = new RequestData(query, query.vs30);
-      var response = process(data, timer, urlHelper);
+      query.checkParameters();
+      var data = new RequestData(query);
+      var response = process(data, urlHelper);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -96,16 +98,18 @@ public final class HazardService {
 
   static Response<RequestData, ResponseData> process(
       RequestData data,
-      Timer timer,
-      UrlHelper urlHelper) throws InterruptedException, ExecutionException {
+      UrlHelper urlHelper)
+      throws InterruptedException, ExecutionException {
+
     var configFunction = new ConfigFunction();
     var siteFunction = new SiteFunction(data);
+    var stopwatch = Stopwatch.createStarted();
     var hazard = ServicesUtil.calcHazard(configFunction, siteFunction);
 
     return new ResultBuilder()
         .hazard(hazard)
         .requestData(data)
-        .timer(timer)
+        .timer(stopwatch)
         .urlHelper(urlHelper)
         .build();
   }
@@ -135,26 +139,38 @@ public final class HazardService {
     }
   }
 
-  public static class Query extends ServiceQueryData {
-    Integer vs30;
+  public static class QueryParameters {
 
-    public Query(Double longitude, Double latitude, Integer vs30) {
-      super(longitude, latitude);
+    Optional<Double> longitude;
+    Optional<Double> latitude;
+    Optional<Integer> vs30;
+
+    public QueryParameters(
+        Optional<Double> longitude,
+        Optional<Double> latitude,
+        Optional<Integer> vs30) {
+
+      this.longitude = longitude;
+      this.latitude = latitude;
       this.vs30 = vs30;
     }
 
-    @Override
-    public boolean isNull() {
-      return super.isNull() && vs30 == null;
+    public boolean isEmpty() {
+      return longitude.isEmpty() && latitude.isEmpty() && vs30.isEmpty();
     }
 
-    @Override
-    public void checkValues() {
-      super.checkValues();
-      WsUtils.checkValue(Key.VS30, vs30);
+    public void checkParameters() {
+      checkParameter(longitude, "longitude");
+      checkParameter(latitude, "latitude");
+      checkParameter(vs30, "vs30");
     }
   }
 
+  private static void checkParameter(Object param, String id) {
+    checkNotNull(param, "Missing parameter: %s", id);
+    // TODO check range here
+  }
+
   /* Service request and model metadata */
   static class RequestMetadata {
 
@@ -186,30 +202,53 @@ public final class HazardService {
     }
   }
 
-  static class RequestData extends ServiceRequestData {
-    final double vs30; // TODO bad bad bad replacement for Vs30 enum
+  static class RequestData {
 
-    RequestData(Query query, double vs30) {
-      super(query);
-      this.vs30 = vs30;
+    final double longitude;
+    final double latitude;
+    final double vs30;
+
+    RequestData(QueryParameters query) {
+      this.longitude = query.longitude.orElseThrow();
+      this.latitude = query.latitude.orElseThrow();
+      this.vs30 = query.vs30.orElseThrow();
     }
   }
 
   private static final class ResponseMetadata {
-    final SourceModel models;
-    final double latitude;
-    final double longitude;
-    final Imt imt;
-    final double vs30;
+    // final SourceModel model;
+    // final double latitude;
+    // final double longitude;
+    // final double vs30;
+    final String imt;
     final String xlabel = "Ground Motion (g)";
     final String ylabel = "Annual Frequency of Exceedence";
 
-    ResponseMetadata(RequestData request, Imt imt) {
-      models = new SourceModel(ServletUtil.model());
-      latitude = request.latitude;
-      longitude = request.longitude;
-      this.imt = imt;
-      vs30 = request.vs30;
+    ResponseMetadata(Imt imt) {
+      // model = new SourceModel(ServletUtil.model());
+      // latitude = data.latitude;
+      // longitude = data.longitude;
+      // vs30 = data.vs30;
+      this.imt = imtShortLabel(imt);
+    }
+  }
+
+  private static String imtShortLabel(Imt imt) {
+    if (imt.equals(Imt.PGA) || imt.equals(Imt.PGV)) {
+      return imt.name();
+    } else if (imt.isSA()) {
+      return imt.period() + " s";
+    }
+    return imt.toString();
+  }
+
+  @Deprecated
+  static class RequestDataOld extends ServiceRequestData {
+    final double vs30;
+
+    RequestDataOld(Query query, double vs30) {
+      super(query);
+      this.vs30 = vs30;
     }
   }
 
@@ -246,14 +285,16 @@ public final class HazardService {
   private static final String TOTAL_KEY = "Total";
 
   private static final class ResultBuilder {
+
     UrlHelper urlHelper;
-    Timer timer;
+    Stopwatch timer;
     RequestData request;
 
     Map<Imt, Map<SourceType, MutableXySequence>> componentMaps;
     Map<Imt, MutableXySequence> totalMap;
 
     ResultBuilder hazard(Hazard hazardResult) {
+      // TODO necessary??
       checkState(totalMap == null, "Hazard has already been added to this builder");
 
       componentMaps = new EnumMap<>(Imt.class);
@@ -262,10 +303,11 @@ public final class HazardService {
       var typeTotalMaps = curvesBySource(hazardResult);
 
       for (var imt : hazardResult.curves().keySet()) {
-        // total curve
+
+        /* Total curve for IMT. */
         XySequence.addToMap(imt, totalMap, hazardResult.curves().get(imt));
 
-        // component curves
+        /* Source component curves for IMT. */
         var typeTotalMap = typeTotalMaps.get(imt);
         var componentMap = componentMaps.get(imt);
 
@@ -287,7 +329,7 @@ public final class HazardService {
       return this;
     }
 
-    ResultBuilder timer(Timer timer) {
+    ResultBuilder timer(Stopwatch timer) {
       this.timer = timer;
       return this;
     }
@@ -301,7 +343,7 @@ public final class HazardService {
       var hazards = new ArrayList<HazardResponse>();
 
       for (Imt imt : totalMap.keySet()) {
-        var responseData = new ResponseMetadata(request, imt);
+        var responseData = new ResponseMetadata(imt);
         var curves = new ArrayList<Curve>();
 
         // total curve
@@ -322,4 +364,26 @@ public final class HazardService {
       return new Response<>(Status.SUCCESS, NAME, request, response, urlHelper);
     }
   }
+
+  @Deprecated
+  public static class Query extends ServiceQueryData {
+    Integer vs30;
+
+    public Query(Double longitude, Double latitude, Integer vs30) {
+      super(longitude, latitude);
+      this.vs30 = vs30;
+    }
+
+    @Override
+    public boolean isNull() {
+      return super.isNull() && vs30 == null;
+    }
+
+    @Override
+    public void checkValues() {
+      super.checkValues();
+      WsUtils.checkValue(ServicesUtil.Key.VS30, vs30);
+    }
+  }
+
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
index 0fcd21daa..071f31da5 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
@@ -6,6 +6,7 @@ import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.util.concurrent.ListenableFuture;
 
 import gov.usgs.earthquake.nshmp.Maths;
@@ -25,7 +26,6 @@ import gov.usgs.earthquake.nshmp.www.meta.Metadata.DefaultParameters;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceRequestData;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 
 import io.micronaut.http.HttpResponse;
 
@@ -87,7 +87,7 @@ public final class RateService {
 
       query.checkValues();
       var requestData = new RequestData(query);
-      var response = processRequest(service, requestData, urlHelper, timer);
+      var response = processRequest(service, requestData, urlHelper);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -104,8 +104,8 @@ public final class RateService {
   static Response<RequestData, ResponseData> processRequest(
       Service service,
       RequestData data,
-      UrlHelper urlHelper,
-      Timer timer) throws InterruptedException, ExecutionException {
+      UrlHelper urlHelper) throws InterruptedException, ExecutionException {
+    var timer = Stopwatch.createStarted();
     var rates = calc(service, data);
     var responseData = new ResponseData(new ResponseMetadata(service, data), rates, timer);
     return new Response<>(Status.SUCCESS, service.name, data, responseData, urlHelper);
@@ -259,7 +259,7 @@ public final class RateService {
     final ResponseMetadata metadata;
     final List<Sequence> data;
 
-    ResponseData(ResponseMetadata metadata, EqRate rates, Timer timer) {
+    ResponseData(ResponseMetadata metadata, EqRate rates, Stopwatch timer) {
       server = Metadata.serverData(ServletUtil.THREAD_COUNT, timer);
       this.metadata = metadata;
       this.data = buildSequence(rates);
@@ -319,7 +319,7 @@ public final class RateService {
     private Usage(Service service, DefaultParameters parameters) {
       description = service.description;
       this.syntax = service.syntax;
-      server = Metadata.serverData(1, ServletUtil.timer());
+      server = Metadata.serverData(1, Stopwatch.createStarted());
       this.parameters = parameters;
     }
   }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
index 3cf5b3470..7efcfbc98 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
@@ -17,7 +17,6 @@ import gov.usgs.earthquake.nshmp.internal.www.Response;
 import gov.usgs.earthquake.nshmp.internal.www.WsUtils;
 import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
-import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
 import io.micronaut.http.HttpResponse;
 
@@ -59,7 +58,9 @@ class ServicesUtil {
     return Hazard.merge(hazards);
   }
 
+  @Deprecated
   static class ServiceQueryData implements ServiceQuery {
+
     public final Double longitude;
     public final Double latitude;
 
@@ -80,13 +81,13 @@ class ServicesUtil {
     }
   }
 
+  @Deprecated
   static class ServiceRequestData {
-    public final SourceModel model;
+
     public final double longitude;
     public final double latitude;
 
     public ServiceRequestData(ServiceQueryData query) {
-      model = new SourceModel(ServletUtil.model());
       longitude = query.longitude;
       latitude = query.latitude;
     }
@@ -118,6 +119,7 @@ class ServicesUtil {
     }
   }
 
+  @Deprecated
   private static interface ServiceQuery {
     boolean isNull();
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
index ba4284d1c..ca4483047 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
@@ -162,6 +162,7 @@ public class ServletUtil {
    * Simple timer object. The servlet timer just runs. The calculation timer can
    * be started later.
    */
+  @Deprecated
   public static final class Timer {
     Stopwatch servlet = Stopwatch.createStarted();
     Stopwatch calc = Stopwatch.createUnstarted();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
index cc74be880..4773a3c80 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
@@ -3,6 +3,7 @@ package gov.usgs.earthquake.nshmp.www.services;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.base.Stopwatch;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 
@@ -66,7 +67,7 @@ public class SourceServices {
 
     public ResponseData() {
       this.description = "Installed source model listing";
-      this.server = Metadata.serverData(ServletUtil.THREAD_COUNT, ServletUtil.timer());
+      this.server = Metadata.serverData(ServletUtil.THREAD_COUNT, Stopwatch.createStarted());
       // this.parameters = new Parameters();
     }
   }
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java
index 6864f0aec..25f4935f5 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java
@@ -44,7 +44,6 @@ package gov.usgs.earthquake.nshmp;
  * @see NshmTestsSmall
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public class NshmTestsLarge {
 
   // private static final List<String> COUS_REGION_IDS = ImmutableList.of("wus",
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java
index 26dcf4527..c85c84aa3 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java
@@ -27,7 +27,6 @@ package gov.usgs.earthquake.nshmp;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public class NshmTestsSmall {
 
   // /*
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java b/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java
index 46274746a..8ffeefca0 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java
@@ -3,7 +3,6 @@ package gov.usgs.earthquake.nshmp.programs;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-@SuppressWarnings("javadoc")
 public class HazardCurveTest {
 
   @BeforeEach
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java b/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java
index 866975eec..d6da4edd2 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java
@@ -59,7 +59,6 @@ import gov.usgs.earthquake.nshmp.geo.Location;
 import gov.usgs.earthquake.nshmp.internal.UsRegion;
 import gov.usgs.earthquake.nshmp.site.NshmpSite.StateComparator;
 
-@SuppressWarnings("javadoc")
 public class NshmpSiteTests {
 
   @Test
-- 
GitLab