Skip to content

Commit 2fc9781

Browse files
Add getObservationById, updateObservation, deleteObservation
1 parent 5415824 commit 2fc9781

9 files changed

Lines changed: 170 additions & 96 deletions

File tree

CSAPI-lib/DataModels/Data/DataBlockMixed.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ namespace ConnectedSystemsAPI {
7171
j[pair.first] = pair.second;
7272
}
7373
}
74+
75+
inline std::ostream& operator<<(std::ostream& os, const DataBlockMixed& v) {
76+
nlohmann::ordered_json j;
77+
to_json(j, v);
78+
os << j.dump(2);
79+
return os;
80+
}
7481
}
7582
}
7683
}

CSAPI-lib/DataModels/Data/DataValue.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,18 @@ namespace ConnectedSystemsAPI {
3131
DataValue(std::string&& v) : value(std::move(v)) {}
3232
DataValue(const char* s) : value(std::string(s)) {}
3333

34+
// Assignment operators for underlying types
35+
DataValue& operator=(bool v) { value = v; return *this; }
36+
DataValue& operator=(int64_t v) { value = v; return *this; }
37+
DataValue& operator=(uint64_t v) { value = v; return *this; }
38+
DataValue& operator=(double v) { value = v; return *this; }
39+
DataValue& operator=(const std::string& v) { value = v; return *this; }
40+
DataValue& operator=(std::string&& v) { value = std::move(v); return *this; }
41+
DataValue& operator=(const char* s) { value = std::string(s); return *this; }
42+
3443
std::string toString() const {
3544
if (std::holds_alternative<bool>(value)) {
36-
return std::holds_alternative<bool>(value) && std::get<bool>(value) ? "true" : "false";
45+
return std::get<bool>(value) ? "true" : "false";
3746
}
3847
else if (std::holds_alternative<int64_t>(value)) {
3948
return std::to_string(std::get<int64_t>(value));

CSAPI-lib/DataModels/Observation.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,12 @@ namespace ConnectedSystemsAPI {
128128

129129
j["result"] = o.result;
130130
}
131+
132+
inline std::ostream& operator<<(std::ostream& os, const Observation& o) {
133+
nlohmann::ordered_json j;
134+
to_json(j, o);
135+
os << j.dump(2);
136+
return os;
137+
}
131138
}
132139
}

CSAPI-lib/DataModels/ObservationBuilder.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ namespace ConnectedSystemsAPI {
2626

2727
public:
2828
ObservationBuilder() = default;
29+
30+
ObservationBuilder& from(const Observation& o) {
31+
id = o.getId();
32+
dataStreamId = o.getDataStreamId();
33+
samplingFeatureId = o.getSamplingFeatureId();
34+
procedureLink = o.getProcedureLink();
35+
phenomenonTime = o.getPhenomenonTime();
36+
resultTime = o.getResultTime();
37+
result = o.getResult();
38+
resultLink = o.getResultLink();
39+
links = o.getLinks();
40+
return *this;
41+
}
42+
2943
ObservationBuilder& withId(const std::string& v) { id = v; return *this; }
3044
ObservationBuilder& withDataStreamId(const std::string& v) { dataStreamId = v; return *this; }
3145
ObservationBuilder& withSamplingFeatureId(const std::string& v) { samplingFeatureId = v; return *this; }

CSAPI-lib/ObservationsAPI.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ namespace ConnectedSystemsAPI {
4040
return response;
4141
}
4242

43+
APIResponse<DataModels::Observation> getObservationById(const std::string& observationId) {
44+
auto response = APIRequest::Builder()
45+
.setApiRoot(apiRoot)
46+
.setMethod("GET")
47+
.setAuthHeader(authHeader)
48+
.setResourcePath("/observations/" + observationId)
49+
.build()
50+
.execute<DataModels::Observation>();
51+
return response;
52+
}
53+
4354
APIResponse<void> createObservation(const std::string& dataStreamId, const DataModels::Observation& observation) {
4455
nlohmann::ordered_json j;
4556
ConnectedSystemsAPI::DataModels::to_json(j, observation);
@@ -54,5 +65,31 @@ namespace ConnectedSystemsAPI {
5465
.execute<void>();
5566
return response;
5667
}
68+
69+
APIResponse<void> updateObservation(const std::string& observationId, const DataModels::Observation& observation) {
70+
nlohmann::ordered_json j;
71+
ConnectedSystemsAPI::DataModels::to_json(j, observation);
72+
auto response = APIRequest::Builder()
73+
.setApiRoot(apiRoot)
74+
.setMethod("PUT")
75+
.setAuthHeader(authHeader)
76+
.addHeader("Content-Type", "application/json")
77+
.setResourcePath("/observations/" + observationId)
78+
.setBody(j.dump())
79+
.build()
80+
.execute<void>();
81+
return response;
82+
}
83+
84+
APIResponse<void> deleteObservation(const std::string& observationId) {
85+
auto response = APIRequest::Builder()
86+
.setApiRoot(apiRoot)
87+
.setMethod("DELETE")
88+
.setAuthHeader(authHeader)
89+
.setResourcePath("/observations/" + observationId)
90+
.build()
91+
.execute<void>();
92+
return response;
93+
}
5794
};
5895
}

CSAPI-test/DataStreamsTest.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,16 @@ namespace CSAPItest {
4444
}
4545

4646
TEST_METHOD(CreateDataStream) {
47-
testHelper.createTestSystem();
48-
std::string systemId = testHelper.getTestSystemId();
49-
auto dataStream = testHelper.createDataStream();
47+
auto systemId = testHelper.createTestSystem();
48+
auto dataStream = testHelper.createTestDataStreamObject();
5049
auto response = testHelper.csapi.getDataStreamsAPI().createDataStream(systemId, dataStream);
5150
Assert::IsTrue(response.isSuccessful());
5251
}
5352

5453
TEST_METHOD(DeleteDataStream) {
55-
testHelper.createTestSystem();
56-
std::string systemId = testHelper.getTestSystemId();
57-
auto dataStream = testHelper.createDataStream();
58-
auto dsId = dataStream.getId().value_or("");
59-
testHelper.csapi.getDataStreamsAPI().deleteDataStream(dsId, true);
54+
auto systemId = testHelper.createTestSystem();
55+
auto dataStreamId = testHelper.createTestDataStream(systemId);
56+
testHelper.csapi.getDataStreamsAPI().deleteDataStream(dataStreamId, true);
6057
}
6158
};
6259
}

