diff --git a/build.gradle b/build.gradle index 11a5bd2e..180413eb 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ targetCompatibility = '1.8' sourceCompatibility = '1.8' ext.grizzly = '2.4.3' -ext.jersey = '2.26' +ext.jersey = '2.27' ext.junitVersion = '4.12' ext.hamcrestVersion = '1.3' ext.logback = '1.2.2' diff --git a/src/endToEndTest/java/org/radarcns/EndToEndTest.java b/src/endToEndTest/java/org/radarcns/EndToEndTest.java index d09e40f4..68cf7775 100644 --- a/src/endToEndTest/java/org/radarcns/EndToEndTest.java +++ b/src/endToEndTest/java/org/radarcns/EndToEndTest.java @@ -53,8 +53,8 @@ import org.radarcns.domain.restapi.dataset.Dataset; import org.radarcns.domain.restapi.format.Acceleration; import org.radarcns.domain.restapi.format.Quartiles; +import org.radarcns.domain.restapi.header.DataSetHeader; import org.radarcns.domain.restapi.header.DescriptiveStatistic; -import org.radarcns.domain.restapi.header.Header; import org.radarcns.integration.util.ApiClient; import org.radarcns.integration.util.ExpectedDataSetFactory; import org.radarcns.integration.util.Utility; @@ -258,10 +258,10 @@ private static Map getReceivedMessage( Dataset dataset = Utility.cloneDataset(expectedCount.get(config)); - Header updatedHeader = dataset.getHeader(); - updatedHeader.setDescriptiveStatistic(DescriptiveStatistic.RECEIVED_MESSAGES); - updatedHeader.setUnit("PERCENTAGE"); - dataset.setHeader(updatedHeader); + DataSetHeader updatedHeader = (DataSetHeader) dataset.getHeader() + .descriptiveStatistic(DescriptiveStatistic.RECEIVED_MESSAGES) + .unit("PERCENTAGE"); + dataset.header(updatedHeader); for (DataItem item : dataset.getDataset()) { if (item.getValue() instanceof Double) { diff --git a/src/integrationTest/java/org/radarcns/integration/util/ExpectedDataSetFactory.java b/src/integrationTest/java/org/radarcns/integration/util/ExpectedDataSetFactory.java index 32c3c2d1..860c2dd5 100644 --- a/src/integrationTest/java/org/radarcns/integration/util/ExpectedDataSetFactory.java +++ b/src/integrationTest/java/org/radarcns/integration/util/ExpectedDataSetFactory.java @@ -27,6 +27,7 @@ import org.radarcns.domain.restapi.dataset.Dataset; import org.radarcns.domain.restapi.format.Acceleration; import org.radarcns.domain.restapi.format.Quartiles; +import org.radarcns.domain.restapi.header.DataSetHeader; import org.radarcns.domain.restapi.header.DescriptiveStatistic; import org.radarcns.domain.restapi.header.Header; import org.radarcns.domain.restapi.header.TimeFrame; @@ -57,8 +58,8 @@ public Dataset getDataset(ExpectedValue expectedValue, String projectName, Strin String sourceId, String sourceType, String sensorType, DescriptiveStatistic statistic, TimeWindow timeWindow) { - Header header = getHeader(expectedValue, projectName, subjectId, sourceId, sourceType, - sensorType, statistic, timeWindow); + DataSetHeader header = getHeader(expectedValue, projectName, subjectId, sourceId, + sourceType, sensorType, statistic, timeWindow); return new Dataset(header, getItem(expectedValue, header)); } @@ -75,11 +76,11 @@ public Dataset getDataset(ExpectedValue expectedValue, String projectName, Strin * @param timeWindow time interval between two consecutive samples * @return {@link Header} for a {@link Dataset} */ - public Header getHeader(ExpectedValue expectedValue, String projectName, String subjectId, - String sourceId, String sourceType, String sensorType, DescriptiveStatistic statistic, - TimeWindow timeWindow) { - return new Header(projectName, subjectId, sourceId, sourceType, sensorType, statistic, - null, timeWindow, null, + public DataSetHeader getHeader(ExpectedValue expectedValue, String projectName, + String subjectId, String sourceId, String sourceType, String sensorType, + DescriptiveStatistic statistic, TimeWindow timeWindow) { + return new DataSetHeader(projectName, subjectId, sourceId, sourceType, sensorType, + statistic, null, timeWindow, null, getEffectiveTimeFrame(expectedValue, timeWindow)); } @@ -108,7 +109,7 @@ public TimeFrame getEffectiveTimeFrame(ExpectedValue expectedValue, TimeWindo * @return {@code List} for a {@link Dataset} * @see DataItem **/ - public List getItem(ExpectedValue expectedValue, Header header) { + public List getItem(ExpectedValue expectedValue, DataSetHeader header) { if (expectedValue.getSeries().isEmpty()) { return Collections.emptyList(); diff --git a/src/integrationTest/java/org/radarcns/integration/util/RandomInput.java b/src/integrationTest/java/org/radarcns/integration/util/RandomInput.java index b5781ec3..c9ab9612 100644 --- a/src/integrationTest/java/org/radarcns/integration/util/RandomInput.java +++ b/src/integrationTest/java/org/radarcns/integration/util/RandomInput.java @@ -17,9 +17,9 @@ package org.radarcns.integration.util; import static java.time.temporal.ChronoUnit.SECONDS; -import static org.radarcns.mongo.data.monitor.ApplicationStatusRecordCounter.RECORD_COLLECTION; -import static org.radarcns.mongo.data.monitor.ApplicationStatusServerStatus.STATUS_COLLECTION; -import static org.radarcns.mongo.data.monitor.ApplicationStatusUpTime.UPTIME_COLLECTION; +import static org.radarcns.mongo.data.monitor.application.ApplicationStatusRecordCounter.RECORD_COLLECTION; +import static org.radarcns.mongo.data.monitor.application.ApplicationStatusServerStatus.STATUS_COLLECTION; +import static org.radarcns.mongo.data.monitor.application.ApplicationStatusUpTime.UPTIME_COLLECTION; import static org.radarcns.mongo.util.MongoHelper.ID; import static org.radarcns.mongo.util.MongoHelper.KEY; import static org.radarcns.mongo.util.MongoHelper.PROJECT_ID; @@ -139,6 +139,28 @@ private static Map getBoth(ObservationKey key, return map; } + /** + * Generates and returns a randomly generated + * {@link org.radarcns.domain.restapi.monitor.QuestionnaireCompletionStatus} mock data + * sent by RADAR-CNS aRMT. + **/ + public static Document getRandomQuestionnaireCompletionLog(String project, + String user, String source) { + + ThreadLocalRandom random = ThreadLocalRandom.current(); + + double timestamp = random.nextDouble(); + double completionPercentage = random.nextDouble(0d,100d); + String name = "PHQ8"; + Document completionDoc = new Document() + .append("time", timestamp) + .append("name", name) + .append("completionPercentage", completionPercentage); + + return buildDocumentWithObservationKey(project, user, source, completionDoc); + + } + /** * Generates and returns a randomly generated {@code ApplicationStatus} mocking data sent by * RADAR-CNS pRMT. @@ -184,9 +206,12 @@ public static Map getRandomApplicationStatus(String project, S .append("recordsUnsent", recordsUnsent); Map documents = new HashMap<>(); - documents.put(STATUS_COLLECTION, buildAppStatusDocument(project, user, source, statusDoc)); - documents.put(RECORD_COLLECTION, buildAppStatusDocument(project, user, source, recordsDoc)); - documents.put(UPTIME_COLLECTION, buildAppStatusDocument(project, user, source, uptimeDoc)); + documents.put(STATUS_COLLECTION, + buildDocumentWithObservationKey(project, user, source, statusDoc)); + documents.put(RECORD_COLLECTION, + buildDocumentWithObservationKey(project, user, source, recordsDoc)); + documents.put(UPTIME_COLLECTION, + buildDocumentWithObservationKey(project, user, source, uptimeDoc)); return documents; } @@ -197,7 +222,7 @@ private static Document buildKeyDocument(String projectName, String subjectId, .append(SOURCE_ID, sourceId); } - private static Document buildAppStatusDocument(String projectName, String subjectId, + private static Document buildDocumentWithObservationKey(String projectName, String subjectId, String sourceId, Document value) { return new Document().append(ID, "{" diff --git a/src/integrationTest/java/org/radarcns/integration/util/Utility.java b/src/integrationTest/java/org/radarcns/integration/util/Utility.java index a5d96fdb..58a3cadb 100644 --- a/src/integrationTest/java/org/radarcns/integration/util/Utility.java +++ b/src/integrationTest/java/org/radarcns/integration/util/Utility.java @@ -16,34 +16,51 @@ package org.radarcns.integration.util; -import static org.radarcns.mongo.data.monitor.ApplicationStatusRecordCounter.RECORD_COLLECTION; -import static org.radarcns.mongo.data.monitor.ApplicationStatusServerStatus.STATUS_COLLECTION; -import static org.radarcns.mongo.data.monitor.ApplicationStatusUpTime.UPTIME_COLLECTION; +import static org.radarcns.mongo.data.monitor.application.ApplicationStatusRecordCounter.RECORD_COLLECTION; +import static org.radarcns.mongo.data.monitor.application.ApplicationStatusServerStatus.STATUS_COLLECTION; +import static org.radarcns.mongo.data.monitor.application.ApplicationStatusUpTime.UPTIME_COLLECTION; import static org.radarcns.mongo.util.MongoHelper.VALUE; import java.util.ArrayList; import java.util.List; import java.util.Map; + import org.bson.Document; -import org.radarcns.domain.restapi.Application; import org.radarcns.domain.restapi.dataset.DataItem; import org.radarcns.domain.restapi.dataset.Dataset; import org.radarcns.domain.restapi.format.Acceleration; -import org.radarcns.domain.restapi.header.Header; +import org.radarcns.domain.restapi.header.DataSetHeader; import org.radarcns.domain.restapi.header.TimeFrame; +import org.radarcns.domain.restapi.monitor.ApplicationStatus; +import org.radarcns.domain.restapi.monitor.QuestionnaireCompletionStatus; import org.radarcns.util.RadarConverter; public class Utility { /** - * Converts Bson Document into an ApplicationConfig. + * Converts Bson Document into an QuestionnaireCompletionStatus. * - * @param documents map containing variables to create the ApplicationConfig class + * @param document Document data to create the QuestionnaireCompletionStatus class * @return an ApplicationConfig class - * @see Application + * @see ApplicationStatus */ //TODO take field names from RADAR Mongo Connector - public static Application convertDocToApplication(Map documents) { - return new Application( + public static QuestionnaireCompletionStatus convertDocToQuestionnaireCompletionStatus(Document + document) { + return new QuestionnaireCompletionStatus( + ((Document)document.get(VALUE)).getDouble("time"), + ((Document)document.get(VALUE)).getString("name"), + ((Document)document.get(VALUE)).getDouble("completionPercentage")); + } + + /** + * Converts Bson Document into an ApplicationStatus. + * + * @param documents map containing variables to create the ApplicationStatus class + * @return an ApplicationStatus class + * @see ApplicationStatus + */ + public static ApplicationStatus convertDocToApplicationStatus(Map documents) { + return new ApplicationStatus( ((Document) documents.get(STATUS_COLLECTION).get(VALUE)).getString("clientIP"), ((Document) documents.get(UPTIME_COLLECTION).get(VALUE)).getDouble("uptime"), RadarConverter.getServerStatus( @@ -52,8 +69,8 @@ public static Application convertDocToApplication(Map document ((Document) documents.get(RECORD_COLLECTION).get(VALUE)) .getInteger("recordsCached"), ((Document) documents.get(RECORD_COLLECTION).get(VALUE)).getInteger("recordsSent"), - ((Document) documents.get(RECORD_COLLECTION).get(VALUE)).getInteger("recordsUnsent") - ); + ((Document) documents.get(RECORD_COLLECTION).get(VALUE)) + .getInteger("recordsUnsent")); } /** @@ -63,18 +80,18 @@ public static Application convertDocToApplication(Map document * @return {@link Dataset} cloned from {@code input} */ public static Dataset cloneDataset(Dataset input) { - Header inputHeader = input.getHeader(); - TimeFrame cloneEffectiveTimeFrame = new TimeFrame( - inputHeader.getEffectiveTimeFrame().getStartDateTime(), - inputHeader.getEffectiveTimeFrame().getEndDateTime()); - TimeFrame cloneTimeFrame = new TimeFrame( - inputHeader.getTimeFrame().getStartDateTime(), + DataSetHeader inputHeader = input.getHeader(); + TimeFrame cloneEffectiveTimeFrame = + new TimeFrame(inputHeader.getEffectiveTimeFrame().getStartDateTime(), + inputHeader.getEffectiveTimeFrame().getEndDateTime()); + TimeFrame cloneTimeFrame = new TimeFrame(inputHeader.getTimeFrame().getStartDateTime(), inputHeader.getTimeFrame().getEndDateTime()); - Header cloneHeader = new Header(inputHeader.getProjectId(), inputHeader.getSubjectId(), + DataSetHeader cloneHeader = new DataSetHeader(inputHeader.getProjectId(), + inputHeader.getSubjectId(), inputHeader.getSourceId(), inputHeader.getSourceType(), - inputHeader.getSourceDataType(), - inputHeader.getDescriptiveStatistic(), inputHeader.getUnit(), - inputHeader.getTimeWindow(), cloneTimeFrame, cloneEffectiveTimeFrame); + inputHeader.getSourceDataType(), inputHeader.getDescriptiveStatistic(), + inputHeader.getUnit(), inputHeader.getTimeWindow(), cloneTimeFrame, + cloneEffectiveTimeFrame); List cloneItem = new ArrayList<>(); Object value; @@ -86,8 +103,8 @@ public static Dataset cloneDataset(Dataset input) { Acceleration temp = (Acceleration) item.getValue(); value = new Acceleration(temp.getX(), temp.getY(), temp.getZ()); } else { - throw new IllegalArgumentException(item.getValue().getClass().getCanonicalName() - + " is not supported yet"); + throw new IllegalArgumentException( + item.getValue().getClass().getCanonicalName() + " is not supported yet"); } cloneItem.add(new DataItem(value, item.getStartDateTime())); diff --git a/src/integrationTest/java/org/radarcns/webapp/AppStatusEndPointTest.java b/src/integrationTest/java/org/radarcns/webapp/AppStatusEndPointTest.java index 10f4b04f..3223c9c5 100644 --- a/src/integrationTest/java/org/radarcns/webapp/AppStatusEndPointTest.java +++ b/src/integrationTest/java/org/radarcns/webapp/AppStatusEndPointTest.java @@ -17,20 +17,25 @@ package org.radarcns.webapp; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.radarcns.domain.restapi.header.MonitorHeader.MonitorCategory.PASSIVE; +import static org.radarcns.domain.restapi.header.MonitorHeader.MonitorCategory.QUESTIONNAIRE; +import static org.radarcns.mongo.data.monitor.questionnaire.QuestionnaireCompletionLogWrapper.QUESTIONNAIRE_COMPLETION_LOG_COLLECTION; import static org.radarcns.webapp.SampleDataHandler.PROJECT; -import static org.radarcns.webapp.SampleDataHandler.SOURCE; -import static org.radarcns.webapp.SampleDataHandler.SUBJECT; import static org.radarcns.webapp.resource.BasePath.APPLICATION_STATUS; import java.io.IOException; import java.util.Map; import javax.ws.rs.core.Response.Status; + import org.bson.Document; import org.junit.Rule; import org.junit.Test; -import org.radarcns.domain.restapi.Application; -import org.radarcns.domain.restapi.ServerStatus; +import org.radarcns.domain.restapi.header.MonitorHeader; +import org.radarcns.domain.restapi.monitor.ApplicationStatus; +import org.radarcns.domain.restapi.monitor.MonitorData; +import org.radarcns.domain.restapi.monitor.QuestionnaireCompletionStatus; import org.radarcns.integration.MongoRule; import org.radarcns.integration.util.ApiClient; import org.radarcns.integration.util.RandomInput; @@ -40,8 +45,6 @@ public class AppStatusEndPointTest { - private static final String SOURCE_PATH = - APPLICATION_STATUS + '/' + PROJECT + '/' + SUBJECT + '/' + SOURCE; @Rule public final ApiClient apiClient = new ApiClient( @@ -52,21 +55,67 @@ public class AppStatusEndPointTest { @Test public void getStatusTest200Unknown() throws IOException { - Application actual = apiClient.getJson(SOURCE_PATH, Application.class, Status.OK); - assertSame(ServerStatus.UNKNOWN, actual.getServerStatus()); + String sourceId = "c4064d12-b963-47ae-b560-067131e321ea"; + String subjectId = "sub-2"; + + MonitorHeader monitorHeader = new MonitorHeader(PROJECT, subjectId, sourceId, null); + assertRequestsMatch(subjectId, sourceId, monitorHeader); } @Test public void getStatusTest200() throws IOException { + String sourceId = "c4064d12-b963-47ae-b560-067131e321ea"; + String subjectId = "sub-2"; + Map map = RandomInput.getRandomApplicationStatus( - PROJECT, SUBJECT, SOURCE); + PROJECT, subjectId, sourceId); map.forEach((k, v) -> mongoRule.getCollection(k).insertOne(v)); - Application expected = Utility.convertDocToApplication(map); - Application actual = apiClient.getJson(SOURCE_PATH, Application.class, Status.OK); + ApplicationStatus expected = Utility.convertDocToApplicationStatus(map); + MonitorHeader monitorHeader = new MonitorHeader(PROJECT, subjectId, sourceId, PASSIVE); + MonitorData actual = assertRequestsMatch(subjectId, sourceId, monitorHeader); + + assertTrue(actual.getData() instanceof Map); + Map status = (Map) actual.getData(); + + assertEquals(expected.getServerStatus().toString(), status.get("serverStatus")); + } + + @Test + public void getQuestionnaireCompletionStatusTest200() throws IOException { + String sourceId = "0d29b9eb-289a-4dc6-b969-534dca72a187"; + String subjectId = "sub-3"; + + Document document = RandomInput.getRandomQuestionnaireCompletionLog( + PROJECT, subjectId, sourceId); + + mongoRule.getCollection(QUESTIONNAIRE_COMPLETION_LOG_COLLECTION).insertOne(document); + + QuestionnaireCompletionStatus expected = Utility + .convertDocToQuestionnaireCompletionStatus(document); + MonitorHeader monitorHeader = new MonitorHeader(PROJECT, subjectId, sourceId, + QUESTIONNAIRE); + MonitorData actual = assertRequestsMatch(subjectId, sourceId, monitorHeader); + + assertTrue(actual.getData() instanceof Map); + Map status = (Map) actual.getData(); + + assertEquals(expected.getCompletionPercentage(), status.get("completionPercentage")); + } + + private MonitorData assertRequestsMatch(String subjectId, String sourceId, MonitorHeader + expectedHeader) + throws IOException { + String relativeUrl = + APPLICATION_STATUS + '/' + PROJECT + '/' + subjectId + '/' + sourceId; - assertEquals(expected.getServerStatus(), actual.getServerStatus()); - assertEquals(expected.getIpAddress(), actual.getIpAddress()); + MonitorData actual = apiClient.getJson(relativeUrl, MonitorData.class, Status.OK); + assertNotNull(actual); + MonitorHeader actualHeader = actual.getHeader(); + assertEquals(expectedHeader.getProjectId(), actualHeader.getProjectId()); + assertEquals(expectedHeader.getSubjectId(), actualHeader.getSubjectId()); + assertEquals(expectedHeader.getSourceId(), actualHeader.getSourceId()); + return actual; } } diff --git a/src/integrationTest/resources/config/liquibase/source_type.csv b/src/integrationTest/resources/config/liquibase/source_type.csv new file mode 100644 index 00000000..11717887 --- /dev/null +++ b/src/integrationTest/resources/config/liquibase/source_type.csv @@ -0,0 +1,5 @@ +"ID";"PRODUCER";"MODEL";"catalog_version";"SOURCE_TYPE_SCOPE";"dynamic_registration";"created_by" +"1";"Empatica";"E4";"v1";"PASSIVE";"FALSE";"system" +"2";"THINC-IT App";"App";"v1";"ACTIVE";"true";"system" +"3";"RADAR";"pRMT";"1.0.0";"MONITOR";"false";"system" +"4";"RADAR";"aRMT-App";"1.2.0";"ACTIVE";"true";"system" diff --git a/src/integrationTest/resources/config/liquibase/sources.csv b/src/integrationTest/resources/config/liquibase/sources.csv new file mode 100644 index 00000000..0957ab67 --- /dev/null +++ b/src/integrationTest/resources/config/liquibase/sources.csv @@ -0,0 +1,4 @@ +"ID";"source_id";"source_name";"assigned";"created_by";"source_type_id";"project_id" +"1";"03d28e5c-e005-46d4-a9b3-279c27fbbc83";"source-1";"TRUE";"system";"1";"1" +"2";"c4064d12-b963-47ae-b560-067131e321ea";"source-2";"TRUE";"system";"3";"1" +"3";"0d29b9eb-289a-4dc6-b969-534dca72a187";"source-3";"TRUE";"system";"4";"1" \ No newline at end of file diff --git a/src/integrationTest/resources/config/liquibase/subject_sources.csv b/src/integrationTest/resources/config/liquibase/subject_sources.csv new file mode 100644 index 00000000..ad40944d --- /dev/null +++ b/src/integrationTest/resources/config/liquibase/subject_sources.csv @@ -0,0 +1,5 @@ +"SUBJECTS_ID";"SOURCES_ID" +"1";"1" +"2";"2" +"3";"3" + diff --git a/src/main/java/org/radarcns/domain/managementportal/ProjectDTO.java b/src/main/java/org/radarcns/domain/managementportal/ProjectDTO.java index dcaecbd9..45bab609 100644 --- a/src/main/java/org/radarcns/domain/managementportal/ProjectDTO.java +++ b/src/main/java/org/radarcns/domain/managementportal/ProjectDTO.java @@ -1,6 +1,5 @@ package org.radarcns.domain.managementportal; - import java.io.Serializable; import java.time.ZonedDateTime; import java.util.HashSet; diff --git a/src/main/java/org/radarcns/domain/managementportal/SourceDTO.java b/src/main/java/org/radarcns/domain/managementportal/SourceDTO.java index dfb22138..5e83d6ad 100644 --- a/src/main/java/org/radarcns/domain/managementportal/SourceDTO.java +++ b/src/main/java/org/radarcns/domain/managementportal/SourceDTO.java @@ -1,6 +1,5 @@ package org.radarcns.domain.managementportal; - import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; import java.util.Map; diff --git a/src/main/java/org/radarcns/domain/managementportal/SourceDataDTO.java b/src/main/java/org/radarcns/domain/managementportal/SourceDataDTO.java index 94c26082..93126040 100644 --- a/src/main/java/org/radarcns/domain/managementportal/SourceDataDTO.java +++ b/src/main/java/org/radarcns/domain/managementportal/SourceDataDTO.java @@ -1,6 +1,5 @@ package org.radarcns.domain.managementportal; - import java.io.Serializable; import java.util.Objects; import javax.validation.constraints.NotNull; diff --git a/src/main/java/org/radarcns/domain/managementportal/SourceTypeDTO.java b/src/main/java/org/radarcns/domain/managementportal/SourceTypeDTO.java index 76616806..0f87a25e 100644 --- a/src/main/java/org/radarcns/domain/managementportal/SourceTypeDTO.java +++ b/src/main/java/org/radarcns/domain/managementportal/SourceTypeDTO.java @@ -1,6 +1,5 @@ package org.radarcns.domain.managementportal; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import java.io.Serializable; diff --git a/src/main/java/org/radarcns/domain/restapi/dataset/Dataset.java b/src/main/java/org/radarcns/domain/restapi/dataset/Dataset.java index 8ef6b238..5493452d 100644 --- a/src/main/java/org/radarcns/domain/restapi/dataset/Dataset.java +++ b/src/main/java/org/radarcns/domain/restapi/dataset/Dataset.java @@ -3,12 +3,13 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; -import org.radarcns.domain.restapi.header.Header; + +import org.radarcns.domain.restapi.header.DataSetHeader; public class Dataset { @JsonProperty - public Header header; + public DataSetHeader header; @JsonProperty public List dataset; @@ -21,25 +22,27 @@ public class Dataset { */ @JsonCreator public Dataset( - @JsonProperty("header") Header header, + @JsonProperty("header") DataSetHeader header, @JsonProperty("dataset") List dataset) { this.header = header; this.dataset = dataset; } - public Header getHeader() { + public DataSetHeader getHeader() { return header; } - public void setHeader(Header header) { + public Dataset header(DataSetHeader header) { this.header = header; + return this; } public List getDataset() { return dataset; } - public void setDataset(List dataset) { + public Dataset setDataset(List dataset) { this.dataset = dataset; + return this; } } diff --git a/src/main/java/org/radarcns/domain/restapi/format/SourceData.java b/src/main/java/org/radarcns/domain/restapi/format/SourceData.java index af15b0c2..094adf6f 100644 --- a/src/main/java/org/radarcns/domain/restapi/format/SourceData.java +++ b/src/main/java/org/radarcns/domain/restapi/format/SourceData.java @@ -19,7 +19,7 @@ public SourceData(String name) { public SourceData(String name, String type) { this.name = name; - this.name = type; + this.type = type; } public String getName() { diff --git a/src/main/java/org/radarcns/domain/restapi/header/DataSetHeader.java b/src/main/java/org/radarcns/domain/restapi/header/DataSetHeader.java new file mode 100644 index 00000000..48133396 --- /dev/null +++ b/src/main/java/org/radarcns/domain/restapi/header/DataSetHeader.java @@ -0,0 +1,92 @@ +package org.radarcns.domain.restapi.header; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +import org.radarcns.domain.restapi.TimeWindow; + +public class DataSetHeader extends Header { + + /** + * Report the source data name or specific type of assessment. + */ + @JsonProperty + public String sourceDataType; + + /** + * Statical value expressed by samples. + */ + @JsonProperty + public DescriptiveStatistic descriptiveStatistic; + + /** + * Default constructor. + */ + public DataSetHeader() { + // default constructor + } + + /** + * All-args constructor. + * + * @param subjectId Subject identifier. + * @param sourceId Source identifier. + * @param sourceType Sourcetype information, it can be a device or assessment name. + * @param sourceDataType Source data information, it can be a device or assessment name. + * @param descriptiveStatistic Statical value expressed by samples. + * @param unit Unit used by the sourceType. + * @param timeWindow Time interval between two consecutive samples. + * @param timeFrame Timestamps of request. + * @param effectiveTimeFrame Timestamps of the first and the last samples in the data-set. + */ + @SuppressWarnings("PMD.ExcessiveParameterList") + public DataSetHeader(String projectId, String subjectId, String sourceId, String sourceType, + String sourceDataType, DescriptiveStatistic descriptiveStatistic, String unit, + TimeWindow timeWindow, TimeFrame timeFrame, TimeFrame effectiveTimeFrame) { + super(projectId, subjectId, sourceId, sourceType, unit, timeWindow, timeFrame, + effectiveTimeFrame); + this.sourceDataType = sourceDataType; + this.descriptiveStatistic = descriptiveStatistic; + } + + public String getSourceDataType() { + return sourceDataType; + } + + public DataSetHeader sourceDataType(String sourceDataType) { + this.sourceDataType = sourceDataType; + return this; + } + + public DescriptiveStatistic getDescriptiveStatistic() { + return descriptiveStatistic; + } + + public DataSetHeader descriptiveStatistic(DescriptiveStatistic descriptiveStatistic) { + this.descriptiveStatistic = descriptiveStatistic; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + DataSetHeader that = (DataSetHeader) o; + return Objects.equals(sourceDataType, that.sourceDataType) + && descriptiveStatistic == that.descriptiveStatistic; + } + + @Override + public int hashCode() { + + return Objects.hash(super.hashCode(), sourceDataType, descriptiveStatistic); + } +} diff --git a/src/main/java/org/radarcns/domain/restapi/header/Header.java b/src/main/java/org/radarcns/domain/restapi/header/Header.java index d609d658..74c2bd94 100644 --- a/src/main/java/org/radarcns/domain/restapi/header/Header.java +++ b/src/main/java/org/radarcns/domain/restapi/header/Header.java @@ -26,18 +26,6 @@ public class Header { */ @JsonProperty public String sourceType; - - /** - * Report the source data name or specific type of assessment. - */ - @JsonProperty - public String sourceDataType; - - /** - * Statical value expressed by samples. - */ - @JsonProperty - public DescriptiveStatistic descriptiveStatistic; /** * Unit used by the sourceType. */ @@ -69,110 +57,96 @@ public Header() { * @param subjectId Subject identifier. * @param sourceId Source identifier. * @param sourceType Sourcetype information, it can be a device or assessment name. - * @param sourceDataType Source data information, it can be a device or assessment name. - * @param descriptiveStatistic Statical value expressed by samples. * @param unit Unit used by the sourceType. * @param timeWindow Time interval between two consecutive samples. * @param timeFrame Timestamps of request. * @param effectiveTimeFrame Timestamps of the first and the last samples in the data-set. */ @SuppressWarnings("PMD.ExcessiveParameterList") - public Header(String projectId, String subjectId, String sourceId, String sourceType, String - sourceDataType, - DescriptiveStatistic descriptiveStatistic, String unit, TimeWindow timeWindow, - TimeFrame timeFrame, TimeFrame effectiveTimeFrame) { + public Header(String projectId, String subjectId, String sourceId, String sourceType, + String unit, TimeWindow timeWindow, TimeFrame timeFrame, + TimeFrame effectiveTimeFrame) { this.projectId = projectId; this.subjectId = subjectId; this.sourceId = sourceId; this.sourceType = sourceType; - this.sourceDataType = sourceDataType; - this.descriptiveStatistic = descriptiveStatistic; this.unit = unit; this.timeWindow = timeWindow; this.timeFrame = timeFrame; this.effectiveTimeFrame = effectiveTimeFrame; } + public String getProjectId() { + return projectId; + } + + public Header projectId(String projectId) { + this.projectId = projectId; + return this; + } + public String getSubjectId() { return subjectId; } - public void setSubjectId(String subjectId) { + public Header subjectId(String subjectId) { this.subjectId = subjectId; + return this; } public String getSourceId() { return sourceId; } - public void setSourceId(String sourceId) { + public Header sourceId(String sourceId) { this.sourceId = sourceId; - } - - public String getProjectId() { - return projectId; - } - - public void setProjectId(String projectId) { - this.projectId = projectId; + return this; } public String getSourceType() { return sourceType; } - public void setSourceType(String sourceType) { + public Header sourceType(String sourceType) { this.sourceType = sourceType; - } - - public String getSourceDataType() { - return sourceDataType; - } - - public void setSourceDataType(String sourceDataType) { - this.sourceDataType = sourceDataType; - } - - public DescriptiveStatistic getDescriptiveStatistic() { - return descriptiveStatistic; - } - - public void setDescriptiveStatistic( - DescriptiveStatistic descriptiveStatistic) { - this.descriptiveStatistic = descriptiveStatistic; + return this; } public String getUnit() { return unit; } - public void setUnit(String unit) { + public Header unit(String unit) { this.unit = unit; + return this; } public TimeWindow getTimeWindow() { return timeWindow; } - public void setTimeWindow(TimeWindow timeWindow) { + public Header timeWindow(TimeWindow timeWindow) { this.timeWindow = timeWindow; + return this; } public TimeFrame getEffectiveTimeFrame() { return effectiveTimeFrame; } - public void setEffectiveTimeFrame( + public Header effectiveTimeFrame( TimeFrame effectiveTimeFrame) { this.effectiveTimeFrame = effectiveTimeFrame; + return this; } public TimeFrame getTimeFrame() { return timeFrame; } - public void setTimeFrame(TimeFrame timeFrame) { + public Header timeFrame(TimeFrame timeFrame) { this.timeFrame = timeFrame; + return this; } @@ -184,23 +158,21 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - Header effectiveTimeFrame = (Header) o; + Header that = (Header) o; - return Objects.equals(subjectId, effectiveTimeFrame.subjectId) - && Objects.equals(projectId, effectiveTimeFrame.projectId) - && Objects.equals(sourceId, effectiveTimeFrame.sourceId) - && Objects.equals(sourceType, effectiveTimeFrame.sourceType) - && Objects.equals(sourceDataType, effectiveTimeFrame.sourceDataType) - && Objects.equals(descriptiveStatistic, effectiveTimeFrame.descriptiveStatistic) - && Objects.equals(unit, effectiveTimeFrame.unit) - && Objects.equals(timeWindow, effectiveTimeFrame.timeWindow) - && Objects.equals(timeFrame, effectiveTimeFrame.timeFrame) - && Objects.equals(effectiveTimeFrame, effectiveTimeFrame.effectiveTimeFrame); + return Objects.equals(subjectId, that.subjectId) + && Objects.equals(projectId, that.projectId) + && Objects.equals(sourceId, that.sourceId) + && Objects.equals(sourceType, that.sourceType) + && Objects.equals(unit, that.unit) + && Objects.equals(timeWindow, that.timeWindow) + && Objects.equals(timeFrame, that.timeFrame) + && Objects.equals(effectiveTimeFrame, that.effectiveTimeFrame); } @Override public int hashCode() { - return Objects.hash(subjectId, projectId, sourceId, sourceType, sourceDataType, - descriptiveStatistic, unit, timeWindow, timeFrame, effectiveTimeFrame); + return Objects.hash(subjectId, projectId, sourceId, sourceType, unit, timeWindow, timeFrame, + effectiveTimeFrame); } } diff --git a/src/main/java/org/radarcns/domain/restapi/header/MonitorHeader.java b/src/main/java/org/radarcns/domain/restapi/header/MonitorHeader.java new file mode 100644 index 00000000..9e549335 --- /dev/null +++ b/src/main/java/org/radarcns/domain/restapi/header/MonitorHeader.java @@ -0,0 +1,96 @@ +package org.radarcns.domain.restapi.header; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +import org.radarcns.domain.restapi.TimeWindow; + +public class MonitorHeader extends Header { + + public enum MonitorCategory { + PASSIVE, QUESTIONNAIRE + } + + @JsonProperty + private MonitorCategory monitorCategory; + + /** + * Default constructor. + */ + public MonitorHeader() { + + } + + /** + * Contains meta-data of the monitored source. + * @param projectId project name + * @param subjectId subject identifier. + * @param sourceId source identifier. + * @param monitorCategory monitor category. + */ + public MonitorHeader(String projectId, String subjectId, String sourceId, + MonitorCategory monitorCategory) { + super(projectId, subjectId, sourceId, null, null, null, null, null); + this.monitorCategory = monitorCategory; + } + + + /** + * Contains meta-data of the monitored source. + * @param projectId project name + * @param subjectId subject identifier. + * @param sourceId source identifier. + * @param sourceType source-type of source. + * @param unit unit of measurement + * @param timeWindow timewindow between records. + * @param timeFrame requested time frame. + * @param effectiveTimeFrame effective time frame. + * @param monitorCategory monitor category. + */ + public MonitorHeader(String projectId, String subjectId, String sourceId, String sourceType, + String unit, TimeWindow timeWindow, TimeFrame timeFrame, TimeFrame effectiveTimeFrame, + MonitorCategory monitorCategory) { + super(projectId, subjectId, sourceId, sourceType, unit, timeWindow, timeFrame, + effectiveTimeFrame); + this.monitorCategory = monitorCategory; + } + + + + public MonitorCategory getMonitorCategory() { + return monitorCategory; + } + + public MonitorHeader monitorCategory(MonitorCategory monitorCategory) { + this.monitorCategory = monitorCategory; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MonitorHeader that = (MonitorHeader) o; + return Objects.equals(projectId, that.projectId) && Objects + .equals(subjectId, that.subjectId) && Objects.equals(sourceId, that.sourceId) + && monitorCategory == that.monitorCategory; + } + + @Override + public int hashCode() { + + return Objects.hash(projectId, subjectId, sourceId, monitorCategory); + } + + @Override + public String toString() { + return "MonitorHeader{" + "projectId='" + projectId + '\'' + ", subjectId='" + subjectId + + '\'' + ", sourceId='" + sourceId + '\'' + ", monitorCategory=" + monitorCategory + + '}'; + } +} diff --git a/src/main/java/org/radarcns/domain/restapi/Application.java b/src/main/java/org/radarcns/domain/restapi/monitor/ApplicationStatus.java similarity index 79% rename from src/main/java/org/radarcns/domain/restapi/Application.java rename to src/main/java/org/radarcns/domain/restapi/monitor/ApplicationStatus.java index d3aa1b13..15112aed 100644 --- a/src/main/java/org/radarcns/domain/restapi/Application.java +++ b/src/main/java/org/radarcns/domain/restapi/monitor/ApplicationStatus.java @@ -1,9 +1,10 @@ -package org.radarcns.domain.restapi; +package org.radarcns.domain.restapi.monitor; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; +import org.radarcns.domain.restapi.ServerStatus; -public class Application { +public class ApplicationStatus { /** * Hardware identifier of client application. @@ -39,7 +40,7 @@ public class Application { /** * Default constructor. */ - public Application() { + public ApplicationStatus() { } /** @@ -52,7 +53,7 @@ public Application() { * @param recordsSent Number of records sent since application start. * @param recordsUnsent Number of unsent records. */ - public Application(java.lang.String ipAddress, java.lang.Double uptime, + public ApplicationStatus(java.lang.String ipAddress, java.lang.Double uptime, ServerStatus serverStatus, java.lang.Integer recordsCached, java.lang.Integer recordsSent, java.lang.Integer recordsUnsent) { @@ -120,14 +121,14 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - Application application = (Application) o; - - return Objects.equals(ipAddress, application.ipAddress) - && Objects.equals(uptime, application.uptime) - && Objects.equals(serverStatus, application.serverStatus) - && Objects.equals(recordsCached, application.recordsCached) - && Objects.equals(recordsSent, application.recordsSent) - && Objects.equals(recordsUnsent, application.recordsUnsent); + ApplicationStatus applicationStatus = (ApplicationStatus) o; + + return Objects.equals(ipAddress, applicationStatus.ipAddress) + && Objects.equals(uptime, applicationStatus.uptime) + && Objects.equals(serverStatus, applicationStatus.serverStatus) + && Objects.equals(recordsCached, applicationStatus.recordsCached) + && Objects.equals(recordsSent, applicationStatus.recordsSent) + && Objects.equals(recordsUnsent, applicationStatus.recordsUnsent); } @Override diff --git a/src/main/java/org/radarcns/domain/restapi/monitor/MonitorData.java b/src/main/java/org/radarcns/domain/restapi/monitor/MonitorData.java new file mode 100644 index 00000000..885df827 --- /dev/null +++ b/src/main/java/org/radarcns/domain/restapi/monitor/MonitorData.java @@ -0,0 +1,72 @@ +package org.radarcns.domain.restapi.monitor; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; +import org.radarcns.domain.restapi.header.MonitorHeader; + +public class MonitorData { + + @JsonProperty + private MonitorHeader header; + + @JsonProperty + private Object data; + + public MonitorData() { + + } + + public MonitorData(MonitorHeader monitorHeader, Object data) { + this.header = monitorHeader; + this.data = data; + } + + public MonitorHeader getHeader() { + return header; + } + + public void setHeader(MonitorHeader header) { + this.header = header; + } + + public Object getData() { + return data; + } + + public MonitorData header(MonitorHeader monitorHeader) { + this.header = monitorHeader; + return this; + } + + public void setData(Object data) { + this.data = data; + } + + public MonitorData data(Object data) { + this.data = data; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MonitorData that = (MonitorData) o; + return Objects.equals(header, that.header) && Objects.equals(data, that.data); + } + + @Override + public int hashCode() { + + return Objects.hash(header, data); + } + + @Override + public String toString() { + return "MonitorData{" + "header=" + header + ", data=" + data + '}'; + } +} diff --git a/src/main/java/org/radarcns/domain/restapi/monitor/QuestionnaireCompletionStatus.java b/src/main/java/org/radarcns/domain/restapi/monitor/QuestionnaireCompletionStatus.java new file mode 100644 index 00000000..923761cf --- /dev/null +++ b/src/main/java/org/radarcns/domain/restapi/monitor/QuestionnaireCompletionStatus.java @@ -0,0 +1,88 @@ +package org.radarcns.domain.restapi.monitor; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + + +public class QuestionnaireCompletionStatus { + + @JsonProperty + private Double timeRecorded; + + @JsonProperty + private String questionnaireName; + + @JsonProperty + private Double completionPercentage = 0d; + + /** + * Default constructor. + */ + public QuestionnaireCompletionStatus() { + // default constructor + } + + /** + * Constructor. + * @param timeRecorded recorded time of the status. + * @param questionnaireName name of the questionnaire. + * @param completionPercentage percentage of completion. + */ + public QuestionnaireCompletionStatus(Double timeRecorded, + String questionnaireName, Double completionPercentage) { + this.timeRecorded = timeRecorded; + this.questionnaireName = questionnaireName; + this.completionPercentage = completionPercentage; + } + + public Double getTimeRecorded() { + return timeRecorded; + } + + public void setTimeRecorded(Double timeRecorded) { + this.timeRecorded = timeRecorded; + } + + public String getQuestionnaireName() { + return questionnaireName; + } + + public void setQuestionnaireName(String questionnaireName) { + this.questionnaireName = questionnaireName; + } + + public Double getCompletionPercentage() { + return completionPercentage; + } + + public void setCompletionPercentage(Double completionPercentage) { + this.completionPercentage = completionPercentage; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + QuestionnaireCompletionStatus that = (QuestionnaireCompletionStatus) o; + return Objects.equals(timeRecorded, that.timeRecorded) && Objects + .equals(questionnaireName, that.questionnaireName) && Objects + .equals(completionPercentage, that.completionPercentage); + } + + @Override + public int hashCode() { + + return Objects.hash(timeRecorded, questionnaireName, completionPercentage); + } + + @Override + public String toString() { + return "QuestionnaireCompletionStatus{" + ", timeRecorded=" + + timeRecorded + ", questionnaireName='" + questionnaireName + '\'' + + ", completionPercentage=" + completionPercentage + '}'; + } +} diff --git a/src/main/java/org/radarcns/listener/managementportal/ManagementPortalClient.java b/src/main/java/org/radarcns/listener/managementportal/ManagementPortalClient.java index 927bbc88..d9e69c11 100644 --- a/src/main/java/org/radarcns/listener/managementportal/ManagementPortalClient.java +++ b/src/main/java/org/radarcns/listener/managementportal/ManagementPortalClient.java @@ -325,7 +325,8 @@ public List retrieveSourceData() throws IOException { } List allSourceData = SOURCE_DATA_LIST_READER.readValue(responseBody); logger.info("Retrieved {} SourceData from MP", allSourceData.size()); - return allSourceData.stream().map(DataFormat::getMongoSensor) + return allSourceData.stream() + .map(DataFormat::getMongoSensor) .collect(Collectors.toList()); } } diff --git a/src/main/java/org/radarcns/mongo/data/monitor/ApplicationStatusRecordCounter.java b/src/main/java/org/radarcns/mongo/data/monitor/application/ApplicationStatusRecordCounter.java similarity index 85% rename from src/main/java/org/radarcns/mongo/data/monitor/ApplicationStatusRecordCounter.java rename to src/main/java/org/radarcns/mongo/data/monitor/application/ApplicationStatusRecordCounter.java index f31420bb..dd71574c 100644 --- a/src/main/java/org/radarcns/mongo/data/monitor/ApplicationStatusRecordCounter.java +++ b/src/main/java/org/radarcns/mongo/data/monitor/application/ApplicationStatusRecordCounter.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package org.radarcns.mongo.data.monitor; +package org.radarcns.mongo.data.monitor.application; import org.bson.Document; -import org.radarcns.domain.restapi.Application; +import org.radarcns.domain.restapi.monitor.ApplicationStatus; public class ApplicationStatusRecordCounter extends MongoApplicationStatusWrapper { @@ -25,7 +25,7 @@ public class ApplicationStatusRecordCounter extends MongoApplicationStatusWrappe //TODO take field names from RADAR MongoDb Connector @Override - protected Application getApplication(Document doc, Application app) { + protected ApplicationStatus getApplication(Document doc, ApplicationStatus app) { app.setRecordsCached(doc.getInteger("recordsCached")); app.setRecordsSent(doc.getInteger("recordsSent")); app.setRecordsUnsent(doc.getInteger("recordsUnsent")); diff --git a/src/main/java/org/radarcns/mongo/data/monitor/ApplicationStatusServerStatus.java b/src/main/java/org/radarcns/mongo/data/monitor/application/ApplicationStatusServerStatus.java similarity index 85% rename from src/main/java/org/radarcns/mongo/data/monitor/ApplicationStatusServerStatus.java rename to src/main/java/org/radarcns/mongo/data/monitor/application/ApplicationStatusServerStatus.java index a162a41b..29a036e4 100644 --- a/src/main/java/org/radarcns/mongo/data/monitor/ApplicationStatusServerStatus.java +++ b/src/main/java/org/radarcns/mongo/data/monitor/application/ApplicationStatusServerStatus.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package org.radarcns.mongo.data.monitor; +package org.radarcns.mongo.data.monitor.application; import org.bson.Document; -import org.radarcns.domain.restapi.Application; +import org.radarcns.domain.restapi.monitor.ApplicationStatus; import org.radarcns.util.RadarConverter; public class ApplicationStatusServerStatus extends MongoApplicationStatusWrapper { @@ -26,7 +26,7 @@ public class ApplicationStatusServerStatus extends MongoApplicationStatusWrapper //TODO take field names from RADAR MongoDb Connector @Override - protected Application getApplication(Document doc, Application app) { + protected ApplicationStatus getApplication(Document doc, ApplicationStatus app) { app.setIpAddress(doc.getString("clientIP")); app.setServerStatus(RadarConverter.getServerStatus(doc.getString("serverStatus"))); diff --git a/src/main/java/org/radarcns/mongo/data/monitor/ApplicationStatusUpTime.java b/src/main/java/org/radarcns/mongo/data/monitor/application/ApplicationStatusUpTime.java similarity index 83% rename from src/main/java/org/radarcns/mongo/data/monitor/ApplicationStatusUpTime.java rename to src/main/java/org/radarcns/mongo/data/monitor/application/ApplicationStatusUpTime.java index 8ae57c10..006d96e0 100644 --- a/src/main/java/org/radarcns/mongo/data/monitor/ApplicationStatusUpTime.java +++ b/src/main/java/org/radarcns/mongo/data/monitor/application/ApplicationStatusUpTime.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package org.radarcns.mongo.data.monitor; +package org.radarcns.mongo.data.monitor.application; import org.bson.Document; -import org.radarcns.domain.restapi.Application; +import org.radarcns.domain.restapi.monitor.ApplicationStatus; public class ApplicationStatusUpTime extends MongoApplicationStatusWrapper { @@ -25,7 +25,7 @@ public class ApplicationStatusUpTime extends MongoApplicationStatusWrapper { //TODO take field names from RADAR MongoDb Connector @Override - protected Application getApplication(Document doc, Application app) { + protected ApplicationStatus getApplication(Document doc, ApplicationStatus app) { app.setUptime(doc.getDouble("uptime")); return app; diff --git a/src/main/java/org/radarcns/mongo/data/monitor/MongoApplicationStatusWrapper.java b/src/main/java/org/radarcns/mongo/data/monitor/application/MongoApplicationStatusWrapper.java similarity index 81% rename from src/main/java/org/radarcns/mongo/data/monitor/MongoApplicationStatusWrapper.java rename to src/main/java/org/radarcns/mongo/data/monitor/application/MongoApplicationStatusWrapper.java index 7190a53f..00953571 100644 --- a/src/main/java/org/radarcns/mongo/data/monitor/MongoApplicationStatusWrapper.java +++ b/src/main/java/org/radarcns/mongo/data/monitor/application/MongoApplicationStatusWrapper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.radarcns.mongo.data.monitor; +package org.radarcns.mongo.data.monitor.application; import static org.radarcns.mongo.util.MongoHelper.ASCENDING; import static org.radarcns.mongo.util.MongoHelper.VALUE; @@ -22,7 +22,7 @@ import com.mongodb.MongoClient; import com.mongodb.client.MongoCursor; import org.bson.Document; -import org.radarcns.domain.restapi.Application; +import org.radarcns.domain.restapi.monitor.ApplicationStatus; import org.radarcns.mongo.util.MongoHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,16 +36,15 @@ public abstract class MongoApplicationStatusWrapper { .getLogger(MongoApplicationStatusWrapper.class); /** - * Returns an {@code Application} initialised with the extracted value. + * Returns an {@code ApplicationStatus} initialised with the extracted value. * * @param subject is the subjectID * @param source is the sourceID * @param client is the mongoDb client instance * @return the last seen status update for the given subject and sourceType, otherwise null */ - public Application valueByProjectSubjectSource(String project, String subject, String source, - Application app, - MongoClient client) { + public ApplicationStatus valueByProjectSubjectSource(String project, String subject, + String source, ApplicationStatus app, MongoClient client) { MongoCursor cursor = MongoHelper .findDocumentBySource(MongoHelper.getCollection(client, getCollectionName()), @@ -62,14 +61,14 @@ public Application valueByProjectSubjectSource(String project, String subject, S cursor.close(); if (app == null) { - return getApplication((Document) doc.get(VALUE), new Application()); + return getApplication((Document) doc.get(VALUE), new ApplicationStatus()); } return getApplication((Document) doc.get(VALUE), app); } - protected abstract Application getApplication(Document doc, Application app); + protected abstract ApplicationStatus getApplication(Document doc, ApplicationStatus app); public abstract String getCollectionName(); diff --git a/src/main/java/org/radarcns/mongo/data/monitor/questionnaire/QuestionnaireCompletionLogWrapper.java b/src/main/java/org/radarcns/mongo/data/monitor/questionnaire/QuestionnaireCompletionLogWrapper.java new file mode 100644 index 00000000..4db24b3b --- /dev/null +++ b/src/main/java/org/radarcns/mongo/data/monitor/questionnaire/QuestionnaireCompletionLogWrapper.java @@ -0,0 +1,56 @@ +package org.radarcns.mongo.data.monitor.questionnaire; + +import static org.radarcns.mongo.util.MongoHelper.ASCENDING; +import static org.radarcns.mongo.util.MongoHelper.VALUE; + +import com.mongodb.MongoClient; +import com.mongodb.client.MongoCursor; +import org.bson.Document; +import org.radarcns.domain.restapi.monitor.QuestionnaireCompletionStatus; +import org.radarcns.mongo.data.monitor.application.MongoApplicationStatusWrapper; +import org.radarcns.mongo.util.MongoHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class QuestionnaireCompletionLogWrapper { + private static final Logger LOGGER = + LoggerFactory.getLogger(MongoApplicationStatusWrapper.class); + + public static final String QUESTIONNAIRE_COMPLETION_LOG_COLLECTION = + "questionnaire-completion-log"; + + + /** + * Returns an {@code QuestionnaireCompletionStatus} initialised with the extracted value. + * + * @param project is the projectName + * @param subject is the subjectID + * @param source is the sourceID + * @param client is the mongoDb client instance + * @return the last recorded value of questionnaire-completion-log, otherwise null + */ + public QuestionnaireCompletionStatus valueByProjectSubjectSource(String project, String subject, + String source, MongoClient client) { + + MongoCursor cursor = MongoHelper.findDocumentBySource( + MongoHelper.getCollection(client, QUESTIONNAIRE_COMPLETION_LOG_COLLECTION), project, + subject, source, VALUE + ".time", ASCENDING, 1); + + if (!cursor.hasNext()) { + LOGGER.debug("Empty cursor"); + cursor.close(); + return null; + } + + Document doc = cursor.next(); + cursor.close(); + Document value = (Document) doc.get(VALUE); + + QuestionnaireCompletionStatus data = new QuestionnaireCompletionStatus(); + data.setTimeRecorded(value.getDouble("time")); + data.setQuestionnaireName(value.getString("name")); + data.setCompletionPercentage(value.getDouble("completionPercentage")); + + return data; + } +} diff --git a/src/main/java/org/radarcns/mongo/data/passive/SourceDataMongoWrapper.java b/src/main/java/org/radarcns/mongo/data/passive/SourceDataMongoWrapper.java index cf1268c6..4f3610d0 100644 --- a/src/main/java/org/radarcns/mongo/data/passive/SourceDataMongoWrapper.java +++ b/src/main/java/org/radarcns/mongo/data/passive/SourceDataMongoWrapper.java @@ -32,6 +32,7 @@ import org.radarcns.domain.restapi.TimeWindow; import org.radarcns.domain.restapi.dataset.DataItem; import org.radarcns.domain.restapi.dataset.Dataset; +import org.radarcns.domain.restapi.header.DataSetHeader; import org.radarcns.domain.restapi.header.DescriptiveStatistic; import org.radarcns.domain.restapi.header.Header; import org.radarcns.domain.restapi.header.TimeFrame; @@ -93,7 +94,7 @@ public String getSourceDataName() { * @see Dataset */ @SuppressWarnings("checkstyle:AbbreviationAsWordInName") - public Dataset getLatestRecord(String projectName, String subject, String source, Header + public Dataset getLatestRecord(String projectName, String subject, String source, DataSetHeader header, Stat stat, MongoCollection collection) { try (MongoCursor cursor = MongoHelper.findDocumentBySource( collection, projectName, subject, source, KEY + "." + END, DESCENDING, 1)) { @@ -115,7 +116,7 @@ public Dataset getLatestRecord(String projectName, String subject, String source * @see Dataset */ public Dataset getAllRecords(MongoCollection collection, String projectName, - String subject, String source, Header header, Stat stat) { + String subject, String source, DataSetHeader header, Stat stat) { try (MongoCursor cursor = MongoHelper.findDocumentBySource( collection, projectName, subject, source, KEY + "." + START, ASCENDING, null)) { return getDataSet(stat.getParam(), RadarConverter.getDescriptiveStatistic(stat), header, @@ -137,7 +138,7 @@ public Dataset getAllRecords(MongoCollection collection, String projec * @see Dataset */ public Dataset getAllRecordsInWindow(MongoCollection collection, String projectName, - String subject, String source, Header header, Stat stat, TimeFrame timeFrame) { + String subject, String source, DataSetHeader header, Stat stat, TimeFrame timeFrame) { try (MongoCursor cursor = MongoHelper.findDocumentsBySource( collection, projectName, subject, source, timeFrame)) { return getDataSet(stat.getParam(), RadarConverter.getDescriptiveStatistic(stat), header, @@ -156,7 +157,7 @@ public Dataset getAllRecordsInWindow(MongoCollection collection, Strin * @return data dataset for the given input, otherwise empty dataset * @see Dataset */ - private Dataset getDataSet(String field, DescriptiveStatistic stat, Header header, + private Dataset getDataSet(String field, DescriptiveStatistic stat, DataSetHeader header, MongoCursor cursor) { TimeFrame timeFrame = null; @@ -180,7 +181,7 @@ private Dataset getDataSet(String field, DescriptiveStatistic stat, Header heade currentFrame.getStartDateTime())); } - header.setEffectiveTimeFrame(timeFrame); + header.effectiveTimeFrame(timeFrame); LOGGER.debug("Found {} value(s)", list.size()); diff --git a/src/main/java/org/radarcns/service/ApplicationStatusMonitorService.java b/src/main/java/org/radarcns/service/ApplicationStatusMonitorService.java deleted file mode 100644 index 467ae516..00000000 --- a/src/main/java/org/radarcns/service/ApplicationStatusMonitorService.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2016 King's College London and The Hyve - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.radarcns.service; - -import com.mongodb.MongoClient; -import java.util.LinkedList; -import java.util.List; -import javax.inject.Inject; -import org.radarcns.domain.restapi.Application; -import org.radarcns.mongo.data.monitor.ApplicationStatusRecordCounter; -import org.radarcns.mongo.data.monitor.ApplicationStatusServerStatus; -import org.radarcns.mongo.data.monitor.ApplicationStatusUpTime; -import org.radarcns.mongo.data.monitor.MongoApplicationStatusWrapper; - -/** - * Data Access Object for Android App Status values. - */ -public class ApplicationStatusMonitorService { - - - private final List dataAccessObjects; - - /** - * Default constructor. Initiates all the delegate classes to compute Application Status. - */ - @Inject - public ApplicationStatusMonitorService() { - //TODO simplify processing application status - dataAccessObjects = new LinkedList<>(); - dataAccessObjects.add(new ApplicationStatusUpTime()); - dataAccessObjects.add(new ApplicationStatusRecordCounter()); - dataAccessObjects.add(new ApplicationStatusServerStatus()); - } - - /** - * Computes the Android App Status realign on different collection. - * - * @param project of the subject - * @param subject identifier - * @param source identifier - * @param client is the MongoDb client - * @return {@code Application} representing the status of the related Android App - */ - public Application getStatus(String project, String subject, String source, MongoClient - client) { - Application app = null; - - for (MongoApplicationStatusWrapper dataAccessObject : dataAccessObjects) { - app = dataAccessObject - .valueByProjectSubjectSource(project, subject, source, app, client); - } - - return app; - } -} \ No newline at end of file diff --git a/src/main/java/org/radarcns/service/DataSetService.java b/src/main/java/org/radarcns/service/DataSetService.java index 4a23227a..123b208f 100644 --- a/src/main/java/org/radarcns/service/DataSetService.java +++ b/src/main/java/org/radarcns/service/DataSetService.java @@ -16,6 +16,8 @@ package org.radarcns.service; +import static org.radarcns.util.ThrowingFunction.tryOrRethrow; + import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import java.io.IOException; @@ -34,6 +36,7 @@ import org.radarcns.domain.restapi.dataset.DataItem; import org.radarcns.domain.restapi.dataset.Dataset; import org.radarcns.domain.restapi.format.SourceData; +import org.radarcns.domain.restapi.header.DataSetHeader; import org.radarcns.domain.restapi.header.DescriptiveStatistic; import org.radarcns.domain.restapi.header.Header; import org.radarcns.domain.restapi.header.TimeFrame; @@ -88,8 +91,8 @@ public static Dataset emptyDataset(String projectName, String subjectId, String TimeFrame timeFrame) { return new Dataset( - new Header(projectName, subjectId, sourceId, "UNKNOWN", sourceDataName, stat, - null, interval, timeFrame, null), + new DataSetHeader(projectName, subjectId, sourceId, "UNKNOWN", + sourceDataName, stat, null, interval, timeFrame, null), Collections.emptyList()); } @@ -129,7 +132,7 @@ public Dataset getLastReceivedSample(String projectName, String subjectId, Strin new TimeFrame(now.minus(TimeScale.getDuration(timeWindow)), now), timeWindow); - Header header = getHeader(projectName, subjectId, sourceId, + DataSetHeader header = getHeader(projectName, subjectId, sourceId, sourceDataName, stat, timeScale); SourceDataMongoWrapper sourceData = this.sourceCatalog @@ -160,7 +163,7 @@ public Dataset getAllRecordsInWindow(String projectName, String subjectId, SourceDataMongoWrapper sourceData = this.sourceCatalog.getSourceDataWrapper(sourceDataName); - Header header = getHeader(projectName, subjectId, sourceId, + DataSetHeader header = getHeader(projectName, subjectId, sourceId, sourceData.getSourceData(), stat, timeScale, source.getSourceTypeIdentifier().toString()); @@ -170,7 +173,7 @@ public Dataset getAllRecordsInWindow(String projectName, String subjectId, timeScale.getTimeFrame()); } - private Header getHeader(String projectName, String subjectId, String sourceId, + private DataSetHeader getHeader(String projectName, String subjectId, String sourceId, String sourceDataName, DescriptiveStatistic stat, TimeScale timeScale) throws IOException { SourceDTO source = managementPortalClient.getSource(sourceId); @@ -190,11 +193,12 @@ private Header getHeader(String projectName, String subjectId, String sourceId, * @return {@link Header} related to the given inputs * @see Dataset */ - private Header getHeader(String project, String subject, String source, + private DataSetHeader getHeader(String project, String subject, String source, SourceDataDTO sourceData, DescriptiveStatistic stat, TimeScale timeScale, String sourceType) { - return new Header(project, subject, source, sourceType, sourceData.getSourceDataType(), - stat, sourceData.getUnit(), timeScale.getTimeWindow(), timeScale.getTimeFrame(), + return new DataSetHeader(project, subject, source, sourceType, + sourceData.getSourceDataType(), stat, sourceData.getUnit(), + timeScale.getTimeWindow(), timeScale.getTimeFrame(), null); } @@ -228,10 +232,10 @@ public AggregatedDataPoints getDistinctData(String projectName, String subjectId timeScale.getTimeWindow())) .collect(Collectors.toList()); - Integer maximumValue = dataItems.stream() - .map(p -> ((Number) p.getValue()).intValue()) - .reduce(Integer::max) - .orElse(null); + Integer maximumValue = dataItems.isEmpty() ? null : dataItems.stream() + .mapToInt(p -> ((Number)p.getValue()).intValue()) + .max() + .orElseThrow(() -> new IllegalStateException("Data items are empty")); return new AggregatedDataPoints(projectName, subjectId, maximumValue, timeScale, sources, dataItems); @@ -241,15 +245,9 @@ private DataItem collectDistinctSources(String projectName, String subjectId, List aggregateDataSources, TimeFrame timeFrame, TimeWindow timeWindow) { int count = aggregateDataSources.stream() - .map(aggregate -> (int) aggregate.getSourceData().stream() - .map(sourceData -> { - try { - return this.sourceCatalog - .getSourceDataWrapper(sourceData.getName()); - } catch (IOException exe) { - throw new BadGatewayException(exe); - } - }) + .mapToInt(aggregate -> (int) aggregate.getSourceData().stream() + .map(tryOrRethrow(s -> this.sourceCatalog.getSourceDataWrapper(s.getName()), + BadGatewayException::new)) .filter(wrapper -> { MongoCollection collection = MongoHelper.getCollection( mongoClient, wrapper.getCollectionName(timeWindow)); @@ -258,7 +256,7 @@ private DataItem collectDistinctSources(String projectName, String subjectId, aggregate.getSourceId(), timeFrame); }) .count()) - .reduce(0, Integer::sum); + .sum(); return new DataItem(count, timeFrame.getStartDateTime()); } diff --git a/src/main/java/org/radarcns/service/SourceService.java b/src/main/java/org/radarcns/service/SourceService.java index 7fb214c6..f82ebf19 100644 --- a/src/main/java/org/radarcns/service/SourceService.java +++ b/src/main/java/org/radarcns/service/SourceService.java @@ -57,8 +57,9 @@ public SourceService(SourceMonitorService sourceMonitorService, SourceCatalog so */ private List buildSourcesFromMinimal(String projectId, String subjectId, Collection sources) { - return sources.stream().map(p -> buildSource(projectId, subjectId, p)).collect(Collectors - .toList()); + return sources.stream() + .map(p -> buildSource(projectId, subjectId, p)) + .collect(Collectors.toList()); } /** diff --git a/src/main/java/org/radarcns/service/SourceStatusMonitorService.java b/src/main/java/org/radarcns/service/SourceStatusMonitorService.java new file mode 100644 index 00000000..05d6c8f4 --- /dev/null +++ b/src/main/java/org/radarcns/service/SourceStatusMonitorService.java @@ -0,0 +1,104 @@ +/* + * Copyright 2016 King's College London and The Hyve + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.radarcns.service; + +import static org.radarcns.domain.restapi.header.MonitorHeader.MonitorCategory.PASSIVE; +import static org.radarcns.domain.restapi.header.MonitorHeader.MonitorCategory.QUESTIONNAIRE; + +import com.mongodb.MongoClient; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import javax.inject.Inject; +import org.radarcns.domain.managementportal.SourceDTO; +import org.radarcns.domain.restapi.header.MonitorHeader; +import org.radarcns.domain.restapi.monitor.ApplicationStatus; +import org.radarcns.domain.restapi.monitor.MonitorData; +import org.radarcns.listener.managementportal.ManagementPortalClient; +import org.radarcns.mongo.data.monitor.application.ApplicationStatusRecordCounter; +import org.radarcns.mongo.data.monitor.application.ApplicationStatusServerStatus; +import org.radarcns.mongo.data.monitor.application.ApplicationStatusUpTime; +import org.radarcns.mongo.data.monitor.application.MongoApplicationStatusWrapper; +import org.radarcns.mongo.data.monitor.questionnaire.QuestionnaireCompletionLogWrapper; + +/** + * Data Access Object for Source Status values. + */ +public class SourceStatusMonitorService { + + + private final List dataAccessObjects; + + private QuestionnaireCompletionLogWrapper questionnaireCompletionLogWrapper; + + private final ManagementPortalClient managementPortalClient; + + /** + * Default constructor. Initiates all the delegate classes to compute Source Status. + */ + @Inject + public SourceStatusMonitorService(ManagementPortalClient managementPortalClient) { + this.managementPortalClient = managementPortalClient; + dataAccessObjects = new LinkedList<>(); + dataAccessObjects.add(new ApplicationStatusUpTime()); + dataAccessObjects.add(new ApplicationStatusRecordCounter()); + dataAccessObjects.add(new ApplicationStatusServerStatus()); + + this.questionnaireCompletionLogWrapper = new QuestionnaireCompletionLogWrapper(); + } + + /** + * Computes the Source Status realign on different collection. + * + * @param projectName of the subject + * @param subjectId identifier + * @param sourceId identifier + * @param client is the MongoDb client + * @return {@code MonitorData} representing the status of the related source + */ + public MonitorData getStatus(String projectName, String subjectId, String sourceId, + MongoClient client) throws IOException { + + MonitorHeader header = (MonitorHeader) new MonitorHeader() + .projectId(projectName) + .subjectId(subjectId) + .sourceId(sourceId); + SourceDTO source = managementPortalClient.getSource(sourceId); + if (source.getSourceType() != null) { + header.sourceType(source.getSourceType().getSourceTypeIdentifier().toString()); + if (source.getSourceType().getModel().contains("pRMT") || source.getSourceType() + .getSourceTypeScope().equals("MONITOR")) { + ApplicationStatus app = new ApplicationStatus(); + for (MongoApplicationStatusWrapper dataAccessObject : dataAccessObjects) { + app = dataAccessObject + .valueByProjectSubjectSource(projectName, subjectId, sourceId, app, + client); + } + header.monitorCategory(PASSIVE); + return new MonitorData().header(header).data(app); + } + + if (source.getSourceType().getModel().contains("aRMT-App")) { + header.monitorCategory(QUESTIONNAIRE); + return new MonitorData().header(header).data(questionnaireCompletionLogWrapper + .valueByProjectSubjectSource(projectName, subjectId, sourceId, client)); + } + + } + return new MonitorData().header(header); + } +} \ No newline at end of file diff --git a/src/main/java/org/radarcns/service/SubjectService.java b/src/main/java/org/radarcns/service/SubjectService.java index eb16b58e..4b45bb14 100644 --- a/src/main/java/org/radarcns/service/SubjectService.java +++ b/src/main/java/org/radarcns/service/SubjectService.java @@ -1,16 +1,19 @@ package org.radarcns.service; +import static org.radarcns.util.ThrowingFunction.tryOrRethrow; + import java.io.IOException; import java.time.Instant; +import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import javax.inject.Inject; -import javax.ws.rs.BadRequestException; import javax.ws.rs.NotFoundException; import org.radarcns.domain.managementportal.SubjectDTO; import org.radarcns.domain.restapi.Source; import org.radarcns.domain.restapi.Subject; +import org.radarcns.domain.restapi.header.TimeFrame; import org.radarcns.listener.managementportal.ManagementPortalClient; import org.radarcns.webapp.exception.BadGatewayException; import org.slf4j.Logger; @@ -42,20 +45,19 @@ public SubjectService(ManagementPortalClient managementPortalClient, * * @param subjectId of subject * @param sourceId of source - * @return {@code true} if available. * @throws IOException when unable to process the request. */ - public boolean checkSourceAssignedToSubject(String subjectId, String sourceId) + public void checkSourceAssignedToSubject(String subjectId, String sourceId) throws IOException { SubjectDTO subject = managementPortalClient.getSubject(subjectId); - if (subject.getSources().stream().filter(p -> p.getSourceId().toString().equals(sourceId)) - .collect(Collectors.toList()).isEmpty()) { + if (subject.getSources().stream() + .map(s -> s.getSourceId().toString()) + .noneMatch(sourceId::equals)) { LOGGER.error("Cannot find source-id " + sourceId + "for subject" + subject.getId()); - throw new BadRequestException( - "Source-id " + sourceId + " is not available for subject " + throw new NotFoundException( + "Source-id " + sourceId + " is not found for subject " + subject.getId()); } - return true; } private Subject buildSubject(SubjectDTO subject) @@ -73,10 +75,11 @@ private Subject buildSubject(SubjectDTO subject) private Instant getLastSeenForSubject(List sources) { return sources.stream() - .map(s -> s.getEffectiveTimeFrame() != null - ? s.getEffectiveTimeFrame().getEndDateTime() : null) + .map(Source::getEffectiveTimeFrame) + .filter(Objects::nonNull) + .map(TimeFrame::getEndDateTime) .filter(Objects::nonNull) - .reduce((i1, i2) -> i1.isAfter(i2) ? i1 : i2) + .max(Comparator.naturalOrder()) .orElse(null); } @@ -93,13 +96,8 @@ public List getAllSubjectsFromProject(String projectName) // returns NotFound if a project is not available this.managementPortalClient.getProject(projectName); return this.managementPortalClient.getAllSubjectsFromProject(projectName).stream() - .map(s -> { - try { - return buildSubject(s); - } catch (IOException exe) { - throw new BadGatewayException(exe); - } - }).collect(Collectors.toList()); + .map(tryOrRethrow(this::buildSubject, BadGatewayException::new)) + .collect(Collectors.toList()); } public Subject getSubjectBySubjectId(String projectName, String subjectId) diff --git a/src/main/java/org/radarcns/util/ThrowingFunction.java b/src/main/java/org/radarcns/util/ThrowingFunction.java new file mode 100644 index 00000000..bdac1e63 --- /dev/null +++ b/src/main/java/org/radarcns/util/ThrowingFunction.java @@ -0,0 +1,26 @@ +package org.radarcns.util; + +import java.util.function.Function; + +/** Function that may throw an unchecked exception. */ +@FunctionalInterface +public interface ThrowingFunction { + R apply(T value) throws Exception; + + /** + * Run a function. If it throws any exception, apply toException to map it to a runtime + * exception and throw that instead. RuntimeException objects will also be mapped by + * toException. + */ + static Function tryOrRethrow( + ThrowingFunction function, + Function toException) { + return t -> { + try { + return function.apply(t); + } catch (Exception e) { + throw toException.apply(e); + } + }; + } +} diff --git a/src/main/java/org/radarcns/webapp/RadarApplication.java b/src/main/java/org/radarcns/webapp/RadarApplication.java index 2b046024..4a85bfa1 100644 --- a/src/main/java/org/radarcns/webapp/RadarApplication.java +++ b/src/main/java/org/radarcns/webapp/RadarApplication.java @@ -9,10 +9,10 @@ import org.radarcns.listener.HttpClientFactory; import org.radarcns.listener.MongoFactory; import org.radarcns.listener.managementportal.ManagementPortalClient; -import org.radarcns.service.ApplicationStatusMonitorService; import org.radarcns.service.DataSetService; import org.radarcns.service.SourceMonitorService; import org.radarcns.service.SourceService; +import org.radarcns.service.SourceStatusMonitorService; import org.radarcns.service.SubjectService; import org.radarcns.webapp.filter.AuthenticationFilter; import org.radarcns.webapp.filter.AuthorizationFeature; @@ -76,8 +76,8 @@ protected void configure() { .to(DataSetService.class) .in(Singleton.class); - bind(ApplicationStatusMonitorService.class) - .to(ApplicationStatusMonitorService.class) + bind(SourceStatusMonitorService.class) + .to(SourceStatusMonitorService.class) .in(Singleton.class); } }); diff --git a/src/main/java/org/radarcns/webapp/param/TimeScaleParser.java b/src/main/java/org/radarcns/webapp/param/TimeScaleParser.java index 487f4b4b..85ec6422 100644 --- a/src/main/java/org/radarcns/webapp/param/TimeScaleParser.java +++ b/src/main/java/org/radarcns/webapp/param/TimeScaleParser.java @@ -9,8 +9,10 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nonnull; @@ -112,7 +114,7 @@ private TimeWindow getFittingTimeWindow(TimeFrame timeFrame) { double logSeconds = Math.log(timeFrame.getDuration().getSeconds() / defaultNumberOfWindows); return TIME_WINDOW_LOG.stream() .map(e -> RadarConverter.pair(e.getKey(), Math.abs(logSeconds - e.getValue()))) - .reduce((e1, e2) -> e1.getValue() < e2.getValue() ? e1 : e2) + .min(Comparator.comparing(Entry::getValue)) .orElseThrow(() -> new AssertionError("No close time window found")) .getKey(); } diff --git a/src/main/java/org/radarcns/webapp/resource/AppStatusEndPoint.java b/src/main/java/org/radarcns/webapp/resource/AppStatusEndPoint.java index 886547d9..db422d0e 100644 --- a/src/main/java/org/radarcns/webapp/resource/AppStatusEndPoint.java +++ b/src/main/java/org/radarcns/webapp/resource/AppStatusEndPoint.java @@ -35,10 +35,9 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.radarcns.auth.NeedsPermissionOnSubject; -import org.radarcns.domain.restapi.Application; -import org.radarcns.domain.restapi.ServerStatus; +import org.radarcns.domain.restapi.monitor.MonitorData; import org.radarcns.listener.managementportal.ManagementPortalClient; -import org.radarcns.service.ApplicationStatusMonitorService; +import org.radarcns.service.SourceStatusMonitorService; import org.radarcns.service.SubjectService; import org.radarcns.webapp.filter.Authenticated; import org.radarcns.webapp.validation.Alphanumeric; @@ -60,7 +59,7 @@ public class AppStatusEndPoint { private SubjectService subjectService; @Inject - private ApplicationStatusMonitorService applicationStatusMonitorService; + private SourceStatusMonitorService sourceStatusMonitorService; //--------------------------------------------------------------------------------------------// // APPLICATION_STATUS FUNCTIONS // //--------------------------------------------------------------------------------------------// @@ -78,22 +77,15 @@ public class AppStatusEndPoint { "Return a application object containing last received status") @ApiResponse(responseCode = "401", description = "Access denied error occurred") @ApiResponse(responseCode = "403", description = "Not Authorised error occurred") - @ApiResponse(responseCode = "404", description = "Subject not found.") + @ApiResponse(responseCode = "404", description = "project, subject or source not found.") @NeedsPermissionOnSubject(entity = SOURCE, operation = READ) - public Application getLastReceivedAppStatusJson( + public MonitorData getLastReceivedAppStatusJson( @Alphanumeric @PathParam(PROJECT_NAME) String projectName, @Alphanumeric @PathParam(SUBJECT_ID) String subjectId, @Alphanumeric @PathParam(SOURCE_ID) String sourceId) throws IOException { mpClient.checkSubjectInProject(projectName, subjectId); - Application application = null; - if (subjectService.checkSourceAssignedToSubject(subjectId, sourceId)) { - application = applicationStatusMonitorService.getStatus(projectName, - subjectId, sourceId, mongoClient); - } - if (application == null) { - return new Application(null, 0d, ServerStatus.UNKNOWN, -1, -1, -1); + subjectService.checkSourceAssignedToSubject(subjectId, sourceId); - } - return application; + return sourceStatusMonitorService.getStatus(projectName, subjectId, sourceId, mongoClient); } }