-
Notifications
You must be signed in to change notification settings - Fork 190
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a library that maps FHIR primitives to their respective FHIRPath …
…primitive types. PiperOrigin-RevId: 320487100
- Loading branch information
1 parent
7dfd19a
commit 683b31d
Showing
4 changed files
with
367 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Copyright 2020 Google LLC | ||
// | ||
// 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:https://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. | ||
|
||
#include "google/fhir/fhir_path/fhir_path_types.h" | ||
|
||
#include "absl/strings/string_view.h" | ||
#include "google/fhir/annotations.h" | ||
|
||
namespace google::fhir::fhir_path::internal { | ||
|
||
using ::google::protobuf::Message; | ||
|
||
StatusOr<FhirPathSystemType> GetSystemType( | ||
const ::google::protobuf::Message& fhir_primitive) { | ||
static const auto* type_map = | ||
new absl::flat_hash_map<absl::string_view, FhirPathSystemType>( | ||
{{"http:https://hl7.org/fhir/StructureDefinition/boolean", | ||
FhirPathSystemType::kBoolean}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/string", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/uri", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/url", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/canonical", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/code", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/oid", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/id", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/uuid", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/sid", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/markdown", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/base64Binary", | ||
FhirPathSystemType::kString}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/integer", | ||
FhirPathSystemType::kInteger}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/unsignedInt", | ||
FhirPathSystemType::kInteger}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/positiveInt", | ||
FhirPathSystemType::kInteger}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/decimal", | ||
FhirPathSystemType::kDecimal}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/date", | ||
FhirPathSystemType::kDate}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/dateTime", | ||
FhirPathSystemType::kDateTime}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/instant", | ||
FhirPathSystemType::kDateTime}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/time", | ||
FhirPathSystemType::kTime}, | ||
{"http:https://hl7.org/fhir/StructureDefinition/Quantity", | ||
FhirPathSystemType::kQuantity}}); | ||
|
||
auto type = | ||
type_map->find(GetStructureDefinitionUrl(fhir_primitive.GetDescriptor())); | ||
if (type == type_map->end()) { | ||
return absl::NotFoundError( | ||
absl::StrCat(fhir_primitive.GetTypeName(), | ||
" does not map to a FHIRPath primitive type.")); | ||
} | ||
return type->second; | ||
} | ||
|
||
bool IsSystemInteger(const Message& message) { | ||
StatusOr<FhirPathSystemType> type = GetSystemType(message); | ||
return type.ok() && type.ValueOrDie() == FhirPathSystemType::kInteger; | ||
} | ||
|
||
bool IsSystemString(const Message& message) { | ||
StatusOr<FhirPathSystemType> type = GetSystemType(message); | ||
return type.ok() && type.ValueOrDie() == FhirPathSystemType::kString; | ||
} | ||
|
||
bool IsSystemDecimal(const Message& message) { | ||
StatusOr<FhirPathSystemType> type = GetSystemType(message); | ||
return type.ok() && type.ValueOrDie() == FhirPathSystemType::kDecimal; | ||
} | ||
|
||
} // namespace google::fhir::fhir_path::internal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright 2020 Google LLC | ||
// | ||
// 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:https://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. | ||
|
||
#ifndef GOOGLE_FHIR_FHIR_PATH_FHIR_PATH_TYPES_H_ | ||
#define GOOGLE_FHIR_FHIR_PATH_FHIR_PATH_TYPES_H_ | ||
|
||
#include "google/protobuf/message.h" | ||
#include "absl/container/flat_hash_map.h" | ||
#include "google/fhir/status/statusor.h" | ||
|
||
namespace google::fhir::fhir_path::internal { | ||
enum class FhirPathSystemType { | ||
kBoolean = 1, | ||
kString = 2, | ||
kInteger = 3, | ||
kDecimal = 4, | ||
kDate = 5, | ||
kDateTime = 6, | ||
kTime = 7, | ||
kQuantity = 8 | ||
}; | ||
|
||
// Returns the FHIRPath primitive type the provided FHIR primitive maps to. | ||
// Returns a NotFoundError if no mapping exists between the provided FHIR type | ||
// and a FHIRPath primitive type. | ||
// | ||
// See https://www.hl7.org/fhir/fhirpath.html#types | ||
StatusOr<FhirPathSystemType> GetSystemType( | ||
const ::google::protobuf::Message& fhir_primitive); | ||
|
||
// Returns true if the provided FHIR message converts to System.Integer. False | ||
// otherwise. | ||
// | ||
// See https://www.hl7.org/fhir/fhirpath.html#types | ||
bool IsSystemInteger(const ::google::protobuf::Message& message); | ||
|
||
// Returns true if the provided FHIR message converts to System.String. False | ||
// otherwise. | ||
// | ||
// See https://www.hl7.org/fhir/fhirpath.html#types | ||
bool IsSystemString(const ::google::protobuf::Message& message); | ||
|
||
// Returns true if the provided FHIR message converts to System.Decimal. False | ||
// otherwise. | ||
// | ||
// See https://www.hl7.org/fhir/fhirpath.html#types | ||
bool IsSystemDecimal(const ::google::protobuf::Message& message); | ||
|
||
} // namespace google::fhir::fhir_path::internal | ||
|
||
#endif // GOOGLE_FHIR_FHIR_PATH_FHIR_PATH_TYPES_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
// Copyright 2020 Google LLC | ||
// | ||
// 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:https://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. | ||
|
||
#include "google/fhir/fhir_path/fhir_path_types.h" | ||
|
||
#include "gmock/gmock.h" | ||
#include "gtest/gtest.h" | ||
#include "google/fhir/util.h" | ||
#include "google/fhir/type_macros.h" | ||
#include "proto/r4/core/datatypes.pb.h" | ||
#include "proto/r4/core/resources/bundle_and_contained_resource.pb.h" | ||
#include "proto/stu3/datatypes.pb.h" | ||
#include "proto/stu3/resources.pb.h" | ||
|
||
namespace google::fhir::fhir_path::internal { | ||
|
||
using testing::Not; | ||
using testing::Pointee; | ||
using testing::Truly; | ||
|
||
template <typename T> | ||
void TestType(FhirPathSystemType expected_type) { | ||
T proto; | ||
StatusOr<FhirPathSystemType> system_type = GetSystemType(proto); | ||
|
||
if (!system_type.ok()) { | ||
ADD_FAILURE() << "No system type defined for " << proto.GetTypeName() | ||
<< ": " << system_type.status(); | ||
} | ||
|
||
EXPECT_EQ(system_type.ValueOrDie(), expected_type) | ||
<< "Wrong system type for " << proto.GetTypeName(); | ||
} | ||
|
||
template <typename... T> | ||
struct FhirPrimitiveTypes { | ||
static void VerifySystemTypeMapping(FhirPathSystemType expected_type) { | ||
(TestType<T>(expected_type), ...); | ||
} | ||
|
||
static std::vector<std::unique_ptr<::google::protobuf::Message>> GetInstances() { | ||
std::vector<std::unique_ptr<::google::protobuf::Message>> results; | ||
(results.push_back(std::make_unique<T>()), ...); | ||
return results; | ||
} | ||
}; | ||
|
||
template <typename BundleType, typename... AdditionalStringTypes> | ||
struct FhirStringTypes | ||
: public FhirPrimitiveTypes< | ||
FHIR_DATATYPE(BundleType, string_value), | ||
FHIR_DATATYPE(BundleType, uri), FHIR_DATATYPE(BundleType, code), | ||
FHIR_DATATYPE(BundleType, oid), FHIR_DATATYPE(BundleType, id), | ||
FHIR_DATATYPE(BundleType, markdown), | ||
FHIR_DATATYPE(BundleType, base64_binary), AdditionalStringTypes...> { | ||
}; | ||
|
||
template <typename BundleType> | ||
struct FhirTypes { | ||
using Booleans = FhirPrimitiveTypes<FHIR_DATATYPE(BundleType, boolean)>; | ||
|
||
using Integers = FhirPrimitiveTypes<FHIR_DATATYPE(BundleType, integer), | ||
FHIR_DATATYPE(BundleType, unsigned_int), | ||
FHIR_DATATYPE(BundleType, positive_int)>; | ||
|
||
using Strings = FhirStringTypes<BundleType>; | ||
|
||
using Decimals = FhirPrimitiveTypes<FHIR_DATATYPE(BundleType, decimal)>; | ||
|
||
using Dates = FhirPrimitiveTypes<FHIR_DATATYPE(BundleType, date)>; | ||
|
||
using DateTimes = FhirPrimitiveTypes<FHIR_DATATYPE(BundleType, date_time), | ||
FHIR_DATATYPE(BundleType, instant)>; | ||
|
||
using Times = FhirPrimitiveTypes<FHIR_DATATYPE(BundleType, time)>; | ||
|
||
using Quantities = FhirPrimitiveTypes<FHIR_DATATYPE(BundleType, quantity)>; | ||
}; | ||
|
||
struct Stu3Types : public FhirTypes<stu3::proto::Bundle> {}; | ||
|
||
struct R4Types : public FhirTypes<r4::core::Bundle> { | ||
using Strings = FhirStringTypes<r4::core::Bundle, r4::core::Uuid, | ||
r4::core::Canonical, r4::core::Url>; | ||
}; | ||
|
||
template <typename T> | ||
class FhirPathTypesTest : public ::testing::Test {}; | ||
|
||
using TestTypes = ::testing::Types<Stu3Types, R4Types>; | ||
TYPED_TEST_SUITE(FhirPathTypesTest, TestTypes); | ||
|
||
TYPED_TEST(FhirPathTypesTest, GetSystemType) { | ||
TypeParam::Booleans::VerifySystemTypeMapping(FhirPathSystemType::kBoolean); | ||
TypeParam::Integers::VerifySystemTypeMapping(FhirPathSystemType::kInteger); | ||
TypeParam::Strings::VerifySystemTypeMapping(FhirPathSystemType::kString); | ||
TypeParam::Decimals::VerifySystemTypeMapping(FhirPathSystemType::kDecimal); | ||
TypeParam::Dates::VerifySystemTypeMapping(FhirPathSystemType::kDate); | ||
TypeParam::DateTimes::VerifySystemTypeMapping(FhirPathSystemType::kDateTime); | ||
TypeParam::Times::VerifySystemTypeMapping(FhirPathSystemType::kTime); | ||
TypeParam::Quantities::VerifySystemTypeMapping(FhirPathSystemType::kQuantity); | ||
} | ||
|
||
TYPED_TEST(FhirPathTypesTest, IsSystemInteger) { | ||
EXPECT_THAT(TypeParam::Booleans::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemInteger))))); | ||
EXPECT_THAT(TypeParam::Integers::GetInstances(), | ||
Each(Pointee(Truly(IsSystemInteger)))); | ||
EXPECT_THAT(TypeParam::Strings::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemInteger))))); | ||
EXPECT_THAT(TypeParam::Decimals::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemInteger))))); | ||
EXPECT_THAT(TypeParam::Dates::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemInteger))))); | ||
EXPECT_THAT(TypeParam::DateTimes::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemInteger))))); | ||
EXPECT_THAT(TypeParam::Times::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemInteger))))); | ||
EXPECT_THAT(TypeParam::Quantities::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemInteger))))); | ||
} | ||
|
||
TYPED_TEST(FhirPathTypesTest, IsSystemString) { | ||
EXPECT_THAT(TypeParam::Booleans::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemString))))); | ||
EXPECT_THAT(TypeParam::Integers::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemString))))); | ||
EXPECT_THAT(TypeParam::Strings::GetInstances(), | ||
Each(Pointee(Truly(IsSystemString)))); | ||
EXPECT_THAT(TypeParam::Decimals::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemString))))); | ||
EXPECT_THAT(TypeParam::Dates::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemString))))); | ||
EXPECT_THAT(TypeParam::DateTimes::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemString))))); | ||
EXPECT_THAT(TypeParam::Times::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemString))))); | ||
EXPECT_THAT(TypeParam::Quantities::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemString))))); | ||
} | ||
|
||
TYPED_TEST(FhirPathTypesTest, IsSystemDecimal) { | ||
EXPECT_THAT(TypeParam::Booleans::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemDecimal))))); | ||
EXPECT_THAT(TypeParam::Integers::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemDecimal))))); | ||
EXPECT_THAT(TypeParam::Strings::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemDecimal))))); | ||
EXPECT_THAT(TypeParam::Decimals::GetInstances(), | ||
Each(Pointee(Truly(IsSystemDecimal)))); | ||
EXPECT_THAT(TypeParam::Dates::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemDecimal))))); | ||
EXPECT_THAT(TypeParam::DateTimes::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemDecimal))))); | ||
EXPECT_THAT(TypeParam::Times::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemDecimal))))); | ||
EXPECT_THAT(TypeParam::Quantities::GetInstances(), | ||
Each(Pointee(Not(Truly(IsSystemDecimal))))); | ||
} | ||
|
||
} // namespace google::fhir::fhir_path::internal |