CSAPI-test/ObservationsTest.cpp

Lines changed: 60 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,34 @@ namespace CSAPItest {
1717
{
1818
private:
1919
TestHelper testHelper;
20+
21+
ConnectedSystemsAPI::DataModels::Data::DataBlockMixed createTestDataBlock(const std::string& dataStreamId) {
22+
//Get the schema to know what kind of observation to create
23+
auto schemaResponse = testHelper.csapi.getDataStreamsAPI().getObservationSchema(dataStreamId);
24+
auto schema = schemaResponse.getItems().at(0).getResultSchema();
25+
auto schemaDataRecord = dynamic_cast<const ConnectedSystemsAPI::DataModels::Component::DataRecord*>(schema);
26+
// Create a data block according to the schema
27+
ConnectedSystemsAPI::DataModels::Data::DataBlockMixed dataBlock = schemaDataRecord->createDataBlock();
28+
return dataBlock;
29+
}
30+
31+
ConnectedSystemsAPI::DataModels::Observation pushTestObservation(const std::string& dataStreamId, const ConnectedSystemsAPI::DataModels::Data::DataBlockMixed& dataBlock) {
32+
auto now = ConnectedSystemsAPI::DataModels::TimeInstant(std::chrono::system_clock::now());
33+
auto observation = ConnectedSystemsAPI::DataModels::ObservationBuilder()
34+
.withResultTime(now)
35+
.withResult(dataBlock)
36+
.build();
37+
testHelper.csapi.getObservationsAPI().createObservation(dataStreamId, observation);
38+
return getTestObservation(dataStreamId);
39+
}
40+
41+
ConnectedSystemsAPI::DataModels::Observation getTestObservation(const std::string& dataStreamId) {
42+
auto observationsResponse = testHelper.csapi.getObservationsAPI().getObservationsOfDataStream(dataStreamId);
43+
Assert::IsTrue(observationsResponse.isSuccessful());
44+
Assert::IsTrue(observationsResponse.getItems().size() > 0);
45+
return observationsResponse.getItems().at(0);
46+
}
47+
2048
public:
2149
TEST_METHOD_INITIALIZE(ClassInitialize) {
2250
testHelper = TestHelper();
@@ -45,54 +73,17 @@ namespace CSAPItest {
4573
}
4674

4775
TEST_METHOD(CreateObservation) {
48-
testHelper.createTestSystem();
49-
std::string systemId = testHelper.getTestSystemId();
50-
auto dataStream = testHelper.createDataStream();
51-
auto dataStreamCreateResponse = testHelper.csapi.getDataStreamsAPI().createDataStream(systemId, dataStream);
52-
auto dataStreamGetResponse = testHelper.csapi.getDataStreamsAPI().getDataStreams();
53-
54-
// First create a datastream
55-
std::string dataStreamId;
56-
for (const auto& ds : dataStreamGetResponse.getItems()) {
57-
if (ds.getName().value_or("") == dataStream.getName().value_or("")) {
58-
dataStreamId = ds.getId().value_or("");
59-
break;
60-
}
61-
}
62-
assert(!dataStreamId.empty());
76+
auto systemId = testHelper.createTestSystem();
77+
auto dataStreamId = testHelper.createTestDataStream(systemId);
78+
auto dataBlock = createTestDataBlock(dataStreamId);
6379

64-
//Get the schema to know what kind of observation to create
65-
auto schemaResponse = testHelper.csapi.getDataStreamsAPI().getObservationSchema(dataStreamId);
66-
Assert::IsTrue(schemaResponse.isSuccessful());
67-
auto schema = schemaResponse.getItems().at(0).getResultSchema();
68-
auto schemaDataRecord = dynamic_cast<const ConnectedSystemsAPI::DataModels::Component::DataRecord*>(schema);
69-
Assert::IsNotNull(schemaDataRecord);
70-
// Create a data block according to the schema
71-
auto dataBlock = schemaDataRecord->createDataBlock();
7280
dataBlock.setField("booleanField", ConnectedSystemsAPI::DataModels::Data::DataValue(true));
81+
auto observation = pushTestObservation(dataStreamId, dataBlock);
7382

74-
auto now = ConnectedSystemsAPI::DataModels::TimeInstant(std::chrono::system_clock::now());
75-
76-
// Then create an observation for that datastream
77-
auto observation = ConnectedSystemsAPI::DataModels::ObservationBuilder()
78-
.withResultTime(now)
79-
.withResult(dataBlock)
80-
.build();
81-
// Print out the observation JSON
82-
std::cout << "Observation to Create: " << observation.toJson().dump(2) << std::endl;
83-
84-
auto observationCreateResponse = testHelper.csapi.getObservationsAPI().createObservation(dataStreamId, observation);
85-
std::cout << "Create Observation Response Code: " << observationCreateResponse.getResponseCode() << std::endl;
86-
Assert::IsTrue(observationCreateResponse.isSuccessful());
87-
88-
// Get the observations to verify
89-
auto observationsResponse = testHelper.csapi.getObservationsAPI().getObservationsOfDataStream(dataStreamId);
90-
Assert::IsTrue(observationsResponse.isSuccessful());
91-
Assert::IsTrue(observationsResponse.getItems().size() > 0);
9283
//Verify the data stream id matches
93-
Assert::AreEqual(dataStreamId, observationsResponse.getItems().at(0).getDataStreamId().value_or(""));
84+
Assert::AreEqual(dataStreamId, observation.getDataStreamId().value_or(""));
9485
//Verify the result matches
95-
const auto* resultValue = observationsResponse.getItems().at(0).getResult().getField("booleanField");
86+
const auto* resultValue = observation.getResult().getField("booleanField");
9687
Assert::IsNotNull(resultValue);
9788
Assert::IsTrue(std::holds_alternative<bool>(resultValue->value));
9889
}
@@ -138,9 +129,33 @@ namespace CSAPItest {
138129
//Verify the result matches
139130
const auto* resultValue = observationsResponse.getItems().at(0).getResult().getField("data");
140131
Assert::IsNotNull(resultValue);
141-
std::cout << "Result value type index: " << resultValue->value.index() << std::endl;
142132
Assert::IsTrue(std::holds_alternative<std::string>(resultValue->value));
143-
std::cout << "Result value: " << std::get<std::string>(resultValue->value) << std::endl;
133+
}
134+
135+
TEST_METHOD(GetObservationById) {
136+
auto systemId = testHelper.createTestSystem();
137+
auto dataStreamId = testHelper.createTestDataStream(systemId);
138+
auto dataBlock = createTestDataBlock(dataStreamId);
139+
auto observation = pushTestObservation(dataStreamId, dataBlock);
140+
auto observationId = observation.getId().value_or("");
141+
142+
auto getResponse = testHelper.csapi.getObservationsAPI().getObservationById(observationId);
143+
Assert::IsTrue(getResponse.isSuccessful());
144+
Assert::AreEqual(observationId, getResponse.getItems().at(0).getId().value_or(""));
145+
}
146+
147+
TEST_METHOD(DeleteObservation) {
148+
auto systemId = testHelper.createTestSystem();
149+
auto dataStreamId = testHelper.createTestDataStream(systemId);
150+
auto dataBlock = createTestDataBlock(dataStreamId);
151+
auto observation = pushTestObservation(dataStreamId, dataBlock);
152+
auto observationId = observation.getId().value_or("");
153+
154+
auto deleteResponse = testHelper.csapi.getObservationsAPI().deleteObservation(observationId);
155+
Assert::IsTrue(deleteResponse.isSuccessful());
156+
157+
auto getResponse = testHelper.csapi.getObservationsAPI().getObservationById(observationId);
158+
Assert::IsFalse(getResponse.isSuccessful());
144159
}
145160
};
146161
}

CSAPI-test/SystemsTest.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,14 @@ namespace CSAPItest {
4949
}
5050

5151
TEST_METHOD(CreateSystem) {
52-
auto response = testHelper.createTestSystem();
53-
Assert::IsTrue(response.isSuccessful());
52+
auto systemId = testHelper.createTestSystem();
53+
Assert::IsFalse(systemId.empty());
5454
}
5555

5656
TEST_METHOD(CreateSubsystem) {
5757
testHelper.createTestSystem();
58-
auto response = testHelper.createTestSubsystem();
59-
testHelper.printSystems();
60-
Assert::IsTrue(response.isSuccessful());
58+
auto subsystemId = testHelper.createTestSubsystem();
59+
Assert::IsFalse(subsystemId.empty());
6160
}
6261

6362
TEST_METHOD(UpdateSystem) {

0 commit comments

Comments
 (0)