diff --git a/Dockerfile b/Dockerfile index 28b1b617..2cc9c042 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ COPY commons /code/commons COPY specifications /code/specifications COPY restapi /code/restapi COPY java-sdk/gradle /code/java-sdk/gradle -COPY java-sdk/gradle.properties java-sdk/build.gradle java-sdk/settings.gradle java-sdk/gradlew /code/java-sdk/ +COPY java-sdk/build.gradle java-sdk/settings.gradle java-sdk/gradlew /code/java-sdk/ RUN ./gradlew tasks COPY java-sdk/radar-schemas-commons/build.gradle /code/java-sdk/radar-schemas-commons/ COPY java-sdk/radar-schemas-commons/src /code/java-sdk/radar-schemas-commons/src diff --git a/README.md b/README.md index c5695c5d..93c8d0ec 100644 --- a/README.md +++ b/README.md @@ -58,4 +58,7 @@ docker-compose run --rm tools radar-schemas-tools list docker-compose run --rm tools radar-schemas-tools register http://schema-registry:8081 # create topics with zookeeper docker-compose run --rm tools radar-schemas-tools create zookeeper-1:2181 +# run source-catalogue webservice +docker-compose run --rm tools radar-schemas-tools serve -p + ``` diff --git a/java-sdk/build.gradle b/java-sdk/build.gradle index e046df8c..ff6a6fe2 100644 --- a/java-sdk/build.gradle +++ b/java-sdk/build.gradle @@ -17,7 +17,7 @@ subprojects { apply plugin: 'idea' // Configuration - version = '0.2' + version = '0.2.1' group = 'org.radarcns' ext.githubRepoName = 'RADAR-CNS/RADAR-Schemas' diff --git a/java-sdk/radar-schemas-tools/build.gradle b/java-sdk/radar-schemas-tools/build.gradle index a66cb54b..24adc95c 100644 --- a/java-sdk/radar-schemas-tools/build.gradle +++ b/java-sdk/radar-schemas-tools/build.gradle @@ -21,7 +21,8 @@ sourceSets { ext.junitVersion = '4.12' ext.slf4jVersion = '1.7.25' - +ext.jettyVersion = '9.4.7.v20170914' +ext.jerseyVersion = '2.9' dependencies { api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.8.10' api group: 'javax.validation', name: 'validation-api', version: '2.0.0.Final' @@ -32,6 +33,11 @@ dependencies { implementation (group: 'org.apache.kafka', name: 'kafka_2.11', version: '0.11.0.1') { exclude group: 'org.slf4j', module: 'slf4j-log4j12' } + implementation group: 'org.eclipse.jetty', name: 'jetty-server', version: jettyVersion + implementation group: 'org.eclipse.jetty', name: 'jetty-servlet', version: jettyVersion + implementation group: 'org.glassfish.jersey.core', name: 'jersey-server', version: jerseyVersion + implementation group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet-core', version: jerseyVersion + implementation group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: jerseyVersion runtimeOnly group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.25' diff --git a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/CommandLineApp.java b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/CommandLineApp.java index da511824..c9d16aeb 100644 --- a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/CommandLineApp.java +++ b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/CommandLineApp.java @@ -24,6 +24,7 @@ import net.sourceforge.argparse4j.inf.Subparsers; import org.radarcns.schema.registration.KafkaTopics; import org.radarcns.schema.registration.SchemaRegistry; +import org.radarcns.schema.service.SourceCatalogueServer; import org.radarcns.schema.specification.DataProducer; import org.radarcns.schema.specification.DataTopic; import org.radarcns.schema.specification.SourceCatalogue; @@ -53,6 +54,7 @@ */ @SuppressWarnings("PMD.SystemPrintln") public class CommandLineApp { + private static final Logger logger = LoggerFactory.getLogger(CommandLineApp.class); private final SourceCatalogue catalogue; @@ -166,7 +168,8 @@ public static void main(String... args) { KafkaTopics.command(), SchemaRegistry.command(), listCommand(), - SchemaValidator.command()); + SchemaValidator.command(), + SourceCatalogueServer.command()); ArgumentParser parser = getArgumentParser(subCommands); diff --git a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/service/SourceCatalogueServer.java b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/service/SourceCatalogueServer.java new file mode 100644 index 00000000..4e836c25 --- /dev/null +++ b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/service/SourceCatalogueServer.java @@ -0,0 +1,89 @@ +package org.radarcns.schema.service; + +import java.io.Closeable; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.Namespace; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.servlet.ServletContainer; +import org.radarcns.schema.CommandLineApp; +import org.radarcns.schema.specification.SourceCatalogue; +import org.radarcns.schema.util.SubCommand; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This server provides a webservice to share the SourceType Catalogues provided in *.yml files as + * {@link org.radarcns.schema.service.SourceCatalogueService.SourceTypeResponse} + */ +public class SourceCatalogueServer implements Closeable { + + private static final Logger logger = LoggerFactory.getLogger(SourceCatalogueServer.class); + + private final Server server; + + public SourceCatalogueServer(int serverPort) { + this.server = new Server(serverPort); + } + + @Override + public void close() { + try { + this.server.join(); + } catch (InterruptedException e) { + logger.error("Cannot stop server", e); + } + server.destroy(); + } + + @SuppressWarnings("PMD.SignatureDeclareThrowsException") + private void start(SourceCatalogue sourceCatalogue) throws Exception { + + ResourceConfig config = new ResourceConfig(); + config.register(new SourceCatalogueService(sourceCatalogue)); + ServletHolder servlet = new ServletHolder(new ServletContainer(config)); + ServletContextHandler context = new ServletContextHandler(server, "/*"); + context.addServlet(servlet, "/*"); + server.start(); + } + + public static SubCommand command() { + return new SourceCatalogueServiceCommand(); + } + + private static class SourceCatalogueServiceCommand implements SubCommand { + + @Override + public String getName() { + return "serve"; + } + + @Override + public int execute(Namespace options, CommandLineApp app) { + int partitions = options.getInt("port"); + SourceCatalogueServer service = new SourceCatalogueServer(partitions); + try { + service.start(app.getCatalogue()); + } catch (Exception e) { + logger.error("Cannot start server ", e); + return 1; + } + service.close(); + return 0; + } + + @Override + public void addParser(ArgumentParser parser) { + parser.description("A web service to share source-type catalogs"); + parser.addArgument("-p" ,"--port") + .help("Port number of the SourceCatalogue Server ") + .type(Integer.class) + .setDefault(9010); + SubCommand.addRootArgument(parser); + } + } + + +} diff --git a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/service/SourceCatalogueService.java b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/service/SourceCatalogueService.java new file mode 100644 index 00000000..3fccb14d --- /dev/null +++ b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/service/SourceCatalogueService.java @@ -0,0 +1,116 @@ +package org.radarcns.schema.service; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.radarcns.schema.specification.SourceCatalogue; +import org.radarcns.schema.specification.active.ActiveSource; +import org.radarcns.schema.specification.monitor.MonitorSource; +import org.radarcns.schema.specification.passive.PassiveSource; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.List; + +/** + * Webservice resource to share SourceCatalogues. The response has a "Source-Type-Class" header that + * mentions the class of SourceCatalogues and the body has the SourceCatalogues in JSON format. + */ +@Path("/source-types") +@Produces(MediaType.APPLICATION_JSON) +public class SourceCatalogueService { + + private static final String SOURCE_TYPE_CLASS_HEADER = "Source-Type-Class"; + private final SourceCatalogue sourceCatalogue; + + SourceCatalogueService(SourceCatalogue sourceCatalogue) { + this.sourceCatalogue = sourceCatalogue; + } + + @GET + @Path("/passive") + public Response getPassiveSources() { + return Response.ok().entity(new SourceTypeResponse(this.sourceCatalogue).passive()) + .header(SOURCE_TYPE_CLASS_HEADER, "PASSIVE").build(); + } + + @GET + @Path("/active") + public Response getActiveSources() { + return Response.ok().entity(new SourceTypeResponse(this.sourceCatalogue).active()) + .header(SOURCE_TYPE_CLASS_HEADER, "ACTIVE").build(); + } + + @GET + @Path("/monitor") + public Response getMonitorSources() { + return Response.ok().entity(new SourceTypeResponse(this.sourceCatalogue).monitor()) + .header(SOURCE_TYPE_CLASS_HEADER, "MONITOR").build(); + } + + @GET + public Response getAllSourceTypes() { + return Response.ok().entity(new SourceTypeResponse(this.sourceCatalogue).all()) + .header(SOURCE_TYPE_CLASS_HEADER, "ALL").build(); + } + + public class SourceTypeResponse { + + @JsonIgnore + private final SourceCatalogue sourceCatalogue; + + @JsonProperty("passive-source-types") + private List passiveSources; + + @JsonProperty("active-source-types") + private List activeSources; + + @JsonProperty("monitor-source-types") + private List monitorSources; + + private SourceTypeResponse(SourceCatalogue sourceCatalogue) { + this.sourceCatalogue = sourceCatalogue; + } + + private SourceTypeResponse passive() { + this.passiveSources = new ArrayList<>( + this.sourceCatalogue.getPassiveSources().values()); + return this; + } + + public SourceTypeResponse active() { + this.activeSources = new ArrayList<>(this.sourceCatalogue.getActiveSources().values()); + return this; + } + + public SourceTypeResponse monitor() { + this.monitorSources = new ArrayList<>( + this.sourceCatalogue.getMonitorSources().values()); + return this; + } + + private SourceTypeResponse all() { + this.passiveSources = new ArrayList<>( + this.sourceCatalogue.getPassiveSources().values()); + this.activeSources = new ArrayList<>(this.sourceCatalogue.getActiveSources().values()); + this.monitorSources = new ArrayList<>( + this.sourceCatalogue.getMonitorSources().values()); + return this; + } + + public List getPassiveSources() { + return passiveSources; + } + + public List getActiveSources() { + return activeSources; + } + + public List getMonitorSources() { + return monitorSources; + } + } +} diff --git a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/AppSource.java b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/AppSource.java index fc76f6fb..b13e589b 100644 --- a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/AppSource.java +++ b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/AppSource.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; +import java.util.Objects; import static org.radarcns.schema.util.Utils.expandClass; @@ -9,6 +10,15 @@ public abstract class AppSource extends DataProducer { @JsonProperty("app_provider") private String appProvider; + @JsonProperty + private String vendor; + + @JsonProperty + private String model; + + @JsonProperty + private String version; + @JsonSetter @SuppressWarnings("PMD.UnusedPrivateMethod") private void setAppProvider(String provider) { @@ -18,4 +28,37 @@ private void setAppProvider(String provider) { public String getAppProvider() { return appProvider; } + + public String getVersion() { + return version; + } + + public String getVendor() { + return vendor; + } + + public String getModel() { + return model; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AppSource provider = (AppSource) o; + return Objects.equals(appProvider, provider.appProvider) + && Objects.equals(version, provider.version) + && Objects.equals(model, provider.model) + && Objects.equals(vendor, provider.vendor) + && Objects.equals(getData(), provider.getData()); + } + + @Override + public int hashCode() { + return Objects.hash(appProvider, vendor, model, version, getData()); + } } diff --git a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/DataProducer.java b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/DataProducer.java index 36af741e..2484de24 100644 --- a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/DataProducer.java +++ b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/DataProducer.java @@ -56,6 +56,7 @@ public Stream getTopicNames() { return getData().stream().flatMap(applyOrEmpty(DataTopic::getTopics)); } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/active/ActiveSource.java b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/active/ActiveSource.java index 9cbd53c8..44a46809 100644 --- a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/active/ActiveSource.java +++ b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/active/ActiveSource.java @@ -47,6 +47,15 @@ public enum RadarSourceTypes { @JsonProperty private List data; + @JsonProperty + private String vendor; + + @JsonProperty + private String model; + + @JsonProperty + private String version; + public String getAssessmentType() { return assessmentType; } @@ -60,4 +69,16 @@ public List getData() { public Scope getScope() { return Scope.ACTIVE; } + + public String getVendor() { + return vendor; + } + + public String getModel() { + return model; + } + + public String getVersion() { + return version; + } } diff --git a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/passive/PassiveSource.java b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/passive/PassiveSource.java index d1119740..07ecdb53 100644 --- a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/passive/PassiveSource.java +++ b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/specification/passive/PassiveSource.java @@ -20,7 +20,6 @@ import org.radarcns.schema.Scope; import org.radarcns.schema.specification.AppSource; -import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; @@ -33,12 +32,6 @@ public enum RadarSourceTypes { EMPATICA_E4, PEBBLE_2, ANDROID_PHONE, BIOVOTION_VSM1 } - @JsonProperty @NotBlank - private String vendor; - - @JsonProperty @NotBlank - private String model; - @JsonProperty @NotEmpty private List data; @@ -53,15 +46,7 @@ public Scope getScope() { } public String getName() { - return vendor + '_' + model; - } - - public String getVendor() { - return vendor; - } - - public String getModel() { - return model; + return super.getVendor() + '_' + super.getModel(); } /** diff --git a/specifications/active/phq8.yml b/specifications/active/phq8.yml index 5a0126d3..21a2c6e4 100644 --- a/specifications/active/phq8.yml +++ b/specifications/active/phq8.yml @@ -1,5 +1,8 @@ #==================== Personal Health Questionnaire Depression Scale (PHQ-8) ======================# name: PHQ8 +vendor: PHQ +model: 8 +version: 1.0.0 assessment_type: QUESTIONNAIRE doc: Personal Health Questionnaire Depression Scale (PHQ-8) definition. data: @@ -102,4 +105,4 @@ data: - text: More than half the days value: 2 - text: Nearly every day - value: 3 \ No newline at end of file + value: 3 diff --git a/specifications/active/thincit.yml b/specifications/active/thincit.yml index 503af4d9..052464e8 100644 --- a/specifications/active/thincit.yml +++ b/specifications/active/thincit.yml @@ -1,4 +1,7 @@ name: THINCIT +vendor: THINCIT IIRC +model: THINCIT +version: 1.0.0 assessment_type: APP doc: ThincIt Cognition in Depression app. data: diff --git a/specifications/monitor/radar_prmt.yml b/specifications/monitor/radar_prmt.yml index e5d454ed..89b9bc66 100644 --- a/specifications/monitor/radar_prmt.yml +++ b/specifications/monitor/radar_prmt.yml @@ -1,4 +1,7 @@ name: ANDROID_PHONE +vendor: ANDROID +model: PHONE_MONITOR +version: 1.0.0 doc: Status updates from the RADAR-CNS pRMT app. app_provider: .application.ApplicationServiceProvider data: diff --git a/specifications/passive/android_phone.yml b/specifications/passive/android_phone.yml index ebe57d5d..f5226e5d 100644 --- a/specifications/passive/android_phone.yml +++ b/specifications/passive/android_phone.yml @@ -1,6 +1,7 @@ #====================================== Android Phone Sensors =====================================# vendor: ANDROID model: PHONE +version: 1.0.0 data: #Phone sensors - type: ACCELEROMETER diff --git a/specifications/passive/biovotion_vsm1.yml b/specifications/passive/biovotion_vsm1.yml index 4e3b51c7..f245e1b6 100644 --- a/specifications/passive/biovotion_vsm1.yml +++ b/specifications/passive/biovotion_vsm1.yml @@ -1,6 +1,7 @@ #===================================== Biovotion VSM1 Everion =====================================# vendor: BIOVOTION model: VSM1 +version: 1.0.0 app_provider: .biovotion.BiovotionServiceProvider data: - type: ACCELEROMETER @@ -86,4 +87,4 @@ data: unit: CELSIUS processing_state: RAW topic: android_biovotion_vsm1_temperature - value_schema: .passive.biovotion.BiovotionVsm1Temperature \ No newline at end of file + value_schema: .passive.biovotion.BiovotionVsm1Temperature diff --git a/specifications/passive/empatica_e4.yml b/specifications/passive/empatica_e4.yml index 01ea00e2..786726aa 100644 --- a/specifications/passive/empatica_e4.yml +++ b/specifications/passive/empatica_e4.yml @@ -1,6 +1,7 @@ #====================================== Empatica E4 Wristband =====================================# vendor: EMPATICA model: E4 +version: 1.0.0 app_provider: .empatica.E4ServiceProvider data: - type: ACCELEROMETER diff --git a/specifications/passive/pebble_2.yml b/specifications/passive/pebble_2.yml index b66fedd8..44f0c70c 100644 --- a/specifications/passive/pebble_2.yml +++ b/specifications/passive/pebble_2.yml @@ -1,6 +1,7 @@ #============================================ Pebble 2 ============================================# vendor: PEBBLE model: 2 +version: 1.0.0 doc: Pebble 2 data collected over Bluetooth by a RADAR Pebble app app_provider: .pebble.PebbleServiceProvider data: